import org.apache.poi.hssf.record.formula.FuncPtg;
import org.apache.poi.hssf.record.formula.FuncVarPtg;
import org.apache.poi.hssf.record.formula.IntPtg;
-import org.apache.poi.hssf.record.formula.LessEqualPtg;
-import org.apache.poi.hssf.record.formula.LessThanPtg;
import org.apache.poi.hssf.record.formula.MissingArgPtg;
import org.apache.poi.hssf.record.formula.MultiplyPtg;
import org.apache.poi.hssf.record.formula.NamePtg;
-import org.apache.poi.hssf.record.formula.NotEqualPtg;
import org.apache.poi.hssf.record.formula.NumberPtg;
import org.apache.poi.hssf.record.formula.PercentPtg;
import org.apache.poi.hssf.record.formula.PowerPtg;
/**
* @return parsed token array already confirmed not <code>null</code>
*/
- private static Ptg[] parseFormula(String s) {
- FormulaParser fp = new FormulaParser(s, null);
- fp.parse();
- Ptg[] result = fp.getRPNPtg();
+ /* package */ static Ptg[] parseFormula(String formula) {
+ Ptg[] result = FormulaParser.parse(formula, null);
assertNotNull("Ptg array should not be null", result);
return result;
}
assertEquals(true, flag.getValue());
}
- public void testYN() {
- Ptg[] ptgs = parseFormula("IF(TRUE,\"Y\",\"N\")");
- assertEquals(7, ptgs.length);
-
- BoolPtg flag = (BoolPtg) ptgs[0];
- AttrPtg funif = (AttrPtg) ptgs[1];
- StringPtg y = (StringPtg) ptgs[2];
- AttrPtg goto1 = (AttrPtg) ptgs[3];
- StringPtg n = (StringPtg) ptgs[4];
-
-
- assertEquals(true, flag.getValue());
- assertEquals("Y", y.getValue());
- assertEquals("N", n.getValue());
- assertEquals("IF", funif.toFormulaString((HSSFWorkbook) null));
- assertTrue("Goto ptg exists", goto1.isGoto());
- }
-
- public void testSimpleIf() {
- String formula = "IF(1=1,0,1)";
-
- Class[] expectedClasses = {
- IntPtg.class,
- IntPtg.class,
- EqualPtg.class,
- AttrPtg.class,
- IntPtg.class,
- AttrPtg.class,
- IntPtg.class,
- AttrPtg.class,
- FuncVarPtg.class,
- };
- confirmTokenClasses(formula, expectedClasses);
-
- Ptg[] ptgs = parseFormula(formula);
-
- AttrPtg ifPtg = (AttrPtg) ptgs[3];
- AttrPtg ptgGoto= (AttrPtg) ptgs[5];
- assertEquals("Goto 1 Length", 10, ptgGoto.getData());
-
- AttrPtg ptgGoto2 = (AttrPtg) ptgs[7];
- assertEquals("Goto 2 Length", 3, ptgGoto2.getData());
- assertEquals("If FALSE offset", 7, ifPtg.getData());
- }
-
- /**
- * Make sure the ptgs are generated properly with two functions embedded
- *
- */
- public void testNestedFunctionIf() {
- Ptg[] ptgs = parseFormula("IF(A1=B1,AVERAGE(A1:B1),AVERAGE(A2:B2))");
- assertEquals(11, ptgs.length);
-
- assertTrue("IF Attr set correctly", (ptgs[3] instanceof AttrPtg));
- AttrPtg ifFunc = (AttrPtg)ptgs[3];
- assertTrue("It is not an if", ifFunc.isOptimizedIf());
-
- assertTrue("Average Function set correctly", (ptgs[5] instanceof FuncVarPtg));
- }
-
- public void testIfSingleCondition(){
- Ptg[] ptgs = parseFormula("IF(1=1,10)");
- assertEquals(7, ptgs.length);
-
- assertTrue("IF Attr set correctly", (ptgs[3] instanceof AttrPtg));
- AttrPtg ifFunc = (AttrPtg)ptgs[3];
- assertTrue("It is not an if", ifFunc.isOptimizedIf());
-
- assertTrue("Single Value is not an IntPtg", (ptgs[4] instanceof IntPtg));
- IntPtg intPtg = (IntPtg)ptgs[4];
- assertEquals("Result", (short)10, intPtg.getValue());
-
- assertTrue("Ptg is not a Variable Function", (ptgs[6] instanceof FuncVarPtg));
- FuncVarPtg funcPtg = (FuncVarPtg)ptgs[6];
- assertEquals("Arguments", 2, funcPtg.getNumberOfOperands());
- }
-
public void testSumIf() {
Ptg[] ptgs = parseFormula("SUMIF(A1:A5,\">4000\",B1:B5)");
assertEquals(4, ptgs.length);
//the PTG order isn't 100% correct but it still works - dmui
}
- public void testSimpleLogical() {
- Ptg[] ptgs = parseFormula("IF(A1<A2,B1,B2)");
- assertEquals(9, ptgs.length);
- assertEquals("3rd Ptg is less than", LessThanPtg.class, ptgs[2].getClass());
- }
-
- public void testParenIf() {
- Ptg[] ptgs = parseFormula("IF((A1+A2)<=3,\"yes\",\"no\")");
- assertEquals(12, ptgs.length);
- 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());
- }
-
- public void testEmbeddedIf() {
- Ptg[] ptgs = parseFormula("IF(3>=1,\"*\",IF(4<>1,\"first\",\"second\"))");
- assertEquals(17, ptgs.length);
-
- 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("15th Ptg is not the inner IF variable function ptg",FuncVarPtg.class,ptgs[14].getClass());
- }
-
public void testMacroFunction() {
HSSFWorkbook w = new HSSFWorkbook();
- FormulaParser fp = new FormulaParser("FOO()", w);
- fp.parse();
- Ptg[] ptg = fp.getRPNPtg();
+ Ptg[] ptg = FormulaParser.parse("FOO()", w);
// the name gets encoded as the first arg
NamePtg tname = (NamePtg) ptg[0];
confirmTokenClasses("2^200%", expClss);
}
- private static void confirmTokenClasses(String formula, Class[] expectedClasses) {
+ /* package */ static Ptg[] confirmTokenClasses(String formula, Class[] expectedClasses) {
Ptg[] ptgs = parseFormula(formula);
assertEquals(expectedClasses.length, ptgs.length);
for (int i = 0; i < expectedClasses.length; i++) {
+ ptgs[i].getClass().getName() + ")");
}
}
+ return ptgs;
}
public void testPower() {
--- /dev/null
+/* ====================================================================
+ 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.hssf.model;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.record.formula.AddPtg;
+import org.apache.poi.hssf.record.formula.AttrPtg;
+import org.apache.poi.hssf.record.formula.BoolPtg;
+import org.apache.poi.hssf.record.formula.FuncPtg;
+import org.apache.poi.hssf.record.formula.FuncVarPtg;
+import org.apache.poi.hssf.record.formula.IntPtg;
+import org.apache.poi.hssf.record.formula.LessEqualPtg;
+import org.apache.poi.hssf.record.formula.LessThanPtg;
+import org.apache.poi.hssf.record.formula.MultiplyPtg;
+import org.apache.poi.hssf.record.formula.NotEqualPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.ReferencePtg;
+import org.apache.poi.hssf.record.formula.StringPtg;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * Tests <tt>FormulaParser</tt> specifically with respect to IF() functions
+ */
+public final class TestFormulaParserIf extends TestCase {
+ private static Ptg[] parseFormula(String formula) {
+ return TestFormulaParser.parseFormula(formula);
+ }
+
+ private static Ptg[] confirmTokenClasses(String formula, Class[] expectedClasses) {
+ return TestFormulaParser.confirmTokenClasses(formula, expectedClasses);
+ }
+
+ private static void confirmAttrData(Ptg[] ptgs, int i, int expectedData) {
+ Ptg ptg = ptgs[i];
+ if (!(ptg instanceof AttrPtg)) {
+ throw new AssertionFailedError("Token[" + i + "] was not AttrPtg as expected");
+ }
+ AttrPtg attrPtg = (AttrPtg) ptg;
+ assertEquals(expectedData, attrPtg.getData());
+ }
+
+ public void testSimpleIf() {
+
+ Class[] expClss;
+
+ expClss = new Class[] {
+ ReferencePtg.class,
+ AttrPtg.class, // tAttrIf
+ IntPtg.class,
+ AttrPtg.class, // tAttrSkip
+ IntPtg.class,
+ AttrPtg.class, // tAttrSkip
+ FuncVarPtg.class,
+ };
+
+ Ptg[] ptgs = confirmTokenClasses("if(A1,1,2)", expClss);
+
+ confirmAttrData(ptgs, 1, 7);
+ confirmAttrData(ptgs, 3, 10);
+ confirmAttrData(ptgs, 5, 3);
+ }
+
+ public void testSimpleIfNoFalseParam() {
+
+ Class[] expClss;
+
+ expClss = new Class[] {
+ ReferencePtg.class,
+ AttrPtg.class, // tAttrIf
+ ReferencePtg.class,
+ AttrPtg.class, // tAttrSkip
+ FuncVarPtg.class,
+ };
+
+ Ptg[] ptgs = confirmTokenClasses("if(A1,B1)", expClss);
+
+ confirmAttrData(ptgs, 1, 9);
+ confirmAttrData(ptgs, 3, 3);
+ }
+
+ public void testIfWithLargeParams() {
+
+ Class[] expClss;
+
+ expClss = new Class[] {
+ ReferencePtg.class,
+ AttrPtg.class, // tAttrIf
+
+ ReferencePtg.class,
+ IntPtg.class,
+ MultiplyPtg.class,
+ ReferencePtg.class,
+ IntPtg.class,
+ AddPtg.class,
+ FuncPtg.class,
+ AttrPtg.class, // tAttrSkip
+
+ ReferencePtg.class,
+ ReferencePtg.class,
+ FuncPtg.class,
+
+ AttrPtg.class, // tAttrSkip
+ FuncVarPtg.class,
+ };
+
+ Ptg[] ptgs = confirmTokenClasses("if(A1,round(B1*100,C1+2),round(B1,C1))", expClss);
+
+ confirmAttrData(ptgs, 1, 25);
+ confirmAttrData(ptgs, 9, 20);
+ confirmAttrData(ptgs, 13, 3);
+ }
+
+ public void testNestedIf() {
+
+ Class[] expClss;
+
+ expClss = new Class[] {
+
+ ReferencePtg.class,
+ AttrPtg.class, // A tAttrIf
+ ReferencePtg.class,
+ AttrPtg.class, // B tAttrIf
+ IntPtg.class,
+ AttrPtg.class, // B tAttrSkip
+ IntPtg.class,
+ AttrPtg.class, // B tAttrSkip
+ FuncVarPtg.class,
+ AttrPtg.class, // A tAttrSkip
+ ReferencePtg.class,
+ AttrPtg.class, // C tAttrIf
+ IntPtg.class,
+ AttrPtg.class, // C tAttrSkip
+ IntPtg.class,
+ AttrPtg.class, // C tAttrSkip
+ FuncVarPtg.class,
+ AttrPtg.class, // A tAttrSkip
+ FuncVarPtg.class,
+ };
+
+ Ptg[] ptgs = confirmTokenClasses("if(A1,if(B1,1,2),if(C1,3,4))", expClss);
+ confirmAttrData(ptgs, 1, 31);
+ confirmAttrData(ptgs, 3, 7);
+ confirmAttrData(ptgs, 5, 10);
+ confirmAttrData(ptgs, 7, 3);
+ confirmAttrData(ptgs, 9, 34);
+ confirmAttrData(ptgs, 11, 7);
+ confirmAttrData(ptgs, 13, 10);
+ confirmAttrData(ptgs, 15, 3);
+ confirmAttrData(ptgs, 17, 3);
+ }
+
+ public void testEmbeddedIf() {
+ Ptg[] ptgs = parseFormula("IF(3>=1,\"*\",IF(4<>1,\"first\",\"second\"))");
+ assertEquals(17, ptgs.length);
+
+ 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("15th Ptg is not the inner IF variable function ptg",FuncVarPtg.class,ptgs[14].getClass());
+ }
+
+
+ public void testSimpleLogical() {
+ Ptg[] ptgs = parseFormula("IF(A1<A2,B1,B2)");
+ assertEquals(9, ptgs.length);
+ assertEquals("3rd Ptg is less than", LessThanPtg.class, ptgs[2].getClass());
+ }
+
+ public void testParenIf() {
+ Ptg[] ptgs = parseFormula("IF((A1+A2)<=3,\"yes\",\"no\")");
+ assertEquals(12, ptgs.length);
+ 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());
+ }
+ public void testYN() {
+ Ptg[] ptgs = parseFormula("IF(TRUE,\"Y\",\"N\")");
+ assertEquals(7, ptgs.length);
+
+ BoolPtg flag = (BoolPtg) ptgs[0];
+ AttrPtg funif = (AttrPtg) ptgs[1];
+ StringPtg y = (StringPtg) ptgs[2];
+ AttrPtg goto1 = (AttrPtg) ptgs[3];
+ StringPtg n = (StringPtg) ptgs[4];
+
+
+ assertEquals(true, flag.getValue());
+ assertEquals("Y", y.getValue());
+ assertEquals("N", n.getValue());
+ assertEquals("IF", funif.toFormulaString((HSSFWorkbook) null));
+ assertTrue("Goto ptg exists", goto1.isGoto());
+ }
+ /**
+ * Make sure the ptgs are generated properly with two functions embedded
+ *
+ */
+ public void testNestedFunctionIf() {
+ Ptg[] ptgs = parseFormula("IF(A1=B1,AVERAGE(A1:B1),AVERAGE(A2:B2))");
+ assertEquals(11, ptgs.length);
+
+ assertTrue("IF Attr set correctly", (ptgs[3] instanceof AttrPtg));
+ AttrPtg ifFunc = (AttrPtg)ptgs[3];
+ assertTrue("It is not an if", ifFunc.isOptimizedIf());
+
+ assertTrue("Average Function set correctly", (ptgs[5] instanceof FuncVarPtg));
+ }
+
+ public void testIfSingleCondition(){
+ Ptg[] ptgs = parseFormula("IF(1=1,10)");
+ assertEquals(7, ptgs.length);
+
+ assertTrue("IF Attr set correctly", (ptgs[3] instanceof AttrPtg));
+ AttrPtg ifFunc = (AttrPtg)ptgs[3];
+ assertTrue("It is not an if", ifFunc.isOptimizedIf());
+
+ assertTrue("Single Value is not an IntPtg", (ptgs[4] instanceof IntPtg));
+ IntPtg intPtg = (IntPtg)ptgs[4];
+ assertEquals("Result", (short)10, intPtg.getValue());
+
+ assertTrue("Ptg is not a Variable Function", (ptgs[6] instanceof FuncVarPtg));
+ FuncVarPtg funcPtg = (FuncVarPtg)ptgs[6];
+ assertEquals("Arguments", 2, funcPtg.getNumberOfOperands());
+ }
+}