Apply, with a few tweaks, the patch from bug #48996 - initial support for External Name References in HSSF formula evaluation
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@953395 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
bf4e6ff464
commit
e92c009814
@ -34,6 +34,7 @@
|
||||
|
||||
<changes>
|
||||
<release version="3.7-SNAPSHOT" date="2010-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="add">48996 - initial support for External Name References in HSSF formula evaluation</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">46664 - fix up Tab IDs when adding new sheets, so that print areas don't end up invalid</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45269 - improve replaceText on HWPF ranges</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">47815 - correct documentation on what happens when you request a String from a non-string Formula cell</action>
|
||||
|
@ -162,6 +162,7 @@ public final class BiffViewer {
|
||||
case ExtSSTRecord.sid: return new ExtSSTRecord(in);
|
||||
case ExtendedFormatRecord.sid: return new ExtendedFormatRecord(in);
|
||||
case ExternSheetRecord.sid: return new ExternSheetRecord(in);
|
||||
case ExternalNameRecord.sid: return new ExternalNameRecord(in);
|
||||
case FeatRecord.sid: return new FeatRecord(in);
|
||||
case FeatHdrRecord.sid: return new FeatHdrRecord(in);
|
||||
case FilePassRecord.sid: return new FilePassRecord(in);
|
||||
|
@ -81,6 +81,7 @@ import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.hssf.record.formula.FormulaShifter;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.util.HSSFColor;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
@ -1771,6 +1772,14 @@ public final class InternalWorkbook {
|
||||
}
|
||||
return new ExternalSheet(extNames[0], extNames[1]);
|
||||
}
|
||||
public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
|
||||
String nameName = linkTable.resolveNameXText(externSheetIndex, externNameIndex);
|
||||
if(nameName == null) {
|
||||
return null;
|
||||
}
|
||||
int ix = linkTable.resolveNameXIx(externSheetIndex, externNameIndex);
|
||||
return new ExternalName(nameName, externNameIndex, ix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the sheet index for a particular external sheet number.
|
||||
|
@ -125,6 +125,10 @@ final class LinkTable {
|
||||
return _externalNameRecords[definedNameIndex].getText();
|
||||
}
|
||||
|
||||
public int getNameIx(int definedNameIndex) {
|
||||
return _externalNameRecords[definedNameIndex].getIx();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs case-insensitive search
|
||||
* @return -1 if not found
|
||||
@ -316,8 +320,12 @@ final class LinkTable {
|
||||
if (!ebr.isExternalReferences()) {
|
||||
return null;
|
||||
}
|
||||
// Sheet name only applies if not a global reference
|
||||
int shIx = _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex);
|
||||
String usSheetName = ebr.getSheetNames()[shIx];
|
||||
String usSheetName = null;
|
||||
if(shIx >= 0) {
|
||||
usSheetName = ebr.getSheetNames()[shIx];
|
||||
}
|
||||
return new String[] {
|
||||
ebr.getURL(),
|
||||
usSheetName,
|
||||
@ -419,6 +427,10 @@ final class LinkTable {
|
||||
int extBookIndex = _externSheetRecord.getExtbookIndexFromRefIndex(refIndex);
|
||||
return _externalBookBlocks[extBookIndex].getNameText(definedNameIndex);
|
||||
}
|
||||
public int resolveNameXIx(int refIndex, int definedNameIndex) {
|
||||
int extBookIndex = _externSheetRecord.getExtbookIndexFromRefIndex(refIndex);
|
||||
return _externalBookBlocks[extBookIndex].getNameIx(definedNameIndex);
|
||||
}
|
||||
|
||||
public NameXPtg getNameXPtg(String name) {
|
||||
// first find any external book block that contains the name:
|
||||
|
@ -41,7 +41,8 @@ public final class ExternalNameRecord extends StandardRecord {
|
||||
|
||||
|
||||
private short field_1_option_flag;
|
||||
private int field_2_not_used;
|
||||
private short field_2_ixals;
|
||||
private short field_3_not_used;
|
||||
private String field_4_name;
|
||||
private Formula field_5_name_definition;
|
||||
|
||||
@ -97,6 +98,16 @@ public final class ExternalNameRecord extends StandardRecord {
|
||||
return field_4_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is a local name, then this is the (1 based)
|
||||
* index of the name of the Sheet this refers to, as
|
||||
* defined in the preceeding {@link SupBookRecord}.
|
||||
* If it isn't a local name, then it must be zero.
|
||||
*/
|
||||
public short getIx() {
|
||||
return field_2_ixals;
|
||||
}
|
||||
|
||||
protected int getDataSize(){
|
||||
int result = 2 + 4; // short and int
|
||||
result += StringUtil.getEncodedSize(field_4_name) - 1; //size is byte, not short
|
||||
@ -114,7 +125,8 @@ public final class ExternalNameRecord extends StandardRecord {
|
||||
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(field_1_option_flag);
|
||||
out.writeInt(field_2_not_used);
|
||||
out.writeShort(field_2_ixals);
|
||||
out.writeShort(field_3_not_used);
|
||||
|
||||
out.writeByte(field_4_name.length());
|
||||
StringUtil.writeUnicodeStringFlagAndData(out, field_4_name);
|
||||
@ -133,7 +145,8 @@ public final class ExternalNameRecord extends StandardRecord {
|
||||
|
||||
public ExternalNameRecord(RecordInputStream in) {
|
||||
field_1_option_flag = in.readShort();
|
||||
field_2_not_used = in.readInt();
|
||||
field_2_ixals = in.readShort();
|
||||
field_3_not_used = in.readShort();
|
||||
|
||||
int numChars = in.readUByte();
|
||||
field_4_name = StringUtil.readUnicodeString(in, numChars);
|
||||
@ -166,10 +179,13 @@ public final class ExternalNameRecord extends StandardRecord {
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName()).append(" [EXTERNALNAME ");
|
||||
sb.append(" ").append(field_4_name);
|
||||
sb.append(" ix=").append(field_2_not_used);
|
||||
sb.append("]");
|
||||
sb.append("[EXTERNALNAME]\n");
|
||||
sb.append(" .ix = ").append(field_2_ixals).append("\n");
|
||||
sb.append(" .name = ").append(field_4_name).append("\n");
|
||||
if(field_5_name_definition != null) {
|
||||
sb.append(" .formula = ").append(field_5_name_definition).append("\n");
|
||||
}
|
||||
sb.append("[/EXTERNALNAME]\n");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +74,12 @@ public final class NameXPtg extends OperandPtg implements WorkbookDependentFormu
|
||||
throw new RuntimeException("3D references need a workbook to determine formula text");
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
String retValue = "NameXPtg:[sheetRefIndex:" + _sheetRefIndex +
|
||||
" , nameNumber:" + _nameNumber + "]" ;
|
||||
return retValue;
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import org.apache.poi.ss.formula.FormulaParseException;
|
||||
import org.apache.poi.ss.formula.FormulaParsingWorkbook;
|
||||
import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
|
||||
import org.apache.poi.ss.formula.FormulaType;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
|
||||
|
||||
/**
|
||||
* Internal POI use only
|
||||
@ -108,6 +109,10 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||
return _iBook.getExternalSheet(externSheetIndex);
|
||||
}
|
||||
|
||||
public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
|
||||
return _iBook.getExternalName(externSheetIndex, externNameIndex);
|
||||
}
|
||||
|
||||
public String resolveNameXText(NameXPtg n) {
|
||||
return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex());
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ public interface EvaluationWorkbook {
|
||||
*/
|
||||
ExternalSheet getExternalSheet(int externSheetIndex);
|
||||
int convertFromExternSheetIndex(int externSheetIndex);
|
||||
ExternalName getExternalName(int externSheetIndex, int externNameIndex);
|
||||
EvaluationName getName(NamePtg namePtg);
|
||||
String resolveNameXText(NameXPtg ptg);
|
||||
Ptg[] getFormulaTokens(EvaluationCell cell);
|
||||
@ -66,4 +67,24 @@ public interface EvaluationWorkbook {
|
||||
return _sheetName;
|
||||
}
|
||||
}
|
||||
class ExternalName {
|
||||
private final String _nameName;
|
||||
private final int _nameNumber;
|
||||
private final int _ix;
|
||||
|
||||
public ExternalName(String nameName, int nameNumber, int ix) {
|
||||
_nameName = nameName;
|
||||
_nameNumber = nameNumber;
|
||||
_ix = ix;
|
||||
}
|
||||
public String getName() {
|
||||
return _nameName;
|
||||
}
|
||||
public int getNumber() {
|
||||
return _nameNumber;
|
||||
}
|
||||
public int getIx() {
|
||||
return _ix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,15 @@
|
||||
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.Area3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.Ref3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.eval.*;
|
||||
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
||||
import org.apache.poi.ss.SpreadsheetVersion;
|
||||
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.ss.util.CellReference.NameType;
|
||||
@ -254,4 +259,40 @@ public final class OperationEvaluationContext {
|
||||
SheetRefEvaluator sre = createExternSheetRefEvaluator(extSheetIndex);
|
||||
return new LazyAreaEval(firstRowIndex, firstColumnIndex, lastRowIndex, lastColumnIndex, sre);
|
||||
}
|
||||
public ValueEval getNameXEval(NameXPtg nameXPtg) {
|
||||
ExternalSheet externSheet = _workbook.getExternalSheet(nameXPtg.getSheetRefIndex());
|
||||
if(externSheet == null)
|
||||
return new NameXEval(nameXPtg);
|
||||
String workbookName = externSheet.getWorkbookName();
|
||||
ExternalName externName = _workbook.getExternalName(
|
||||
nameXPtg.getSheetRefIndex(),
|
||||
nameXPtg.getNameIndex()
|
||||
);
|
||||
try{
|
||||
WorkbookEvaluator refWorkbookEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName);
|
||||
EvaluationName evaluationName = refWorkbookEvaluator.getName(externName.getName(),externName.getIx()-1);
|
||||
if(evaluationName != null && evaluationName.hasFormula()){
|
||||
if (evaluationName.getNameDefinition().length > 1) {
|
||||
throw new RuntimeException("Complex name formulas not supported yet");
|
||||
}
|
||||
Ptg ptg = evaluationName.getNameDefinition()[0];
|
||||
if(ptg instanceof Ref3DPtg){
|
||||
Ref3DPtg ref3D = (Ref3DPtg)ptg;
|
||||
int sheetIndex = refWorkbookEvaluator.getSheetIndexByExternIndex(ref3D.getExternSheetIndex());
|
||||
String sheetName = refWorkbookEvaluator.getSheetName(sheetIndex);
|
||||
SheetRefEvaluator sre = createExternSheetRefEvaluator(workbookName, sheetName);
|
||||
return new LazyRefEval(ref3D.getRow(), ref3D.getColumn(), sre);
|
||||
}else if(ptg instanceof Area3DPtg){
|
||||
Area3DPtg area3D = (Area3DPtg)ptg;
|
||||
int sheetIndex = refWorkbookEvaluator.getSheetIndexByExternIndex(area3D.getExternSheetIndex());
|
||||
String sheetName = refWorkbookEvaluator.getSheetName(sheetIndex);
|
||||
SheetRefEvaluator sre = createExternSheetRefEvaluator(workbookName, sheetName);
|
||||
return new LazyAreaEval(area3D.getFirstRow(), area3D.getFirstColumn(), area3D.getLastRow(), area3D.getLastColumn(), sre);
|
||||
}
|
||||
}
|
||||
return ErrorEval.REF_INVALID;
|
||||
}catch(WorkbookNotFoundException wnfe){
|
||||
return ErrorEval.REF_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ import org.apache.poi.hssf.record.formula.functions.Choose;
|
||||
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
||||
import org.apache.poi.hssf.record.formula.functions.IfFunc;
|
||||
import org.apache.poi.hssf.record.formula.udf.UDFFinder;
|
||||
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
|
||||
import org.apache.poi.ss.formula.eval.NotImplementedException;
|
||||
@ -125,6 +126,19 @@ public final class WorkbookEvaluator {
|
||||
return _workbook.getSheet(sheetIndex);
|
||||
}
|
||||
|
||||
/* package */ EvaluationName getName(String name, int sheetIndex) {
|
||||
NamePtg namePtg = null;
|
||||
if(_workbook instanceof HSSFEvaluationWorkbook){
|
||||
namePtg =((HSSFEvaluationWorkbook)_workbook).getName(name, sheetIndex).createPtg();
|
||||
}
|
||||
|
||||
if(namePtg == null) {
|
||||
return null;
|
||||
} else {
|
||||
return _workbook.getName(namePtg);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDebugLogEnabled() {
|
||||
return false;
|
||||
}
|
||||
@ -224,6 +238,10 @@ public final class WorkbookEvaluator {
|
||||
return result.intValue();
|
||||
}
|
||||
|
||||
/* package */ int getSheetIndexByExternIndex(int externSheetIndex) {
|
||||
return _workbook.convertFromExternSheetIndex(externSheetIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return never <code>null</code>, never {@link BlankEval}
|
||||
@ -524,7 +542,7 @@ public final class WorkbookEvaluator {
|
||||
throw new RuntimeException("Don't now how to evalate name '" + nameRecord.getNameText() + "'");
|
||||
}
|
||||
if (ptg instanceof NameXPtg) {
|
||||
return new NameXEval(((NameXPtg) ptg));
|
||||
return ec.getNameXEval(((NameXPtg) ptg));
|
||||
}
|
||||
|
||||
if (ptg instanceof IntPtg) {
|
||||
|
@ -107,6 +107,10 @@ final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
|
||||
return getSharedSheet(getSheetName(sheetIndex));
|
||||
}
|
||||
|
||||
public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
|
||||
return _masterBook.getExternalName(externSheetIndex, externNameIndex);
|
||||
}
|
||||
|
||||
public int getSheetIndex(EvaluationSheet sheet) {
|
||||
if (sheet instanceof ForkedEvaluationSheet) {
|
||||
ForkedEvaluationSheet mes = (ForkedEvaluationSheet) sheet;
|
||||
|
@ -29,6 +29,7 @@ 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.FormulaType;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
||||
|
||||
/**
|
||||
@ -95,6 +96,10 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||
return _uBook.getSheetName(sheetIndex);
|
||||
}
|
||||
|
||||
public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
|
||||
throw new RuntimeException("Not implemented yet");
|
||||
}
|
||||
|
||||
public NameXPtg getNameXPtg(String name) {
|
||||
// may require to return null to make tests pass
|
||||
throw new RuntimeException("Not implemented yet");
|
||||
|
@ -0,0 +1,106 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
/**
|
||||
* Tests for proper calculation of named ranges from external workbooks.
|
||||
*
|
||||
*
|
||||
* @author Stephen Wolke (smwolke at geistig.com)
|
||||
*/
|
||||
public final class TestExternalNameReference extends TestCase {
|
||||
double MARKUP_COST = 1.9d;
|
||||
double MARKUP_COST_1 = 1.8d;
|
||||
double MARKUP_COST_2 = 1.5d;
|
||||
double PART_COST = 12.3d;
|
||||
double NEW_QUANT = 7.0d;
|
||||
double NEW_PART_COST = 15.3d;
|
||||
/**
|
||||
* tests <tt>NameXPtg for external cell reference by name</tt> and logic in Workbook below that
|
||||
*/
|
||||
public void testReadCalcSheet() {
|
||||
try{
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("XRefCalc.xls");
|
||||
assertEquals("Sheet1!$A$2", wb.getName("QUANT").getRefersToFormula());
|
||||
assertEquals("Sheet1!$B$2", wb.getName("PART").getRefersToFormula());
|
||||
assertEquals("x123",wb.getSheet("Sheet1").getRow(1).getCell(1).getStringCellValue());
|
||||
assertEquals("Sheet1!$C$2", wb.getName("UNITCOST").getRefersToFormula());
|
||||
CellReference cellRef = new CellReference(wb.getName("UNITCOST").getRefersToFormula());
|
||||
HSSFCell cell = wb.getSheet(cellRef.getSheetName()).getRow(cellRef.getRow()).getCell((int)cellRef.getCol());
|
||||
assertEquals("VLOOKUP(PART,COSTS,2,FALSE)",cell.getCellFormula());
|
||||
assertEquals("Sheet1!$D$2", wb.getName("COST").getRefersToFormula());
|
||||
cellRef = new CellReference(wb.getName("COST").getRefersToFormula());
|
||||
cell = wb.getSheet(cellRef.getSheetName()).getRow(cellRef.getRow()).getCell((int)cellRef.getCol());
|
||||
assertEquals("UNITCOST*Quant",cell.getCellFormula());
|
||||
assertEquals("Sheet1!$E$2", wb.getName("TOTALCOST").getRefersToFormula());
|
||||
cellRef = new CellReference(wb.getName("TOTALCOST").getRefersToFormula());
|
||||
cell = wb.getSheet(cellRef.getSheetName()).getRow(cellRef.getRow()).getCell((int)cellRef.getCol());
|
||||
assertEquals("Cost*Markup_Cost",cell.getCellFormula());
|
||||
}catch(Exception e){
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
public void testReadReferencedSheet() {
|
||||
try{
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("XRefCalcData.xls");
|
||||
assertEquals("CostSheet!$A$2:$B$3", wb.getName("COSTS").getRefersToFormula());
|
||||
assertEquals("x123",wb.getSheet("CostSheet").getRow(1).getCell(0).getStringCellValue());
|
||||
assertEquals(PART_COST,wb.getSheet("CostSheet").getRow(1).getCell(1).getNumericCellValue());
|
||||
assertEquals("MarkupSheet!$B$1", wb.getName("Markup_Cost").getRefersToFormula());
|
||||
assertEquals(MARKUP_COST_1,wb.getSheet("MarkupSheet").getRow(0).getCell(1).getNumericCellValue());
|
||||
}catch(Exception e){
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
public void testEvaluate() throws Exception {
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("XRefCalc.xls");
|
||||
HSSFWorkbook wb2 = HSSFTestDataSamples.openSampleWorkbook("XRefCalcData.xls");
|
||||
CellReference cellRef = new CellReference(wb.getName("QUANT").getRefersToFormula());
|
||||
HSSFCell cell = wb.getSheet(cellRef.getSheetName()).getRow(cellRef.getRow()).getCell((int)cellRef.getCol());
|
||||
cell.setCellValue(NEW_QUANT);
|
||||
cell = wb2.getSheet("CostSheet").getRow(1).getCell(1);
|
||||
cell.setCellValue(NEW_PART_COST);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
|
||||
HSSFFormulaEvaluator evaluatorCost = new HSSFFormulaEvaluator(wb2);
|
||||
String[] bookNames = { "XRefCalc.xls", "XRefCalcData.xls" };
|
||||
HSSFFormulaEvaluator[] evaluators = { evaluator, evaluatorCost, };
|
||||
HSSFFormulaEvaluator.setupEnvironment(bookNames, evaluators);
|
||||
cellRef = new CellReference(wb.getName("UNITCOST").getRefersToFormula());
|
||||
HSSFCell uccell = wb.getSheet(cellRef.getSheetName()).getRow(cellRef.getRow()).getCell((int)cellRef.getCol());
|
||||
cellRef = new CellReference(wb.getName("COST").getRefersToFormula());
|
||||
HSSFCell ccell = wb.getSheet(cellRef.getSheetName()).getRow(cellRef.getRow()).getCell((int)cellRef.getCol());
|
||||
cellRef = new CellReference(wb.getName("TOTALCOST").getRefersToFormula());
|
||||
HSSFCell tccell = wb.getSheet(cellRef.getSheetName()).getRow(cellRef.getRow()).getCell((int)cellRef.getCol());
|
||||
evaluator.evaluateFormulaCell(uccell);
|
||||
evaluator.evaluateFormulaCell(ccell);
|
||||
evaluator.evaluateFormulaCell(tccell);
|
||||
assertEquals(NEW_PART_COST, uccell.getNumericCellValue());
|
||||
assertEquals(NEW_PART_COST*NEW_QUANT, ccell.getNumericCellValue());
|
||||
assertEquals(NEW_PART_COST*NEW_QUANT*MARKUP_COST_2, tccell.getNumericCellValue());
|
||||
}
|
||||
}
|
@ -215,4 +215,65 @@ public final class TestHSSFFormulaEvaluator extends TestCase {
|
||||
assertEquals(3, evalCount);
|
||||
assertEquals(2.0, ((NumberEval)ve).getNumberValue(), 0D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that we can handle NameXPtgs in the formulas
|
||||
* we parse.
|
||||
*/
|
||||
public void testXRefs() throws Exception {
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("XRefCalc.xls");
|
||||
HSSFWorkbook wbData = HSSFTestDataSamples.openSampleWorkbook("XRefCalcData.xls");
|
||||
Cell cell;
|
||||
|
||||
// VLookup on a name in another file
|
||||
cell = wb.getSheetAt(0).getRow(1).getCell(2);
|
||||
assertEquals(Cell.CELL_TYPE_FORMULA, cell.getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_NUMERIC, cell.getCachedFormulaResultType());
|
||||
assertEquals(12.30, cell.getNumericCellValue(), 0.0001);
|
||||
// WARNING - this is wrong!
|
||||
// The file name should be showing, but bug #45970 is fixed
|
||||
// we seem to loose it
|
||||
assertEquals("VLOOKUP(PART,COSTS,2,FALSE)", cell.getCellFormula());
|
||||
|
||||
|
||||
// Simple reference to a name in another file
|
||||
cell = wb.getSheetAt(0).getRow(1).getCell(4);
|
||||
assertEquals(Cell.CELL_TYPE_FORMULA, cell.getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_NUMERIC, cell.getCachedFormulaResultType());
|
||||
assertEquals(36.90, cell.getNumericCellValue(), 0.0001);
|
||||
// WARNING - this is wrong!
|
||||
// The file name should be showing, but bug #45970 is fixed
|
||||
// we seem to loose it
|
||||
assertEquals("Cost*Markup_Cost", cell.getCellFormula());
|
||||
|
||||
|
||||
// Evaluate the cells
|
||||
HSSFFormulaEvaluator eval = new HSSFFormulaEvaluator(wb);
|
||||
HSSFFormulaEvaluator.setupEnvironment(
|
||||
new String[] { "XRefCalc.xls", "XRefCalcData.xls" },
|
||||
new HSSFFormulaEvaluator[] {
|
||||
eval,
|
||||
new HSSFFormulaEvaluator(wbData)
|
||||
}
|
||||
);
|
||||
eval.evaluateFormulaCell(
|
||||
wb.getSheetAt(0).getRow(1).getCell(2)
|
||||
);
|
||||
eval.evaluateFormulaCell(
|
||||
wb.getSheetAt(0).getRow(1).getCell(4)
|
||||
);
|
||||
|
||||
|
||||
// Re-check VLOOKUP one
|
||||
cell = wb.getSheetAt(0).getRow(1).getCell(2);
|
||||
assertEquals(Cell.CELL_TYPE_FORMULA, cell.getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_NUMERIC, cell.getCachedFormulaResultType());
|
||||
assertEquals(12.30, cell.getNumericCellValue(), 0.0001);
|
||||
|
||||
// Re-check ref one
|
||||
cell = wb.getSheetAt(0).getRow(1).getCell(4);
|
||||
assertEquals(Cell.CELL_TYPE_FORMULA, cell.getCellType());
|
||||
assertEquals(Cell.CELL_TYPE_NUMERIC, cell.getCachedFormulaResultType());
|
||||
assertEquals(36.90, cell.getNumericCellValue(), 0.0001);
|
||||
}
|
||||
}
|
||||
|
BIN
test-data/spreadsheet/XRefCalc.xls
Normal file
BIN
test-data/spreadsheet/XRefCalc.xls
Normal file
Binary file not shown.
BIN
test-data/spreadsheet/XRefCalcData.xls
Normal file
BIN
test-data/spreadsheet/XRefCalcData.xls
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user