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>
|
<changes>
|
||||||
<release version="3.7-SNAPSHOT" date="2010-??-??">
|
<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">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">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>
|
<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 ExtSSTRecord.sid: return new ExtSSTRecord(in);
|
||||||
case ExtendedFormatRecord.sid: return new ExtendedFormatRecord(in);
|
case ExtendedFormatRecord.sid: return new ExtendedFormatRecord(in);
|
||||||
case ExternSheetRecord.sid: return new ExternSheetRecord(in);
|
case ExternSheetRecord.sid: return new ExternSheetRecord(in);
|
||||||
|
case ExternalNameRecord.sid: return new ExternalNameRecord(in);
|
||||||
case FeatRecord.sid: return new FeatRecord(in);
|
case FeatRecord.sid: return new FeatRecord(in);
|
||||||
case FeatHdrRecord.sid: return new FeatHdrRecord(in);
|
case FeatHdrRecord.sid: return new FeatHdrRecord(in);
|
||||||
case FilePassRecord.sid: return new FilePassRecord(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.FormulaShifter;
|
||||||
import org.apache.poi.hssf.record.formula.Ptg;
|
import org.apache.poi.hssf.record.formula.Ptg;
|
||||||
import org.apache.poi.hssf.util.HSSFColor;
|
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.ss.formula.EvaluationWorkbook.ExternalSheet;
|
||||||
import org.apache.poi.util.Internal;
|
import org.apache.poi.util.Internal;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
@ -1771,6 +1772,14 @@ public final class InternalWorkbook {
|
|||||||
}
|
}
|
||||||
return new ExternalSheet(extNames[0], extNames[1]);
|
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.
|
* Finds the sheet index for a particular external sheet number.
|
||||||
|
@ -124,6 +124,10 @@ final class LinkTable {
|
|||||||
public String getNameText(int definedNameIndex) {
|
public String getNameText(int definedNameIndex) {
|
||||||
return _externalNameRecords[definedNameIndex].getText();
|
return _externalNameRecords[definedNameIndex].getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getNameIx(int definedNameIndex) {
|
||||||
|
return _externalNameRecords[definedNameIndex].getIx();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs case-insensitive search
|
* Performs case-insensitive search
|
||||||
@ -316,8 +320,12 @@ final class LinkTable {
|
|||||||
if (!ebr.isExternalReferences()) {
|
if (!ebr.isExternalReferences()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
// Sheet name only applies if not a global reference
|
||||||
int shIx = _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex);
|
int shIx = _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex);
|
||||||
String usSheetName = ebr.getSheetNames()[shIx];
|
String usSheetName = null;
|
||||||
|
if(shIx >= 0) {
|
||||||
|
usSheetName = ebr.getSheetNames()[shIx];
|
||||||
|
}
|
||||||
return new String[] {
|
return new String[] {
|
||||||
ebr.getURL(),
|
ebr.getURL(),
|
||||||
usSheetName,
|
usSheetName,
|
||||||
@ -419,6 +427,10 @@ final class LinkTable {
|
|||||||
int extBookIndex = _externSheetRecord.getExtbookIndexFromRefIndex(refIndex);
|
int extBookIndex = _externSheetRecord.getExtbookIndexFromRefIndex(refIndex);
|
||||||
return _externalBookBlocks[extBookIndex].getNameText(definedNameIndex);
|
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) {
|
public NameXPtg getNameXPtg(String name) {
|
||||||
// first find any external book block that contains the 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 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 String field_4_name;
|
||||||
private Formula field_5_name_definition;
|
private Formula field_5_name_definition;
|
||||||
|
|
||||||
@ -96,6 +97,16 @@ public final class ExternalNameRecord extends StandardRecord {
|
|||||||
public String getText() {
|
public String getText() {
|
||||||
return field_4_name;
|
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(){
|
protected int getDataSize(){
|
||||||
int result = 2 + 4; // short and int
|
int result = 2 + 4; // short and int
|
||||||
@ -114,10 +125,11 @@ public final class ExternalNameRecord extends StandardRecord {
|
|||||||
|
|
||||||
public void serialize(LittleEndianOutput out) {
|
public void serialize(LittleEndianOutput out) {
|
||||||
out.writeShort(field_1_option_flag);
|
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());
|
out.writeByte(field_4_name.length());
|
||||||
StringUtil.writeUnicodeStringFlagAndData(out, field_4_name);
|
StringUtil.writeUnicodeStringFlagAndData(out, field_4_name);
|
||||||
|
|
||||||
if(!isOLELink() && !isStdDocumentNameIdentifier()){
|
if(!isOLELink() && !isStdDocumentNameIdentifier()){
|
||||||
if(isAutomaticLink()){
|
if(isAutomaticLink()){
|
||||||
@ -133,7 +145,8 @@ public final class ExternalNameRecord extends StandardRecord {
|
|||||||
|
|
||||||
public ExternalNameRecord(RecordInputStream in) {
|
public ExternalNameRecord(RecordInputStream in) {
|
||||||
field_1_option_flag = in.readShort();
|
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();
|
int numChars = in.readUByte();
|
||||||
field_4_name = StringUtil.readUnicodeString(in, numChars);
|
field_4_name = StringUtil.readUnicodeString(in, numChars);
|
||||||
@ -166,10 +179,13 @@ public final class ExternalNameRecord extends StandardRecord {
|
|||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
sb.append(getClass().getName()).append(" [EXTERNALNAME ");
|
sb.append("[EXTERNALNAME]\n");
|
||||||
sb.append(" ").append(field_4_name);
|
sb.append(" .ix = ").append(field_2_ixals).append("\n");
|
||||||
sb.append(" ix=").append(field_2_not_used);
|
sb.append(" .name = ").append(field_4_name).append("\n");
|
||||||
sb.append("]");
|
if(field_5_name_definition != null) {
|
||||||
|
sb.append(" .formula = ").append(field_5_name_definition).append("\n");
|
||||||
|
}
|
||||||
|
sb.append("[/EXTERNALNAME]\n");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,13 @@ public final class NameXPtg extends OperandPtg implements WorkbookDependentFormu
|
|||||||
public String toFormulaString() {
|
public String toFormulaString() {
|
||||||
throw new RuntimeException("3D references need a workbook to determine formula text");
|
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() {
|
public byte getDefaultOperandClass() {
|
||||||
return Ptg.CLASS_VALUE;
|
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.FormulaParsingWorkbook;
|
||||||
import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
|
import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
|
||||||
import org.apache.poi.ss.formula.FormulaType;
|
import org.apache.poi.ss.formula.FormulaType;
|
||||||
|
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal POI use only
|
* Internal POI use only
|
||||||
@ -107,6 +108,10 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
|||||||
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
||||||
return _iBook.getExternalSheet(externSheetIndex);
|
return _iBook.getExternalSheet(externSheetIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
|
||||||
|
return _iBook.getExternalName(externSheetIndex, externNameIndex);
|
||||||
|
}
|
||||||
|
|
||||||
public String resolveNameXText(NameXPtg n) {
|
public String resolveNameXText(NameXPtg n) {
|
||||||
return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex());
|
return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex());
|
||||||
|
@ -47,6 +47,7 @@ public interface EvaluationWorkbook {
|
|||||||
*/
|
*/
|
||||||
ExternalSheet getExternalSheet(int externSheetIndex);
|
ExternalSheet getExternalSheet(int externSheetIndex);
|
||||||
int convertFromExternSheetIndex(int externSheetIndex);
|
int convertFromExternSheetIndex(int externSheetIndex);
|
||||||
|
ExternalName getExternalName(int externSheetIndex, int externNameIndex);
|
||||||
EvaluationName getName(NamePtg namePtg);
|
EvaluationName getName(NamePtg namePtg);
|
||||||
String resolveNameXText(NameXPtg ptg);
|
String resolveNameXText(NameXPtg ptg);
|
||||||
Ptg[] getFormulaTokens(EvaluationCell cell);
|
Ptg[] getFormulaTokens(EvaluationCell cell);
|
||||||
@ -66,4 +67,24 @@ public interface EvaluationWorkbook {
|
|||||||
return _sheetName;
|
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;
|
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.eval.*;
|
||||||
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
||||||
import org.apache.poi.ss.SpreadsheetVersion;
|
import org.apache.poi.ss.SpreadsheetVersion;
|
||||||
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
|
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.formula.EvaluationWorkbook.ExternalSheet;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.util.CellReference;
|
||||||
import org.apache.poi.ss.util.CellReference.NameType;
|
import org.apache.poi.ss.util.CellReference.NameType;
|
||||||
@ -254,4 +259,40 @@ public final class OperationEvaluationContext {
|
|||||||
SheetRefEvaluator sre = createExternSheetRefEvaluator(extSheetIndex);
|
SheetRefEvaluator sre = createExternSheetRefEvaluator(extSheetIndex);
|
||||||
return new LazyAreaEval(firstRowIndex, firstColumnIndex, lastRowIndex, lastColumnIndex, sre);
|
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.FreeRefFunction;
|
||||||
import org.apache.poi.hssf.record.formula.functions.IfFunc;
|
import org.apache.poi.hssf.record.formula.functions.IfFunc;
|
||||||
import org.apache.poi.hssf.record.formula.udf.UDFFinder;
|
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.hssf.util.CellReference;
|
||||||
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
|
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
|
||||||
import org.apache.poi.ss.formula.eval.NotImplementedException;
|
import org.apache.poi.ss.formula.eval.NotImplementedException;
|
||||||
@ -124,6 +125,19 @@ public final class WorkbookEvaluator {
|
|||||||
/* package */ EvaluationSheet getSheet(int sheetIndex) {
|
/* package */ EvaluationSheet getSheet(int sheetIndex) {
|
||||||
return _workbook.getSheet(sheetIndex);
|
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() {
|
private static boolean isDebugLogEnabled() {
|
||||||
return false;
|
return false;
|
||||||
@ -223,6 +237,10 @@ public final class WorkbookEvaluator {
|
|||||||
}
|
}
|
||||||
return result.intValue();
|
return result.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* package */ int getSheetIndexByExternIndex(int externSheetIndex) {
|
||||||
|
return _workbook.convertFromExternSheetIndex(externSheetIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -524,7 +542,7 @@ public final class WorkbookEvaluator {
|
|||||||
throw new RuntimeException("Don't now how to evalate name '" + nameRecord.getNameText() + "'");
|
throw new RuntimeException("Don't now how to evalate name '" + nameRecord.getNameText() + "'");
|
||||||
}
|
}
|
||||||
if (ptg instanceof NameXPtg) {
|
if (ptg instanceof NameXPtg) {
|
||||||
return new NameXEval(((NameXPtg) ptg));
|
return ec.getNameXEval(((NameXPtg) ptg));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptg instanceof IntPtg) {
|
if (ptg instanceof IntPtg) {
|
||||||
|
@ -106,6 +106,10 @@ final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
|
|||||||
public EvaluationSheet getSheet(int sheetIndex) {
|
public EvaluationSheet getSheet(int sheetIndex) {
|
||||||
return getSharedSheet(getSheetName(sheetIndex));
|
return getSharedSheet(getSheetName(sheetIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
|
||||||
|
return _masterBook.getExternalName(externSheetIndex, externNameIndex);
|
||||||
|
}
|
||||||
|
|
||||||
public int getSheetIndex(EvaluationSheet sheet) {
|
public int getSheetIndex(EvaluationSheet sheet) {
|
||||||
if (sheet instanceof ForkedEvaluationSheet) {
|
if (sheet instanceof ForkedEvaluationSheet) {
|
||||||
|
@ -29,6 +29,7 @@ import org.apache.poi.ss.formula.FormulaParser;
|
|||||||
import org.apache.poi.ss.formula.FormulaParsingWorkbook;
|
import org.apache.poi.ss.formula.FormulaParsingWorkbook;
|
||||||
import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
|
import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
|
||||||
import org.apache.poi.ss.formula.FormulaType;
|
import org.apache.poi.ss.formula.FormulaType;
|
||||||
|
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,6 +95,10 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
|||||||
public String getSheetName(int sheetIndex) {
|
public String getSheetName(int sheetIndex) {
|
||||||
return _uBook.getSheetName(sheetIndex);
|
return _uBook.getSheetName(sheetIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
|
||||||
|
throw new RuntimeException("Not implemented yet");
|
||||||
|
}
|
||||||
|
|
||||||
public NameXPtg getNameXPtg(String name) {
|
public NameXPtg getNameXPtg(String name) {
|
||||||
// may require to return null to make tests pass
|
// may require to return null to make tests pass
|
||||||
|
@ -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(3, evalCount);
|
||||||
assertEquals(2.0, ((NumberEval)ve).getNumberValue(), 0D);
|
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