Changed FormulaRecord.getParsedExpression to return Ptg array

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@690091 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-08-29 03:25:23 +00:00
parent 8685d30fd5
commit 357f3eaf7d
7 changed files with 82 additions and 107 deletions

View File

@ -15,25 +15,21 @@
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
/*
* FormulaViewer.java - finds formulas in a BIFF8 file and attempts to parse them and
* display info about them.
*
* Created on November 18, 2001, 7:58 AM
*/
package org.apache.poi.hssf.dev; package org.apache.poi.hssf.dev;
import java.io.FileInputStream; import java.io.FileInputStream;
//import java.io.*;
import java.util.List; import java.util.List;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.formula.*; import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordFactory;
import org.apache.poi.hssf.record.formula.ExpPtg;
import org.apache.poi.hssf.record.formula.FuncPtg;
import org.apache.poi.hssf.record.formula.OperationPtg;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.model.*; import org.apache.poi.poifs.filesystem.POIFSFileSystem;
/** /**
* FormulaViewer - finds formulas in a BIFF8 file and attempts to read them/display * FormulaViewer - finds formulas in a BIFF8 file and attempts to read them/display
@ -87,20 +83,21 @@ public class FormulaViewer
private void listFormula(FormulaRecord record) { private void listFormula(FormulaRecord record) {
String sep="~"; String sep="~";
List tokens= record.getParsedExpression(); Ptg[] tokens= record.getParsedExpression();
int numptgs = record.getNumberOfExpressionTokens(); Ptg token;
Ptg token = null; int numptgs = tokens.length;
String name,numArg; String numArg;
if (tokens != null) { token = tokens[numptgs-1];
token = (Ptg) tokens.get(numptgs-1);
if (token instanceof FuncPtg) { if (token instanceof FuncPtg) {
numArg = String.valueOf(numptgs-1); numArg = String.valueOf(numptgs-1);
} else { numArg = String.valueOf(-1);} } else {
numArg = String.valueOf(-1);
}
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
if (token instanceof ExpPtg) return; if (token instanceof ExpPtg) return;
buf.append(name=((OperationPtg) token).toFormulaString((HSSFWorkbook)null)); buf.append(((OperationPtg) token).toFormulaString((HSSFWorkbook)null));
buf.append(sep); buf.append(sep);
switch (token.getPtgClass()) { switch (token.getPtgClass()) {
case Ptg.CLASS_REF : case Ptg.CLASS_REF :
@ -116,7 +113,7 @@ public class FormulaViewer
buf.append(sep); buf.append(sep);
if (numptgs>1) { if (numptgs>1) {
token = (Ptg) tokens.get(numptgs-2); token = tokens[numptgs-2];
switch (token.getPtgClass()) { switch (token.getPtgClass()) {
case Ptg.CLASS_REF : case Ptg.CLASS_REF :
buf.append("REF"); buf.append("REF");
@ -134,9 +131,6 @@ public class FormulaViewer
buf.append(sep); buf.append(sep);
buf.append(numArg); buf.append(numArg);
System.out.println(buf.toString()); System.out.println(buf.toString());
} else {
System.out.println("#NAME");
}
} }
/** /**
@ -155,20 +149,18 @@ public class FormulaViewer
System.out.println("value = " + record.getValue()); System.out.println("value = " + record.getValue());
System.out.print("xf = " + record.getXFIndex()); System.out.print("xf = " + record.getXFIndex());
System.out.print(", number of ptgs = " System.out.print(", number of ptgs = "
+ record.getNumberOfExpressionTokens()); + record.getParsedExpression().length);
System.out.println(", options = " + record.getOptions()); System.out.println(", options = " + record.getOptions());
System.out.println("RPN List = "+formulaString(record)); System.out.println("RPN List = "+formulaString(record));
System.out.println("Formula text = "+ composeFormula(record)); System.out.println("Formula text = "+ composeFormula(record));
} }
private String formulaString(FormulaRecord record) { private String formulaString(FormulaRecord record) {
StringBuffer formula = new StringBuffer("=");
int numptgs = record.getNumberOfExpressionTokens();
List tokens = record.getParsedExpression();
Ptg token;
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
for (int i=0;i<numptgs;i++) { Ptg[] tokens = record.getParsedExpression();
token = (Ptg) tokens.get(i); for (int i = 0; i < tokens.length; i++) {
Ptg token = tokens[i];
buf.append( token.toFormulaString((HSSFWorkbook)null)); buf.append( token.toFormulaString((HSSFWorkbook)null));
switch (token.getPtgClass()) { switch (token.getPtgClass()) {
case Ptg.CLASS_REF : case Ptg.CLASS_REF :
@ -187,9 +179,9 @@ public class FormulaViewer
} }
private String composeFormula(FormulaRecord record) private static String composeFormula(FormulaRecord record)
{ {
return org.apache.poi.hssf.model.FormulaParser.toFormulaString((HSSFWorkbook)null,record.getParsedExpression()); return FormulaParser.toFormulaString((HSSFWorkbook)null, record.getParsedExpression());
} }
/** /**

View File

@ -180,18 +180,10 @@ public final class FormulaRecord extends Record implements CellValueRecordInterf
} }
/** /**
* get the size of the stack * @return the formula tokens. never <code>null</code>
* @return size of the stack
*/ */
public int getNumberOfExpressionTokens() { public Ptg[] getParsedExpression() {
return field_8_parsed_expr.length; return (Ptg[]) field_8_parsed_expr.clone();
}
/**
* @return list of formula tokens. never <code>null</code>
*/
public List getParsedExpression() {
return Arrays.asList(field_8_parsed_expr); // TODO - return array
} }
public void setParsedExpression(Ptg[] ptgs) { public void setParsedExpression(Ptg[] ptgs) {

View File

@ -29,6 +29,7 @@ import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.model.Workbook; import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.FormulaRecord; import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.Ref3DPtg; import org.apache.poi.hssf.record.formula.Ref3DPtg;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.SheetReferences; import org.apache.poi.hssf.util.SheetReferences;
@ -56,13 +57,13 @@ public final class TestEventWorkbookBuilder extends TestCase {
} }
} }
public void testBasics() throws Exception { public void testBasics() {
assertNotNull(listener.getSSTRecord()); assertNotNull(listener.getSSTRecord());
assertNotNull(listener.getBoundSheetRecords()); assertNotNull(listener.getBoundSheetRecords());
assertNotNull(listener.getExternSheetRecords()); assertNotNull(listener.getExternSheetRecords());
} }
public void testGetStubWorkbooks() throws Exception { public void testGetStubWorkbooks() {
assertNotNull(listener.getStubWorkbook()); assertNotNull(listener.getStubWorkbook());
assertNotNull(listener.getStubHSSFWorkbook()); assertNotNull(listener.getStubHSSFWorkbook());
@ -70,7 +71,7 @@ public final class TestEventWorkbookBuilder extends TestCase {
assertNotNull(listener.getStubHSSFWorkbook().getSheetReferences()); assertNotNull(listener.getStubHSSFWorkbook().getSheetReferences());
} }
public void testContents() throws Exception { public void testContents() {
assertEquals(2, listener.getSSTRecord().getNumStrings()); assertEquals(2, listener.getSSTRecord().getNumStrings());
assertEquals(3, listener.getBoundSheetRecords().length); assertEquals(3, listener.getBoundSheetRecords().length);
assertEquals(1, listener.getExternSheetRecords().length); assertEquals(1, listener.getExternSheetRecords().length);
@ -83,11 +84,12 @@ public final class TestEventWorkbookBuilder extends TestCase {
assertEquals("S2", ref.getSheetName(2)); assertEquals("S2", ref.getSheetName(2));
} }
public void testFormulas() throws Exception { public void testFormulas() {
FormulaRecord fr;
FormulaRecord[] fRecs = mockListen.getFormulaRecords();
// Check our formula records // Check our formula records
assertEquals(6, mockListen._frecs.size()); assertEquals(6, fRecs.length);
Workbook stubWB = listener.getStubWorkbook(); Workbook stubWB = listener.getStubWorkbook();
assertNotNull(stubWB); assertNotNull(stubWB);
@ -100,47 +102,45 @@ public final class TestEventWorkbookBuilder extends TestCase {
assertEquals("Sh3", stubWB.getSheetName(2)); assertEquals("Sh3", stubWB.getSheetName(2));
// Check we can get the formula without breaking // Check we can get the formula without breaking
for(int i=0; i<mockListen._frecs.size(); i++) { for(int i=0; i<fRecs.length; i++) {
fr = (FormulaRecord)mockListen._frecs.get(i); FormulaParser.toFormulaString(stubHSSF, fRecs[i].getParsedExpression());
FormulaParser.toFormulaString(stubHSSF, fr.getParsedExpression());
} }
// Peer into just one formula, and check that // Peer into just one formula, and check that
// all the ptgs give back the right things // all the ptgs give back the right things
List ptgs = ((FormulaRecord)mockListen._frecs.get(0)).getParsedExpression(); Ptg[] ptgs = fRecs[0].getParsedExpression();
assertEquals(1, ptgs.size()); assertEquals(1, ptgs.length);
assertTrue(ptgs.get(0) instanceof Ref3DPtg); assertTrue(ptgs[0] instanceof Ref3DPtg);
Ref3DPtg ptg = (Ref3DPtg)ptgs.get(0); Ref3DPtg ptg = (Ref3DPtg)ptgs[0];
assertEquals("Sheet1!A1", ptg.toFormulaString(stubHSSF)); assertEquals("Sheet1!A1", ptg.toFormulaString(stubHSSF));
// Now check we get the right formula back for // Now check we get the right formula back for
// a few sample ones // a few sample ones
FormulaRecord fr;
// Sheet 1 A2 is on same sheet // Sheet 1 A2 is on same sheet
fr = (FormulaRecord)mockListen._frecs.get(0); fr = fRecs[0];
assertEquals(1, fr.getRow()); assertEquals(1, fr.getRow());
assertEquals(0, fr.getColumn()); assertEquals(0, fr.getColumn());
assertEquals("Sheet1!A1", FormulaParser.toFormulaString(stubHSSF, fr.getParsedExpression())); assertEquals("Sheet1!A1", FormulaParser.toFormulaString(stubHSSF, fr.getParsedExpression()));
// Sheet 1 A5 is to another sheet // Sheet 1 A5 is to another sheet
fr = (FormulaRecord)mockListen._frecs.get(3); fr = fRecs[3];
assertEquals(4, fr.getRow()); assertEquals(4, fr.getRow());
assertEquals(0, fr.getColumn()); assertEquals(0, fr.getColumn());
assertEquals("'S2'!A1", FormulaParser.toFormulaString(stubHSSF, fr.getParsedExpression())); assertEquals("'S2'!A1", FormulaParser.toFormulaString(stubHSSF, fr.getParsedExpression()));
// Sheet 1 A7 is to another sheet, range // Sheet 1 A7 is to another sheet, range
fr = (FormulaRecord)mockListen._frecs.get(5); fr = fRecs[5];
assertEquals(6, fr.getRow()); assertEquals(6, fr.getRow());
assertEquals(0, fr.getColumn()); assertEquals(0, fr.getColumn());
assertEquals("SUM(Sh3!A1:A4)", FormulaParser.toFormulaString(stubHSSF, fr.getParsedExpression())); assertEquals("SUM(Sh3!A1:A4)", FormulaParser.toFormulaString(stubHSSF, fr.getParsedExpression()));
// Now, load via Usermodel and re-check // Now, load via Usermodel and re-check
InputStream is = HSSFTestDataSamples.openSampleFileStream("3dFormulas.xls"); HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("3dFormulas.xls");
POIFSFileSystem fs = new POIFSFileSystem(is);
HSSFWorkbook wb = new HSSFWorkbook(fs);
assertEquals("Sheet1!A1", wb.getSheetAt(0).getRow(1).getCell(0).getCellFormula()); assertEquals("Sheet1!A1", wb.getSheetAt(0).getRow(1).getCell(0).getCellFormula());
assertEquals("SUM(Sh3!A1:A4)", wb.getSheetAt(0).getRow(6).getCell(0).getCellFormula()); assertEquals("SUM(Sh3!A1:A4)", wb.getSheetAt(0).getRow(6).getCell(0).getCellFormula());
} }
@ -156,5 +156,10 @@ public final class TestEventWorkbookBuilder extends TestCase {
_frecs.add(record); _frecs.add(record);
} }
} }
public FormulaRecord[] getFormulaRecords() {
FormulaRecord[] result = new FormulaRecord[_frecs.size()];
_frecs.toArray(result);
return result;
}
} }
} }

