public ValueEval Evaluate(ValueEval[] args, OperationEvaluationContext ec) { int srcCellRow = ec.RowIndex; int srcCellCol = ec.ColumnIndex; double result; try { int basis = 0; // default switch (args.Length) { case 3: basis = EvaluateIntArg(args[2], srcCellRow, srcCellCol); break; case 2: //basis = EvaluateIntArg(args[2], srcCellRow, srcCellCol); break; default: return ErrorEval.VALUE_INVALID; } double startDateVal = EvaluateDateArg(args[0], srcCellRow, srcCellCol); double endDateVal = EvaluateDateArg(args[1], srcCellRow, srcCellCol); result = YearFracCalculator.Calculate(startDateVal, endDateVal, basis); } catch (EvaluationException e) { return e.GetErrorEval(); } return new NumberEval(result); }
public ValueEval Evaluate(ValueEval[] args, OperationEvaluationContext ec) { int nIncomingArgs = args.Length; if (nIncomingArgs < 1) { throw new Exception("function name argument missing"); } ValueEval nameArg = args[0]; String functionName = string.Empty ; if (nameArg is NameEval) { functionName = ((NameEval)nameArg).FunctionName; } else if (nameArg is NameXEval) { functionName = ec.GetWorkbook().ResolveNameXText(((NameXEval)nameArg).Ptg); } else { throw new Exception("First argument should be a NameEval, but got (" + nameArg.GetType().Name + ")"); } FreeRefFunction targetFunc = ec.FindUserDefinedFunction(functionName); if (targetFunc == null) { throw new NotImplementedException(functionName); } int nOutGoingArgs = nIncomingArgs - 1; ValueEval[] outGoingArgs = new ValueEval[nOutGoingArgs]; Array.Copy(args, 1, outGoingArgs, 0, nOutGoingArgs); return targetFunc.Evaluate(outGoingArgs, ec); }
/** * returns the OperationEval concrete impl instance corresponding * to the supplied operationPtg */ public static ValueEval Evaluate(OperationPtg ptg, ValueEval[] args, OperationEvaluationContext ec) { if(ptg == null) { throw new ArgumentException("ptg must not be null"); } Function result = _instancesByPtgClass[ptg] as Function; if (result != null) { return result.Evaluate(args, ec.RowIndex, (short) ec.ColumnIndex); } if (ptg is AbstractFunctionPtg) { AbstractFunctionPtg fptg = (AbstractFunctionPtg)ptg; int functionIndex = fptg.GetFunctionIndex(); switch (functionIndex) { case NPOI.HSSF.Record.Formula.Function.FunctionMetadataRegistry.FUNCTION_INDEX_INDIRECT: return Indirect.instance.Evaluate(args, ec); case NPOI.HSSF.Record.Formula.Function.FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL: return UserDefinedFunction.instance.Evaluate(args, ec); } return FunctionEval.GetBasicFunction(functionIndex).Evaluate(args, ec.RowIndex, ec.ColumnIndex); } throw new Exception("Unexpected operation ptg class (" + ptg.GetType().Name + ")"); }
public ValueEval Evaluate(ValueEval[] args, OperationEvaluationContext ec) { if (args.Length < 1) { return ErrorEval.VALUE_INVALID; } bool isA1style; String text; try { ValueEval ve = OperandResolver.GetSingleValue(args[0], ec.RowIndex, ec .ColumnIndex); text = OperandResolver.CoerceValueToString(ve); switch (args.Length) { case 1: isA1style = true; break; case 2: isA1style = EvaluateBooleanArg(args[1], ec); break; default: return ErrorEval.VALUE_INVALID; } } catch (EvaluationException e) { return e.GetErrorEval(); } return EvaluateIndirect(ec, text, isA1style); }
public ValueEval Evaluate(ValueEval[] args, OperationEvaluationContext ec) { if (args.Length != 1) { return ErrorEval.VALUE_INVALID; } return Evaluate(ec.RowIndex, ec.ColumnIndex, args[0]); }
public ValueEval Evaluate(ValueEval[] args, OperationEvaluationContext ec) { if (args.Length != 1 || !(args[0] is StringEval)) { return ErrorEval.VALUE_INVALID; } StringEval input = (StringEval)args[0]; return new StringEval(input.StringValue + "abc2"); }
private static bool EvaluateBooleanArg(ValueEval arg, OperationEvaluationContext ec) { ValueEval ve = OperandResolver.GetSingleValue(arg, ec.RowIndex, ec.ColumnIndex); if (ve == BlankEval.instance || ve == MissingArgEval.instance) { return false; } // numeric quantities follow standard bool conversion rules // for strings, only "TRUE" and "FALSE" (case insensitive) are valid return (bool)OperandResolver.CoerceValueToBoolean(ve, false); }
public ValueEval Evaluate(ValueEval[] args, OperationEvaluationContext ec) { if (args.Length != 1) { return ErrorEval.VALUE_INVALID; } int val; try { val = EvaluateArgParity(args[0], ec.RowIndex, ec.ColumnIndex); } catch (EvaluationException e) { return e.GetErrorEval(); } return BoolEval.ValueOf(val == _desiredParity); }
public ValueEval Evaluate(ValueEval[] args, OperationEvaluationContext ec) { if (args.Length != 2) { return ErrorEval.VALUE_INVALID; } try { double startDateAsNumber = NumericFunction.SingleOperandEvaluate(args[0], ec.RowIndex, ec.ColumnIndex); int months = (int)NumericFunction.SingleOperandEvaluate(args[1], ec.RowIndex, ec.ColumnIndex); // Excel treats date 0 as 1900-01-00; EOMONTH results in 1900-01-31 if (startDateAsNumber >= 0.0 && startDateAsNumber < 1.0) { startDateAsNumber = 1.0; } DateTime startDate = DateUtil.GetJavaDate(startDateAsNumber, false); //the month DateTime dtEnd = startDate.AddMonths(months); //next month dtEnd = dtEnd.AddMonths(1); //first day of next month dtEnd = new DateTime(dtEnd.Year, dtEnd.Month, 1); //last day of the month dtEnd = dtEnd.AddDays(-1); return new NumberEval(DateUtil.GetExcelDate(dtEnd)); } catch (EvaluationException e) { return e.GetErrorEval(); } }
public ValueEval Evaluate(ValueEval[] args, OperationEvaluationContext ec) { Double result = double.NaN; if (args.Length == 0 || args.Length % 2 > 0) { return ErrorEval.VALUE_INVALID; } for (int i = 0; i < args.Length; ) { ValueEval firstArg = args[i]; ValueEval secondArg = args[i + 1]; i += 2; NumberEval Evaluate = (NumberEval)new Countif().Evaluate(new ValueEval[] { firstArg, secondArg }, ec.RowIndex, ec.ColumnIndex); if (double.IsNaN(result)) { result = Evaluate.NumberValue; } else if (Evaluate.NumberValue < result) { result = Evaluate.NumberValue; } } return new NumberEval(double.IsNaN(result) ? 0 : result); }
/** * 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 ValueEval GetEvalForPtg(Ptg ptg, OperationEvaluationContext ec) { // 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, ec)); } 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 rptg = (Ref3DPtg)ptg; return(ec.GetRef3DEval(rptg.Row, rptg.Column, rptg.ExternSheetIndex)); } if (ptg is Area3DPtg) { Area3DPtg aptg = (Area3DPtg)ptg; return(ec.GetArea3DEval(aptg.FirstRow, aptg.FirstColumn, aptg.LastRow, aptg.LastColumn, aptg.ExternSheetIndex)); } if (ptg is RefPtg) { RefPtg rptg = (RefPtg)ptg; return(ec.GetRefEval(rptg.Row, rptg.Column)); } if (ptg is AreaPtg) { AreaPtg aptg = (AreaPtg)ptg; return(ec.GetAreaEval(aptg.FirstRow, aptg.FirstColumn, aptg.LastRow, aptg.LastColumn)); } 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 + ")"); }
/** * @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 ValueEval Evaluate(ValueEval[] args, OperationEvaluationContext ec) { throw new NotImplementedException("not implemented"); }
private OperationEvaluationContext CreateContext() { HSSFWorkbook wb = new HSSFWorkbook(); ISheet sheet = wb.CreateSheet(); IRow row = sheet.CreateRow(0); ICell cell = row.CreateCell(0); cell.SetCellValue("13.43"); cell = row.CreateCell(1); cell.SetCellValue("8"); cell = row.CreateCell(2); cell.SetCellValue("-8"); cell = row.CreateCell(3); cell.SetCellValue("1"); HSSFEvaluationWorkbook workbook = HSSFEvaluationWorkbook.Create(wb); WorkbookEvaluator workbookEvaluator = new WorkbookEvaluator(workbook, new IStabilityClassifier1(), null); OperationEvaluationContext ctx = new OperationEvaluationContext(workbookEvaluator, workbook, 0, 0, 0, null); return ctx; }
/** * 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 ValueEval GetEvalForPtg(Ptg ptg, OperationEvaluationContext ec) { // 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, ec); } 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 rptg = (Ref3DPtg)ptg; return ec.GetRef3DEval(rptg.Row, rptg.Column, rptg.ExternSheetIndex); } if (ptg is Area3DPtg) { Area3DPtg aptg = (Area3DPtg)ptg; return ec.GetArea3DEval(aptg.FirstRow, aptg.FirstColumn, aptg.LastRow, aptg.LastColumn, aptg.ExternSheetIndex); } if (ptg is RefPtg) { RefPtg rptg = (RefPtg)ptg; return ec.GetRefEval(rptg.Row, rptg.Column); } if (ptg is AreaPtg) { AreaPtg aptg = (AreaPtg)ptg; return ec.GetAreaEval(aptg.FirstRow, aptg.FirstColumn, aptg.LastRow, aptg.LastColumn); } 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 static ValueEval InvokeSumifs(ValueEval[] args, OperationEvaluationContext ec) { return new Sumifs().Evaluate(args, EC); }
// visibility raised for testing /* package */ public ValueEval EvaluateFormula(OperationEvaluationContext ec, Ptg[] ptgs) { Stack <ValueEval> stack = new Stack <ValueEval>(); 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 (attrPtg.IsOptimizedChoose) { ValueEval arg0 = stack.Pop(); int[] jumpTable = attrPtg.JumpTable; int dist; int nChoices = jumpTable.Length; try { int switchIndex = Choose.EvaluateFirstArg(arg0, ec.RowIndex, ec.ColumnIndex); if (switchIndex < 1 || switchIndex > nChoices) { stack.Push(ErrorEval.VALUE_INVALID); dist = attrPtg.ChooseFuncOffset + 4; // +4 for tFuncFar(CHOOSE) } else { dist = jumpTable[switchIndex - 1]; } } catch (EvaluationException e) { stack.Push(e.GetErrorEval()); dist = attrPtg.ChooseFuncOffset + 4; // +4 for tFuncFar(CHOOSE) } // Encoded dist for tAttrChoose includes size of jump table, but // countTokensToBeSkipped() does not (it counts whole tokens). dist -= nChoices * 2 + 2; // subtract jump table size i += CountTokensToBeSkipped(ptgs, i, dist); continue; } if (attrPtg.IsOptimizedIf) { ValueEval arg0 = stack.Pop(); bool evaluatedPredicate; try { evaluatedPredicate = If.EvaluateFirstArg(arg0, ec.RowIndex, ec.ColumnIndex); } catch (EvaluationException e) { stack.Push(e.GetErrorEval()); int dist = attrPtg.Data; i += CountTokensToBeSkipped(ptgs, i, dist); attrPtg = (AttrPtg)ptgs[i]; dist = attrPtg.Data + 1; i += CountTokensToBeSkipped(ptgs, i, dist); continue; } if (evaluatedPredicate) { // nothing to skip - true param folows } else { int dist = attrPtg.Data; i += CountTokensToBeSkipped(ptgs, i, dist); Ptg nextPtg = ptgs[i + 1]; if (ptgs[i] is AttrPtg && nextPtg is FuncVarPtg) { // this is an if statement without a false param (as opposed to MissingArgPtg as the false param) i++; stack.Push(BoolEval.FALSE); } } continue; } if (attrPtg.IsSkip) { int dist = attrPtg.Data + 1; i += CountTokensToBeSkipped(ptgs, i, dist); if (stack.Peek() == MissingArgEval.instance) { stack.Pop(); stack.Push(BlankEval.instance); } continue; } } 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; } ValueEval opResult; if (ptg is OperationPtg) { OperationPtg optg = (OperationPtg)ptg; if (optg is UnionPtg) { continue; } int numops = optg.NumberOfOperands; ValueEval[] ops = new ValueEval[numops]; // storing the ops in reverse order since they are popping for (int j = numops - 1; j >= 0; j--) { ValueEval p = (ValueEval)stack.Pop(); ops[j] = p; } // logDebug("Invoke " + operation + " (nAgs=" + numops + ")"); opResult = OperationEvaluatorFactory.Evaluate(optg, ops, ec); } else { opResult = GetEvalForPtg(ptg, ec); } 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, ec.RowIndex, ec.ColumnIndex); 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); }
private static ValueEval EvaluateFormula(Ptg[] ptgs) { OperationEvaluationContext ec = new OperationEvaluationContext(null, null, 0, 0, 0, null); return new WorkbookEvaluator(null, null, null).EvaluateFormula(ec, ptgs); }
internal ValueEval EvaluateNameFormula(Ptg[] ptgs, OperationEvaluationContext ec) { if (ptgs.Length == 1) { return GetEvalForPtg(ptgs[0], ec); } return EvaluateFormula(ec, ptgs); }
/** * 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 ValueEval GetEvalForPtg(Ptg ptg, OperationEvaluationContext ec) { // 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; IEvaluationName nameRecord = _workbook.GetName(namePtg); return GetEvalForNameRecord(nameRecord, ec); } if (ptg is NameXPtg) { // Externally defined named ranges or macro functions return ProcessNameEval(ec.GetNameXEval((NameXPtg)ptg), ec); } if (ptg is NameXPxg) { // Externally defined named ranges or macro functions return ProcessNameEval(ec.GetNameXEval((NameXPxg)ptg), ec); } 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) { return ec.GetRef3DEval((Ref3DPtg)ptg); } if (ptg is Ref3DPxg) { return ec.GetRef3DEval((Ref3DPxg)ptg); } if (ptg is Area3DPtg) { return ec.GetArea3DEval((Area3DPtg)ptg); } if (ptg is Area3DPxg) { return ec.GetArea3DEval((Area3DPxg)ptg); } if (ptg is RefPtg) { RefPtg rptg = (RefPtg)ptg; return ec.GetRefEval(rptg.Row, rptg.Column); } if (ptg is AreaPtg) { AreaPtg aptg = (AreaPtg)ptg; return ec.GetAreaEval(aptg.FirstRow, aptg.FirstColumn, aptg.LastRow, aptg.LastColumn); } 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 RuntimeException("UnknownPtg not allowed"); } if (ptg is ExpPtg) { // ExpPtg is used for array formulas and shared formulas. // it is currently unsupported, and may not even get implemented here throw new RuntimeException("ExpPtg currently not supported"); } throw new RuntimeException("Unexpected ptg class (" + ptg.GetType().Name + ")"); }
// visibility raised for testing /* package */ public ValueEval EvaluateFormula(OperationEvaluationContext ec, Ptg[] ptgs) { String dbgIndentStr = ""; // always init. to non-null just for defensive avoiding NPE if (dbgEvaluationOutputForNextEval) { // first evaluation call when ouput is desired, so iit. this evaluator instance dbgEvaluationOutputIndent = 1; dbgEvaluationOutputForNextEval = false; } if (dbgEvaluationOutputIndent > 0) { // init. indent string to needed spaces (create as substring vom very long space-only string; // limit indendation for deep recursions) dbgIndentStr = " "; dbgIndentStr = dbgIndentStr.Substring(0, Math.Min(dbgIndentStr.Length, dbgEvaluationOutputIndent * 2)); EVAL_LOG.Log(POILogger.WARN, dbgIndentStr + "- evaluateFormula('" + ec.GetRefEvaluatorForCurrentSheet().SheetName + "'/" + new CellReference(ec.RowIndex, ec.ColumnIndex).FormatAsString() + "): " + Arrays.ToString(ptgs).Replace("\\Qorg.apache.poi.ss.formula.ptg.\\E", "")); dbgEvaluationOutputIndent++; } Stack<ValueEval> stack = new Stack<ValueEval>(); 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 (dbgEvaluationOutputIndent > 0) { EVAL_LOG.Log(POILogger.INFO, dbgIndentStr + " * ptg " + i + ": " + ptg.ToString()); } 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 = FuncVarPtg.SUM;//.Create("SUM", nArgs); } if (attrPtg.IsOptimizedChoose) { ValueEval arg0 = stack.Pop(); int[] jumpTable = attrPtg.JumpTable; int dist; int nChoices = jumpTable.Length; try { int switchIndex = Choose.EvaluateFirstArg(arg0, ec.RowIndex, ec.ColumnIndex); if (switchIndex < 1 || switchIndex > nChoices) { stack.Push(ErrorEval.VALUE_INVALID); dist = attrPtg.ChooseFuncOffset + 4; // +4 for tFuncFar(CHOOSE) } else { dist = jumpTable[switchIndex - 1]; } } catch (EvaluationException e) { stack.Push(e.GetErrorEval()); dist = attrPtg.ChooseFuncOffset + 4; // +4 for tFuncFar(CHOOSE) } // Encoded dist for tAttrChoose includes size of jump table, but // countTokensToBeSkipped() does not (it counts whole tokens). dist -= nChoices * 2 + 2; // subtract jump table size i += CountTokensToBeSkipped(ptgs, i, dist); continue; } if (attrPtg.IsOptimizedIf) { ValueEval arg0 = stack.Pop(); bool evaluatedPredicate; try { evaluatedPredicate = If.EvaluateFirstArg(arg0, ec.RowIndex, ec.ColumnIndex); } catch (EvaluationException e) { stack.Push(e.GetErrorEval()); int dist = attrPtg.Data; i += CountTokensToBeSkipped(ptgs, i, dist); attrPtg = (AttrPtg)ptgs[i]; dist = attrPtg.Data + 1; i += CountTokensToBeSkipped(ptgs, i, dist); continue; } if (evaluatedPredicate) { // nothing to skip - true param folows } else { int dist = attrPtg.Data; i += CountTokensToBeSkipped(ptgs, i, dist); Ptg nextPtg = ptgs[i + 1]; if (ptgs[i] is AttrPtg && nextPtg is FuncVarPtg) { // this is an if statement without a false param (as opposed to MissingArgPtg as the false param) i++; stack.Push(BoolEval.FALSE); } } continue; } if (attrPtg.IsSkip) { int dist = attrPtg.Data + 1; i += CountTokensToBeSkipped(ptgs, i, dist); if (stack.Peek() == MissingArgEval.instance) { stack.Pop(); stack.Push(BlankEval.instance); } continue; } } if (ptg is ControlPtg) { // skip Parentheses, Attr, etc continue; } if (ptg is MemFuncPtg|| ptg is MemAreaPtg) { // can ignore, rest of Tokens for this expression are in OK RPN order continue; } if (ptg is MemErrPtg) { continue; } ValueEval opResult; if (ptg is OperationPtg) { OperationPtg optg = (OperationPtg)ptg; if (optg is UnionPtg) { continue; } int numops = optg.NumberOfOperands; ValueEval[] ops = new ValueEval[numops]; // storing the ops in reverse order since they are popping for (int j = numops - 1; j >= 0; j--) { ValueEval p = (ValueEval)stack.Pop(); ops[j] = p; } // logDebug("Invoke " + operation + " (nAgs=" + numops + ")"); opResult = OperationEvaluatorFactory.Evaluate(optg, ops, ec); } else { opResult = GetEvalForPtg(ptg, ec); } if (opResult == null) { throw new Exception("Evaluation result must not be null"); } // logDebug("push " + opResult); stack.Push(opResult); if (dbgEvaluationOutputIndent > 0) { EVAL_LOG.Log(POILogger.INFO, dbgIndentStr + " = " + opResult.ToString()); } } ValueEval value = ((ValueEval)stack.Pop()); if (stack.Count != 0) { throw new InvalidOperationException("evaluation stack not empty"); } ValueEval result = DereferenceResult(value, ec.RowIndex, ec.ColumnIndex); if (dbgEvaluationOutputIndent > 0) { EVAL_LOG.Log(POILogger.INFO, dbgIndentStr + "finshed eval of " + new CellReference(ec.RowIndex, ec.ColumnIndex).FormatAsString() + ": " + result.ToString()); dbgEvaluationOutputIndent--; if (dbgEvaluationOutputIndent == 1) { // this evaluation is done, reset indent to stop logging dbgEvaluationOutputIndent = -1; } } // if return result; }
/** * @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; }
private ValueEval ProcessNameEval(ValueEval eval, OperationEvaluationContext ec) { if (eval is ExternalNameEval) { IEvaluationName name = ((ExternalNameEval)eval).Name; return GetEvalForNameRecord(name, ec); } return eval; }
/** * @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(); }
private static ValueEval EvaluateIndirect(OperationEvaluationContext ec, String text, bool isA1style) { // Search backwards for '!' because sheet names can contain '!' int plingPos = text.LastIndexOf('!'); String workbookName; String sheetName; String refText; // whitespace around this Gets Trimmed OK if (plingPos < 0) { workbookName = null; sheetName = null; refText = text; } else { String[] parts = ParseWorkbookAndSheetName(text.Substring(0, plingPos)); if (parts == null) { return ErrorEval.REF_INVALID; } workbookName = parts[0]; sheetName = parts[1]; refText = text.Substring(plingPos + 1); } String refStrPart1; String refStrPart2; int colonPos = refText.IndexOf(':'); if (colonPos < 0) { refStrPart1 = refText.Trim(); refStrPart2 = null; } else { refStrPart1 = refText.Substring(0, colonPos).Trim(); refStrPart2 = refText.Substring(colonPos + 1).Trim(); } return ec.GetDynamicReference(workbookName, sheetName, refStrPart1, refStrPart2, isA1style); }
// visibility raised for testing /* package */ public ValueEval EvaluateFormula(OperationEvaluationContext ec, Ptg[] ptgs) { Stack<ValueEval> stack = new Stack<ValueEval>(); 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 (attrPtg.IsOptimizedChoose) { ValueEval arg0 = stack.Pop(); int[] jumpTable = attrPtg.JumpTable; int dist; int nChoices = jumpTable.Length; try { int switchIndex = Choose.EvaluateFirstArg(arg0, ec.RowIndex, ec.ColumnIndex); if (switchIndex<1 || switchIndex > nChoices) { stack.Push(ErrorEval.VALUE_INVALID); dist = attrPtg.ChooseFuncOffset + 4; // +4 for tFuncFar(CHOOSE) } else { dist = jumpTable[switchIndex-1]; } } catch (EvaluationException e) { stack.Push(e.GetErrorEval()); dist = attrPtg.ChooseFuncOffset + 4; // +4 for tFuncFar(CHOOSE) } // Encoded dist for tAttrChoose includes size of jump table, but // countTokensToBeSkipped() does not (it counts whole tokens). dist -= nChoices*2+2; // subtract jump table size i+= CountTokensToBeSkipped(ptgs, i, dist); continue; } if (attrPtg.IsOptimizedIf) { ValueEval arg0 = stack.Pop(); bool evaluatedPredicate; try { evaluatedPredicate = If.EvaluateFirstArg(arg0, ec.RowIndex, ec.ColumnIndex); } catch (EvaluationException e) { stack.Push(e.GetErrorEval()); int dist = attrPtg.Data; i+= CountTokensToBeSkipped(ptgs, i, dist); attrPtg = (AttrPtg) ptgs[i]; dist = attrPtg.Data+1; i+= CountTokensToBeSkipped(ptgs, i, dist); continue; } if (evaluatedPredicate) { // nothing to skip - true param folows } else { int dist = attrPtg.Data; i+= CountTokensToBeSkipped(ptgs, i, dist); Ptg nextPtg = ptgs[i+1]; if (ptgs[i] is AttrPtg && nextPtg is FuncVarPtg) { // this is an if statement without a false param (as opposed to MissingArgPtg as the false param) i++; stack.Push(BoolEval.FALSE); } } continue; } if (attrPtg.IsSkip) { int dist = attrPtg.Data+1; i+= CountTokensToBeSkipped(ptgs, i, dist); if (stack.Peek() == MissingArgEval.instance) { stack.Pop(); stack.Push(BlankEval.instance); } continue; } } 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; } ValueEval opResult; if (ptg is OperationPtg) { OperationPtg optg = (OperationPtg)ptg; if (optg is UnionPtg) { continue; } int numops = optg.NumberOfOperands; ValueEval[] ops = new ValueEval[numops]; // storing the ops in reverse order since they are popping for (int j = numops - 1; j >= 0; j--) { ValueEval p = (ValueEval)stack.Pop(); ops[j] = p; } // logDebug("Invoke " + operation + " (nAgs=" + numops + ")"); opResult = OperationEvaluatorFactory.Evaluate(optg, ops, ec); } else { opResult = GetEvalForPtg(ptg, ec); } 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, ec.RowIndex, ec.ColumnIndex); 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; }
public ValueEval Evaluate(ValueEval[] args, OperationEvaluationContext ec) { return ErrorEval.NUM_ERROR; }
private ValueEval EvaluateNameFormula(Ptg[] ptgs, OperationEvaluationContext ec) { if (ptgs.Length > 1) { throw new Exception("Complex name formulas not supported yet"); } return GetEvalForPtg(ptgs[0], ec); }
private OperationEvaluationContext CreateContext() { HSSFWorkbook wb = new HSSFWorkbook(); wb.CreateSheet(); HSSFEvaluationWorkbook workbook = HSSFEvaluationWorkbook.Create(wb); WorkbookEvaluator workbookEvaluator = new WorkbookEvaluator(workbook, new IStabilityClassifier1(), null); OperationEvaluationContext ctx = new OperationEvaluationContext(workbookEvaluator, workbook, 0, 0, 0, null); return ctx; }
public ValueEval Evaluate(ValueEval[] args, OperationEvaluationContext ec) { throw new NotImplementedException(_functionName); }
// Fetch the workbook this refers to, and the name as defined with that private ValueEval GetExternalNameXEval(ExternalName externName, String workbookName) { try { WorkbookEvaluator refWorkbookEvaluator = _bookEvaluator.GetOtherWorkbookEvaluator(workbookName); IEvaluationName evaluationName = refWorkbookEvaluator.GetName(externName.Name, externName.Ix - 1); if (evaluationName != null && evaluationName.HasFormula) { if (evaluationName.NameDefinition.Length > 1) { throw new Exception("Complex name formulas not supported yet"); } // Need to Evaluate the reference in the context of the other book OperationEvaluationContext refWorkbookContext = new OperationEvaluationContext( refWorkbookEvaluator, refWorkbookEvaluator.Workbook, -1, -1, -1, _tracker); Ptg ptg = evaluationName.NameDefinition[0]; if (ptg is Ref3DPtg) { Ref3DPtg ref3D = (Ref3DPtg)ptg; return refWorkbookContext.GetRef3DEval(ref3D); } else if (ptg is Ref3DPxg) { Ref3DPxg ref3D = (Ref3DPxg)ptg; return refWorkbookContext.GetRef3DEval(ref3D); } else if (ptg is Area3DPtg) { Area3DPtg area3D = (Area3DPtg)ptg; return refWorkbookContext.GetArea3DEval(area3D); } else if (ptg is Area3DPxg) { Area3DPxg area3D = (Area3DPxg)ptg; return refWorkbookContext.GetArea3DEval(area3D); } } return ErrorEval.REF_INVALID; } catch (WorkbookNotFoundException) { return ErrorEval.REF_INVALID; } }
/** * @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()); }
private ValueEval GetEvalForNameRecord(IEvaluationName nameRecord, OperationEvaluationContext ec) { if (nameRecord.IsFunctionName) { return new FunctionNameEval(nameRecord.NameText); } if (nameRecord.HasFormula) { return EvaluateNameFormula(nameRecord.NameDefinition, ec); } throw new Exception("Don't now how to Evalate name '" + nameRecord.NameText + "'"); }