You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by fa...@apache.org on 2021/05/22 20:56:49 UTC
svn commit: r1890120 [15/43] - in /poi/trunk/poi/src:
main/java/org/apache/poi/ main/java/org/apache/poi/ddf/
main/java/org/apache/poi/extractor/ main/java/org/apache/poi/hpsf/
main/java/org/apache/poi/hssf/ main/java/org/apache/poi/hssf/dev/
main/java...
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/CellEvaluationFrame.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/CellEvaluationFrame.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/CellEvaluationFrame.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/CellEvaluationFrame.java Sat May 22 20:56:44 2021
@@ -27,51 +27,51 @@ import org.apache.poi.ss.formula.eval.Va
*/
final class CellEvaluationFrame {
- private final FormulaCellCacheEntry _cce;
- private final Set<CellCacheEntry> _sensitiveInputCells;
- private FormulaUsedBlankCellSet _usedBlankCellGroup;
+ private final FormulaCellCacheEntry _cce;
+ private final Set<CellCacheEntry> _sensitiveInputCells;
+ private FormulaUsedBlankCellSet _usedBlankCellGroup;
- public CellEvaluationFrame(FormulaCellCacheEntry cce) {
- _cce = cce;
- _sensitiveInputCells = new HashSet<>();
- }
- public CellCacheEntry getCCE() {
- return _cce;
- }
+ public CellEvaluationFrame(FormulaCellCacheEntry cce) {
+ _cce = cce;
+ _sensitiveInputCells = new HashSet<>();
+ }
+ public CellCacheEntry getCCE() {
+ return _cce;
+ }
- public String toString() {
- StringBuilder sb = new StringBuilder(64);
- sb.append(getClass().getName()).append(" [");
- sb.append("]");
- return sb.toString();
- }
- /**
- * @param inputCell a cell directly used by the formula of this evaluation frame
- */
- public void addSensitiveInputCell(CellCacheEntry inputCell) {
- _sensitiveInputCells.add(inputCell);
- }
- /**
- * @return never <code>null</code>, (possibly empty) array of all cells directly used while
- * evaluating the formula of this frame.
- */
- private CellCacheEntry[] getSensitiveInputCells() {
- int nItems = _sensitiveInputCells.size();
- if (nItems < 1) {
- return CellCacheEntry.EMPTY_ARRAY;
- }
- CellCacheEntry[] result = new CellCacheEntry[nItems];
- _sensitiveInputCells.toArray(result);
- return result;
- }
- public void addUsedBlankCell(EvaluationWorkbook evalWorkbook, int bookIndex, int sheetIndex, int rowIndex, int columnIndex) {
- if (_usedBlankCellGroup == null) {
- _usedBlankCellGroup = new FormulaUsedBlankCellSet();
- }
- _usedBlankCellGroup.addCell(evalWorkbook, bookIndex, sheetIndex, rowIndex, columnIndex);
- }
+ public String toString() {
+ StringBuilder sb = new StringBuilder(64);
+ sb.append(getClass().getName()).append(" [");
+ sb.append("]");
+ return sb.toString();
+ }
+ /**
+ * @param inputCell a cell directly used by the formula of this evaluation frame
+ */
+ public void addSensitiveInputCell(CellCacheEntry inputCell) {
+ _sensitiveInputCells.add(inputCell);
+ }
+ /**
+ * @return never <code>null</code>, (possibly empty) array of all cells directly used while
+ * evaluating the formula of this frame.
+ */
+ private CellCacheEntry[] getSensitiveInputCells() {
+ int nItems = _sensitiveInputCells.size();
+ if (nItems < 1) {
+ return CellCacheEntry.EMPTY_ARRAY;
+ }
+ CellCacheEntry[] result = new CellCacheEntry[nItems];
+ _sensitiveInputCells.toArray(result);
+ return result;
+ }
+ public void addUsedBlankCell(EvaluationWorkbook evalWorkbook, int bookIndex, int sheetIndex, int rowIndex, int columnIndex) {
+ if (_usedBlankCellGroup == null) {
+ _usedBlankCellGroup = new FormulaUsedBlankCellSet();
+ }
+ _usedBlankCellGroup.addCell(evalWorkbook, bookIndex, sheetIndex, rowIndex, columnIndex);
+ }
- public void updateFormulaResult(ValueEval result) {
- _cce.updateFormulaResult(result, getSensitiveInputCells(), _usedBlankCellGroup);
- }
+ public void updateFormulaResult(ValueEval result) {
+ _cce.updateFormulaResult(result, getSensitiveInputCells(), _usedBlankCellGroup);
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationCache.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationCache.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationCache.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationCache.java Sat May 22 20:56:44 2021
@@ -35,178 +35,178 @@ import org.apache.poi.ss.usermodel.CellT
*/
final class EvaluationCache {
- private final PlainCellCache _plainCellCache;
- private final FormulaCellCache _formulaCellCache;
- /** only used for testing. <code>null</code> otherwise */
- final IEvaluationListener _evaluationListener;
-
- /* package */EvaluationCache(IEvaluationListener evaluationListener) {
- _evaluationListener = evaluationListener;
- _plainCellCache = new PlainCellCache();
- _formulaCellCache = new FormulaCellCache();
- }
-
- public void notifyUpdateCell(int bookIndex, int sheetIndex, EvaluationCell cell) {
- FormulaCellCacheEntry fcce = _formulaCellCache.get(cell);
-
- int rowIndex = cell.getRowIndex();
- int columnIndex = cell.getColumnIndex();
- Loc loc = new Loc(bookIndex, sheetIndex, rowIndex, columnIndex);
- PlainValueCellCacheEntry pcce = _plainCellCache.get(loc);
-
- if (cell.getCellType() == CellType.FORMULA) {
- if (fcce == null) {
- fcce = new FormulaCellCacheEntry();
- if (pcce == null) {
- if (_evaluationListener != null) {
- _evaluationListener.onChangeFromBlankValue(sheetIndex, rowIndex,
- columnIndex, cell, fcce);
- }
- updateAnyBlankReferencingFormulas(bookIndex, sheetIndex, rowIndex,
- columnIndex);
- }
- _formulaCellCache.put(cell, fcce);
- } else {
- fcce.recurseClearCachedFormulaResults(_evaluationListener);
- fcce.clearFormulaEntry();
- }
- if (pcce == null) {
- // was formula cell before - no change of type
- } else {
- // changing from plain cell to formula cell
- pcce.recurseClearCachedFormulaResults(_evaluationListener);
- _plainCellCache.remove(loc);
- }
- } else {
- ValueEval value = WorkbookEvaluator.getValueFromNonFormulaCell(cell);
- if (pcce == null) {
- if (value != BlankEval.instance) {
- // only cache non-blank values in the plain cell cache
- // (dependencies on blank cells are managed by
- // FormulaCellCacheEntry._usedBlankCellGroup)
- pcce = new PlainValueCellCacheEntry(value);
- if (fcce == null) {
- if (_evaluationListener != null) {
- _evaluationListener.onChangeFromBlankValue(sheetIndex, rowIndex, columnIndex, cell, pcce);
- }
- updateAnyBlankReferencingFormulas(bookIndex, sheetIndex,
- rowIndex, columnIndex);
- }
- _plainCellCache.put(loc, pcce);
- }
- } else {
- if (pcce.updateValue(value)) {
- pcce.recurseClearCachedFormulaResults(_evaluationListener);
- }
- if (value == BlankEval.instance) {
- _plainCellCache.remove(loc);
- }
- }
- if (fcce == null) {
- // was plain cell before - no change of type
- } else {
- // was formula cell before - now a plain value
- _formulaCellCache.remove(cell);
- fcce.setSensitiveInputCells(null);
- fcce.recurseClearCachedFormulaResults(_evaluationListener);
- }
- }
- }
-
- private void updateAnyBlankReferencingFormulas(int bookIndex, int sheetIndex,
- final int rowIndex, final int columnIndex) {
- final BookSheetKey bsk = new BookSheetKey(bookIndex, sheetIndex);
- _formulaCellCache.applyOperation(entry -> entry.notifyUpdatedBlankCell(bsk, rowIndex, columnIndex, _evaluationListener));
- }
-
- public PlainValueCellCacheEntry getPlainValueEntry(int bookIndex, int sheetIndex,
- int rowIndex, int columnIndex, ValueEval value) {
-
- Loc loc = new Loc(bookIndex, sheetIndex, rowIndex, columnIndex);
- PlainValueCellCacheEntry result = _plainCellCache.get(loc);
- if (result == null) {
- result = new PlainValueCellCacheEntry(value);
- _plainCellCache.put(loc, result);
- if (_evaluationListener != null) {
- _evaluationListener.onReadPlainValue(sheetIndex, rowIndex, columnIndex, result);
- }
- } else {
- // TODO - if we are confident that this sanity check is not required, we can remove 'value' from plain value cache entry
- if (!areValuesEqual(result.getValue(), value)) {
- throw new IllegalStateException("value changed");
- }
- if (_evaluationListener != null) {
- _evaluationListener.onCacheHit(sheetIndex, rowIndex, columnIndex, value);
- }
- }
- return result;
- }
- private boolean areValuesEqual(ValueEval a, ValueEval b) {
- if (a == null) {
- return false;
- }
- Class<?> cls = a.getClass();
- if (cls != b.getClass()) {
- // value type is changing
- return false;
- }
- if (a == BlankEval.instance) {
- return b == a;
- }
- if (cls == NumberEval.class) {
- return ((NumberEval)a).getNumberValue() == ((NumberEval)b).getNumberValue();
- }
- if (cls == StringEval.class) {
- return ((StringEval)a).getStringValue().equals(((StringEval)b).getStringValue());
- }
- if (cls == BoolEval.class) {
- return ((BoolEval)a).getBooleanValue() == ((BoolEval)b).getBooleanValue();
- }
- if (cls == ErrorEval.class) {
- return ((ErrorEval)a).getErrorCode() == ((ErrorEval)b).getErrorCode();
- }
- throw new IllegalStateException("Unexpected value class (" + cls.getName() + ")");
- }
-
- public FormulaCellCacheEntry getOrCreateFormulaCellEntry(EvaluationCell cell) {
- FormulaCellCacheEntry result = _formulaCellCache.get(cell);
- if (result == null) {
-
- result = new FormulaCellCacheEntry();
- _formulaCellCache.put(cell, result);
- }
- return result;
- }
-
- /**
- * Should be called whenever there are changes to input cells in the evaluated workbook.
- */
- public void clear() {
- if(_evaluationListener != null) {
- _evaluationListener.onClearWholeCache();
- }
- _plainCellCache.clear();
- _formulaCellCache.clear();
- }
- public void notifyDeleteCell(int bookIndex, int sheetIndex, EvaluationCell cell) {
-
- if (cell.getCellType() == CellType.FORMULA) {
- FormulaCellCacheEntry fcce = _formulaCellCache.remove(cell);
- if (fcce == null) {
- // formula cell has not been evaluated yet
- } else {
- fcce.setSensitiveInputCells(null);
- fcce.recurseClearCachedFormulaResults(_evaluationListener);
- }
- } else {
- Loc loc = new Loc(bookIndex, sheetIndex, cell.getRowIndex(), cell.getColumnIndex());
- PlainValueCellCacheEntry pcce = _plainCellCache.get(loc);
-
- if (pcce == null) {
- // cache entry doesn't exist. nothing to do
- } else {
- pcce.recurseClearCachedFormulaResults(_evaluationListener);
- }
- }
- }
+ private final PlainCellCache _plainCellCache;
+ private final FormulaCellCache _formulaCellCache;
+ /** only used for testing. <code>null</code> otherwise */
+ final IEvaluationListener _evaluationListener;
+
+ /* package */EvaluationCache(IEvaluationListener evaluationListener) {
+ _evaluationListener = evaluationListener;
+ _plainCellCache = new PlainCellCache();
+ _formulaCellCache = new FormulaCellCache();
+ }
+
+ public void notifyUpdateCell(int bookIndex, int sheetIndex, EvaluationCell cell) {
+ FormulaCellCacheEntry fcce = _formulaCellCache.get(cell);
+
+ int rowIndex = cell.getRowIndex();
+ int columnIndex = cell.getColumnIndex();
+ Loc loc = new Loc(bookIndex, sheetIndex, rowIndex, columnIndex);
+ PlainValueCellCacheEntry pcce = _plainCellCache.get(loc);
+
+ if (cell.getCellType() == CellType.FORMULA) {
+ if (fcce == null) {
+ fcce = new FormulaCellCacheEntry();
+ if (pcce == null) {
+ if (_evaluationListener != null) {
+ _evaluationListener.onChangeFromBlankValue(sheetIndex, rowIndex,
+ columnIndex, cell, fcce);
+ }
+ updateAnyBlankReferencingFormulas(bookIndex, sheetIndex, rowIndex,
+ columnIndex);
+ }
+ _formulaCellCache.put(cell, fcce);
+ } else {
+ fcce.recurseClearCachedFormulaResults(_evaluationListener);
+ fcce.clearFormulaEntry();
+ }
+ if (pcce == null) {
+ // was formula cell before - no change of type
+ } else {
+ // changing from plain cell to formula cell
+ pcce.recurseClearCachedFormulaResults(_evaluationListener);
+ _plainCellCache.remove(loc);
+ }
+ } else {
+ ValueEval value = WorkbookEvaluator.getValueFromNonFormulaCell(cell);
+ if (pcce == null) {
+ if (value != BlankEval.instance) {
+ // only cache non-blank values in the plain cell cache
+ // (dependencies on blank cells are managed by
+ // FormulaCellCacheEntry._usedBlankCellGroup)
+ pcce = new PlainValueCellCacheEntry(value);
+ if (fcce == null) {
+ if (_evaluationListener != null) {
+ _evaluationListener.onChangeFromBlankValue(sheetIndex, rowIndex, columnIndex, cell, pcce);
+ }
+ updateAnyBlankReferencingFormulas(bookIndex, sheetIndex,
+ rowIndex, columnIndex);
+ }
+ _plainCellCache.put(loc, pcce);
+ }
+ } else {
+ if (pcce.updateValue(value)) {
+ pcce.recurseClearCachedFormulaResults(_evaluationListener);
+ }
+ if (value == BlankEval.instance) {
+ _plainCellCache.remove(loc);
+ }
+ }
+ if (fcce == null) {
+ // was plain cell before - no change of type
+ } else {
+ // was formula cell before - now a plain value
+ _formulaCellCache.remove(cell);
+ fcce.setSensitiveInputCells(null);
+ fcce.recurseClearCachedFormulaResults(_evaluationListener);
+ }
+ }
+ }
+
+ private void updateAnyBlankReferencingFormulas(int bookIndex, int sheetIndex,
+ final int rowIndex, final int columnIndex) {
+ final BookSheetKey bsk = new BookSheetKey(bookIndex, sheetIndex);
+ _formulaCellCache.applyOperation(entry -> entry.notifyUpdatedBlankCell(bsk, rowIndex, columnIndex, _evaluationListener));
+ }
+
+ public PlainValueCellCacheEntry getPlainValueEntry(int bookIndex, int sheetIndex,
+ int rowIndex, int columnIndex, ValueEval value) {
+
+ Loc loc = new Loc(bookIndex, sheetIndex, rowIndex, columnIndex);
+ PlainValueCellCacheEntry result = _plainCellCache.get(loc);
+ if (result == null) {
+ result = new PlainValueCellCacheEntry(value);
+ _plainCellCache.put(loc, result);
+ if (_evaluationListener != null) {
+ _evaluationListener.onReadPlainValue(sheetIndex, rowIndex, columnIndex, result);
+ }
+ } else {
+ // TODO - if we are confident that this sanity check is not required, we can remove 'value' from plain value cache entry
+ if (!areValuesEqual(result.getValue(), value)) {
+ throw new IllegalStateException("value changed");
+ }
+ if (_evaluationListener != null) {
+ _evaluationListener.onCacheHit(sheetIndex, rowIndex, columnIndex, value);
+ }
+ }
+ return result;
+ }
+ private boolean areValuesEqual(ValueEval a, ValueEval b) {
+ if (a == null) {
+ return false;
+ }
+ Class<?> cls = a.getClass();
+ if (cls != b.getClass()) {
+ // value type is changing
+ return false;
+ }
+ if (a == BlankEval.instance) {
+ return b == a;
+ }
+ if (cls == NumberEval.class) {
+ return ((NumberEval)a).getNumberValue() == ((NumberEval)b).getNumberValue();
+ }
+ if (cls == StringEval.class) {
+ return ((StringEval)a).getStringValue().equals(((StringEval)b).getStringValue());
+ }
+ if (cls == BoolEval.class) {
+ return ((BoolEval)a).getBooleanValue() == ((BoolEval)b).getBooleanValue();
+ }
+ if (cls == ErrorEval.class) {
+ return ((ErrorEval)a).getErrorCode() == ((ErrorEval)b).getErrorCode();
+ }
+ throw new IllegalStateException("Unexpected value class (" + cls.getName() + ")");
+ }
+
+ public FormulaCellCacheEntry getOrCreateFormulaCellEntry(EvaluationCell cell) {
+ FormulaCellCacheEntry result = _formulaCellCache.get(cell);
+ if (result == null) {
+
+ result = new FormulaCellCacheEntry();
+ _formulaCellCache.put(cell, result);
+ }
+ return result;
+ }
+
+ /**
+ * Should be called whenever there are changes to input cells in the evaluated workbook.
+ */
+ public void clear() {
+ if(_evaluationListener != null) {
+ _evaluationListener.onClearWholeCache();
+ }
+ _plainCellCache.clear();
+ _formulaCellCache.clear();
+ }
+ public void notifyDeleteCell(int bookIndex, int sheetIndex, EvaluationCell cell) {
+
+ if (cell.getCellType() == CellType.FORMULA) {
+ FormulaCellCacheEntry fcce = _formulaCellCache.remove(cell);
+ if (fcce == null) {
+ // formula cell has not been evaluated yet
+ } else {
+ fcce.setSensitiveInputCells(null);
+ fcce.recurseClearCachedFormulaResults(_evaluationListener);
+ }
+ } else {
+ Loc loc = new Loc(bookIndex, sheetIndex, cell.getRowIndex(), cell.getColumnIndex());
+ PlainValueCellCacheEntry pcce = _plainCellCache.get(loc);
+
+ if (pcce == null) {
+ // cache entry doesn't exist. nothing to do
+ } else {
+ pcce.recurseClearCachedFormulaResults(_evaluationListener);
+ }
+ }
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationCell.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationCell.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationCell.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationCell.java Sat May 22 20:56:44 2021
@@ -27,26 +27,26 @@ import org.apache.poi.util.Internal;
*/
@Internal
public interface EvaluationCell {
- /**
- * @return an Object that identifies the underlying cell,
- * suitable for use as a key in a {@link java.util.HashMap}
- */
- Object getIdentityKey();
+ /**
+ * @return an Object that identifies the underlying cell,
+ * suitable for use as a key in a {@link java.util.HashMap}
+ */
+ Object getIdentityKey();
- EvaluationSheet getSheet();
- int getRowIndex();
- int getColumnIndex();
- CellType getCellType();
+ EvaluationSheet getSheet();
+ int getRowIndex();
+ int getColumnIndex();
+ CellType getCellType();
- double getNumericCellValue();
- String getStringCellValue();
- boolean getBooleanCellValue();
- int getErrorCellValue();
- CellRangeAddress getArrayFormulaRange();
- boolean isPartOfArrayFormulaGroup();
+ double getNumericCellValue();
+ String getStringCellValue();
+ boolean getBooleanCellValue();
+ int getErrorCellValue();
+ CellRangeAddress getArrayFormulaRange();
+ boolean isPartOfArrayFormulaGroup();
- /**
- * @return cell type of cached formula result
- */
- CellType getCachedFormulaResultType();
+ /**
+ * @return cell type of cached formula result
+ */
+ CellType getCachedFormulaResultType();
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationName.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationName.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationName.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationName.java Sat May 22 20:56:44 2021
@@ -27,14 +27,14 @@ import org.apache.poi.util.Internal;
@Internal
public interface EvaluationName {
- String getNameText();
+ String getNameText();
- boolean isFunctionName();
+ boolean isFunctionName();
- boolean hasFormula();
+ boolean hasFormula();
- Ptg[] getNameDefinition();
+ Ptg[] getNameDefinition();
- boolean isRange();
- NamePtg createPtg();
+ boolean isRange();
+ NamePtg createPtg();
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationTracker.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationTracker.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationTracker.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationTracker.java Sat May 22 20:56:44 2021
@@ -34,116 +34,116 @@ import org.apache.poi.ss.formula.eval.Va
* references in spreadsheet formulas.
*/
final class EvaluationTracker {
- // TODO - consider deleting this class and letting CellEvaluationFrame take care of itself
- private final List<CellEvaluationFrame> _evaluationFrames;
- private final Set<FormulaCellCacheEntry> _currentlyEvaluatingCells;
- private final EvaluationCache _cache;
-
- public EvaluationTracker(EvaluationCache cache) {
- _cache = cache;
- _evaluationFrames = new ArrayList<>();
- _currentlyEvaluatingCells = new HashSet<>();
- }
-
- /**
- * Notifies this evaluation tracker that evaluation of the specified cell is
- * about to start.<br>
- *
- * In the case of a {@code true} return code, the caller should
- * continue evaluation of the specified cell, and also be sure to call
- * {@code endEvaluate()} when complete.<br>
- *
- * In the case of a {@code null} return code, the caller should
- * return an evaluation result of
- * {@code ErrorEval.CIRCULAR_REF_ERROR}, and not call {@code endEvaluate()}.
- * <br>
- * @return {@code false} if the specified cell is already being evaluated
- */
- public boolean startEvaluate(FormulaCellCacheEntry cce) {
- if (cce == null) {
- throw new IllegalArgumentException("cellLoc must not be null");
- }
- if (_currentlyEvaluatingCells.contains(cce)) {
- return false;
- }
- _currentlyEvaluatingCells.add(cce);
- _evaluationFrames.add(new CellEvaluationFrame(cce));
- return true;
- }
-
- public void updateCacheResult(ValueEval result) {
-
- int nFrames = _evaluationFrames.size();
- if (nFrames < 1) {
- throw new IllegalStateException("Call to endEvaluate without matching call to startEvaluate");
- }
- CellEvaluationFrame frame = _evaluationFrames.get(nFrames-1);
- if (result == ErrorEval.CIRCULAR_REF_ERROR && nFrames > 1) {
- // Don't cache a circular ref error result if this cell is not the top evaluated cell.
- // A true circular ref error will propagate all the way around the loop. However, it's
- // possible to have parts of the formula tree (/ parts of the loop) to evaluate to
- // CIRCULAR_REF_ERROR, and that value not get used in the final cell result (see the
- // unit tests for a simple example). Thus, the only CIRCULAR_REF_ERROR result that can
- // safely be cached is that of the top evaluated cell.
- return;
- }
-
- frame.updateFormulaResult(result);
- }
-
- /**
- * Notifies this evaluation tracker that the evaluation of the specified cell is complete. <p>
- *
- * Every successful call to {@code startEvaluate} must be followed by a call to {@code endEvaluate} (recommended in a finally block) to enable
- * proper tracking of which cells are being evaluated at any point in time.<p>
- *
- * Assuming a well behaved client, parameters to this method would not be
- * required. However, they have been included to assert correct behaviour,
- * and form more meaningful error messages.
- */
- public void endEvaluate(CellCacheEntry cce) {
-
- int nFrames = _evaluationFrames.size();
- if (nFrames < 1) {
- throw new IllegalStateException("Call to endEvaluate without matching call to startEvaluate");
- }
-
- nFrames--;
- CellEvaluationFrame frame = _evaluationFrames.get(nFrames);
- if (cce != frame.getCCE()) {
- throw new IllegalStateException("Wrong cell specified. ");
- }
- // else - no problems so pop current frame
- _evaluationFrames.remove(nFrames);
- _currentlyEvaluatingCells.remove(cce);
- }
-
- public void acceptFormulaDependency(CellCacheEntry cce) {
- // Tell the currently evaluating cell frame that it has a dependency on the specified
- int prevFrameIndex = _evaluationFrames.size()-1;
- if (prevFrameIndex < 0) {
- // Top level frame, there is no 'cell' above this frame that is using the current cell
- } else {
- CellEvaluationFrame consumingFrame = _evaluationFrames.get(prevFrameIndex);
- consumingFrame.addSensitiveInputCell(cce);
- }
- }
-
- public void acceptPlainValueDependency(EvaluationWorkbook evalWorkbook, int bookIndex, int sheetIndex,
- int rowIndex, int columnIndex, ValueEval value) {
- // Tell the currently evaluating cell frame that it has a dependency on the specified
- int prevFrameIndex = _evaluationFrames.size() - 1;
- if (prevFrameIndex < 0) {
- // Top level frame, there is no 'cell' above this frame that is using the current cell
- } else {
- CellEvaluationFrame consumingFrame = _evaluationFrames.get(prevFrameIndex);
- if (value == BlankEval.instance) {
- consumingFrame.addUsedBlankCell(evalWorkbook, bookIndex, sheetIndex, rowIndex, columnIndex);
- } else {
- PlainValueCellCacheEntry cce = _cache.getPlainValueEntry(bookIndex, sheetIndex,
- rowIndex, columnIndex, value);
- consumingFrame.addSensitiveInputCell(cce);
- }
- }
- }
+ // TODO - consider deleting this class and letting CellEvaluationFrame take care of itself
+ private final List<CellEvaluationFrame> _evaluationFrames;
+ private final Set<FormulaCellCacheEntry> _currentlyEvaluatingCells;
+ private final EvaluationCache _cache;
+
+ public EvaluationTracker(EvaluationCache cache) {
+ _cache = cache;
+ _evaluationFrames = new ArrayList<>();
+ _currentlyEvaluatingCells = new HashSet<>();
+ }
+
+ /**
+ * Notifies this evaluation tracker that evaluation of the specified cell is
+ * about to start.<br>
+ *
+ * In the case of a {@code true} return code, the caller should
+ * continue evaluation of the specified cell, and also be sure to call
+ * {@code endEvaluate()} when complete.<br>
+ *
+ * In the case of a {@code null} return code, the caller should
+ * return an evaluation result of
+ * {@code ErrorEval.CIRCULAR_REF_ERROR}, and not call {@code endEvaluate()}.
+ * <br>
+ * @return {@code false} if the specified cell is already being evaluated
+ */
+ public boolean startEvaluate(FormulaCellCacheEntry cce) {
+ if (cce == null) {
+ throw new IllegalArgumentException("cellLoc must not be null");
+ }
+ if (_currentlyEvaluatingCells.contains(cce)) {
+ return false;
+ }
+ _currentlyEvaluatingCells.add(cce);
+ _evaluationFrames.add(new CellEvaluationFrame(cce));
+ return true;
+ }
+
+ public void updateCacheResult(ValueEval result) {
+
+ int nFrames = _evaluationFrames.size();
+ if (nFrames < 1) {
+ throw new IllegalStateException("Call to endEvaluate without matching call to startEvaluate");
+ }
+ CellEvaluationFrame frame = _evaluationFrames.get(nFrames-1);
+ if (result == ErrorEval.CIRCULAR_REF_ERROR && nFrames > 1) {
+ // Don't cache a circular ref error result if this cell is not the top evaluated cell.
+ // A true circular ref error will propagate all the way around the loop. However, it's
+ // possible to have parts of the formula tree (/ parts of the loop) to evaluate to
+ // CIRCULAR_REF_ERROR, and that value not get used in the final cell result (see the
+ // unit tests for a simple example). Thus, the only CIRCULAR_REF_ERROR result that can
+ // safely be cached is that of the top evaluated cell.
+ return;
+ }
+
+ frame.updateFormulaResult(result);
+ }
+
+ /**
+ * Notifies this evaluation tracker that the evaluation of the specified cell is complete. <p>
+ *
+ * Every successful call to {@code startEvaluate} must be followed by a call to {@code endEvaluate} (recommended in a finally block) to enable
+ * proper tracking of which cells are being evaluated at any point in time.<p>
+ *
+ * Assuming a well behaved client, parameters to this method would not be
+ * required. However, they have been included to assert correct behaviour,
+ * and form more meaningful error messages.
+ */
+ public void endEvaluate(CellCacheEntry cce) {
+
+ int nFrames = _evaluationFrames.size();
+ if (nFrames < 1) {
+ throw new IllegalStateException("Call to endEvaluate without matching call to startEvaluate");
+ }
+
+ nFrames--;
+ CellEvaluationFrame frame = _evaluationFrames.get(nFrames);
+ if (cce != frame.getCCE()) {
+ throw new IllegalStateException("Wrong cell specified. ");
+ }
+ // else - no problems so pop current frame
+ _evaluationFrames.remove(nFrames);
+ _currentlyEvaluatingCells.remove(cce);
+ }
+
+ public void acceptFormulaDependency(CellCacheEntry cce) {
+ // Tell the currently evaluating cell frame that it has a dependency on the specified
+ int prevFrameIndex = _evaluationFrames.size()-1;
+ if (prevFrameIndex < 0) {
+ // Top level frame, there is no 'cell' above this frame that is using the current cell
+ } else {
+ CellEvaluationFrame consumingFrame = _evaluationFrames.get(prevFrameIndex);
+ consumingFrame.addSensitiveInputCell(cce);
+ }
+ }
+
+ public void acceptPlainValueDependency(EvaluationWorkbook evalWorkbook, int bookIndex, int sheetIndex,
+ int rowIndex, int columnIndex, ValueEval value) {
+ // Tell the currently evaluating cell frame that it has a dependency on the specified
+ int prevFrameIndex = _evaluationFrames.size() - 1;
+ if (prevFrameIndex < 0) {
+ // Top level frame, there is no 'cell' above this frame that is using the current cell
+ } else {
+ CellEvaluationFrame consumingFrame = _evaluationFrames.get(prevFrameIndex);
+ if (value == BlankEval.instance) {
+ consumingFrame.addUsedBlankCell(evalWorkbook, bookIndex, sheetIndex, rowIndex, columnIndex);
+ } else {
+ PlainValueCellCacheEntry cce = _cache.getPlainValueEntry(bookIndex, sheetIndex,
+ rowIndex, columnIndex, value);
+ consumingFrame.addSensitiveInputCell(cce);
+ }
+ }
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/ExternSheetReferenceToken.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/ExternSheetReferenceToken.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/ExternSheetReferenceToken.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/ExternSheetReferenceToken.java Sat May 22 20:56:44 2021
@@ -23,9 +23,9 @@ package org.apache.poi.ss.formula;
* For POI internal use only
*/
public interface ExternSheetReferenceToken {
- int getExternSheetIndex();
- /**
- * @return formula text for this reference token without the qualifying sheet name
- */
- String format2DRefAsString();
+ int getExternSheetIndex();
+ /**
+ * @return formula text for this reference token without the qualifying sheet name
+ */
+ String format2DRefAsString();
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/Formula.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/Formula.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/Formula.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/Formula.java Sat May 22 20:56:44 2021
@@ -38,173 +38,173 @@ import org.apache.poi.util.LittleEndianO
*/
public class Formula implements GenericRecord {
- //Arbitrarily set. May need to increase.
- private static final int MAX_ENCODED_LEN = 100000;
+ //Arbitrarily set. May need to increase.
+ private static final int MAX_ENCODED_LEN = 100000;
- private static final Formula EMPTY = new Formula(new byte[0], 0);
+ private static final Formula EMPTY = new Formula(new byte[0], 0);
- /** immutable */
- private final byte[] _byteEncoding;
- private final int _encodedTokenLen;
-
- public Formula(Formula other) {
- _byteEncoding = (other._byteEncoding == null) ? null : other._byteEncoding.clone();
- _encodedTokenLen = other._encodedTokenLen;
- }
-
- private Formula(byte[] byteEncoding, int encodedTokenLen) {
- _byteEncoding = byteEncoding.clone();
- _encodedTokenLen = encodedTokenLen;
-
- // TODO - this seems to occur when IntersectionPtg is present
- // This example file "IntersectionPtg.xls"
- // used by test: TestIntersectionPtg.testReading()
- // has 10 bytes unused at the end of the formula
- // 10 extra bytes are just 0x01 and 0x00
- // LittleEndianByteArrayInputStream in = new LittleEndianByteArrayInputStream(byteEncoding);
- // Ptg.readTokens(encodedTokenLen, in);
- // int nUnusedBytes = _byteEncoding.length - in.getReadIndex();
- }
- /**
- * Convenience method for {@link #read(int, LittleEndianInput, int)}
- */
- public static Formula read(int encodedTokenLen, LittleEndianInput in) {
- return read(encodedTokenLen, in, encodedTokenLen);
- }
- /**
- * When there are no array constants present, {@code encodedTokenLen}=={@code totalEncodedLen}
- * @param encodedTokenLen number of bytes in the stream taken by the plain formula tokens
- * @param totalEncodedLen the total number of bytes in the formula (includes trailing encoding
- * for array constants, but does not include 2 bytes for initial {@code ushort encodedTokenLen} field.
- * @return A new formula object as read from the stream. Possibly empty, never {@code null}.
- */
- public static Formula read(int encodedTokenLen, LittleEndianInput in, int totalEncodedLen) {
- byte[] byteEncoding = IOUtils.safelyAllocate(totalEncodedLen, MAX_ENCODED_LEN);
- in.readFully(byteEncoding);
- return new Formula(byteEncoding, encodedTokenLen);
- }
-
- public Ptg[] getTokens() {
- LittleEndianInput in = new LittleEndianByteArrayInputStream(_byteEncoding);
- return Ptg.readTokens(_encodedTokenLen, in);
- }
- /**
- * Writes The formula encoding is includes:
- * <ul>
- * <li>ushort tokenDataLen</li>
- * <li>tokenData</li>
- * <li>arrayConstantData (if present)</li>
- * </ul>
- */
- public void serialize(LittleEndianOutput out) {
- out.writeShort(_encodedTokenLen);
- out.write(_byteEncoding);
- }
-
- public void serializeTokens(LittleEndianOutput out) {
- out.write(_byteEncoding, 0, _encodedTokenLen);
- }
- public void serializeArrayConstantData(LittleEndianOutput out) {
- int len = _byteEncoding.length-_encodedTokenLen;
- out.write(_byteEncoding, _encodedTokenLen, len);
- }
-
-
- /**
- * @return total formula encoding length. The formula encoding includes:
- * <ul>
- * <li>ushort tokenDataLen</li>
- * <li>tokenData</li>
- * <li>arrayConstantData (optional)</li>
- * </ul>
- * Note - this value is different to {@code tokenDataLength}
- */
- public int getEncodedSize() {
- return 2 + _byteEncoding.length;
- }
- /**
- * This method is often used when the formula length does not appear immediately before
- * the encoded token data.
- *
- * @return the encoded length of the plain formula tokens. This does <em>not</em> include
- * the leading ushort field, nor any trailing array constant data.
- */
- public int getEncodedTokenSize() {
- return _encodedTokenLen;
- }
-
- /**
- * Creates a Formula object from a supplied {@link Ptg} array.
- * Handles {@code null}s OK.
- * @param ptgs may be {@code null}
- * @return Never {@code null} (Possibly empty if the supplied {@code ptgs} is {@code null})
- */
- public static Formula create(Ptg[] ptgs) {
- if (ptgs == null || ptgs.length < 1) {
- return EMPTY;
- }
- int totalSize = Ptg.getEncodedSize(ptgs);
- byte[] encodedData = new byte[totalSize];
- Ptg.serializePtgs(ptgs, encodedData, 0);
- int encodedTokenLen = Ptg.getEncodedSizeWithoutArrayData(ptgs);
- return new Formula(encodedData, encodedTokenLen);
- }
- /**
- * Gets the {@link Ptg} array from the supplied Formula.
- * Handles {@code null}s OK.
- *
- * @param formula may be {@code null}
- * @return possibly {@code null} (if the supplied {@code formula} is {@code null})
- */
- public static Ptg[] getTokens(Formula formula) {
- if (formula == null) {
- return null;
- }
- return formula.getTokens();
- }
-
- public Formula copy() {
- // OK to return this because immutable
- return this;
- }
+ /** immutable */
+ private final byte[] _byteEncoding;
+ private final int _encodedTokenLen;
+
+ public Formula(Formula other) {
+ _byteEncoding = (other._byteEncoding == null) ? null : other._byteEncoding.clone();
+ _encodedTokenLen = other._encodedTokenLen;
+ }
+
+ private Formula(byte[] byteEncoding, int encodedTokenLen) {
+ _byteEncoding = byteEncoding.clone();
+ _encodedTokenLen = encodedTokenLen;
+
+ // TODO - this seems to occur when IntersectionPtg is present
+ // This example file "IntersectionPtg.xls"
+ // used by test: TestIntersectionPtg.testReading()
+ // has 10 bytes unused at the end of the formula
+ // 10 extra bytes are just 0x01 and 0x00
+ // LittleEndianByteArrayInputStream in = new LittleEndianByteArrayInputStream(byteEncoding);
+ // Ptg.readTokens(encodedTokenLen, in);
+ // int nUnusedBytes = _byteEncoding.length - in.getReadIndex();
+ }
+ /**
+ * Convenience method for {@link #read(int, LittleEndianInput, int)}
+ */
+ public static Formula read(int encodedTokenLen, LittleEndianInput in) {
+ return read(encodedTokenLen, in, encodedTokenLen);
+ }
+ /**
+ * When there are no array constants present, {@code encodedTokenLen}=={@code totalEncodedLen}
+ * @param encodedTokenLen number of bytes in the stream taken by the plain formula tokens
+ * @param totalEncodedLen the total number of bytes in the formula (includes trailing encoding
+ * for array constants, but does not include 2 bytes for initial {@code ushort encodedTokenLen} field.
+ * @return A new formula object as read from the stream. Possibly empty, never {@code null}.
+ */
+ public static Formula read(int encodedTokenLen, LittleEndianInput in, int totalEncodedLen) {
+ byte[] byteEncoding = IOUtils.safelyAllocate(totalEncodedLen, MAX_ENCODED_LEN);
+ in.readFully(byteEncoding);
+ return new Formula(byteEncoding, encodedTokenLen);
+ }
+
+ public Ptg[] getTokens() {
+ LittleEndianInput in = new LittleEndianByteArrayInputStream(_byteEncoding);
+ return Ptg.readTokens(_encodedTokenLen, in);
+ }
+ /**
+ * Writes The formula encoding is includes:
+ * <ul>
+ * <li>ushort tokenDataLen</li>
+ * <li>tokenData</li>
+ * <li>arrayConstantData (if present)</li>
+ * </ul>
+ */
+ public void serialize(LittleEndianOutput out) {
+ out.writeShort(_encodedTokenLen);
+ out.write(_byteEncoding);
+ }
+
+ public void serializeTokens(LittleEndianOutput out) {
+ out.write(_byteEncoding, 0, _encodedTokenLen);
+ }
+ public void serializeArrayConstantData(LittleEndianOutput out) {
+ int len = _byteEncoding.length-_encodedTokenLen;
+ out.write(_byteEncoding, _encodedTokenLen, len);
+ }
+
+
+ /**
+ * @return total formula encoding length. The formula encoding includes:
+ * <ul>
+ * <li>ushort tokenDataLen</li>
+ * <li>tokenData</li>
+ * <li>arrayConstantData (optional)</li>
+ * </ul>
+ * Note - this value is different to {@code tokenDataLength}
+ */
+ public int getEncodedSize() {
+ return 2 + _byteEncoding.length;
+ }
+ /**
+ * This method is often used when the formula length does not appear immediately before
+ * the encoded token data.
+ *
+ * @return the encoded length of the plain formula tokens. This does <em>not</em> include
+ * the leading ushort field, nor any trailing array constant data.
+ */
+ public int getEncodedTokenSize() {
+ return _encodedTokenLen;
+ }
+
+ /**
+ * Creates a Formula object from a supplied {@link Ptg} array.
+ * Handles {@code null}s OK.
+ * @param ptgs may be {@code null}
+ * @return Never {@code null} (Possibly empty if the supplied {@code ptgs} is {@code null})
+ */
+ public static Formula create(Ptg[] ptgs) {
+ if (ptgs == null || ptgs.length < 1) {
+ return EMPTY;
+ }
+ int totalSize = Ptg.getEncodedSize(ptgs);
+ byte[] encodedData = new byte[totalSize];
+ Ptg.serializePtgs(ptgs, encodedData, 0);
+ int encodedTokenLen = Ptg.getEncodedSizeWithoutArrayData(ptgs);
+ return new Formula(encodedData, encodedTokenLen);
+ }
+ /**
+ * Gets the {@link Ptg} array from the supplied Formula.
+ * Handles {@code null}s OK.
+ *
+ * @param formula may be {@code null}
+ * @return possibly {@code null} (if the supplied {@code formula} is {@code null})
+ */
+ public static Ptg[] getTokens(Formula formula) {
+ if (formula == null) {
+ return null;
+ }
+ return formula.getTokens();
+ }
+
+ public Formula copy() {
+ // OK to return this because immutable
+ return this;
+ }
- /**
- * Gets the locator for the corresponding {@link org.apache.poi.hssf.record.SharedFormulaRecord},
+ /**
+ * Gets the locator for the corresponding {@link org.apache.poi.hssf.record.SharedFormulaRecord},
* {@link org.apache.poi.hssf.record.ArrayRecord} or {@link org.apache.poi.hssf.record.TableRecord}
* if this formula belongs to such a grouping. The {@link CellReference}
- * returned by this method will match the top left corner of the range of that grouping.
- * The return value is usually not the same as the location of the cell containing this formula.
- *
- * @return the firstRow & firstColumn of an array formula or shared formula that this formula
- * belongs to. {@code null} if this formula is not part of an array or shared formula.
- */
- public CellReference getExpReference() {
- byte[] data = _byteEncoding;
- if (data.length != 5) {
- // tExp and tTbl are always 5 bytes long, and the only ptg in the formula
- return null;
- }
- switch (data[0]) {
- case ExpPtg.sid:
- break;
- case TblPtg.sid:
- break;
- default:
- return null;
- }
- int firstRow = LittleEndian.getUShort(data, 1);
- int firstColumn = LittleEndian.getUShort(data, 3);
- return new CellReference(firstRow, firstColumn);
- }
- public boolean isSame(Formula other) {
- return Arrays.equals(_byteEncoding, other._byteEncoding);
- }
-
- @Override
- public Map<String, Supplier<?>> getGenericProperties() {
- return GenericRecordUtil.getGenericProperties(
- "tokens", this::getTokens,
- "expReference", this::getExpReference
- );
- }
+ * returned by this method will match the top left corner of the range of that grouping.
+ * The return value is usually not the same as the location of the cell containing this formula.
+ *
+ * @return the firstRow & firstColumn of an array formula or shared formula that this formula
+ * belongs to. {@code null} if this formula is not part of an array or shared formula.
+ */
+ public CellReference getExpReference() {
+ byte[] data = _byteEncoding;
+ if (data.length != 5) {
+ // tExp and tTbl are always 5 bytes long, and the only ptg in the formula
+ return null;
+ }
+ switch (data[0]) {
+ case ExpPtg.sid:
+ break;
+ case TblPtg.sid:
+ break;
+ default:
+ return null;
+ }
+ int firstRow = LittleEndian.getUShort(data, 1);
+ int firstColumn = LittleEndian.getUShort(data, 3);
+ return new CellReference(firstRow, firstColumn);
+ }
+ public boolean isSame(Formula other) {
+ return Arrays.equals(_byteEncoding, other._byteEncoding);
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "tokens", this::getTokens,
+ "expReference", this::getExpReference
+ );
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaCellCache.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaCellCache.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaCellCache.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaCellCache.java Sat May 22 20:56:44 2021
@@ -23,47 +23,47 @@ import java.util.Map;
final class FormulaCellCache {
- static interface IEntryOperation {
- void processEntry(FormulaCellCacheEntry entry);
- }
-
- private final Map<Object, FormulaCellCacheEntry> _formulaEntriesByCell;
-
- public FormulaCellCache() {
- // assumes the object returned by EvaluationCell.getIdentityKey() has a well behaved hashCode+equals
- _formulaEntriesByCell = new HashMap<>();
- }
-
- public CellCacheEntry[] getCacheEntries() {
-
- FormulaCellCacheEntry[] result = new FormulaCellCacheEntry[_formulaEntriesByCell.size()];
- _formulaEntriesByCell.values().toArray(result);
- return result;
- }
-
- public void clear() {
- _formulaEntriesByCell.clear();
- }
-
- /**
- * @return <code>null</code> if not found
- */
- public FormulaCellCacheEntry get(EvaluationCell cell) {
- return _formulaEntriesByCell.get(cell.getIdentityKey());
- }
-
- public void put(EvaluationCell cell, FormulaCellCacheEntry entry) {
- _formulaEntriesByCell.put(cell.getIdentityKey(), entry);
- }
-
- public FormulaCellCacheEntry remove(EvaluationCell cell) {
- return _formulaEntriesByCell.remove(cell.getIdentityKey());
- }
-
- public void applyOperation(IEntryOperation operation) {
- Iterator<FormulaCellCacheEntry> i = _formulaEntriesByCell.values().iterator();
- while (i.hasNext()) {
- operation.processEntry(i.next());
- }
- }
+ static interface IEntryOperation {
+ void processEntry(FormulaCellCacheEntry entry);
+ }
+
+ private final Map<Object, FormulaCellCacheEntry> _formulaEntriesByCell;
+
+ public FormulaCellCache() {
+ // assumes the object returned by EvaluationCell.getIdentityKey() has a well behaved hashCode+equals
+ _formulaEntriesByCell = new HashMap<>();
+ }
+
+ public CellCacheEntry[] getCacheEntries() {
+
+ FormulaCellCacheEntry[] result = new FormulaCellCacheEntry[_formulaEntriesByCell.size()];
+ _formulaEntriesByCell.values().toArray(result);
+ return result;
+ }
+
+ public void clear() {
+ _formulaEntriesByCell.clear();
+ }
+
+ /**
+ * @return <code>null</code> if not found
+ */
+ public FormulaCellCacheEntry get(EvaluationCell cell) {
+ return _formulaEntriesByCell.get(cell.getIdentityKey());
+ }
+
+ public void put(EvaluationCell cell, FormulaCellCacheEntry entry) {
+ _formulaEntriesByCell.put(cell.getIdentityKey(), entry);
+ }
+
+ public FormulaCellCacheEntry remove(EvaluationCell cell) {
+ return _formulaEntriesByCell.remove(cell.getIdentityKey());
+ }
+
+ public void applyOperation(IEntryOperation operation) {
+ Iterator<FormulaCellCacheEntry> i = _formulaEntriesByCell.values().iterator();
+ while (i.hasNext()) {
+ operation.processEntry(i.next());
+ }
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaCellCacheEntry.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaCellCacheEntry.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaCellCacheEntry.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaCellCacheEntry.java Sat May 22 20:56:44 2021
@@ -30,94 +30,94 @@ import org.apache.poi.ss.formula.Formula
* Stores the cached result of a formula evaluation, along with the set of sensitive input cells
*/
final class FormulaCellCacheEntry extends CellCacheEntry {
-
- /**
- * Cells 'used' in the current evaluation of the formula corresponding to this cache entry
- *
- * If any of the following cells change, this cache entry needs to be cleared
- */
- private CellCacheEntry[] _sensitiveInputCells;
-
- private FormulaUsedBlankCellSet _usedBlankCellGroup;
-
- public FormulaCellCacheEntry() {
- // leave fields un-set
- }
-
- public boolean isInputSensitive() {
- if (_sensitiveInputCells != null) {
- if (_sensitiveInputCells.length > 0 ) {
- return true;
- }
- }
- return _usedBlankCellGroup == null ? false : !_usedBlankCellGroup.isEmpty();
- }
-
- public void setSensitiveInputCells(CellCacheEntry[] sensitiveInputCells) {
- // need to tell all cells that were previously used, but no longer are,
- // that they are not consumed by this cell any more
- if (sensitiveInputCells == null) {
+
+ /**
+ * Cells 'used' in the current evaluation of the formula corresponding to this cache entry
+ *
+ * If any of the following cells change, this cache entry needs to be cleared
+ */
+ private CellCacheEntry[] _sensitiveInputCells;
+
+ private FormulaUsedBlankCellSet _usedBlankCellGroup;
+
+ public FormulaCellCacheEntry() {
+ // leave fields un-set
+ }
+
+ public boolean isInputSensitive() {
+ if (_sensitiveInputCells != null) {
+ if (_sensitiveInputCells.length > 0 ) {
+ return true;
+ }
+ }
+ return _usedBlankCellGroup == null ? false : !_usedBlankCellGroup.isEmpty();
+ }
+
+ public void setSensitiveInputCells(CellCacheEntry[] sensitiveInputCells) {
+ // need to tell all cells that were previously used, but no longer are,
+ // that they are not consumed by this cell any more
+ if (sensitiveInputCells == null) {
_sensitiveInputCells = null;
- changeConsumingCells(CellCacheEntry.EMPTY_ARRAY);
- } else {
- _sensitiveInputCells = sensitiveInputCells.clone();
- changeConsumingCells(_sensitiveInputCells);
- }
- }
-
- public void clearFormulaEntry() {
- CellCacheEntry[] usedCells = _sensitiveInputCells;
- if (usedCells != null) {
- for (int i = usedCells.length-1; i>=0; i--) {
- usedCells[i].clearConsumingCell(this);
- }
- }
- _sensitiveInputCells = null;
- clearValue();
- }
-
- private void changeConsumingCells(CellCacheEntry[] usedCells) {
-
- CellCacheEntry[] prevUsedCells = _sensitiveInputCells;
- int nUsed = usedCells.length;
- for (int i = 0; i < nUsed; i++) {
- usedCells[i].addConsumingCell(this);
- }
- if (prevUsedCells == null) {
- return;
- }
- int nPrevUsed = prevUsedCells.length;
- if (nPrevUsed < 1) {
- return;
- }
- Set<CellCacheEntry> usedSet;
- if (nUsed < 1) {
- usedSet = Collections.emptySet();
- } else {
- usedSet = new HashSet<>(nUsed * 3 / 2);
- usedSet.addAll(Arrays.asList(usedCells).subList(0, nUsed));
- }
- for (int i = 0; i < nPrevUsed; i++) {
- CellCacheEntry prevUsed = prevUsedCells[i];
- if (!usedSet.contains(prevUsed)) {
- // previously was used by cellLoc, but not anymore
- prevUsed.clearConsumingCell(this);
- }
- }
- }
-
- public void updateFormulaResult(ValueEval result, CellCacheEntry[] sensitiveInputCells, FormulaUsedBlankCellSet usedBlankAreas) {
- updateValue(result);
- setSensitiveInputCells(sensitiveInputCells);
- _usedBlankCellGroup = usedBlankAreas;
- }
-
- public void notifyUpdatedBlankCell(BookSheetKey bsk, int rowIndex, int columnIndex, IEvaluationListener evaluationListener) {
- if (_usedBlankCellGroup != null) {
- if (_usedBlankCellGroup.containsCell(bsk, rowIndex, columnIndex)) {
- clearFormulaEntry();
- recurseClearCachedFormulaResults(evaluationListener);
- }
- }
- }
+ changeConsumingCells(CellCacheEntry.EMPTY_ARRAY);
+ } else {
+ _sensitiveInputCells = sensitiveInputCells.clone();
+ changeConsumingCells(_sensitiveInputCells);
+ }
+ }
+
+ public void clearFormulaEntry() {
+ CellCacheEntry[] usedCells = _sensitiveInputCells;
+ if (usedCells != null) {
+ for (int i = usedCells.length-1; i>=0; i--) {
+ usedCells[i].clearConsumingCell(this);
+ }
+ }
+ _sensitiveInputCells = null;
+ clearValue();
+ }
+
+ private void changeConsumingCells(CellCacheEntry[] usedCells) {
+
+ CellCacheEntry[] prevUsedCells = _sensitiveInputCells;
+ int nUsed = usedCells.length;
+ for (int i = 0; i < nUsed; i++) {
+ usedCells[i].addConsumingCell(this);
+ }
+ if (prevUsedCells == null) {
+ return;
+ }
+ int nPrevUsed = prevUsedCells.length;
+ if (nPrevUsed < 1) {
+ return;
+ }
+ Set<CellCacheEntry> usedSet;
+ if (nUsed < 1) {
+ usedSet = Collections.emptySet();
+ } else {
+ usedSet = new HashSet<>(nUsed * 3 / 2);
+ usedSet.addAll(Arrays.asList(usedCells).subList(0, nUsed));
+ }
+ for (int i = 0; i < nPrevUsed; i++) {
+ CellCacheEntry prevUsed = prevUsedCells[i];
+ if (!usedSet.contains(prevUsed)) {
+ // previously was used by cellLoc, but not anymore
+ prevUsed.clearConsumingCell(this);
+ }
+ }
+ }
+
+ public void updateFormulaResult(ValueEval result, CellCacheEntry[] sensitiveInputCells, FormulaUsedBlankCellSet usedBlankAreas) {
+ updateValue(result);
+ setSensitiveInputCells(sensitiveInputCells);
+ _usedBlankCellGroup = usedBlankAreas;
+ }
+
+ public void notifyUpdatedBlankCell(BookSheetKey bsk, int rowIndex, int columnIndex, IEvaluationListener evaluationListener) {
+ if (_usedBlankCellGroup != null) {
+ if (_usedBlankCellGroup.containsCell(bsk, rowIndex, columnIndex)) {
+ clearFormulaEntry();
+ recurseClearCachedFormulaResults(evaluationListener);
+ }
+ }
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaCellCacheEntrySet.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaCellCacheEntrySet.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaCellCacheEntrySet.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaCellCacheEntrySet.java Sat May 22 20:56:44 2021
@@ -25,129 +25,129 @@ package org.apache.poi.ss.formula;
* thousands of formula cells with multiple interdependencies, the savings can be very significant.
*/
final class FormulaCellCacheEntrySet {
- private static final FormulaCellCacheEntry[] EMPTY_ARRAY = { };
+ private static final FormulaCellCacheEntry[] EMPTY_ARRAY = { };
- private int _size;
- private FormulaCellCacheEntry[] _arr;
+ private int _size;
+ private FormulaCellCacheEntry[] _arr;
- public FormulaCellCacheEntrySet() {
- _arr = EMPTY_ARRAY;
- }
-
- public FormulaCellCacheEntry[] toArray() {
- int nItems = _size;
- if (nItems < 1) {
- return EMPTY_ARRAY;
- }
- FormulaCellCacheEntry[] result = new FormulaCellCacheEntry[nItems];
- int j=0;
- for(int i=0; i<_arr.length; i++) {
- FormulaCellCacheEntry cce = _arr[i];
- if (cce != null) {
- result[j++] = cce;
- }
- }
- if (j!= nItems) {
- throw new IllegalStateException("size mismatch");
- }
- return result;
- }
-
-
- public void add(CellCacheEntry cce) {
- if (_size * 3 >= _arr.length * 2) {
- // re-hash
- FormulaCellCacheEntry[] prevArr = _arr;
- FormulaCellCacheEntry[] newArr = new FormulaCellCacheEntry[4 + _arr.length * 3 / 2]; // grow 50%
- for(int i=0; i<prevArr.length; i++) {
- FormulaCellCacheEntry prevCce = _arr[i];
- if (prevCce != null) {
- addInternal(newArr, prevCce);
- }
- }
- _arr = newArr;
- }
- if (addInternal(_arr, cce)) {
- _size++;
- }
- }
-
-
- private static boolean addInternal(CellCacheEntry[] arr, CellCacheEntry cce) {
- int startIx = Math.abs(cce.hashCode() % arr.length);
-
- for(int i=startIx; i<arr.length; i++) {
- CellCacheEntry item = arr[i];
- if (item == cce) {
- // already present
- return false;
- }
- if (item == null) {
- arr[i] = cce;
- return true;
- }
- }
- for(int i=0; i<startIx; i++) {
- CellCacheEntry item = arr[i];
- if (item == cce) {
- // already present
- return false;
- }
- if (item == null) {
- arr[i] = cce;
- return true;
- }
- }
- throw new IllegalStateException("No empty space found");
- }
-
- public boolean remove(CellCacheEntry cce) {
- FormulaCellCacheEntry[] arr = _arr;
-
- if (_size * 3 < _arr.length && _arr.length > 8) {
- // re-hash
- boolean found = false;
- FormulaCellCacheEntry[] prevArr = _arr;
- FormulaCellCacheEntry[] newArr = new FormulaCellCacheEntry[_arr.length / 2]; // shrink 50%
- for(int i=0; i<prevArr.length; i++) {
- FormulaCellCacheEntry prevCce = _arr[i];
- if (prevCce != null) {
- if (prevCce == cce) {
- found=true;
- _size--;
- // skip it
- continue;
- }
- addInternal(newArr, prevCce);
- }
- }
- _arr = newArr;
- return found;
- }
- // else - usual case
- // delete single element (without re-hashing)
-
- int startIx = Math.abs(cce.hashCode() % arr.length);
-
- // note - can't exit loops upon finding null because of potential previous deletes
- for(int i=startIx; i<arr.length; i++) {
- FormulaCellCacheEntry item = arr[i];
- if (item == cce) {
- // found it
- arr[i] = null;
- _size--;
- return true;
- }
- }
- for(int i=0; i<startIx; i++) {
- FormulaCellCacheEntry item = arr[i];
- if (item == cce) {
- // found it
- arr[i] = null;
- _size--;
- return true;
- }
- }
- return false;
- }
+ public FormulaCellCacheEntrySet() {
+ _arr = EMPTY_ARRAY;
+ }
+
+ public FormulaCellCacheEntry[] toArray() {
+ int nItems = _size;
+ if (nItems < 1) {
+ return EMPTY_ARRAY;
+ }
+ FormulaCellCacheEntry[] result = new FormulaCellCacheEntry[nItems];
+ int j=0;
+ for(int i=0; i<_arr.length; i++) {
+ FormulaCellCacheEntry cce = _arr[i];
+ if (cce != null) {
+ result[j++] = cce;
+ }
+ }
+ if (j!= nItems) {
+ throw new IllegalStateException("size mismatch");
+ }
+ return result;
+ }
+
+
+ public void add(CellCacheEntry cce) {
+ if (_size * 3 >= _arr.length * 2) {
+ // re-hash
+ FormulaCellCacheEntry[] prevArr = _arr;
+ FormulaCellCacheEntry[] newArr = new FormulaCellCacheEntry[4 + _arr.length * 3 / 2]; // grow 50%
+ for(int i=0; i<prevArr.length; i++) {
+ FormulaCellCacheEntry prevCce = _arr[i];
+ if (prevCce != null) {
+ addInternal(newArr, prevCce);
+ }
+ }
+ _arr = newArr;
+ }
+ if (addInternal(_arr, cce)) {
+ _size++;
+ }
+ }
+
+
+ private static boolean addInternal(CellCacheEntry[] arr, CellCacheEntry cce) {
+ int startIx = Math.abs(cce.hashCode() % arr.length);
+
+ for(int i=startIx; i<arr.length; i++) {
+ CellCacheEntry item = arr[i];
+ if (item == cce) {
+ // already present
+ return false;
+ }
+ if (item == null) {
+ arr[i] = cce;
+ return true;
+ }
+ }
+ for(int i=0; i<startIx; i++) {
+ CellCacheEntry item = arr[i];
+ if (item == cce) {
+ // already present
+ return false;
+ }
+ if (item == null) {
+ arr[i] = cce;
+ return true;
+ }
+ }
+ throw new IllegalStateException("No empty space found");
+ }
+
+ public boolean remove(CellCacheEntry cce) {
+ FormulaCellCacheEntry[] arr = _arr;
+
+ if (_size * 3 < _arr.length && _arr.length > 8) {
+ // re-hash
+ boolean found = false;
+ FormulaCellCacheEntry[] prevArr = _arr;
+ FormulaCellCacheEntry[] newArr = new FormulaCellCacheEntry[_arr.length / 2]; // shrink 50%
+ for(int i=0; i<prevArr.length; i++) {
+ FormulaCellCacheEntry prevCce = _arr[i];
+ if (prevCce != null) {
+ if (prevCce == cce) {
+ found=true;
+ _size--;
+ // skip it
+ continue;
+ }
+ addInternal(newArr, prevCce);
+ }
+ }
+ _arr = newArr;
+ return found;
+ }
+ // else - usual case
+ // delete single element (without re-hashing)
+
+ int startIx = Math.abs(cce.hashCode() % arr.length);
+
+ // note - can't exit loops upon finding null because of potential previous deletes
+ for(int i=startIx; i<arr.length; i++) {
+ FormulaCellCacheEntry item = arr[i];
+ if (item == cce) {
+ // found it
+ arr[i] = null;
+ _size--;
+ return true;
+ }
+ }
+ for(int i=0; i<startIx; i++) {
+ FormulaCellCacheEntry item = arr[i];
+ if (item == cce) {
+ // found it
+ arr[i] = null;
+ _size--;
+ return true;
+ }
+ }
+ return false;
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaParseException.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaParseException.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaParseException.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaParseException.java Sat May 22 20:56:44 2021
@@ -6,7 +6,7 @@
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
+ http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
@@ -25,7 +25,7 @@ package org.apache.poi.ss.formula;
*/
public final class FormulaParseException extends RuntimeException {
- FormulaParseException(String msg) {
- super(msg);
- }
+ FormulaParseException(String msg) {
+ super(msg);
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java Sat May 22 20:56:44 2021
@@ -1155,7 +1155,7 @@ public final class FormulaParser {
private SheetIdentifier parseSheetName() {
String bookName;
if (look == '[') {
- bookName = getBookName();
+ bookName = getBookName();
} else {
bookName = null;
}
@@ -1164,7 +1164,7 @@ public final class FormulaParser {
Match('\'');
if (look == '[')
- bookName = getBookName();
+ bookName = getBookName();
StringBuilder sb = new StringBuilder();
boolean done = look == '\'';
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaRenderingWorkbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaRenderingWorkbook.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaRenderingWorkbook.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaRenderingWorkbook.java Sat May 22 20:56:44 2021
@@ -27,20 +27,20 @@ import org.apache.poi.util.Internal;
*/
@Internal
public interface FormulaRenderingWorkbook {
- /**
- * @return {@code null} if externSheetIndex refers to a sheet inside the current workbook
- */
- ExternalSheet getExternalSheet(int externSheetIndex);
+ /**
+ * @return {@code null} if externSheetIndex refers to a sheet inside the current workbook
+ */
+ ExternalSheet getExternalSheet(int externSheetIndex);
- /**
- * @return the name of the (first) sheet referred to by the given external sheet index
- */
- String getSheetFirstNameByExternSheet(int externSheetIndex);
+ /**
+ * @return the name of the (first) sheet referred to by the given external sheet index
+ */
+ String getSheetFirstNameByExternSheet(int externSheetIndex);
/**
* @return the name of the (last) sheet referred to by the given external sheet index
*/
String getSheetLastNameByExternSheet(int externSheetIndex);
- String resolveNameXText(NameXPtg nameXPtg);
- String getNameText(NamePtg namePtg);
+ String resolveNameXText(NameXPtg nameXPtg);
+ String getNameText(NamePtg namePtg);
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaUsedBlankCellSet.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaUsedBlankCellSet.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaUsedBlankCellSet.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaUsedBlankCellSet.java Sat May 22 20:56:44 2021
@@ -28,176 +28,176 @@ import org.apache.poi.ss.util.CellRefere
* Optimization - compacts many blank cell references used by a single formula.
*/
final class FormulaUsedBlankCellSet {
- public static final class BookSheetKey {
+ public static final class BookSheetKey {
- private final int _bookIndex;
- private final int _sheetIndex;
+ private final int _bookIndex;
+ private final int _sheetIndex;
- public BookSheetKey(int bookIndex, int sheetIndex) {
- _bookIndex = bookIndex;
- _sheetIndex = sheetIndex;
- }
- @Override
+ public BookSheetKey(int bookIndex, int sheetIndex) {
+ _bookIndex = bookIndex;
+ _sheetIndex = sheetIndex;
+ }
+ @Override
public int hashCode() {
- return _bookIndex * 17 + _sheetIndex;
- }
- @Override
+ return _bookIndex * 17 + _sheetIndex;
+ }
+ @Override
public boolean equals(Object obj) {
- if (!(obj instanceof BookSheetKey)) {
- return false;
- }
- BookSheetKey other = (BookSheetKey) obj;
- return _bookIndex == other._bookIndex && _sheetIndex == other._sheetIndex;
- }
- }
-
- private static final class BlankCellSheetGroup {
- private final List<BlankCellRectangleGroup> _rectangleGroups;
- private int _currentRowIndex;
- private int _firstColumnIndex;
- private int _lastColumnIndex;
- private BlankCellRectangleGroup _currentRectangleGroup;
+ if (!(obj instanceof BookSheetKey)) {
+ return false;
+ }
+ BookSheetKey other = (BookSheetKey) obj;
+ return _bookIndex == other._bookIndex && _sheetIndex == other._sheetIndex;
+ }
+ }
+
+ private static final class BlankCellSheetGroup {
+ private final List<BlankCellRectangleGroup> _rectangleGroups;
+ private int _currentRowIndex;
+ private int _firstColumnIndex;
+ private int _lastColumnIndex;
+ private BlankCellRectangleGroup _currentRectangleGroup;
private int _lastDefinedRow;
- public BlankCellSheetGroup(int lastDefinedRow) {
- _rectangleGroups = new ArrayList<>();
- _currentRowIndex = -1;
- _lastDefinedRow = lastDefinedRow;
- }
-
- public void addCell(int rowIndex, int columnIndex) {
- if (rowIndex > _lastDefinedRow) return;
-
- if (_currentRowIndex == -1) {
- _currentRowIndex = rowIndex;
- _firstColumnIndex = columnIndex;
- _lastColumnIndex = columnIndex;
- } else {
- if (_currentRowIndex == rowIndex && _lastColumnIndex+1 == columnIndex) {
- _lastColumnIndex = columnIndex;
- } else {
- // cell does not fit on end of current row
- if (_currentRectangleGroup == null) {
- _currentRectangleGroup = new BlankCellRectangleGroup(_currentRowIndex, _firstColumnIndex, _lastColumnIndex);
- } else {
- if (!_currentRectangleGroup.acceptRow(_currentRowIndex, _firstColumnIndex, _lastColumnIndex)) {
- _rectangleGroups.add(_currentRectangleGroup);
- _currentRectangleGroup = new BlankCellRectangleGroup(_currentRowIndex, _firstColumnIndex, _lastColumnIndex);
- }
- }
- _currentRowIndex = rowIndex;
- _firstColumnIndex = columnIndex;
- _lastColumnIndex = columnIndex;
- }
- }
- }
-
- public boolean containsCell(int rowIndex, int columnIndex) {
- if (rowIndex > _lastDefinedRow) return true;
-
- for (int i=_rectangleGroups.size()-1; i>=0; i--) {
- BlankCellRectangleGroup bcrg = _rectangleGroups.get(i);
- if (bcrg.containsCell(rowIndex, columnIndex)) {
- return true;
- }
- }
- if(_currentRectangleGroup != null && _currentRectangleGroup.containsCell(rowIndex, columnIndex)) {
- return true;
- }
- if (_currentRowIndex != -1 && _currentRowIndex == rowIndex) {
- if (_firstColumnIndex <= columnIndex && columnIndex <= _lastColumnIndex) {
- return true;
- }
- }
- return false;
- }
- }
-
- private static final class BlankCellRectangleGroup {
-
- private final int _firstRowIndex;
- private final int _firstColumnIndex;
- private final int _lastColumnIndex;
- private int _lastRowIndex;
-
- public BlankCellRectangleGroup(int firstRowIndex, int firstColumnIndex, int lastColumnIndex) {
- _firstRowIndex = firstRowIndex;
- _firstColumnIndex = firstColumnIndex;
- _lastColumnIndex = lastColumnIndex;
- _lastRowIndex = firstRowIndex;
- }
-
- public boolean containsCell(int rowIndex, int columnIndex) {
- if (columnIndex < _firstColumnIndex) {
- return false;
- }
- if (columnIndex > _lastColumnIndex) {
- return false;
- }
- if (rowIndex < _firstRowIndex) {
- return false;
- }
- if (rowIndex > _lastRowIndex) {
- return false;
- }
- return true;
- }
-
- public boolean acceptRow(int rowIndex, int firstColumnIndex, int lastColumnIndex) {
- if (firstColumnIndex != _firstColumnIndex) {
- return false;
- }
- if (lastColumnIndex != _lastColumnIndex) {
- return false;
- }
- if (rowIndex != _lastRowIndex+1) {
- return false;
- }
- _lastRowIndex = rowIndex;
- return true;
- }
- @Override
+ public BlankCellSheetGroup(int lastDefinedRow) {
+ _rectangleGroups = new ArrayList<>();
+ _currentRowIndex = -1;
+ _lastDefinedRow = lastDefinedRow;
+ }
+
+ public void addCell(int rowIndex, int columnIndex) {
+ if (rowIndex > _lastDefinedRow) return;
+
+ if (_currentRowIndex == -1) {
+ _currentRowIndex = rowIndex;
+ _firstColumnIndex = columnIndex;
+ _lastColumnIndex = columnIndex;
+ } else {
+ if (_currentRowIndex == rowIndex && _lastColumnIndex+1 == columnIndex) {
+ _lastColumnIndex = columnIndex;
+ } else {
+ // cell does not fit on end of current row
+ if (_currentRectangleGroup == null) {
+ _currentRectangleGroup = new BlankCellRectangleGroup(_currentRowIndex, _firstColumnIndex, _lastColumnIndex);
+ } else {
+ if (!_currentRectangleGroup.acceptRow(_currentRowIndex, _firstColumnIndex, _lastColumnIndex)) {
+ _rectangleGroups.add(_currentRectangleGroup);
+ _currentRectangleGroup = new BlankCellRectangleGroup(_currentRowIndex, _firstColumnIndex, _lastColumnIndex);
+ }
+ }
+ _currentRowIndex = rowIndex;
+ _firstColumnIndex = columnIndex;
+ _lastColumnIndex = columnIndex;
+ }
+ }
+ }
+
+ public boolean containsCell(int rowIndex, int columnIndex) {
+ if (rowIndex > _lastDefinedRow) return true;
+
+ for (int i=_rectangleGroups.size()-1; i>=0; i--) {
+ BlankCellRectangleGroup bcrg = _rectangleGroups.get(i);
+ if (bcrg.containsCell(rowIndex, columnIndex)) {
+ return true;
+ }
+ }
+ if(_currentRectangleGroup != null && _currentRectangleGroup.containsCell(rowIndex, columnIndex)) {
+ return true;
+ }
+ if (_currentRowIndex != -1 && _currentRowIndex == rowIndex) {
+ if (_firstColumnIndex <= columnIndex && columnIndex <= _lastColumnIndex) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ private static final class BlankCellRectangleGroup {
+
+ private final int _firstRowIndex;
+ private final int _firstColumnIndex;
+ private final int _lastColumnIndex;
+ private int _lastRowIndex;
+
+ public BlankCellRectangleGroup(int firstRowIndex, int firstColumnIndex, int lastColumnIndex) {
+ _firstRowIndex = firstRowIndex;
+ _firstColumnIndex = firstColumnIndex;
+ _lastColumnIndex = lastColumnIndex;
+ _lastRowIndex = firstRowIndex;
+ }
+
+ public boolean containsCell(int rowIndex, int columnIndex) {
+ if (columnIndex < _firstColumnIndex) {
+ return false;
+ }
+ if (columnIndex > _lastColumnIndex) {
+ return false;
+ }
+ if (rowIndex < _firstRowIndex) {
+ return false;
+ }
+ if (rowIndex > _lastRowIndex) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean acceptRow(int rowIndex, int firstColumnIndex, int lastColumnIndex) {
+ if (firstColumnIndex != _firstColumnIndex) {
+ return false;
+ }
+ if (lastColumnIndex != _lastColumnIndex) {
+ return false;
+ }
+ if (rowIndex != _lastRowIndex+1) {
+ return false;
+ }
+ _lastRowIndex = rowIndex;
+ return true;
+ }
+ @Override
public String toString() {
- StringBuilder sb = new StringBuilder(64);
- CellReference crA = new CellReference(_firstRowIndex, _firstColumnIndex, false, false);
- CellReference crB = new CellReference(_lastRowIndex, _lastColumnIndex, false, false);
- sb.append(getClass().getName());
- sb.append(" [").append(crA.formatAsString()).append(':').append(crB.formatAsString()).append("]");
- return sb.toString();
- }
- }
-
- private final Map<BookSheetKey, BlankCellSheetGroup> _sheetGroupsByBookSheet;
-
- public FormulaUsedBlankCellSet() {
- _sheetGroupsByBookSheet = new HashMap<>();
- }
-
- public void addCell(EvaluationWorkbook evalWorkbook, int bookIndex, int sheetIndex, int rowIndex, int columnIndex) {
- BlankCellSheetGroup sbcg = getSheetGroup(evalWorkbook, bookIndex, sheetIndex);
- sbcg.addCell(rowIndex, columnIndex);
- }
-
- private BlankCellSheetGroup getSheetGroup(EvaluationWorkbook evalWorkbook, int bookIndex, int sheetIndex) {
- BookSheetKey key = new BookSheetKey(bookIndex, sheetIndex);
-
- BlankCellSheetGroup result = _sheetGroupsByBookSheet.get(key);
- if (result == null) {
- result = new BlankCellSheetGroup(evalWorkbook.getSheet(sheetIndex).getLastRowNum());
- _sheetGroupsByBookSheet.put(key, result);
- }
- return result;
- }
-
- public boolean containsCell(BookSheetKey key, int rowIndex, int columnIndex) {
- BlankCellSheetGroup bcsg = _sheetGroupsByBookSheet.get(key);
- if (bcsg == null) {
- return false;
- }
- return bcsg.containsCell(rowIndex, columnIndex);
- }
-
- public boolean isEmpty() {
- return _sheetGroupsByBookSheet.isEmpty();
- }
+ StringBuilder sb = new StringBuilder(64);
+ CellReference crA = new CellReference(_firstRowIndex, _firstColumnIndex, false, false);
+ CellReference crB = new CellReference(_lastRowIndex, _lastColumnIndex, false, false);
+ sb.append(getClass().getName());
+ sb.append(" [").append(crA.formatAsString()).append(':').append(crB.formatAsString()).append("]");
+ return sb.toString();
+ }
+ }
+
+ private final Map<BookSheetKey, BlankCellSheetGroup> _sheetGroupsByBookSheet;
+
+ public FormulaUsedBlankCellSet() {
+ _sheetGroupsByBookSheet = new HashMap<>();
+ }
+
+ public void addCell(EvaluationWorkbook evalWorkbook, int bookIndex, int sheetIndex, int rowIndex, int columnIndex) {
+ BlankCellSheetGroup sbcg = getSheetGroup(evalWorkbook, bookIndex, sheetIndex);
+ sbcg.addCell(rowIndex, columnIndex);
+ }
+
+ private BlankCellSheetGroup getSheetGroup(EvaluationWorkbook evalWorkbook, int bookIndex, int sheetIndex) {
+ BookSheetKey key = new BookSheetKey(bookIndex, sheetIndex);
+
+ BlankCellSheetGroup result = _sheetGroupsByBookSheet.get(key);
+ if (result == null) {
+ result = new BlankCellSheetGroup(evalWorkbook.getSheet(sheetIndex).getLastRowNum());
+ _sheetGroupsByBookSheet.put(key, result);
+ }
+ return result;
+ }
+
+ public boolean containsCell(BookSheetKey key, int rowIndex, int columnIndex) {
+ BlankCellSheetGroup bcsg = _sheetGroupsByBookSheet.get(key);
+ if (bcsg == null) {
+ return false;
+ }
+ return bcsg.containsCell(rowIndex, columnIndex);
+ }
+
+ public boolean isEmpty() {
+ return _sheetGroupsByBookSheet.isEmpty();
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/IEvaluationListener.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/IEvaluationListener.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/IEvaluationListener.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/IEvaluationListener.java Sat May 22 20:56:44 2021
@@ -25,28 +25,28 @@ import org.apache.poi.ss.formula.eval.Va
* For POI internal testing use only
*/
interface IEvaluationListener {
- /**
- * A (mostly) opaque interface to allow test clients to trace cache values
- * Each spreadsheet cell gets one unique cache entry instance. These objects
- * are safe to use as keys in {@link java.util.HashMap}s
- */
- interface ICacheEntry {
- ValueEval getValue();
- }
+ /**
+ * A (mostly) opaque interface to allow test clients to trace cache values
+ * Each spreadsheet cell gets one unique cache entry instance. These objects
+ * are safe to use as keys in {@link java.util.HashMap}s
+ */
+ interface ICacheEntry {
+ ValueEval getValue();
+ }
- void onCacheHit(int sheetIndex, int rowIndex, int columnIndex, ValueEval result);
- void onReadPlainValue(int sheetIndex, int rowIndex, int columnIndex, ICacheEntry entry);
- void onStartEvaluate(EvaluationCell cell, ICacheEntry entry);
- void onEndEvaluate(ICacheEntry entry, ValueEval result);
- void onClearWholeCache();
- void onClearCachedValue(ICacheEntry entry);
- /**
- * Internally, formula {@link ICacheEntry}s are stored in sets which may change ordering due
- * to seemingly trivial changes. This method is provided to make the order of call-backs to
- * {@link #onClearDependentCachedValue(ICacheEntry, int)} more deterministic.
- */
- void sortDependentCachedValues(ICacheEntry[] formulaCells);
- void onClearDependentCachedValue(ICacheEntry formulaCell, int depth);
- void onChangeFromBlankValue(int sheetIndex, int rowIndex, int columnIndex,
- EvaluationCell cell, ICacheEntry entry);
+ void onCacheHit(int sheetIndex, int rowIndex, int columnIndex, ValueEval result);
+ void onReadPlainValue(int sheetIndex, int rowIndex, int columnIndex, ICacheEntry entry);
+ void onStartEvaluate(EvaluationCell cell, ICacheEntry entry);
+ void onEndEvaluate(ICacheEntry entry, ValueEval result);
+ void onClearWholeCache();
+ void onClearCachedValue(ICacheEntry entry);
+ /**
+ * Internally, formula {@link ICacheEntry}s are stored in sets which may change ordering due
+ * to seemingly trivial changes. This method is provided to make the order of call-backs to
+ * {@link #onClearDependentCachedValue(ICacheEntry, int)} more deterministic.
+ */
+ void sortDependentCachedValues(ICacheEntry[] formulaCells);
+ void onClearDependentCachedValue(ICacheEntry formulaCell, int depth);
+ void onChangeFromBlankValue(int sheetIndex, int rowIndex, int columnIndex,
+ EvaluationCell cell, ICacheEntry entry);
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/IStabilityClassifier.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/IStabilityClassifier.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/IStabilityClassifier.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/IStabilityClassifier.java Sat May 22 20:56:44 2021
@@ -55,26 +55,26 @@ package org.apache.poi.ss.formula;
*/
public interface IStabilityClassifier {
- /**
- * Convenience implementation for situations where all cell definitions remain fixed after
- * evaluation begins.
- */
- IStabilityClassifier TOTALLY_IMMUTABLE = new IStabilityClassifier() {
- public boolean isCellFinal(int sheetIndex, int rowIndex, int columnIndex) {
- return true;
- }
- };
+ /**
+ * Convenience implementation for situations where all cell definitions remain fixed after
+ * evaluation begins.
+ */
+ IStabilityClassifier TOTALLY_IMMUTABLE = new IStabilityClassifier() {
+ public boolean isCellFinal(int sheetIndex, int rowIndex, int columnIndex) {
+ return true;
+ }
+ };
- /**
- * Checks if a cell's value(/formula) is fixed - in other words - not expected to be modified
- * between calls to the evaluator. (Note - this is an independent concept from whether a
- * formula cell's evaluated value may change during successive calls to the evaluator).
- *
- * @param sheetIndex zero based index into workbook sheet list
- * @param rowIndex zero based row index of cell
- * @param columnIndex zero based column index of cell
- * @return <code>false</code> if the evaluating application may need to modify the specified
- * cell between calls to the evaluator.
- */
- boolean isCellFinal(int sheetIndex, int rowIndex, int columnIndex);
+ /**
+ * Checks if a cell's value(/formula) is fixed - in other words - not expected to be modified
+ * between calls to the evaluator. (Note - this is an independent concept from whether a
+ * formula cell's evaluated value may change during successive calls to the evaluator).
+ *
+ * @param sheetIndex zero based index into workbook sheet list
+ * @param rowIndex zero based row index of cell
+ * @param columnIndex zero based column index of cell
+ * @return <code>false</code> if the evaluating application may need to modify the specified
+ * cell between calls to the evaluator.
+ */
+ boolean isCellFinal(int sheetIndex, int rowIndex, int columnIndex);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org