コード例 #1
0
        internal TSharedFormula(TNameRecordList Names, UInt64 aKey, byte[] aData, int start, int len)
        {
            Key = aKey;
            TFormulaConvertBiff8ToInternal p = new TFormulaConvertBiff8ToInternal();

            Data = p.ParseRPN(Names, -1, -1, aData, start, len, true); //no real need for relative since shared formulas can't be 3d, and we only need relative for the non-existing tokens ptgarea3dn and ptgref3dn.
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        internal static TParsedTokenList CreateObjFmlaFromBiff8(TNameRecordList Names, int aRow, int aCol, byte[] aData, int aStart, int aLen, bool aRelative3dRanges)
        {
            TFormulaConvertBiff8ToInternal rpn = new TFormulaConvertBiff8ToInternal();
            bool HasSubtotal; bool HasAggregate;

            return(rpn.ParseRPN(Names, aRow, aCol, aData, aStart, aLen, aRelative3dRanges, out HasSubtotal, out HasAggregate, true));
        }
コード例 #4
0
        /// <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());
                }
            }
        }
コード例 #5
0
        internal bool Update;         //We will contemplate 2 ways of working for this. When Update is true, ranges will be modified, else we will just build the list.

        internal TDeletedRanges(int NameCount, TReferences aReferences, TNameRecordList aNames)
        {
            Refs       = new bool[NameCount];
            Offs       = new int[NameCount];
            Length     = NameCount;
            References = aReferences;
            Names      = aNames;
            Update     = false;
        }
コード例 #6
0
        private static void FixFutureFunctions(TNameRecordList Names, Int32List FuturePos, TParsedTokenList Tokens, MemoryStream Data, int[] TokenOffset, ref TTokenOffset StreamPos)
        {
            if (FuturePos.Count == 0)
            {
                return;
            }


            List <byte> NewData = new List <byte>(Data.ToArray()); //we need to insert in any order

            for (int i = 0; i < FuturePos.Count; i++)
            {
                Tokens.MoveTo(FuturePos[i]);
                TBaseFunctionToken FuncToken = (TBaseFunctionToken)Tokens.GetToken(FuturePos[i]);
                for (int k = 0; k < FuncToken.ArgumentCount; k++) //this doesn't include the name.
                {
                    Tokens.Flush();
                }

                int TokPos = Tokens.SavePosition();
                while (TokPos > 0)
                {
                    if (!(Tokens.GetToken(TokPos - 1) is TIgnoreInCalcToken) || Tokens.GetToken(TokPos - 1) is TAttrToken)
                    {
                        break;
                    }
                    TokPos--;
                }

                int ofs = TokenOffset[TokPos];
                WriteFutureName(NewData, ofs, FindName(Names, FuncToken.GetFunctionData().FutureName));

                for (int k = TokPos; k < TokenOffset.Length; k++)
                {
                    TokenOffset[k] += 5;
                }

                TTokenOffset NewStreamPos = new TTokenOffset();
                foreach (int streamofs in StreamPos.Keys)
                {
                    int sofs = streamofs;
                    if (sofs >= ofs)
                    {
                        sofs += 5;
                    }
                    NewStreamPos.Add(sofs, StreamPos[streamofs]);
                }

                StreamPos = NewStreamPos;
            }

            Data.SetLength(0);
            Data.Write(NewData.ToArray(), 0, NewData.Count);
        }
