diff --git a/src/java/org/apache/poi/hssf/model/HSSFFormulaParser.java b/src/java/org/apache/poi/hssf/model/HSSFFormulaParser.java index baf2b97d0..b54b27ad4 100644 --- a/src/java/org/apache/poi/hssf/model/HSSFFormulaParser.java +++ b/src/java/org/apache/poi/hssf/model/HSSFFormulaParser.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.model; import org.apache.poi.ss.formula.ptg.Ptg; +import org.apache.poi.util.Internal; import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.formula.FormulaParseException; @@ -29,6 +30,7 @@ import org.apache.poi.ss.formula.FormulaType; /** * HSSF wrapper for the {@link FormulaParser} and {@link FormulaRenderer} */ +@Internal public final class HSSFFormulaParser { private static FormulaParsingWorkbook createParsingWorkbook(HSSFWorkbook book) { @@ -40,18 +42,36 @@ public final class HSSFFormulaParser { } /** - * Convenience method for parsing cell formulas. see {@link #parse(String, HSSFWorkbook, int, int)} + * Convenience method for parsing cell formulas. see {@link #parse(String, HSSFWorkbook, FormulaType, int)} + * @param formula The formula to parse, excluding the leading equals sign + * @param workbook The parent workbook + * @return the parsed formula tokens + * @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid */ public static Ptg[] parse(String formula, HSSFWorkbook workbook) throws FormulaParseException { return parse(formula, workbook, FormulaType.CELL); } /** + * @param formula The formula to parse, excluding the leading equals sign + * @param workbook The parent workbook * @param formulaType a constant from {@link FormulaType} * @return the parsed formula tokens * @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid + * + * @deprecated POI 3.15 beta 3. Use {@link #parse(String, HSSFWorkbook, FormulaType)} instead. */ public static Ptg[] parse(String formula, HSSFWorkbook workbook, int formulaType) throws FormulaParseException { + return parse(formula, workbook, FormulaType.forInt(formulaType)); + } + /** + * @param formula The formula to parse, excluding the leading equals sign + * @param workbook The parent workbook + * @param formulaType The type of formula + * @return The parsed formula tokens + * @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid + */ + public static Ptg[] parse(String formula, HSSFWorkbook workbook, FormulaType formulaType) throws FormulaParseException { return parse(formula, workbook, formulaType, -1); } @@ -65,8 +85,23 @@ public final class HSSFFormulaParser { * * @return the parsed formula tokens * @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid + * @deprecated POI 3.15 beta 3. Use {@link #parse(String, HSSFWorkbook, FormulaType, int)} instead. */ public static Ptg[] parse(String formula, HSSFWorkbook workbook, int formulaType, int sheetIndex) throws FormulaParseException { + return parse(formula, workbook, FormulaType.forInt(formulaType), sheetIndex); + } + /** + * @param formula The formula to parse + * @param workbook The parent workbook + * @param formulaType The type of formula + * @param sheetIndex The 0-based index of the sheet this formula belongs to. + * The sheet index is required to resolve sheet-level names. -1 means that + * the scope of the name will be ignored and the parser will match named ranges only by name + * + * @return the parsed formula tokens + * @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid + */ + public static Ptg[] parse(String formula, HSSFWorkbook workbook, FormulaType formulaType, int sheetIndex) throws FormulaParseException { return FormulaParser.parse(formula, createParsingWorkbook(workbook), formulaType, sheetIndex); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java index 06afe8296..969da83f9 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java @@ -45,14 +45,14 @@ import org.apache.poi.ss.usermodel.Workbook; */ public class HSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluatorProvider { - private WorkbookEvaluator _bookEvaluator; - private HSSFWorkbook _book; + private final WorkbookEvaluator _bookEvaluator; + private final HSSFWorkbook _book; public HSSFFormulaEvaluator(HSSFWorkbook workbook) { this(workbook, null); - this._book = workbook; } /** + * @param workbook The workbook to perform the formula evaluations in * @param stabilityClassifier used to optimise caching performance. Pass null * for the (conservative) assumption that any cell may have its definition changed after * evaluation begins. @@ -62,13 +62,19 @@ public class HSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluator } /** + * @param workbook The workbook to perform the formula evaluations in + * @param stabilityClassifier used to optimise caching performance. Pass null + * for the (conservative) assumption that any cell may have its definition changed after + * evaluation begins. * @param udfFinder pass null for default (AnalysisToolPak only) */ private HSSFFormulaEvaluator(HSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) { + _book = workbook; _bookEvaluator = new WorkbookEvaluator(HSSFEvaluationWorkbook.create(workbook), stabilityClassifier, udfFinder); } /** + * @param workbook The workbook to perform the formula evaluations in * @param stabilityClassifier used to optimise caching performance. Pass null * for the (conservative) assumption that any cell may have its definition changed after * evaluation begins. diff --git a/src/java/org/apache/poi/ss/formula/FormulaParser.java b/src/java/org/apache/poi/ss/formula/FormulaParser.java index 35e6fd53e..6caf8e1eb 100644 --- a/src/java/org/apache/poi/ss/formula/FormulaParser.java +++ b/src/java/org/apache/poi/ss/formula/FormulaParser.java @@ -74,6 +74,7 @@ import org.apache.poi.ss.usermodel.Table; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.util.CellReference.NameType; +import org.apache.poi.util.Internal; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -90,6 +91,7 @@ import org.apache.poi.util.POILogger; * For POI internal use only *

*/ +@Internal public final class FormulaParser { private final static POILogger log = POILogFactory.getLogger(FormulaParser.class); private final String _formulaString; @@ -110,7 +112,7 @@ public final class FormulaParser { private char look; /** - * Tracks whether the run of whitespace preceeding "look" could be an + * Tracks whether the run of whitespace preceding "look" could be an * intersection operator. See GetChar. */ private boolean _inIntersection = false; @@ -130,11 +132,11 @@ public final class FormulaParser { * parse results. * This class is recommended only for single threaded use. * - * If you only have a usermodel.HSSFWorkbook, and not a - * model.Workbook, then use the convenience method on - * usermodel.HSSFFormulaEvaluator + * If you have a {@link org.apache.poi.hssf.usermodel.HSSFWorkbook}, and not a + * {@link org.apache.poi.hssf.model.Workbook}, then use the convenience method on + * {@link org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator} */ - private FormulaParser(String formula, FormulaParsingWorkbook book, int sheetIndex, int rowIndex){ + private FormulaParser(String formula, FormulaParsingWorkbook book, int sheetIndex, int rowIndex) { _formulaString = formula; _pointer=0; _book = book; @@ -151,7 +153,7 @@ public final class FormulaParser { * * @param formula the formula to parse * @param workbook the parent workbook - * @param formulaType the type of the formula, see {@link FormulaType} + * @param formulaType the type of the formula * @param sheetIndex the 0-based index of the sheet this formula belongs to. * The sheet index is required to resolve sheet-level names. -1 means that * the scope of the name will be ignored and the parser will match names only by name @@ -163,7 +165,7 @@ public final class FormulaParser { * @return array of parsed tokens * @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid */ - public static Ptg[] parse(String formula, FormulaParsingWorkbook workbook, int formulaType, int sheetIndex, int rowIndex) { + public static Ptg[] parse(String formula, FormulaParsingWorkbook workbook, FormulaType formulaType, int sheetIndex, int rowIndex) { FormulaParser fp = new FormulaParser(formula, workbook, sheetIndex, rowIndex); fp.parse(); return fp.getRPNPtg(formulaType); @@ -176,7 +178,7 @@ public final class FormulaParser { * * @param formula the formula to parse * @param workbook the parent workbook - * @param formulaType the type of the formula, see {@link FormulaType} + * @param formulaType the type of the formula * @param sheetIndex the 0-based index of the sheet this formula belongs to. * The sheet index is required to resolve sheet-level names. -1 means that * the scope of the name will be ignored and the parser will match names only by name @@ -184,7 +186,7 @@ public final class FormulaParser { * @return array of parsed tokens * @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid */ - public static Ptg[] parse(String formula, FormulaParsingWorkbook workbook, int formulaType, int sheetIndex) { + public static Ptg[] parse(String formula, FormulaParsingWorkbook workbook, FormulaType formulaType, int sheetIndex) { return parse(formula, workbook, formulaType, sheetIndex, -1); } @@ -1022,7 +1024,7 @@ public final class FormulaParser { return null; } } else if (hasLetters) { - if (!CellReference.isColumnWithnRange(rep.replace("$", ""), _ssVersion)) { + if (!CellReference.isColumnWithinRange(rep.replace("$", ""), _ssVersion)) { return null; } } else if (hasDigits) { @@ -2001,7 +2003,7 @@ end; } } - private Ptg[] getRPNPtg(int formulaType) { + private Ptg[] getRPNPtg(FormulaType formulaType) { OperandClassTransformer oct = new OperandClassTransformer(formulaType); // RVA is for 'operand class': 'reference', 'value', 'array' oct.transformFormula(_rootNode); diff --git a/src/java/org/apache/poi/ss/formula/FormulaType.java b/src/java/org/apache/poi/ss/formula/FormulaType.java index b77001990..a26398b63 100644 --- a/src/java/org/apache/poi/ss/formula/FormulaType.java +++ b/src/java/org/apache/poi/ss/formula/FormulaType.java @@ -17,24 +17,60 @@ package org.apache.poi.ss.formula; -/** - * Enumeration of various formula types.
- * - * For POI internal use only - * - * @author Josh Micich - */ -public final class FormulaType { - private FormulaType() { - // no instances of this class - } - public static final int CELL = 0; - public static final int SHARED = 1; - public static final int ARRAY =2; - public static final int CONDFORMAT = 3; - public static final int NAMEDRANGE = 4; - // this constant is currently very specific. The exact differences from general data - // validation formulas or conditional format formulas is not known yet - public static final int DATAVALIDATION_LIST = 5; +import org.apache.poi.util.Internal; +/** + * Enumeration of various formula types. + * + * See Sections 3 and 4.8 of https://www.openoffice.org/sc/excelfileformat.pdf + */ +@Internal +public enum FormulaType { + /** Regular cell formula */ + CELL(0), + + /** + * A Shared Formula ("{=SUM(A1:E1*{1,2,3,4,5}}") + * + * Similar to an array formula, but stored in a SHAREDFMLA instead of ARRAY record as a file size optimization. + * See Section 4.8 of https://www.openoffice.org/sc/excelfileformat.pdf + */ + SHARED(1), + + /** + * An Array formula ("{=SUM(A1:E1*{1,2,3,4,5}}") + * https://support.office.com/en-us/article/Guidelines-and-examples-of-array-formulas-7D94A64E-3FF3-4686-9372-ECFD5CAA57C7 + */ + ARRAY(2), + + /** Conditional formatting */ + CONDFORMAT(3), + + /** Named range */ + NAMEDRANGE(4), + + /** + * This constant is currently very specific. The exact differences from general data + * validation formulas or conditional format formulas is not known yet + */ + DATAVALIDATION_LIST(5); + + /** @deprecated POI 3.15 beta 3. */ + private final int code; + /** @deprecated POI 3.15 beta 3. + * Formula type code doesn't mean anything. Only in this class for transitioning from a class with int constants to a true enum. + * Remove hard-coded numbers from the enums above. */ + private FormulaType(int code) { + this.code = code; + } + + /** @deprecated POI 3.15 beta 3. Used to transition code from ints to FormulaTypes. */ + public static FormulaType forInt(int code) { + for (FormulaType type : values()) { + if (type.code == code) { + return type; + } + } + throw new IllegalArgumentException("Invalid FormulaType code: " + code); + } } diff --git a/src/java/org/apache/poi/ss/formula/OperandClassTransformer.java b/src/java/org/apache/poi/ss/formula/OperandClassTransformer.java index ea3a48876..a45d5a2d1 100644 --- a/src/java/org/apache/poi/ss/formula/OperandClassTransformer.java +++ b/src/java/org/apache/poi/ss/formula/OperandClassTransformer.java @@ -57,9 +57,13 @@ import org.apache.poi.ss.formula.ptg.ValueOperatorPtg; */ final class OperandClassTransformer { - private final int _formulaType; + private final FormulaType _formulaType; + /** @deprecated POI 3.15 beta 3. */ public OperandClassTransformer(int formulaType) { + this(FormulaType.forInt(formulaType)); + } + public OperandClassTransformer(FormulaType formulaType) { _formulaType = formulaType; } @@ -70,14 +74,14 @@ final class OperandClassTransformer { public void transformFormula(ParseNode rootNode) { byte rootNodeOperandClass; switch (_formulaType) { - case FormulaType.CELL: + case CELL: rootNodeOperandClass = Ptg.CLASS_VALUE; break; - case FormulaType.ARRAY: + case ARRAY: rootNodeOperandClass = Ptg.CLASS_ARRAY; break; - case FormulaType.NAMEDRANGE: - case FormulaType.DATAVALIDATION_LIST: + case NAMEDRANGE: + case DATAVALIDATION_LIST: rootNodeOperandClass = Ptg.CLASS_REF; break; default: diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java index 463bad5c3..37adc7ead 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java @@ -551,8 +551,7 @@ public final class XSSFCell implements Cell { cellFormula.setRef(range.formatAsString()); } - @SuppressWarnings("resource") - private void setFormula(String formula, int formulaType) { + private void setFormula(String formula, FormulaType formulaType) { XSSFWorkbook wb = _row.getSheet().getWorkbook(); if (formula == null) { wb.onDeleteFormula(this);