From d97867e5bee87d1c8273d00cc92c0ebb4482f614 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Fri, 25 Jul 2014 14:50:44 +0000 Subject: [PATCH] Start preparing LazyAreaEval and LazyRefEval to handle sheet ranges, for #55906 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1613443 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/ss/formula/LazyAreaEval.java | 23 +++---- .../apache/poi/ss/formula/LazyRefEval.java | 20 +++--- .../formula/OperationEvaluationContext.java | 65 +++++++++++++------ .../poi/ss/formula/SheetRangeEvaluator.java | 19 ++++++ .../poi/ss/formula/WorkbookEvaluator.java | 2 +- 5 files changed, 88 insertions(+), 41 deletions(-) diff --git a/src/java/org/apache/poi/ss/formula/LazyAreaEval.java b/src/java/org/apache/poi/ss/formula/LazyAreaEval.java index c23fb4f4e..9791641a9 100644 --- a/src/java/org/apache/poi/ss/formula/LazyAreaEval.java +++ b/src/java/org/apache/poi/ss/formula/LazyAreaEval.java @@ -17,28 +17,28 @@ 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); } } diff --git a/src/java/org/apache/poi/ss/formula/LazyRefEval.java b/src/java/org/apache/poi/ss/formula/LazyRefEval.java index 167fd102e..b813cb7eb 100644 --- a/src/java/org/apache/poi/ss/formula/LazyRefEval.java +++ b/src/java/org/apache/poi/ss/formula/LazyRefEval.java @@ -17,22 +17,22 @@ 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("]"); diff --git a/src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java b/src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java index 6cbc9c95b..6dba12aba 100644 --- a/src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java +++ b/src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java @@ -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 _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); diff --git a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java index 92318d87d..8a32c9c8b 100644 --- a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java +++ b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java @@ -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++;