/** * Used by the lazy ref evals whenever they need To Get the value of a contained cell. */ /* package */ public ValueEval EvaluateReference(IEvaluationSheet sheet, int sheetIndex, int rowIndex, int columnIndex, EvaluationTracker tracker) { IEvaluationCell cell = sheet.GetCell(rowIndex, columnIndex); return(EvaluateAny(cell, sheetIndex, rowIndex, columnIndex, tracker)); }
public SheetRefEvaluator(WorkbookEvaluator bookEvaluator, EvaluationTracker tracker, EvaluationWorkbook _workbook, int sheetIndex) { _bookEvaluator = bookEvaluator; _tracker = tracker; _sheet = _workbook.GetSheet(sheetIndex); _sheetIndex = sheetIndex; }
public SheetRefEvaluator(WorkbookEvaluator bookEvaluator, EvaluationTracker tracker, int sheetIndex) { if (sheetIndex < 0) { throw new ArgumentException("Invalid sheetIndex: " + sheetIndex + "."); } _bookEvaluator = bookEvaluator; _tracker = tracker; _sheetIndex = sheetIndex; }
public OperationEvaluationContext(WorkbookEvaluator bookEvaluator, IEvaluationWorkbook workbook, int sheetIndex, int srcRowNum, int srcColNum, EvaluationTracker tracker) { _bookEvaluator = bookEvaluator; _workbook = workbook; _sheetIndex = sheetIndex; _rowIndex = srcRowNum; _columnIndex = srcColNum; _tracker = tracker; }
/** * @return never <c>null</c>, never {@link BlankEval} */ private ValueEval EvaluateAny(EvaluationCell srcCell, int sheetIndex, int rowIndex, int columnIndex, EvaluationTracker tracker) { if (srcCell == null || srcCell.CellType != CellType.FORMULA) { ValueEval result = GetValueFromNonFormulaCell(srcCell); tracker.AcceptPlainValueDependency(_workbookIx, sheetIndex, rowIndex, columnIndex, result); return result; } FormulaCellCacheEntry cce = _cache.GetOrCreateFormulaCellEntry(srcCell); 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 { ValueEval result; 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); } 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()); } return cce.GetValue(); }
/** * @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); } catch (RuntimeException re) { if (re.InnerException is WorkbookNotFoundException && _ignoreMissingWorkbooks) { LogInfo(re.InnerException.Message + " - Continuing with cached value!"); switch (srcCell.CachedFormulaResultType) { case CellType.Numeric: result = new NumberEval(srcCell.NumericCellValue); break; case CellType.String: result = new StringEval(srcCell.StringCellValue); break; case CellType.Blank: result = BlankEval.instance; break; case CellType.Boolean: result = BoolEval.ValueOf(srcCell.BooleanCellValue); break; case CellType.Error: result = ErrorEval.ValueOf(srcCell.ErrorCellValue); break; case CellType.Formula: default: throw new RuntimeException("Unexpected cell type '" + srcCell.CellType + "' found!"); } } else { throw re; } } 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()); } // 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 OperationEvaluationContext(WorkbookEvaluator bookEvaluator, IEvaluationWorkbook workbook, int sheetIndex, int srcRowNum, int srcColNum, EvaluationTracker tracker) : this(bookEvaluator, workbook, sheetIndex, srcRowNum, srcColNum, tracker, isSingleValue : true) { }
/** * @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; }
private Eval EvaluateNameFormula(Ptg[] ptgs, int sheetIndex, EvaluationTracker tracker) { if (ptgs.Length > 1) { throw new Exception("Complex name formulas not supported yet"); } return GetEvalForPtg(ptgs[0], sheetIndex, tracker); }
/** * returns an appropriate Eval impl instance for the Ptg. The Ptg must be * one of: Area3DPtg, AreaPtg, ReferencePtg, Ref3DPtg, IntPtg, NumberPtg, * StringPtg, BoolPtg <br/>special Note: OperationPtg subtypes cannot be * passed here! */ private Eval GetEvalForPtg(Ptg ptg, int sheetIndex, EvaluationTracker tracker) { // consider converting all these (ptg is XxxPtg) expressions To (ptg.GetType() == XxxPtg.class) if (ptg is NamePtg) { // named ranges, macro functions NamePtg namePtg = (NamePtg)ptg; EvaluationName nameRecord = _workbook.GetName(namePtg); if (nameRecord.IsFunctionName) { return new NameEval(nameRecord.NameText); } if (nameRecord.HasFormula) { return EvaluateNameFormula(nameRecord.NameDefinition, sheetIndex, tracker); } throw new Exception("Don't now how To evalate name '" + nameRecord.NameText + "'"); } if (ptg is NameXPtg) { return new NameXEval(((NameXPtg)ptg)); } if (ptg is IntPtg) { return new NumberEval(((IntPtg)ptg).Value); } if (ptg is NumberPtg) { return new NumberEval(((NumberPtg)ptg).Value); } if (ptg is StringPtg) { return new StringEval(((StringPtg)ptg).Value); } if (ptg is BoolPtg) { return BoolEval.ValueOf(((BoolPtg)ptg).Value); } if (ptg is ErrPtg) { return ErrorEval.ValueOf(((ErrPtg)ptg).ErrorCode); } if (ptg is MissingArgPtg) { return MissingArgEval.instance; } if (ptg is AreaErrPtg || ptg is RefErrorPtg || ptg is DeletedArea3DPtg || ptg is DeletedRef3DPtg) { return ErrorEval.REF_INVALID; } if (ptg is Ref3DPtg) { Ref3DPtg refPtg = (Ref3DPtg)ptg; SheetRefEvaluator sre = CreateExternSheetRefEvaluator(tracker, refPtg); return new LazyRefEval(refPtg, sre); } if (ptg is Area3DPtg) { Area3DPtg aptg = (Area3DPtg)ptg; SheetRefEvaluator sre = CreateExternSheetRefEvaluator(tracker, aptg); return new LazyAreaEval(aptg, sre); } SheetRefEvaluator sre1 = new SheetRefEvaluator(this, tracker, _workbook, sheetIndex); if (ptg is RefPtg) { return new LazyRefEval(((RefPtg)ptg), sre1); } if (ptg is AreaPtg) { return new LazyAreaEval(((AreaPtg)ptg), sre1); } if (ptg is UnknownPtg) { // POI uses UnknownPtg when the encoded Ptg array seems To be corrupted. // This seems To occur in very rare cases (e.g. unused name formulas in bug 44774, attachment 21790) // In any case, formulas are re-parsed before execution, so UnknownPtg should not Get here throw new Exception("UnknownPtg not allowed"); } throw new Exception("Unexpected ptg class (" + ptg.GetType().Name + ")"); }
private SheetRefEvaluator CreateExternSheetRefEvaluator(EvaluationTracker tracker, ExternSheetReferenceToken ptg) { int externSheetIndex = ptg.ExternSheetIndex; ExternalSheet externalSheet = _workbook.GetExternalSheet(externSheetIndex); if (externalSheet != null) { WorkbookEvaluator otherEvaluator = _collaboratingWorkbookEnvironment.GetWorkbookEvaluator(externalSheet.GetWorkbookName()); EvaluationWorkbook otherBook = otherEvaluator._workbook; int otherSheetIndex = otherBook.GetSheetIndex(externalSheet.GetSheetName()); return new SheetRefEvaluator(otherEvaluator, tracker, otherBook, otherSheetIndex); } int otherSheetIndex1 = _workbook.ConvertFromExternSheetIndex(externSheetIndex); return new SheetRefEvaluator(this, tracker, _workbook, otherSheetIndex1); }
// visibility raised for testing /* package */ public ValueEval EvaluateFormula(int sheetIndex, int srcRowNum, int srcColNum, Ptg[] ptgs, EvaluationTracker tracker) { Stack stack = new Stack(); for (int i = 0, iSize = ptgs.Length; i < iSize; i++) { // since we don't know how To handle these yet :( Ptg ptg = ptgs[i]; if (ptg is AttrPtg) { AttrPtg attrPtg = (AttrPtg)ptg; if (attrPtg.IsSum) { // Excel prefers To encode 'SUM()' as a tAttr Token, but this evaluator // expects the equivalent function Token byte nArgs = 1; // tAttrSum always Has 1 parameter ptg = new FuncVarPtg("SUM", nArgs); } } if (ptg is ControlPtg) { // skip Parentheses, Attr, etc continue; } if (ptg is MemFuncPtg) { // can ignore, rest of Tokens for this expression are in OK RPN order continue; } if (ptg is MemErrPtg) { continue; } Eval opResult; if (ptg is OperationPtg) { OperationPtg optg = (OperationPtg)ptg; if (optg is UnionPtg) { continue; } OperationEval operation = OperationEvaluatorFactory.Create(optg); int numops = operation.NumberOfOperands; Eval[] ops = new Eval[numops]; // storing the ops in reverse order since they are popping for (int j = numops - 1; j >= 0; j--) { Eval p = (Eval)stack.Pop(); ops[j] = p; } // logDebug("Invoke " + operation + " (nAgs=" + numops + ")"); opResult = InvokeOperation(operation, ops, _workbook, sheetIndex, srcRowNum, srcColNum); if (opResult == MissingArgEval.instance) { opResult = BlankEval.INSTANCE; } } else { opResult = GetEvalForPtg(ptg, sheetIndex, tracker); } if (opResult == null) { throw new Exception("Evaluation result must not be null"); } // logDebug("push " + opResult); stack.Push(opResult); } ValueEval value = ((ValueEval)stack.Pop()); if (stack.Count != 0) { throw new InvalidOperationException("evaluation stack not empty"); } value = DereferenceValue(value, srcRowNum, srcColNum); if (value == BlankEval.INSTANCE) { // Note Excel behaviour here. A blank value Is converted To zero. return NumberEval.ZERO; // Formulas _never_ evaluate To blank. If a formula appears To have evaluated To // blank, the actual value Is empty string. This can be verified with ISBLANK(). } return value; }
/** * @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); }
/** * Used by the lazy ref evals whenever they need To Get the value of a contained cell. */ /* package */ public ValueEval EvaluateReference(EvaluationSheet sheet, int sheetIndex, int rowIndex, int columnIndex, EvaluationTracker tracker) { EvaluationCell cell = sheet.GetCell(rowIndex, columnIndex); return EvaluateAny(cell, sheetIndex, rowIndex, columnIndex, tracker); }
/** * @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); } catch (RuntimeException re) { if (re.InnerException is WorkbookNotFoundException && _ignoreMissingWorkbooks) { LogInfo(re.InnerException.Message + " - Continuing with cached value!"); switch (srcCell.CachedFormulaResultType) { case CellType.NUMERIC: result = new NumberEval(srcCell.NumericCellValue); break; case CellType.STRING: result = new StringEval(srcCell.StringCellValue); break; case CellType.BLANK: result = BlankEval.instance; break; case CellType.BOOLEAN: result = BoolEval.ValueOf(srcCell.BooleanCellValue); break; case CellType.ERROR: result = ErrorEval.ValueOf(srcCell.ErrorCellValue); break; case CellType.FORMULA: default: throw new RuntimeException("Unexpected cell type '" + srcCell.CellType + "' found!"); } } else { throw re; } } 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()); } // 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); }
/** * @return never <c>null</c>, never {@link BlankEval} */ private ValueEval EvaluateAny(EvaluationCell srcCell, int sheetIndex, int rowIndex, int columnIndex, EvaluationTracker tracker) { if (srcCell == null || srcCell.CellType != CellType.FORMULA) { ValueEval result = GetValueFromNonFormulaCell(srcCell); tracker.AcceptPlainValueDependency(_workbookIx, sheetIndex, rowIndex, columnIndex, result); return(result); } FormulaCellCacheEntry cce = _cache.GetOrCreateFormulaCellEntry(srcCell); 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 { ValueEval result; 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); } 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()); } return(cce.GetValue()); }