diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java
index 877a8f21de..6b8c30dc39 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java
@@ -120,10 +120,29 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
}
public ExternalSheet getExternalSheet(int externSheetIndex) {
- return _iBook.getExternalSheet(externSheetIndex);
+ ExternalSheet sheet = _iBook.getExternalSheet(externSheetIndex);
+ if (sheet == null) {
+ // Try to treat it as a local sheet
+ int localSheetIndex = convertFromExternSheetIndex(externSheetIndex);
+ if (localSheetIndex == -1) {
+ // The sheet referenced can't be found, sorry
+ return null;
+ }
+ if (localSheetIndex == -2) {
+ // Not actually sheet based at all - is workbook scoped
+ return null;
+ }
+ // Look up the local sheet
+ String sheetName = getSheetName(localSheetIndex);
+ sheet = new ExternalSheet(null, sheetName);
+ }
+ return sheet;
}
-
- public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
+ public ExternalSheet getExternalSheet(String sheetName, int externalWorkbookNumber) {
+ throw new IllegalStateException("XSSF-style external references are not supported for HSSF");
+ }
+
+ public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
return _iBook.getExternalName(externSheetIndex, externNameIndex);
}
@@ -141,7 +160,9 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
int ix = namePtg.getIndex();
return new Name(_iBook.getNameRecord(ix), ix);
}
- public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
+
+ @SuppressWarnings("unused")
+ 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
@@ -159,6 +180,7 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
return fra.getFormulaTokens();
}
+
public UDFFinder getUDFFinder(){
return _uBook.getUDFFinder();
}
diff --git a/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java b/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java
index 49f4598f5a..ca87e313a3 100644
--- a/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java
+++ b/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java
@@ -44,10 +44,21 @@ public interface EvaluationWorkbook {
EvaluationSheet getSheet(int sheetIndex);
/**
- * @return null
if externSheetIndex refers to a sheet inside the current workbook
+ * HSSF Only - fetch the external-style sheet details
+ *
Return will have no workbook set if it's actually in our own workbook
*/ ExternalSheet getExternalSheet(int externSheetIndex); + /** + * XSSF Only - fetch the external-style sheet details + *Return will have no workbook set if it's actually in our own workbook
+ */ + ExternalSheet getExternalSheet(String sheetName, int externalWorkbookNumber); + /** + * HSSF Only - convert an external sheet index to an internal sheet index, + * for an external-style reference to one of this workbook's own sheets + */ int convertFromExternSheetIndex(int externSheetIndex); + ExternalName getExternalName(int externSheetIndex, int externNameIndex); EvaluationName getName(NamePtg namePtg); EvaluationName getName(String name, int sheetIndex); diff --git a/src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java b/src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java index 6bf3ed6e32..aad61c5905 100644 --- a/src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java +++ b/src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java @@ -17,16 +17,21 @@ package org.apache.poi.ss.formula; -import org.apache.poi.ss.formula.ptg.Area3DPtg; -import org.apache.poi.ss.formula.ptg.NameXPtg; -import org.apache.poi.ss.formula.ptg.Ptg; -import org.apache.poi.ss.formula.ptg.Ref3DPtg; -import org.apache.poi.ss.formula.eval.*; -import org.apache.poi.ss.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.formula.eval.AreaEval; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.NameXEval; +import org.apache.poi.ss.formula.eval.RefEval; +import org.apache.poi.ss.formula.eval.ValueEval; +import org.apache.poi.ss.formula.functions.FreeRefFunction; +import org.apache.poi.ss.formula.ptg.Area3DPtg; +import org.apache.poi.ss.formula.ptg.NameXPtg; +import org.apache.poi.ss.formula.ptg.Ptg; +import org.apache.poi.ss.formula.ptg.Ref3DPtg; +import org.apache.poi.ss.formula.ptg.Ref3DPxg; import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.util.CellReference.NameType; @@ -70,13 +75,20 @@ public final class OperationEvaluationContext { SheetRefEvaluator createExternSheetRefEvaluator(ExternSheetReferenceToken ptg) { return createExternSheetRefEvaluator(ptg.getExternSheetIndex()); } + SheetRefEvaluator createExternSheetRefEvaluator(String sheetName, int externalWorkbookNumber) { + ExternalSheet externalSheet = _workbook.getExternalSheet(sheetName, externalWorkbookNumber); + return createExternSheetRefEvaluator(externalSheet); + } SheetRefEvaluator createExternSheetRefEvaluator(int externSheetIndex) { ExternalSheet externalSheet = _workbook.getExternalSheet(externSheetIndex); + return createExternSheetRefEvaluator(externalSheet); + } + SheetRefEvaluator createExternSheetRefEvaluator(ExternalSheet externalSheet) { WorkbookEvaluator targetEvaluator; int otherSheetIndex; - if (externalSheet == null) { + if (externalSheet == null || externalSheet.getWorkbookName() == null) { // sheet is in same workbook - otherSheetIndex = _workbook.convertFromExternSheetIndex(externSheetIndex); + otherSheetIndex = _workbook.getSheetIndex(externalSheet.getSheetName()); targetEvaluator = _bookEvaluator; } else { // look up sheet by name from external workbook @@ -259,10 +271,14 @@ public final class OperationEvaluationContext { SheetRefEvaluator sre = getRefEvaluatorForCurrentSheet(); return new LazyRefEval(rowIndex, columnIndex, sre); } - public ValueEval getRef3DEval(int rowIndex, int columnIndex, int extSheetIndex) { - SheetRefEvaluator sre = createExternSheetRefEvaluator(extSheetIndex); - return new LazyRefEval(rowIndex, columnIndex, sre); + public ValueEval getRef3DEval(Ref3DPtg rptg) { + SheetRefEvaluator sre = createExternSheetRefEvaluator(rptg.getExternSheetIndex()); + return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre); } + public ValueEval getRef3DEval(Ref3DPxg rptg) { + SheetRefEvaluator sre = createExternSheetRefEvaluator(rptg.getSheetName(), rptg.getExternalWorkbookNumber()); + return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre); + } public ValueEval getAreaEval(int firstRowIndex, int firstColumnIndex, int lastRowIndex, int lastColumnIndex) { SheetRefEvaluator sre = getRefEvaluatorForCurrentSheet(); diff --git a/src/java/org/apache/poi/ss/formula/SheetRefEvaluator.java b/src/java/org/apache/poi/ss/formula/SheetRefEvaluator.java index 1746690050..7452d5ab58 100644 --- a/src/java/org/apache/poi/ss/formula/SheetRefEvaluator.java +++ b/src/java/org/apache/poi/ss/formula/SheetRefEvaluator.java @@ -28,7 +28,6 @@ import org.apache.poi.ss.usermodel.Cell; * @author Josh Micich */ final class SheetRefEvaluator { - private final WorkbookEvaluator _bookEvaluator; private final EvaluationTracker _tracker; private final int _sheetIndex; diff --git a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java index 3d583138cd..3daa8714cc 100644 --- a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java +++ b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java @@ -673,12 +673,10 @@ public final class WorkbookEvaluator { return ErrorEval.REF_INVALID; } if (ptg instanceof Ref3DPtg) { - Ref3DPtg rptg = (Ref3DPtg) ptg; - return ec.getRef3DEval(rptg.getRow(), rptg.getColumn(), rptg.getExternSheetIndex()); + return ec.getRef3DEval((Ref3DPtg)ptg); } if (ptg instanceof Ref3DPxg) { - Ref3DPtg rptg = (Ref3DPtg) ptg; - // TODO Return the right eval, should be easy as we already know the sheet details + return ec.getRef3DEval((Ref3DPxg)ptg); } if (ptg instanceof Area3DPtg) { Area3DPtg aptg = (Area3DPtg) ptg; diff --git a/src/java/org/apache/poi/ss/formula/eval/forked/ForkedEvaluationWorkbook.java b/src/java/org/apache/poi/ss/formula/eval/forked/ForkedEvaluationWorkbook.java index 28aacc215e..442b748593 100644 --- a/src/java/org/apache/poi/ss/formula/eval/forked/ForkedEvaluationWorkbook.java +++ b/src/java/org/apache/poi/ss/formula/eval/forked/ForkedEvaluationWorkbook.java @@ -20,13 +20,13 @@ package org.apache.poi.ss.formula.eval.forked; import java.util.HashMap; import java.util.Map; -import org.apache.poi.ss.formula.ptg.NamePtg; -import org.apache.poi.ss.formula.ptg.NameXPtg; -import org.apache.poi.ss.formula.ptg.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.ptg.NamePtg; +import org.apache.poi.ss.formula.ptg.NameXPtg; +import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.udf.UDFFinder; import org.apache.poi.ss.usermodel.Workbook; @@ -90,8 +90,11 @@ final class ForkedEvaluationWorkbook implements EvaluationWorkbook { public ExternalSheet getExternalSheet(int externSheetIndex) { return _masterBook.getExternalSheet(externSheetIndex); } + public ExternalSheet getExternalSheet(String sheetName, int externalWorkbookNumber) { + return _masterBook.getExternalSheet(sheetName, externalWorkbookNumber); + } - public Ptg[] getFormulaTokens(EvaluationCell cell) { + public Ptg[] getFormulaTokens(EvaluationCell cell) { if (cell instanceof ForkedEvaluationCell) { // doesn't happen yet because formulas cannot be modified from the master workbook throw new RuntimeException("Updated formulas not supported yet"); diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java index 5a4bfa534b..5f326b6ad7 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java @@ -37,6 +37,7 @@ import org.apache.poi.ss.formula.udf.IndexedUDFFinder; import org.apache.poi.ss.formula.udf.UDFFinder; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellReference; +import org.apache.poi.xssf.model.ExternalLinksTable; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName; /** @@ -63,7 +64,8 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E return externSheetIndex; } /** - * @return the sheet index of the sheet with the given external index. + * XSSF doesn't use external sheet indexes, so when asked treat + * it just as a local index */ public int convertFromExternSheetIndex(int externSheetIndex) { return externSheetIndex; @@ -175,10 +177,21 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E } public ExternalSheet getExternalSheet(int externSheetIndex) { - // TODO Auto-generated method stub - return null; + throw new IllegalStateException("HSSF-style external references are not supported for XSSF"); } - public int getExternalSheetIndex(String workbookName, String sheetName) { + public ExternalSheet getExternalSheet(String sheetName, int externalWorkbookNumber) { + if (externalWorkbookNumber > 0) { + // External reference - reference is 1 based, link table is 0 based + int linkNumber = externalWorkbookNumber - 1; + ExternalLinksTable linkTable = _uBook.getExternalLinksTable().get(linkNumber); + return new ExternalSheet(linkTable.getLinkedFileName(), sheetName); + } else { + // Internal reference + return new ExternalSheet(null, sheetName); + } + } + + public int getExternalSheetIndex(String workbookName, String sheetName) { throw new RuntimeException("not implemented yet"); } public int getSheetIndex(String sheetName) {