mirror of https://github.com/apache/poi.git
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
3e8eeb5a3d
commit
89200f48f9
|
@ -743,7 +743,7 @@ public class Sheet
|
|||
rec.setOptions(( short ) 2);
|
||||
rec.setValue(0);
|
||||
rec.setXFIndex(( short ) 0x0f);
|
||||
FormulaParser fp = new FormulaParser(formula);
|
||||
FormulaParser fp = new FormulaParser(formula,null); //fix - do we need this method?
|
||||
fp.parse();
|
||||
Ptg[] ptg = fp.getRPNPtg();
|
||||
int size = 0;
|
||||
|
|
|
@ -57,6 +57,7 @@ package org.apache.poi.hssf.record.formula;
|
|||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.hssf.util.RangeAddress;
|
||||
import org.apache.poi.hssf.util.AreaReference;
|
||||
|
||||
/**
|
||||
* Title: Area 3D Ptg - 3D referecnce (Sheet + Area)<P>
|
||||
|
@ -77,11 +78,22 @@ public class Area3DPtg extends Ptg
|
|||
private short field_5_last_column;
|
||||
|
||||
/** 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)
|
||||
{
|
||||
offset++;
|
||||
|
@ -113,7 +125,7 @@ public class Area3DPtg extends Ptg
|
|||
|
||||
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, 3 + offset , getFirstRow());
|
||||
LittleEndian.putShort(array, 5 + offset , getLastRow());
|
||||
|
|
|
@ -63,6 +63,8 @@ import java.util.Stack;
|
|||
import java.io.FileOutputStream;
|
||||
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.
|
||||
|
@ -98,6 +100,8 @@ public class FormulaParser {
|
|||
|
||||
private char Look; // Lookahead Character
|
||||
|
||||
private Workbook book;
|
||||
|
||||
|
||||
/** create the parser with the string that is to be parsed
|
||||
* 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
|
||||
* 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;
|
||||
pointer=0;
|
||||
this.book = book;
|
||||
}
|
||||
|
||||
|
||||
|
@ -130,7 +135,7 @@ public class FormulaParser {
|
|||
private void Abort(String s) {
|
||||
Error(s);
|
||||
//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();;
|
||||
}
|
||||
|
||||
/** Parse and Translate a Identifier */
|
||||
/** Parse and Translate a String Identifier */
|
||||
private void Ident() {
|
||||
String name;
|
||||
name = GetName();
|
||||
if (Look == '('){
|
||||
//This is a function
|
||||
Match('(');
|
||||
int numArgs = Arguments();
|
||||
Match(')');
|
||||
//this is the end of the function
|
||||
tokens.add(function(name,(byte)numArgs));
|
||||
function(name);
|
||||
} else if (Look == ':') { // this is a AreaReference
|
||||
String first = name;
|
||||
Match(':');
|
||||
String second = GetName();
|
||||
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 {
|
||||
//this can be either a cell ref or a named range !!
|
||||
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;
|
||||
retval = new FuncVarPtg(name,numArgs);
|
||||
/** 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.hssf.util.RangeAddress;
|
||||
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
/**
|
||||
* Title: Reference 3D Ptg <P>
|
||||
* Description: Defined a cell in extern sheet. <P>
|
||||
|
@ -75,9 +75,7 @@ public class Ref3DPtg extends Ptg {
|
|||
private short field_3_column;
|
||||
|
||||
/** Creates new AreaPtg */
|
||||
|
||||
public Ref3DPtg() {
|
||||
}
|
||||
public Ref3DPtg() {}
|
||||
|
||||
public Ref3DPtg(byte[] data, int offset) {
|
||||
offset++;
|
||||
|
@ -86,6 +84,15 @@ public class Ref3DPtg extends Ptg {
|
|||
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() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
|
@ -100,7 +107,7 @@ public class Ref3DPtg extends Ptg {
|
|||
}
|
||||
|
||||
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, 3 + offset , getRow());
|
||||
LittleEndian.putShort(array, 5 + offset , getColumnRaw());
|
||||
|
|
|
@ -701,7 +701,7 @@ public class HSSFCell
|
|||
rec.setOptions(( short ) 2);
|
||||
rec.setValue(0);
|
||||
rec.setXFIndex(( short ) 0x0f);
|
||||
FormulaParser fp = new FormulaParser(formula+";");
|
||||
FormulaParser fp = new FormulaParser(formula+";",book);
|
||||
fp.parse();
|
||||
Ptg[] ptg = fp.getRPNPtg();
|
||||
int size = 0;
|
||||
|
|
|
@ -20,13 +20,13 @@ public class TestFormulaParser extends TestCase {
|
|||
}
|
||||
|
||||
public void testSimpleFormula() {
|
||||
FormulaParser fp = new FormulaParser("2+2;");
|
||||
FormulaParser fp = new FormulaParser("2+2;",null);
|
||||
fp.parse();
|
||||
Ptg[] ptgs = fp.getRPNPtg();
|
||||
assertTrue("three tokens expected, got "+ptgs.length,ptgs.length == 3);
|
||||
}
|
||||
public void testFormulaWithSpace1() {
|
||||
FormulaParser fp = new FormulaParser(" 2 + 2 ;");
|
||||
FormulaParser fp = new FormulaParser(" 2 + 2 ;",null);
|
||||
fp.parse();
|
||||
Ptg[] ptgs = fp.getRPNPtg();
|
||||
assertTrue("three tokens expected, got "+ptgs.length,ptgs.length == 3);
|
||||
|
@ -39,7 +39,7 @@ public class TestFormulaParser extends TestCase {
|
|||
public void testFormulaWithSpace2() {
|
||||
Ptg[] ptgs;
|
||||
FormulaParser fp;
|
||||
fp = new FormulaParser("2+ sum( 3 , 4) ;");
|
||||
fp = new FormulaParser("2+ sum( 3 , 4) ;",null);
|
||||
fp.parse();
|
||||
ptgs = fp.getRPNPtg();
|
||||
assertTrue("five tokens expected, got "+ptgs.length,ptgs.length == 5);
|
||||
|
@ -48,7 +48,7 @@ public class TestFormulaParser extends TestCase {
|
|||
public void testFormulaWithSpaceNRef() {
|
||||
Ptg[] ptgs;
|
||||
FormulaParser fp;
|
||||
fp = new FormulaParser("sum( A2:A3 );");
|
||||
fp = new FormulaParser("sum( A2:A3 );",null);
|
||||
fp.parse();
|
||||
ptgs = fp.getRPNPtg();
|
||||
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
|
||||
|
@ -57,7 +57,7 @@ public class TestFormulaParser extends TestCase {
|
|||
public void testFormulaWithString() {
|
||||
Ptg[] ptgs;
|
||||
FormulaParser fp;
|
||||
fp = new FormulaParser("\"hello\" & \"world\" ;");
|
||||
fp = new FormulaParser("\"hello\" & \"world\" ;",null);
|
||||
fp.parse();
|
||||
ptgs = fp.getRPNPtg();
|
||||
assertTrue("three token expected, got " + ptgs.length, ptgs.length == 3);
|
||||
|
|
|
@ -751,6 +751,42 @@ extends TestCase {
|
|||
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 {
|
||||
File file = File.createTempFile("testFormulaRVA",".xls");
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
|
|
Loading…
Reference in New Issue