public FormulaCellCacheEntry[] ToArray() { int nItems = _size; if (nItems < 1) { return(FormulaCellCacheEntry.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 InvalidOperationException("size mismatch"); } return(result); }
public void ClearConsumingCell(FormulaCellCacheEntry cce) { if (!_consumingCells.Remove(cce)) { throw new InvalidOperationException("Specified formula cell is not consumed by this cell"); } }
public void NotifyDeleteCell(int bookIndex, int sheetIndex, IEvaluationCell cell) { if (cell.CellType == Fruit.Utils.NPOI.SS.UserModel.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.RowIndex, cell.ColumnIndex); PlainValueCellCacheEntry pcce = _plainCellCache.Get(loc); if (pcce == null) { // cache entry doesn't exist. nothing To do } else { pcce.RecurseClearCachedFormulaResults(_evaluationListener); } } }
public FormulaCellCacheEntry Remove(IEvaluationCell cell) { FormulaCellCacheEntry tmp = (FormulaCellCacheEntry)_formulaEntriesByCell[cell.IdentityKey]; _formulaEntriesByCell.Remove(cell); return(tmp); }
public bool Remove(CellCacheEntry cce) { FormulaCellCacheEntry[] arr = _arr; if (_size * 3 < _arr.Length && _arr.Length > 8) { // re-Hash bool 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 = cce.GetHashCode() % 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 FormulaCellCacheEntry GetOrCreateFormulaCellEntry(IEvaluationCell cell) { FormulaCellCacheEntry result = _formulaCellCache.Get(cell); if (result == null) { result = new FormulaCellCacheEntry(); _formulaCellCache.Put(cell, result); } return(result); }
/** * Calls formulaCell.SetFormulaResult(null, null) recursively all the way up the tree of * dependencies. Calls usedCell.ClearConsumingCell(fc) for each child of a cell that Is * Cleared along the way. * @param formulaCells */ protected void RecurseClearCachedFormulaResults() { FormulaCellCacheEntry[] formulaCells = GetConsumingCells(); for (int i = 0; i < formulaCells.Length; i++) { FormulaCellCacheEntry fc = formulaCells[i]; fc.ClearFormulaEntry(); fc.RecurseClearCachedFormulaResults(); } }
/** * Identical To {@link #RecurseClearCachedFormulaResults()} except for the listener call-backs */ protected void RecurseClearCachedFormulaResults(IEvaluationListener listener, int depth) { FormulaCellCacheEntry[] formulaCells = GetConsumingCells(); listener.SortDependentCachedValues(formulaCells); for (int i = 0; i < formulaCells.Length; i++) { FormulaCellCacheEntry fc = formulaCells[i]; listener.OnClearDependentCachedValue(fc, depth); fc.ClearFormulaEntry(); fc.RecurseClearCachedFormulaResults(listener, depth + 1); } }
/** * Notifies this evaluation tracker that evaluation of the specified cell Is * about To start.<br/> * * In the case of a <c>true</c> return code, the caller should * continue evaluation of the specified cell, and also be sure To call * <c>endEvaluate()</c> when complete.<br/> * * In the case of a <c>null</c> return code, the caller should * return an evaluation result of * <c>ErrorEval.CIRCULAR_REF_ERROR</c>, and not call <c>endEvaluate()</c>. * <br/> * @return <c>false</c> if the specified cell is already being evaluated */ public bool StartEvaluate(FormulaCellCacheEntry cce) { if (cce == null) { throw new ArgumentException("cellLoc must not be null"); } if (_currentlyEvaluatingCells.Contains(cce)) { return(false); } _currentlyEvaluatingCells.Add(cce); _evaluationFrames.Add(new CellEvaluationFrame(cce)); return(true); }
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++; } }
public void AddConsumingCell(FormulaCellCacheEntry cellLoc) { _consumingCells.Add(cellLoc); }
public CellEvaluationFrame(FormulaCellCacheEntry cce) { _cce = cce; _sensitiveInputCells = new ArrayList(); }
/** * @return never <c>null</c>, never {@link BlankEval} */ private ValueEval EvaluateAny(IEvaluationCell srcCell, int sheetIndex, int rowIndex, int columnIndex, EvaluationTracker tracker) { bool shouldCellDependencyBeRecorded = _stabilityClassifier == null ? true : !_stabilityClassifier.IsCellFinal(sheetIndex, rowIndex, columnIndex); ValueEval result; if (srcCell == null || srcCell.CellType != CellType.FORMULA) { result = GetValueFromNonFormulaCell(srcCell); if (shouldCellDependencyBeRecorded) { tracker.AcceptPlainValueDependency(_workbookIx, sheetIndex, rowIndex, columnIndex, result); } return(result); } FormulaCellCacheEntry cce = _cache.GetOrCreateFormulaCellEntry(srcCell); if (shouldCellDependencyBeRecorded || cce.IsInputSensitive) { tracker.AcceptFormulaDependency(cce); } IEvaluationListener evalListener = _evaluationListener; if (cce.GetValue() == null) { if (!tracker.StartEvaluate(cce)) { return(ErrorEval.CIRCULAR_REF_ERROR); } OperationEvaluationContext ec = new OperationEvaluationContext(this, _workbook, sheetIndex, rowIndex, columnIndex, tracker); try { Ptg[] ptgs = _workbook.GetFormulaTokens(srcCell); if (evalListener == null) { result = EvaluateFormula(ec, ptgs); } else { evalListener.OnStartEvaluate(srcCell, cce); result = EvaluateFormula(ec, ptgs); evalListener.OnEndEvaluate(cce, result); } tracker.UpdateCacheResult(result); } catch (NotImplementedException e) { throw AddExceptionInfo(e, sheetIndex, rowIndex, columnIndex); } finally { tracker.EndEvaluate(cce); } } else { if (evalListener != null) { evalListener.OnCacheHit(sheetIndex, rowIndex, columnIndex, cce.GetValue()); } return(cce.GetValue()); } if (IsDebugLogEnabled()) { String sheetName = GetSheetName(sheetIndex); CellReference cr = new CellReference(rowIndex, columnIndex); LogDebug("Evaluated " + sheetName + "!" + cr.FormatAsString() + " To " + cce.GetValue().ToString()); } // Usually (result === cce.getValue()) // But sometimes: (result==ErrorEval.CIRCULAR_REF_ERROR, cce.getValue()==null) // When circular references are detected, the cache entry is only updated for // the top evaluation frame //return cce.GetValue(); return(result); }
public void NotifyUpdateCell(int bookIndex, int sheetIndex, IEvaluationCell cell) { FormulaCellCacheEntry fcce = _formulaCellCache.Get(cell); int rowIndex = cell.RowIndex; int columnIndex = cell.ColumnIndex; Loc loc = new Loc(bookIndex, sheetIndex, cell.RowIndex, cell.ColumnIndex); PlainValueCellCacheEntry pcce = _plainCellCache.Get(loc); if (cell.CellType == Fruit.Utils.NPOI.SS.UserModel.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) { 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); } } }
public CellCacheEntry[] GetCacheEntries() { FormulaCellCacheEntry[] result = new FormulaCellCacheEntry[_formulaEntriesByCell.Count]; _formulaEntriesByCell.Values.CopyTo(result, 0); return(result); }
public void Put(IEvaluationCell cell, FormulaCellCacheEntry entry) { _formulaEntriesByCell[cell.IdentityKey] = entry; }
public void ProcessEntry(FormulaCellCacheEntry entry) { entry.NotifyUpdatedBlankCell(bsk, rowIndex, columnIndex, evaluationListener); }