FormulaParser changes to support IF function(s)
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353027 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
9087b6e859
commit
9dfd573ce7
@ -2,7 +2,7 @@
|
|||||||
/* ====================================================================
|
/* ====================================================================
|
||||||
* The Apache Software License, Version 1.1
|
* The Apache Software License, Version 1.1
|
||||||
*
|
*
|
||||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
* Copyright (c) 2002, 2003 The Apache Software Foundation. All rights
|
||||||
* reserved.
|
* reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -56,12 +56,34 @@
|
|||||||
|
|
||||||
package org.apache.poi.hssf.model;
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
import org.apache.poi.hssf.record.formula.*;
|
|
||||||
import org.apache.poi.hssf.util.SheetReferences;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.AddPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.Area3DPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.AttrPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.BoolPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.ConcatPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.DividePtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.EqualPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.FuncVarPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.IntPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.MultiplyPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.NumberPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.OperationPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.ParenthesisPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.PowerPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.Ptg;
|
||||||
|
import org.apache.poi.hssf.record.formula.Ref3DPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.ReferencePtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.StringPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.SubtractPtg;
|
||||||
|
import org.apache.poi.hssf.util.SheetReferences;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class parses a formula string into a List of tokens in RPN order.
|
* This class parses a formula string into a List of tokens in RPN order.
|
||||||
@ -90,6 +112,12 @@ public class FormulaParser {
|
|||||||
private int formulaLength;
|
private int formulaLength;
|
||||||
|
|
||||||
private List tokens = new java.util.Stack();
|
private List tokens = new java.util.Stack();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Using an unsynchronized linkedlist to implement a stack since we're not multi-threaded.
|
||||||
|
*/
|
||||||
|
private List functionTokens = new LinkedList();
|
||||||
|
|
||||||
//private Stack tokens = new java.util.Stack();
|
//private Stack tokens = new java.util.Stack();
|
||||||
private List result = new ArrayList();
|
private List result = new ArrayList();
|
||||||
private int numParen;
|
private int numParen;
|
||||||
@ -98,6 +126,7 @@ public class FormulaParser {
|
|||||||
private static char CR = '\n';
|
private static char CR = '\n';
|
||||||
|
|
||||||
private char look; // Lookahead Character
|
private char look; // Lookahead Character
|
||||||
|
private boolean inFunction = false;
|
||||||
|
|
||||||
private Workbook book;
|
private Workbook book;
|
||||||
|
|
||||||
@ -297,25 +326,140 @@ public class FormulaParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a pointer to the last token to the latest function argument list.
|
||||||
|
* @param obj
|
||||||
|
*/
|
||||||
|
private void addArgumentPointer() {
|
||||||
|
if (this.functionTokens.size() > 0) {
|
||||||
|
//no bounds check because this method should not be called unless a token array is setup by function()
|
||||||
|
List arguments = (List)this.functionTokens.get(0);
|
||||||
|
arguments.add(tokens.get(tokens.size()-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void function(String name) {
|
private void function(String name) {
|
||||||
|
//average 2 args per function
|
||||||
|
this.functionTokens.add(0, new ArrayList(2));
|
||||||
|
|
||||||
Match('(');
|
Match('(');
|
||||||
int numArgs = Arguments();
|
int numArgs = Arguments();
|
||||||
Match(')');
|
Match(')');
|
||||||
tokens.add(getFunction(name,(byte)numArgs));
|
|
||||||
|
Ptg functionPtg = getFunction(name,(byte)numArgs);
|
||||||
|
|
||||||
|
tokens.add(functionPtg);
|
||||||
|
|
||||||
|
//remove what we just put in
|
||||||
|
this.functionTokens.remove(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the size of all the ptgs after the provided index (inclusive).
|
||||||
|
* <p>
|
||||||
|
* Initially used to count a goto
|
||||||
|
* @param index
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private int getPtgSize(int index) {
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
Iterator ptgIterator = tokens.listIterator(index);
|
||||||
|
while (ptgIterator.hasNext()) {
|
||||||
|
Ptg ptg = (Ptg)ptgIterator.next();
|
||||||
|
count+=ptg.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getPtgSize(int start, int end) {
|
||||||
|
int count = 0;
|
||||||
|
int index = start;
|
||||||
|
Iterator ptgIterator = tokens.listIterator(index);
|
||||||
|
while (ptgIterator.hasNext() && index <= end) {
|
||||||
|
Ptg ptg = (Ptg)ptgIterator.next();
|
||||||
|
count+=ptg.getSize();
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the variable function ptg for the formula.
|
||||||
|
* <p>
|
||||||
|
* For IF Formulas, additional PTGs are added to the tokens
|
||||||
|
* @param name
|
||||||
|
* @param numArgs
|
||||||
|
* @return Ptg a null is returned if we're in an IF formula, it needs extreme manipulation and is handled in this function
|
||||||
|
*/
|
||||||
private Ptg getFunction(String name,byte numArgs) {
|
private Ptg getFunction(String name,byte numArgs) {
|
||||||
Ptg retval = null;
|
Ptg retval = null;
|
||||||
//retval = new FuncVarPtg(name,numArgs);
|
|
||||||
if (name.equals("IF")) {
|
|
||||||
AttrPtg ptg = new AttrPtg();
|
|
||||||
ptg.setData((short)6); //sums don't care but this is what excel does.
|
|
||||||
ptg.setOptimizedIf(true);
|
|
||||||
retval = ptg;
|
|
||||||
} else {
|
|
||||||
retval = new FuncVarPtg(name,numArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (name.equals("IF")) {
|
||||||
|
retval = new FuncVarPtg(AbstractFunctionPtg.ATTR_NAME, numArgs);
|
||||||
|
|
||||||
|
//simulated pop, no bounds checking because this list better be populated by function()
|
||||||
|
List argumentPointers = (List)this.functionTokens.get(0);
|
||||||
|
|
||||||
|
|
||||||
|
AttrPtg ifPtg = new AttrPtg();
|
||||||
|
ifPtg.setData((short)7); //mirroring excel output
|
||||||
|
ifPtg.setOptimizedIf(true);
|
||||||
|
|
||||||
|
if (argumentPointers.size() != 2 && argumentPointers.size() != 3) {
|
||||||
|
throw new IllegalArgumentException("["+argumentPointers.size()+"] Arguments Found - An IF formula requires 2 or 3 arguments. IF(CONDITION, TRUE_VALUE, FALSE_VALUE [OPTIONAL]");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Biffview of an IF formula record indicates the attr ptg goes after the condition ptgs and are
|
||||||
|
//tracked in the argument pointers
|
||||||
|
//The beginning first argument pointer is the last ptg of the condition
|
||||||
|
int ifIndex = tokens.indexOf(argumentPointers.get(0))+1;
|
||||||
|
tokens.add(ifIndex, ifPtg);
|
||||||
|
|
||||||
|
//we now need a goto ptgAttr to skip to the end of the formula after a true condition
|
||||||
|
//the true condition is should be inserted after the last ptg in the first argument
|
||||||
|
|
||||||
|
int gotoIndex = tokens.indexOf(argumentPointers.get(1))+1;
|
||||||
|
|
||||||
|
AttrPtg goto1Ptg = new AttrPtg();
|
||||||
|
goto1Ptg.setGoto(true);
|
||||||
|
|
||||||
|
|
||||||
|
tokens.add(gotoIndex, goto1Ptg);
|
||||||
|
|
||||||
|
|
||||||
|
if (numArgs > 2) { //only add false jump if there is a false condition
|
||||||
|
|
||||||
|
//second goto to skip past the function ptg
|
||||||
|
AttrPtg goto2Ptg = new AttrPtg();
|
||||||
|
goto2Ptg.setGoto(true);
|
||||||
|
goto2Ptg.setData((short)(retval.getSize()-1));
|
||||||
|
//Page 472 of the Microsoft Excel Developer's kit states that:
|
||||||
|
//The b(or w) field specifies the number byes (or words to skip, minus 1
|
||||||
|
|
||||||
|
tokens.add(goto2Ptg); //this goes after all the arguments are defined
|
||||||
|
}
|
||||||
|
|
||||||
|
//data portion of the if ptg points to the false subexpression (Page 472 of MS Excel Developer's kit)
|
||||||
|
//count the number of bytes after the ifPtg to the False Subexpression
|
||||||
|
//doesn't specify -1 in the documentation
|
||||||
|
ifPtg.setData((short)(getPtgSize(ifIndex+1, gotoIndex)));
|
||||||
|
|
||||||
|
//count all the additional (goto) ptgs but dont count itself
|
||||||
|
int ptgCount = this.getPtgSize(gotoIndex)-goto1Ptg.getSize()+retval.getSize();
|
||||||
|
if (ptgCount > (int)Short.MAX_VALUE) {
|
||||||
|
throw new RuntimeException("Ptg Size exceeds short when being specified for a goto ptg in an if");
|
||||||
|
}
|
||||||
|
|
||||||
|
goto1Ptg.setData((short)(ptgCount-1));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
retval = new FuncVarPtg(name,numArgs);
|
||||||
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,6 +595,8 @@ public class FormulaParser {
|
|||||||
if (look == '*') Multiply();
|
if (look == '*') Multiply();
|
||||||
if (look == '/') Divide();
|
if (look == '/') Divide();
|
||||||
}
|
}
|
||||||
|
addArgumentPointer();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,56 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
* The Apache Software License, Version 1.1
|
||||||
|
*
|
||||||
|
* Copyright (c) 2002, 2003 The Apache Software Foundation. All rights
|
||||||
|
* reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution,
|
||||||
|
* if any, must include the following acknowledgment:
|
||||||
|
* "This product includes software developed by the
|
||||||
|
* Apache Software Foundation (http://www.apache.org/)."
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself,
|
||||||
|
* if and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||||
|
* "Apache POI" must not be used to endorse or promote products
|
||||||
|
* derived from this software without prior written permission. For
|
||||||
|
* written permission, please contact apache@apache.org.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called "Apache",
|
||||||
|
* "Apache POI", nor may "Apache" appear in their name, without
|
||||||
|
* prior written permission of the Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||||
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
* ====================================================================
|
||||||
|
*
|
||||||
|
* This software consists of voluntary contributions made by many
|
||||||
|
* individuals on behalf of the Apache Software Foundation. For more
|
||||||
|
* information on the Apache Software Foundation, please see
|
||||||
|
* <http://www.apache.org/>.
|
||||||
|
*/
|
||||||
package org.apache.poi.hssf.record.formula;
|
package org.apache.poi.hssf.record.formula;
|
||||||
|
|
||||||
import org.apache.poi.util.BinaryTree;
|
import org.apache.poi.util.BinaryTree;
|
||||||
@ -13,7 +66,9 @@ import java.util.Stack;
|
|||||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractFunctionPtg extends OperationPtg {
|
public abstract class AbstractFunctionPtg extends OperationPtg {
|
||||||
|
//constant used allow a ptgAttr to be mapped properly for its functionPtg
|
||||||
|
public static final String ATTR_NAME = "specialflag";
|
||||||
|
|
||||||
private final static int SIZE = 4;
|
private final static int SIZE = 4;
|
||||||
|
|
||||||
private static BinaryTree map = produceHash();
|
private static BinaryTree map = produceHash();
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/* ====================================================================
|
/* ====================================================================
|
||||||
* The Apache Software License, Version 1.1
|
* The Apache Software License, Version 1.1
|
||||||
*
|
*
|
||||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
* Copyright (c) 2002, 2003 The Apache Software Foundation. All rights
|
||||||
* reserved.
|
* reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -144,6 +144,14 @@ public class AttrPtg
|
|||||||
field_1_options=optiIf.setByteBoolean(field_1_options,bif);
|
field_1_options=optiIf.setByteBoolean(field_1_options,bif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags this ptg as a goto/jump
|
||||||
|
* @param isGoto
|
||||||
|
*/
|
||||||
|
public void setGoto(boolean isGoto) {
|
||||||
|
field_1_options=optGoto.setByteBoolean(field_1_options, isGoto);
|
||||||
|
}
|
||||||
|
|
||||||
// lets hope no one uses this anymore
|
// lets hope no one uses this anymore
|
||||||
public boolean isBaxcel()
|
public boolean isBaxcel()
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,56 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
* The Apache Software License, Version 1.1
|
||||||
|
*
|
||||||
|
* Copyright (c) 2002, 2003 The Apache Software Foundation. All rights
|
||||||
|
* reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution,
|
||||||
|
* if any, must include the following acknowledgment:
|
||||||
|
* "This product includes software developed by the
|
||||||
|
* Apache Software Foundation (http://www.apache.org/)."
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself,
|
||||||
|
* if and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||||
|
* "Apache POI" must not be used to endorse or promote products
|
||||||
|
* derived from this software without prior written permission. For
|
||||||
|
* written permission, please contact apache@apache.org.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called "Apache",
|
||||||
|
* "Apache POI", nor may "Apache" appear in their name, without
|
||||||
|
* prior written permission of the Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||||
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
* ====================================================================
|
||||||
|
*
|
||||||
|
* This software consists of voluntary contributions made by many
|
||||||
|
* individuals on behalf of the Apache Software Foundation. For more
|
||||||
|
* information on the Apache Software Foundation, please see
|
||||||
|
* <http://www.apache.org/>.
|
||||||
|
*/
|
||||||
package org.apache.poi.hssf.model;
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
@ -80,20 +133,95 @@ public class TestFormulaParser extends TestCase {
|
|||||||
FormulaParser fp = new FormulaParser(yn, null);
|
FormulaParser fp = new FormulaParser(yn, null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
Ptg[] asts = fp.getRPNPtg();
|
Ptg[] asts = fp.getRPNPtg();
|
||||||
assertEquals(4, asts.length);
|
assertEquals(7, asts.length);
|
||||||
|
|
||||||
BoolPtg flag = (BoolPtg) asts[0];
|
BoolPtg flag = (BoolPtg) asts[0];
|
||||||
StringPtg y = (StringPtg) asts[1];
|
AttrPtg funif = (AttrPtg) asts[1];
|
||||||
StringPtg n = (StringPtg) asts[2];
|
StringPtg y = (StringPtg) asts[2];
|
||||||
AttrPtg funif = (AttrPtg) asts[3];
|
AttrPtg goto1 = (AttrPtg) asts[3];
|
||||||
|
StringPtg n = (StringPtg) asts[4];
|
||||||
|
|
||||||
|
|
||||||
assertEquals(true, flag.getValue());
|
assertEquals(true, flag.getValue());
|
||||||
assertEquals("Y", y.getValue());
|
assertEquals("Y", y.getValue());
|
||||||
assertEquals("N", n.getValue());
|
assertEquals("N", n.getValue());
|
||||||
assertEquals("IF", funif.toFormulaString(new SheetReferences()));
|
assertEquals("IF", funif.toFormulaString(new SheetReferences()));
|
||||||
|
assertTrue("Goto ptg exists", goto1.isGoto());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSimpleIf() throws Exception {
|
||||||
|
final String simpleif = "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];
|
||||||
|
IntPtg op2 = (IntPtg) asts[1];
|
||||||
|
EqualPtg eq = (EqualPtg) asts[2];
|
||||||
|
AttrPtg ifPtg = (AttrPtg) asts[3];
|
||||||
|
IntPtg res1 = (IntPtg) asts[4];
|
||||||
|
|
||||||
|
AttrPtg ptgGoto= (AttrPtg) asts[5];
|
||||||
|
assertEquals("Goto 1 Length", (short)10, ptgGoto.getData());
|
||||||
|
|
||||||
|
IntPtg res2 = (IntPtg) asts[6];
|
||||||
|
AttrPtg ptgGoto2 = (AttrPtg) asts[7];
|
||||||
|
assertEquals("Goto 2 Length", (short)3, ptgGoto2.getData());
|
||||||
|
|
||||||
|
assertEquals("If FALSE offset", (short)7, ifPtg.getData());
|
||||||
|
|
||||||
|
FuncVarPtg funcPtg = (FuncVarPtg)asts[8];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure the ptgs are generated properly with two functions embedded
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void testNestedFunctionIf() {
|
||||||
|
String function = "IF(A1=B1,AVERAGE(A1:B1),AVERAGE(A2:B2))";
|
||||||
|
|
||||||
|
FormulaParser fp = new FormulaParser(function, null);
|
||||||
|
fp.parse();
|
||||||
|
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("Average Function set correctly", (asts[5] instanceof FuncVarPtg));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIfSingleCondition(){
|
||||||
|
String function = "IF(1=1,10)";
|
||||||
|
|
||||||
|
FormulaParser fp = new FormulaParser(function, null);
|
||||||
|
fp.parse();
|
||||||
|
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("Single Value is not an IntPtg", (asts[4] instanceof IntPtg));
|
||||||
|
IntPtg intPtg = (IntPtg)asts[4];
|
||||||
|
assertEquals("Result", (short)10, intPtg.getValue());
|
||||||
|
|
||||||
|
assertTrue("Ptg is not a Variable Function", (asts[6] instanceof FuncVarPtg));
|
||||||
|
FuncVarPtg funcPtg = (FuncVarPtg)asts[6];
|
||||||
|
assertEquals("Arguments", 2, funcPtg.getNumberOfOperands());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String [] args) {
|
public static void main(String [] args) {
|
||||||
System.out.println("Testing org.apache.poi.hssf.record.formula.FormulaParser");
|
System.out.println("Testing org.apache.poi.hssf.record.formula.FormulaParser");
|
||||||
junit.textui.TestRunner.run(TestFormulaParser.class);
|
junit.textui.TestRunner.run(TestFormulaParser.class);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/* ====================================================================
|
/* ====================================================================
|
||||||
* The Apache Software License, Version 1.1
|
* The Apache Software License, Version 1.1
|
||||||
*
|
*
|
||||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
* Copyright (c) 2002, 2003 The Apache Software Foundation. All rights
|
||||||
* reserved.
|
* reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -894,7 +894,7 @@ extends TestCase {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
public void testIfFormulas()
|
public void testIfFormulas()
|
||||||
throws java.io.IOException
|
throws java.io.IOException
|
||||||
{
|
{
|
||||||
@ -935,9 +935,56 @@ extends TestCase {
|
|||||||
assertTrue("expected: IF(A3=A1,\"A1\",\"A2\") got "+c.getCellFormula(), ("IF(A3=A1,\"A1\",\"A2\")").equals(c.getCellFormula()));
|
assertTrue("expected: IF(A3=A1,\"A1\",\"A2\") got "+c.getCellFormula(), ("IF(A3=A1,\"A1\",\"A2\")").equals(c.getCellFormula()));
|
||||||
//c = r.getCell((short)1);
|
//c = r.getCell((short)1);
|
||||||
//assertTrue("expected: A!A1+A!B1 got: "+c.getCellFormula(), ("A!A1+A!B1").equals(c.getCellFormula()));
|
//assertTrue("expected: A!A1+A!B1 got: "+c.getCellFormula(), ("A!A1+A!B1").equals(c.getCellFormula()));
|
||||||
in.close();
|
in.close();
|
||||||
|
|
||||||
|
File simpleIf = File.createTempFile("testSimpleIfFormulaWrite",".xls");
|
||||||
|
out = new FileOutputStream(simpleIf);
|
||||||
|
wb = new HSSFWorkbook();
|
||||||
|
s = wb.createSheet("Sheet1");
|
||||||
|
r = null;
|
||||||
|
c = null;
|
||||||
|
r = s.createRow((short)0);
|
||||||
|
c=r.createCell((short)0); c.setCellFormula("IF(1=1,0,1)");
|
||||||
|
|
||||||
|
wb.write(out);
|
||||||
|
out.close();
|
||||||
|
assertTrue("file exists", simpleIf.exists());
|
||||||
|
|
||||||
|
assertTrue("length of simpleIf file is zero", (simpleIf.length()>0));
|
||||||
|
|
||||||
|
File nestedIf = File.createTempFile("testNestedIfFormula",".xls");
|
||||||
|
out = new FileOutputStream(nestedIf);
|
||||||
|
wb = new HSSFWorkbook();
|
||||||
|
s = wb.createSheet("Sheet1");
|
||||||
|
r = null;
|
||||||
|
c = null;
|
||||||
|
r = s.createRow((short)0);
|
||||||
|
c=r.createCell((short)0);
|
||||||
|
c.setCellValue(1);
|
||||||
|
|
||||||
|
c=r.createCell((short)1);
|
||||||
|
c.setCellValue(3);
|
||||||
|
|
||||||
|
|
||||||
|
HSSFCell formulaCell=r.createCell((short)3);
|
||||||
|
|
||||||
|
r = s.createRow((short)1);
|
||||||
|
c=r.createCell((short)0);
|
||||||
|
c.setCellValue(3);
|
||||||
|
|
||||||
|
c=r.createCell((short)1);
|
||||||
|
c.setCellValue(7);
|
||||||
|
|
||||||
|
formulaCell.setCellFormula("IF(A1=B1,AVERAGE(A1:B1),AVERAGE(A2:B2))");
|
||||||
|
|
||||||
|
|
||||||
|
wb.write(out);
|
||||||
|
out.close();
|
||||||
|
assertTrue("file exists", nestedIf.exists());
|
||||||
|
|
||||||
|
assertTrue("length of nestedIf file is zero", (nestedIf.length()>0));
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
public static void main(String [] args) {
|
public static void main(String [] args) {
|
||||||
System.out
|
System.out
|
||||||
|
Loading…
Reference in New Issue
Block a user