]> source.dussan.org Git - poi.git/commitdiff
Start to update how the formula parser looks up sheets from formula ptgs, to account...
authorNick Burch <nick@apache.org>
Sat, 19 Jul 2014 19:19:06 +0000 (19:19 +0000)
committerNick Burch <nick@apache.org>
Sat, 19 Jul 2014 19:19:06 +0000 (19:19 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1611948 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java
src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java
src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java
src/java/org/apache/poi/ss/formula/SheetRefEvaluator.java
src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
src/java/org/apache/poi/ss/formula/eval/forked/ForkedEvaluationWorkbook.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java

index 877a8f21debac6944b46ef07c15a72f6582178ae..6b8c30dc3980fc9c3faf160d94c73a885b6fa995 100644 (file)
@@ -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();
     }
index 49f4598f5a3c695595326847b485cbfc9015b044..ca87e313a36c7144244443ef3acb615aa3eb0dd1 100644 (file)
@@ -44,10 +44,21 @@ public interface EvaluationWorkbook {
        EvaluationSheet getSheet(int sheetIndex);
 
        /**
-        * @return <code>null</code> if externSheetIndex refers to a sheet inside the current workbook
+        * HSSF Only - fetch the external-style sheet details
+        * <p>Return will have no workbook set if it's actually in our own workbook</p>
         */
        ExternalSheet getExternalSheet(int externSheetIndex);
+       /**
+        * XSSF Only - fetch the external-style sheet details
+     * <p>Return will have no workbook set if it's actually in our own workbook</p>
+        */
+       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);
index 6bf3ed6e32606520a847c274a45f4718343b5886..aad61c590532471edaefa2e4cc34b3582a5fcf18 100644 (file)
 
 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();
index 174669005038a7846c3949c66a0290a6eff5c057..7452d5ab5810cfb54e010909b70cbca7a3551d4e 100644 (file)
@@ -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;
index 3d583138cdf65e5fdba848f341d1870bb3b70eb6..3daa8714cc0fd90bf27d1436c328485cfdf6a913 100644 (file)
@@ -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;
index 28aacc215e6241dac32620ff7ec165451656df99..442b74859375cb0f3572150e6fecfe2ff9992128 100644 (file)
@@ -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");
index 5a4bfa534bfb9cb3ddfbc6c90a360eb30888c7dc..5f326b6ad7d8572417625b78187e3c63252e0c6b 100644 (file)
@@ -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) {