fixed formula parser to correctly resolve sheet-level names
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@729028 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
98121b7691
commit
177533e23b
@ -37,6 +37,7 @@
|
||||
|
||||
<!-- Don't forget to update status.xml too! -->
|
||||
<release version="3.5-beta5" date="2008-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">fixed formula parser to correctly resolve sheet-level names</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">46433 - support for shared formulas in XSSF</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">46299 - support for carriage return and line break in XWPFRun</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">46300 - support for line spacing in XWPFParagraph</action>
|
||||
|
@ -34,6 +34,7 @@
|
||||
<!-- Don't forget to update changes.xml too! -->
|
||||
<changes>
|
||||
<release version="3.5-beta5" date="2008-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">fixed formula parser to correctly resolve sheet-level names</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">46433 - support for shared formulas in XSSF</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">46299 - support for carriage return and line break in XWPFRun</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">46300 - support for line spacing in XWPFParagraph</action>
|
||||
|
@ -44,7 +44,7 @@ public final class HSSFFormulaParser {
|
||||
* Convenience method for parsing cell formulas. see {@link #parse(String, HSSFWorkbook, int)}
|
||||
*/
|
||||
public static Ptg[] parse(String formula, HSSFWorkbook workbook) {
|
||||
return FormulaParser.parse(formula, createParsingWorkbook(workbook));
|
||||
return parse(formula, workbook, FormulaType.CELL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,7 +52,21 @@ public final class HSSFFormulaParser {
|
||||
* @return the parsed formula tokens
|
||||
*/
|
||||
public static Ptg[] parse(String formula, HSSFWorkbook workbook, int formulaType) {
|
||||
return FormulaParser.parse(formula, createParsingWorkbook(workbook), formulaType);
|
||||
return parse(formula, workbook, formulaType, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param formula the formula to parse
|
||||
* @param workbook the parent workbook
|
||||
* @param formulaType a constant from {@link FormulaType}
|
||||
* @param sheetIndex the 0-based index of the sheet this formula belongs to.
|
||||
* The sheet index is required to resolve sheet-level names. <code>-1</code> means that
|
||||
* the scope of the name will be ignored and the parser will match named ranges only by name
|
||||
*
|
||||
* @return the parsed formula tokens
|
||||
*/
|
||||
public static Ptg[] parse(String formula, HSSFWorkbook workbook, int formulaType, int sheetIndex) {
|
||||
return FormulaParser.parse(formula, createParsingWorkbook(workbook), formulaType, sheetIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,9 @@ import org.apache.poi.hssf.record.cf.FontFormatting;
|
||||
import org.apache.poi.hssf.record.cf.PatternFormatting;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.ss.formula.Formula;
|
||||
import org.apache.poi.ss.formula.FormulaType;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
@ -132,18 +134,18 @@ public final class CFRuleRecord extends StandardRecord {
|
||||
/**
|
||||
* Creates a new comparison operation rule
|
||||
*/
|
||||
public static CFRuleRecord create(HSSFWorkbook workbook, String formulaText) {
|
||||
Ptg[] formula1 = parseFormula(formulaText, workbook);
|
||||
public static CFRuleRecord create(HSSFSheet sheet, String formulaText) {
|
||||
Ptg[] formula1 = parseFormula(formulaText, sheet);
|
||||
return new CFRuleRecord(CONDITION_TYPE_FORMULA, ComparisonOperator.NO_COMPARISON,
|
||||
formula1, null);
|
||||
}
|
||||
/**
|
||||
* Creates a new comparison operation rule
|
||||
*/
|
||||
public static CFRuleRecord create(HSSFWorkbook workbook, byte comparisonOperation,
|
||||
public static CFRuleRecord create(HSSFSheet sheet, byte comparisonOperation,
|
||||
String formulaText1, String formulaText2) {
|
||||
Ptg[] formula1 = parseFormula(formulaText1, workbook);
|
||||
Ptg[] formula2 = parseFormula(formulaText2, workbook);
|
||||
Ptg[] formula1 = parseFormula(formulaText1, sheet);
|
||||
Ptg[] formula2 = parseFormula(formulaText2, sheet);
|
||||
return new CFRuleRecord(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, formula1, formula2);
|
||||
}
|
||||
|
||||
@ -527,10 +529,11 @@ public final class CFRuleRecord extends StandardRecord {
|
||||
*
|
||||
* @return <code>null</code> if <tt>formula</tt> was null.
|
||||
*/
|
||||
private static Ptg[] parseFormula(String formula, HSSFWorkbook workbook) {
|
||||
private static Ptg[] parseFormula(String formula, HSSFSheet sheet) {
|
||||
if(formula == null) {
|
||||
return null;
|
||||
}
|
||||
return HSSFFormulaParser.parse(formula, workbook);
|
||||
int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet);
|
||||
return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import org.apache.poi.hssf.model.HSSFFormulaParser;
|
||||
import org.apache.poi.hssf.record.formula.NumberPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.StringPtg;
|
||||
import org.apache.poi.ss.formula.FormulaParser;
|
||||
import org.apache.poi.ss.formula.FormulaType;
|
||||
|
||||
/**
|
||||
@ -324,24 +323,25 @@ public class DVConstraint {
|
||||
/**
|
||||
* @return both parsed formulas (for expression 1 and 2).
|
||||
*/
|
||||
/* package */ FormulaPair createFormulas(HSSFWorkbook workbook) {
|
||||
/* package */ FormulaPair createFormulas(HSSFSheet sheet) {
|
||||
Ptg[] formula1;
|
||||
Ptg[] formula2;
|
||||
if (isListValidationType()) {
|
||||
formula1 = createListFormula(workbook);
|
||||
formula1 = createListFormula(sheet);
|
||||
formula2 = Ptg.EMPTY_PTG_ARRAY;
|
||||
} else {
|
||||
formula1 = convertDoubleFormula(_formula1, _value1, workbook);
|
||||
formula2 = convertDoubleFormula(_formula2, _value2, workbook);
|
||||
formula1 = convertDoubleFormula(_formula1, _value1, sheet);
|
||||
formula2 = convertDoubleFormula(_formula2, _value2, sheet);
|
||||
}
|
||||
return new FormulaPair(formula1, formula2);
|
||||
}
|
||||
|
||||
private Ptg[] createListFormula(HSSFWorkbook workbook) {
|
||||
private Ptg[] createListFormula(HSSFSheet sheet) {
|
||||
|
||||
if (_explicitListValues == null) {
|
||||
HSSFWorkbook wb = sheet.getWorkbook();
|
||||
// formula is parsed with slightly different RVA rules: (root node type must be 'reference')
|
||||
return HSSFFormulaParser.parse(_formula1, workbook, FormulaType.DATAVALIDATION_LIST);
|
||||
return HSSFFormulaParser.parse(_formula1, wb, FormulaType.DATAVALIDATION_LIST, wb.getSheetIndex(sheet));
|
||||
// To do: Excel places restrictions on the available operations within a list formula.
|
||||
// Some things like union and intersection are not allowed.
|
||||
}
|
||||
@ -361,7 +361,7 @@ public class DVConstraint {
|
||||
* @return The parsed token array representing the formula or value specified.
|
||||
* Empty array if both formula and value are <code>null</code>
|
||||
*/
|
||||
private static Ptg[] convertDoubleFormula(String formula, Double value, HSSFWorkbook workbook) {
|
||||
private static Ptg[] convertDoubleFormula(String formula, Double value, HSSFSheet sheet) {
|
||||
if (formula == null) {
|
||||
if (value == null) {
|
||||
return Ptg.EMPTY_PTG_ARRAY;
|
||||
@ -371,7 +371,8 @@ public class DVConstraint {
|
||||
if (value != null) {
|
||||
throw new IllegalStateException("Both formula and value cannot be present");
|
||||
}
|
||||
return HSSFFormulaParser.parse(formula, workbook);
|
||||
HSSFWorkbook wb = sheet.getWorkbook();
|
||||
return HSSFFormulaParser.parse(formula, wb, FormulaType.CELL, wb.getSheetIndex(sheet));
|
||||
}
|
||||
|
||||
|
||||
|
@ -54,6 +54,7 @@ import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.Comment;
|
||||
import org.apache.poi.ss.usermodel.Hyperlink;
|
||||
import org.apache.poi.ss.usermodel.RichTextString;
|
||||
import org.apache.poi.ss.formula.FormulaType;
|
||||
|
||||
/**
|
||||
* High level representation of a cell in a row of a spreadsheet.
|
||||
@ -594,7 +595,8 @@ public class HSSFCell implements Cell {
|
||||
setCellType(CELL_TYPE_BLANK, false, row, col, styleIndex);
|
||||
return;
|
||||
}
|
||||
Ptg[] ptgs = HSSFFormulaParser.parse(formula, book);
|
||||
int sheetIndex = book.getSheetIndex(sheet);
|
||||
Ptg[] ptgs = HSSFFormulaParser.parse(formula, book, FormulaType.CELL, sheetIndex);
|
||||
setCellType(CELL_TYPE_FORMULA, false, row, col, styleIndex);
|
||||
FormulaRecordAggregate agg = (FormulaRecordAggregate) record;
|
||||
FormulaRecord frec = agg.getFormulaRecord();
|
||||
|
@ -219,9 +219,9 @@ public final class HSSFDataValidation {
|
||||
return _error_text;
|
||||
}
|
||||
|
||||
public DVRecord createDVRecord(HSSFWorkbook workbook) {
|
||||
public DVRecord createDVRecord(HSSFSheet sheet) {
|
||||
|
||||
FormulaPair fp = _constraint.createFormulas(workbook);
|
||||
FormulaPair fp = _constraint.createFormulas(sheet);
|
||||
|
||||
return new DVRecord(_constraint.getValidationType(),
|
||||
_constraint.getOperator(),
|
||||
|
@ -24,12 +24,7 @@ import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.ss.formula.EvaluationCell;
|
||||
import org.apache.poi.ss.formula.EvaluationName;
|
||||
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||
import org.apache.poi.ss.formula.FormulaParsingWorkbook;
|
||||
import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
|
||||
import org.apache.poi.ss.formula.*;
|
||||
|
||||
/**
|
||||
* Internal POI use only
|
||||
@ -65,14 +60,21 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||
return _iBook.getNameXPtg(name);
|
||||
}
|
||||
|
||||
public EvaluationName getName(String name) {
|
||||
/**
|
||||
* Lookup a named range by its name.
|
||||
*
|
||||
* @param name the name to search
|
||||
* @param sheetIndex the 0-based index of the sheet this formula belongs to.
|
||||
* The sheet index is required to resolve sheet-level names. <code>-1</code> means workbook-global names
|
||||
*/
|
||||
public EvaluationName getName(String name, int sheetIndex) {
|
||||
for(int i=0; i < _iBook.getNumNames(); i++) {
|
||||
NameRecord nr = _iBook.getNameRecord(i);
|
||||
if (name.equalsIgnoreCase(nr.getNameText())) {
|
||||
if (nr.getSheetNumber() == sheetIndex+1 && name.equalsIgnoreCase(nr.getNameText())) {
|
||||
return new Name(nr, i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return sheetIndex == -1 ? null : getName(name, -1);
|
||||
}
|
||||
|
||||
public int getSheetIndex(EvaluationSheet evalSheet) {
|
||||
@ -118,7 +120,7 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||
// re-parsing the formula text also works, but is a waste of time
|
||||
// It is useful from time to time to run all unit tests with this code
|
||||
// to make sure that all formulas POI can evaluate can also be parsed.
|
||||
return HSSFFormulaParser.parse(cell.getCellFormula(), _uBook);
|
||||
return HSSFFormulaParser.parse(cell.getCellFormula(), _uBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()));
|
||||
}
|
||||
FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
|
||||
return fra.getFormulaTokens();
|
||||
|
@ -163,7 +163,7 @@ public final class HSSFName implements Name {
|
||||
* @throws IllegalArgumentException if the specified reference is unparsable
|
||||
*/
|
||||
public void setRefersToFormula(String formulaText) {
|
||||
Ptg[] ptgs = HSSFFormulaParser.parse(formulaText, _book, FormulaType.NAMEDRANGE);
|
||||
Ptg[] ptgs = HSSFFormulaParser.parse(formulaText, _book, FormulaType.NAMEDRANGE, getSheetIndex());
|
||||
_definedNameRec.setNameDefinition(ptgs);
|
||||
}
|
||||
|
||||
|
@ -367,7 +367,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
|
||||
}
|
||||
DataValidityTable dvt = sheet.getOrCreateDataValidityTable();
|
||||
|
||||
DVRecord dvRecord = dataValidation.createDVRecord(workbook);
|
||||
DVRecord dvRecord = dataValidation.createDVRecord(this);
|
||||
dvt.addDataValidation(dvRecord);
|
||||
}
|
||||
|
||||
@ -1789,6 +1789,6 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
|
||||
}
|
||||
|
||||
public HSSFSheetConditionalFormatting getSheetConditionalFormatting() {
|
||||
return new HSSFSheetConditionalFormatting(workbook, sheet);
|
||||
return new HSSFSheetConditionalFormatting(this);
|
||||
}
|
||||
}
|
||||
|
@ -31,12 +31,12 @@ import org.apache.poi.ss.util.CellRangeAddress;
|
||||
*/
|
||||
public final class HSSFSheetConditionalFormatting {
|
||||
|
||||
private final HSSFWorkbook _workbook;
|
||||
private final HSSFSheet _sheet;
|
||||
private final ConditionalFormattingTable _conditionalFormattingTable;
|
||||
|
||||
/* package */ HSSFSheetConditionalFormatting(HSSFWorkbook workbook, Sheet sheet) {
|
||||
_workbook = workbook;
|
||||
_conditionalFormattingTable = sheet.getConditionalFormattingTable();
|
||||
/* package */ HSSFSheetConditionalFormatting(HSSFSheet sheet) {
|
||||
_sheet = sheet;
|
||||
_conditionalFormattingTable = sheet.getSheet().getConditionalFormattingTable();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,8 +67,8 @@ public final class HSSFSheetConditionalFormatting {
|
||||
String formula1,
|
||||
String formula2) {
|
||||
|
||||
HSSFWorkbook wb = _workbook;
|
||||
CFRuleRecord rr = CFRuleRecord.create(wb, comparisonOperation, formula1, formula2);
|
||||
HSSFWorkbook wb = _sheet.getWorkbook();
|
||||
CFRuleRecord rr = CFRuleRecord.create(_sheet, comparisonOperation, formula1, formula2);
|
||||
return new HSSFConditionalFormattingRule(wb, rr);
|
||||
}
|
||||
|
||||
@ -80,8 +80,8 @@ public final class HSSFSheetConditionalFormatting {
|
||||
* @param formula - formula for the valued, compared with the cell
|
||||
*/
|
||||
public HSSFConditionalFormattingRule createConditionalFormattingRule(String formula) {
|
||||
HSSFWorkbook wb = _workbook;
|
||||
CFRuleRecord rr = CFRuleRecord.create(wb, formula);
|
||||
HSSFWorkbook wb = _sheet.getWorkbook();
|
||||
CFRuleRecord rr = CFRuleRecord.create(_sheet, formula);
|
||||
return new HSSFConditionalFormattingRule(wb, rr);
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ public final class HSSFSheetConditionalFormatting {
|
||||
if (cf == null) {
|
||||
return null;
|
||||
}
|
||||
return new HSSFConditionalFormatting(_workbook, cf);
|
||||
return new HSSFConditionalFormatting(_sheet.getWorkbook(), cf);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,6 +66,7 @@ import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.ss.usermodel.CreationHelper;
|
||||
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
|
||||
import org.apache.poi.ss.formula.FormulaType;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
@ -1381,7 +1382,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
||||
sb.append("!");
|
||||
sb.append(parts[i]);
|
||||
}
|
||||
name.setNameDefinition(HSSFFormulaParser.parse(sb.toString(), this));
|
||||
name.setNameDefinition(HSSFFormulaParser.parse(sb.toString(), this, FormulaType.CELL, sheetIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -142,6 +142,7 @@ public final class FormulaParser {
|
||||
|
||||
private FormulaParsingWorkbook _book;
|
||||
|
||||
private int _sheetIndex;
|
||||
|
||||
|
||||
/**
|
||||
@ -156,11 +157,12 @@ public final class FormulaParser {
|
||||
* model.Workbook, then use the convenience method on
|
||||
* usermodel.HSSFFormulaEvaluator
|
||||
*/
|
||||
private FormulaParser(String formula, FormulaParsingWorkbook book){
|
||||
private FormulaParser(String formula, FormulaParsingWorkbook book, int sheetIndex){
|
||||
_formulaString = formula;
|
||||
_pointer=0;
|
||||
_book = book;
|
||||
_formulaLength = _formulaString.length();
|
||||
_sheetIndex = sheetIndex;
|
||||
}
|
||||
|
||||
public static Ptg[] parse(String formula, FormulaParsingWorkbook book) {
|
||||
@ -168,7 +170,24 @@ public final class FormulaParser {
|
||||
}
|
||||
|
||||
public static Ptg[] parse(String formula, FormulaParsingWorkbook workbook, int formulaType) {
|
||||
FormulaParser fp = new FormulaParser(formula, workbook);
|
||||
return parse(formula, workbook, formulaType, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a formula into a array of tokens
|
||||
*
|
||||
* @param formula the formula to parse
|
||||
* @param workbook the parent workbook
|
||||
* @param formulaType the type of the formula, see {@link FormulaType}
|
||||
* @param sheetIndex the 0-based index of the sheet this formula belongs to.
|
||||
* The sheet index is required to resolve sheet-level names. <code>-1</code> means that
|
||||
* the scope of the name will be ignored and the parser will match names only by name
|
||||
*
|
||||
* @return array of parsed tokens
|
||||
* @throws FormulaParseException if the formula is unparsable
|
||||
*/
|
||||
public static Ptg[] parse(String formula, FormulaParsingWorkbook workbook, int formulaType, int sheetIndex) {
|
||||
FormulaParser fp = new FormulaParser(formula, workbook, sheetIndex);
|
||||
fp.parse();
|
||||
return fp.getRPNPtg(formulaType);
|
||||
}
|
||||
@ -413,7 +432,7 @@ public final class FormulaParser {
|
||||
new FormulaParseException("Name '" + name
|
||||
+ "' does not look like a cell reference or named range");
|
||||
}
|
||||
EvaluationName evalName = _book.getName(name);
|
||||
EvaluationName evalName = _book.getName(name, _sheetIndex);
|
||||
if (evalName == null) {
|
||||
throw new FormulaParseException("Specified named range '"
|
||||
+ name + "' does not exist in the current workbook.");
|
||||
@ -516,7 +535,7 @@ public final class FormulaParser {
|
||||
// user defined function
|
||||
// in the token tree, the name is more or less the first argument
|
||||
|
||||
EvaluationName hName = _book.getName(name);
|
||||
EvaluationName hName = _book.getName(name, _sheetIndex);
|
||||
if (hName == null) {
|
||||
|
||||
nameToken = _book.getNameXPtg(name);
|
||||
|
@ -30,7 +30,7 @@ public interface FormulaParsingWorkbook {
|
||||
/**
|
||||
* named range name matching is case insensitive
|
||||
*/
|
||||
EvaluationName getName(String name);
|
||||
EvaluationName getName(String name, int sheetIndex);
|
||||
|
||||
NameXPtg getNameXPtg(String name);
|
||||
|
||||
|
@ -347,8 +347,9 @@ public final class XSSFCell implements Cell {
|
||||
throw new IllegalStateException("Shared Formula not found for group index " + idx);
|
||||
}
|
||||
String sharedFormula = sfCell.getCTCell().getF().getStringValue();
|
||||
int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet);
|
||||
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(sheet.getWorkbook());
|
||||
Ptg[] ptgs = FormulaParser.parse(sharedFormula, fpb);
|
||||
Ptg[] ptgs = FormulaParser.parse(sharedFormula, fpb, FormulaType.CELL, sheetIndex);
|
||||
Ptg[] fmla = SharedFormulaRecord.convertSharedFormulas(ptgs,
|
||||
getRowIndex() - sfCell.getRowIndex(), getColumnIndex() - sfCell.getColumnIndex());
|
||||
return FormulaRenderer.toFormulaString(fpb, fmla);
|
||||
@ -371,9 +372,10 @@ public final class XSSFCell implements Cell {
|
||||
return;
|
||||
}
|
||||
|
||||
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(row.getSheet().getWorkbook());
|
||||
XSSFWorkbook wb = row.getSheet().getWorkbook();
|
||||
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
|
||||
try {
|
||||
Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL);
|
||||
Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, wb.getSheetIndex(getSheet()));
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getClass().getName().startsWith(FormulaParser.class.getName())) {
|
||||
throw new IllegalArgumentException("Unparsable formula '" + formula + "'", e);
|
||||
|
@ -20,13 +20,7 @@ package org.apache.poi.xssf.usermodel;
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.ss.formula.EvaluationCell;
|
||||
import org.apache.poi.ss.formula.EvaluationName;
|
||||
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||
import org.apache.poi.ss.formula.FormulaParser;
|
||||
import org.apache.poi.ss.formula.FormulaParsingWorkbook;
|
||||
import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
|
||||
import org.apache.poi.ss.formula.*;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
||||
|
||||
/**
|
||||
@ -73,14 +67,15 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||
return convertToExternalSheetIndex(sheetIndex);
|
||||
}
|
||||
|
||||
public EvaluationName getName(String name) {
|
||||
public EvaluationName getName(String name, int sheetIndex) {
|
||||
for(int i=0; i < _uBook.getNumberOfNames(); i++) {
|
||||
String nameText = _uBook.getNameAt(i).getNameName();
|
||||
if (name.equalsIgnoreCase(nameText)) {
|
||||
XSSFName nm = _uBook.getNameAt(i);
|
||||
String nameText = nm.getNameName();
|
||||
if (name.equalsIgnoreCase(nameText) && nm.getSheetIndex() == sheetIndex) {
|
||||
return new Name(_uBook.getNameAt(i), i, this);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return sheetIndex == -1 ? null : getName(name, -1);
|
||||
}
|
||||
|
||||
public int getSheetIndex(EvaluationSheet evalSheet) {
|
||||
@ -135,7 +130,7 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||
public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
|
||||
XSSFCell cell = ((XSSFEvaluationCell)evalCell).getXSSFCell();
|
||||
XSSFEvaluationWorkbook frBook = XSSFEvaluationWorkbook.create(_uBook);
|
||||
return FormulaParser.parse(cell.getCellFormula(), frBook);
|
||||
return FormulaParser.parse(cell.getCellFormula(), frBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()));
|
||||
}
|
||||
|
||||
private static final class Name implements EvaluationName {
|
||||
@ -152,7 +147,7 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||
|
||||
public Ptg[] getNameDefinition() {
|
||||
|
||||
return FormulaParser.parse(_nameRecord.getRefersToFormula(), _fpBook);
|
||||
return FormulaParser.parse(_nameRecord.getRefersToFormula(), _fpBook, FormulaType.NAMEDRANGE, _nameRecord.getSheetIndex());
|
||||
}
|
||||
|
||||
public String getNameText() {
|
||||
|
@ -199,7 +199,7 @@ public final class XSSFName implements Name {
|
||||
public void setRefersToFormula(String formulaText) {
|
||||
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(workbook);
|
||||
try {
|
||||
Ptg[] ptgs = FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE);
|
||||
Ptg[] ptgs = FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex());
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getClass().getName().startsWith(FormulaParser.class.getName())) {
|
||||
throw new IllegalArgumentException("Unparsable formula '" + formulaText + "'", e);
|
||||
|
@ -121,4 +121,41 @@ public final class TestXSSFFormulaEvaluation extends TestCase {
|
||||
assertEquals("B5", cell.getCellFormula());
|
||||
assertEquals("UniqueDocumentNumberID", evaluator.evaluate(cell).getStringValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creation / evaluation of formulas with sheet-level names
|
||||
*/
|
||||
public void testSheetLevelFormulas(){
|
||||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
|
||||
XSSFRow row;
|
||||
XSSFSheet sh1 = wb.createSheet("Sheet1");
|
||||
XSSFName nm1 = wb.createName();
|
||||
nm1.setNameName("sales_1");
|
||||
nm1.setSheetIndex(0);
|
||||
nm1.setRefersToFormula("Sheet1!$A$1");
|
||||
row = sh1.createRow(0);
|
||||
row.createCell(0).setCellValue(3);
|
||||
row.createCell(1).setCellFormula("sales_1");
|
||||
row.createCell(2).setCellFormula("sales_1*2");
|
||||
|
||||
XSSFSheet sh2 = wb.createSheet("Sheet2");
|
||||
XSSFName nm2 = wb.createName();
|
||||
nm2.setNameName("sales_1");
|
||||
nm2.setSheetIndex(1);
|
||||
nm2.setRefersToFormula("Sheet2!$A$1");
|
||||
|
||||
row = sh2.createRow(0);
|
||||
row.createCell(0).setCellValue(5);
|
||||
row.createCell(1).setCellFormula("sales_1");
|
||||
row.createCell(2).setCellFormula("sales_1*3");
|
||||
|
||||
XSSFFormulaEvaluator evaluator = new XSSFFormulaEvaluator(wb);
|
||||
assertEquals(3.0, evaluator.evaluate(sh1.getRow(0).getCell(1)).getNumberValue());
|
||||
assertEquals(6.0, evaluator.evaluate(sh1.getRow(0).getCell(2)).getNumberValue());
|
||||
|
||||
assertEquals(5.0, evaluator.evaluate(sh2.getRow(0).getCell(1)).getNumberValue());
|
||||
assertEquals(15.0, evaluator.evaluate(sh2.getRow(0).getCell(2)).getNumberValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.RefNPtg;
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.util.HSSFColor;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.ss.formula.Formula;
|
||||
@ -43,20 +44,21 @@ public final class TestCFRuleRecord extends TestCase
|
||||
public void testConstructors ()
|
||||
{
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
|
||||
CFRuleRecord rule1 = CFRuleRecord.create(workbook, "7");
|
||||
CFRuleRecord rule1 = CFRuleRecord.create(sheet, "7");
|
||||
assertEquals(CFRuleRecord.CONDITION_TYPE_FORMULA, rule1.getConditionType());
|
||||
assertEquals(ComparisonOperator.NO_COMPARISON, rule1.getComparisonOperation());
|
||||
assertNotNull(rule1.getParsedExpression1());
|
||||
assertSame(Ptg.EMPTY_PTG_ARRAY, rule1.getParsedExpression2());
|
||||
|
||||
CFRuleRecord rule2 = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "2", "5");
|
||||
CFRuleRecord rule2 = CFRuleRecord.create(sheet, ComparisonOperator.BETWEEN, "2", "5");
|
||||
assertEquals(CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS, rule2.getConditionType());
|
||||
assertEquals(ComparisonOperator.BETWEEN, rule2.getComparisonOperation());
|
||||
assertNotNull(rule2.getParsedExpression1());
|
||||
assertNotNull(rule2.getParsedExpression2());
|
||||
|
||||
CFRuleRecord rule3 = CFRuleRecord.create(workbook, ComparisonOperator.EQUAL, null, null);
|
||||
CFRuleRecord rule3 = CFRuleRecord.create(sheet, ComparisonOperator.EQUAL, null, null);
|
||||
assertEquals(CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS, rule3.getConditionType());
|
||||
assertEquals(ComparisonOperator.EQUAL, rule3.getComparisonOperation());
|
||||
assertSame(Ptg.EMPTY_PTG_ARRAY, rule3.getParsedExpression2());
|
||||
@ -66,7 +68,8 @@ public final class TestCFRuleRecord extends TestCase
|
||||
public void testCreateCFRuleRecord ()
|
||||
{
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
CFRuleRecord record = CFRuleRecord.create(workbook, "7");
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
CFRuleRecord record = CFRuleRecord.create(sheet, "7");
|
||||
testCFRuleRecord(record);
|
||||
|
||||
// Serialize
|
||||
@ -306,7 +309,8 @@ public final class TestCFRuleRecord extends TestCase
|
||||
|
||||
public void testWrite() {
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
CFRuleRecord rr = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "5", "10");
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
CFRuleRecord rr = CFRuleRecord.create(sheet, ComparisonOperator.BETWEEN, "5", "10");
|
||||
|
||||
PatternFormatting patternFormatting = new PatternFormatting();
|
||||
patternFormatting.setFillPattern(PatternFormatting.BRICKS);
|
||||
|
@ -31,6 +31,7 @@ import org.apache.poi.hssf.record.CFRuleRecord;
|
||||
import org.apache.poi.hssf.record.RecordFactory;
|
||||
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
@ -46,11 +47,13 @@ public final class TestCFRecordsAggregate extends TestCase
|
||||
public void testCFRecordsAggregate()
|
||||
{
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
|
||||
List recs = new ArrayList();
|
||||
CFHeaderRecord header = new CFHeaderRecord();
|
||||
CFRuleRecord rule1 = CFRuleRecord.create(workbook, "7");
|
||||
CFRuleRecord rule2 = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "2", "5");
|
||||
CFRuleRecord rule3 = CFRuleRecord.create(workbook, ComparisonOperator.GE, "100", null);
|
||||
CFRuleRecord rule1 = CFRuleRecord.create(sheet, "7");
|
||||
CFRuleRecord rule2 = CFRuleRecord.create(sheet, ComparisonOperator.BETWEEN, "2", "5");
|
||||
CFRuleRecord rule3 = CFRuleRecord.create(sheet, ComparisonOperator.GE, "100", null);
|
||||
header.setNumberOfConditionalFormats(3);
|
||||
CellRangeAddress[] cellRanges = {
|
||||
new CellRangeAddress(0,1,0,0),
|
||||
@ -107,13 +110,14 @@ public final class TestCFRecordsAggregate extends TestCase
|
||||
*/
|
||||
public void testNRules() {
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
CellRangeAddress[] cellRanges = {
|
||||
new CellRangeAddress(0,1,0,0),
|
||||
new CellRangeAddress(0,1,2,2),
|
||||
};
|
||||
CFRuleRecord[] rules = {
|
||||
CFRuleRecord.create(workbook, "7"),
|
||||
CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "2", "5"),
|
||||
CFRuleRecord.create(sheet, "7"),
|
||||
CFRuleRecord.create(sheet, ComparisonOperator.BETWEEN, "2", "5"),
|
||||
};
|
||||
CFRecordsAggregate agg = new CFRecordsAggregate(cellRanges, rules);
|
||||
byte[] serializedRecord = new byte[agg.getRecordSize()];
|
||||
|
@ -25,8 +25,12 @@ import java.util.Date;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.model.HSSFFormulaParser;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.util.TempFile;
|
||||
import org.apache.poi.ss.formula.FormulaType;
|
||||
|
||||
/**
|
||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||
@ -884,4 +888,51 @@ public final class TestFormulas extends TestCase {
|
||||
assertEquals("DZ2*2", wb.getSheetAt(0).getRow(1).getCell(128).toString());
|
||||
assertEquals("B32770*2", wb.getSheetAt(0).getRow(32768).getCell(1).toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creation / evaluation of formulas with sheet-level names
|
||||
*/
|
||||
public void testSheetLevelFormulas(){
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
|
||||
HSSFRow row;
|
||||
HSSFSheet sh1 = wb.createSheet("Sheet1");
|
||||
HSSFName nm1 = wb.createName();
|
||||
nm1.setNameName("sales_1");
|
||||
nm1.setSheetIndex(0);
|
||||
nm1.setRefersToFormula("Sheet1!$A$1");
|
||||
row = sh1.createRow(0);
|
||||
row.createCell(0).setCellValue(3);
|
||||
row.createCell(1).setCellFormula("sales_1");
|
||||
row.createCell(2).setCellFormula("sales_1*2");
|
||||
|
||||
|
||||
HSSFSheet sh2 = wb.createSheet("Sheet2");
|
||||
HSSFName nm2 = wb.createName();
|
||||
nm2.setNameName("sales_1");
|
||||
nm2.setSheetIndex(1);
|
||||
nm2.setRefersToFormula("Sheet2!$A$1");
|
||||
|
||||
row = sh2.createRow(0);
|
||||
row.createCell(0).setCellValue(5);
|
||||
row.createCell(1).setCellFormula("sales_1");
|
||||
row.createCell(2).setCellFormula("sales_1*3");
|
||||
|
||||
//check that NamePtg refers to the correct NameRecord
|
||||
Ptg[] ptgs1 = HSSFFormulaParser.parse("sales_1", wb, FormulaType.CELL, 0);
|
||||
NamePtg nPtg1 = (NamePtg)ptgs1[0];
|
||||
assertSame(nm1, wb.getNameAt(nPtg1.getIndex()));
|
||||
|
||||
Ptg[] ptgs2 = HSSFFormulaParser.parse("sales_1", wb, FormulaType.CELL, 1);
|
||||
NamePtg nPtg2 = (NamePtg)ptgs2[0];
|
||||
assertSame(nm2, wb.getNameAt(nPtg2.getIndex()));
|
||||
|
||||
//check that the formula evaluator returns the correct result
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
|
||||
assertEquals(3.0, evaluator.evaluate(sh1.getRow(0).getCell(1)).getNumberValue());
|
||||
assertEquals(6.0, evaluator.evaluate(sh1.getRow(0).getCell(2)).getNumberValue());
|
||||
|
||||
assertEquals(5.0, evaluator.evaluate(sh2.getRow(0).getCell(1)).getNumberValue());
|
||||
assertEquals(15.0, evaluator.evaluate(sh2.getRow(0).getCell(2)).getNumberValue());
|
||||
}
|
||||
}
|
||||
|
@ -543,7 +543,7 @@ public final class TestNamedRange extends TestCase {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
wb.createSheet("CSCO");
|
||||
|
||||
Ptg[] ptgs = HSSFFormulaParser.parse("CSCO!$E$71", wb, FormulaType.NAMEDRANGE);
|
||||
Ptg[] ptgs = HSSFFormulaParser.parse("CSCO!$E$71", wb, FormulaType.NAMEDRANGE, 0);
|
||||
for (int i = 0; i < ptgs.length; i++) {
|
||||
assertEquals('R', ptgs[i].getRVAType());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user