/// <summary> /// FmlaWithoutArrayLen might be less than the total array len /// </summary> internal static byte[] GetTokenData(TNameRecordList Names, TParsedTokenList Tokens, TFormulaType FmlaType, out int FmlaLenWithoutArray) { // Remember to ungrow maxrow and maxcol from 2007 too biff8 // Tokens that grow are ptgref, area, 3dref and 3darea. All of them (and nothing else) should ungrow. using (MemoryStream Data = new MemoryStream()) { using (MemoryStream ArrayData = new MemoryStream()) { int[] TokenOffset = new int[Tokens.Count + 1]; TTokenOffset StreamPos = new TTokenOffset(); Int32List FuturePos = new Int32List(); Tokens.ResetPositionToStart(); while (!Tokens.Eof()) { TBaseParsedToken Token = Tokens.ForwardPop(); TokenOffset[Tokens.SavePosition()] = (int)Data.Position; ptg BaseToken = Token.GetBaseId; Add(Data, ArrayData, Token, BaseToken, Tokens, StreamPos, FmlaType, FuturePos); } //while TokenOffset[Tokens.Count] = (int)Data.Position; FixFutureFunctions(Names, FuturePos, Tokens, Data, TokenOffset, ref StreamPos); FixGotoAndMemTokens(Tokens, Data, TokenOffset, StreamPos); ArrayData.Position = 0; Data.Position = Data.Length; //FixGoto will change this. FmlaLenWithoutArray = (int)Data.Length; ArrayData.WriteTo(Data); return(Data.ToArray()); } } }
protected static void AddParsedRefN(TParsedTokenListBuilder TokenBuilder, ptg aId, int Rw1, int grBit1) { bool RowAbs; bool ColAbs; int Row; int Col; GetRelativeRowAndCol(Rw1, grBit1, out RowAbs, out ColAbs, out Row, out Col); Push(TokenBuilder, new TRefNToken(aId, Row, Col, RowAbs, ColAbs, true)); }
internal static string AsString(TParsedTokenList Tokens, int CellRow, int CellCol, ICellList CellList, TWorkbookGlobals Globals, int MaxStringConstantLen, bool WritingXlsx, bool SkipEqual) { string StartFormula = fts(TFormulaToken.fmStartFormula); //Formulas do not always begin with "=". Array formulas begin with "{", and they override this var to empty. TFormulaStack ParsedStack = new TFormulaStack(); bool R1C1 = false; if (Globals != null && !WritingXlsx) { R1C1 = Globals.Workbook.FormulaReferenceStyle == TReferenceStyle.R1C1; } Tokens.ResetPositionToStart(); while (!Tokens.Eof()) { TBaseParsedToken Token = Tokens.ForwardPop(); ptg BaseToken = Token.GetBaseId; Evaluate(Token, R1C1, CellRow, CellCol, BaseToken, Tokens, CellList, Globals, ParsedStack, ref StartFormula, MaxStringConstantLen, WritingXlsx); } //while if (WritingXlsx || SkipEqual) { StartFormula = String.Empty; } if (ParsedStack.Count == 0) { return(String.Empty); //StartFormula + TFormulaMessages.ErrString(TFlxFormulaErrorValue.ErrRef); This is needed for deleted named ranges. } return(StartFormula + ParsedStack.Pop()); }
private bool DoRPN(TParsedTokenListBuilder TokenBuilder, TNameRecordList Names, byte[] RPN, int atPos, int afPos, ref bool HasSubtotal, ref bool HasAggregate) { int tPos = atPos; int fPos = afPos; int ArrayPos = fPos; TTokenOffset TokenOffset = new TTokenOffset(); while (tPos < fPos) { TokenOffset.Add(tPos, TokenBuilder.Count); byte RealToken = RPN[tPos]; ptg BaseToken = TBaseParsedToken.CalcBaseToken((ptg)RealToken); TUnsupportedFormulaErrorType ErrType = TUnsupportedFormulaErrorType.FormulaTooComplex; string ErrName = null; if (!Evaluate(TokenBuilder, TokenOffset, Names, BaseToken, (ptg)RealToken, RPN, ref tPos, ref ArrayPos, ref ErrType, ref ErrName, ref HasSubtotal, ref HasAggregate)) { TokenBuilder.Clear(); return(false); } tPos++; } //while TokenOffset.Add(tPos, TokenBuilder.Count); //eof FixGotosAndMemTokens(TokenBuilder, TokenOffset); return(true); }
private static bool IsError(ptg BaseToken, TFormulaType FmlaType) { switch (FmlaType) { case TFormulaType.Normal: return(false); case TFormulaType.Name: return(BaseToken == ptg.Tbl || BaseToken == ptg.Exp || BaseToken == ptg.Ref || BaseToken == ptg.RefN || BaseToken == ptg.RefErr || BaseToken == ptg.Area || BaseToken == ptg.AreaN || BaseToken == ptg.AreaErr); case TFormulaType.DataValidation: return(BaseToken == ptg.Tbl || BaseToken == ptg.Exp || BaseToken == ptg.Isect || BaseToken == ptg.Union || BaseToken == ptg.Array || BaseToken == ptg.Ref3d || BaseToken == ptg.Area3d || BaseToken == ptg.Ref3dErr || BaseToken == ptg.Area3dErr || BaseToken == ptg.NameX || BaseToken == ptg.MemArea || BaseToken == ptg.MemNoMem ); case TFormulaType.CondFmt: return(BaseToken == ptg.Tbl || BaseToken == ptg.Exp || BaseToken == ptg.Isect || BaseToken == ptg.Union || BaseToken == ptg.Array || BaseToken == ptg.Ref3d || BaseToken == ptg.Ref3dErr || BaseToken == ptg.NameX || BaseToken == ptg.MemArea || BaseToken == ptg.MemNoMem ); case TFormulaType.Chart: return(BaseToken != ptg.Paren && BaseToken != ptg.Union && BaseToken != ptg.Ref3d && BaseToken != ptg.Ref3dErr && BaseToken != ptg.Area3d && BaseToken != ptg.Area3dErr && BaseToken != ptg.NameX && BaseToken != ptg.MemFunc ); } return(false); }
internal static void Add(int Index, ptg PtgId, int ArgCount, TBaseFunctionToken ResultValue) { EnsureFList(); if (FList.Count > 1024) { FList.Clear(); //Shouldn't happen, but just in case avoid this growing ad infinitum. } FList.Add(new TFunctionKey(Index, PtgId, ArgCount), ResultValue); }
internal static bool TryGetValue(int Index, ptg PtgId, int ArgCount, out TBaseFunctionToken ResultValue) { EnsureFList(); #if (FRAMEWORK20) return(FList.TryGetValue(new TFunctionKey(Index, PtgId, ArgCount), out ResultValue)); #else ResultValue = FList[GetHash(Index, PtgId, ArgCount)] as TBaseFunctionToken; return(ResultValue != null); #endif }
protected static void AddParsedAreaN(TParsedTokenListBuilder TokenBuilder, ptg aId, int Rw1, int Rw2, int grBit1, int grBit2) { bool RowAbs1; bool ColAbs1; int Row1; int Col1; GetRelativeRowAndCol(Rw1, grBit1, out RowAbs1, out ColAbs1, out Row1, out Col1); bool RowAbs2; bool ColAbs2; int Row2; int Col2; GetRelativeRowAndCol(Rw2, grBit2, out RowAbs2, out ColAbs2, out Row2, out Col2); Push(TokenBuilder, new TAreaNToken(aId, Row1, Col1, RowAbs1, ColAbs1, Row2, Col2, RowAbs2, ColAbs2, true)); }
protected override bool LastIsReference() { if (LastRefOp < 0) { return(false); } ptg aptg = GetLastRefOp(); TFmReturnType PtgMode = GetPtgMode(aptg); return(PtgMode == TFmReturnType.Ref); }
private static ptg GetRealPtg(ptg PtgBase, TFmReturnType ReturnType) { switch (ReturnType) { case TFmReturnType.Array: return((ptg)(PtgBase + 0x40)); case TFmReturnType.Ref: return((ptg)PtgBase); default: return((ptg)(PtgBase + 0x20)); } //case }
protected static void AddParsedSep(TParsedTokenListBuilder TokenBuilder, ptg b) { switch (b) { case ptg.Isect: Push(TokenBuilder, TISectToken.Instance); break; case ptg.Union: Push(TokenBuilder, TUnionToken.Instance); break; case ptg.Range: Push(TokenBuilder, TRangeToken.Instance); break; default: Push(TokenBuilder, new TUnsupportedToken(2, b)); break; } }
private void AddParsed3dRef(TParsedTokenListBuilder TokenBuilder, ptg RealToken, int ExternSheet, int Rw1, int grBit1) { if (Relative3dRanges) { bool RowAbs1; bool ColAbs1; int Row1; int Col1; GetRelativeRowAndCol(Rw1, grBit1, out RowAbs1, out ColAbs1, out Row1, out Col1); Push(TokenBuilder, new TRef3dNToken(RealToken, ExternSheet, Row1, Col1, RowAbs1, ColAbs1, true)); } else { Push(TokenBuilder, new TRef3dToken(RealToken, ExternSheet, Biff8Utils.ExpandBiff8Row(Rw1), Biff8Utils.ExpandBiff8Col(grBit1 & ColMask), (grBit1 & 0x8000) == 0, (grBit1 & 0x4000) == 0)); } }
private static TArrayDataToken GetArrayDataToken(ptg aId, byte[] RPN, ref int ArrayPos) { int Columns = RPN[ArrayPos] + 1; int Rows = BitOps.GetWord(RPN, ArrayPos + 1) + 1; ArrayPos += 3; object[,] Result = new object[Rows, Columns]; for (int r = 0; r < Rows; r++) { for (int c = 0; c < Columns; c++) { Result[r, c] = GetArrayObject(RPN, ref ArrayPos); } } return(new TArrayDataToken(aId, Result)); }
internal static bool HasExternRefs(TParsedTokenList Data) { Data.ResetPositionToLast(); while (!Data.Bof()) { TBaseParsedToken r = Data.LightPop(); ptg id = r.GetBaseId; // This check is a little simplistic because an Area3d or Ref3d might in fact refer to the same sheet. But then, the externsheet is not copied so // the reference will be invalid anyway. The "right" thing to do would be to convert external refs to the same sheet to external refs on the new sheet. if (id == ptg.Area3d || id == ptg.Ref3d || id == ptg.NameX) { return(true); } } return(false); }
protected override void ConvertLastRefValueType(TFmReturnType RefMode, TParseState ParseState, bool IgnoreArray) { if (LastRefOp < 0) //we should always call this when an operand has been added. { char c = ' '; if (ParsePos - 1 >= 0 && ParsePos - 1 < FormulaText.Length) { c = FormulaText[ParsePos - 1]; } FlxMessages.ThrowException(FlxErr.ErrUnexpectedChar, c, ParsePos, FormulaText); } ptg aptg = GetLastRefOp(); TFmReturnType PtgMode = GetPtgMode(aptg); switch (RefMode) { case TFmReturnType.Ref: if (ParseState.ForcedArrayClass && ParseState.Level > 0 && PtgMode == TFmReturnType.Value) { SetLastRefOp(aptg, TFmReturnType.Array); } break; case TFmReturnType.Value: if (ParseState.ForcedArrayClass && ParseState.Level > 0) { SetLastRefOp(aptg, TFmReturnType.Array); } else if (!IgnoreArray || PtgMode != TFmReturnType.Array) { SetLastRefOp(aptg, TFmReturnType.Value); } break; case TFmReturnType.Array: SetLastRefOp(aptg, TFmReturnType.Array); break; } }
private static TFmReturnType GetPtgMode(ptg aptg) { TFmReturnType PtgMode = TFmReturnType.Value; if (aptg == ptg.Range || aptg == ptg.Isect || aptg == ptg.Union) //binary operators with ref results. { PtgMode = TFmReturnType.Ref; } switch (((byte)aptg) & 0x60) { case 0x20: PtgMode = TFmReturnType.Ref; break; case 0x60: PtgMode = TFmReturnType.Array; break; } return(PtgMode); }
internal static bool HasExternLinks(TParsedTokenList Data, TReferences References) { Data.ResetPositionToLast(); while (!Data.Bof()) { TBaseParsedToken r = Data.LightPop(); ptg id = r.GetBaseId; if (id == ptg.Area3d || id == ptg.Ref3d || id == ptg.NameX) { if (References != null) { int ExternSheet = r.ExternSheet; if (!References.IsLocalSheet(ExternSheet)) { return(true); } } } } return(false); }
private void SetLastRefOp(ptg aptg, TFmReturnType RefMode) { byte newptg = (byte)aptg; if ((((byte)aptg) & 0x60) != 0) { switch (RefMode) { case TFmReturnType.Ref: newptg = (byte)(newptg & 0x9F | 0x20); break; case TFmReturnType.Value: newptg = (byte)(newptg & 0x9F | 0x40); break; case TFmReturnType.Array: newptg = (byte)(newptg | 0x60); break; } } FParsedDataBuilder[LastRefOp] = FParsedDataBuilder[LastRefOp].SetId((ptg)newptg); }
internal void Go(TParsedTokenList Data, bool RefIsInInsertingSheet) { Data.ResetPositionToStart(); while (!Data.Eof()) { TBaseParsedToken r = Data.ForwardPop(); ptg id = r.GetBaseId; switch (id) { case ptg.Exp: DoArrayFmla((TExp_Token)r); break; case ptg.Tbl: TTableToken tbl = r as TTableToken; if (tbl != null) //might be also TTableObjToken { DoTable(tbl); } break; case ptg.Name: DoName((TNameToken)r); break; case ptg.RefErr: case ptg.Ref: case ptg.RefN: DoRef((TRefToken)r, RefIsInInsertingSheet); break; case ptg.AreaErr: case ptg.Area: case ptg.AreaN: DoArea((TAreaToken)r, RefIsInInsertingSheet); break; case ptg.MemArea: DoMemArea(Data, (TMemAreaToken)r, RefIsInInsertingSheet); break; case ptg.NameX: { //We'll do Do3d only for local names. //bool ThisRefIsInInsertingSheet; //Do3D(r, out ThisRefIsInInsertingSheet); DoNameX((TNameXToken)r); } break; case ptg.Ref3d: case ptg.Ref3dErr: { bool ThisRefIsInInsertingSheet; Do3D(r, out ThisRefIsInInsertingSheet); DoRef((TRef3dToken)r, ThisRefIsInInsertingSheet); break; } case ptg.Area3dErr: case ptg.Area3d: { bool ThisRefIsInInsertingSheet; Do3D(r, out ThisRefIsInInsertingSheet); DoArea((TArea3dToken)r, ThisRefIsInInsertingSheet); } break; } } }
public TFunctionKey(int aIndex, ptg aPtgId, int aArgCount) { Index = aIndex; PtgId = aPtgId; ArgCount = aArgCount; }
private bool Evaluate(TParsedTokenListBuilder TokenBuilder, TTokenOffset TokenOffset, TNameRecordList Names, ptg BaseToken, ptg RealToken, byte[] RPN, ref int tPos, ref int ArrayPos, ref TUnsupportedFormulaErrorType ErrType, ref string ErrName, ref bool HasSubtotal, ref bool HasAggregate) { switch (BaseToken) { case ptg.Exp: AddParsedExp(TokenBuilder, BitOps.GetWord(RPN, tPos + 1), BitOps.GetWord(RPN, tPos + 3)); tPos += 4; break; case ptg.Tbl: AddParsedTable(TokenBuilder, BitOps.GetWord(RPN, tPos + 1), BitOps.GetWord(RPN, tPos + 3)); tPos += 4; break; case ptg.Add: case ptg.Sub: case ptg.Mul: case ptg.Div: case ptg.Power: case ptg.Concat: case ptg.LT: case ptg.LE: case ptg.EQ: case ptg.GE: case ptg.GT: case ptg.NE: case ptg.Uminus: case ptg.Percent: case ptg.Uplus: AddParsedOp(TokenBuilder, (TOperator)BaseToken); break; case ptg.MissArg: AddMissingArg(TokenBuilder); break; case ptg.Isect: AddParsedSep(TokenBuilder, BaseToken); break; case ptg.Union: AddParsedSep(TokenBuilder, BaseToken); break; case ptg.Range: AddParsedSep(TokenBuilder, BaseToken); break; case ptg.Paren: Push(TokenBuilder, TParenToken.Instance); break; case ptg.Str: long sl = 0; string Result = null; StrOps.GetSimpleString(false, RPN, tPos + 1, false, 0, ref Result, ref sl); AddParsed(TokenBuilder, Result); tPos += (int)sl; break; case ptg.Attr: int AttrLen = 0; if (!ProcessAttr(TokenBuilder, RPN, tPos + 1, ref AttrLen)) { return(false); } tPos += AttrLen; break; case ptg.Sheet: return(false); case ptg.EndSheet: return(false); case ptg.Err: AddParsed(TokenBuilder, (TFlxFormulaErrorValue)RPN[tPos + 1]); tPos++; break; case ptg.Bool: AddParsed(TokenBuilder, RPN[tPos + 1] == 1); tPos++; break; case ptg.Int: AddParsed16(TokenBuilder, BitOps.GetWord(RPN, tPos + 1)); tPos += 2; break; case ptg.Num: AddParsed(TokenBuilder, BitConverter.ToDouble(RPN, tPos + 1)); tPos += 8; break; case ptg.Array: Push(TokenBuilder, GetArrayDataToken(RealToken, RPN, ref ArrayPos)); tPos += 7; break; case ptg.Func: bool Result1; int index = BitOps.GetWord(RPN, tPos + 1); TCellFunctionData fd = TXlsFunction.GetData(index, out Result1); if (!Result1) { return(false); } Debug.Assert(fd.MinArgCount == fd.MaxArgCount, "On a fixed formula the min count of arguments should be the same as the max"); AddParsedFormula(TokenBuilder, RealToken, fd, (byte)fd.MinArgCount); tPos += 2; break; case ptg.FuncVar: bool Result2; int index2 = BitOps.GetWord(RPN, tPos + 2); TCellFunctionData fd2 = TXlsFunction.GetData(index2, out Result2); if (!Result2) { return(false); } if (fd2.Index == 344) // SubTotal { HasSubtotal = true; } int np = RPN[tPos + 1] & 0x7F; if (fd2.Index == 255) { CheckFutureFunction(TokenBuilder, ref np, Names, ref fd2, TokenOffset, ref HasAggregate); } AddParsedFormula(TokenBuilder, RealToken, fd2, (byte)np); tPos += 3; break; case ptg.Name: Push(TokenBuilder, new TNameToken(RealToken, BitOps.GetWord(RPN, tPos + 1))); tPos += 4; break; case ptg.NameX: Push(TokenBuilder, new TNameXToken(RealToken, BitOps.GetWord(RPN, tPos + 1), BitOps.GetWord(RPN, tPos + 3))); tPos += 6; break; case ptg.RefErr: case ptg.Ref: AddParsedRef(TokenBuilder, RealToken, BitOps.GetWord(RPN, tPos + 1), BitOps.GetWord(RPN, tPos + 2 + 1)); tPos += 4; break; case ptg.RefN: AddParsedRefN(TokenBuilder, RealToken, BitOps.GetWord(RPN, tPos + 1), BitOps.GetWord(RPN, tPos + 2 + 1)); tPos += 4; break; case ptg.AreaErr: case ptg.Area: AddParsedArea(TokenBuilder, RealToken, BitOps.GetWord(RPN, tPos + 1), BitOps.GetWord(RPN, tPos + 2 + 1), BitOps.GetWord(RPN, tPos + 4 + 1), BitOps.GetWord(RPN, tPos + 6 + 1)); tPos += 8; break; case ptg.AreaN: AddParsedAreaN(TokenBuilder, RealToken, BitOps.GetWord(RPN, tPos + 1), BitOps.GetWord(RPN, tPos + 2 + 1), BitOps.GetWord(RPN, tPos + 4 + 1), BitOps.GetWord(RPN, tPos + 6 + 1)); tPos += 8; break; case ptg.MemArea: { int ArrayLen; Push(TokenBuilder, new TMemAreaToken(RealToken, GetMemControl(RPN, ArrayPos, out ArrayLen), tPos + 1 + 6 + BitOps.GetWord(RPN, tPos + 1 + 4))); ArrayPos += ArrayLen; tPos += 6; break; //this is an optimization, but we don't need it. } case ptg.MemErr: { Push(TokenBuilder, new TMemErrToken(RealToken, (TFlxFormulaErrorValue)RPN[tPos + 1], tPos + 1 + 6 + BitOps.GetWord(RPN, tPos + 1 + 4))); tPos += 6; break; //this is an optimization, but we don't need it. } case ptg.MemNoMem: { Push(TokenBuilder, new TMemNoMemToken(RealToken, tPos + 1 + 6 + BitOps.GetWord(RPN, tPos + 1 + 4))); tPos += 6; break; //this is an optimization, but we don't need it. } case ptg.MemFunc: { Push(TokenBuilder, new TMemFuncToken(RealToken, tPos + 1 + 2 + BitOps.GetWord(RPN, tPos + 1))); tPos += 2; break; //this is an optimization, but we don't need it. } case ptg.MemAreaN: { Push(TokenBuilder, new TMemAreaNToken(RealToken, tPos + 1 + 2 + BitOps.GetWord(RPN, tPos + 1))); tPos += 2; break; //this is an optimization, but we don't need it. } case ptg.MemNoMemN: { Push(TokenBuilder, new TMemNoMemNToken(RealToken, tPos + 1 + 2 + BitOps.GetWord(RPN, tPos + 1))); tPos += 2; break; //this is an optimization, but we don't need it. } case ptg.Ref3dErr: case ptg.Ref3d: { int grBit1 = BitOps.GetWord(RPN, tPos + 4 + 1); int ExternSheet = BitOps.GetWord(RPN, tPos + 1); int Row1 = BitOps.GetWord(RPN, tPos + 2 + 1); AddParsed3dRef(TokenBuilder, RealToken, ExternSheet, Row1, grBit1); tPos += 6; break; } case ptg.Area3dErr: case ptg.Area3d: { int ExternSheet = BitOps.GetWord(RPN, tPos + 1); int Row1 = BitOps.GetWord(RPN, tPos + 2 + 1); int Row2 = BitOps.GetWord(RPN, tPos + 4 + 1); int grBit1 = BitOps.GetWord(RPN, tPos + 6 + 1); int grBit2 = BitOps.GetWord(RPN, tPos + 8 + 1); AddParsed3dArea(TokenBuilder, RealToken, ExternSheet, Row1, Row2, grBit1, grBit2); tPos += 10; break; } default: return(false); } return(true); }
protected static void AddParsedFormula(TParsedTokenListBuilder TokenBuilder, ptg FmlaPtg, TCellFunctionData Func, byte ArgCount) { TBaseParsedToken FmlaToken = TParsedTokenListBuilder.GetParsedFormula(FmlaPtg, Func, ArgCount); Push(TokenBuilder, FmlaToken); //Always push unsupported. }
protected static void AddParsedArea(TParsedTokenListBuilder TokenBuilder, ptg aId, int Rw1, int Rw2, int grBit1, int grBit2) { Push(TokenBuilder, new TAreaToken(aId, Biff8Utils.ExpandBiff8Row(Rw1), Biff8Utils.ExpandBiff8Col(grBit1 & ColMask), (grBit1 & 0x8000) == 0, (grBit1 & 0x4000) == 0, Biff8Utils.ExpandBiff8Row(Rw2), Biff8Utils.ExpandBiff8Col(grBit2 & ColMask), (grBit2 & 0x8000) == 0, (grBit2 & 0x4000) == 0)); }
private static void Add(Stream Data, Stream ArrayData, TBaseParsedToken Token, ptg BaseToken, TParsedTokenList Tokens, TTokenOffset StreamPos, TFormulaType FmlaType, Int32List FuturePos) { if (IsError(BaseToken, FmlaType)) { Data.WriteByte(0x1C); //PtgErr Data.WriteByte(0x2A); return; } Data.WriteByte((byte)Token.GetId); switch (BaseToken) { case ptg.Exp: TExp_Token exp = (TExp_Token)Token; Biff8Utils.CheckRow(exp.Row); Biff8Utils.CheckCol(exp.Col); WriteWord(Data, exp.Row); WriteWord(Data, exp.Col); break; case ptg.Tbl: TTableObjToken tblo = Token as TTableObjToken; if (tblo != null) { //no biff8 checks here. This numbers might be anything. WriteWord(Data, tblo.Row); WriteWord(Data, tblo.Col); } else { TTableToken tbl = (TTableToken)Token; Biff8Utils.CheckRow(tbl.Row); Biff8Utils.CheckCol(tbl.Col); WriteWord(Data, tbl.Row); WriteWord(Data, tbl.Col); } break; case ptg.Add: case ptg.Sub: case ptg.Mul: case ptg.Div: case ptg.Power: case ptg.Concat: case ptg.LT: case ptg.LE: case ptg.EQ: case ptg.GE: case ptg.GT: case ptg.NE: case ptg.Isect: case ptg.Union: case ptg.Range: case ptg.Uplus: case ptg.Uminus: case ptg.Percent: case ptg.Paren: case ptg.MissArg: break; case ptg.Str: { TStrDataToken tkd = Token as TStrDataToken; string s = tkd.GetData(); if (s.Length > FlxConsts.Max_FormulaStringConstant) { FlxMessages.ThrowException(FlxErr.ErrStringConstantInFormulaTooLong, s, String.Empty); } TExcelString Xs = new TExcelString(TStrLenLength.is8bits, s, null, false); byte[] b = new byte[Xs.TotalSize()]; Xs.CopyToPtr(b, 0); Data.Write(b, 0, b.Length); break; } case ptg.Attr: WriteAttr(Data, Token, StreamPos, Tokens.SavePosition()); break; /* * case ptg.Sheet: //Can't happen, ConvertBiff8ToInternal skips them. * case ptg.EndSheet: //Can't happen, ConvertBiff8ToInternal skips them. * break;*/ case ptg.Err: { Data.WriteByte((byte)((TErrDataToken)Token).GetData()); break; } case ptg.Bool: { if (((TBoolDataToken)Token).GetData()) { Data.WriteByte(1); } else { Data.WriteByte(0); } break; } case ptg.Int: { UInt16 a = (UInt16)((TIntDataToken)Token).GetData(); WriteWord(Data, a); break; } case ptg.Num: { double d = ((TNumDataToken)Token).GetData(); Data.Write(BitConverter.GetBytes(d), 0, 8); break; } case ptg.Array: { Data.Write(new byte[7], 0, 7); TArrayDataToken tk = (TArrayDataToken)Token; object[,] Arr = tk.GetData; int ColCount = Arr.GetLength(1) - 1; if (ColCount < 0 || ColCount > FlxConsts.Max_Columns97_2003) { FlxMessages.ThrowException(FlxErr.ErrInvalidCols, ColCount, FlxConsts.Max_Columns97_2003 + 1); } ArrayData.WriteByte((byte)(ColCount)); int RowCount = Arr.GetLength(0) - 1; if (RowCount < 0 || RowCount > FlxConsts.Max_Rows) { FlxMessages.ThrowException(FlxErr.ErrInvalidRows, RowCount, FlxConsts.Max_Rows + 1); } WriteWord(ArrayData, RowCount); for (int r = 0; r <= RowCount; r++) { for (int c = 0; c <= ColCount; c++) { WriteArrayObject(ArrayData, Arr[r, c]); } } break; } case ptg.Func: { TBaseFunctionToken ft = (TBaseFunctionToken)Token; TCellFunctionData fd = ft.GetFunctionData(); WriteWord(Data, fd.Index); break; } case ptg.FuncVar: { TBaseFunctionToken ft = (TBaseFunctionToken)Token; TCellFunctionData fd = ft.GetFunctionData(); if (!BackFromFutureToUserDef(Data, Tokens, FuturePos, ft, fd)) { Data.WriteByte((byte)ft.ArgumentCount); WriteWord(Data, fd.Index); } break; } case ptg.Name: WriteWord(Data, ((TNameToken)Token).NameIndex); WriteWord(Data, 0); break; case ptg.Ref: case ptg.RefN: case ptg.RefErr: { TRefToken reft = (TRefToken)Token; WriteRef(Data, reft.CanHaveRelativeOffsets, reft.Row, reft.RowAbs, reft.Col, reft.ColAbs); break; } case ptg.Area: case ptg.AreaN: case ptg.AreaErr: { TAreaToken areat = (TAreaToken)Token; WriteArea(Data, areat.CanHaveRelativeOffsets, areat.Row1, areat.RowAbs1, areat.Col1, areat.ColAbs1, areat.Row2, areat.RowAbs2, areat.Col2, areat.ColAbs2); break; } case ptg.MemArea: { WriteWord(Data, 0); WriteWord(Data, 0); StreamPos.Add((int)Data.Position, Tokens.SavePosition()); WriteWord(Data, 0); TRefRange[] Range = ((TMemAreaToken)Token).Data; WriteWord(ArrayData, Range.Length); foreach (TRefRange OneRef in Range) { int r1 = Biff8Utils.CheckAndContractBiff8Row(OneRef.FirstRow); int r2 = Biff8Utils.CheckAndContractBiff8Row(OneRef.LastRow); int c1 = Biff8Utils.CheckAndContractBiff8Col(OneRef.FirstCol); int c2 = Biff8Utils.CheckAndContractBiff8Col(OneRef.LastCol); WriteWord(ArrayData, r1); WriteWord(ArrayData, r2); WriteWord(ArrayData, c1); WriteWord(ArrayData, c2); } break; } case ptg.MemErr: case ptg.MemNoMem: WriteWord(Data, 0); WriteWord(Data, 0); StreamPos.Add((int)Data.Position, Tokens.SavePosition()); WriteWord(Data, 0); break; case ptg.MemFunc: case ptg.MemAreaN: case ptg.MemNoMemN: StreamPos.Add((int)Data.Position, Tokens.SavePosition()); WriteWord(Data, 0); break; case ptg.NameX: TNameXToken NameX = (TNameXToken)Token; WriteWord(Data, NameX.FExternSheet); WriteWord(Data, NameX.NameIndex); WriteWord(Data, 0); break; case ptg.Ref3dErr: case ptg.Ref3d: TRef3dToken reft3d = (TRef3dToken)Token; WriteWord(Data, reft3d.FExternSheet); WriteRef(Data, reft3d.CanHaveRelativeOffsets, reft3d.Row, reft3d.RowAbs, reft3d.Col, reft3d.ColAbs); break; case ptg.Area3d: case ptg.Area3dErr: TArea3dToken areat3d = (TArea3dToken)Token; WriteWord(Data, areat3d.FExternSheet); WriteArea(Data, areat3d.CanHaveRelativeOffsets, areat3d.Row1, areat3d.RowAbs1, areat3d.Col1, areat3d.ColAbs1, areat3d.Row2, areat3d.RowAbs2, areat3d.Col2, areat3d.ColAbs2); break; default: XlsMessages.ThrowException(XlsErr.ErrInternal); //All tokens here should exist break; } }
private static void Evaluate(TBaseParsedToken Token, bool R1C1, int CellRow, int CellCol, ptg BaseToken, TParsedTokenList RPN, ICellList CellList, TWorkbookGlobals Globals, TFormulaStack ParsedStack, ref string StartFormula, int MaxStringConstantLen, bool WritingXlsx) { string s1; string s2; string s3; switch (BaseToken) { case ptg.Exp: AddArray(Token, CellRow, CellCol, CellList, Globals, ParsedStack, MaxStringConstantLen, WritingXlsx); StartFormula = String.Empty; break; case ptg.Tbl: AddTable(R1C1, Token, CellList, ParsedStack); StartFormula = String.Empty; break; case ptg.Add: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmPlus) + s2); break; case ptg.Sub: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmMinus) + s2); break; case ptg.Mul: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmMul) + s2); break; case ptg.Div: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmDiv) + s2); break; case ptg.Power: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmPower) + s2); break; case ptg.Concat: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmAnd) + s2); break; case ptg.LT: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmLT) + s2); break; case ptg.LE: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmLE) + s2); break; case ptg.EQ: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmEQ) + s2); break; case ptg.GE: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmGE) + s2); break; case ptg.GT: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmGT) + s2); break; case ptg.NE: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmNE) + s2); break; case ptg.Isect: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmIntersect) + s2); break; case ptg.Union: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmUnion) + s2); break; case ptg.Range: s2 = ParsedStack.Pop(); s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmRangeSep) + s2); break; case ptg.Uplus: s1 = ParsedStack.Pop(); ParsedStack.Push(ParsedStack.FmSpaces + fts(TFormulaToken.fmPlus) + s1); break; case ptg.Uminus: s1 = ParsedStack.Pop(); ParsedStack.Push(ParsedStack.FmSpaces + fts(TFormulaToken.fmMinus) + s1); break; case ptg.Percent: s1 = ParsedStack.Pop(); ParsedStack.Push(s1 + ParsedStack.FmSpaces + fts(TFormulaToken.fmPercent)); break; case ptg.Paren: s1 = ParsedStack.Pop(); ParsedStack.Push(ParsedStack.FmPreSpaces + fts(TFormulaToken.fmOpenParen) + s1 + ParsedStack.FmPostSpaces + fts(TFormulaToken.fmCloseParen)); break; case ptg.MissArg: ParsedStack.Push(ParsedStack.FmSpaces); break; case ptg.Str: ParsedStack.Push(ParsedStack.FmSpaces + fts(TFormulaToken.fmStr) + GetString(((TStrDataToken)Token).GetData(), MaxStringConstantLen) + fts(TFormulaToken.fmStr)); break; case ptg.Attr: ProcessAttr(Token, ParsedStack); break; case ptg.Sheet: break; case ptg.EndSheet: break; case ptg.Err: ParsedStack.Push(ParsedStack.FmSpaces + GetErrorText(((TErrDataToken)Token).GetData())); break; case ptg.Bool: ParsedStack.Push(ParsedStack.FmSpaces + GetBoolText(((TBoolDataToken)Token).GetData())); break; case ptg.Int: ParsedStack.Push(ParsedStack.FmSpaces + TFormulaMessages.FloatToString(((TIntDataToken)Token).GetData())); break; case ptg.Num: ParsedStack.Push(ParsedStack.FmSpaces + TFormulaMessages.FloatToString(((TNumDataToken)Token).GetData())); break; case ptg.Array: ParsedStack.Push(ParsedStack.FmSpaces + GetArrayText(((TArrayDataToken)Token).GetData, MaxStringConstantLen)); break; case ptg.Func: case ptg.FuncVar: int ArgCount; bool IsAddin; StringBuilder sb = new StringBuilder(); TBaseFunctionToken FunctionTk = Token as TBaseFunctionToken; s3 = ParsedStack.FmSpaces + GetFuncName(FunctionTk, out ArgCount, WritingXlsx, out IsAddin); if (ArgCount > 0) { sb.Append(ParsedStack.Pop()); } for (int i = 2; i <= ArgCount; i++) { s1 = ParsedStack.Pop(); sb.Insert(0, s1 + fts(TFormulaToken.fmFunctionSep)); } if (IsAddin) { s3 += ConvertInternalFunctionName(Globals, ParsedStack.Pop()); } ParsedStack.Push(s3 + fts(TFormulaToken.fmOpenParen) + ParsedStack.FmPreSpaces + sb.ToString() + ParsedStack.FmPostSpaces + fts(TFormulaToken.fmCloseParen)); break; case ptg.Name: ParsedStack.Push(ParsedStack.FmSpaces + GetName(((TNameToken)Token).NameIndex, -1, Globals, WritingXlsx)); break; case ptg.RefN: case ptg.Ref: ParsedStack.Push(ParsedStack.FmSpaces + GetRef(R1C1, (TRefToken)Token, CellRow, CellCol)); break; case ptg.AreaN: case ptg.Area: ParsedStack.Push(ParsedStack.FmSpaces + GetArea(R1C1, (TAreaToken)Token, CellRow, CellCol)); break; case ptg.MemArea: break; case ptg.MemErr: break; case ptg.MemNoMem: break; case ptg.MemFunc: break; case ptg.RefErr: ParsedStack.Push(ParsedStack.FmSpaces + TFormulaMessages.ErrString(TFlxFormulaErrorValue.ErrRef)); break; case ptg.AreaErr: ParsedStack.Push(ParsedStack.FmSpaces + TFormulaMessages.ErrString(TFlxFormulaErrorValue.ErrRef)); break; case ptg.MemAreaN: break; case ptg.MemNoMemN: break; case ptg.NameX: ParsedStack.Push(ParsedStack.FmSpaces + GetNameX((TNameXToken)Token, Globals, WritingXlsx)); break; case ptg.Ref3d: ParsedStack.Push(ParsedStack.FmSpaces + GetRef3D(R1C1, (TRef3dToken)Token, CellRow, CellCol, Globals, false, WritingXlsx)); break; case ptg.Area3d: ParsedStack.Push(ParsedStack.FmSpaces + GetArea3D(R1C1, (TArea3dToken)Token, CellRow, CellCol, Globals, false, WritingXlsx)); break; case ptg.Ref3dErr: ParsedStack.Push(ParsedStack.FmSpaces + GetRef3D(R1C1, (TRef3dToken)Token, -1, -1, Globals, true, WritingXlsx)); break; case ptg.Area3dErr: ParsedStack.Push(ParsedStack.FmSpaces + GetArea3D(R1C1, (TArea3dToken)Token, CellRow, CellCol, Globals, true, WritingXlsx)); break; default: XlsMessages.ThrowException(XlsErr.ErrBadToken, Token); break; } }