first cut support for sheet references. Writing works fine, reading also works except for bug 9632 .. which means that the formula string retrieved is incorrect. will fix soon
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@352723 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cf3e8aacd0
commit
3d30c55466
@ -743,7 +743,7 @@ public class Sheet
|
|||||||
rec.setOptions(( short ) 2);
|
rec.setOptions(( short ) 2);
|
||||||
rec.setValue(0);
|
rec.setValue(0);
|
||||||
rec.setXFIndex(( short ) 0x0f);
|
rec.setXFIndex(( short ) 0x0f);
|
||||||
FormulaParser fp = new FormulaParser(formula);
|
FormulaParser fp = new FormulaParser(formula,null); //fix - do we need this method?
|
||||||
fp.parse();
|
fp.parse();
|
||||||
Ptg[] ptg = fp.getRPNPtg();
|
Ptg[] ptg = fp.getRPNPtg();
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
@ -57,6 +57,7 @@ package org.apache.poi.hssf.record.formula;
|
|||||||
|
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.hssf.util.RangeAddress;
|
import org.apache.poi.hssf.util.RangeAddress;
|
||||||
|
import org.apache.poi.hssf.util.AreaReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Title: Area 3D Ptg - 3D referecnce (Sheet + Area)<P>
|
* Title: Area 3D Ptg - 3D referecnce (Sheet + Area)<P>
|
||||||
@ -77,11 +78,22 @@ public class Area3DPtg extends Ptg
|
|||||||
private short field_5_last_column;
|
private short field_5_last_column;
|
||||||
|
|
||||||
/** Creates new AreaPtg */
|
/** Creates new AreaPtg */
|
||||||
|
public Area3DPtg() {}
|
||||||
|
|
||||||
|
protected Area3DPtg(String arearef, short externIdx) {
|
||||||
|
AreaReference ar = new AreaReference(arearef);
|
||||||
|
|
||||||
|
setFirstRow((short)ar.getCells()[0].getRow());
|
||||||
|
setFirstColumn((short)ar.getCells()[0].getCol());
|
||||||
|
setLastRow((short)ar.getCells()[1].getRow());
|
||||||
|
setLastColumn((short)ar.getCells()[1].getCol());
|
||||||
|
//setFirstColRelative(!ar.getCells()[0].isColAbsolute());
|
||||||
|
//setLastColRelative(!ar.getCells()[1].isColAbsolute());
|
||||||
|
//setFirstRowRelative(!ar.getCells()[0].isRowAbsolute());
|
||||||
|
//setLastRowRelative(!ar.getCells()[1].isRowAbsolute());
|
||||||
|
setExternSheetIndex(externIdx);
|
||||||
|
|
||||||
public Area3DPtg()
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Area3DPtg(byte[] data, int offset)
|
public Area3DPtg(byte[] data, int offset)
|
||||||
{
|
{
|
||||||
offset++;
|
offset++;
|
||||||
@ -113,7 +125,7 @@ public class Area3DPtg extends Ptg
|
|||||||
|
|
||||||
public void writeBytes(byte [] array, int offset)
|
public void writeBytes(byte [] array, int offset)
|
||||||
{
|
{
|
||||||
array[ 0 + offset ] = sid;
|
array[ 0 + offset ] = (byte) (sid + ptgClass);
|
||||||
LittleEndian.putShort(array, 1 + offset , getExternSheetIndex());
|
LittleEndian.putShort(array, 1 + offset , getExternSheetIndex());
|
||||||
LittleEndian.putShort(array, 3 + offset , getFirstRow());
|
LittleEndian.putShort(array, 3 + offset , getFirstRow());
|
||||||
LittleEndian.putShort(array, 5 + offset , getLastRow());
|
LittleEndian.putShort(array, 5 + offset , getLastRow());
|
||||||
|
@ -63,6 +63,8 @@ import java.util.Stack;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.model.Workbook;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@ -98,6 +100,8 @@ public class FormulaParser {
|
|||||||
|
|
||||||
private char Look; // Lookahead Character
|
private char Look; // Lookahead Character
|
||||||
|
|
||||||
|
private Workbook book;
|
||||||
|
|
||||||
|
|
||||||
/** create the parser with the string that is to be parsed
|
/** create the parser with the string that is to be parsed
|
||||||
* later call the parse() method to return ptg list in rpn order
|
* later call the parse() method to return ptg list in rpn order
|
||||||
@ -106,9 +110,10 @@ public class FormulaParser {
|
|||||||
* The parse and getPRNPtg are internally synchronized for safety, thus
|
* 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.
|
* while it is safe to use in a multithreaded environment, you will get long lock waits.
|
||||||
*/
|
*/
|
||||||
public FormulaParser(String formula){
|
public FormulaParser(String formula, Workbook book){
|
||||||
formulaString = formula;
|
formulaString = formula;
|
||||||
pointer=0;
|
pointer=0;
|
||||||
|
this.book = book;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -130,7 +135,7 @@ public class FormulaParser {
|
|||||||
private void Abort(String s) {
|
private void Abort(String s) {
|
||||||
Error(s);
|
Error(s);
|
||||||
//System.exit(1); //throw exception??
|
//System.exit(1); //throw exception??
|
||||||
throw new RuntimeException("Cannot Parse, sorry");
|
throw new RuntimeException("Cannot Parse, sorry : "+s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -235,22 +240,31 @@ public class FormulaParser {
|
|||||||
System.out.println();;
|
System.out.println();;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Parse and Translate a Identifier */
|
/** Parse and Translate a String Identifier */
|
||||||
private void Ident() {
|
private void Ident() {
|
||||||
String name;
|
String name;
|
||||||
name = GetName();
|
name = GetName();
|
||||||
if (Look == '('){
|
if (Look == '('){
|
||||||
//This is a function
|
//This is a function
|
||||||
Match('(');
|
function(name);
|
||||||
int numArgs = Arguments();
|
|
||||||
Match(')');
|
|
||||||
//this is the end of the function
|
|
||||||
tokens.add(function(name,(byte)numArgs));
|
|
||||||
} else if (Look == ':') { // this is a AreaReference
|
} else if (Look == ':') { // this is a AreaReference
|
||||||
String first = name;
|
String first = name;
|
||||||
Match(':');
|
Match(':');
|
||||||
String second = GetName();
|
String second = GetName();
|
||||||
tokens.add(new AreaPtg(first+":"+second));
|
tokens.add(new AreaPtg(first+":"+second));
|
||||||
|
} else if (Look == '!') {
|
||||||
|
Match('!');
|
||||||
|
String sheetName = name;
|
||||||
|
String first = GetName();
|
||||||
|
short externIdx = book.checkExternSheet(book.getSheetIndex(sheetName));
|
||||||
|
if (Look == ':') {
|
||||||
|
Match(':');
|
||||||
|
String second=GetName();
|
||||||
|
|
||||||
|
tokens.add(new Area3DPtg(first+":"+second,externIdx));
|
||||||
|
} else {
|
||||||
|
tokens.add(new Ref3DPtg(first,externIdx));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
//this can be either a cell ref or a named range !!
|
//this can be either a cell ref or a named range !!
|
||||||
boolean cellRef = true ; //we should probably do it with reg exp??
|
boolean cellRef = true ; //we should probably do it with reg exp??
|
||||||
@ -262,7 +276,14 @@ public class FormulaParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Ptg function(String name,byte numArgs) {
|
private void function(String name) {
|
||||||
|
Match('(');
|
||||||
|
int numArgs = Arguments();
|
||||||
|
Match(')');
|
||||||
|
tokens.add(getFunction(name,(byte)numArgs));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Ptg getFunction(String name,byte numArgs) {
|
||||||
Ptg retval = null;
|
Ptg retval = null;
|
||||||
retval = new FuncVarPtg(name,numArgs);
|
retval = new FuncVarPtg(name,numArgs);
|
||||||
/** if (numArgs == 1 && name.equals("SUM")) {
|
/** if (numArgs == 1 && name.equals("SUM")) {
|
||||||
|
@ -58,7 +58,7 @@ package org.apache.poi.hssf.record.formula;
|
|||||||
|
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.hssf.util.RangeAddress;
|
import org.apache.poi.hssf.util.RangeAddress;
|
||||||
|
import org.apache.poi.hssf.util.CellReference;
|
||||||
/**
|
/**
|
||||||
* Title: Reference 3D Ptg <P>
|
* Title: Reference 3D Ptg <P>
|
||||||
* Description: Defined a cell in extern sheet. <P>
|
* Description: Defined a cell in extern sheet. <P>
|
||||||
@ -75,9 +75,7 @@ public class Ref3DPtg extends Ptg {
|
|||||||
private short field_3_column;
|
private short field_3_column;
|
||||||
|
|
||||||
/** Creates new AreaPtg */
|
/** Creates new AreaPtg */
|
||||||
|
public Ref3DPtg() {}
|
||||||
public Ref3DPtg() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Ref3DPtg(byte[] data, int offset) {
|
public Ref3DPtg(byte[] data, int offset) {
|
||||||
offset++;
|
offset++;
|
||||||
@ -86,6 +84,15 @@ public class Ref3DPtg extends Ptg {
|
|||||||
field_3_column = LittleEndian.getShort(data, 4 + offset);
|
field_3_column = LittleEndian.getShort(data, 4 + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Ref3DPtg(String cellref, short externIdx ) {
|
||||||
|
CellReference c= new CellReference(cellref);
|
||||||
|
setRow((short) c.getRow());
|
||||||
|
setColumn((short) c.getCol());
|
||||||
|
//setColRelative(!c.isColAbsolute());
|
||||||
|
//setRowRelative(!c.isRowAbsolute());
|
||||||
|
setExternSheetIndex(externIdx);
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
@ -100,7 +107,7 @@ public class Ref3DPtg extends Ptg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void writeBytes(byte [] array, int offset) {
|
public void writeBytes(byte [] array, int offset) {
|
||||||
array[ 0 + offset ] = sid;
|
array[ 0 + offset ] = (byte) (sid + ptgClass);
|
||||||
LittleEndian.putShort(array, 1 + offset , getExternSheetIndex());
|
LittleEndian.putShort(array, 1 + offset , getExternSheetIndex());
|
||||||
LittleEndian.putShort(array, 3 + offset , getRow());
|
LittleEndian.putShort(array, 3 + offset , getRow());
|
||||||
LittleEndian.putShort(array, 5 + offset , getColumnRaw());
|
LittleEndian.putShort(array, 5 + offset , getColumnRaw());
|
||||||
|
@ -701,7 +701,7 @@ public class HSSFCell
|
|||||||
rec.setOptions(( short ) 2);
|
rec.setOptions(( short ) 2);
|
||||||
rec.setValue(0);
|
rec.setValue(0);
|
||||||
rec.setXFIndex(( short ) 0x0f);
|
rec.setXFIndex(( short ) 0x0f);
|
||||||
FormulaParser fp = new FormulaParser(formula+";");
|
FormulaParser fp = new FormulaParser(formula+";",book);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
Ptg[] ptg = fp.getRPNPtg();
|
Ptg[] ptg = fp.getRPNPtg();
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
@ -20,13 +20,13 @@ public class TestFormulaParser extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testSimpleFormula() {
|
public void testSimpleFormula() {
|
||||||
FormulaParser fp = new FormulaParser("2+2;");
|
FormulaParser fp = new FormulaParser("2+2;",null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
Ptg[] ptgs = fp.getRPNPtg();
|
Ptg[] ptgs = fp.getRPNPtg();
|
||||||
assertTrue("three tokens expected, got "+ptgs.length,ptgs.length == 3);
|
assertTrue("three tokens expected, got "+ptgs.length,ptgs.length == 3);
|
||||||
}
|
}
|
||||||
public void testFormulaWithSpace1() {
|
public void testFormulaWithSpace1() {
|
||||||
FormulaParser fp = new FormulaParser(" 2 + 2 ;");
|
FormulaParser fp = new FormulaParser(" 2 + 2 ;",null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
Ptg[] ptgs = fp.getRPNPtg();
|
Ptg[] ptgs = fp.getRPNPtg();
|
||||||
assertTrue("three tokens expected, got "+ptgs.length,ptgs.length == 3);
|
assertTrue("three tokens expected, got "+ptgs.length,ptgs.length == 3);
|
||||||
@ -39,7 +39,7 @@ public class TestFormulaParser extends TestCase {
|
|||||||
public void testFormulaWithSpace2() {
|
public void testFormulaWithSpace2() {
|
||||||
Ptg[] ptgs;
|
Ptg[] ptgs;
|
||||||
FormulaParser fp;
|
FormulaParser fp;
|
||||||
fp = new FormulaParser("2+ sum( 3 , 4) ;");
|
fp = new FormulaParser("2+ sum( 3 , 4) ;",null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
ptgs = fp.getRPNPtg();
|
ptgs = fp.getRPNPtg();
|
||||||
assertTrue("five tokens expected, got "+ptgs.length,ptgs.length == 5);
|
assertTrue("five tokens expected, got "+ptgs.length,ptgs.length == 5);
|
||||||
@ -48,7 +48,7 @@ public class TestFormulaParser extends TestCase {
|
|||||||
public void testFormulaWithSpaceNRef() {
|
public void testFormulaWithSpaceNRef() {
|
||||||
Ptg[] ptgs;
|
Ptg[] ptgs;
|
||||||
FormulaParser fp;
|
FormulaParser fp;
|
||||||
fp = new FormulaParser("sum( A2:A3 );");
|
fp = new FormulaParser("sum( A2:A3 );",null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
ptgs = fp.getRPNPtg();
|
ptgs = fp.getRPNPtg();
|
||||||
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
|
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
|
||||||
@ -57,7 +57,7 @@ public class TestFormulaParser extends TestCase {
|
|||||||
public void testFormulaWithString() {
|
public void testFormulaWithString() {
|
||||||
Ptg[] ptgs;
|
Ptg[] ptgs;
|
||||||
FormulaParser fp;
|
FormulaParser fp;
|
||||||
fp = new FormulaParser("\"hello\" & \"world\" ;");
|
fp = new FormulaParser("\"hello\" & \"world\" ;",null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
ptgs = fp.getRPNPtg();
|
ptgs = fp.getRPNPtg();
|
||||||
assertTrue("three token expected, got " + ptgs.length, ptgs.length == 3);
|
assertTrue("three token expected, got " + ptgs.length, ptgs.length == 3);
|
||||||
|
@ -751,6 +751,42 @@ extends TestCase {
|
|||||||
in.close();
|
in.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSheetFunctions()
|
||||||
|
throws java.io.IOException
|
||||||
|
{
|
||||||
|
String filename = System.getProperty("HSSF.testdata.path");
|
||||||
|
|
||||||
|
File file = File.createTempFile("testSheetFormula",".xls");
|
||||||
|
FileOutputStream out = new FileOutputStream(file);
|
||||||
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
HSSFSheet s = wb.createSheet("A");
|
||||||
|
HSSFRow r = null;
|
||||||
|
HSSFCell c = null;
|
||||||
|
r = s.createRow((short)0);
|
||||||
|
c = r.createCell((short)0);c.setCellValue(1);
|
||||||
|
c = r.createCell((short)1);c.setCellValue(2);
|
||||||
|
|
||||||
|
s = wb.createSheet("B");
|
||||||
|
r = s.createRow((short)0);
|
||||||
|
c=r.createCell((short)0); c.setCellFormula("AVERAGE(A!A1:B1)");
|
||||||
|
c=r.createCell((short)1); c.setCellFormula("A!A1+A!B1");
|
||||||
|
c=r.createCell((short)2); c.setCellFormula("C!A1+C!B1");
|
||||||
|
wb.write(out);
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
assertTrue("file exists",file.exists());
|
||||||
|
|
||||||
|
FileInputStream in = new FileInputStream(file);
|
||||||
|
wb = new HSSFWorkbook(in);
|
||||||
|
s = wb.getSheet("B");
|
||||||
|
r = s.getRow(0);
|
||||||
|
c = r.getCell((short)0);
|
||||||
|
//assertTrue("expected: AVERAGE(A!A1:B1) got: "+c.getCellFormula(), ("AVERAGE(A!A1:B1)").equals(c.getCellFormula()));
|
||||||
|
c = r.getCell((short)1);
|
||||||
|
//assertTrue("expected: A!A1+A!B1 got: "+c.getCellFormula(), ("A!A1+A!B1").equals(c.getCellFormula()));
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
|
||||||
public void testRVAoperands() throws Exception {
|
public void testRVAoperands() throws Exception {
|
||||||
File file = File.createTempFile("testFormulaRVA",".xls");
|
File file = File.createTempFile("testFormulaRVA",".xls");
|
||||||
FileOutputStream out = new FileOutputStream(file);
|
FileOutputStream out = new FileOutputStream(file);
|
||||||
|
Loading…
Reference in New Issue
Block a user