]> source.dussan.org Git - poi.git/commitdiff
Start preparing LazyAreaEval and LazyRefEval to handle sheet ranges, for #55906
authorNick Burch <nick@apache.org>
Fri, 25 Jul 2014 14:50:44 +0000 (14:50 +0000)
committerNick Burch <nick@apache.org>
Fri, 25 Jul 2014 14:50:44 +0000 (14:50 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1613443 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/ss/formula/LazyAreaEval.java
src/java/org/apache/poi/ss/formula/LazyRefEval.java
src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java
src/java/org/apache/poi/ss/formula/SheetRangeEvaluator.java
src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java

index c23fb4f4e4e92d761b38f4adc1eca754f7a40b46..9791641a9d459e546a77f8c9fb67a91fb0f99525 100644 (file)
 
 package org.apache.poi.ss.formula;
 
-import org.apache.poi.ss.formula.ptg.AreaI;
-import org.apache.poi.ss.formula.ptg.AreaI.OffsetArea;
 import org.apache.poi.ss.formula.eval.AreaEval;
 import org.apache.poi.ss.formula.eval.AreaEvalBase;
 import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.ptg.AreaI;
+import org.apache.poi.ss.formula.ptg.AreaI.OffsetArea;
 import org.apache.poi.ss.util.CellReference;
 
 /**
- *
- * @author Josh Micich
+ * Provides Lazy Evaluation to a 3D Ranges
+ * 
+ * TODO Provide access to multiple sheets where present
  */
 final class LazyAreaEval extends AreaEvalBase {
+       private final SheetRangeEvaluator _evaluator;
 
-       private final SheetRefEvaluator _evaluator;
-
-       LazyAreaEval(AreaI ptg, SheetRefEvaluator evaluator) {
+       LazyAreaEval(AreaI ptg, SheetRangeEvaluator evaluator) {
                super(ptg);
                _evaluator = evaluator;
        }
 
        public LazyAreaEval(int firstRowIndex, int firstColumnIndex, int lastRowIndex,
-                       int lastColumnIndex, SheetRefEvaluator evaluator) {
+                       int lastColumnIndex, SheetRangeEvaluator evaluator) {
                super(firstRowIndex, firstColumnIndex, lastRowIndex, lastColumnIndex);
                _evaluator = evaluator;
        }
@@ -48,7 +48,7 @@ final class LazyAreaEval extends AreaEvalBase {
                int rowIx = (relativeRowIndex + getFirstRow() ) ;
                int colIx = (relativeColumnIndex + getFirstColumn() ) ;
 
-               return _evaluator.getEvalForCell(rowIx, colIx);
+               return _evaluator.getEvalForCell(_evaluator.getFirstSheetIndex(), rowIx, colIx);
        }
 
        public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
@@ -79,7 +79,7 @@ final class LazyAreaEval extends AreaEvalBase {
                CellReference crB = new CellReference(getLastRow(), getLastColumn());
                StringBuffer sb = new StringBuffer();
                sb.append(getClass().getName()).append("[");
-               sb.append(_evaluator.getSheetName());
+               sb.append(_evaluator.getSheetNameRange());
                sb.append('!');
                sb.append(crA.formatAsString());
                sb.append(':');
@@ -93,6 +93,7 @@ final class LazyAreaEval extends AreaEvalBase {
     */
     public boolean isSubTotal(int rowIndex, int columnIndex){
         // delegate the query to the sheet evaluator which has access to internal ptgs
-        return _evaluator.isSubTotal(getFirstRow() + rowIndex, getFirstColumn() + columnIndex);
+        SheetRefEvaluator _sre = _evaluator.getSheetEvaluator(_evaluator.getFirstSheetIndex());
+        return _sre.isSubTotal(getFirstRow() + rowIndex, getFirstColumn() + columnIndex);
     }
 }
index 167fd102e538e7a52ecc819f2251cb174d3f0473..b813cb7ebc67f36ec4b3db6bb2073a081f9f720a 100644 (file)
 
 package org.apache.poi.ss.formula;
 
-import org.apache.poi.ss.formula.ptg.AreaI;
-import org.apache.poi.ss.formula.ptg.AreaI.OffsetArea;
 import org.apache.poi.ss.formula.eval.AreaEval;
 import org.apache.poi.ss.formula.eval.RefEvalBase;
 import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.ptg.AreaI;
+import org.apache.poi.ss.formula.ptg.AreaI.OffsetArea;
 import org.apache.poi.ss.util.CellReference;
 
 /**
-*
-* @author Josh Micich
-*/
+ * Provides Lazy Evaluation to a 3D Reference
+ * 
+ * TODO Provide access to multiple sheets where present
+ */
 final class LazyRefEval extends RefEvalBase {
+       private final SheetRangeEvaluator _evaluator;
 
-       private final SheetRefEvaluator _evaluator;
-
-       public LazyRefEval(int rowIndex, int columnIndex, SheetRefEvaluator sre) {
+       public LazyRefEval(int rowIndex, int columnIndex, SheetRangeEvaluator sre) {
                super(rowIndex, columnIndex);
                if (sre == null) {
                        throw new IllegalArgumentException("sre must not be null");
@@ -41,7 +41,7 @@ final class LazyRefEval extends RefEvalBase {
        }
 
        public ValueEval getInnerValueEval() {
-               return _evaluator.getEvalForCell(getRow(), getColumn());
+               return _evaluator.getEvalForCell(_evaluator.getFirstSheetIndex(), getRow(), getColumn());
        }
 
        public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
@@ -56,7 +56,7 @@ final class LazyRefEval extends RefEvalBase {
                CellReference cr = new CellReference(getRow(), getColumn());
                StringBuffer sb = new StringBuffer();
                sb.append(getClass().getName()).append("[");
-               sb.append(_evaluator.getSheetName());
+               sb.append(_evaluator.getSheetNameRange());
                sb.append('!');
                sb.append(cr.formatAsString());
                sb.append("]");
index 6cbc9c95b7029cba136afcea0e147968d121df57..6dba12aba853cf3603f84a0b6a3f980f9b0163ed 100644 (file)
@@ -21,6 +21,7 @@ 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.EvaluationWorkbook.ExternalSheetRange;
 import org.apache.poi.ss.formula.eval.AreaEval;
 import org.apache.poi.ss.formula.eval.ErrorEval;
 import org.apache.poi.ss.formula.eval.ExternalNameEval;
@@ -75,24 +76,30 @@ public final class OperationEvaluationContext {
                return _columnIndex;
        }
 
-       SheetRefEvaluator createExternSheetRefEvaluator(ExternSheetReferenceToken ptg) {
+       SheetRangeEvaluator createExternSheetRefEvaluator(ExternSheetReferenceToken ptg) {
                return createExternSheetRefEvaluator(ptg.getExternSheetIndex());
        }
-    SheetRefEvaluator createExternSheetRefEvaluator(String sheetName, int externalWorkbookNumber) {
+       SheetRangeEvaluator createExternSheetRefEvaluator(String sheetName, int externalWorkbookNumber) {
         ExternalSheet externalSheet = _workbook.getExternalSheet(sheetName, null, externalWorkbookNumber);
         return createExternSheetRefEvaluator(externalSheet);
     }
-       SheetRefEvaluator createExternSheetRefEvaluator(int externSheetIndex) {
+       SheetRangeEvaluator createExternSheetRefEvaluator(int externSheetIndex) {
                ExternalSheet externalSheet = _workbook.getExternalSheet(externSheetIndex);
         return createExternSheetRefEvaluator(externalSheet);
        }
-    SheetRefEvaluator createExternSheetRefEvaluator(ExternalSheet externalSheet) {
+       SheetRangeEvaluator createExternSheetRefEvaluator(ExternalSheet externalSheet) {
                WorkbookEvaluator targetEvaluator;
-               int otherSheetIndex;
+               int otherFirstSheetIndex;
+               int otherLastSheetIndex = -1;
                if (externalSheet == null || externalSheet.getWorkbookName() == null) {
                        // sheet is in same workbook
-                       otherSheetIndex = _workbook.getSheetIndex(externalSheet.getSheetName());
                        targetEvaluator = _bookEvaluator;
+                       otherFirstSheetIndex = _workbook.getSheetIndex(externalSheet.getSheetName());
+                       
+                       if (externalSheet instanceof ExternalSheetRange) {
+                           String lastSheetName = ((ExternalSheetRange)externalSheet).getLastSheetName();
+                           otherLastSheetIndex = _workbook.getSheetIndex(lastSheetName);
+                       }
                } else {
                        // look up sheet by name from external workbook
                        String workbookName = externalSheet.getWorkbookName();
@@ -101,13 +108,30 @@ public final class OperationEvaluationContext {
                        } catch (WorkbookNotFoundException e) {
                                throw new RuntimeException(e.getMessage(), e);
                        }
-                       otherSheetIndex = targetEvaluator.getSheetIndex(externalSheet.getSheetName());
-                       if (otherSheetIndex < 0) {
+                       
+                       otherFirstSheetIndex = targetEvaluator.getSheetIndex(externalSheet.getSheetName());
+            if (externalSheet instanceof ExternalSheetRange) {
+                String lastSheetName = ((ExternalSheetRange)externalSheet).getLastSheetName();
+                otherLastSheetIndex = targetEvaluator.getSheetIndex(lastSheetName);
+            }
+                       
+                       if (otherFirstSheetIndex < 0) {
                                throw new RuntimeException("Invalid sheet name '" + externalSheet.getSheetName()
                                                + "' in bool '" + workbookName + "'.");
                        }
                }
-               return new SheetRefEvaluator(targetEvaluator, _tracker, otherSheetIndex);
+               
+               if (otherLastSheetIndex == -1) {
+                   // Reference to just one sheet
+                   otherLastSheetIndex = otherFirstSheetIndex;
+               }
+               
+               SheetRefEvaluator[] evals = new SheetRefEvaluator[otherLastSheetIndex-otherFirstSheetIndex+1];
+               for (int i=0; i<evals.length; i++) {
+                   int otherSheetIndex = i+otherFirstSheetIndex;
+                   evals[i] = new SheetRefEvaluator(targetEvaluator, _tracker, otherSheetIndex); 
+               }
+               return new SheetRangeEvaluator(otherFirstSheetIndex, otherLastSheetIndex, evals);
        }
 
        /**
@@ -134,8 +158,9 @@ public final class OperationEvaluationContext {
                return new SheetRefEvaluator(targetEvaluator, _tracker, otherSheetIndex);
        }
 
-       public SheetRefEvaluator getRefEvaluatorForCurrentSheet() {
-               return new SheetRefEvaluator(_bookEvaluator, _tracker, _sheetIndex);
+       public SheetRangeEvaluator getRefEvaluatorForCurrentSheet() {
+               SheetRefEvaluator sre = new SheetRefEvaluator(_bookEvaluator, _tracker, _sheetIndex);
+               return new SheetRangeEvaluator(_sheetIndex, sre);
        }
 
 
@@ -162,10 +187,12 @@ public final class OperationEvaluationContext {
                if (!isA1Style) {
                        throw new RuntimeException("R1C1 style not supported yet");
                }
-               SheetRefEvaluator sre = createExternSheetRefEvaluator(workbookName, sheetName);
-               if (sre == null) {
+               SheetRefEvaluator se = createExternSheetRefEvaluator(workbookName, sheetName);
+               if (se == null) {
                        return ErrorEval.REF_INVALID;
                }
+               SheetRangeEvaluator sre = new SheetRangeEvaluator(_sheetIndex, se);
+               
                // ugly typecast - TODO - make spreadsheet version more easily accessible
                SpreadsheetVersion ssVersion = ((FormulaParsingWorkbook)_workbook).getSpreadsheetVersion();
 
@@ -271,30 +298,30 @@ public final class OperationEvaluationContext {
        }
 
        public ValueEval getRefEval(int rowIndex, int columnIndex) {
-               SheetRefEvaluator sre = getRefEvaluatorForCurrentSheet();
+           SheetRangeEvaluator sre = getRefEvaluatorForCurrentSheet();
                return new LazyRefEval(rowIndex, columnIndex, sre);
        }
        public ValueEval getRef3DEval(Ref3DPtg rptg) {
-               SheetRefEvaluator sre = createExternSheetRefEvaluator(rptg.getExternSheetIndex());
+           SheetRangeEvaluator sre = createExternSheetRefEvaluator(rptg.getExternSheetIndex());
                return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre);
        }
     public ValueEval getRef3DEval(Ref3DPxg rptg) {
-        SheetRefEvaluator sre = createExternSheetRefEvaluator(rptg.getSheetName(), rptg.getExternalWorkbookNumber());
+        SheetRangeEvaluator 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();
+           SheetRangeEvaluator sre = getRefEvaluatorForCurrentSheet();
                return new LazyAreaEval(firstRowIndex, firstColumnIndex, lastRowIndex, lastColumnIndex, sre);
        }
     public ValueEval getArea3DEval(Area3DPtg aptg) {
-        SheetRefEvaluator sre = createExternSheetRefEvaluator(aptg.getExternSheetIndex());
+        SheetRangeEvaluator sre = createExternSheetRefEvaluator(aptg.getExternSheetIndex());
         return new LazyAreaEval(aptg.getFirstRow(), aptg.getFirstColumn(),
                 aptg.getLastRow(), aptg.getLastColumn(), sre);
     }
     public ValueEval getArea3DEval(Area3DPxg aptg) {
-        SheetRefEvaluator sre = createExternSheetRefEvaluator(aptg.getSheetName(), aptg.getExternalWorkbookNumber());
+        SheetRangeEvaluator sre = createExternSheetRefEvaluator(aptg.getSheetName(), aptg.getExternalWorkbookNumber());
         return new LazyAreaEval(aptg.getFirstRow(), aptg.getFirstColumn(),
                 aptg.getLastRow(), aptg.getLastColumn(), sre);
     }
index 9157a1d0daa20e12c5ff3e20d05fc11c2f207083..92200dd642678ba3d3eb5a15e35f2c26f340f2a0 100644 (file)
@@ -38,6 +38,9 @@ final class SheetRangeEvaluator {
         _lastSheetIndex = lastSheetIndex;
         _sheetEvaluators = sheetEvaluators;
        }
+    public SheetRangeEvaluator(int onlySheetIndex, SheetRefEvaluator sheetEvaluator) {
+        this(onlySheetIndex, onlySheetIndex, new SheetRefEvaluator[] {sheetEvaluator});
+    }
        
        public SheetRefEvaluator getSheetEvaluator(int sheetIndex) {
            if (sheetIndex < _firstSheetIndex || sheetIndex > _lastSheetIndex) {
@@ -46,10 +49,26 @@ final class SheetRangeEvaluator {
            }
            return _sheetEvaluators[sheetIndex-_firstSheetIndex];
        }
+       
+       public int getFirstSheetIndex() {
+           return _firstSheetIndex;
+       }
+    public int getLastSheetIndex() {
+        return _lastSheetIndex;
+    }
 
        public String getSheetName(int sheetIndex) {
            return getSheetEvaluator(sheetIndex).getSheetName();
        }
+       public String getSheetNameRange() {
+           StringBuilder sb = new StringBuilder();
+           sb.append(getSheetName(_firstSheetIndex));
+           if (_firstSheetIndex != _lastSheetIndex) {
+               sb.append(':');
+               sb.append(getSheetName(_lastSheetIndex));
+           }
+           return sb.toString();
+       }
 
        public ValueEval getEvalForCell(int sheetIndex, int rowIndex, int columnIndex) {
         return getSheetEvaluator(sheetIndex).getEvalForCell(rowIndex, columnIndex);
index 92318d87d9a749296b378ebef7e7d4e271cb0a1d..8a32c9c8b1a1a582089b504cf478a830ee194a29 100644 (file)
@@ -427,7 +427,7 @@ public final class WorkbookEvaluator {
                        dbgIndentStr = "                                                                                                    ";
                        dbgIndentStr = dbgIndentStr.substring(0, Math.min(dbgIndentStr.length(), dbgEvaluationOutputIndent*2));
                        EVAL_LOG.log(POILogger.WARN, dbgIndentStr
-                                          + "- evaluateFormula('" + ec.getRefEvaluatorForCurrentSheet().getSheetName()
+                                          + "- evaluateFormula('" + ec.getRefEvaluatorForCurrentSheet().getSheetNameRange()
                                           + "'/" + new CellReference(ec.getRowIndex(), ec.getColumnIndex()).formatAsString()
                                           + "): " + Arrays.toString(ptgs).replaceAll("\\Qorg.apache.poi.ss.formula.ptg.\\E", ""));
                        dbgEvaluationOutputIndent++;