Fix from bug #43510 - support named ranges in formulas
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@610016 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a4ae0c47c7
commit
b67b9cb0ce
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.0.2-FINAL" date="2008-??-??">
|
<release version="3.0.2-FINAL" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">43510 - Add support for named ranges in formulas</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">43937 - Add support for hiding and un-hiding sheets, and checking their current hidden status</action>
|
<action dev="POI-DEVELOPERS" type="add">43937 - Add support for hiding and un-hiding sheets, and checking their current hidden status</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">44167 - Fix for non-contiguous named ranges</action>
|
<action dev="POI-DEVELOPERS" type="fix">44167 - Fix for non-contiguous named ranges</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">44070 - Fix for shifting comments when shifting rows</action>
|
<action dev="POI-DEVELOPERS" type="fix">44070 - Fix for shifting comments when shifting rows</action>
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
<!-- Don't forget to update changes.xml too! -->
|
<!-- Don't forget to update changes.xml too! -->
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.0.2-FINAL" date="2008-??-??">
|
<release version="3.0.2-FINAL" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">43510 - Add support for named ranges in formulas</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">43937 - Add support for hiding and un-hiding sheets, and checking their current hidden status</action>
|
<action dev="POI-DEVELOPERS" type="add">43937 - Add support for hiding and un-hiding sheets, and checking their current hidden status</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">44167 - Fix for non-contiguous named ranges</action>
|
<action dev="POI-DEVELOPERS" type="fix">44167 - Fix for non-contiguous named ranges</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">44070 - Fix for shifting comments when shifting rows</action>
|
<action dev="POI-DEVELOPERS" type="fix">44070 - Fix for shifting comments when shifting rows</action>
|
||||||
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
//import PTG's .. since we need everything, import *
|
//import PTG's .. since we need everything, import *
|
||||||
import org.apache.poi.hssf.record.formula.*;
|
import org.apache.poi.hssf.record.formula.*;
|
||||||
@ -66,6 +67,12 @@ public class FormulaParser {
|
|||||||
*/
|
*/
|
||||||
private List functionTokens = new LinkedList();
|
private List functionTokens = new LinkedList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for spotting if we have a cell reference,
|
||||||
|
* or a named range
|
||||||
|
*/
|
||||||
|
private final static Pattern CELL_REFERENCE_PATTERN = Pattern.compile("(?:('?)[^:\\\\/\\?\\*\\[\\]]+\\1!)?\\$?[A-Za-z]+\\$?[\\d]+");
|
||||||
|
|
||||||
private static char TAB = '\t';
|
private static char TAB = '\t';
|
||||||
private static char CR = '\n';
|
private static char CR = '\n';
|
||||||
|
|
||||||
@ -306,15 +313,27 @@ public class FormulaParser {
|
|||||||
tokens.add(new Ref3DPtg(first,externIdx));
|
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??
|
// Try to spot which it is
|
||||||
|
boolean cellRef = CELL_REFERENCE_PATTERN.matcher(name).matches();
|
||||||
boolean boolLit = (name.equals("TRUE") || name.equals("FALSE"));
|
boolean boolLit = (name.equals("TRUE") || name.equals("FALSE"));
|
||||||
|
|
||||||
if (boolLit) {
|
if (boolLit) {
|
||||||
tokens.add(new BoolPtg(name));
|
tokens.add(new BoolPtg(name));
|
||||||
} else if (cellRef) {
|
} else if (cellRef) {
|
||||||
tokens.add(new ReferencePtg(name));
|
tokens.add(new ReferencePtg(name));
|
||||||
} else {
|
} else {
|
||||||
//handle after named range is integrated!!
|
boolean nameRecordExists = false;
|
||||||
|
for(int i = 0; i < book.getNumNames(); i++) {
|
||||||
|
// Our formula will by now contain an upper-cased
|
||||||
|
// version of any named range names
|
||||||
|
if(book.getNameRecord(i).getNameText().toUpperCase().equals(name)) {
|
||||||
|
nameRecordExists = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!nameRecordExists)
|
||||||
|
Abort("Found reference to named range \"" + name + "\", but that named range wasn't defined!");
|
||||||
|
tokens.add(new NamePtg(name, book));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,8 @@ import org.apache.poi.hssf.record.formula.StringPtg;
|
|||||||
import org.apache.poi.hssf.record.formula.UnaryMinusPtg;
|
import org.apache.poi.hssf.record.formula.UnaryMinusPtg;
|
||||||
import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
|
import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFName;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
@ -350,6 +352,38 @@ public class TestFormulaParser extends TestCase {
|
|||||||
assertTrue("ptg0 contains exact value", ((StringPtg)ptg[0]).getValue().equals(value));
|
assertTrue("ptg0 contains exact value", ((StringPtg)ptg[0]).getValue().equals(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testWithNamedRange() throws Exception {
|
||||||
|
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||||
|
FormulaParser fp;
|
||||||
|
Ptg[] ptgs;
|
||||||
|
|
||||||
|
HSSFSheet s = workbook.createSheet("Foo");
|
||||||
|
s.createRow(0).createCell((short)0).setCellValue(1.1);
|
||||||
|
s.createRow(1).createCell((short)0).setCellValue(2.3);
|
||||||
|
s.createRow(2).createCell((short)2).setCellValue(3.1);
|
||||||
|
|
||||||
|
HSSFName name = workbook.createName();
|
||||||
|
name.setNameName("testName");
|
||||||
|
name.setReference("A1:A2");
|
||||||
|
|
||||||
|
fp = HSSFFormulaEvaluator.getUnderlyingParser(workbook, "SUM(testName)");
|
||||||
|
fp.parse();
|
||||||
|
ptgs = fp.getRPNPtg();
|
||||||
|
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
|
||||||
|
assertEquals(NamePtg.class, ptgs[0].getClass());
|
||||||
|
assertEquals(FuncVarPtg.class, ptgs[1].getClass());
|
||||||
|
|
||||||
|
// Now make it a single cell
|
||||||
|
name.setReference("C3");
|
||||||
|
|
||||||
|
fp = HSSFFormulaEvaluator.getUnderlyingParser(workbook, "SUM(testName)");
|
||||||
|
fp.parse();
|
||||||
|
ptgs = fp.getRPNPtg();
|
||||||
|
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
|
||||||
|
assertEquals(NamePtg.class, ptgs[0].getClass());
|
||||||
|
assertEquals(FuncVarPtg.class, ptgs[1].getClass());
|
||||||
|
}
|
||||||
|
|
||||||
public void testLookupAndMatchFunctionArgs()
|
public void testLookupAndMatchFunctionArgs()
|
||||||
{
|
{
|
||||||
FormulaParser fp = new FormulaParser("lookup(A1, A3:A52, B3:B52)", null);
|
FormulaParser fp = new FormulaParser("lookup(A1, A3:A52, B3:B52)", null);
|
||||||
|
Loading…
Reference in New Issue
Block a user