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
This commit is contained in:
Nick Burch 2014-07-25 14:50:44 +00:00
parent 3e2e01c149
commit d97867e5be
5 changed files with 88 additions and 41 deletions

View File

@ -17,28 +17,28 @@
package org.apache.poi.ss.formula; 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.AreaEval;
import org.apache.poi.ss.formula.eval.AreaEvalBase; import org.apache.poi.ss.formula.eval.AreaEvalBase;
import org.apache.poi.ss.formula.eval.ValueEval; 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; import org.apache.poi.ss.util.CellReference;
/** /**
* * Provides Lazy Evaluation to a 3D Ranges
* @author Josh Micich *
* TODO Provide access to multiple sheets where present
*/ */
final class LazyAreaEval extends AreaEvalBase { final class LazyAreaEval extends AreaEvalBase {
private final SheetRangeEvaluator _evaluator;
private final SheetRefEvaluator _evaluator; LazyAreaEval(AreaI ptg, SheetRangeEvaluator evaluator) {
LazyAreaEval(AreaI ptg, SheetRefEvaluator evaluator) {
super(ptg); super(ptg);
_evaluator = evaluator; _evaluator = evaluator;
} }
public LazyAreaEval(int firstRowIndex, int firstColumnIndex, int lastRowIndex, public LazyAreaEval(int firstRowIndex, int firstColumnIndex, int lastRowIndex,
int lastColumnIndex, SheetRefEvaluator evaluator) { int lastColumnIndex, SheetRangeEvaluator evaluator) {
super(firstRowIndex, firstColumnIndex, lastRowIndex, lastColumnIndex); super(firstRowIndex, firstColumnIndex, lastRowIndex, lastColumnIndex);
_evaluator = evaluator; _evaluator = evaluator;
} }
@ -48,7 +48,7 @@ final class LazyAreaEval extends AreaEvalBase {
int rowIx = (relativeRowIndex + getFirstRow() ) ; int rowIx = (relativeRowIndex + getFirstRow() ) ;
int colIx = (relativeColumnIndex + getFirstColumn() ) ; 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) { 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()); CellReference crB = new CellReference(getLastRow(), getLastColumn());
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append(getClass().getName()).append("["); sb.append(getClass().getName()).append("[");
sb.append(_evaluator.getSheetName()); sb.append(_evaluator.getSheetNameRange());
sb.append('!'); sb.append('!');
sb.append(crA.formatAsString()); sb.append(crA.formatAsString());
sb.append(':'); sb.append(':');
@ -93,6 +93,7 @@ final class LazyAreaEval extends AreaEvalBase {
*/ */
public boolean isSubTotal(int rowIndex, int columnIndex){ public boolean isSubTotal(int rowIndex, int columnIndex){
// delegate the query to the sheet evaluator which has access to internal ptgs // 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);
} }
} }

View File

@ -17,22 +17,22 @@
package org.apache.poi.ss.formula; 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.AreaEval;
import org.apache.poi.ss.formula.eval.RefEvalBase; import org.apache.poi.ss.formula.eval.RefEvalBase;
import org.apache.poi.ss.formula.eval.ValueEval; 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; import org.apache.poi.ss.util.CellReference;
/** /**
* * Provides Lazy Evaluation to a 3D Reference
* @author Josh Micich *
*/ * TODO Provide access to multiple sheets where present
*/
final class LazyRefEval extends RefEvalBase { final class LazyRefEval extends RefEvalBase {
private final SheetRangeEvaluator _evaluator;
private final SheetRefEvaluator _evaluator; public LazyRefEval(int rowIndex, int columnIndex, SheetRangeEvaluator sre) {
public LazyRefEval(int rowIndex, int columnIndex, SheetRefEvaluator sre) {
super(rowIndex, columnIndex); super(rowIndex, columnIndex);
if (sre == null) { if (sre == null) {
throw new IllegalArgumentException("sre must not be null"); throw new IllegalArgumentException("sre must not be null");
@ -41,7 +41,7 @@ final class LazyRefEval extends RefEvalBase {
} }
public ValueEval getInnerValueEval() { 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) { 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()); CellReference cr = new CellReference(getRow(), getColumn());
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append(getClass().getName()).append("["); sb.append(getClass().getName()).append("[");
sb.append(_evaluator.getSheetName()); sb.append(_evaluator.getSheetNameRange());
sb.append('!'); sb.append('!');
sb.append(cr.formatAsString()); sb.append(cr.formatAsString());
sb.append("]"); sb.append("]");

View 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.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName; import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet; 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.AreaEval;
import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.ExternalNameEval; import org.apache.poi.ss.formula.eval.ExternalNameEval;
@ -75,24 +76,30 @@ public final class OperationEvaluationContext {
return _columnIndex; return _columnIndex;
} }
SheetRefEvaluator createExternSheetRefEvaluator(ExternSheetReferenceToken ptg) { SheetRangeEvaluator createExternSheetRefEvaluator(ExternSheetReferenceToken ptg) {
return createExternSheetRefEvaluator(ptg.getExternSheetIndex()); return createExternSheetRefEvaluator(ptg.getExternSheetIndex());
} }
SheetRefEvaluator createExternSheetRefEvaluator(String sheetName, int externalWorkbookNumber) { SheetRangeEvaluator createExternSheetRefEvaluator(String sheetName, int externalWorkbookNumber) {
ExternalSheet externalSheet = _workbook.getExternalSheet(sheetName, null, externalWorkbookNumber); ExternalSheet externalSheet = _workbook.getExternalSheet(sheetName, null, externalWorkbookNumber);
return createExternSheetRefEvaluator(externalSheet); return createExternSheetRefEvaluator(externalSheet);
} }
SheetRefEvaluator createExternSheetRefEvaluator(int externSheetIndex) { SheetRangeEvaluator createExternSheetRefEvaluator(int externSheetIndex) {
ExternalSheet externalSheet = _workbook.getExternalSheet(externSheetIndex); ExternalSheet externalSheet = _workbook.getExternalSheet(externSheetIndex);
return createExternSheetRefEvaluator(externalSheet); return createExternSheetRefEvaluator(externalSheet);
} }
SheetRefEvaluator createExternSheetRefEvaluator(ExternalSheet externalSheet) { SheetRangeEvaluator createExternSheetRefEvaluator(ExternalSheet externalSheet) {
WorkbookEvaluator targetEvaluator; WorkbookEvaluator targetEvaluator;
int otherSheetIndex; int otherFirstSheetIndex;
int otherLastSheetIndex = -1;
if (externalSheet == null || externalSheet.getWorkbookName() == null) { if (externalSheet == null || externalSheet.getWorkbookName() == null) {
// sheet is in same workbook // sheet is in same workbook
otherSheetIndex = _workbook.getSheetIndex(externalSheet.getSheetName());
targetEvaluator = _bookEvaluator; targetEvaluator = _bookEvaluator;
otherFirstSheetIndex = _workbook.getSheetIndex(externalSheet.getSheetName());
if (externalSheet instanceof ExternalSheetRange) {
String lastSheetName = ((ExternalSheetRange)externalSheet).getLastSheetName();
otherLastSheetIndex = _workbook.getSheetIndex(lastSheetName);
}
} else { } else {
// look up sheet by name from external workbook // look up sheet by name from external workbook
String workbookName = externalSheet.getWorkbookName(); String workbookName = externalSheet.getWorkbookName();
@ -101,13 +108,30 @@ public final class OperationEvaluationContext {
} catch (WorkbookNotFoundException e) { } catch (WorkbookNotFoundException e) {
throw new RuntimeException(e.getMessage(), 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() throw new RuntimeException("Invalid sheet name '" + externalSheet.getSheetName()
+ "' in bool '" + workbookName + "'."); + "' 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); return new SheetRefEvaluator(targetEvaluator, _tracker, otherSheetIndex);
} }
public SheetRefEvaluator getRefEvaluatorForCurrentSheet() { public SheetRangeEvaluator getRefEvaluatorForCurrentSheet() {
return new SheetRefEvaluator(_bookEvaluator, _tracker, _sheetIndex); SheetRefEvaluator sre = new SheetRefEvaluator(_bookEvaluator, _tracker, _sheetIndex);
return new SheetRangeEvaluator(_sheetIndex, sre);
} }
@ -162,10 +187,12 @@ public final class OperationEvaluationContext {
if (!isA1Style) { if (!isA1Style) {
throw new RuntimeException("R1C1 style not supported yet"); throw new RuntimeException("R1C1 style not supported yet");
} }
SheetRefEvaluator sre = createExternSheetRefEvaluator(workbookName, sheetName); SheetRefEvaluator se = createExternSheetRefEvaluator(workbookName, sheetName);
if (sre == null) { if (se == null) {
return ErrorEval.REF_INVALID; return ErrorEval.REF_INVALID;
} }
SheetRangeEvaluator sre = new SheetRangeEvaluator(_sheetIndex, se);
// ugly typecast - TODO - make spreadsheet version more easily accessible // ugly typecast - TODO - make spreadsheet version more easily accessible
SpreadsheetVersion ssVersion = ((FormulaParsingWorkbook)_workbook).getSpreadsheetVersion(); SpreadsheetVersion ssVersion = ((FormulaParsingWorkbook)_workbook).getSpreadsheetVersion();
@ -271,30 +298,30 @@ public final class OperationEvaluationContext {
} }
public ValueEval getRefEval(int rowIndex, int columnIndex) { public ValueEval getRefEval(int rowIndex, int columnIndex) {
SheetRefEvaluator sre = getRefEvaluatorForCurrentSheet(); SheetRangeEvaluator sre = getRefEvaluatorForCurrentSheet();
return new LazyRefEval(rowIndex, columnIndex, sre); return new LazyRefEval(rowIndex, columnIndex, sre);
} }
public ValueEval getRef3DEval(Ref3DPtg rptg) { public ValueEval getRef3DEval(Ref3DPtg rptg) {
SheetRefEvaluator sre = createExternSheetRefEvaluator(rptg.getExternSheetIndex()); SheetRangeEvaluator sre = createExternSheetRefEvaluator(rptg.getExternSheetIndex());
return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre); return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre);
} }
public ValueEval getRef3DEval(Ref3DPxg rptg) { 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); return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre);
} }
public ValueEval getAreaEval(int firstRowIndex, int firstColumnIndex, public ValueEval getAreaEval(int firstRowIndex, int firstColumnIndex,
int lastRowIndex, int lastColumnIndex) { int lastRowIndex, int lastColumnIndex) {
SheetRefEvaluator sre = getRefEvaluatorForCurrentSheet(); SheetRangeEvaluator sre = getRefEvaluatorForCurrentSheet();
return new LazyAreaEval(firstRowIndex, firstColumnIndex, lastRowIndex, lastColumnIndex, sre); return new LazyAreaEval(firstRowIndex, firstColumnIndex, lastRowIndex, lastColumnIndex, sre);
} }
public ValueEval getArea3DEval(Area3DPtg aptg) { public ValueEval getArea3DEval(Area3DPtg aptg) {
SheetRefEvaluator sre = createExternSheetRefEvaluator(aptg.getExternSheetIndex()); SheetRangeEvaluator sre = createExternSheetRefEvaluator(aptg.getExternSheetIndex());
return new LazyAreaEval(aptg.getFirstRow(), aptg.getFirstColumn(), return new LazyAreaEval(aptg.getFirstRow(), aptg.getFirstColumn(),
aptg.getLastRow(), aptg.getLastColumn(), sre); aptg.getLastRow(), aptg.getLastColumn(), sre);
} }
public ValueEval getArea3DEval(Area3DPxg aptg) { 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(), return new LazyAreaEval(aptg.getFirstRow(), aptg.getFirstColumn(),
aptg.getLastRow(), aptg.getLastColumn(), sre); aptg.getLastRow(), aptg.getLastColumn(), sre);
} }

View File

@ -38,6 +38,9 @@ final class SheetRangeEvaluator {
_lastSheetIndex = lastSheetIndex; _lastSheetIndex = lastSheetIndex;
_sheetEvaluators = sheetEvaluators; _sheetEvaluators = sheetEvaluators;
} }
public SheetRangeEvaluator(int onlySheetIndex, SheetRefEvaluator sheetEvaluator) {
this(onlySheetIndex, onlySheetIndex, new SheetRefEvaluator[] {sheetEvaluator});
}
public SheetRefEvaluator getSheetEvaluator(int sheetIndex) { public SheetRefEvaluator getSheetEvaluator(int sheetIndex) {
if (sheetIndex < _firstSheetIndex || sheetIndex > _lastSheetIndex) { if (sheetIndex < _firstSheetIndex || sheetIndex > _lastSheetIndex) {
@ -46,10 +49,26 @@ final class SheetRangeEvaluator {
} }
return _sheetEvaluators[sheetIndex-_firstSheetIndex]; return _sheetEvaluators[sheetIndex-_firstSheetIndex];
} }
public int getFirstSheetIndex() {
return _firstSheetIndex;
}
public int getLastSheetIndex() {
return _lastSheetIndex;
}
public String getSheetName(int sheetIndex) { public String getSheetName(int sheetIndex) {
return getSheetEvaluator(sheetIndex).getSheetName(); 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) { public ValueEval getEvalForCell(int sheetIndex, int rowIndex, int columnIndex) {
return getSheetEvaluator(sheetIndex).getEvalForCell(rowIndex, columnIndex); return getSheetEvaluator(sheetIndex).getEvalForCell(rowIndex, columnIndex);

View File

@ -427,7 +427,7 @@ public final class WorkbookEvaluator {
dbgIndentStr = " "; dbgIndentStr = " ";
dbgIndentStr = dbgIndentStr.substring(0, Math.min(dbgIndentStr.length(), dbgEvaluationOutputIndent*2)); dbgIndentStr = dbgIndentStr.substring(0, Math.min(dbgIndentStr.length(), dbgEvaluationOutputIndent*2));
EVAL_LOG.log(POILogger.WARN, dbgIndentStr EVAL_LOG.log(POILogger.WARN, dbgIndentStr
+ "- evaluateFormula('" + ec.getRefEvaluatorForCurrentSheet().getSheetName() + "- evaluateFormula('" + ec.getRefEvaluatorForCurrentSheet().getSheetNameRange()
+ "'/" + new CellReference(ec.getRowIndex(), ec.getColumnIndex()).formatAsString() + "'/" + new CellReference(ec.getRowIndex(), ec.getColumnIndex()).formatAsString()
+ "): " + Arrays.toString(ptgs).replaceAll("\\Qorg.apache.poi.ss.formula.ptg.\\E", "")); + "): " + Arrays.toString(ptgs).replaceAll("\\Qorg.apache.poi.ss.formula.ptg.\\E", ""));
dbgEvaluationOutputIndent++; dbgEvaluationOutputIndent++;