git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@729028 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_5_BETA5
@@ -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,9 +52,23 @@ 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); | |||
} | |||
/** | |||
* Static method to convert an array of {@link Ptg}s in RPN order | |||
* to a human readable string format in infix mode. |
@@ -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); | |||
return new CFRuleRecord(CONDITION_TYPE_FORMULA, ComparisonOperator.NO_COMPARISON, | |||
formula1, null); | |||
} | |||
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) { | |||
if(formula == null) { | |||
return null; | |||
} | |||
return HSSFFormulaParser.parse(formula, workbook); | |||
} | |||
private static Ptg[] parseFormula(String formula, HSSFSheet sheet) { | |||
if(formula == null) { | |||
return null; | |||
} | |||
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) { | |||
// formula is parsed with slightly different RVA rules: (root node type must be 'reference') | |||
return HSSFFormulaParser.parse(_formula1, workbook, FormulaType.DATAVALIDATION_LIST); | |||
HSSFWorkbook wb = sheet.getWorkbook(); | |||
// formula is parsed with slightly different RVA rules: (root node type must be 'reference') | |||
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. | |||
@@ -269,7 +270,7 @@ public class HSSFCell implements Cell { | |||
public short getCellNum() { | |||
return (short) getColumnIndex(); | |||
} | |||
public int getColumnIndex() { | |||
return record.getColumn() & 0xFFFF; | |||
} | |||
@@ -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(); | |||
@@ -874,7 +876,7 @@ public class HSSFCell implements Cell { | |||
* @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getCellStyleAt(short) | |||
*/ | |||
public void setCellStyle(CellStyle style) { | |||
setCellStyle( (HSSFCellStyle)style ); | |||
setCellStyle( (HSSFCellStyle)style ); | |||
} | |||
public void setCellStyle(HSSFCellStyle style) { | |||
// Verify it really does belong to our workbook | |||
@@ -1111,8 +1113,8 @@ public class HSSFCell implements Cell { | |||
* @param hyperlink hypelrink associated with this cell | |||
*/ | |||
public void setHyperlink(Hyperlink hyperlink){ | |||
HSSFHyperlink link = (HSSFHyperlink)hyperlink; | |||
HSSFHyperlink link = (HSSFHyperlink)hyperlink; | |||
link.setFirstRow(record.getRow()); | |||
link.setLastRow(record.getRow()); | |||
link.setFirstColumn(record.getColumn()); |
@@ -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 | |||
@@ -38,118 +33,125 @@ import org.apache.poi.ss.formula.FormulaRenderingWorkbook; | |||
*/ | |||
public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook { | |||
private final HSSFWorkbook _uBook; | |||
private final Workbook _iBook; | |||
public static HSSFEvaluationWorkbook create(HSSFWorkbook book) { | |||
if (book == null) { | |||
return null; | |||
} | |||
return new HSSFEvaluationWorkbook(book); | |||
} | |||
private HSSFEvaluationWorkbook(HSSFWorkbook book) { | |||
_uBook = book; | |||
_iBook = book.getWorkbook(); | |||
} | |||
public int getExternalSheetIndex(String sheetName) { | |||
int sheetIndex = _uBook.getSheetIndex(sheetName); | |||
return _iBook.checkExternSheet(sheetIndex); | |||
} | |||
public int getExternalSheetIndex(String workbookName, String sheetName) { | |||
return _iBook.getExternalSheetIndex(workbookName, sheetName); | |||
} | |||
public NameXPtg getNameXPtg(String name) { | |||
return _iBook.getNameXPtg(name); | |||
} | |||
public EvaluationName getName(String name) { | |||
for(int i=0; i < _iBook.getNumNames(); i++) { | |||
NameRecord nr = _iBook.getNameRecord(i); | |||
if (name.equalsIgnoreCase(nr.getNameText())) { | |||
return new Name(nr, i); | |||
} | |||
} | |||
return null; | |||
} | |||
public int getSheetIndex(EvaluationSheet evalSheet) { | |||
HSSFSheet sheet = ((HSSFEvaluationSheet)evalSheet).getHSSFSheet(); | |||
return _uBook.getSheetIndex(sheet); | |||
} | |||
public int getSheetIndex(String sheetName) { | |||
return _uBook.getSheetIndex(sheetName); | |||
} | |||
public String getSheetName(int sheetIndex) { | |||
return _uBook.getSheetName(sheetIndex); | |||
} | |||
public EvaluationSheet getSheet(int sheetIndex) { | |||
return new HSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex)); | |||
} | |||
public int convertFromExternSheetIndex(int externSheetIndex) { | |||
return _iBook.getSheetIndexFromExternSheetIndex(externSheetIndex); | |||
} | |||
public ExternalSheet getExternalSheet(int externSheetIndex) { | |||
return _iBook.getExternalSheet(externSheetIndex); | |||
} | |||
public String resolveNameXText(NameXPtg n) { | |||
return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex()); | |||
} | |||
public String getSheetNameByExternSheet(int externSheetIndex) { | |||
return _iBook.findSheetNameFromExternSheet(externSheetIndex); | |||
} | |||
public String getNameText(NamePtg namePtg) { | |||
return _iBook.getNameRecord(namePtg.getIndex()).getNameText(); | |||
} | |||
public EvaluationName getName(NamePtg namePtg) { | |||
int ix = namePtg.getIndex(); | |||
return new Name(_iBook.getNameRecord(ix), ix); | |||
} | |||
public Ptg[] getFormulaTokens(EvaluationCell evalCell) { | |||
HSSFCell cell = ((HSSFEvaluationCell)evalCell).getHSSFCell(); | |||
if (false) { | |||
// 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); | |||
} | |||
FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord(); | |||
return fra.getFormulaTokens(); | |||
} | |||
private static final class Name implements EvaluationName { | |||
private final NameRecord _nameRecord; | |||
private final int _index; | |||
public Name(NameRecord nameRecord, int index) { | |||
_nameRecord = nameRecord; | |||
_index = index; | |||
} | |||
public Ptg[] getNameDefinition() { | |||
return _nameRecord.getNameDefinition(); | |||
} | |||
public String getNameText() { | |||
return _nameRecord.getNameText(); | |||
} | |||
public boolean hasFormula() { | |||
return _nameRecord.hasFormula(); | |||
} | |||
public boolean isFunctionName() { | |||
return _nameRecord.isFunctionName(); | |||
} | |||
public boolean isRange() { | |||
return _nameRecord.hasFormula(); // TODO - is this right? | |||
} | |||
public NamePtg createPtg() { | |||
return new NamePtg(_index); | |||
} | |||
} | |||
private final HSSFWorkbook _uBook; | |||
private final Workbook _iBook; | |||
public static HSSFEvaluationWorkbook create(HSSFWorkbook book) { | |||
if (book == null) { | |||
return null; | |||
} | |||
return new HSSFEvaluationWorkbook(book); | |||
} | |||
private HSSFEvaluationWorkbook(HSSFWorkbook book) { | |||
_uBook = book; | |||
_iBook = book.getWorkbook(); | |||
} | |||
public int getExternalSheetIndex(String sheetName) { | |||
int sheetIndex = _uBook.getSheetIndex(sheetName); | |||
return _iBook.checkExternSheet(sheetIndex); | |||
} | |||
public int getExternalSheetIndex(String workbookName, String sheetName) { | |||
return _iBook.getExternalSheetIndex(workbookName, sheetName); | |||
} | |||
public NameXPtg getNameXPtg(String name) { | |||
return _iBook.getNameXPtg(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 (nr.getSheetNumber() == sheetIndex+1 && name.equalsIgnoreCase(nr.getNameText())) { | |||
return new Name(nr, i); | |||
} | |||
} | |||
return sheetIndex == -1 ? null : getName(name, -1); | |||
} | |||
public int getSheetIndex(EvaluationSheet evalSheet) { | |||
HSSFSheet sheet = ((HSSFEvaluationSheet)evalSheet).getHSSFSheet(); | |||
return _uBook.getSheetIndex(sheet); | |||
} | |||
public int getSheetIndex(String sheetName) { | |||
return _uBook.getSheetIndex(sheetName); | |||
} | |||
public String getSheetName(int sheetIndex) { | |||
return _uBook.getSheetName(sheetIndex); | |||
} | |||
public EvaluationSheet getSheet(int sheetIndex) { | |||
return new HSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex)); | |||
} | |||
public int convertFromExternSheetIndex(int externSheetIndex) { | |||
return _iBook.getSheetIndexFromExternSheetIndex(externSheetIndex); | |||
} | |||
public ExternalSheet getExternalSheet(int externSheetIndex) { | |||
return _iBook.getExternalSheet(externSheetIndex); | |||
} | |||
public String resolveNameXText(NameXPtg n) { | |||
return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex()); | |||
} | |||
public String getSheetNameByExternSheet(int externSheetIndex) { | |||
return _iBook.findSheetNameFromExternSheet(externSheetIndex); | |||
} | |||
public String getNameText(NamePtg namePtg) { | |||
return _iBook.getNameRecord(namePtg.getIndex()).getNameText(); | |||
} | |||
public EvaluationName getName(NamePtg namePtg) { | |||
int ix = namePtg.getIndex(); | |||
return new Name(_iBook.getNameRecord(ix), ix); | |||
} | |||
public Ptg[] getFormulaTokens(EvaluationCell evalCell) { | |||
HSSFCell cell = ((HSSFEvaluationCell)evalCell).getHSSFCell(); | |||
if (false) { | |||
// 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, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet())); | |||
} | |||
FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord(); | |||
return fra.getFormulaTokens(); | |||
} | |||
private static final class Name implements EvaluationName { | |||
private final NameRecord _nameRecord; | |||
private final int _index; | |||
public Name(NameRecord nameRecord, int index) { | |||
_nameRecord = nameRecord; | |||
_index = index; | |||
} | |||
public Ptg[] getNameDefinition() { | |||
return _nameRecord.getNameDefinition(); | |||
} | |||
public String getNameText() { | |||
return _nameRecord.getNameText(); | |||
} | |||
public boolean hasFormula() { | |||
return _nameRecord.hasFormula(); | |||
} | |||
public boolean isFunctionName() { | |||
return _nameRecord.isFunctionName(); | |||
} | |||
public boolean isRange() { | |||
return _nameRecord.hasFormula(); // TODO - is this right? | |||
} | |||
public NamePtg createPtg() { | |||
return new NamePtg(_index); | |||
} | |||
} | |||
} |
@@ -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,13 +31,13 @@ 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(); | |||
} | |||
/** | |||
* A factory method allowing to create a conditional formatting rule | |||
@@ -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,15 +67,16 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E | |||
return convertToExternalSheetIndex(sheetIndex); | |||
} | |||
public EvaluationName getName(String name) { | |||
for(int i=0; i < _uBook.getNumberOfNames(); i++) { | |||
String nameText = _uBook.getNameAt(i).getNameName(); | |||
if (name.equalsIgnoreCase(nameText)) { | |||
return new Name(_uBook.getNameAt(i), i, this); | |||
} | |||
} | |||
return null; | |||
} | |||
public EvaluationName getName(String name, int sheetIndex) { | |||
for(int i=0; i < _uBook.getNumberOfNames(); i++) { | |||
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 sheetIndex == -1 ? null : getName(name, -1); | |||
} | |||
public int getSheetIndex(EvaluationSheet evalSheet) { | |||
XSSFSheet sheet = ((XSSFEvaluationSheet)evalSheet).getXSSFSheet(); | |||
@@ -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()); | |||
} | |||
} |
@@ -899,11 +899,11 @@ public final class TestFormulaParser extends TestCase { | |||
wb.setSheetName(0, "Sheet1"); | |||
cell.setCellFormula("Sheet1!B$4:Sheet1!$C1"); // explicit range ':' operator | |||
assertEquals("Sheet1!B$4:Sheet1!$C1", cell.getCellFormula()); | |||
assertEquals("Sheet1!B$4:Sheet1!$C1", cell.getCellFormula()); | |||
cell.setCellFormula("Sheet1!B$4:$C1"); // plain area ref | |||
assertEquals("Sheet1!B1:$C$4", cell.getCellFormula()); // note - area ref is normalised | |||
cell.setCellFormula("Sheet1!$C1...B$4"); // different syntax for plain area ref | |||
assertEquals("Sheet1!B1:$C$4", cell.getCellFormula()); | |||
@@ -922,7 +922,7 @@ public final class TestFormulaParser extends TestCase { | |||
assertEquals("'true'!B2", cell.getCellFormula()); | |||
} | |||
public void testParseExternalWorkbookReference() { | |||
HSSFWorkbook wbA = HSSFTestDataSamples.openSampleWorkbook("multibookFormulaA.xls"); | |||
HSSFCell cell = wbA.getSheetAt(0).getRow(0).getCell(0); | |||
@@ -931,15 +931,15 @@ public final class TestFormulaParser extends TestCase { | |||
assertEquals("[multibookFormulaB.xls]BSheet1!B1", cell.getCellFormula()); | |||
Ptg[] expectedPtgs = FormulaExtractor.getPtgs(cell); | |||
confirmSingle3DRef(expectedPtgs, 1); | |||
// now try (re-)parsing the formula | |||
Ptg[] actualPtgs = HSSFFormulaParser.parse("[multibookFormulaB.xls]BSheet1!B1", wbA); | |||
confirmSingle3DRef(actualPtgs, 1); // externalSheetIndex 1 -> BSheet1 | |||
// try parsing a formula pointing to a different external sheet | |||
Ptg[] otherPtgs = HSSFFormulaParser.parse("[multibookFormulaB.xls]AnotherSheet!B1", wbA); | |||
confirmSingle3DRef(otherPtgs, 0); // externalSheetIndex 0 -> AnotherSheet | |||
// try setting the same formula in a cell | |||
cell.setCellFormula("[multibookFormulaB.xls]AnotherSheet!B1"); | |||
assertEquals("[multibookFormulaB.xls]AnotherSheet!B1", cell.getCellFormula()); | |||
@@ -950,13 +950,13 @@ public final class TestFormulaParser extends TestCase { | |||
assertEquals(Ref3DPtg.class, ptg0.getClass()); | |||
assertEquals(expectedExternSheetIndex, ((Ref3DPtg)ptg0).getExternSheetIndex()); | |||
} | |||
public void testUnion() { | |||
String formula = "Sheet1!$B$2:$C$3,OFFSET(Sheet1!$E$2:$E$4,1,Sheet1!$A$1),Sheet1!$D$6"; | |||
HSSFWorkbook wb = new HSSFWorkbook(); | |||
wb.createSheet("Sheet1"); | |||
Ptg[] ptgs = FormulaParser.parse(formula, HSSFEvaluationWorkbook.create(wb)); | |||
Class[] expectedClasses = { | |||
// TODO - AttrPtg.class, // Excel prepends this | |||
MemFuncPtg.class, |
@@ -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(); | |||
List recs = new ArrayList(); | |||
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) | |||
@@ -182,11 +186,11 @@ public final class TestFormulas extends TestCase { | |||
// don't know how to check correct result .. for the moment, we just verify that the file can be read. | |||
for (int x = 1; x < Short.MAX_VALUE && x > 0; x=(short)(x*2)) { | |||
HSSFRow r = s.getRow(x); | |||
HSSFRow r = s.getRow(x); | |||
for (int y = 1; y < 256 && y > 0; y=(short)(y+2)) { | |||
HSSFCell c = r.getCell(y); | |||
HSSFCell c = r.getCell(y); | |||
assertTrue("got a formula",c.getCellFormula()!=null); | |||
assertTrue("loop Formula is as expected "+x+"."+y+operator+y+"."+x+"!="+c.getCellFormula(),( | |||
@@ -535,9 +539,9 @@ public final class TestFormulas extends TestCase { | |||
public void testAbsRefs() { | |||
HSSFWorkbook wb = new HSSFWorkbook(); | |||
HSSFSheet s = wb.createSheet(); | |||
HSSFRow r; | |||
HSSFCell c; | |||
HSSFSheet s = wb.createSheet(); | |||
HSSFRow r; | |||
HSSFCell c; | |||
r = s.createRow(0); | |||
c = r.createCell(0); | |||
@@ -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()); | |||
} |