From: Nick Burch Date: Sat, 19 Jul 2014 19:19:06 +0000 (+0000) Subject: Start to update how the formula parser looks up sheets from formula ptgs, to account... X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=2cd4290460c245bcb9019d1c67afd36a6da98985;p=poi.git Start to update how the formula parser looks up sheets from formula ptgs, to account for the differences in how HSSF and XSSF store references to external sheets. For #56737 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1611948 13f79535-47bb-0310-9956-ffa450edef68 --- 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); - } - - public ExternalName getExternalName(int externSheetIndex, int externNameIndex) { + 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 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) {