Patch 48284 - raise visibility of FormulaParseException

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@885007 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2009-11-27 21:01:59 +00:00
parent c73dd9d324
commit 5c7dbb2730
12 changed files with 157 additions and 215 deletions

View File

@ -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);
}

View File

@ -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.
* <p>
* 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)}
* </p>
*
* @param formula the formula to set, e.g. <code>SUM(C4:E4)</code>.
* If the argument is <code>null</code> 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 + "')");
}
}

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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;
* <term> ::= <factor> [ <mulop> <factor> ]*
* <factor> ::= <number> | (<expression>) | <cellRef> | <function>
* <function> ::= <functionName> ([expression [, expression]*])
* <p/>
* For POI internal use only
* <p/>
*
*
* @author Avik Sengupta <avik at apache dot org>
* @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.<br/>
* Primarily used by test cases when testing for specific parsing exceptions.</p>
*
*/
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 <code>true</code> 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;
//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;
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;
}

View File

@ -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.
* <p>
@ -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.
* <p>
@ -210,11 +213,11 @@ public interface Cell {
* To set the precalculated value use {@link #setCellValue(double)} or {@link #setCellValue(String)}
* </p>
*
* @param formula the formula to set, e.g. <code>SUM(C4:E4)</code>.
* @param formula the formula to set, e.g. <code>"SUM(C4:E4)"</code>.
* If the argument is <code>null</code> 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, <code>SUM(C4:E4)</code>

View File

@ -362,17 +362,6 @@ public final class XSSFCell implements Cell {
return FormulaRenderer.toFormulaString(fpb, fmla);
}
/**
* Sets formula for this cell.
* <p>
* 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)}
* </p>
*
* @param formula the formula to set, e.g. <code>SUM(C4:E4)</code>.
* If the argument is <code>null</code> 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) {

View File

@ -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);
}
}
}

View File

@ -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());
}
}

View File

@ -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");
}

View File

@ -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());

View File

@ -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 <tt>e</tt> 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 <tt>e</tt> is not a formula parser exception
* or if <tt>e</tt> 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);
}
}
}