Example #1
0
        private void CheckFutureFunction(TParsedTokenListBuilder TokenBuilder, ref int np, TNameRecordList Names, ref TCellFunctionData fd2, TTokenOffset TokenOffset, ref bool HasAggregate)
        {
            //We need to recursively read parameters in back order to find out the name, which is stored as far as possible from the function :(
            TParsedTokenList ParsedList = TokenBuilder.ToParsedTokenList();

            ParsedList.ResetPositionToLast();
            for (int i = 0; i < np; i++) //np is +1. But we will move below the name, then inc 1, so we know there isn't a "neutral" token like parent or memarea, intead of the real thing.
            {
                ParsedList.Flush();
            }

            ParsedList.MoveBack();
            TNameToken bp = ParsedList.ForwardPop() as TNameToken;

            if (bp is TNameXToken)
            {
                return;                    //This name isn't an internal 2007 name.
            }
            if (bp == null)
            {
                return;
            }
            if (bp.NameIndex <= 0 || bp.NameIndex > Names.Count)
            {
                return;
            }
            string FunctionName = Names[bp.NameIndex - 1].Name;

            if (FunctionName.StartsWith("_xlfn.", StringComparison.InvariantCultureIgnoreCase))
            {
                TCellFunctionData fn = TXlsFunction.GetData(FunctionName.Substring("_xlfn.".Length));
                if (fn != null)
                {
                    if (fn.Index == (int)TFutureFunctions.Aggregate)
                    {
                        HasAggregate = true;
                    }

                    fd2 = fn;
                    int tPos = ParsedList.SavePosition();
                    TokenBuilder.RemoveAt(tPos);
                    TokenOffset.RemoveToken(tPos);
                    np--;
                }
            }
        }
Example #2
0
        private static string GetFuncName(TBaseFunctionToken Token, out int ArgCount, bool WritingXlsx, out bool IsAddin)
        {
            TCellFunctionData fd = Token.GetFunctionData();

            ArgCount = Token.ArgumentCount;

            IsAddin = Token is TUserDefinedToken;
            if (IsAddin)
            {
                ArgCount--;
                return(String.Empty);
            }

            if (WritingXlsx && fd.FutureInXlsx)
            {
                return(fd.FutureName);
            }
            return(fd.Name);
        }
Example #3
0
        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);
        }
Example #4
0
        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.
        }
Example #5
0
        private static bool BackFromFutureToUserDef(Stream Data, TParsedTokenList Tokens, Int32List FuturePos, TBaseFunctionToken ft, TCellFunctionData fd)
        {
            string FutureName = fd.FutureName;

            if (FutureName != null)
            {
                Data.WriteByte((byte)(ft.ArgumentCount + 1));
                WriteWord(Data, 0xFF); //User def...
                FuturePos.Add(Tokens.SavePosition());
                return(true);
            }

            return(false);
        }
Example #6
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;
            }
        }