From 43b3e52344930dfc61ef222841e8322a4303913c Mon Sep 17 00:00:00 2001 From: Josh Micich Date: Fri, 27 Nov 2009 21:01:59 +0000 Subject: [PATCH] Patch 48284 - raise visibility of FormulaParseException git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@885007 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/model/HSSFFormulaParser.java | 11 ++- .../apache/poi/hssf/usermodel/HSSFCell.java | 19 +---- .../usermodel/HSSFEvaluationWorkbook.java | 3 +- .../poi/ss/formula/FormulaParseException.java | 33 ++++++++ .../apache/poi/ss/formula/FormulaParser.java | 83 +++++++------------ .../org/apache/poi/ss/usermodel/Cell.java | 13 +-- .../apache/poi/xssf/usermodel/XSSFCell.java | 11 --- .../xssf/usermodel/TestXSSFFormulaParser.java | 50 +++++------ .../poi/hssf/model/TestFormulaParser.java | 46 +++++----- .../poi/hssf/model/TestFormulaParserEval.java | 17 ++-- .../hssf/record/TestSharedFormulaRecord.java | 33 ++++---- .../ss/formula/FormulaParserTestHelper.java | 55 ------------ 12 files changed, 158 insertions(+), 216 deletions(-) create mode 100644 src/java/org/apache/poi/ss/formula/FormulaParseException.java delete mode 100644 src/testcases/org/apache/poi/ss/formula/FormulaParserTestHelper.java diff --git a/src/java/org/apache/poi/hssf/model/HSSFFormulaParser.java b/src/java/org/apache/poi/hssf/model/HSSFFormulaParser.java index 026590d71d..d65943b564 100644 --- a/src/java/org/apache/poi/hssf/model/HSSFFormulaParser.java +++ b/src/java/org/apache/poi/hssf/model/HSSFFormulaParser.java @@ -20,6 +20,7 @@ package org.apache.poi.hssf.model; import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.formula.FormulaParseException; import org.apache.poi.ss.formula.FormulaParser; import org.apache.poi.ss.formula.FormulaParsingWorkbook; import org.apache.poi.ss.formula.FormulaRenderer; @@ -41,17 +42,18 @@ public final class HSSFFormulaParser { } /** - * Convenience method for parsing cell formulas. see {@link #parse(String, HSSFWorkbook, int)} + * Convenience method for parsing cell formulas. see {@link #parse(String, HSSFWorkbook, int, int)} */ - public static Ptg[] parse(String formula, HSSFWorkbook workbook) { + public static Ptg[] parse(String formula, HSSFWorkbook workbook) throws FormulaParseException { return parse(formula, workbook, FormulaType.CELL); } /** * @param formulaType a constant from {@link FormulaType} * @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, int formulaType) { + public static Ptg[] parse(String formula, HSSFWorkbook workbook, int formulaType) throws FormulaParseException { return parse(formula, workbook, formulaType, -1); } @@ -64,8 +66,9 @@ public final class HSSFFormulaParser { * 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, int formulaType, int sheetIndex) { + public static Ptg[] parse(String formula, HSSFWorkbook workbook, int formulaType, int sheetIndex) throws FormulaParseException { return FormulaParser.parse(formula, createParsingWorkbook(workbook), formulaType, sheetIndex); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index 701b7ce746..ad1c53545d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -81,7 +81,7 @@ public class HSSFCell implements Cell { */ public static final int LAST_COLUMN_NUMBER = SpreadsheetVersion.EXCEL97.getLastColumnIndex(); // 2^8 - 1 private static final String LAST_COLUMN_NAME = SpreadsheetVersion.EXCEL97.getLastColumnName(); - + public final static short ENCODING_UNCHANGED = -1; public final static short ENCODING_COMPRESSED_UNICODE = 0; public final static short ENCODING_UTF_16 = 1; @@ -507,7 +507,7 @@ public class HSSFCell implements Cell { } /** - * set a string value for the cell. + * set a string value for the cell. * * @param value value to set the cell to. For formulas we'll set the formula * cached string result, for String cells we'll set its value. For other types we will @@ -573,17 +573,6 @@ public class HSSFCell implements Cell { _stringValue.setUnicodeString(_book.getWorkbook().getSSTString(index)); } - /** - * Sets formula for this cell. - *

- * Note, this method only sets the formula string and does not calculate the formula value. - * To set the precalculated value use {@link #setCellValue(double)} or {@link #setCellValue(String)} - *

- * - * @param formula the formula to set, e.g. SUM(C4:E4). - * If the argument is null then the current formula is removed. - * @throws IllegalArgumentException if the formula is unparsable - */ public void setCellFormula(String formula) { int row=_record.getRow(); short col=_record.getColumn(); @@ -918,8 +907,8 @@ public class HSSFCell implements Cell { */ private static void checkBounds(int cellIndex) { if (cellIndex < 0 || cellIndex > LAST_COLUMN_NUMBER) { - throw new IllegalArgumentException("Invalid column index (" + cellIndex - + "). Allowable column range for " + FILE_FORMAT_NAME + " is (0.." + throw new IllegalArgumentException("Invalid column index (" + cellIndex + + "). Allowable column range for " + FILE_FORMAT_NAME + " is (0.." + LAST_COLUMN_NUMBER + ") or ('A'..'" + LAST_COLUMN_NAME + "')"); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java index 824fa46d80..7b55d81db7 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java @@ -29,6 +29,7 @@ import org.apache.poi.ss.formula.EvaluationCell; import org.apache.poi.ss.formula.EvaluationName; import org.apache.poi.ss.formula.EvaluationSheet; import org.apache.poi.ss.formula.EvaluationWorkbook; +import org.apache.poi.ss.formula.FormulaParseException; import org.apache.poi.ss.formula.FormulaParsingWorkbook; import org.apache.poi.ss.formula.FormulaRenderingWorkbook; import org.apache.poi.ss.formula.FormulaType; @@ -129,7 +130,7 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E // to make sure that all formulas POI can evaluate can also be parsed. try { return HSSFFormulaParser.parse(cell.getCellFormula(), _uBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet())); - } catch (RuntimeException e) { + } catch (FormulaParseException e) { // Note - as of Bugzilla 48036 (svn r828244, r828247) POI is capable of evaluating // IntesectionPtg. However it is still not capable of parsing it. // So FormulaEvalTestData.xls now contains a few formulas that produce errors here. diff --git a/src/java/org/apache/poi/ss/formula/FormulaParseException.java b/src/java/org/apache/poi/ss/formula/FormulaParseException.java new file mode 100644 index 0000000000..4b1040f16d --- /dev/null +++ b/src/java/org/apache/poi/ss/formula/FormulaParseException.java @@ -0,0 +1,33 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula; + +/** + * This exception thrown when a supplied formula has incorrect syntax (or syntax currently not + * supported by POI). It is primarily used by test code to confirm specific parsing exceptions. + * Application code should also handle this exception if it potentially supplies formula text + * that is not guaranteed to be well-formed. + * + * @author Josh Micich + */ +public final class FormulaParseException extends RuntimeException { + + FormulaParseException(String msg) { + super(msg); + } +} diff --git a/src/java/org/apache/poi/ss/formula/FormulaParser.java b/src/java/org/apache/poi/ss/formula/FormulaParser.java index 0a7b56812e..adb4bd8779 100644 --- a/src/java/org/apache/poi/ss/formula/FormulaParser.java +++ b/src/java/org/apache/poi/ss/formula/FormulaParser.java @@ -24,7 +24,6 @@ import java.util.regex.Pattern; import org.apache.poi.hssf.record.UnicodeString; import org.apache.poi.hssf.record.constant.ErrorConstant; import org.apache.poi.hssf.record.formula.*; -import org.apache.poi.hssf.record.formula.ValueOperatorPtg; import org.apache.poi.hssf.record.formula.function.FunctionMetadata; import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry; import org.apache.poi.hssf.usermodel.HSSFErrorConstants; @@ -42,6 +41,10 @@ import org.apache.poi.ss.SpreadsheetVersion; * ::= [ ]* * ::= | () | | * ::= ([expression [, expression]*]) + *

+ * For POI internal use only + *

+ * * * @author Avik Sengupta * @author Andrew C. oliver (acoliver at apache dot org) @@ -111,20 +114,6 @@ public final class FormulaParser { } } - /** - * Specific exception thrown when a supplied formula does not parse properly.
- * Primarily used by test cases when testing for specific parsing exceptions.

- * - */ - static final class FormulaParseException extends RuntimeException { - // This class was given package scope until it would become clear that it is useful to - // general client code. - public FormulaParseException(String msg) { - super(msg); - } - } - - private final String _formulaString; private final int _formulaLength; /** points at the next character to be read (after the {@link #look} char) */ @@ -141,7 +130,7 @@ public final class FormulaParser { private char look; private FormulaParsingWorkbook _book; - private SpreadsheetVersion _ssVersion; + private SpreadsheetVersion _ssVersion; private int _sheetIndex; @@ -162,19 +151,11 @@ public final class FormulaParser { _formulaString = formula; _pointer=0; _book = book; - _ssVersion = book == null ? SpreadsheetVersion.EXCEL97 : book.getSpreadsheetVersion(); - _formulaLength = _formulaString.length(); + _ssVersion = book == null ? SpreadsheetVersion.EXCEL97 : book.getSpreadsheetVersion(); + _formulaLength = _formulaString.length(); _sheetIndex = sheetIndex; } - public static Ptg[] parse(String formula, FormulaParsingWorkbook book) { - return parse(formula, book, FormulaType.CELL); - } - - public static Ptg[] parse(String formula, FormulaParsingWorkbook workbook, int formulaType) { - return parse(formula, workbook, formulaType, -1); - } - /** * Parse a formula into a array of tokens * @@ -186,7 +167,7 @@ public final class FormulaParser { * the scope of the name will be ignored and the parser will match names only by name * * @return array of parsed tokens - * @throws FormulaParseException if the formula is unparsable + * @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid */ public static Ptg[] parse(String formula, FormulaParsingWorkbook workbook, int formulaType, int sheetIndex) { FormulaParser fp = new FormulaParser(formula, workbook, sheetIndex); @@ -702,7 +683,7 @@ public final class FormulaParser { if (!isValidCellReference(rep)) { return null; } - } else if (hasLetters) { + } else if (hasLetters) { if (!CellReference.isColumnWithnRange(rep.replace("$", ""), _ssVersion)) { return null; } @@ -881,29 +862,29 @@ public final class FormulaParser { * @return true if the specified name is a valid cell reference */ private boolean isValidCellReference(String str) { - //check range bounds against grid max - boolean result = CellReference.classifyCellReference(str, _ssVersion) == NameType.CELL; - - if(result){ - /** - * Check if the argument is a function. Certain names can be either a cell reference or a function name - * depending on the contenxt. Compare the following examples in Excel 2007: - * (a) LOG10(100) + 1 - * (b) LOG10 + 1 - * In (a) LOG10 is a name of a built-in function. In (b) LOG10 is a cell reference - */ - boolean isFunc = FunctionMetadataRegistry.getFunctionByName(str.toUpperCase()) != null; - if(isFunc){ - int savePointer = _pointer; - resetPointer(_pointer + str.length()); - SkipWhite(); - // open bracket indicates that the argument is a function, - // the returning value should be false, i.e. "not a valid cell reference" - result = look != '('; - resetPointer(savePointer); - } - } - return result; + //check range bounds against grid max + boolean result = CellReference.classifyCellReference(str, _ssVersion) == NameType.CELL; + + if(result){ + /** + * Check if the argument is a function. Certain names can be either a cell reference or a function name + * depending on the contenxt. Compare the following examples in Excel 2007: + * (a) LOG10(100) + 1 + * (b) LOG10 + 1 + * In (a) LOG10 is a name of a built-in function. In (b) LOG10 is a cell reference + */ + boolean isFunc = FunctionMetadataRegistry.getFunctionByName(str.toUpperCase()) != null; + if(isFunc){ + int savePointer = _pointer; + resetPointer(_pointer + str.length()); + SkipWhite(); + // open bracket indicates that the argument is a function, + // the returning value should be false, i.e. "not a valid cell reference" + result = look != '('; + resetPointer(savePointer); + } + } + return result; } diff --git a/src/java/org/apache/poi/ss/usermodel/Cell.java b/src/java/org/apache/poi/ss/usermodel/Cell.java index 0d581db352..17af1831d6 100644 --- a/src/java/org/apache/poi/ss/usermodel/Cell.java +++ b/src/java/org/apache/poi/ss/usermodel/Cell.java @@ -20,6 +20,8 @@ package org.apache.poi.ss.usermodel; import java.util.Calendar; import java.util.Date; +import org.apache.poi.ss.formula.FormulaParseException; + /** * High level representation of a cell in a row of a spreadsheet. *

@@ -76,7 +78,7 @@ public interface Cell { * @see #getCellType() */ public final static int CELL_TYPE_ERROR = 5; - + /** * Returns column index of this cell * @@ -158,7 +160,7 @@ public interface Cell { * data type is now something besides {@link Cell#CELL_TYPE_NUMERIC}. POI * does not attempt to replicate this behaviour. To make a numeric cell * display as a date, use {@link #setCellStyle(CellStyle)} etc. - * + * * @param value the numeric value to set this cell to. For formulas we'll set the * precalculated value, for numerics we'll set its value. For other types we * will change the cell to a numerics cell and set its value. @@ -203,6 +205,7 @@ public interface Cell { */ void setCellValue(String value); + /** * Sets formula for this cell. *

@@ -210,11 +213,11 @@ public interface Cell { * To set the precalculated value use {@link #setCellValue(double)} or {@link #setCellValue(String)} *

* - * @param formula the formula to set, e.g. SUM(C4:E4). + * @param formula the formula to set, e.g. "SUM(C4:E4)". * If the argument is null then the current formula is removed. - * @throws IllegalArgumentException if the formula is unparsable + * @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid */ - void setCellFormula(String formula); + void setCellFormula(String formula) throws FormulaParseException; /** * Return a formula for the cell, for example, SUM(C4:E4) 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 6d1ab6f9e1..2ad093e292 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java @@ -362,17 +362,6 @@ public final class XSSFCell implements Cell { return FormulaRenderer.toFormulaString(fpb, fmla); } - /** - * Sets formula for this cell. - *

- * Note, this method only sets the formula string and does not calculate the formula value. - * To set the precalculated value use {@link #setCellValue(double)} or {@link #setCellValue(String)} - *

- * - * @param formula the formula to set, e.g. SUM(C4:E4). - * If the argument is null then the current formula is removed. - * @throws IllegalArgumentException if the formula is invalid - */ public void setCellFormula(String formula) { XSSFWorkbook wb = _row.getSheet().getWorkbook(); if (formula == null) { diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java index 0d3de41cc8..f75abbc14a 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java @@ -23,55 +23,53 @@ import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.record.formula.IntPtg; import org.apache.poi.hssf.record.formula.FuncPtg; +import org.apache.poi.ss.formula.FormulaParseException; import org.apache.poi.ss.formula.FormulaParser; import org.apache.poi.ss.formula.FormulaType; public final class TestXSSFFormulaParser extends TestCase { + private static Ptg[] parse(XSSFEvaluationWorkbook fpb, String fmla) { + return FormulaParser.parse(fmla, fpb, FormulaType.CELL, -1); + } + public void testParse() { XSSFWorkbook wb = new XSSFWorkbook(); XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb); - String fmla; Ptg[] ptgs; - fmla = "ABC10"; - ptgs = FormulaParser.parse(fmla, fpb, FormulaType.CELL); + ptgs = parse(fpb, "ABC10"); assertEquals(1, ptgs.length); - assertTrue("",(ptgs[0] instanceof RefPtg)); + assertTrue("", ptgs[0] instanceof RefPtg); - fmla = "A500000"; - ptgs = FormulaParser.parse(fmla, fpb, FormulaType.CELL); + ptgs = parse(fpb, "A500000"); assertEquals(1, ptgs.length); - assertTrue("",(ptgs[0] instanceof RefPtg)); + assertTrue("", ptgs[0] instanceof RefPtg); - fmla = "ABC500000"; - ptgs = FormulaParser.parse(fmla, fpb, FormulaType.CELL); + ptgs = parse(fpb, "ABC500000"); assertEquals(1, ptgs.length); - assertTrue("",(ptgs[0] instanceof RefPtg)); + assertTrue("", ptgs[0] instanceof RefPtg); //highest allowed rows and column (XFD and 0x100000) - fmla = "XFD1048576"; - ptgs = FormulaParser.parse(fmla, fpb, FormulaType.CELL); + ptgs = parse(fpb, "XFD1048576"); assertEquals(1, ptgs.length); - assertTrue("",(ptgs[0] instanceof RefPtg)); + assertTrue("", ptgs[0] instanceof RefPtg); //column greater than XFD - fmla = "XFE10"; try { - ptgs = FormulaParser.parse(fmla, fpb, FormulaType.CELL); + ptgs = parse(fpb, "XFE10"); fail("expected exception"); - } catch (Exception e){ + } catch (FormulaParseException e){ assertEquals("Specified named range 'XFE10' does not exist in the current workbook.", e.getMessage()); } //row greater than 0x100000 - fmla = "XFD1048577"; try { - ptgs = FormulaParser.parse(fmla, fpb, FormulaType.CELL); + ptgs = parse(fpb, "XFD1048577"); fail("expected exception"); - } catch (Exception e){ + } catch (FormulaParseException e){ assertEquals("Specified named range 'XFD1048577' does not exist in the current workbook.", e.getMessage()); } } @@ -79,19 +77,15 @@ public final class TestXSSFFormulaParser extends TestCase { public void testBuiltInFormulas() { XSSFWorkbook wb = new XSSFWorkbook(); XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb); - String fmla; Ptg[] ptgs; - fmla = "LOG10"; - ptgs = FormulaParser.parse(fmla, fpb, FormulaType.CELL); + ptgs = parse(fpb, "LOG10"); assertEquals(1, ptgs.length); assertTrue("",(ptgs[0] instanceof RefPtg)); - fmla = "LOG10(100)"; - ptgs = FormulaParser.parse(fmla, fpb, FormulaType.CELL); + ptgs = parse(fpb, "LOG10(100)"); assertEquals(2, ptgs.length); - assertTrue("",(ptgs[0] instanceof IntPtg)); - assertTrue("",(ptgs[1] instanceof FuncPtg)); - + assertTrue("", ptgs[0] instanceof IntPtg); + assertTrue("", ptgs[1] instanceof FuncPtg); } -} \ No newline at end of file +} diff --git a/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java b/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java index 6af5ba4ba1..9950e75794 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java +++ b/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java @@ -65,8 +65,9 @@ import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.TestHSSFName; +import org.apache.poi.ss.formula.FormulaParseException; import org.apache.poi.ss.formula.FormulaParser; -import org.apache.poi.ss.formula.FormulaParserTestHelper; +import org.apache.poi.ss.formula.FormulaType; import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues; import org.apache.poi.ss.usermodel.Name; @@ -684,9 +685,9 @@ public final class TestFormulaParser extends TestCase { try { parseFormula(formula); throw new AssertionFailedError("expected parse exception"); - } catch (RuntimeException e) { + } catch (FormulaParseException e) { // expected during successful test - FormulaParserTestHelper.confirmParseException(e); + assertNotNull(e.getMessage()); } } @@ -782,8 +783,8 @@ public final class TestFormulaParser extends TestCase { try { HSSFFormulaParser.parse(formula, book); throw new AssertionFailedError("Didn't get parse exception as expected"); - } catch (RuntimeException e) { - FormulaParserTestHelper.confirmParseException(e, expectedMessage); + } catch (FormulaParseException e) { + confirmParseException(e, expectedMessage); } } @@ -792,16 +793,16 @@ public final class TestFormulaParser extends TestCase { try { parseFormula("round(3.14;2)"); throw new AssertionFailedError("Didn't get parse exception as expected"); - } catch (RuntimeException e) { - FormulaParserTestHelper.confirmParseException(e, + } catch (FormulaParseException e) { + confirmParseException(e, "Parse error near char 10 ';' in specified formula 'round(3.14;2)'. Expected ',' or ')'"); } try { parseFormula(" =2+2"); throw new AssertionFailedError("Didn't get parse exception as expected"); - } catch (RuntimeException e) { - FormulaParserTestHelper.confirmParseException(e, + } catch (FormulaParseException e) { + confirmParseException(e, "The specified formula ' =2+2' starts with an equals sign which is not allowed."); } } @@ -853,8 +854,8 @@ public final class TestFormulaParser extends TestCase { try { cell.setCellFormula("count(pf1)"); throw new AssertionFailedError("Expected formula parse execption"); - } catch (RuntimeException e) { - FormulaParserTestHelper.confirmParseException(e, + } catch (FormulaParseException e) { + confirmParseException(e, "Specified named range 'pf1' does not exist in the current workbook."); } cell.setCellFormula("count(fp1)"); // plain cell ref, col is in range @@ -962,7 +963,7 @@ public final class TestFormulaParser extends TestCase { String formula = "Sheet1!$B$2:$C$3,OFFSET(Sheet1!$E$2:$E$4,1,Sheet1!$A$1),Sheet1!$D$6"; HSSFWorkbook wb = new HSSFWorkbook(); wb.createSheet("Sheet1"); - Ptg[] ptgs = FormulaParser.parse(formula, HSSFEvaluationWorkbook.create(wb)); + Ptg[] ptgs = FormulaParser.parse(formula, HSSFEvaluationWorkbook.create(wb), FormulaType.CELL, -1); Class[] expectedClasses = { // TODO - AttrPtg.class, // Excel prepends this @@ -985,7 +986,7 @@ public final class TestFormulaParser extends TestCase { String formula = "Sheet1!A1:Sheet1!B3"; HSSFWorkbook wb = new HSSFWorkbook(); wb.createSheet("Sheet1"); - Ptg[] ptgs = FormulaParser.parse(formula, HSSFEvaluationWorkbook.create(wb)); + Ptg[] ptgs = FormulaParser.parse(formula, HSSFEvaluationWorkbook.create(wb), FormulaType.CELL, -1); if (ptgs.length == 3) { confirmTokenClasses(ptgs, new Class[] { Ref3DPtg.class, Ref3DPtg.class, RangePtg.class,}); @@ -1195,8 +1196,8 @@ public final class TestFormulaParser extends TestCase { try { HSSFFormulaParser.parse(formula, wb); throw new AssertionFailedError("Expected formula parse execption"); - } catch (RuntimeException e) { - FormulaParserTestHelper.confirmParseException(e, expectedMessage); + } catch (FormulaParseException e) { + confirmParseException(e, expectedMessage); } } @@ -1220,8 +1221,7 @@ public final class TestFormulaParser extends TestCase { Ptg[] result; try { result = HSSFFormulaParser.parse("1+foo", wb); - } catch (RuntimeException e) { - FormulaParserTestHelper.confirmParseException(e); + } catch (FormulaParseException e) { if (e.getMessage().equals("Specified name 'foo' is not a range as expected.")) { throw new AssertionFailedError("Identified bug 47078c"); } @@ -1247,9 +1247,9 @@ public final class TestFormulaParser extends TestCase { HSSFFormulaParser.parse(badCellRef, wb); throw new AssertionFailedError("Identified bug 47312b - Shouldn't be able to parse cell ref '" + badCellRef + "'."); - } catch (RuntimeException e) { + } catch (FormulaParseException e) { // expected during successful test - FormulaParserTestHelper.confirmParseException(e, "Specified named range '" + confirmParseException(e, "Specified named range '" + badCellRef + "' does not exist in the current workbook."); } @@ -1257,8 +1257,8 @@ public final class TestFormulaParser extends TestCase { try { ptgs = HSSFFormulaParser.parse(leadingZeroCellRef, wb); assertEquals("B1", ((RefPtg) ptgs[0]).toFormulaString()); - } catch (RuntimeException e) { - FormulaParserTestHelper.confirmParseException(e, "Specified named range '" + } catch (FormulaParseException e) { + confirmParseException(e, "Specified named range '" + leadingZeroCellRef + "' does not exist in the current workbook."); // close but no cigar throw new AssertionFailedError("Identified bug 47312c - '" @@ -1272,4 +1272,8 @@ public final class TestFormulaParser extends TestCase { ptgs = HSSFFormulaParser.parse("B0", wb); assertEquals(NamePtg.class, ptgs[0].getClass()); } + + private static void confirmParseException(FormulaParseException e, String expMsg) { + assertEquals(expMsg, e.getMessage()); + } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestFormulaParserEval.java b/src/testcases/org/apache/poi/hssf/model/TestFormulaParserEval.java index e3b8ed9530..3dea74d21e 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestFormulaParserEval.java +++ b/src/testcases/org/apache/poi/hssf/model/TestFormulaParserEval.java @@ -29,12 +29,12 @@ import org.apache.poi.hssf.usermodel.HSSFName; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.formula.FormulaParserTestHelper; +import org.apache.poi.ss.formula.FormulaParseException; import org.apache.poi.ss.usermodel.CellValue; /** * Test the low level formula parser functionality, - * but using parts which need to use + * but using parts which need to use * HSSFFormulaEvaluator. */ public final class TestFormulaParserEval extends TestCase { @@ -56,11 +56,11 @@ public final class TestFormulaParserEval extends TestCase { // Now make it a single cell name.setRefersToFormula("C3"); confirmParseFormula(workbook); - + // And make it non-contiguous // using area unions name.setRefersToFormula("A1:A2,C3"); - + confirmParseFormula(workbook); } @@ -75,11 +75,11 @@ public final class TestFormulaParserEval extends TestCase { } public void testEvaluateFormulaWithRowBeyond32768_Bug44539() { - + HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet(); wb.setSheetName(0, "Sheet1"); - + HSSFRow row = sheet.createRow(0); HSSFCell cell = row.createCell(0); cell.setCellFormula("SUM(A32769:A32770)"); @@ -87,13 +87,12 @@ public final class TestFormulaParserEval extends TestCase { // put some values in the cells to make the evaluation more interesting sheet.createRow(32768).createCell(0).setCellValue(31); sheet.createRow(32769).createCell(0).setCellValue(11); - + HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); CellValue result; try { result = fe.evaluate(cell); - } catch (RuntimeException e) { - FormulaParserTestHelper.confirmParseException(e); + } catch (FormulaParseException e) { if (!e.getMessage().equals("Found reference to named range \"A\", but that named range wasn't defined!")) { throw new AssertionFailedError("Identifed bug 44539"); } diff --git a/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java b/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java index 3960548341..10a64813cd 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java @@ -28,6 +28,7 @@ import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.usermodel.CellValue; import org.apache.poi.ss.formula.FormulaParser; import org.apache.poi.ss.formula.FormulaRenderer; +import org.apache.poi.ss.formula.FormulaType; import org.apache.poi.util.LittleEndianInput; /** @@ -101,7 +102,7 @@ public final class TestSharedFormulaRecord extends TestCase { HSSFEvaluationWorkbook fpb = HSSFEvaluationWorkbook.create(wb); Ptg[] sharedFormula, convertedFormula; - sharedFormula = FormulaParser.parse("A2", fpb); + sharedFormula = FormulaParser.parse("A2", fpb, FormulaType.CELL, -1); convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 0, 0); confirmOperandClasses(sharedFormula, convertedFormula); //conversion relative to [0,0] should return the original formula @@ -117,7 +118,7 @@ public final class TestSharedFormulaRecord extends TestCase { //one row down and one cell right assertEquals("B3", FormulaRenderer.toFormulaString(fpb, convertedFormula)); - sharedFormula = FormulaParser.parse("SUM(A1:C1)", fpb); + sharedFormula = FormulaParser.parse("SUM(A1:C1)", fpb, FormulaType.CELL, -1); convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 0, 0); confirmOperandClasses(sharedFormula, convertedFormula); assertEquals("SUM(A1:C1)", FormulaRenderer.toFormulaString(fpb, convertedFormula)); @@ -139,22 +140,22 @@ public final class TestSharedFormulaRecord extends TestCase { HSSFSheet sheet; HSSFCell cellB32769; HSSFCell cellC32769; - + // Reading directly from XLS file wb = HSSFTestDataSamples.openSampleWorkbook(SHARED_FORMULA_TEST_XLS); sheet = wb.getSheetAt(0); cellB32769 = sheet.getRow(32768).getCell(1); cellC32769 = sheet.getRow(32768).getCell(2); - // check reading of formulas which are shared (two cells from a 1R x 8C range) - assertEquals("B32770*2", cellB32769.getCellFormula()); + // check reading of formulas which are shared (two cells from a 1R x 8C range) + assertEquals("B32770*2", cellB32769.getCellFormula()); assertEquals("C32770*2", cellC32769.getCellFormula()); confirmCellEvaluation(wb, cellB32769, 4); confirmCellEvaluation(wb, cellC32769, 6); // Confirm this example really does have SharedFormulas. // there are 3 others besides the one at A32769:H32769 - assertEquals(4, countSharedFormulas(sheet)); - - + assertEquals(4, countSharedFormulas(sheet)); + + // Re-serialize and check again wb = HSSFTestDataSamples.writeOutAndReadBack(wb); sheet = wb.getSheetAt(0); @@ -164,18 +165,18 @@ public final class TestSharedFormulaRecord extends TestCase { confirmCellEvaluation(wb, cellB32769, 4); assertEquals(4, countSharedFormulas(sheet)); } - + public void testUnshareFormulaDueToChangeFormula() { HSSFWorkbook wb; HSSFSheet sheet; HSSFCell cellB32769; HSSFCell cellC32769; - + wb = HSSFTestDataSamples.openSampleWorkbook(SHARED_FORMULA_TEST_XLS); sheet = wb.getSheetAt(0); cellB32769 = sheet.getRow(32768).getCell(1); cellC32769 = sheet.getRow(32768).getCell(2); - + // Updating cell formula, causing it to become unshared cellB32769.setCellFormula("1+1"); confirmCellEvaluation(wb, cellB32769, 2); @@ -194,25 +195,25 @@ public final class TestSharedFormulaRecord extends TestCase { // changing shared formula cell to blank wb = HSSFTestDataSamples.openSampleWorkbook(SHARED_FORMULA_TEST_XLS); sheet = wb.getSheetAt(0); - + assertEquals("A$1*2", sheet.getRow(ROW_IX).getCell(1).getCellFormula()); cell = sheet.getRow(ROW_IX).getCell(1); cell.setCellType(HSSFCell.CELL_TYPE_BLANK); assertEquals(3, countSharedFormulas(sheet)); - + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); sheet = wb.getSheetAt(0); assertEquals("A$1*2", sheet.getRow(ROW_IX+1).getCell(1).getCellFormula()); - + // deleting shared formula cell wb = HSSFTestDataSamples.openSampleWorkbook(SHARED_FORMULA_TEST_XLS); sheet = wb.getSheetAt(0); - + assertEquals("A$1*2", sheet.getRow(ROW_IX).getCell(1).getCellFormula()); cell = sheet.getRow(ROW_IX).getCell(1); sheet.getRow(ROW_IX).removeCell(cell); assertEquals(3, countSharedFormulas(sheet)); - + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); sheet = wb.getSheetAt(0); assertEquals("A$1*2", sheet.getRow(ROW_IX+1).getCell(1).getCellFormula()); diff --git a/src/testcases/org/apache/poi/ss/formula/FormulaParserTestHelper.java b/src/testcases/org/apache/poi/ss/formula/FormulaParserTestHelper.java deleted file mode 100644 index e7a805013c..0000000000 --- a/src/testcases/org/apache/poi/ss/formula/FormulaParserTestHelper.java +++ /dev/null @@ -1,55 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula; - -import junit.framework.Assert; -import junit.framework.AssertionFailedError; - -import org.apache.poi.ss.formula.FormulaParser.FormulaParseException; -/** - * Avoids making {@link FormulaParseException} public - * - * @author Josh Micich - */ -public class FormulaParserTestHelper { - /** - * @throws AssertionFailedError if e is not a formula parser exception - * or if the exception message doesn't match. - */ - public static void confirmParseException(RuntimeException e, String expectedMessage) { - checkType(e); - Assert.assertEquals(expectedMessage, e.getMessage()); - } - /** - * @throws AssertionFailedError if e is not a formula parser exception - * or if e has no message. - */ - public static void confirmParseException(RuntimeException e) { - checkType(e); - Assert.assertNotNull(e.getMessage()); - } - private static void checkType(RuntimeException e) throws AssertionFailedError { - if (!(e instanceof FormulaParseException)) { - String failMsg = "Expected FormulaParseException, but got (" - + e.getClass().getName() + "):"; - System.err.println(failMsg); - e.printStackTrace(); - throw new AssertionFailedError(failMsg); - } - } -} -- 2.39.5