zoukankan      html  css  js  c++  java
  • Delphi unit XLSReadII2;

       

    unit XLSReadII2;

    {

    ********************************************************************************

    ******* XLSReadWriteII V2.00                                             *******

    *******                                                                  *******

    ******* Copyright(C) 1999,2004 Lars Arvidsson, Axolot Data               *******

    *******                                                                  *******

    ******* email: components@axolot.com                                     *******

    ******* URL:   http://www.axolot.com                                     *******

    ********************************************************************************

    ** Users of the XLSReadWriteII component must accept the following            **

    ** disclaimer of warranty:                                                    **

    **                                                                            **

    ** XLSReadWriteII is supplied as is. The author disclaims all warranties,     **

    ** expressedor implied, including, without limitation, the warranties of      **

    ** merchantability and of fitness for any purpose. The author assumes no      **

    ** liability for damages, direct or consequential, which may result from the  **

    ** use of XLSReadWriteII.                                                     **

    ********************************************************************************

    }

    {$B-}

    {$R-}

    interface

    uses Classes, SysUtils, Windows, Messages, BIFFRecsII2, CellFormats2, SheetData2,

         XLSStream2, XLSReadWriteII2, XLSUtils2, Dialogs, DecodeFormula2,

         XLSFonts2, ExcelMaskII2, Validate2, Math, XLSRWIIResourceStrings2,

         RecordStorage2, Escher2, MergedCells2;

    type TSharedFormula = record

         Row1,Row2: word;

         Col1,Col2: byte;

         Len: word;

         Formula: PByteArray;

         end;

    type TXLSReadII = class(TObject)

    protected

         PBuf: PByteArray;

         FXLS: TXLSReadWriteII2;

         FCurrSheet: integer;

         FXLSStream: TXLSStream;

         FBoundsheets: TStringList;

         FBoundsheetIndex: integer;

         Header: TBIFFHeader;

         FSharedFormulas: array of TSharedFormula;

         CurrRecs: TRecordStorage;

         InsertRecord: boolean;

         // File prefix

         procedure RREC_FILEPASS;

         procedure RREC_INTERFACEHDR;

         procedure RREC_ADDMENU;

         procedure RREC_DELMENU;

         procedure RREC_INTERFACEEND;

         procedure RREC_WRITEACCESS;

         procedure RREC_CODEPAGE;

         procedure RREC_DSF;

         procedure RREC_FNGROUPCOUNT;

         procedure RREC_WINDOWPROTECT;

         procedure RREC_PROTECT;

         procedure RREC_PASSWORD;

         procedure RREC_PROT4REV;

         procedure RREC_PROT4REVPASS;

         procedure RREC_WINDOW1;

         procedure RREC_BACKUP;

         procedure RREC_HIDEOBJ;

         procedure RREC_1904;

         procedure RREC_PRECISION;

         procedure RREC_REFRESHALL;

         procedure RREC_BOOKBOOL;

         procedure RREC_PALETTE;

         procedure RREC_FONT;

         procedure RREC_FORMAT;

         procedure RREC_XF;

         procedure RREC_STYLE;

         procedure RREC_NAME;

         procedure RREC_SUPBOOK;

         procedure RREC_EXTERNNAME;

         procedure RREC_XCT;

         procedure RREC_EXTERNCOUNT;

         procedure RREC_EXTERNSHEET;

         procedure RREC_USESELFS;

         procedure RREC_BOUNDSHEET;

         procedure RREC_COUNTRY;

         procedure RREC_RECALCID;

         procedure RREC_MSODRAWINGGROUP;

         procedure RREC_SST;

         procedure RREC_EXTSST;

         procedure RREC_EOF;

         // Sheet prefix

         procedure RREC_CALCMODE;

         procedure RREC_CALCCOUNT;

         procedure RREC_REFMODE;

         procedure RREC_ITERATION;

         procedure RREC_DELTA;

         procedure RREC_SAVERECALC;

         procedure RREC_PRINTHEADERS;

         procedure RREC_PRINTGRIDLINES;

         procedure RREC_GRIDSET;

         procedure RREC_GUTS;

         procedure RREC_DEFAULTROWHEIGHT;

         procedure RREC_WSBOOL;

         procedure RREC_HORIZONTALPAGEBREAKS;

         procedure RREC_VERTICALPAGEBREAKS;

         procedure RREC_HEADER;

         procedure RREC_FOOTER;

         procedure RREC_HCENTER;

         procedure RREC_VCENTER;

         procedure RREC_PLS;

         procedure RREC_SETUP;

         procedure RREC_LEFTMARGIN;

         procedure RREC_RIGHTMARGIN;

         procedure RREC_TOPMARGIN;

         procedure RREC_BOTTOMMARGIN;

         procedure RREC_DEFCOLWIDTH;

         procedure RREC_COLINFO;

         procedure RREC_DIMENSIONS;

         // Sheet data

         procedure RREC_INTEGER_20;

         procedure RREC_NUMBER_20;

         procedure RREC_LABEL_20;

         procedure RREC_ROW;

         procedure RREC_BLANK;

         procedure RREC_BOOLERR;

         procedure RREC_FORMULA;

         procedure RREC_FORMULA_30;

         procedure RREC_NUMBER;

         procedure RREC_RK;

         procedure RREC_MULRK;

         procedure RREC_MULBLANK;

         procedure RREC_LABELSST;

         procedure RREC_LABEL;

         procedure RREC_RSTRING;

         procedure RREC_NOTE;

         procedure READ_SHRFMLA;

         // Sheet suffix

         procedure RREC_MSODRAWING;

         procedure RREC_MSODRAWINGSELECTION;

         procedure RREC_WINDOW2;

         procedure RREC_SCL;

         procedure RREC_PANE;

         procedure RREC_SELECTION;

         procedure RREC_DVAL;

         procedure RREC_MERGEDCELLS;

         procedure RREC_CONDFMT;

         procedure RREC_HLINK;

         procedure Clear;

         procedure ClearSharedFmla;

         procedure ReadFormulaVal(Col,Row,FormatIndex: integer; Value: double; Formula: PByteArray; Len: integer);

         procedure FixupSharedFormula(ACol,ARow: integer);

    public

         constructor Create(XLS: TXLSReadWriteII2);

         destructor Destroy; override;

         procedure LoadFromStream(Stream: TStream);

         end;

    implementation

    constructor TXLSReadII.Create(XLS: TXLSReadWriteII2);

    begin

      FXLS := XLS;

      FXLSStream := TXLSStream.Create;

      FXLSStream.SaveVBA := XLS.PreserveMacros;

      FBoundsheets := TStringList.Create;

    end;

    destructor TXLSReadII.Destroy;

    begin

      FXLSStream.Free;

      FBoundsheets.Free;

      ClearSharedFmla;

      inherited Destroy;

    end;

    procedure TXLSReadII.Clear;

    begin

      FCurrSheet := -1;

      FBoundsheets.Clear;

      FBoundsheetIndex := -1;

    end;

    procedure TXLSReadII.ClearSharedFmla;

    var

      i: integer;

    begin

      for i := 0 to High(FSharedFormulas) do

        FreeMem(FSharedFormulas[i].Formula);

      SetLength(FSharedFormulas,0);

    end;

    procedure TXLSReadII.LoadFromStream(Stream: TStream);

    var

      ProgressCount: integer;

      Count: integer;

      InUSERSVIEW: boolean;

    begin

      InUSERSVIEW := False;

      Count := 0;

      Clear;

      FXLS.WriteDefaultData := False;

      try

        FXLSStream.ExtraObjects := FXLS.ExtraObjects;

        FXLSStream.SourceStream := Stream;

        FXLS.Version := FXLSStream.OpenRead(FXLS.Filename);

        GetMem(PBuf,FXLS.MaxBuffsize);

        CurrRecs := FXLS.Records;

        ProgressCount := 0;

        if Assigned(FXLS.OnProgress) then

          FXLS.OnProgress(Self,0);

        try

          while FXLSStream.ReadHeader(Header) = SizeOf(TBIFFHeader) do begin

            if Header.Length > FXLS.MaxBuffsize then begin

              // Invalid record sizer

              FXLSStream.Seek(Header.Length,soFromCurrent);

              Continue;

            end

            else if (Header.RecID and INTERNAL_PLACEHOLDER) <> 0 then

              raise Exception.Create('Bad record in file')

            else if ((Header.RecID and $FF) <> BIFFRECID_BOF) and (Header.RecId <> BIFFRECID_SST) and (Header.RecId <> BIFFRECID_MSODRAWINGGROUP) and (Header.RecId <> BIFFRECID_MSODRAWING) then begin

              FXLSStream.Read(PBuf^,Header.Length);

    {

              if FXLSStream.IsEncrypted and (Header.Length > 0) then

                FXLSStream.Decrypt(PBuf,Header.Length);

    }

            end;

            Inc(ProgressCount);

            if ProgressCount >= 100 then begin

              if Assigned(FXLS.OnProgress) then

                FXLS.OnProgress(Self,Round((FXLSStream.Pos / FXLSStream.Size) * 100));

              ProgressCount := 0;

            end;

      //      if ((Header.RecID and $FF) <> BIFFRECID_BOF) and (Header.RecID <> BIFFRECID_EXCEL9FILE) then

      //        CurrRecs.Add(Header,PBuf);

            if InUSERSVIEW then begin

              if Header.RecID = BIFFRECID_USERSVIEWEND then

                InUSERSVIEW := False;        

              Continue;

            end;

            InsertRecord := True;

            case Header.RecID of

              BIFFRECID_EOF: begin

                CurrRecs.UpdateDefault(Header,PBuf);

                InsertRecord := False;

                ClearSharedFmla;

                if (FBoundsheets.Count = 0) or (FBoundsheetIndex >= (FBoundsheets.Count - 1)) then begin

                  Break;

                end;

              end;

              // File prefix

      //        BIFFRECID_OBPROJ:              InsertRecord := False;

              BIFFRECID_EXCEL9FILE:          InsertRecord := False;

              BIFFRECID_FILEPASS:            RREC_FILEPASS;

              BIFFRECID_INTERFACEHDR:        RREC_INTERFACEHDR;

              BIFFRECID_INTERFACEEND:        RREC_INTERFACEEND;

              BIFFRECID_WRITEACCESS:         RREC_WRITEACCESS;

              BIFFRECID_CODEPAGE:            RREC_CODEPAGE;

              BIFFRECID_DSF:                 RREC_DSF;

              BIFFRECID_FNGROUPCOUNT:        RREC_FNGROUPCOUNT;

              BIFFRECID_WINDOWPROTECT:       RREC_WINDOWPROTECT;

              BIFFRECID_PROTECT:             RREC_PROTECT;

              BIFFRECID_PASSWORD:            RREC_PASSWORD;

              BIFFRECID_PROT4REV:            RREC_PROT4REV;

              BIFFRECID_PROT4REVPASS:        RREC_PROT4REVPASS;

              BIFFRECID_WINDOW1:             RREC_WINDOW1;

              BIFFRECID_BACKUP:              RREC_BACKUP;

              BIFFRECID_HIDEOBJ:             RREC_HIDEOBJ;

              BIFFRECID_1904:                RREC_1904;

              BIFFRECID_PRECISION:           RREC_PRECISION;

              BIFFRECID_REFRESHALL:          RREC_REFRESHALL;

              BIFFRECID_BOOKBOOL:            RREC_BOOKBOOL;

              BIFFRECID_PALETTE:             RREC_PALETTE;

              BIFFRECID_FONT,$0231:          RREC_FONT;

              BIFFRECID_FORMAT:              RREC_FORMAT;

              BIFFRECID_XF_30,

              BIFFRECID_XF_40,

              BIFFRECID_XF:                  RREC_XF;

              // STYLE (inbyggda) m錽te finnas, annars s� fungerar inte "style"

              // knapparna i Excel.

      //        BIFFRECID_STYLE:               RREC_STYLE;

              BIFFRECID_NAME,$0218:          RREC_NAME;

              BIFFRECID_SUPBOOK:             RREC_SUPBOOK;

              BIFFRECID_EXTERNNAME,$0223:    RREC_EXTERNNAME;

              BIFFRECID_XCT:                 RREC_XCT;

              BIFFRECID_EXTERNCOUNT:         RREC_EXTERNCOUNT;

              BIFFRECID_EXTERNSHEET:         RREC_EXTERNSHEET;

              BIFFRECID_USESELFS:            RREC_USESELFS;

              BIFFRECID_BOUNDSHEET:          RREC_BOUNDSHEET;

              BIFFRECID_COUNTRY:             RREC_COUNTRY;

              BIFFRECID_RECALCID:            RREC_RECALCID;

              BIFFRECID_MSODRAWINGGROUP:     RREC_MSODRAWINGGROUP;

              BIFFRECID_SST:                 RREC_SST;

              BIFFRECID_EXTSST:              RREC_EXTSST;

              // Sheet prefix

              BIFFRECID_CALCMODE:            RREC_CALCMODE;

              BIFFRECID_CALCCOUNT:           RREC_CALCCOUNT;

              BIFFRECID_REFMODE:             RREC_REFMODE;

              BIFFRECID_ITERATION:           RREC_ITERATION;

              BIFFRECID_DELTA:               RREC_DELTA;

              BIFFRECID_SAVERECALC:          RREC_SAVERECALC;

              BIFFRECID_PRINTHEADERS:        RREC_PRINTHEADERS;

              BIFFRECID_PRINTGRIDLINES:      RREC_PRINTGRIDLINES;

              BIFFRECID_GRIDSET:             RREC_GRIDSET;

              BIFFRECID_GUTS:                RREC_GUTS;

              BIFFRECID_DEFAULTROWHEIGHT:    RREC_DEFAULTROWHEIGHT;

              BIFFRECID_WSBOOL:              RREC_WSBOOL;

              BIFFRECID_HORIZONTALPAGEBREAKS:RREC_HORIZONTALPAGEBREAKS;

              BIFFRECID_VERTICALPAGEBREAKS:  RREC_VERTICALPAGEBREAKS;

              BIFFRECID_HEADER:              RREC_HEADER;

              BIFFRECID_FOOTER:              RREC_FOOTER;

              BIFFRECID_HCENTER:             RREC_HCENTER;

              BIFFRECID_VCENTER:             RREC_VCENTER;

              BIFFRECID_PLS:                 RREC_PLS;

              BIFFRECID_SETUP:               RREC_SETUP;

              BIFFRECID_LEFTMARGIN:          RREC_LEFTMARGIN;

              BIFFRECID_RIGHTMARGIN:         RREC_RIGHTMARGIN;

              BIFFRECID_TOPMARGIN:           RREC_TOPMARGIN;

              BIFFRECID_BOTTOMMARGIN:        RREC_BOTTOMMARGIN;

              BIFFRECID_DEFCOLWIDTH:         RREC_DEFCOLWIDTH;

              BIFFRECID_COLINFO:             RREC_COLINFO;

              BIFFRECID_DIMENSIONS_20,

              BIFFRECID_DIMENSIONS:          RREC_DIMENSIONS;

              // Sheet cells/data

              BIFFRECID_INDEX:               InsertRecord := False;

              BIFFRECID_DBCELL:              InsertRecord := False;

              BIFFRECID_INTEGER_20:          RREC_INTEGER_20;

              BIFFRECID_NUMBER_20:           RREC_NUMBER_20;

              BIFFRECID_LABEL_20:            RREC_LABEL_20;

              BIFFRECID_ROW:                 RREC_ROW;

              BIFFRECID_BLANK:               RREC_BLANK;

              BIFFRECID_BOOLERR:             RREC_BOOLERR;

              BIFFRECID_FORMULA:             RREC_FORMULA;

              BIFFRECID_FORMULA_30,

              BIFFRECID_FORMULA_40:          RREC_FORMULA_30;

              BIFFRECID_MULBLANK:            RREC_MULBLANK;

              BIFFRECID_RK,

              BIFFRECID_RK7:                 RREC_RK;

              BIFFRECID_MULRK:               RREC_MULRK;

              BIFFRECID_NUMBER:              RREC_NUMBER;

              BIFFRECID_LABELSST:            RREC_LABELSST;

              BIFFRECID_LABEL:               RREC_LABEL;

              BIFFRECID_RSTRING:             RREC_RSTRING;

              BIFFRECID_NOTE:                RREC_NOTE;

              // Sheet suffix

              BIFFRECID_MSODRAWING:          RREC_MSODRAWING;

              BIFFRECID_MSODRAWINGSELECTION: RREC_MSODRAWINGSELECTION;

              

              BIFFRECID_WINDOW2:             RREC_WINDOW2;

      {

              BIFFRECID_SCL:                 RREC_SCL;

      }

              BIFFRECID_PANE:                RREC_PANE;

              BIFFRECID_SELECTION:           RREC_SELECTION;

              BIFFRECID_MERGEDCELLS:         RREC_MERGEDCELLS;

              BIFFRECID_CONDFMT:             RREC_CONDFMT;

              BIFFRECID_HLINK:               RREC_HLINK;

              BIFFRECID_DVAL:                RREC_DVAL;

              BIFFRECID_USERBVIEW:           InsertRecord := False;

              BIFFRECID_USERSVIEWBEGIN:      begin

                InsertRecord := False;

                InUSERSVIEW := True;

              end;

              else begin

                if (Header.RecID and $FF) = BIFFRECID_BOF then begin

                  FXLSStream.ReadUnencrypted(PBuf^,Header.Length);

                  InsertRecord := False;

                  case PRecBOF8(PBuf).SubStreamType of

                    $0005: begin // Workbook globals

                      if Header.Length > 256 then

                        raise Exception.Create(ersInvalidBOFSize);

                      if PRecBOF8(PBuf).SubStreamType = $0010 then

                      FXLS.IsMac := (FXLS.Version >= xvExcel97) and ((PRecBOF8(PBuf).FileHistoryFlags and $00000010) = $00000010);

                      CurrRecs := FXLS.Records;

                      CurrRecs.UpdateDefault(Header,PBuf);

                    end;

                    $0006: begin // VB Module

                      raise Exception.Create('VB module unhandled');

                    end;

                    $0010: begin // Worksheet

                      Inc(FBoundsheetIndex);

                      Inc(FCurrSheet);

                      FXLS.Sheets.Add;

                      FXLS.Sheets[FCurrSheet].Name := ExcelStrToWideString(FBoundsheets[FBoundsheetIndex]);

                      FXLS.Sheets[FCurrSheet].HasDefaultRecords := True;

                      CurrRecs := FXLS.Sheets[FCurrSheet].Records;

                      CurrRecs.UpdateDefault(Header,PBuf);

                    end;

                    $0020: begin // Chart

                      Inc(FBoundsheetIndex);

                      FXLS.SheetCharts.LoadFromStream(FXLSStream,ExcelStrToWideString(FBoundsheets[FBoundsheetIndex]),PBuf,FXLS.Fonts,FBoundsheetIndex);

                      //raise Exception.Create('Chart unhandled');

                    end;

                    $0040: begin // BIFF4 Macro sheet

                      raise Exception.Create('BIFF4 Macro unhandled');

                    end;

                    $0100: begin // BIFF4 Workbook globals

                      raise Exception.Create('BIFF4 Workbook unhandled');

                    end;

                  end;

                end

              end;

            end;

            if InsertRecord then

              CurrRecs.AddRec(Header,PBuf);

            Inc(Count);

          end;

        except

          on E: Exception do

            raise Exception.CreateFmt('Error on reading record # %d, %.4X Offs: %.8X' + #13 + E.Message,[Count,Header.RecId,FXLSStream.Pos]);

        end;

        if Assigned(FXLS.OnProgress) then

          FXLS.OnProgress(Self,100);

      finally

        FXLSStream.Close;

        FreeMem(PBuf);

      end;

    end;

    // Sheet cells

    procedure TXLSReadII.RREC_BLANK;

    begin

      InsertRecord := False;

      with PRecBLANK(PBuf)^ do

        FXLS.Sheets[FCurrSheet].IntWriteBlank(Col,Row,FormatIndex);

    end;

    procedure TXLSReadII.RREC_ROW;

    begin

      InsertRecord := False;

      if XLS_DebugMode then begin

        if Assigned(FXLS.OnRowHeight) and (PRecROW(PBuf).Height <> 255) then

          FXLS.OnRowHeight(Self,PRecROW(PBuf).Row,PRecROW(PBuf).FormatIndex,PRecROW(PBuf).Height);

      end;

      

      if (PRecROW(PBuf).Options and $0080) = $0080 then

        FXLS.Sheets[FCurrSheet].Rows.SetRecROW(PRecROW(PBuf),PRecROW(PBuf).FormatIndex and $0FFF)

      else

        FXLS.Sheets[FCurrSheet].Rows.SetRecROW(PRecROW(PBuf),DEFAULT_FORMAT);

    end;

    procedure TXLSReadII.RREC_BOOLERR;

    begin

      InsertRecord := False;

      with PRecBOOLERR(PBuf)^ do begin

        if Error = 0 then

          FXLS.Sheets[FCurrSheet].IntWriteBoolean(Col,Row,FormatIndex,Boolean(BoolErr))

        else

          FXLS.Sheets[FCurrSheet].IntWriteError(Col,Row,FormatIndex,ErrorCodeToCellError(BoolErr));

      end;

    end;

    procedure TXLSReadII.ReadFormulaVal(Col,Row,FormatIndex: integer; Value: double; Formula: PByteArray; Len: integer);

    var

    //  ExtSz: integer;

      Fmla: PByteArray;

      S: string;

    begin

    //  ExtSz := 0;

      GetMem(Fmla,Len);

      try

        // Formula points to PBuf, which is overwritten by the next read of the file.

        Move(Formula^,Fmla^,Len);

        case TByte8Array(Value)[0] of

          0: begin

            Header.RecID := FXLSStream.PeekHeader;

            if (Header.RecID = BIFFRECID_SHRFMLA) or (Header.RecID = $04BC) then begin

              raise Exception.Create('Unxepected SHRFMLA');

    {

              ExtSz := SizeOf(TBIFFHeader) + Header.Length;

              FXLSStream.Read(PBuf^,Header.Length);

              FXLSStream.ReadHeader(Header);

    }

            end;

            if Header.RecID = BIFFRECID_STRING then begin

              FXLSStream.ReadHeader(Header);

              FXLSStream.Read(PBuf^,Header.Length);

              S := ByteStrToWideString(@PRecSTRING(PBuf).Data,PRecSTRING(PBuf).Len);

    {

              if ExtSz > 0 then begin

                Inc(ExtSz,SizeOf(TBIFFHeader) + Header.Length);

                FXLSStream.Seek2(-ExtSz,soFromCurrent);

              end;

    }

            end

            else if Header.RecID = BIFFRECID_STRING_20 then begin

              FXLSStream.ReadHeader(Header);

              FXLSStream.Read(PBuf^,Header.Length);

              S := ByteStrToWideString(@PRec2STRING(PBuf).Data,PRec2STRING(PBuf).Len);

            end

            else

              Exit;

            FXLS.Sheets[FCurrSheet].WriteRawStrFormula(Col,Row,FormatIndex,Fmla,Len,S);

          end;

          1: FXLS.Sheets[FCurrSheet].WriteRawBoolFormula(Col,Row,FormatIndex,Fmla,Len,Boolean(Integer(TByte8Array(Value)[2])));

          2: FXLS.Sheets[FCurrSheet].WriteRawErrFormula(Col,Row,FormatIndex,Fmla,Len,TByte8Array(Value)[2]);

          // Undocumented: the value 3 indicates that the result is an empty string,

          // and therefore there is no STRING record following the formula.

          3: FXLS.Sheets[FCurrSheet].WriteRawStrFormula(Col,Row,FormatIndex,Fmla,Len,'');

        end;

      finally

        FreeMem(Fmla);

      end;

    end;

    procedure TXLSReadII.RREC_FORMULA;

    var

      P: PByteArray;

    begin

      InsertRecord := False;

      if FXLS.Version  xvExcel30 then with PRec2FORMULA(PBuf)^ do begin

        if (TByte8Array(Value)[6] = $FF) and (TByte8Array(Value)[7] = $FF) then

          ReadFormulaVal(Col,Row,-1,Value,@Data,ParseLen)

        else

          FXLS.Sheets[FCurrSheet].WriteRawNumFormula(Col,Row,DEFAULT_FORMAT,@Data,ParseLen,Value);

      end

      else with PRecFORMULA(PBuf)^ do begin

        // ATTN: Under some circumstances (don't know why) the Shared Formula bit is set

        // in the Options field, even if the formula not is part of a shared formula group.

        // There is no SHRFMLA record following the FORMULA record.

        // The formula contaions a complete expression.

        // This seems to only occure in XLS-97 files.

        // Bug in Excel?

        // One way to check this is to se if the first PTG in the formula is ptgExp, = part of shared formula.

        if ((Options and $0008) = $0008) and (Data[0] = ptgExp) then begin

          Header.RecID := FXLSStream.PeekHeader;

          if (Header.RecID = BIFFRECID_SHRFMLA) or (Header.RecID = BIFFRECID_SHRFMLA_20) then begin

            FXLSStream.ReadHeader(Header);

            READ_SHRFMLA

          end;

          FixupSharedFormula(Col,Row);

        end

        else if Data[0] = ptgExp then begin

          if FXLSStream.PeekHeader = BIFFRECID_ARRAY then begin

            FXLSStream.ReadHeader(Header);

            GetMem(P,Header.Length);

            try

              FXLSStream.Read(P^,Header.Length);

              FXLS.Sheets[FCurrSheet].WriteRawArrayFormula(Col,Row,FormatIndex,@Data,ParseLen,Value,P,Header.Length);

            finally

              FreeMem(P);

            end;

            Exit;

          end;

        end;

        if (TByte8Array(Value)[0] in [$00,$01,$02,$03]) and (TByte8Array(Value)[6] = $FF) and (TByte8Array(Value)[7] = $FF) then

          ReadFormulaVal(Col,Row,FormatIndex,Value,@Data,ParseLen)

        else if ParseLen <> 0 then begin

          // This detects NAN values. A NAN number may cause an "Invalid Floating Point Operation" exception when used.

          if (TByte8Array(Value)[0] = $02) and (TByte8Array(Value)[6] = $FF) and (TByte8Array(Value)[7] = $FF) then

            FXLS.Sheets[FCurrSheet].WriteRawNumFormula(Col,Row,FormatIndex,@Data,ParseLen,0)

          else

            FXLS.Sheets[FCurrSheet].WriteRawNumFormula(Col,Row,FormatIndex,@Data,ParseLen,Value);

        end;

      end;

    end;

    procedure TXLSReadII.RREC_FORMULA_30;

    begin

      InsertRecord := False;

      with PRecFORMULA3(PBuf)^ do begin

        FXLS.Sheets[FCurrSheet].WriteRawNumFormula(Col,Row,FormatIndex,@Data,ParseLen,Value);

        if (TByte8Array(Value)[6] = $FF) and (TByte8Array(Value)[7] = $FF) then

          ReadFormulaVal(Col,Row,FormatIndex,Value,@Data,ParseLen);

      end;

    end;

    procedure TXLSReadII.RREC_NUMBER;

    begin

      InsertRecord := False;

      with PRecNUMBER(PBuf)^ do

        FXLS.Sheets[FCurrSheet].IntWriteNumber(Col,Row,FormatIndex,Value);

    end;

    procedure TXLSReadII.RREC_INTEGER_20;

    begin

      InsertRecord := False;

      with PRec2INTEGER(PBuf)^ do

        FXLS.Sheets[FCurrSheet].IntWriteNumber(Col,Row,DEFAULT_FORMAT,Value);

    end;

    procedure TXLSReadII.RREC_LABEL_20;

    var

      S: string;

    begin

      InsertRecord := False;

      with PRec2LABEL(PBuf)^ do begin

        SetLength(S,Len);

        Move(Data,Pointer(S)^,Len);

        FXLS.Sheets[FCurrSheet].IntWriteSSTString(Col,Row,DEFAULT_FORMAT,S);

      end;

    end;

    procedure TXLSReadII.RREC_NUMBER_20;

    begin

      InsertRecord := False;

      with PRec2NUMBER(PBuf)^ do

        FXLS.Sheets[FCurrSheet].IntWriteNumber(Col,Row,DEFAULT_FORMAT,Value);

    end;

    procedure TXLSReadII.RREC_LABELSST;

    begin

      InsertRecord := False;

      with PRecLABELSST(PBuf)^ do

        FXLS.Sheets[FCurrSheet].IntWriteSSTStringIndex(Col,Row,FormatIndex,SSTIndex);

    end;

    procedure TXLSReadII.RREC_LABEL;

    var

      S: string;

      WS: WideString;

    begin

      InsertRecord := False;

      with PRecLABEL(PBuf)^ do begin

        if (Len > 0) and (Data[0] = 1) then begin

          SetLength(WS,Len);

          Move(Data,Pointer(S)^,Len * 2);

          FXLS.Sheets[FCurrSheet].IntWriteSSTString(Col,Row,FormatIndex,WS);

        end

        else if (Len > 0) and (Data[0] = 0) then begin

          SetLength(S,Len);

          Move(Data,Pointer(S)^,Len);

          FXLS.Sheets[FCurrSheet].IntWriteSSTString(Col,Row,FormatIndex,S);

        end

        else begin

          SetLength(S,Len);

          Move(Data,Pointer(S)^,Len);

          FXLS.Sheets[FCurrSheet].IntWriteSSTString(Col,Row,FormatIndex,S);

        end;

      end;

    end;

    procedure TXLSReadII.RREC_RSTRING;

    var

      S: string;

    begin

      InsertRecord := False;

      with PRecLABEL(PBuf)^ do begin

        SetLength(S,Len);

        Move(Data,Pointer(S)^,Len);

        FXLS.Sheets[FCurrSheet].IntWriteSSTString(Col,Row,FormatIndex,S);

      end;

    end;

    procedure TXLSReadII.RREC_MULBLANK;

    var

      i: integer;

    begin

      InsertRecord := False;

      with PRecMULBLANK(PBuf)^ do begin

        for i := 0 to (Header.Length - 6) div 2 - 1 do

          FXLS.Sheets[FCurrSheet].IntWriteBlank(Col1 + i,Row,FormatIndexes[i]);

      end;

    end;

    procedure TXLSReadII.RREC_RK;

    begin

      InsertRecord := False;

      with PRecRK(PBuf)^ do

        FXLS.Sheets[FCurrSheet].IntWriteNumber(Col,Row,FormatIndex,DecodeRK(Value));

    end;

    procedure TXLSReadII.RREC_MULRK;

    var

      i: integer;

    begin

      InsertRecord := False;

      with PRecMULRK(PBuf)^ do begin

        for i := 0 to (Header.Length - 6) div 6 - 1 do

          FXLS.Sheets[FCurrSheet].IntWriteNumber(Col1 + i,Row,RKs[i].FormatIndex,DecodeRK(RKs[i].Value));

      end;

    end;

    procedure TXLSReadII.FixupSharedFormula(ACol,ARow: integer);

    var

      i: integer;

    begin

      // ATTN: Ranges of shared formulas may overlap. The last one written seems

      // to be the correct, therefore all shared formulas has to be searched.

      for i := 0 to High(FSharedFormulas) do begin

        with FSharedFormulas[i] do begin

          if (ACol >= Col1) and (ACol = Col2) and (ARow >= Row1) and (ARow = Row2) then begin

            Move(Formula^,PRecFORMULA(PBuf).Data,Len);

            PRecFORMULA(PBuf).ParseLen := Len;

            ConvertShrFmla(FXLS.Version = xvExcel97,@PRecFORMULA(PBuf).Data,PRecFORMULA(PBuf).ParseLen,ACol,ARow);

            Break;

          end;

        end;

      end;

    end;

    procedure TXLSReadII.READ_SHRFMLA;

    var

      i: integer;

    begin

      // ATTN: If Excel saves a SHRFMLA where some cells have been deleted,

      // (Ex: If you have 10 formulas in a row, saves it, open the sheet again,

      // deletes 4 of them and saves it again) then may the deleted formulas

      // still be saved in the SHRFMLA record!

      // The only way to check this is to look for the corresponding FORMULA

      // records. There is only FORMULA records for formulas that exsists on

      // the sheet. I think :-)

      SetLength(FSharedFormulas,Length(FSharedFormulas) + 1);

      i := High(FSharedFormulas);

      FXLSStream.Read(FSharedFormulas[i],6);

      FXLSStream.Read(FSharedFormulas[i].Len,2); // Reserved data

      FXLSStream.Read(FSharedFormulas[i].Len,2);

      GetMem(FSharedFormulas[i].Formula,FSharedFormulas[i].Len);

      FXLSStream.Read(FSharedFormulas[i].Formula^,FSharedFormulas[i].Len);

    end;

    procedure TXLSReadII.RREC_NOTE;

    begin

      InsertRecord := False;

      TRecordStorageSheet(CurrRecs).UpdateInternal(INTERNAL_SUFFIXDATA);

      with PRecNOTE(PBuf)^ do

        FXLS.Sheets[FCurrSheet].EscherDrawing.SetNoteData(Col,Row,Options,ObjId,ByteStrToWideString(PByteArray(@AuthorName),AuthorNameLen));

    end;

    procedure TXLSReadII.RREC_1904;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_ADDMENU;

    begin

      // Not used

    end;

    procedure TXLSReadII.RREC_BACKUP;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_BOOKBOOL;

    begin

      CurrRecs.UpdateDefault(Header,PBuf);

      InsertRecord := False;

      TRecordStorageGlobals(CurrRecs).UpdateInternal(INTERNAL_FORMATS);

    end;

    procedure TXLSReadII.RREC_PALETTE;

    var

      i: integer;

    begin

      if PRecPALETTE(PBuf).Count > (Length(ExcelColorPalette) - 8) then

        PRecPALETTE(PBuf).Count := Length(ExcelColorPalette) - 8;

      for i := 0 to PRecPALETTE(PBuf).Count - 1 do

        ExcelColorPalette[i + 8] := PRecPALETTE(PBuf).Color[i];

    end;

    procedure TXLSReadII.RREC_BOUNDSHEET;

    var

      S: string;

    begin

      TRecordStorageGlobals(CurrRecs).UpdateInternal(INTERNAL_BOUNDSHEETS);

      InsertRecord := False;

      if FXLS.Version  xvExcel97 then with PRecBOUNDSHEET7(PBuf)^ do begin

        SetLength(S,NameLen);

        Move(Name,Pointer(S)^,NameLen);

      end

      else with PRecBOUNDSHEET8(PBuf)^ do begin

        if Name[0] = 1 then begin

          SetLength(S,((NameLen * 2) and $00FF) + 1);

          Move(Name[0],Pointer(S)^,((NameLen * 2) and $00FF) + 1)

        end

        else begin

          SetLength(S,(NameLen and $00FF) + 1);

          Move(Name[0],Pointer(S)^,(NameLen and $00FF) + 1);

        end;

      end;

      FBoundsheets.AddObject(S,TObject(CurrRecs.Count - 1));

    end;

    procedure TXLSReadII.RREC_CALCCOUNT;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_CALCMODE;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_CODEPAGE;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_COLINFO;

    {

    var

      Col,MaxCol: integer;

    }

    begin

      TRecordStorageSheet(CurrRecs).UpdateInternal(INTERNAL_COLINFO);

      InsertRecord := False;

      FXLS.Sheets[FCurrSheet].Columns.SetRecCOLINFO(PRecCOLINFO(PBuf));

    {

      MaxCol := PRecCOLINFO(PBuf).Col2;

      if PRecCOLINFO(PBuf).Col2 > 255 then

        MaxCol := 255;

      if Assigned(FXLS.OnColWidth) then begin

        for Col := PRecCOLINFO(PBuf).Col1 to MaxCol do

          FXLS.OnColWidth(Self,Col,PRecCOLINFO(PBuf).FormatIndex,PRecCOLINFO(PBuf).Width);

      end;

    }

    end;

    procedure TXLSReadII.RREC_COUNTRY;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_RECALCID;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_DEFAULTROWHEIGHT;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_DEFCOLWIDTH;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_DELMENU;

    begin

      // Not used.

    end;

    procedure TXLSReadII.RREC_DELTA;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_DIMENSIONS;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_DSF;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_FNGROUPCOUNT;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_EOF;

    begin

      // This shall never happens.

      raise Exception.Create(ersEOFUnexpected);

    end;

    procedure TXLSReadII.RREC_NAME;

    begin

      case FXLS.Version of

        xvExcel97: begin

          TRecordStorageGlobals(CurrRecs).UpdateInternal(INTERNAL_NAMES);

          FXLS.InternalNames.SetNAME(PRecNAME(PBuf));

          InsertRecord := False;

        end;

      end;

    end;

    procedure TXLSReadII.RREC_SUPBOOK;

    begin

      case FXLS.Version of

        xvExcel97: begin

          TRecordStorageGlobals(CurrRecs).UpdateInternal(INTERNAL_NAMES);

          InsertRecord := False;

          FXLS.FormulaHandler.ExternalNames.SetSUPBOOK(PRecSUPBOOK(PBuf));

        end;

      end;

    end;

    procedure TXLSReadII.RREC_EXTERNNAME;

    begin

      case FXLS.Version of

        xvExcel97: begin

          TRecordStorageGlobals(CurrRecs).UpdateInternal(INTERNAL_NAMES);

          InsertRecord := False;

          FXLS.FormulaHandler.ExternalNames.SetEXTERNNAME(PRecEXTERNNAME8(PBuf));

        end;

      end;

    end;

    procedure TXLSReadII.RREC_XCT;

    var

      i,Count,Index: integer;

    begin

      InsertRecord := False;

      Count := PRecXCT(PBuf).CRNCount;

      if Count = $FFFF then

        Count := 1;

      Index := PRecXCT(PBuf).SheetIndex;

      for i := 0 to Count - 1 do begin

        if (FXLSStream.ReadHeader(Header) <> SizeOf(TBIFFHeader)) or (Header.RecID <> BIFFRECID_CRN) then

          raise Exception.Create('CRN record missing');

        FXLSStream.Read(PBuf^,Header.Length);

        FXLS.FormulaHandler.ExternalNames.SetCRN(Index,PRecCRN(PBuf),Header.Length);

      end;

    end;

    procedure TXLSReadII.RREC_EXTERNCOUNT;

    begin

    //  if FXLS.Version = xvExcel97 then

    //    FXLS.NameDefs.ExternCount := PWord(PBuf)^;

    end;

    procedure TXLSReadII.RREC_EXTERNSHEET;

    begin

      case FXLS.Version of

        xvExcel97: begin

          TRecordStorageGlobals(CurrRecs).UpdateInternal(INTERNAL_NAMES);

          InsertRecord := False;

          FXLS.FormulaHandler.ExternalNames.SetEXTERNSHEET(PBuf);

        end;

        xvExcel50: begin

        end;

      end;

    end;

    procedure TXLSReadII.RREC_FONT;

    begin

      InsertRecord := False;

      with FXLS.Fonts.Add do begin

        CharSet := PRecFONT(PBuf).CharSet;

        Family := PRecFONT(PBuf).Family;

        if PRecFONT(PBuf).ColorIndex > $00FF then

          Color := xcBlack

        else

          Color := TExcelColor(PRecFONT(PBuf).ColorIndex);

        Name := ByteStrToWideString(@PRecFONT(PBuf).Name,PRecFONT(PBuf).NameLen);

        Size20 := PRecFONT(PBuf).Height;

        Style := [];

        if PRecFONT(PBuf).Bold >= $02BC then

          Style := Style + [xfsBold];

        Underline := TXUnderline(PRecFONT(PBuf).Underline);

        if (PRecFONT(PBuf).Attributes and $02) = $02 then

          Style := Style + [xfsItalic];

        if (PRecFONT(PBuf).Attributes and $08) = $08 then

          Style := Style + [xfsStrikeout];

        // Font #4 does not exsists (and is not stored in the XLS file).

        if FXLS.Fonts.Count = 4 then

          FXLS.Fonts.Add;

      end;

    end;

    procedure TXLSReadII.RREC_HEADER;

    begin

      TRecordStorageSheet(CurrRecs).UpdateInternal(INTERNAL_HEADER);

      if FXLS.Version  xvExcel97 then begin

        Move(PBuf[1],PBuf[3],Header.Length - 1);

        PBuf[1] := 0;

        PBuf[2] := 0;

      end

      else if Header.Length > 0 then

        FXLS.Sheets[FCurrSheet].PrintSettings.Header := ByteStrToWideString(@PBuf[2],PWordArray(PBuf)[0])

      else

        FXLS.Sheets[FCurrSheet].PrintSettings.Header := '';

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_FOOTER;

    begin

      TRecordStorageSheet(CurrRecs).UpdateInternal(INTERNAL_HEADER);

      if FXLS.Version  xvExcel97 then begin

        Move(PBuf[1],PBuf[3],Header.Length - 1);

        PBuf[1] := 0;

        PBuf[2] := 0;

      end

      else if Header.Length > 0 then

        FXLS.Sheets[FCurrSheet].PrintSettings.Footer := ByteStrToWideString(@PBuf[2],PWordArray(PBuf)[0])

      else

        FXLS.Sheets[FCurrSheet].PrintSettings.Footer := '';

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_FORMAT;

    begin

      InsertRecord := False;

      if FXLS.Version  xvExcel97 then begin

        with PRecFORMAT7(PBuf)^ do

          FXLS.AddNumberFormat(ByteStrToWideString(@Data,Len),Index);

      end

      else begin

        with PRecFORMAT8(PBuf)^ do

          FXLS.AddNumberFormat(ByteStrToWideString(@Data,Len),Index);

      end;

    end;

    procedure TXLSReadII.RREC_GRIDSET;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_GUTS;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_HCENTER;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_HIDEOBJ;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_HLINK;

    begin

      if FXLS.Version  xvExcel97 then

        Exit;

      FXLS.Sheets[FCurrSheet].Hyperlinks.LoadFromStream(FXLSStream,Header.Length,PBuf);

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_FILEPASS;

    var

      S: WideString;

    begin

      if PRecFILEPASS(PBuf).Options = 0 then

        raise Exception.Create('File encrypted with non-standard key. French?');

      if PRecFILEPASS(PBuf).Options <> 1 then

        raise Exception.Create('Can not read file, unknown type of encryption.');

      if not Assigned(FXLS.OnPassword) then

        raise Exception.Create('File is encrypted. Password required.');

      S := '';

      FXLS.OnPassword(FXLS,S);

      if S = '' then

        raise Exception.Create('Password is missing.');

      if not FXLSStream.SetReadDecrypt(PRecFILEPASS(PBuf),S) then

        raise Exception.Create('Invalid password');

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_INTERFACEEND;

    begin

      // Not used.

    end;

    procedure TXLSReadII.RREC_INTERFACEHDR;

    begin

      // Not used.

    end;

    procedure TXLSReadII.RREC_ITERATION;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_MERGEDCELLS;

    var

      i,Count: integer;

    begin

      TRecordStorageSheet(CurrRecs).UpdateInternal(INTERNAL_SUFFIXDATA);

      InsertRecord := False;

      Count := PRecMERGEDCELLS(PBuf).Count;

      for i := 0 to Count - 1 do begin

        with TMergedCell(FXLS.Sheets[FCurrSheet].MergedCells.Add) do begin

          Row1 := PRecMERGEDCELLS(PBuf).Cells[i].Row1;

          Row2 := PRecMERGEDCELLS(PBuf).Cells[i].Row2;

          Col1 := PRecMERGEDCELLS(PBuf).Cells[i].Col1;

          Col2 := PRecMERGEDCELLS(PBuf).Cells[i].Col2;

        end;

      end;

    end;

    procedure TXLSReadII.RREC_CONDFMT;

    begin

      InsertRecord := False;

      FXLS.Sheets[FCurrSheet].ConditionalFormats.LoadFromStream(FXLSStream,PBuf);

    end;

    procedure TXLSReadII.RREC_MSODRAWING;

    begin

      TRecordStorageSheet(CurrRecs).UpdateInternal(INTERNAL_SUFFIXDATA);

      FXLS.Sheets[FCurrSheet].EscherDrawing.LoadFromStream(FXLSStream,PBuf);

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_MSODRAWINGGROUP;

    begin

      InsertRecord := False;

      TRecordStorageGlobals(CurrRecs).UpdateInternal(INTERNAL_MSODRWGRP);

      FXLSStream.BeginCONTINUERead;

      try

        FXLS.MSOPictures.LoadFromStream(FXLSStream,PBuf);

      finally

        FXLSStream.EndCONTINUERead;

      end;

    end;

    procedure TXLSReadII.RREC_MSODRAWINGSELECTION;

    begin

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_PASSWORD;

    begin

      // Silly password for not encrypted sheets.

      // password protected

    //  InsertRecord := False;

    //  CurrRecs.UpdateDefault(Header,PBuf);

    {

      if PWord(PBuf)^ <> 0 then

        raise Exception.Create(ersPasswordProtect);

    }

    end;

    procedure TXLSReadII.RREC_PLS;

    begin

    //  InsertRecord := False;

    //  CurrRecs.AddDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_PRECISION;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_PRINTGRIDLINES;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_PRINTHEADERS;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_PROT4REV;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_PROT4REVPASS;

    begin

    end;

    procedure TXLSReadII.RREC_PROTECT;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_REFMODE;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_REFRESHALL;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_SAVERECALC;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_SELECTION;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_DVAL;

    begin

      FXLS.Sheets[FCurrSheet].Validations.LoadFromStream(FXLSStream,PBuf);

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_BOTTOMMARGIN;

    begin

      TRecordStorageSheet(CurrRecs).UpdateInternal(INTERNAL_MARGINS);

      FXLS.Sheets[FCurrSheet].PrintSettings.MarginBottom := PRecMARGIN(PBuf).Value;

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_LEFTMARGIN;

    begin

      TRecordStorageSheet(CurrRecs).UpdateInternal(INTERNAL_MARGINS);

      FXLS.Sheets[FCurrSheet].PrintSettings.MarginLeft := PRecMARGIN(PBuf).Value;

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_RIGHTMARGIN;

    begin

      TRecordStorageSheet(CurrRecs).UpdateInternal(INTERNAL_MARGINS);

      FXLS.Sheets[FCurrSheet].PrintSettings.MarginRight := PRecMARGIN(PBuf).Value;

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_TOPMARGIN;

    begin

      TRecordStorageSheet(CurrRecs).UpdateInternal(INTERNAL_MARGINS);

      FXLS.Sheets[FCurrSheet].PrintSettings.MarginTop := PRecMARGIN(PBuf).Value;

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_SETUP;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_SST;

    begin

      TRecordStorageGlobals(CurrRecs).UpdateInternal(INTERNAL_SST);

      InsertRecord := False;

    //  FXLSStream.Seek2(-(SizeOf(TBIFFHeader) + Header.Length),soFromCurrent);

      FXLS.Sheets.ReadSST(FXLSStream,Header.Length);

    end;

    procedure TXLSReadII.RREC_EXTSST;

    begin

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_STYLE;

    begin

      // Only save Built-in styles.

    {

      if (PRecSTYLE(PBuf).FormatIndex and $8000) = $8000 then

        FXLS.Styles.Add(PRecSTYLE(PBuf));

    }

    end;

    procedure TXLSReadII.RREC_USESELFS;

    begin

      // Not used.

    end;

    procedure TXLSReadII.RREC_VCENTER;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_WINDOW1;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_WINDOW2;

    begin

      if FXLS.Version = xvExcel50 then begin

        PRecWINDOW2_8(PBuf).Zoom := 0;

        PRecWINDOW2_8(PBuf).ZoomPreview := 0;

        PRecWINDOW2_8(PBuf).Reserved := 0;

        Header.Length := SizeOf(TRecWINDOW2_8);

      end;

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_SCL;

    begin

      FXLS.Sheets[FCurrSheet].Zoom := Round((PRecSCL(PBuf).Numerator / PRecSCL(PBuf).Denominator) * 100);

    end;

    procedure TXLSReadII.RREC_PANE;

    begin

      InsertRecord := False;

      with PRecPANE(PBuf)^ do begin

        FXLS.Sheets[FCurrSheet].Pane.ActivePane := PaneNumber;

        FXLS.Sheets[FCurrSheet].Pane.SplitColX := X;

        FXLS.Sheets[FCurrSheet].Pane.SplitRowY := Y;

        FXLS.Sheets[FCurrSheet].Pane.LeftCol := LeftCol;

        FXLS.Sheets[FCurrSheet].Pane.TopRow := TopRow;

        if FXLS.Sheets[FCurrSheet].Pane.PaneType = ptNone then

          FXLS.Sheets[FCurrSheet].Pane.PaneType := ptSplit;

        while FXLSStream.PeekHeader = BIFFRECID_SELECTION do begin

          FXLSStream.ReadHeader(Header);

          FXLSStream.Read(PBuf^,Header.Length);

          FXLS.Sheets[FCurrSheet].Pane.Selections.AddRec(Header,PBuf);

        end;

      end;

    end;

    procedure TXLSReadII.RREC_WINDOWPROTECT;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_WRITEACCESS;

    begin

      InsertRecord := False;

      if FXLS.Version  xvExcel97 then begin

        Move(PBuf[1],PBuf[3],Header.Length - 2);

        PBuf[1] := 0;

        PBuf[2] := 0;

      end;

      if Header.Length  112 then begin

        FillChar(PBuf[Header.Length],112 - Header.Length,' ');

        Header.Length := 112;

      end;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_WSBOOL;

    begin

      InsertRecord := False;

      CurrRecs.UpdateDefault(Header,PBuf);

    end;

    procedure TXLSReadII.RREC_HORIZONTALPAGEBREAKS;

    var

      i: integer;

    begin

      TRecordStorageSheet(CurrRecs).UpdateInternal(INTERNAL_PAGEBREAKES);

      if FXLS.Version >= xvExcel97 then begin

        for i := 0 to PRecHORIZONTALPAGEBREAKS(PBuf).Count - 1 do begin

          with FXLS.Sheets[FCurrSheet].PrintSettings.HorizPagebreaks.Add do begin

            Row := PRecHORIZONTALPAGEBREAKS(PBuf).Breaks[i].Val1 - 1;

            Col1 := PRecHORIZONTALPAGEBREAKS(PBuf).Breaks[i].Val2 - 1;

            Col2 := PRecHORIZONTALPAGEBREAKS(PBuf).Breaks[i].Val3 - 1;

          end;

        end;

      end

      else if FXLS.Version = xvExcel50 then begin

        for i := 1 to PWordArray(PBuf)[0] - 1 do begin

          with FXLS.Sheets[FCurrSheet].PrintSettings.HorizPagebreaks.Add do begin

            Row := PWordArray(PBuf)[i] - 1;

            Col1 := 0;

            Col2 := 255;

          end;

        end;

      end;

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_VERTICALPAGEBREAKS;

    var

      i: integer;

    begin

      TRecordStorageSheet(CurrRecs).UpdateInternal(INTERNAL_PAGEBREAKES);

      if FXLS.Version >= xvExcel97 then begin

        for i := 0 to PRecVERTICALPAGEBREAKS(PBuf).Count - 1 do begin

          with FXLS.Sheets[FCurrSheet].PrintSettings.VertPagebreaks.Add do begin

            Col := PRecVERTICALPAGEBREAKS(PBuf).Breaks[i].Val1 - 1;

            Row1 := PRecVERTICALPAGEBREAKS(PBuf).Breaks[i].Val2 - 1;

            Row2 := PRecVERTICALPAGEBREAKS(PBuf).Breaks[i].Val3 - 1;

          end;

        end;

      end

      else if FXLS.Version = xvExcel50 then begin

        for i := 1 to PWordArray(PBuf)[0] - 1 do begin

          with FXLS.Sheets[FCurrSheet].PrintSettings.VertPagebreaks.Add do begin

            Col := PWordArray(PBuf)[i] - 1;

            Row1 := 0;

            Row2 := MAXROW;

          end;

        end;

      end;

      InsertRecord := False;

    end;

    procedure TXLSReadII.RREC_XF;

    procedure ReadXF30;

    begin

      with FXLS.Formats.Add do begin

    //    Font := FXLS.Fonts[PRecXF3(PBuf).FontIndex];

    //    FontIndex := PRecXF3(PBuf).FontIndex;

      end;

    end;

    begin

      InsertRecord := False;

      if FXLS.Version >= xvExcel97 then

        FXLS.Formats.Add.FromXF8(PBuf)

      else if FXLS.Version >= xvExcel50 then

        FXLS.Formats.Add.FromXF7(PBuf)

      else if FXLS.Version >= xvExcel30 then

        ReadXF30;

    end;

    end.

  • 相关阅读:
    大约PCA算法学习总结
    内部硬盘的硬件结构和工作原理进行了详细解释
    DWZ使用注意事项
    cocos2d-x 在XML分析和数据存储
    HTML精确定位:scrollLeft,scrollWidth,clientWidth,offsetWidth完全详细的说明
    hdu 1114 Piggy-Bank
    getResources()方法
    人机博弈-吃跳棋游戏(三)代移动
    Oracle 11g client安装和配置。
    的微信公众号开发 图灵机器人接口允许调用自己的微通道成为一个智能机器人
  • 原文地址:https://www.cnblogs.com/zhangzhifeng/p/2547342.html
Copyright © 2011-2022 走看看