From 37175f690747f89c4dac703c4b2800a244ff0244 Mon Sep 17 00:00:00 2001 From: "Andrew C. Oliver" Date: Sat, 27 Apr 2002 14:07:53 +0000 Subject: [PATCH] Avik's latest formula patches PR: Obtained from: Submitted by: Reviewed by: git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@352498 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/record/FormulaRecord.java | 5 +- .../poi/hssf/record/formula/AddPtg.java | 13 + .../poi/hssf/record/formula/AttrPtg.java | 7 + .../poi/hssf/record/formula/DividePtg.java | 18 + .../hssf/record/formula/FormulaParser.java | 317 +++++++++--------- .../poi/hssf/record/formula/MultiplyPtg.java | 11 + .../poi/hssf/record/formula/OperationPtg.java | 4 + .../hssf/record/formula/ParenthesisPtg.java | 27 +- .../poi/hssf/record/formula/PowerPtg.java | 17 + .../apache/poi/hssf/record/formula/Ptg.java | 48 +++ .../poi/hssf/record/formula/SubtractPtg.java | 20 +- .../formula/ValueVariableFunctionPtg.java | 12 + .../apache/poi/hssf/usermodel/HSSFCell.java | 29 ++ 13 files changed, 361 insertions(+), 167 deletions(-) diff --git a/src/java/org/apache/poi/hssf/record/FormulaRecord.java b/src/java/org/apache/poi/hssf/record/FormulaRecord.java index 1ed16b02d..ea1b387c6 100644 --- a/src/java/org/apache/poi/hssf/record/FormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/FormulaRecord.java @@ -78,7 +78,7 @@ public class FormulaRecord implements CellValueRecordInterface, Comparable { - public static final boolean EXPERIMENTAL_FORMULA_SUPPORT_ENABLED=false; + public static final boolean EXPERIMENTAL_FORMULA_SUPPORT_ENABLED=true; public static final short sid = 0x06; // docs say 406...because of a bug Microsoft support site article #Q184647) @@ -359,11 +359,10 @@ public class FormulaRecord LittleEndian.putShort(data, 18 + offset, getOptions()); LittleEndian.putInt(data, 20 + offset, field_6_zero); LittleEndian.putShort(data, 24 + offset, getExpressionLength()); + serializePtgs(data, 26+offset); } else { System.arraycopy(all_data,0,data,offset,all_data.length); } - - // serializePtgs(data, 26+offset); return getRecordSize(); } diff --git a/src/java/org/apache/poi/hssf/record/formula/AddPtg.java b/src/java/org/apache/poi/hssf/record/formula/AddPtg.java index 22af5b3b4..81ff876c6 100644 --- a/src/java/org/apache/poi/hssf/record/formula/AddPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/AddPtg.java @@ -141,6 +141,7 @@ public class AddPtg return buffer.toString(); } + public int getPrecedence() { return 5; } @@ -148,6 +149,18 @@ public class AddPtg public int getStringLength() { return 1; } + + + public String toFormulaString(String[] operands) { + StringBuffer buffer = new StringBuffer(); + + buffer.append(operands[ 0 ]); + buffer.append("+"); + buffer.append(operands[ 1 ]); + return buffer.toString(); + } + + public void manipulate(List source, List results, int pos) { standardBinaryManipulation(source,results,pos); diff --git a/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java b/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java index a92712e9c..fba66eda1 100644 --- a/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java @@ -210,5 +210,12 @@ public class AttrPtg public void manipulate(List source, List results, int pos) { } + public String toFormulaString(String[] operands) { + return "SUM(" + operands[ 0 ] + ")"; + } + + public int getPrecedence() { + return 1; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/DividePtg.java b/src/java/org/apache/poi/hssf/record/formula/DividePtg.java index a3d76fe94..6ee743fb5 100644 --- a/src/java/org/apache/poi/hssf/record/formula/DividePtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/DividePtg.java @@ -119,7 +119,25 @@ public class DividePtg buffer.append(operands[ 1 ].toFormulaString()); return buffer.toString(); } + + public int getPrecedence() { + return 4; + } + public int getStringLength() { + return 1; + } + + public String toFormulaString(String[] operands) { + StringBuffer buffer = new StringBuffer(); + + buffer.append(operands[ 0 ]); + buffer.append("/"); + buffer.append(operands[ 1 ]); + return buffer.toString(); + } + + public void manipulate(List source, List results, int pos) { } diff --git a/src/java/org/apache/poi/hssf/record/formula/FormulaParser.java b/src/java/org/apache/poi/hssf/record/formula/FormulaParser.java index acbfea014..8f6da9da8 100644 --- a/src/java/org/apache/poi/hssf/record/formula/FormulaParser.java +++ b/src/java/org/apache/poi/hssf/record/formula/FormulaParser.java @@ -60,56 +60,66 @@ import java.util.List; import java.util.ArrayList; import java.util.Stack; +import org.apache.poi.hssf.usermodel.*; +import java.io.FileOutputStream; + /** - * EXPERIMENTAL code to parse formulas back and forth between RPN and not + * EXPERIMENTAL * - * @author Avik Sengupta + * @author Avik Sengupta + * + * This class parses a formula string into a List of tokens in RPN order + * Inspired by + * Lets Build a Compiler, by Jack Crenshaw + * BNF for the formula expression is : + * ::= [ ]* + * ::= [ ::= | () | */ public class FormulaParser { private String formulaString; private int pointer=0; - private Stack operationsList = new java.util.Stack(); - private Stack operandsList = new java.util.Stack(); + private List tokens = new java.util.Stack(); + //private Stack tokens = new java.util.Stack(); private List result = new ArrayList(); private int numParen; - //{--------------------------------------------------------------} - //{ Constant Declarations } - private static char TAB = '\t'; private static char CR = '\n'; - //{--------------------------------------------------------------} - //{ Variable Declarations } + private char Look; // Lookahead Character - private char Look; //{ Lookahead Character } + /** create the parser with the string that is to be parsed + * later call the parse() method to return ptg list in rpn order + * then call the getRPNPtg() to retrive the parse results + * This class is recommended only for single threaded use + * The parse and getPRNPtg are internally synchronized for safety, thus + * while it is safe to use in a multithreaded environment, you will get long lock waits. + */ public FormulaParser(String formula){ formulaString = formula; pointer=0; } - //{--------------------------------------------------------------} - //{ Read New Character From Input Stream } - + + /** Read New Character From Input Stream */ private void GetChar() { Look=formulaString.charAt(pointer++); - System.out.println("Got char: "+Look); + //System.out.println("Got char: "+Look); } - //{--------------------------------------------------------------} - //{ Report an Error } - + + /** Report an Error */ private void Error(String s) { System.out.println("Error: "+s); } - //{--------------------------------------------------------------} - //{ Report Error and Halt } - + + /** Report Error and Halt */ private void Abort(String s) { Error(s); //System.exit(1); //throw exception?? @@ -117,61 +127,50 @@ public class FormulaParser { } - //{--------------------------------------------------------------} - //{ Report What Was Expected } - + + /** Report What Was Expected */ private void Expected(String s) { Abort(s + " Expected"); } - //{--------------------------------------------------------------} - //{ Recognize an Alpha Character } - + + /** Recognize an Alpha Character */ private boolean IsAlpha(char c) { return Character.isLetter(c); - //return UpCase(c) in ['A'..'Z']; } - //{--------------------------------------------------------------} - //{ Recognize a Decimal Digit } - + + /** Recognize a Decimal Digit */ private boolean IsDigit(char c) { - System.out.println("Checking digit for"+c); + //System.out.println("Checking digit for"+c); return Character.isDigit(c); - - //return ("0123456789".indexOf( (int) c) != 0)//c in ['0'..'9']; } - //{--------------------------------------------------------------} - //{ Recognize an Alphanumeric } - + + /** Recognize an Alphanumeric */ private boolean IsAlNum(char c) { return (IsAlpha(c) || IsDigit(c)); } - //{--------------------------------------------------------------} - //{ Recognize an Addop } - + + /** Recognize an Addop */ private boolean IsAddop( char c) { return (c =='+' || c =='-'); } - - //{--------------------------------------------------------------} - //{ Recognize White Space } - + + /** Recognize White Space */ private boolean IsWhite( char c) { return (c ==' ' || c== TAB); } - //{--------------------------------------------------------------} - //{ Skip Over Leading White Space } - + + /** Skip Over Leading White Space */ private void SkipWhite() { while (IsWhite(Look)) { GetChar(); @@ -179,9 +178,8 @@ public class FormulaParser { } - //{--------------------------------------------------------------} - //{ Match a Specific Input Character } - + + /** Match a Specific Input Character */ private void Match(char x) { if (Look != x) { Expected("" + x + ""); @@ -192,9 +190,7 @@ public class FormulaParser { } - //{--------------------------------------------------------------} - //{ Get an Identifier } - + /** Get an Identifier */ private String GetName() { String Token; Token = ""; @@ -211,9 +207,7 @@ public class FormulaParser { } - //{--------------------------------------------------------------} - //{ Get a Number } - + /** Get a Number */ private String GetNum() { String Value =""; if (!IsDigit(Look)) Expected("Integer"); @@ -224,139 +218,120 @@ public class FormulaParser { SkipWhite(); return Value; } - - - //{--------------------------------------------------------------} - //{ Output a String with Tab } - + + /** Output a String with Tab */ private void Emit(String s){ System.out.print(TAB+s); } - - - //{--------------------------------------------------------------} - //{ Output a String with Tab and CRLF } - + + /** Output a String with Tab and CRLF */ private void EmitLn(String s) { Emit(s); System.out.println();; } - - //{---------------------------------------------------------------} - //{ Parse and Translate a Identifier } - + /** Parse and Translate a Identifier */ private void Ident() { String Name; Name = GetName(); if (Look == '('){ + //This is a function Match('('); - //Expression() -- add this! + int numArgs = Arguments(); Match(')'); //this is the end of the function - //EmitLn("BSR " + Name); + tokens.add(new DummyFunctionPtg(Name,numArgs)); } else { - //EmitLn("MOVE " + Name + "(PC),D0b"); //this can be either a cell ref or a named range !! boolean cellRef = true ; //we should probably do it with reg exp?? if (cellRef) { - operationsList.add(new ValueReferencePtg()); //TODO we need to pass in Name somewhere + tokens.add(new ValueReferencePtg()); //TODO we need to pass in Name somewhere?? }else { //handle after named range is integrated!! } } } + + /** get arguments to a function */ + private int Arguments() { + int numArgs = 0; + if (Look != ')') { + numArgs++; + Expression(); + } + while (Look == ',') { + Match(','); + Expression(); + numArgs++; + } + return numArgs; + } - - //{---------------------------------------------------------------} - //{ Parse and Translate a Math Factor } - - //procedure Expression; Forward; - + /** Parse and Translate a Math Factor */ private void Factor() { if (Look == '(' ) { Match('('); - operationsList.add(new ParenthesisPtg()); Expression(); Match(')'); - operationsList.add(new ParenthesisPtg()); + tokens.add(new ParenthesisPtg()); return; } else if (IsAlpha(Look)){ Ident(); }else{ - //EmitLn("MOVE #" + GetNum() + ",D0"); + IntPtg p = new IntPtg(); p.setValue(Short.parseShort(GetNum())); - operandsList.add(p); + tokens.add(p); } } - //{--------------------------------------------------------------} - //{ Recognize and Translate a Multiply } - + /** Recognize and Translate a Multiply */ private void Multiply(){ Match('*'); Factor(); - operationsList.add(new MultiplyPtg()); - //EmitLn("MULS (SP)+,D0"); + tokens.add(new MultiplyPtg()); + } - //{-------------------------------------------------------------} - //{ Recognize and Translate a Divide } - + /** Recognize and Translate a Divide */ private void Divide() { Match('/'); Factor(); - operationsList.add(new DividePtg()); - //EmitLn("MOVE (SP)+,D1"); - //EmitLn("EXS.L D0"); - //EmitLn("DIVS D1,D0"); + tokens.add(new DividePtg()); + } - //{---------------------------------------------------------------} - //{ Parse and Translate a Math Term } - + /** Parse and Translate a Math Term */ private void Term(){ Factor(); while (Look == '*' || Look == '/' ) { - //EmitLn("MOVE D0,-(SP)"); ///TODO do we need to do anything here?? if (Look == '*') Multiply(); if (Look == '/') Divide(); } } - - //{--------------------------------------------------------------} - //{ Recognize and Translate an Add } - + /** Recognize and Translate an Add */ private void Add() { Match('+'); Term(); - //EmitLn("ADD (SP)+,D0"); - operationsList.add(new AddPtg()); + tokens.add(new AddPtg()); } - //{-------------------------------------------------------------} - //{ Recognize and Translate a Subtract } - + /** Recognize and Translate a Subtract */ private void Subtract() { Match('-'); Term(); - operationsList.add(new SubtractPtg()); - //EmitLn("SUB (SP)+,D0"); - //EmitLn("NEG D0"); + tokens.add(new SubtractPtg()); } - //{---------------------------------------------------------------} - //{ Parse and Translate an Expression } - + /** Parse and Translate an Expression */ private void Expression() { if (IsAddop(Look)) { EmitLn("CLR D0"); //unaryAdd ptg??? @@ -364,9 +339,10 @@ public class FormulaParser { Term(); } while (IsAddop(Look)) { - EmitLn("MOVE D0,-(SP)"); if ( Look == '+' ) Add(); if (Look == '-') Subtract(); + // if (Look == '*') Multiply(); + // if (Look == '/') Divide(); } } @@ -380,71 +356,104 @@ begin Name := GetName; Match('='); Expression; - EmitLn('LEA ' + Name + '(PC),A0'); - EmitLn('MOVE D0,(A0)') + end; **/ - //{--------------------------------------------------------------} - //{ Initialize } + + /** Initialize */ private void Init() { GetChar(); SkipWhite(); } + /** API call to execute the parsing of the formula + * + */ public void parse() { - Init(); - Expression(); - //now tokenisation is done .. convert to RPN!! - tokenToRPN(); - } - - private void tokenToRPN() { - OperationPtg op; - Ptg operand; - int numOper = 0; - int numOnStack = 0; - result.add(operandsList.pop()); numOnStack++; - - while (!operationsList.isEmpty()) { - op = (OperationPtg) operationsList.pop(); - if (op instanceof ParenthesisPtg) { - // do something smart - } - - - for (numOper = op.getNumberOfOperands();numOper>0;numOper--) { - if (numOnStack==0) { - result.add(operandsList.pop());//numOnStack++; - } else { - numOnStack--; - } - } - result.add(op); - numOnStack++; + synchronized (tokens) { + Init(); + Expression(); } } + /** API call to retrive the array of Ptgs created as + * a result of the parsing + */ + public Ptg[] getRPNPtg() { + synchronized (tokens) { + if (tokens == null) throw new IllegalStateException("Please parse a string before trying to access the parse result"); + Ptg[] retval = new Ptg[tokens.size()]; + return (Ptg[]) tokens.toArray(retval); + } + } + + /** Static method to convert an array of Ptgs in RPN order + * to a human readable string format in infix mode + * TODO - extra brackets might appear, but string will be semantically correct. + */ + public static String toFormulaString(Ptg[] ptgs) { + java.util.Stack stack = new java.util.Stack(); + int numPtgs = ptgs.length; + OperationPtg o; + int numOperands; + String[] operands; + for (int i=0;i CR then Expected('NewLine'); } - //{--------------------------------------------------------------} } \ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java b/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java index e4a170379..bd3e41223 100644 --- a/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java @@ -132,6 +132,16 @@ public class MultiplyPtg return buffer.toString(); } + public String toFormulaString(String[] operands) { + StringBuffer buffer = new StringBuffer(); + + buffer.append(operands[ 0 ]); + buffer.append("*"); + buffer.append(operands[ 1 ]); + return buffer.toString(); + } + + public void manipulate(List source, List results, int pos) { standardBinaryManipulation(source, results, pos); } @@ -155,4 +165,5 @@ public class MultiplyPtg } + } diff --git a/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java b/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java index 6f56e2a1c..0cb1ed0bd 100644 --- a/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java @@ -74,6 +74,10 @@ public abstract class OperationPtg extends Ptg public final static int TYPE_FUNCTION = 2; public abstract int getType(); + + public abstract String toFormulaString(String[] operands); + + public abstract int getPrecedence(); public abstract int getNumberOfOperands(); diff --git a/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java b/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java index afd6289f4..e6cdc7512 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java @@ -58,9 +58,9 @@ package org.apache.poi.hssf.record.formula; import java.util.List; /** - * Dummy class, we want it only for for the parsing process - * does not actually get into the file -- note by andy...there is a parenthesis PTG - * that can be written and is sometimes! + * While formula tokens are stored in RPN order and thus do not need parenthesis for + * precedence reasons, Parenthesis tokens ARE written to ensure that user entered + * parenthesis are displayed as-is on reading back * * Avik Sengupta * Andrew C. Oliver (acoliver at apache dot org) @@ -69,17 +69,18 @@ public class ParenthesisPtg extends OperationPtg { - + private final static int SIZE = 1; + public final static byte sid = 0x15; public void writeBytes(byte [] array, int offset) { - //do nothing + array[ offset + 0 ] = sid; } public int getSize() { - return 0; + return SIZE; } public int getType() @@ -89,21 +90,29 @@ public class ParenthesisPtg public int getNumberOfOperands() { - return 0; + return 1; } public String toFormulaString() { - return "("; + return "()"; } public String toFormulaString(Ptg [] operands) { - return "("; + return ""; } public void manipulate(List source, List results, int pos) { } + public String toFormulaString(String[] operands) { + return "("+operands[0]+")"; + } + + public int getPrecedence() { + return 2; + } + } diff --git a/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java b/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java index b3680eb09..d732c8ed2 100644 --- a/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java @@ -109,6 +109,10 @@ public class PowerPtg { return "^"; } + + public int getPrecedence() { + return 3; + } public String toFormulaString(Ptg [] operands) { @@ -119,8 +123,21 @@ public class PowerPtg buffer.append(operands[ 0 ].toFormulaString()); return buffer.toString(); } + + + public String toFormulaString(String[] operands) { + StringBuffer buffer = new StringBuffer(); + + buffer.append(operands[ 1 ]); + buffer.append("^"); + buffer.append(operands[ 0 ]); + return buffer.toString(); + } + + public void manipulate(List source, List results, int pos) { } + } diff --git a/src/java/org/apache/poi/hssf/record/formula/Ptg.java b/src/java/org/apache/poi/hssf/record/formula/Ptg.java index 44eef7ce1..9850341e2 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Ptg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Ptg.java @@ -77,6 +77,54 @@ public abstract class Ptg { } + /** convert infix order ptg list to rpn order ptg list + * @return List ptgs in RPN order + * @param infixPtgs List of ptgs in infix order + */ + public static List ptgsToRpn(List infixPtgs) { + java.util.Stack operands = new java.util.Stack(); + java.util.List retval = new java.util.Stack(); + + java.util.ListIterator i = infixPtgs.listIterator(); + Object p; + OperationPtg o ; + boolean weHaveABracket = false; + while (i.hasNext()) { + p=i.next(); + if (p instanceof OperationPtg) { + if (p instanceof ParenthesisPtg) { + if (!weHaveABracket) { + operands.push(p); + weHaveABracket = true; + } else { + o = (OperationPtg) operands.pop(); + while (!(o instanceof ParenthesisPtg)) { + retval.add(o); + } + weHaveABracket = false; + } + } else { + + while (!operands.isEmpty() && ((OperationPtg) operands.peek()).getPrecedence() >= ((OperationPtg) p).getPrecedence() ) { //TODO handle ^ since it is right associative + retval.add(operands.pop()); + } + operands.push(p); + } + } else { + retval.add(p); + } + } + while (!operands.isEmpty()) { + if (operands.peek() instanceof ParenthesisPtg ){ + //throw some error + } else { + retval.add(operands.pop()); + } + } + return retval; + } + + /* diff --git a/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java b/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java index d550df54d..f2e7f5198 100644 --- a/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java @@ -119,9 +119,27 @@ public class SubtractPtg buffer.append(operands[ 1 ].toFormulaString()); return buffer.toString(); } + + public int getPrecedence() { + return 5; + } + public int getStringLength() { + return 1; + } + + public String toFormulaString(String[] operands) { + StringBuffer buffer = new StringBuffer(); + + buffer.append(operands[ 0 ]); + buffer.append("-"); + buffer.append(operands[ 1 ]); + return buffer.toString(); + } + + public void manipulate(List source, List results, int pos) { } - + } diff --git a/src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java b/src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java index df3972803..fae7990d1 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java @@ -128,8 +128,20 @@ public class ValueVariableFunctionPtg { return toFormulaString(); } + + public String toFormulaString(String[] operands) { + return toFormulaString(); + } + + public void manipulate(List source, List results, int pos) { } + public int getPrecedence() { + return 1; + } + + + } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index 6789d01d7..c2bb655a2 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -70,6 +70,9 @@ import org.apache.poi.hssf.record.NumberRecord; import org.apache.poi.hssf.record.BlankRecord; import org.apache.poi.hssf.record.BoolErrRecord; import org.apache.poi.hssf.record.ExtendedFormatRecord; +import org.apache.poi.hssf.record.formula.Ptg; + +import org.apache.poi.hssf.record.formula.FormulaParser; import java.util.Date; import java.util.Calendar; @@ -684,6 +687,32 @@ public class HSSFCell } } + public void setCellFormula(String formula) { + if (formula==null) { + setCellType(CELL_TYPE_BLANK,false); + } else { + + setCellType(CELL_TYPE_FORMULA,false); + FormulaRecord rec = (FormulaRecord) record; + rec.setOptions(( short ) 2); + rec.setValue(0); + rec.setXFIndex(( short ) 0x0f); + FormulaParser fp = new FormulaParser(formula+";"); + fp.parse(); + Ptg[] ptg = fp.getRPNPtg(); + int size = 0; + System.out.println("got Ptgs " + ptg.length); + for (int k = 0; k < ptg.length; k++) { + size += ptg[ k ].getSize(); + rec.pushExpressionToken(ptg[ k ]); + } + rec.setExpressionLength(( short ) size); + //return rec; + + } + } + + /** * get the value of the cell as a number. For strings we throw an exception. * For blank cells we return a 0.