View File

@ -17,15 +17,14 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.util.List;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hssf.record.formula.AttrPtg; import org.apache.poi.hssf.record.formula.AttrPtg;
import org.apache.poi.hssf.record.formula.FuncVarPtg; import org.apache.poi.hssf.record.formula.FuncVarPtg;
import org.apache.poi.hssf.record.formula.IntPtg; import org.apache.poi.hssf.record.formula.IntPtg;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.record.formula.RefPtg;
/** /**
@ -39,14 +38,12 @@ public final class TestFormulaRecord extends TestCase {
public void testCreateFormulaRecord () { public void testCreateFormulaRecord () {
FormulaRecord record = new FormulaRecord(); FormulaRecord record = new FormulaRecord();
record.setColumn((short)0); record.setColumn((short)0);
//record.setRow((short)1);
record.setRow(1); record.setRow(1);
record.setXFIndex((short)4); record.setXFIndex((short)4);
assertEquals(record.getColumn(),(short)0); assertEquals(record.getColumn(),0);
//assertEquals(record.getRow(),(short)1); assertEquals(record.getRow(), 1);
assertEquals((short)record.getRow(),(short)1); assertEquals(record.getXFIndex(),4);
assertEquals(record.getXFIndex(),(short)4);
} }
/** /**
@ -103,7 +100,7 @@ public final class TestFormulaRecord extends TestCase {
assertEquals("Offset 22", 1, output[26]); assertEquals("Offset 22", 1, output[26]);
} }
public void testWithConcat() throws Exception { public void testWithConcat() {
// =CHOOSE(2,A2,A3,A4) // =CHOOSE(2,A2,A3,A4)
byte[] data = { byte[] data = {
6, 0, 68, 0, 6, 0, 68, 0,
@ -126,23 +123,19 @@ public final class TestFormulaRecord extends TestCase {
FormulaRecord fr = new FormulaRecord(inp); FormulaRecord fr = new FormulaRecord(inp);
List ptgs = fr.getParsedExpression(); Ptg[] ptgs = fr.getParsedExpression();
assertEquals(9, ptgs.size()); assertEquals(9, ptgs.length);
assertEquals(IntPtg.class, ptgs.get(0).getClass()); assertEquals(IntPtg.class, ptgs[0].getClass());
assertEquals(AttrPtg.class, ptgs.get(1).getClass()); assertEquals(AttrPtg.class, ptgs[1].getClass());
assertEquals(RefPtg.class, ptgs.get(2).getClass()); assertEquals(RefPtg.class, ptgs[2].getClass());
assertEquals(AttrPtg.class, ptgs.get(3).getClass()); assertEquals(AttrPtg.class, ptgs[3].getClass());
assertEquals(RefPtg.class, ptgs.get(4).getClass()); assertEquals(RefPtg.class, ptgs[4].getClass());
assertEquals(AttrPtg.class, ptgs.get(5).getClass()); assertEquals(AttrPtg.class, ptgs[5].getClass());
assertEquals(RefPtg.class, ptgs.get(6).getClass()); assertEquals(RefPtg.class, ptgs[6].getClass());
assertEquals(AttrPtg.class, ptgs.get(7).getClass()); assertEquals(AttrPtg.class, ptgs[7].getClass());
assertEquals(FuncVarPtg.class, ptgs.get(8).getClass()); assertEquals(FuncVarPtg.class, ptgs[8].getClass());
FuncVarPtg choose = (FuncVarPtg)ptgs.get(8); FuncVarPtg choose = (FuncVarPtg)ptgs[8];
assertEquals("CHOOSE", choose.getName()); assertEquals("CHOOSE", choose.getName());
} }
public static void main(String [] ignored_args) {
junit.textui.TestRunner.run(TestFormulaRecord.class);
}
} }

View File

@ -17,8 +17,6 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import java.util.List;
import org.apache.poi.hssf.record.CellValueRecordInterface; import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate; import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.record.formula.Ptg;
@ -40,10 +38,6 @@ public final class FormulaExtractor {
throw new IllegalArgumentException("Not a formula cell"); throw new IllegalArgumentException("Not a formula cell");
} }
FormulaRecordAggregate fra = (FormulaRecordAggregate) vr; FormulaRecordAggregate fra = (FormulaRecordAggregate) vr;
List tokens = fra.getFormulaRecord().getParsedExpression(); return fra.getFormulaRecord().getParsedExpression();
Ptg[] result = new Ptg[tokens.size()];
tokens.toArray(result);
return result;
} }
} }

View File

@ -18,13 +18,13 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.FormulaRecord; import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate; import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.CellValue; import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.CellValue;
import org.apache.poi.hssf.util.CellReference; import org.apache.poi.hssf.util.CellReference;
@ -65,15 +65,14 @@ public final class TestBug42464 extends TestCase {
} }
FormulaRecordAggregate record = (FormulaRecordAggregate) cell.getCellValueRecord(); FormulaRecordAggregate record = (FormulaRecordAggregate) cell.getCellValueRecord();
FormulaRecord r = record.getFormulaRecord(); FormulaRecord r = record.getFormulaRecord();
List ptgs = r.getParsedExpression(); Ptg[] ptgs = r.getParsedExpression();
String cellRef = new CellReference(row.getRowNum(), cell.getCellNum(), false, false).formatAsString(); String cellRef = new CellReference(row.getRowNum(), cell.getCellNum(), false, false).formatAsString();
if(false && cellRef.equals("BP24")) { // TODO - replace System.out.println()s with asserts if(false && cellRef.equals("BP24")) { // TODO - replace System.out.println()s with asserts
System.out.print(cellRef); System.out.print(cellRef);
System.out.println(" - has " + r.getNumberOfExpressionTokens() System.out.println(" - has " + ptgs.length + " ptgs:");
+ " ptgs:"); for(int i=0; i<ptgs.length; i++) {
for(int i=0; i<ptgs.size(); i++) { String c = ptgs[i].getClass().toString();
String c = ptgs.get(i).getClass().toString();
System.out.println("\t" + c.substring(c.lastIndexOf('.')+1) ); System.out.println("\t" + c.substring(c.lastIndexOf('.')+1) );
} }
System.out.println("-> " + cell.getCellFormula()); System.out.println("-> " + cell.getCellFormula());

View File

@ -20,7 +20,6 @@ package org.apache.poi.hssf.usermodel;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -29,6 +28,7 @@ import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate; import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.formula.AreaPtg; import org.apache.poi.hssf.record.formula.AreaPtg;
import org.apache.poi.hssf.record.formula.FuncVarPtg; import org.apache.poi.hssf.record.formula.FuncVarPtg;
import org.apache.poi.hssf.record.formula.Ptg;
/** /**
* *
@ -183,14 +183,14 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
HSSFCell cellSUM = rowSUM.getCell(0); HSSFCell cellSUM = rowSUM.getCell(0);
FormulaRecordAggregate frec = (FormulaRecordAggregate) cellSUM.getCellValueRecord(); FormulaRecordAggregate frec = (FormulaRecordAggregate) cellSUM.getCellValueRecord();
List ops = frec.getFormulaRecord().getParsedExpression(); Ptg[] ops = frec.getFormulaRecord().getParsedExpression();
assertEquals(2, ops.size()); assertEquals(2, ops.length);
assertEquals(AreaPtg.class, ops.get(0).getClass()); assertEquals(AreaPtg.class, ops[0].getClass());
assertEquals(FuncVarPtg.class, ops.get(1).getClass()); assertEquals(FuncVarPtg.class, ops[1].getClass());
// Actually stored as C1 to C65536 // Actually stored as C1 to C65536
// (last row is -1 === 65535) // (last row is -1 === 65535)
AreaPtg ptg = (AreaPtg) ops.get(0); AreaPtg ptg = (AreaPtg) ops[0];
assertEquals(2, ptg.getFirstColumn()); assertEquals(2, ptg.getFirstColumn());
assertEquals(2, ptg.getLastColumn()); assertEquals(2, ptg.getLastColumn());
assertEquals(0, ptg.getFirstRow()); assertEquals(0, ptg.getFirstRow());