mirror of https://github.com/apache/poi.git
Bug 45041 - improved FormulaParser parse error messages
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@659452 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c8c2d0139e
commit
71418f099d
|
@ -37,6 +37,7 @@
|
||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.1-final" date="2008-06-??">
|
<release version="3.1-final" date="2008-06-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">45041 - improved FormulaParser parse error messages</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">45046 - allowed EXTERNALBOOK(0x01AE) to be optional in the LinkTable</action>
|
<action dev="POI-DEVELOPERS" type="add">45046 - allowed EXTERNALBOOK(0x01AE) to be optional in the LinkTable</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">45066 - fixed sheet encoding size mismatch problems</action>
|
<action dev="POI-DEVELOPERS" type="add">45066 - fixed sheet encoding size mismatch problems</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">45003 - Support embeded HDGF visio documents</action>
|
<action dev="POI-DEVELOPERS" type="add">45003 - Support embeded HDGF visio documents</action>
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
<!-- Don't forget to update changes.xml too! -->
|
<!-- Don't forget to update changes.xml too! -->
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.1-final" date="2008-06-??">
|
<release version="3.1-final" date="2008-06-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">45041 - improved FormulaParser parse error messages</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">45046 - allowed EXTERNALBOOK(0x01AE) to be optional in the LinkTable</action>
|
<action dev="POI-DEVELOPERS" type="add">45046 - allowed EXTERNALBOOK(0x01AE) to be optional in the LinkTable</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">45066 - fixed sheet encoding size mismatch problems</action>
|
<action dev="POI-DEVELOPERS" type="add">45066 - fixed sheet encoding size mismatch problems</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">45003 - Support embeded HDGF visio documents</action>
|
<action dev="POI-DEVELOPERS" type="add">45003 - Support embeded HDGF visio documents</action>
|
||||||
|
|
|
@ -134,7 +134,7 @@ public final class FormulaParser {
|
||||||
|
|
||||||
/** Report What Was Expected */
|
/** Report What Was Expected */
|
||||||
private RuntimeException expected(String s) {
|
private RuntimeException expected(String s) {
|
||||||
String msg = "Parse error near char " + (pointer-1) + "'" + look + "'"
|
String msg = "Parse error near char " + (pointer-1) + " '" + look + "'"
|
||||||
+ " in specified formula '" + formulaString + "'. Expected "
|
+ " in specified formula '" + formulaString + "'. Expected "
|
||||||
+ s;
|
+ s;
|
||||||
return new FormulaParseException(msg);
|
return new FormulaParseException(msg);
|
||||||
|
@ -486,17 +486,16 @@ public final class FormulaParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean missedPrevArg = true;
|
boolean missedPrevArg = true;
|
||||||
|
|
||||||
int numArgs = 0;
|
int numArgs = 0;
|
||||||
while(true) {
|
while (true) {
|
||||||
SkipWhite();
|
SkipWhite();
|
||||||
if(isArgumentDelimiter(look)) {
|
if (isArgumentDelimiter(look)) {
|
||||||
if(missedPrevArg) {
|
if (missedPrevArg) {
|
||||||
tokens.add(new MissingArgPtg());
|
tokens.add(new MissingArgPtg());
|
||||||
addArgumentPointer(argumentPointers);
|
addArgumentPointer(argumentPointers);
|
||||||
numArgs++;
|
numArgs++;
|
||||||
}
|
}
|
||||||
if(look == ')') {
|
if (look == ')') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Match(',');
|
Match(',');
|
||||||
|
@ -507,6 +506,10 @@ public final class FormulaParser {
|
||||||
addArgumentPointer(argumentPointers);
|
addArgumentPointer(argumentPointers);
|
||||||
numArgs++;
|
numArgs++;
|
||||||
missedPrevArg = false;
|
missedPrevArg = false;
|
||||||
|
SkipWhite();
|
||||||
|
if (!isArgumentDelimiter(look)) {
|
||||||
|
throw expected("',' or ')'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return numArgs;
|
return numArgs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,6 @@ public final class TestFormulaParser extends TestCase {
|
||||||
* @return parsed token array already confirmed not <code>null</code>
|
* @return parsed token array already confirmed not <code>null</code>
|
||||||
*/
|
*/
|
||||||
private static Ptg[] parseFormula(String s) {
|
private static Ptg[] parseFormula(String s) {
|
||||||
// TODO - replace multiple copies of this code with calls to this method
|
|
||||||
FormulaParser fp = new FormulaParser(s, null);
|
FormulaParser fp = new FormulaParser(s, null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
Ptg[] result = fp.getRPNPtg();
|
Ptg[] result = fp.getRPNPtg();
|
||||||
|
@ -74,69 +73,48 @@ public final class TestFormulaParser extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSimpleFormula() {
|
public void testSimpleFormula() {
|
||||||
FormulaParser fp = new FormulaParser("2+2",null);
|
Ptg[] ptgs = parseFormula("2+2");
|
||||||
fp.parse();
|
assertEquals(3, ptgs.length);
|
||||||
Ptg[] ptgs = fp.getRPNPtg();
|
|
||||||
assertTrue("three tokens expected, got "+ptgs.length,ptgs.length == 3);
|
|
||||||
}
|
}
|
||||||
public void testFormulaWithSpace1() {
|
public void testFormulaWithSpace1() {
|
||||||
FormulaParser fp = new FormulaParser(" 2 + 2 ",null);
|
Ptg[] ptgs = parseFormula(" 2 + 2 ");
|
||||||
fp.parse();
|
assertEquals(3, ptgs.length);
|
||||||
Ptg[] ptgs = fp.getRPNPtg();
|
|
||||||
assertTrue("three tokens expected, got "+ptgs.length,ptgs.length == 3);
|
|
||||||
assertTrue("",(ptgs[0] instanceof IntPtg));
|
assertTrue("",(ptgs[0] instanceof IntPtg));
|
||||||
assertTrue("",(ptgs[1] instanceof IntPtg));
|
assertTrue("",(ptgs[1] instanceof IntPtg));
|
||||||
assertTrue("",(ptgs[2] instanceof AddPtg));
|
assertTrue("",(ptgs[2] instanceof AddPtg));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFormulaWithSpace2() {
|
public void testFormulaWithSpace2() {
|
||||||
Ptg[] ptgs;
|
Ptg[] ptgs = parseFormula("2+ sum( 3 , 4) ");
|
||||||
FormulaParser fp;
|
assertEquals(5, ptgs.length);
|
||||||
fp = new FormulaParser("2+ sum( 3 , 4) ",null);
|
|
||||||
fp.parse();
|
|
||||||
ptgs = fp.getRPNPtg();
|
|
||||||
assertTrue("five tokens expected, got "+ptgs.length,ptgs.length == 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFormulaWithSpaceNRef() {
|
public void testFormulaWithSpaceNRef() {
|
||||||
Ptg[] ptgs;
|
Ptg[] ptgs = parseFormula("sum( A2:A3 )");
|
||||||
FormulaParser fp;
|
assertEquals(2, ptgs.length);
|
||||||
fp = new FormulaParser("sum( A2:A3 )",null);
|
|
||||||
fp.parse();
|
|
||||||
ptgs = fp.getRPNPtg();
|
|
||||||
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFormulaWithString() {
|
public void testFormulaWithString() {
|
||||||
Ptg[] ptgs;
|
Ptg[] ptgs = parseFormula("\"hello\" & \"world\" ");
|
||||||
FormulaParser fp;
|
assertEquals(3, ptgs.length);
|
||||||
fp = new FormulaParser("\"hello\" & \"world\" ",null);
|
|
||||||
fp.parse();
|
|
||||||
ptgs = fp.getRPNPtg();
|
|
||||||
assertTrue("three token expected, got " + ptgs.length, ptgs.length == 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTRUE() throws Exception {
|
public void testTRUE() {
|
||||||
FormulaParser fp = new FormulaParser("TRUE", null);
|
Ptg[] ptgs = parseFormula("TRUE");
|
||||||
fp.parse();
|
assertEquals(1, ptgs.length);
|
||||||
Ptg[] asts = fp.getRPNPtg();
|
BoolPtg flag = (BoolPtg) ptgs[0];
|
||||||
assertEquals(1, asts.length);
|
|
||||||
BoolPtg flag = (BoolPtg) asts[0];
|
|
||||||
assertEquals(true, flag.getValue());
|
assertEquals(true, flag.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testYN() throws Exception {
|
public void testYN() {
|
||||||
final String yn = "IF(TRUE,\"Y\",\"N\")";
|
Ptg[] ptgs = parseFormula("IF(TRUE,\"Y\",\"N\")");
|
||||||
FormulaParser fp = new FormulaParser(yn, null);
|
assertEquals(7, ptgs.length);
|
||||||
fp.parse();
|
|
||||||
Ptg[] asts = fp.getRPNPtg();
|
|
||||||
assertEquals(7, asts.length);
|
|
||||||
|
|
||||||
BoolPtg flag = (BoolPtg) asts[0];
|
BoolPtg flag = (BoolPtg) ptgs[0];
|
||||||
AttrPtg funif = (AttrPtg) asts[1];
|
AttrPtg funif = (AttrPtg) ptgs[1];
|
||||||
StringPtg y = (StringPtg) asts[2];
|
StringPtg y = (StringPtg) ptgs[2];
|
||||||
AttrPtg goto1 = (AttrPtg) asts[3];
|
AttrPtg goto1 = (AttrPtg) ptgs[3];
|
||||||
StringPtg n = (StringPtg) asts[4];
|
StringPtg n = (StringPtg) ptgs[4];
|
||||||
|
|
||||||
|
|
||||||
assertEquals(true, flag.getValue());
|
assertEquals(true, flag.getValue());
|
||||||
|
@ -146,29 +124,31 @@ public final class TestFormulaParser extends TestCase {
|
||||||
assertTrue("Goto ptg exists", goto1.isGoto());
|
assertTrue("Goto ptg exists", goto1.isGoto());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSimpleIf() throws Exception {
|
public void testSimpleIf() {
|
||||||
final String simpleif = "IF(1=1,0,1)";
|
String formula = "IF(1=1,0,1)";
|
||||||
FormulaParser fp = new FormulaParser(simpleif, null);
|
|
||||||
fp.parse();
|
|
||||||
Ptg[] asts = fp.getRPNPtg();
|
|
||||||
assertEquals(9, asts.length);
|
|
||||||
|
|
||||||
IntPtg op1 = (IntPtg) asts[0];
|
Class[] expectedClasses = {
|
||||||
IntPtg op2 = (IntPtg) asts[1];
|
IntPtg.class,
|
||||||
EqualPtg eq = (EqualPtg) asts[2];
|
IntPtg.class,
|
||||||
AttrPtg ifPtg = (AttrPtg) asts[3];
|
EqualPtg.class,
|
||||||
IntPtg res1 = (IntPtg) asts[4];
|
AttrPtg.class,
|
||||||
|
IntPtg.class,
|
||||||
|
AttrPtg.class,
|
||||||
|
IntPtg.class,
|
||||||
|
AttrPtg.class,
|
||||||
|
FuncVarPtg.class,
|
||||||
|
};
|
||||||
|
confirmTokenClasses(formula, expectedClasses);
|
||||||
|
|
||||||
AttrPtg ptgGoto= (AttrPtg) asts[5];
|
Ptg[] ptgs = parseFormula(formula);
|
||||||
assertEquals("Goto 1 Length", (short)10, ptgGoto.getData());
|
|
||||||
|
|
||||||
IntPtg res2 = (IntPtg) asts[6];
|
AttrPtg ifPtg = (AttrPtg) ptgs[3];
|
||||||
AttrPtg ptgGoto2 = (AttrPtg) asts[7];
|
AttrPtg ptgGoto= (AttrPtg) ptgs[5];
|
||||||
assertEquals("Goto 2 Length", (short)3, ptgGoto2.getData());
|
assertEquals("Goto 1 Length", 10, ptgGoto.getData());
|
||||||
|
|
||||||
assertEquals("If FALSE offset", (short)7, ifPtg.getData());
|
AttrPtg ptgGoto2 = (AttrPtg) ptgs[7];
|
||||||
|
assertEquals("Goto 2 Length", 3, ptgGoto2.getData());
|
||||||
FuncVarPtg funcPtg = (FuncVarPtg)asts[8];
|
assertEquals("If FALSE offset", 7, ifPtg.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -176,47 +156,36 @@ public final class TestFormulaParser extends TestCase {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void testNestedFunctionIf() {
|
public void testNestedFunctionIf() {
|
||||||
String function = "IF(A1=B1,AVERAGE(A1:B1),AVERAGE(A2:B2))";
|
Ptg[] ptgs = parseFormula("IF(A1=B1,AVERAGE(A1:B1),AVERAGE(A2:B2))");
|
||||||
|
assertEquals(11, ptgs.length);
|
||||||
|
|
||||||
FormulaParser fp = new FormulaParser(function, null);
|
assertTrue("IF Attr set correctly", (ptgs[3] instanceof AttrPtg));
|
||||||
fp.parse();
|
AttrPtg ifFunc = (AttrPtg)ptgs[3];
|
||||||
Ptg[] asts = fp.getRPNPtg();
|
|
||||||
assertEquals("11 Ptgs expected", 11, asts.length);
|
|
||||||
|
|
||||||
assertTrue("IF Attr set correctly", (asts[3] instanceof AttrPtg));
|
|
||||||
AttrPtg ifFunc = (AttrPtg)asts[3];
|
|
||||||
assertTrue("It is not an if", ifFunc.isOptimizedIf());
|
assertTrue("It is not an if", ifFunc.isOptimizedIf());
|
||||||
|
|
||||||
assertTrue("Average Function set correctly", (asts[5] instanceof FuncVarPtg));
|
assertTrue("Average Function set correctly", (ptgs[5] instanceof FuncVarPtg));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIfSingleCondition(){
|
public void testIfSingleCondition(){
|
||||||
String function = "IF(1=1,10)";
|
Ptg[] ptgs = parseFormula("IF(1=1,10)");
|
||||||
|
assertEquals(7, ptgs.length);
|
||||||
|
|
||||||
FormulaParser fp = new FormulaParser(function, null);
|
assertTrue("IF Attr set correctly", (ptgs[3] instanceof AttrPtg));
|
||||||
fp.parse();
|
AttrPtg ifFunc = (AttrPtg)ptgs[3];
|
||||||
Ptg[] asts = fp.getRPNPtg();
|
|
||||||
assertEquals("7 Ptgs expected", 7, asts.length);
|
|
||||||
|
|
||||||
assertTrue("IF Attr set correctly", (asts[3] instanceof AttrPtg));
|
|
||||||
AttrPtg ifFunc = (AttrPtg)asts[3];
|
|
||||||
assertTrue("It is not an if", ifFunc.isOptimizedIf());
|
assertTrue("It is not an if", ifFunc.isOptimizedIf());
|
||||||
|
|
||||||
assertTrue("Single Value is not an IntPtg", (asts[4] instanceof IntPtg));
|
assertTrue("Single Value is not an IntPtg", (ptgs[4] instanceof IntPtg));
|
||||||
IntPtg intPtg = (IntPtg)asts[4];
|
IntPtg intPtg = (IntPtg)ptgs[4];
|
||||||
assertEquals("Result", (short)10, intPtg.getValue());
|
assertEquals("Result", (short)10, intPtg.getValue());
|
||||||
|
|
||||||
assertTrue("Ptg is not a Variable Function", (asts[6] instanceof FuncVarPtg));
|
assertTrue("Ptg is not a Variable Function", (ptgs[6] instanceof FuncVarPtg));
|
||||||
FuncVarPtg funcPtg = (FuncVarPtg)asts[6];
|
FuncVarPtg funcPtg = (FuncVarPtg)ptgs[6];
|
||||||
assertEquals("Arguments", 2, funcPtg.getNumberOfOperands());
|
assertEquals("Arguments", 2, funcPtg.getNumberOfOperands());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSumIf() {
|
public void testSumIf() {
|
||||||
String function ="SUMIF(A1:A5,\">4000\",B1:B5)";
|
Ptg[] ptgs = parseFormula("SUMIF(A1:A5,\">4000\",B1:B5)");
|
||||||
FormulaParser fp = new FormulaParser(function, null);
|
assertEquals(4, ptgs.length);
|
||||||
fp.parse();
|
|
||||||
Ptg[] asts = fp.getRPNPtg();
|
|
||||||
assertEquals("4 Ptgs expected", 4, asts.length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -224,14 +193,12 @@ public final class TestFormulaParser extends TestCase {
|
||||||
* Refers to Bug <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=17582">#17582</a>
|
* Refers to Bug <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=17582">#17582</a>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void testNonAlphaFormula(){
|
public void testNonAlphaFormula() {
|
||||||
String currencyCell = "F3";
|
String currencyCell = "F3";
|
||||||
String function="\"TOTAL[\"&"+currencyCell+"&\"]\"";
|
Ptg[] ptgs = parseFormula("\"TOTAL[\"&"+currencyCell+"&\"]\"");
|
||||||
|
assertEquals(5, ptgs.length);
|
||||||
Ptg[] asts = parseFormula(function);
|
assertTrue ("Ptg[0] is a string", (ptgs[0] instanceof StringPtg));
|
||||||
assertEquals("5 ptgs expected", 5, asts.length);
|
StringPtg firstString = (StringPtg)ptgs[0];
|
||||||
assertTrue ("Ptg[0] is a string", (asts[0] instanceof StringPtg));
|
|
||||||
StringPtg firstString = (StringPtg)asts[0];
|
|
||||||
|
|
||||||
assertEquals("TOTAL[", firstString.getValue());
|
assertEquals("TOTAL[", firstString.getValue());
|
||||||
//the PTG order isn't 100% correct but it still works - dmui
|
//the PTG order isn't 100% correct but it still works - dmui
|
||||||
|
@ -239,20 +206,20 @@ public final class TestFormulaParser extends TestCase {
|
||||||
|
|
||||||
public void testSimpleLogical() {
|
public void testSimpleLogical() {
|
||||||
Ptg[] ptgs = parseFormula("IF(A1<A2,B1,B2)");
|
Ptg[] ptgs = parseFormula("IF(A1<A2,B1,B2)");
|
||||||
assertEquals("Ptg array length", 9, ptgs.length);
|
assertEquals(9, ptgs.length);
|
||||||
assertEquals("3rd Ptg is less than", LessThanPtg.class, ptgs[2].getClass());
|
assertEquals("3rd Ptg is less than", LessThanPtg.class, ptgs[2].getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParenIf() {
|
public void testParenIf() {
|
||||||
Ptg[] ptgs = parseFormula("IF((A1+A2)<=3,\"yes\",\"no\")");
|
Ptg[] ptgs = parseFormula("IF((A1+A2)<=3,\"yes\",\"no\")");
|
||||||
assertEquals("Ptg array length", 12, ptgs.length);
|
assertEquals(12, ptgs.length);
|
||||||
assertEquals("6th Ptg is less than equal",LessEqualPtg.class,ptgs[5].getClass());
|
assertEquals("6th Ptg is less than equal",LessEqualPtg.class,ptgs[5].getClass());
|
||||||
assertEquals("11th Ptg is not a goto (Attr) ptg",AttrPtg.class,ptgs[10].getClass());
|
assertEquals("11th Ptg is not a goto (Attr) ptg",AttrPtg.class,ptgs[10].getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testEmbeddedIf() {
|
public void testEmbeddedIf() {
|
||||||
Ptg[] ptgs = parseFormula("IF(3>=1,\"*\",IF(4<>1,\"first\",\"second\"))");
|
Ptg[] ptgs = parseFormula("IF(3>=1,\"*\",IF(4<>1,\"first\",\"second\"))");
|
||||||
assertEquals("Ptg array length", 17, ptgs.length);
|
assertEquals(17, ptgs.length);
|
||||||
|
|
||||||
assertEquals("6th Ptg is not a goto (Attr) ptg",AttrPtg.class,ptgs[5].getClass());
|
assertEquals("6th Ptg is not a goto (Attr) ptg",AttrPtg.class,ptgs[5].getClass());
|
||||||
assertEquals("9th Ptg is not a not equal ptg",NotEqualPtg.class,ptgs[8].getClass());
|
assertEquals("9th Ptg is not a not equal ptg",NotEqualPtg.class,ptgs[8].getClass());
|
||||||
|
@ -274,23 +241,18 @@ public final class TestFormulaParser extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testEmbeddedSlash() {
|
public void testEmbeddedSlash() {
|
||||||
FormulaParser fp = new FormulaParser("HYPERLINK(\"http://www.jakarta.org\",\"Jakarta\")",null);
|
Ptg[] ptgs = parseFormula("HYPERLINK(\"http://www.jakarta.org\",\"Jakarta\")");
|
||||||
fp.parse();
|
assertTrue("first ptg is string", ptgs[0] instanceof StringPtg);
|
||||||
Ptg[] ptg = fp.getRPNPtg();
|
assertTrue("second ptg is string", ptgs[1] instanceof StringPtg);
|
||||||
assertTrue("first ptg is string",ptg[0] instanceof StringPtg);
|
|
||||||
assertTrue("second ptg is string",ptg[1] instanceof StringPtg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testConcatenate() {
|
public void testConcatenate() {
|
||||||
FormulaParser fp = new FormulaParser("CONCATENATE(\"first\",\"second\")", null);
|
Ptg[] ptgs = parseFormula("CONCATENATE(\"first\",\"second\")");
|
||||||
fp.parse();
|
assertTrue("first ptg is string", ptgs[0] instanceof StringPtg);
|
||||||
Ptg[] ptg = fp.getRPNPtg();
|
assertTrue("second ptg is string", ptgs[1] instanceof StringPtg);
|
||||||
assertTrue("first ptg is string", ptg[0] instanceof StringPtg);
|
|
||||||
assertTrue("second ptg is string", ptg[1] instanceof StringPtg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWorksheetReferences()
|
public void testWorksheetReferences() {
|
||||||
{
|
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
|
||||||
wb.createSheet("NoQuotesNeeded");
|
wb.createSheet("NoQuotesNeeded");
|
||||||
|
@ -307,74 +269,54 @@ public final class TestFormulaParser extends TestCase {
|
||||||
cell.setCellFormula("'Quotes Needed Here &#$@'!A1");
|
cell.setCellFormula("'Quotes Needed Here &#$@'!A1");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUnaryMinus()
|
public void testUnaryMinus() {
|
||||||
{
|
Ptg[] ptgs = parseFormula("-A1");
|
||||||
FormulaParser fp = new FormulaParser("-A1", null);
|
assertEquals(2, ptgs.length);
|
||||||
fp.parse();
|
assertTrue("first ptg is reference",ptgs[0] instanceof ReferencePtg);
|
||||||
Ptg[] ptg = fp.getRPNPtg();
|
assertTrue("second ptg is Minus",ptgs[1] instanceof UnaryMinusPtg);
|
||||||
assertTrue("got 2 ptgs", ptg.length == 2);
|
|
||||||
assertTrue("first ptg is reference",ptg[0] instanceof ReferencePtg);
|
|
||||||
assertTrue("second ptg is Minus",ptg[1] instanceof UnaryMinusPtg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUnaryPlus()
|
public void testUnaryPlus() {
|
||||||
{
|
Ptg[] ptgs = parseFormula("+A1");
|
||||||
FormulaParser fp = new FormulaParser("+A1", null);
|
assertEquals(2, ptgs.length);
|
||||||
fp.parse();
|
assertTrue("first ptg is reference",ptgs[0] instanceof ReferencePtg);
|
||||||
Ptg[] ptg = fp.getRPNPtg();
|
assertTrue("second ptg is Plus",ptgs[1] instanceof UnaryPlusPtg);
|
||||||
assertTrue("got 2 ptgs", ptg.length == 2);
|
|
||||||
assertTrue("first ptg is reference",ptg[0] instanceof ReferencePtg);
|
|
||||||
assertTrue("second ptg is Plus",ptg[1] instanceof UnaryPlusPtg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLeadingSpaceInString()
|
public void testLeadingSpaceInString() {
|
||||||
{
|
|
||||||
String value = " hi ";
|
String value = " hi ";
|
||||||
FormulaParser fp = new FormulaParser("\"" + value + "\"", null);
|
Ptg[] ptgs = parseFormula("\"" + value + "\"");
|
||||||
fp.parse();
|
|
||||||
Ptg[] ptg = fp.getRPNPtg();
|
|
||||||
|
|
||||||
assertTrue("got 1 ptg", ptg.length == 1);
|
assertEquals(1, ptgs.length);
|
||||||
assertTrue("ptg0 is a StringPtg", ptg[0] instanceof StringPtg);
|
assertTrue("ptg0 is a StringPtg", ptgs[0] instanceof StringPtg);
|
||||||
assertTrue("ptg0 contains exact value", ((StringPtg)ptg[0]).getValue().equals(value));
|
assertTrue("ptg0 contains exact value", ((StringPtg)ptgs[0]).getValue().equals(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLookupAndMatchFunctionArgs()
|
public void testLookupAndMatchFunctionArgs() {
|
||||||
{
|
Ptg[] ptgs = parseFormula("lookup(A1, A3:A52, B3:B52)");
|
||||||
FormulaParser fp = new FormulaParser("lookup(A1, A3:A52, B3:B52)", null);
|
|
||||||
fp.parse();
|
|
||||||
Ptg[] ptg = fp.getRPNPtg();
|
|
||||||
|
|
||||||
assertTrue("got 4 ptg", ptg.length == 4);
|
assertEquals(4, ptgs.length);
|
||||||
assertTrue("ptg0 has Value class", ptg[0].getPtgClass() == Ptg.CLASS_VALUE);
|
assertTrue("ptg0 has Value class", ptgs[0].getPtgClass() == Ptg.CLASS_VALUE);
|
||||||
|
|
||||||
fp = new FormulaParser("match(A1, A3:A52)", null);
|
ptgs = parseFormula("match(A1, A3:A52)");
|
||||||
fp.parse();
|
|
||||||
ptg = fp.getRPNPtg();
|
|
||||||
|
|
||||||
assertTrue("got 3 ptg", ptg.length == 3);
|
assertEquals(3, ptgs.length);
|
||||||
assertTrue("ptg0 has Value class", ptg[0].getPtgClass() == Ptg.CLASS_VALUE);
|
assertTrue("ptg0 has Value class", ptgs[0].getPtgClass() == Ptg.CLASS_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** bug 33160*/
|
/** bug 33160*/
|
||||||
public void testLargeInt() {
|
public void testLargeInt() {
|
||||||
FormulaParser fp = new FormulaParser("40", null);
|
Ptg[] ptgs = parseFormula("40");
|
||||||
fp.parse();
|
assertTrue("ptg is Int, is "+ptgs[0].getClass(),ptgs[0] instanceof IntPtg);
|
||||||
Ptg[] ptg=fp.getRPNPtg();
|
|
||||||
assertTrue("ptg is Int, is "+ptg[0].getClass(),ptg[0] instanceof IntPtg);
|
|
||||||
|
|
||||||
fp = new FormulaParser("40000", null);
|
ptgs = parseFormula("40000");
|
||||||
fp.parse();
|
assertTrue("ptg should be IntPtg, is "+ptgs[0].getClass(), ptgs[0] instanceof IntPtg);
|
||||||
ptg=fp.getRPNPtg();
|
|
||||||
assertTrue("ptg should be IntPtg, is "+ptg[0].getClass(), ptg[0] instanceof IntPtg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** bug 33160, testcase by Amol Deshmukh*/
|
/** bug 33160, testcase by Amol Deshmukh*/
|
||||||
public void testSimpleLongFormula() {
|
public void testSimpleLongFormula() {
|
||||||
FormulaParser fp = new FormulaParser("40000/2", null);
|
Ptg[] ptgs = parseFormula("40000/2");
|
||||||
fp.parse();
|
assertEquals(3, ptgs.length);
|
||||||
Ptg[] ptgs = fp.getRPNPtg();
|
|
||||||
assertTrue("three tokens expected, got " + ptgs.length, ptgs.length == 3);
|
|
||||||
assertTrue("IntPtg", (ptgs[0] instanceof IntPtg));
|
assertTrue("IntPtg", (ptgs[0] instanceof IntPtg));
|
||||||
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
|
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
|
||||||
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
|
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
|
||||||
|
@ -392,37 +334,31 @@ public final class TestFormulaParser extends TestCase {
|
||||||
|
|
||||||
cell = row.createCell((short)0);
|
cell = row.createCell((short)0);
|
||||||
cell.setCellFormula("Cash_Flow!A1");
|
cell.setCellFormula("Cash_Flow!A1");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bug 38396 : Formula with exponential numbers not parsed correctly.
|
// bug 38396 : Formula with exponential numbers not parsed correctly.
|
||||||
public void testExponentialParsing() {
|
public void testExponentialParsing() {
|
||||||
FormulaParser fp = new FormulaParser("1.3E21/2", null);
|
Ptg[] ptgs;
|
||||||
fp.parse();
|
ptgs = parseFormula("1.3E21/2");
|
||||||
Ptg[] ptgs = fp.getRPNPtg();
|
assertEquals(3, ptgs.length);
|
||||||
assertTrue("three tokens expected, got " + ptgs.length, ptgs.length == 3);
|
|
||||||
assertTrue("NumberPtg", (ptgs[0] instanceof NumberPtg));
|
assertTrue("NumberPtg", (ptgs[0] instanceof NumberPtg));
|
||||||
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
|
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
|
||||||
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
|
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
|
||||||
|
|
||||||
fp = new FormulaParser("1322E21/2", null);
|
ptgs = parseFormula("1322E21/2");
|
||||||
fp.parse();
|
assertEquals(3, ptgs.length);
|
||||||
ptgs = fp.getRPNPtg();
|
|
||||||
assertTrue("three tokens expected, got " + ptgs.length, ptgs.length == 3);
|
|
||||||
assertTrue("NumberPtg", (ptgs[0] instanceof NumberPtg));
|
assertTrue("NumberPtg", (ptgs[0] instanceof NumberPtg));
|
||||||
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
|
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
|
||||||
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
|
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
|
||||||
|
|
||||||
fp = new FormulaParser("1.3E1/2", null);
|
ptgs = parseFormula("1.3E1/2");
|
||||||
fp.parse();
|
assertEquals(3, ptgs.length);
|
||||||
ptgs = fp.getRPNPtg();
|
|
||||||
assertTrue("three tokens expected, got " + ptgs.length, ptgs.length == 3);
|
|
||||||
assertTrue("NumberPtg", (ptgs[0] instanceof NumberPtg));
|
assertTrue("NumberPtg", (ptgs[0] instanceof NumberPtg));
|
||||||
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
|
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
|
||||||
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
|
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
|
||||||
|
|
||||||
}
|
}
|
||||||
public void testExponentialInSheet() throws Exception {
|
|
||||||
|
public void testExponentialInSheet() {
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
|
||||||
wb.createSheet("Cash_Flow");
|
wb.createSheet("Cash_Flow");
|
||||||
|
@ -493,11 +429,6 @@ public final class TestFormulaParser extends TestCase {
|
||||||
assertEquals("Exponential formula string", "-1.0/310.0*4000.0/30000.0", formula);
|
assertEquals("Exponential formula string", "-1.0/310.0*4000.0/30000.0", formula);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String [] args) {
|
|
||||||
System.out.println("Testing org.apache.poi.hssf.record.formula.FormulaParser");
|
|
||||||
junit.textui.TestRunner.run(TestFormulaParser.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testNumbers() {
|
public void testNumbers() {
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
|
||||||
|
@ -896,15 +827,15 @@ public final class TestFormulaParser extends TestCase {
|
||||||
* (e.g. COUNTIF) Excel fails to evaluate the formula, giving '#VALUE!' instead.
|
* (e.g. COUNTIF) Excel fails to evaluate the formula, giving '#VALUE!' instead.
|
||||||
*/
|
*/
|
||||||
public void testFuncPtgSelection() {
|
public void testFuncPtgSelection() {
|
||||||
HSSFWorkbook book = new HSSFWorkbook();
|
|
||||||
Ptg[] ptgs;
|
Ptg[] ptgs;
|
||||||
ptgs = FormulaParser.parse("countif(A1:A2, 1)", book);
|
ptgs = parseFormula("countif(A1:A2, 1)");
|
||||||
assertEquals(3, ptgs.length);
|
assertEquals(3, ptgs.length);
|
||||||
if(FuncVarPtg.class == ptgs[2].getClass()) {
|
if(FuncVarPtg.class == ptgs[2].getClass()) {
|
||||||
throw new AssertionFailedError("Identified bug 44675");
|
throw new AssertionFailedError("Identified bug 44675");
|
||||||
}
|
}
|
||||||
assertEquals(FuncPtg.class, ptgs[2].getClass());
|
assertEquals(FuncPtg.class, ptgs[2].getClass());
|
||||||
ptgs = FormulaParser.parse("sin(1)", book);
|
ptgs = parseFormula("sin(1)");
|
||||||
assertEquals(2, ptgs.length);
|
assertEquals(2, ptgs.length);
|
||||||
assertEquals(FuncPtg.class, ptgs[1].getClass());
|
assertEquals(FuncPtg.class, ptgs[1].getClass());
|
||||||
}
|
}
|
||||||
|
@ -925,4 +856,14 @@ public final class TestFormulaParser extends TestCase {
|
||||||
assertEquals(expectedMessage, e.getMessage());
|
assertEquals(expectedMessage, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testParseErrorExpecteMsg() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
parseFormula("round(3.14;2)");
|
||||||
|
throw new AssertionFailedError("Didn't get parse exception as expected");
|
||||||
|
} catch (FormulaParseException e) {
|
||||||
|
assertEquals("Parse error near char 10 ';' in specified formula 'round(3.14;2)'. Expected ',' or ')'", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue