/** * 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)); }
/** * Dereferences a single value from any AreaEval or RefEval evaluation * result. If the supplied evaluationResult is just a plain value, it is * returned as-is. * * @return a {@link NumberEval}, {@link StringEval}, {@link BoolEval}, or * {@link ErrorEval}. Never <code>null</code>. {@link BlankEval} is * converted to {@link NumberEval#ZERO} */ public static ValueEval DereferenceResult(ValueEval evaluationResult, OperationEvaluationContext ec) { ValueEval value; if (ec == null) { throw new ArgumentNullException("OperationEvaluationContext ec is null"); } if (ec.GetWorkbook() == null) { throw new ArgumentNullException("OperationEvaluationContext ec.getWorkbook() is null"); } IEvaluationSheet evalSheet = ec.GetWorkbook().GetSheet(ec.SheetIndex); IEvaluationCell evalCell = evalSheet.GetCell(ec.RowIndex, ec.ColumnIndex); if (evalCell.IsPartOfArrayFormulaGroup && evaluationResult is AreaEval) { value = OperandResolver.GetElementFromArray((AreaEval)evaluationResult, evalCell); } else { value = DereferenceResult(evaluationResult, ec.RowIndex, ec.ColumnIndex); } return(value); }
public static ValueEval EvaluateArrayFunction(ArrayFunction func, ValueEval[] args, OperationEvaluationContext ec) { IEvaluationSheet evalSheet = ec.GetWorkbook().GetSheet(ec.SheetIndex); IEvaluationCell evalCell = evalSheet.GetCell(ec.RowIndex, ec.ColumnIndex); if (evalCell != null) { if (evalCell.IsPartOfArrayFormulaGroup) { // array arguments must be evaluated relative to the function defining range Util.CellRangeAddress ca = evalCell.ArrayFormulaRange; return(func.EvaluateArray(args, ca.FirstRow, ca.FirstColumn)); } else if (ec.IsArraymode) { return(func.EvaluateArray(args, ec.RowIndex, ec.ColumnIndex)); } } return(null); }
/** * 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); }
// 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().SheetNameRange + "'/" + new CellReference(ec.RowIndex, ec.ColumnIndex).FormatAsString() + "): " + Arrays.ToString(ptgs).Replace("\\Qorg.apache.poi.ss.formula.ptg.\\E", "")); dbgEvaluationOutputIndent++; } IEvaluationSheet evalSheet = ec.GetWorkbook().GetSheet(ec.SheetIndex); IEvaluationCell evaluationCell = evalSheet.GetCell(ec.RowIndex, ec.ColumnIndex); 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() + ", stack:" + stack); } 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) { if (!evaluationCell.IsPartOfArrayFormulaGroup) { ValueEval arg0 = stack.Pop(); bool evaluatedPredicate; try { evaluatedPredicate = IfFunc.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 && // in order to verify that there is no third param, we need to check // if we really have the IF next or some other FuncVarPtg as third param, e.g. ROW()/COLUMN()! ((FuncVarPtg)nextPtg).FunctionIndex == FunctionMetadataRegistry.FUNCTION_INDEX_IF) { // this is an if statement without a false param (as opposed to MissingArgPtg as the false param) i++; stack.Push(arg0); stack.Push(BoolEval.FALSE); } } } continue; } if (attrPtg.IsSkip && !evaluationCell.IsPartOfArrayFormulaGroup) { 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; } if (ptg is UnionPtg) { ValueEval v2 = stack.Pop(); ValueEval v1 = stack.Pop(); stack.Push(new RefListEval(v1, v2)); 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; if (ec.IsSingleValue) { result = DereferenceResult(value, ec); } else { result = value; } 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); }