On Fri, 2002-04-05 at 02:59, Avik Sengupta wrote:
> Ok, this turned out to be simple. An updated patch (against latest cvs) that
> solves the parenthesis display problem i mentioned earlier. (Parenthesis Ptgs
> ARE written, even tho its not required for RPN calc)
>
> Have a good weekend folks.
>
> Cheers
> -
> Avik
>
> PS. Does the formula viewer work? I cant seem to get it to.
>
> PPS. Anybody have any idea on section 3.12 of the openoffice excel doc
> (predefined sheet formulas) which at the moment is blank? I could do with only
> a few example id's so that i could test.
I think you should get a copy of the Excel 97 Developer's kit from
Amazon.com - you can only get it used (out of print...gee I wonder why?)
but thats okay since its $5.00 -- it has basically most of the "words"
in the BIFF 8 "language" but the grammar is ours to figure out. (and
thats where you "just insert fun" here at the poi project ;-) )
> ----
>
> ? formula3.patch
> ? src/documentation/xdocs/.nbattrs
> ? src/documentation/xdocs/hdf/.nbattrs
> ? src/documentation/xdocs/hpsf/.nbattrs
> ? src/documentation/xdocs/hssf/.nbattrs
> ? src/documentation/xdocs/news/.nbattrs
> ? src/documentation/xdocs/plan/.nbattrs
> ? src/documentation/xdocs/poifs/.nbattrs
> ? src/documentation/xdocs/resolutions/.nbattrs
> ? src/documentation/xdocs/utils/.nbattrs
> ? src/java/org/apache/poi/hssf/model/.nbattrs
> ? src/java/org/apache/poi/hssf/record/.nbattrs
> ? src/java/org/apache/poi/hssf/record/formula/.nbattrs
> ? src/java/org/apache/poi/hssf/record/formula/DummyFunctionPtg.java
> ? src/java/org/apache/poi/hssf/usermodel/.nbattrs
> ? tools/antipede/lib/temp
> Index: .cvsignore
> ===================================================================
> RCS file: /home/cvspublic/jakarta-poi/.cvsignore,v
> retrieving revision 1.7
> diff -u -r1.7 .cvsignore
> --- .cvsignore 15 Apr 2002 08:07:45 -0000 1.7
> +++ .cvsignore 26 Apr 2002 16:17:14 -0000
> @@ -6,3 +6,4 @@
> log*.*
> *.log
> build
> +.nbattrs
> Index: src/documentation/xdocs/plan/POI20Vision.xml
> ===================================================================
> RCS file: /home/cvspublic/jakarta-poi/src/documentation/xdocs/plan/POI20Vision.xml,v
> retrieving revision 1.5
> diff -u -r1.5 POI20Vision.xml
> --- src/documentation/xdocs/plan/POI20Vision.xml 6 Apr 2002 13:36:06 -0000
> 1.5
> +++ src/documentation/xdocs/plan/POI20Vision.xml 26 Apr 2002 16:17:52 -0000
> @@ -17,12 +17,12 @@
> <section title="Preface">
> <p>
> This is the POI 2.0 cycle vision document. Although the vision
> - has not changed and this document is certainly not out of date and
> - the vision has not changed, the structure of the project has
> + has not changed and this document is certainly not out of date,
> + the structure of the project has
> changed a bit. We're not going to change the vision document to
> reflect this (however proper that may be) because it would only
> involve deletion. There is no purpose in providing less
> - information provided we give clarification.
> + information, provided we give clarification.
> </p>
> <p>
> This document was created before the POI components for
> @@ -94,7 +94,7 @@
> </li>
> <li>
> Refactor HSSF for greater
> - performance as well as an event-driven API for reading
> + performance as well as provide an event-driven API for reading
> </li>
> <li>
> Extend HSSF by adding the ability to read and write
>formulas.
> @@ -116,7 +116,7 @@
> POIFSSerializer and HSSFSerializer
> </li>
> <li>
> - Providing the create excel charts. (write only)
> + Providing the ability to create excel charts. (write only)
> </li>
> </ul>
> </section>
> Index: src/java/org/apache/poi/hssf/record/FormulaRecord.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/FormulaRecord.java,v
> retrieving revision 1.5
> diff -u -r1.5 FormulaRecord.java
> --- src/java/org/apache/poi/hssf/record/FormulaRecord.java 18 Apr 2002 12:00:53
>-0000 1.5
> +++ src/java/org/apache/poi/hssf/record/FormulaRecord.java 26 Apr 2002 16:18:20
>-0000
> @@ -78,7 +78,7 @@
> 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 @@
> 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();
> }
>
> Index: src/java/org/apache/poi/hssf/record/formula/AddPtg.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/AddPtg.java,v
> retrieving revision 1.3
> diff -u -r1.3 AddPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/AddPtg.java 23 Apr 2002 23:56:46
>-0000 1.3
> +++ src/java/org/apache/poi/hssf/record/formula/AddPtg.java 26 Apr 2002 16:18:32
>-0000
> @@ -141,6 +141,7 @@
> return buffer.toString();
> }
>
> +
> public int getPrecedence() {
> return 5;
> }
> @@ -148,6 +149,18 @@
> 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);
> Index: src/java/org/apache/poi/hssf/record/formula/AttrPtg.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 AttrPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/AttrPtg.java 23 Apr 2002 23:56:46
>-0000 1.2
> +++ src/java/org/apache/poi/hssf/record/formula/AttrPtg.java 26 Apr 2002 16:18:40
>-0000
> @@ -210,5 +210,12 @@
> public void manipulate(List source, List results, int pos) {
> }
>
> + public String toFormulaString(String[] operands) {
> + return "SUM(" + operands[ 0 ] + ")";
> + }
> +
> + public int getPrecedence() {
> + return 1;
> + }
>
> }
> Index: src/java/org/apache/poi/hssf/record/formula/DividePtg.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/DividePtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 DividePtg.java
> --- src/java/org/apache/poi/hssf/record/formula/DividePtg.java 23 Apr 2002
>23:56:46 -0000 1.2
> +++ src/java/org/apache/poi/hssf/record/formula/DividePtg.java 26 Apr 2002
>16:18:46 -0000
> @@ -119,7 +119,25 @@
> 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) {
> }
>
> Index: src/java/org/apache/poi/hssf/record/formula/FormulaParser.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/FormulaParser.java,v
> retrieving revision 1.1
> diff -u -r1.1 FormulaParser.java
> --- src/java/org/apache/poi/hssf/record/formula/FormulaParser.java 17 Apr 2002
>23:06:49 -0000 1.1
> +++ src/java/org/apache/poi/hssf/record/formula/FormulaParser.java 26 Apr 2002
>16:19:03 -0000
> @@ -60,56 +60,66 @@
> 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 <avik AT Avik Sengupta DOT com>
> *
> - * @author Avik Sengupta <[EMAIL PROTECTED]>
> + * 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 :
> + * <expression> ::= <term> [<addop> <term>]*
> + * <term> ::= <factor> [ <mulop> <factor ]*
> + * <factor> ::= <number> | (<expression>) | <cellRef>
> */
> 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 @@
> }
>
>
> - //{--------------------------------------------------------------}
> - //{ 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 @@
> }
>
>
> - //{--------------------------------------------------------------}
> - //{ Match a Specific Input Character }
> -
> +
> + /** Match a Specific Input Character */
> private void Match(char x) {
> if (Look != x) {
> Expected("" + x + "");
> @@ -192,9 +190,7 @@
> }
>
>
> - //{--------------------------------------------------------------}
> - //{ Get an Identifier }
> -
> + /** Get an Identifier */
> private String GetName() {
> String Token;
> Token = "";
> @@ -211,9 +207,7 @@
> }
>
>
> - //{--------------------------------------------------------------}
> - //{ Get a Number }
> -
> + /** Get a Number */
> private String GetNum() {
> String Value ="";
> if (!IsDigit(Look)) Expected("Integer");
> @@ -224,139 +218,120 @@
> 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!!
> }
> }
> }
> -
> -
> - //{---------------------------------------------------------------}
> - //{ Parse and Translate a Math Factor }
> -
> - //procedure Expression; Forward;
>
> + /** 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 */
> 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 @@
> Term();
> }
> while (IsAddop(Look)) {
> - EmitLn("MOVE D0,-(SP)");
> if ( Look == '+' ) Add();
> if (Look == '-') Subtract();
> + // if (Look == '*') Multiply();
> + // if (Look == '/') Divide();
> }
> }
>
> @@ -380,71 +356,104 @@
> 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();
> + synchronized (tokens) {
> + Init();
> + Expression();
> + }
> }
>
> - 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
> + /** 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<numPtgs;i++) {
> + if (ptgs[i] instanceof OperationPtg) {
> + o = (OperationPtg) ptgs[i];
> + numOperands = o.getNumberOfOperands();
> + operands = new String[numOperands];
> + for (int j=0;j<numOperands;j++) {
> + operands[numOperands-j-1] = (String) stack.pop(); //TODO: catch
>stack underflow and throw parse exception.
> +
> + }
> + String result = o.toFormulaString(operands);
> + //if (! (o instanceof DummyFunctionPtg) ) result = "("+result+")" ;
> + stack.push(result);
> + } else {
> + stack.push(ptgs[i].toFormulaString());
> }
> -
> -
> - for (numOper = op.getNumberOfOperands();numOper>0;numOper--) {
> - if (numOnStack==0) {
> - result.add(operandsList.pop());//numOnStack++;
> - } else {
> - numOnStack--;
> - }
> - }
> - result.add(op);
> - numOnStack++;
> }
> + return (String) stack.pop(); //TODO: catch stack underflow and throw parse
>exception.
> }
> -
> +
> public String toString() {
> StringBuffer buf = new StringBuffer();
> - for (int i=0;i<result.size();i++) {
> - buf.append( ( (Ptg)result.get(i)).toFormulaString());
> + for (int i=0;i<tokens.size();i++) {
> + buf.append( ( (Ptg)tokens.get(i)).toFormulaString());
> buf.append(' ');
> }
> return buf.toString();
> }
>
>
> - //{--------------------------------------------------------------}
> - //{ Main Program for testing}
> + /** Main Program for testing*/
> public static void main(String[] argv) {
> FormulaParser fp = new FormulaParser(argv[0]+";");
> + System.out.println("\nFormula is: ");
> fp.parse();
> - System.out.println(fp.toString());
> + System.out.println("RPN Form is: " +fp.toString());
> +
> + System.out.println("Converted Text form is :
>"+fp.toFormulaString(fp.getRPNPtg()));
> + try {
> + short rownum = 0;
> + FileOutputStream out = new FileOutputStream("test.xls");
> + HSSFWorkbook wb = new HSSFWorkbook();
> + HSSFSheet s = wb.createSheet();
> + HSSFRow r = null;
> + HSSFCell c = null;
> +
> + r = s.createRow((short) 0);
> + c = r.createCell((short) 0);
> + c.setCellFormula(argv[0]);
>
> + wb.write(out);
> + out.close();
> + } catch (java.io.IOException ioe) {
> + ioe.printStackTrace();
> + }
> //If Look <> CR then Expected('NewLine');
> }
> - //{--------------------------------------------------------------}
>
> }
> Index: src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 MultiplyPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java 23 Apr 2002
>23:56:46 -0000 1.2
> +++ src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java 26 Apr 2002
>16:19:09 -0000
> @@ -132,6 +132,16 @@
> 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 @@
> }
>
>
> +
> }
> Index: src/java/org/apache/poi/hssf/record/formula/OperationPtg.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 OperationPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/OperationPtg.java 23 Apr 2002
>23:56:46 -0000 1.2
> +++ src/java/org/apache/poi/hssf/record/formula/OperationPtg.java 26 Apr 2002
>16:19:15 -0000
> @@ -74,6 +74,10 @@
> 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();
>
> Index: src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java,v
> retrieving revision 1.3
> diff -u -r1.3 ParenthesisPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java 23 Apr 2002
>23:56:46 -0000 1.3
> +++ src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java 26 Apr 2002
>16:19:20 -0000
> @@ -58,9 +58,9 @@
> 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 <[EMAIL PROTECTED]>
> * Andrew C. Oliver (acoliver at apache dot org)
> @@ -69,17 +69,18 @@
> 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 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;
> + }
>
> }
>
> Index: src/java/org/apache/poi/hssf/record/formula/PowerPtg.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 PowerPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/PowerPtg.java 23 Apr 2002 23:56:46
>-0000 1.2
> +++ src/java/org/apache/poi/hssf/record/formula/PowerPtg.java 26 Apr 2002 16:19:26
>-0000
> @@ -109,6 +109,10 @@
> {
> return "^";
> }
> +
> + public int getPrecedence() {
> + return 3;
> + }
>
> public String toFormulaString(Ptg [] operands)
> {
> @@ -119,8 +123,21 @@
> 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) {
> }
>
> +
> }
> Index: src/java/org/apache/poi/hssf/record/formula/Ptg.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/Ptg.java,v
> retrieving revision 1.4
> diff -u -r1.4 Ptg.java
> --- src/java/org/apache/poi/hssf/record/formula/Ptg.java 23 Apr 2002 22:24:41
>-0000 1.4
> +++ src/java/org/apache/poi/hssf/record/formula/Ptg.java 26 Apr 2002 16:19:37
>-0000
> @@ -77,6 +77,54 @@
> {
> }
>
> + /** 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;
> + }
> +
> +
>
>
> /*
> Index: src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 SubtractPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java 23 Apr 2002
>23:56:46 -0000 1.2
> +++ src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java 26 Apr 2002
>16:19:44 -0000
> @@ -119,9 +119,27 @@
> buffer.append(operands[ 1 ].toFormulaString());
> return buffer.toString();
> }
> +
> + public int getPrecedence() {
> + return 5;
> + }
>
> - public void manipulate(List source, List results, int pos) {
> + 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) {
> + }
>
> +
> }
> Index: src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 ValueVariableFunctionPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java 23 Apr
>2002 23:56:46 -0000 1.2
> +++ src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java 26 Apr
>2002 16:19:49 -0000
> @@ -128,8 +128,20 @@
> {
> return toFormulaString();
> }
> +
>
> + public String toFormulaString(String[] operands) {
> + return toFormulaString();
> + }
> +
> +
> public void manipulate(List source, List results, int pos) {
> }
>
> + public int getPrecedence() {
> + return 1;
> + }
> +
> +
> +
> }
> Index: src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
> ===================================================================
> RCS file:
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java,v
> retrieving revision 1.5
> diff -u -r1.5 HSSFCell.java
> --- src/java/org/apache/poi/hssf/usermodel/HSSFCell.java 15 Mar 2002 12:15:59
>-0000 1.5
> +++ src/java/org/apache/poi/hssf/usermodel/HSSFCell.java 26 Apr 2002 16:20:26
>-0000
> @@ -70,6 +70,9 @@
> 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 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.
--
http://www.superlinksoftware.com
http://jakarta.apache.org/poi - port of Excel/Word/OLE 2 Compound
Document
format to java
http://developer.java.sun.com/developer/bugParade/bugs/4487555.html
- fix java generics!
The avalanche has already started. It is too late for the pebbles to
vote.
-Ambassador Kosh