Lines 67-75
Link Here
|
67 |
import org.apache.poi.ss.formula.ptg.UnionPtg; |
67 |
import org.apache.poi.ss.formula.ptg.UnionPtg; |
68 |
import org.apache.poi.ss.formula.ptg.ValueOperatorPtg; |
68 |
import org.apache.poi.ss.formula.ptg.ValueOperatorPtg; |
69 |
import org.apache.poi.ss.usermodel.ErrorConstants; |
69 |
import org.apache.poi.ss.usermodel.ErrorConstants; |
|
|
70 |
import org.apache.poi.ss.usermodel.Name; |
70 |
import org.apache.poi.ss.util.AreaReference; |
71 |
import org.apache.poi.ss.util.AreaReference; |
71 |
import org.apache.poi.ss.util.CellReference; |
72 |
import org.apache.poi.ss.util.CellReference; |
72 |
import org.apache.poi.ss.util.CellReference.NameType; |
73 |
import org.apache.poi.ss.util.CellReference.NameType; |
|
|
74 |
import org.apache.poi.util.POILogFactory; |
75 |
import org.apache.poi.util.POILogger; |
73 |
|
76 |
|
74 |
/** |
77 |
/** |
75 |
* This class parses a formula string into a List of tokens in RPN order. |
78 |
* This class parses a formula string into a List of tokens in RPN order. |
Lines 85-90
Link Here
|
85 |
* <p/> |
88 |
* <p/> |
86 |
*/ |
89 |
*/ |
87 |
public final class FormulaParser { |
90 |
public final class FormulaParser { |
|
|
91 |
private final static POILogger log = POILogFactory.getLogger(FormulaParser.class); |
88 |
private final String _formulaString; |
92 |
private final String _formulaString; |
89 |
private final int _formulaLength; |
93 |
private final int _formulaLength; |
90 |
/** points at the next character to be read (after the {@link #look} char) */ |
94 |
/** points at the next character to be read (after the {@link #look} char) */ |
Lines 108-117
Link Here
|
108 |
*/ |
112 |
*/ |
109 |
private boolean _inIntersection = false; |
113 |
private boolean _inIntersection = false; |
110 |
|
114 |
|
111 |
private FormulaParsingWorkbook _book; |
115 |
private final FormulaParsingWorkbook _book; |
112 |
private SpreadsheetVersion _ssVersion; |
116 |
private final SpreadsheetVersion _ssVersion; |
113 |
|
117 |
|
114 |
private int _sheetIndex; |
118 |
private final int _sheetIndex; |
115 |
|
119 |
|
116 |
|
120 |
|
117 |
/** |
121 |
/** |
Lines 137-142
Link Here
|
137 |
|
141 |
|
138 |
/** |
142 |
/** |
139 |
* Parse a formula into a array of tokens |
143 |
* Parse a formula into a array of tokens |
|
|
144 |
* Side effect: creates name (Workbook.createName) if formula contains unrecognized names (names are likely UDFs) |
140 |
* |
145 |
* |
141 |
* @param formula the formula to parse |
146 |
* @param formula the formula to parse |
142 |
* @param workbook the parent workbook |
147 |
* @param workbook the parent workbook |
Lines 927-932
Link Here
|
927 |
* Note - Excel function names are 'case aware but not case sensitive'. This method may end |
932 |
* Note - Excel function names are 'case aware but not case sensitive'. This method may end |
928 |
* up creating a defined name record in the workbook if the specified name is not an internal |
933 |
* up creating a defined name record in the workbook if the specified name is not an internal |
929 |
* Excel function, and has not been encountered before. |
934 |
* Excel function, and has not been encountered before. |
|
|
935 |
* |
936 |
* Side effect: creates workbook name if name is not recognized (name is probably a UDF) |
930 |
* |
937 |
* |
931 |
* @param name case preserved function name (as it was entered/appeared in the formula). |
938 |
* @param name case preserved function name (as it was entered/appeared in the formula). |
932 |
*/ |
939 |
*/ |
Lines 940-961
Link Here
|
940 |
// Only test cases omit the book (expecting it not to be needed) |
947 |
// Only test cases omit the book (expecting it not to be needed) |
941 |
throw new IllegalStateException("Need book to evaluate name '" + name + "'"); |
948 |
throw new IllegalStateException("Need book to evaluate name '" + name + "'"); |
942 |
} |
949 |
} |
|
|
950 |
// Check to see if name is a named range in the workbook |
943 |
EvaluationName hName = _book.getName(name, _sheetIndex); |
951 |
EvaluationName hName = _book.getName(name, _sheetIndex); |
944 |
if (hName == null) { |
952 |
if (hName != null) { |
945 |
nameToken = _book.getNameXPtg(name, null); |
|
|
946 |
if (nameToken == null) { |
947 |
throw new FormulaParseException("Name '" + name |
948 |
+ "' is completely unknown in the current workbook"); |
949 |
} |
950 |
} else { |
951 |
if (!hName.isFunctionName()) { |
953 |
if (!hName.isFunctionName()) { |
952 |
throw new FormulaParseException("Attempt to use name '" + name |
954 |
throw new FormulaParseException("Attempt to use name '" + name |
953 |
+ "' as a function, but defined name in workbook does not refer to a function"); |
955 |
+ "' as a function, but defined name in workbook does not refer to a function"); |
954 |
} |
956 |
} |
955 |
|
957 |
|
956 |
// calls to user-defined functions within the workbook |
958 |
// calls to user-defined functions within the workbook |
957 |
// get a Name token which points to a defined name record |
959 |
// get a Name token which points to a defined name record |
958 |
nameToken = hName.createPtg(); |
960 |
nameToken = hName.createPtg(); |
|
|
961 |
} else { |
962 |
// Check if name is an external names table |
963 |
nameToken = _book.getNameXPtg(name, null); |
964 |
if (nameToken == null) { |
965 |
// name is not an internal or external name |
966 |
if (log.check(POILogger.WARN)) { |
967 |
log.log(POILogger.WARN, |
968 |
"Name '" + name + "' is completely unknown in the current workbook."); |
969 |
} |
970 |
// name is probably the name of an unregistered User-Defined Function |
971 |
addName(name); |
972 |
hName = _book.getName(name, _sheetIndex); |
973 |
nameToken = hName.createPtg(); |
974 |
} |
959 |
} |
975 |
} |
960 |
} |
976 |
} |
961 |
|
977 |
|
Lines 965-970
Link Here
|
965 |
|
981 |
|
966 |
return getFunction(name, nameToken, args); |
982 |
return getFunction(name, nameToken, args); |
967 |
} |
983 |
} |
|
|
984 |
|
985 |
/** |
986 |
* Adds a name (named range or user defined function) to underlying workbook's names table |
987 |
* @param functionName |
988 |
*/ |
989 |
private final void addName(String functionName) { |
990 |
final Name name = _book.createName(); |
991 |
name.setFunction(true); |
992 |
name.setNameName(functionName); |
993 |
name.setSheetIndex(_sheetIndex); |
994 |
} |
968 |
|
995 |
|
969 |
/** |
996 |
/** |
970 |
* Generates the variable function ptg for the formula. |
997 |
* Generates the variable function ptg for the formula. |