コード例 #7
0
ファイル: UXlsWorkbookGlobals.cs プロジェクト: mwilian/demos
        internal TCopiedGen DrawingGen; //used when copying to make sure we don't repeat.
        #endregion

        #region Constructor
        internal TWorkbookGlobals(ExcelFile aWorkbook)
        {
            FWorkbook = aWorkbook;

            FFileEncryption = new TFileEncryption();
            FLel            = new TMiscRecordList();
            FBoundSheets    = new TBoundSheetList();
            FFnGroups       = new TMiscRecordList();

            FWorkbookProtection = new TWorkbookProtection();
            FFonts       = new TFontRecordList();
            FFormats     = TFormatRecordList.Create();
            FStyleXF     = new TXFRecordList();
            FCellXF      = new TXFRecordList();
            FDXF         = new TDXFRecordList();
            FStyles      = new TStyleRecordList();
            FTableStyles = new TTableStyleRecordList();

            FPivotCache = new TMiscRecordList();
#if (FRAMEWORK30 && !COMPACTFRAMEWORK)
            FXlsxPivotCache  = new TXlsxPivotCacheList();
            FXlsxConnections = null;
#endif
            FDocRoute  = new TMiscRecordList();
            FUserBView = new TMiscRecordList();

            FMetaData     = new TMiscRecordList();
            FNames        = new TNameRecordList();
            FRealTimeData = new TMiscRecordList();

            FReferences = new TReferences();

            FHeaderImages = new TDrawingGroup(xlr.HEADERIMG, 14);
            FDrawingGroup = new TDrawingGroup(xlr.MSODRAWINGGROUP, 0);

            FSST    = new TSST();
            FWebPub = new TMiscRecordList();

            FFeatHdr = new TMiscRecordList();
            FDConn   = new TMiscRecordList();

            FBorders            = new TBorderList();
            FPatterns           = new TPatternList();
            FFutureRecords      = new TMiscRecordList();
            StylesFutureStorage = null;

            CalcOptions = new TCalcOptions();
            ThemeRecord = new TThemeRecord();

#if (FRAMEWORK30 && !COMPACTFRAMEWORK)
            CustomXMLData = new TCustomXMLDataStorageList();
#endif
        }
コード例 #8
0
ファイル: URecordLoader.cs プロジェクト: mwilian/demos
 protected TBaseRecordLoader(TSST aSST, IFlexCelFontList aFontList, TEncryptionData aEncryption, TXlsBiffVersion aXlsBiffVersion,
                             TBiff8XFMap aXFMap, TNameRecordList aNames, TVirtualReader aVirtualReader)
 {
     RecordHeader   = new TRecordHeader();
     SST            = aSST;
     FontList       = aFontList;
     Encryption     = aEncryption;
     XlsBiffVersion = aXlsBiffVersion;
     XFMap          = aXFMap;
     Names          = aNames;
     VirtualReader  = aVirtualReader;
 }
コード例 #9
0
        public TParsedTokenList ParseRPN(TNameRecordList Names, int aRow, int aCol, byte[] Data, int atPos, int fmlaLen, bool aRelative3dRanges, out bool HasSubtotal, out bool HasAggregate, bool aIsFmlaObject)
        {
            HasSubtotal      = false;
            HasAggregate     = false;
            Relative3dRanges = aRelative3dRanges;
            IsFmlaObject     = aIsFmlaObject;
            TParsedTokenListBuilder TokenBuilder = new TParsedTokenListBuilder();

            if (!DoRPN(TokenBuilder, Names, Data, atPos, atPos + fmlaLen, ref HasSubtotal, ref HasAggregate))
            {
                XlsMessages.ThrowException(XlsErr.ErrBadFormula, aRow + 1, aCol + 1, 0);
            }
            return(TokenBuilder.ToParsedTokenList());
        }
コード例 #10
0
        internal static void SaveToStream(TNameRecordList Names, IDataStream Workbook, TFormulaType FmlaType, TParsedTokenList Data, bool WriteLen)
        {
            if (Data.TextLenght > FlxConsts.Max_FormulaLen97_2003)
            {
                FlxMessages.ThrowException(FlxErr.ErrFormulaTooLong, TFormulaConvertInternalToText.AsString(Data, 0, 0, null));
            }
            int FmlaNoArrayLen;

            byte[] bData = TFormulaConvertInternalToBiff8.GetTokenData(Names, Data, FmlaType, out FmlaNoArrayLen);
            if (WriteLen)
            {
                Workbook.Write16((UInt16)FmlaNoArrayLen);
            }
            Workbook.Write(bData, bData.Length);
        }
