diff --git a/src/java/org/apache/poi/hssf/record/FormulaRecord.java b/src/java/org/apache/poi/hssf/record/FormulaRecord.java index 4c027b6e28..1ed16b02d8 100644 --- a/src/java/org/apache/poi/hssf/record/FormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/FormulaRecord.java @@ -157,7 +157,7 @@ public class FormulaRecord int offset) { Stack stack = new Stack(); - int pos = 22 + offset; + /*int pos = 22 + offset; while (pos < size) { @@ -165,7 +165,7 @@ public class FormulaRecord pos += ptg.getSize(); stack.push(ptg); - } + }*/ return stack; } 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 4ce150262e..a47cf6956e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/AddPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/AddPtg.java @@ -71,6 +71,8 @@ public class AddPtg { public final static int SIZE = 1; public final static byte sid = 0x03; + + private final static String ADD = "+"; /** Creates new AddPtg */ @@ -83,6 +85,10 @@ public class AddPtg // doesn't need anything } + + protected AddPtg(String formula, int offset) { + + } public void writeBytes(byte [] array, int offset) { @@ -108,6 +114,21 @@ public class AddPtg { return "+"; } + + + public static boolean isNextStringToken(String formula, int pos) { + boolean retval = false; + while (pos < formula.length() && Character.isWhitespace(formula.charAt(pos))) { + pos++; + } + + if (pos < formula.length()) { + if (formula.charAt(pos) == ADD.toCharArray()[0]) { + retval = true; + } + } + return retval; + } public String toFormulaString(Ptg [] operands) { @@ -118,4 +139,12 @@ public class AddPtg buffer.append(operands[ 1 ].toFormulaString()); return buffer.toString(); } + + public int getPrecedence() { + return 5; + } + + public int getStringLength() { + return 1; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/IntPtg.java b/src/java/org/apache/poi/hssf/record/formula/IntPtg.java index 94e8557748..261d1b2d4e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/IntPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/IntPtg.java @@ -75,6 +75,8 @@ public class IntPtg public final static byte sid = 0x1e; private short field_1_value; + private String val; + private int strlen = 0; /** Creates new IntPtg */ public IntPtg() @@ -85,6 +87,14 @@ public class IntPtg { setValue(LittleEndian.getShort(data, offset + 1)); } + + protected IntPtg(String formula, int offset) { + val = parseString(formula, offset); + if (val == null) throw new RuntimeException("WHOOAA there...thats got no int!"); + strlen=val.length(); + field_1_value = Short.parseShort(val); + } + public void setValue(short value) { @@ -111,4 +121,45 @@ public class IntPtg { return "" + getValue(); } + + private static String parseString(String formula, int pos) { + String retval = null; + while (pos < formula.length() && Character.isWhitespace(formula.charAt(pos))) { + pos++; + } + + if (pos < formula.length()) { + if (Character.isDigit(formula.charAt(pos)) ) { + int numpos = pos; + + while (numpos < formula.length() && Character.isDigit(formula.charAt(numpos))){ + numpos++; + } + + if (numpos == formula.length() || formula.charAt(numpos) != '.') { + String numberstr = formula.substring(pos,numpos); + try { + int number = Short.parseShort(numberstr); + retval = numberstr; + } catch (NumberFormatException e) { + retval = null; + } + } + } + } + return retval; + + } + + public static boolean isNextStringToken(String formula, int pos) { + return (parseString(formula,pos) != null); + } + + public int getPrecedence() { + return 5; + } + + public int getStringLength() { + return strlen; + } } 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 3deb3e4410..dc437e9be8 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Ptg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Ptg.java @@ -60,6 +60,9 @@ */ package org.apache.poi.hssf.record.formula; +import java.util.List; +import java.util.ArrayList; + /** * * @author andy @@ -69,12 +72,78 @@ public abstract class Ptg { /** Creates new Ptg */ - + public Ptg() { } + + public static Ptg[] parse(String formula, int offset) { + List ptgs = new ArrayList(); + + while (offset < formula.length()) { + Ptg ptg = getNextToken(formula,offset); + offset += ptg.getStringLength(); + ptgs.add(ptg); + } + + Ptg[] retval = new Ptg[ptgs.size()]; + retval = (Ptg[])ptgs.toArray(retval); + return retval; + } + + public static String ptgsToString(Ptg[] ptgs) { + StringBuffer res = new StringBuffer(); + for (int k =0; k < ptgs.length; k++) { + Ptg ptg = ptgs[k]; + res.append(ptg.toFormulaString()); + } + return res.toString(); + } + + public static Ptg getNextToken(String formula, int offset) { + //later use array of reflected methods like RecordFactory + Ptg retval = null; + + if (AddPtg.isNextStringToken(formula,offset)) { + retval = new AddPtg(formula,offset); + } else if (IntPtg.isNextStringToken(formula,offset)) { + retval = new IntPtg(formula,offset); + } else { + throw new RuntimeException("didn't parse "+formula+" at " +offset); + } + return retval; + } + +/* private static List ptgsToList(Class [] ptgs) + { + List result = new ArrayList(); + Constructor constructor; - public static Ptg createPtg(byte [] data, int offset) + for (int i = 0; i < ptgs.length; i++) + { + Class ptg = null; + + ptg = ptgs[ i ]; + try + { + + constructor = ptg.getConstructor(new Class[] + { + byte [].class, int.class + }); + } + catch (Exception illegalArgumentException) + { + throw new RuntimeException( + "Now that didn't work nicely at all (couldn't do that there list of ptgs)"); + } + result.add(constructor); + } + return result; + }*/ + + + /*public static Ptg createPtg(byte [] data, int offset) { byte id = data[ offset + 0 ]; Ptg retval = null; @@ -148,7 +217,7 @@ public abstract class Ptg + " (" + ( int ) id + ")"); } return retval; - } + }*/ public abstract int getSize(); @@ -164,4 +233,26 @@ public abstract class Ptg public abstract void writeBytes(byte [] array, int offset); public abstract String toFormulaString(); + + /** + * Ptg's should override this + */ +// public boolean isNextStringToken(String formula, int pos) { +// return false; +// } + + public int getPrecedence() { + return 100; + } + + public int getStringLength() { + return 0; + } + + public static void main(String[] args) { + if (args != null && args[0] != null) { + System.out.println("Parsed Formula="+ ptgsToString(parse(args[0],0))); + } + } + }