public NumberEval(Ptg ptg) { if (ptg is IntPtg) { this.value = ((IntPtg)ptg).Value; } else if (ptg is NumberPtg) { this.value = ((NumberPtg)ptg).Value; } }
/** * @param ptgs - if necessary, will get modified by this method * @param currentExternSheetIx - the extern sheet index of the sheet that contains the formula being adjusted * @return <c>true</c> if a change was made to the formula tokens */ public bool AdjustFormula(Ptg[] ptgs, int currentExternSheetIx) { bool refsWereChanged = false; for (int i = 0; i < ptgs.Length; i++) { Ptg newPtg = AdjustPtg(ptgs[i], currentExternSheetIx); if (newPtg != null) { refsWereChanged = true; ptgs[i] = newPtg; } } return refsWereChanged; }
public ParseNode(Ptg token, ParseNode[] children) { _token = token; _children = children; _isIf = IsIf(token); int tokenCount = 1; for (int i = 0; i < children.Length; i++) { tokenCount += children[i].TokenCount; } if (_isIf) { // there will be 2 or 3 extra tAttr Tokens according To whether the false param is present tokenCount += children.Length; } _tokenCount = tokenCount; }
/** * Used to calculate value that should be encoded at the start of the encoded Ptg token array; * @return the size of the encoded Ptg tokens not including any trailing array data. */ public static int GetEncodedSizeWithoutArrayData(Ptg[] ptgs) { int result = 0; for (int i = 0; i < ptgs.Length; i++) { Ptg ptg = ptgs[i]; if (ptg is ArrayPtg) { result += ArrayPtg.PLAIN_TOKEN_SIZE; } else { result += ptg.Size; } } return(result); }
/** * Reads <tt>size</tt> bytes of the input stream, to Create an array of <tt>Ptg</tt>s. * Extra data (beyond <tt>size</tt>) may be Read if and <tt>ArrayPtg</tt>s are present. */ public static Ptg[] ReadTokens(int size, LittleEndianInput in1) { ArrayList temp = new ArrayList(4 + size / 2); int pos = 0; ArrayList arrayPtgs = null; while (pos < size) { Ptg ptg = Ptg.CreatePtg(in1); if (ptg is ArrayPtg) { if (arrayPtgs == null) { arrayPtgs = new ArrayList(5); } arrayPtgs.Add(ptg); pos += ArrayPtg.PLAIN_TOKEN_SIZE; } else { pos += ptg.Size; } temp.Add(ptg); } if (pos != size) { throw new Exception("Ptg array size mismatch"); } if (arrayPtgs != null) { for (int i = 0; i < arrayPtgs.Count; i++) { ArrayPtg p = (ArrayPtg)arrayPtgs[i]; p.ReadTokenValues(in1); } } return(ToPtgArray(temp)); }
private static Ptg CreateDeletedRef(Ptg ptg) { if (ptg is RefPtg) { return(new RefErrorPtg()); } if (ptg is Ref3DPtg) { Ref3DPtg rptg = (Ref3DPtg)ptg; return(new DeletedRef3DPtg(rptg.ExternSheetIndex)); } if (ptg is AreaPtg) { return(new AreaErrPtg()); } if (ptg is Area3DPtg) { Area3DPtg area3DPtg = (Area3DPtg)ptg; return(new DeletedArea3DPtg(area3DPtg.ExternSheetIndex)); } throw new ArgumentException("Unexpected ref ptg class (" + ptg.GetType().Name + ")"); }
private static bool IsDeletedCellRef(Ptg ptg) { if (ptg == ErrPtg.REF_INVALID) { return(true); } if (ptg is DeletedArea3DPtg) { return(true); } if (ptg is DeletedRef3DPtg) { return(true); } if (ptg is AreaErrPtg) { return(true); } if (ptg is RefErrorPtg) { return(true); } return(false); }
/** * Static method To Convert an array of Ptgs in RPN order * To a human Readable string format in infix mode. Works * on the current workbook for named and 3D references. * @param ptgs array of Ptg, can be null or empty * @return a human Readable String */ public String ToFormulaString(Ptg[] ptgs) { return ToFormulaString(book, ptgs); }
/** * Generates the variable Function ptg for the formula. * * For IF Formulas, Additional PTGs are Added To the Tokens * @param name a {@link NamePtg} or {@link NameXPtg} or <c>null</c> * @param numArgs * @return Ptg a null is returned if we're in an IF formula, it needs extreme manipulation and is handled in this Function */ private ParseNode GetFunction(String name, Ptg namePtg, ParseNode[] args) { FunctionMetadata fm = FunctionMetadataRegistry.GetFunctionByName(name.ToUpper()); int numArgs = args.Length; if (fm == null) { if (namePtg == null) { throw new InvalidOperationException("NamePtg must be supplied for external Functions"); } // must be external Function ParseNode[] allArgs = new ParseNode[numArgs + 1]; allArgs[0] = new ParseNode(namePtg); System.Array.Copy(args, 0, allArgs, 1, numArgs); return new ParseNode(new FuncVarPtg(name, (byte)(numArgs + 1)), allArgs); } if (namePtg != null) { throw new InvalidOperationException("NamePtg no applicable To internal Functions"); } bool IsVarArgs = !fm.HasFixedArgsLength; int funcIx = fm.Index; ValidateNumArgs(args.Length, fm); AbstractFunctionPtg retval; if (IsVarArgs) { retval = new FuncVarPtg(name, (byte)numArgs); } else { retval = new FuncPtg(funcIx); } return new ParseNode(retval, args); }
/** * * "A1", "B3" -> "A1:B3" * "sheet1!A1", "B3" -> "sheet1!A1:B3" * * @return <c>null</c> if the range expression cannot / shouldn't be reduced. */ private static Ptg ReduceRangeExpression(Ptg ptgA, Ptg ptgB) { if (!(ptgB is RefPtg)) { // only when second ref is simple 2-D ref can the range // expression be converted To an area ref return null; } RefPtg refB = (RefPtg)ptgB; if (ptgA is RefPtg) { RefPtg refA = (RefPtg)ptgA; return new AreaPtg(refA.Row, refB.Row, refA.Column, refB.Column, refA.IsRowRelative, refB.IsRowRelative, refA.IsColRelative, refB.IsColRelative); } if (ptgA is Ref3DPtg) { Ref3DPtg refA = (Ref3DPtg)ptgA; return new Area3DPtg(refA.Row, refB.Row, refA.Column, refB.Column, refA.IsRowRelative, refB.IsRowRelative, refA.IsColRelative, refB.IsColRelative, refA.ExternSheetIndex); } // Note - other operand types (like AreaPtg) which probably can't evaluate // do not cause validation errors at Parse time return null; }
private Ptg AdjustPtg(Ptg ptg, int currentExternSheetIx) { return AdjustPtgDueToRowMove(ptg, currentExternSheetIx); }
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); }
/** * Calculates the number of tokens that the evaluator should skip upon reaching a tAttrSkip. * * @return the number of tokens (starting from <tt>startIndex+1</tt>) that need to be skipped * to achieve the specified <tt>distInBytes</tt> skip distance. */ private static int CountTokensToBeSkipped(Ptg[] ptgs, int startIndex, int distInBytes) { int remBytes = distInBytes; int index = startIndex; while (remBytes != 0) { index++; remBytes -= ptgs[index].Size; if (remBytes < 0) { throw new Exception("Bad skip distance (wrong token size calculation)."); } if (index >= ptgs.Length) { throw new Exception("Skip distance too far (ran out of formula tokens)."); } } return index - startIndex; }
/** * Static method To convert an array of {@link Ptg}s in RPN order * To a human readable string format in infix mode. * @param book used for defined names and 3D references * @param ptgs must not be <c>null</c> * @return a human readable String */ public static String ToFormulaString(FormulaRenderingWorkbook book, Ptg[] ptgs) { if (ptgs == null || ptgs.Length == 0) { throw new ArgumentException("ptgs must not be null"); } Stack stack = new Stack(); for (int i = 0; i < ptgs.Length; i++) { Ptg ptg = ptgs[i]; // TODO - what about MemNoMemPtg? if (ptg is MemAreaPtg || ptg is MemFuncPtg || ptg is MemErrPtg) { // marks the start of a list of area expressions which will be naturally combined // by their trailing operators (e.g. UnionPtg) // TODO - Put comment and throw exception in ToFormulaString() of these classes continue; } if (ptg is ParenthesisPtg) { String contents = (String)stack.Pop(); stack.Push("(" + contents + ")"); continue; } if (ptg is AttrPtg) { AttrPtg attrPtg = ((AttrPtg)ptg); if (attrPtg.IsOptimizedIf || attrPtg.IsOptimizedChoose || attrPtg.IsSkip) { continue; } if (attrPtg.IsSpace) { // POI currently doesn't render spaces in formulas continue; // but if it ever did, care must be taken: // tAttrSpace comes *before* the operand it applies To, which may be consistent // with how the formula text appears but is against the RPN ordering assumed here } if (attrPtg.IsSemiVolatile) { // similar To tAttrSpace - RPN is violated continue; } if (attrPtg.IsSum) { String[] operands = GetOperands(stack, attrPtg.NumberOfOperands); stack.Push(attrPtg.ToFormulaString(operands)); continue; } throw new Exception("Unexpected tAttr: " + attrPtg.ToString()); } if (ptg is WorkbookDependentFormula) { WorkbookDependentFormula optg = (WorkbookDependentFormula)ptg; stack.Push(optg.ToFormulaString(book)); continue; } if (!(ptg is OperationPtg)) { stack.Push(ptg.ToFormulaString()); continue; } OperationPtg o = (OperationPtg)ptg; String[] operands1 = GetOperands(stack, o.NumberOfOperands); stack.Push(o.ToFormulaString(operands1)); } if (stack.Count == 0) { // inspection of the code above reveals that every stack.pop() is followed by a // stack.push(). So this is either an internal error or impossible. throw new InvalidOperationException("Stack underflow"); } String result = (String)stack.Pop(); if (stack.Count != 0) { // Might be caused by some Tokens like AttrPtg and Mem*Ptg, which really shouldn't // Put anything on the stack throw new InvalidOperationException("too much stuff left on the stack"); } return result; }
public void Add(Ptg token) { if (token == null) { throw new ArgumentException("token must not be null"); } _ptgs[_offset] = token; _offset++; }
public void SetPlaceholder(int index, Ptg token) { if (_ptgs[index] != null) { throw new InvalidOperationException("Invalid placeholder index (" + index + ")"); } _ptgs[index] = token; }
private static bool IsIf(Ptg token) { if (token is FuncVarPtg) { FuncVarPtg func = (FuncVarPtg)token; if (FunctionMetadataRegistry.FUNCTION_NAME_IF.Equals(func.Name)) { return true; } } return false; }
/** * Creates a non shared formula from the shared formula counterpart<br/> * * Perhaps this functionality could be implemented in terms of the raw * byte array inside {@link Formula}. */ public static Ptg[] ConvertSharedFormulas(Ptg[] ptgs, int formulaRow, int formulaColumn) { Ptg[] newPtgStack = new Ptg[ptgs.Length]; for (int k = 0; k < ptgs.Length; k++) { Ptg ptg = ptgs[k]; byte originalOperandClass = unchecked((byte)-1); if (!ptg.IsBaseToken) { originalOperandClass = ptg.PtgClass; } if (ptg is RefPtgBase) { RefPtgBase refNPtg = (RefPtgBase)ptg; ptg = new RefPtg(FixupRelativeRow(formulaRow, refNPtg.Row, refNPtg.IsRowRelative), FixupRelativeColumn(formulaColumn, refNPtg.Column, refNPtg.IsColRelative), refNPtg.IsRowRelative, refNPtg.IsColRelative); ptg.PtgClass = originalOperandClass; } else if (ptg is AreaPtgBase) { AreaPtgBase areaNPtg = (AreaPtgBase)ptg; ptg = new AreaPtg(FixupRelativeRow(formulaRow, areaNPtg.FirstRow, areaNPtg.IsFirstRowRelative), FixupRelativeRow(formulaRow, areaNPtg.LastRow, areaNPtg.IsLastRowRelative), FixupRelativeColumn(formulaColumn, areaNPtg.FirstColumn, areaNPtg.IsFirstColRelative), FixupRelativeColumn(formulaColumn, areaNPtg.LastColumn, areaNPtg.IsLastColRelative), areaNPtg.IsFirstRowRelative, areaNPtg.IsLastRowRelative, areaNPtg.IsFirstColRelative, areaNPtg.IsLastColRelative); ptg.PtgClass = originalOperandClass; } else if (ptg is OperandPtg) { // Any subclass of OperandPtg is mutable, so it's safest to not share these instances. ptg = ((OperandPtg)ptg).Copy(); } else { // all other Ptgs are immutable and can be shared } newPtgStack[k] = ptg; } return newPtgStack; }
private static Ptg CreateDeletedRef(Ptg ptg) { if (ptg is RefPtg) { return new RefErrorPtg(); } if (ptg is Ref3DPtg) { Ref3DPtg rptg = (Ref3DPtg)ptg; return new DeletedRef3DPtg(rptg.ExternSheetIndex); } if (ptg is AreaPtg) { return new AreaErrPtg(); } if (ptg is Area3DPtg) { Area3DPtg area3DPtg = (Area3DPtg)ptg; return new DeletedArea3DPtg(area3DPtg.ExternSheetIndex); } throw new ArgumentException("Unexpected ref ptg class (" + ptg.GetType().Name + ")"); }
/** * Convenience method which takes in a list then passes it To the * other ToFormulaString signature. * @param book workbook for 3D and named references * @param lptgs list of Ptg, can be null or empty * @return a human Readable String */ public static String ToFormulaString(HSSFWorkbook book, Stack lptgs) { String retval = null; if (lptgs == null || lptgs.Count == 0) return "#NAME"; Ptg[] ptgs = new Ptg[lptgs.Count]; ptgs = (Ptg[])lptgs.ToArray(); retval = ToFormulaString(book, ptgs); return retval; }
private static bool IsSimpleValueFunction(Ptg token) { if (token is AbstractFunctionPtg) { AbstractFunctionPtg aptg = (AbstractFunctionPtg)token; if (aptg.DefaultOperandClass != Ptg.CLASS_VALUE) { return false; } int numberOfOperands = aptg.NumberOfOperands; for (int i = numberOfOperands - 1; i >= 0; i--) { if (aptg.GetParameterClass(i) != Ptg.CLASS_VALUE) { return false; } } return true; } return false; }
public FormulaPair(Ptg[] formula1, Ptg[] formula2) { _formula1 = formula1; _formula2 = formula2; }
private static Ptg[] SafeClone(Ptg[] ptgs) { if (ptgs == null) { return null; } return (Ptg[])ptgs.Clone(); }
// 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; }
/** * Static method to convert an array of {@link Ptg}s in RPN order * to a human readable string format in infix mode. * @param book used for defined names and 3D references * @param ptgs must not be <c>null</c> * @return a human readable String */ public static String ToFormulaString(HSSFWorkbook book, Ptg[] ptgs) { return FormulaRenderer.ToFormulaString(HSSFEvaluationWorkbook.Create(book), 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; 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 Ptg AdjustPtg(Ptg ptg, int currentExternSheetIx) { return(AdjustPtgDueToRowMove(ptg, currentExternSheetIx)); }
public ParseNode(Ptg token) : this(token, EMPTY_ARRAY) { }
/** * @return <c>true</c> if this Ptg needed to be changed */ private Ptg AdjustPtgDueToRowMove(Ptg ptg, int currentExternSheetIx) { if (ptg is RefPtg) { if (currentExternSheetIx != _externSheetIndex) { // local refs on other sheets are unaffected return null; } RefPtg rptg = (RefPtg)ptg; return RowMoveRefPtg(rptg); } if (ptg is Ref3DPtg) { Ref3DPtg rptg = (Ref3DPtg)ptg; if (_externSheetIndex != rptg.ExternSheetIndex) { // only move 3D refs that refer to the sheet with cells being moved // (currentExternSheetIx is irrelevant) return null; } return RowMoveRefPtg(rptg); } if (ptg is Area2DPtgBase) { if (currentExternSheetIx != _externSheetIndex) { // local refs on other sheets are unaffected return ptg; } return RowMoveAreaPtg((Area2DPtgBase)ptg); } if (ptg is Area3DPtg) { Area3DPtg aptg = (Area3DPtg)ptg; if (_externSheetIndex != aptg.ExternSheetIndex) { // only move 3D refs that refer to the sheet with cells being moved // (currentExternSheetIx is irrelevant) return null; } return RowMoveAreaPtg(aptg); } return null; }
private CFRuleRecord(byte conditionType, ComparisonOperator comparisonOperation, Ptg[] formula1, Ptg[] formula2) :this(conditionType, comparisonOperation) { field_1_condition_type = CONDITION_TYPE_CELL_VALUE_IS; field_2_comparison_operator = (byte)comparisonOperation; field_17_formula1 = formula1; field_18_formula2 = formula2; }
public ParseNode(Ptg token, ParseNode child0, ParseNode child1) : this(token, new ParseNode[] { child0, child1, }) { }
/** * @param ptgs may be <c>null</c> * @return encoded size of the formula */ private static int GetFormulaSize(Ptg[] ptgs) { if (ptgs == null) { return 0; } return Ptg.GetEncodedSize(ptgs); }
public void SetParsedExpression(Ptg[] ptgs) { field_8_parsed_expr = NPOI.SS.Formula.Formula.Create(ptgs); }
/** * Also checks for a related shared formula and unlinks it if found */ public void SetParsedExpression(Ptg[] ptgs) { NotifyFormulaChanging(); _formulaRecord.ParsedExpression=(ptgs); }
private static Double ConvertArrayNumber(Ptg ptg) { if (ptg is IntPtg) { return ((IntPtg)ptg).Value; } if (ptg is NumberPtg) { return ((NumberPtg)ptg).Value; } throw new Exception("Unexpected ptg (" + ptg.GetType().Name + ")"); }