コード例 #11
0
        private static int FindName(TNameRecordList Names, string Name)
        {
            if (Names == null)
            {
                return(0);               //Calculating length.
            }
            for (int i = 0; i < Names.Count; i++)
            {
                if (String.Equals(Name, Names[i].Name, StringComparison.CurrentCultureIgnoreCase) && (Names[i].IsAddin))
                {
                    return(i + 1);
                }
            }

            FlxMessages.ThrowException(FlxErr.ErrCantFindNamedRange, Name);
            return(-1);
        }
コード例 #12
0
ファイル: UXlsWorkbookGlobals.cs プロジェクト: mwilian/demos
        internal void MergeFromPxlGlobals(TWorkbookGlobals SourceGlobals)
        {
            sBOF         = SourceGlobals.sBOF;
            FSST         = SourceGlobals.FSST;
            FReferences  = SourceGlobals.FReferences;
            FBoundSheets = SourceGlobals.FBoundSheets;

            //Pxl doesn't have styles.
            CellXF.MergeFromPxlXF(SourceGlobals.CellXF, Fonts.Count - 1, this, SourceGlobals);  //-1 because fonts[0] will be merged
            FFonts.MergeFromPxlFont(SourceGlobals.Fonts);
            //Formats are added in FXF.Merge

            FNames  = SourceGlobals.FNames;
            Window1 = SourceGlobals.Window1;

            CodePage = SourceGlobals.CodePage;
            Country  = SourceGlobals.Country;
        }
コード例 #13
0
ファイル: UXlsRecordLoader.cs プロジェクト: mwilian/demos
 internal TXlsRecordLoader(TOle2File aDataStream, TBiff8XFMap aXFMap, TSST aSST, IFlexCelFontList aFontList, TBorderList aBorderList,
                           TPatternList aPatternList, TEncryptionData aEncryption, TXlsBiffVersion aXlsBiffVersion, TNameRecordList aNames, TVirtualReader VirtualReader)
     : base(aSST, aFontList, aEncryption, aXlsBiffVersion, aXFMap, aNames, VirtualReader)
 {
     DataStream  = aDataStream;
     BorderList  = aBorderList;
     PatternList = aPatternList;
 }
コード例 #14
0
        internal TParsedTokenList ParseRPN(TNameRecordList Names, int aCol, int aRow, byte[] Data, int p, int FLen, bool aRelative3dRanges)
        {
            bool HasSubtotal; bool HasAggregate;

            return(ParseRPN(Names, aCol, aRow, Data, p, FLen, aRelative3dRanges, out HasSubtotal, out HasAggregate, false));
        }
コード例 #15
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--;
                }
            }
        }
コード例 #16
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);
        }
コード例 #17
0
ファイル: URecordLoader.cs プロジェクト: mwilian/demos
 protected TBinRecordLoader(TSST aSST, IFlexCelFontList aFontList, TEncryptionData aEncryption,
                            TXlsBiffVersion aXlsBiffVersion, TBiff8XFMap aXFMap, TNameRecordList aNames, TVirtualReader aVirtualReader)
     : base(aSST, aFontList, aEncryption, aXlsBiffVersion, aXFMap, aNames, aVirtualReader)
 {
 }
コード例 #18
0
ファイル: UPxlRecordLoader.cs プロジェクト: mwilian/demos
        internal TPxlRecordLoader(Stream aDataStream, TExternSheetList aExternSheetList,
                                  TEncryptionData aEncryption, TSST aSST, IFlexCelFontList aFontList, TBorderList aBorderList,
                                  TPatternList aPatternList, ExcelFile aWorkbook, TBiff8XFMap aXFMap, int aMainBookXFCount, TNameRecordList aNames, TVirtualReader VirtualReader)
            : base(aSST, aFontList, aEncryption, aWorkbook.XlsBiffVersion, aXFMap, aNames, VirtualReader)
        {
            DataStream         = aDataStream;
            FExternSheetList   = aExternSheetList;
            FormatId           = 233;
            FWorkbook          = aWorkbook;
            BorderList         = aBorderList;
            PatternList        = aPatternList;
            DataStreamLength   = DataStream.Length;
            DataStreamPosition = DataStream.Position;  //cached for performance.

            MainBookXFCount = aMainBookXFCount;
        }