From 17a6cb61daaf5ec04f257eb0f32f02b12495701b Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Thu, 14 Aug 2014 15:47:13 +0000 Subject: [PATCH] fpspreadsheet: Add more details on DEFINEDNAME record to BIFFExplorer; add details on EXTERN* records; fix compilation issue with TIpHTMLPanel. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3483 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../reference/BIFFExplorer/beabout.lfm | 17 - .../reference/BIFFExplorer/beabout.pas | 14 +- .../reference/BIFFExplorer/bebiffgrid.pas | 689 +++++++++++------- .../reference/BIFFExplorer/bemain.lfm | 47 +- .../reference/BIFFExplorer/bemain.pas | 9 +- 5 files changed, 457 insertions(+), 319 deletions(-) diff --git a/components/fpspreadsheet/reference/BIFFExplorer/beabout.lfm b/components/fpspreadsheet/reference/BIFFExplorer/beabout.lfm index f386fc606..a86f5b52f 100644 --- a/components/fpspreadsheet/reference/BIFFExplorer/beabout.lfm +++ b/components/fpspreadsheet/reference/BIFFExplorer/beabout.lfm @@ -65,21 +65,4 @@ object AboutForm: TAboutForm Align = alTop Shape = bsTopLine end - object HTMLViewer: TIpHtmlPanel - Left = 0 - Height = 440 - Top = 72 - Width = 642 - Align = alClient - FixedTypeface = 'Courier New' - DefaultTypeFace = 'default' - DefaultFontSize = 9 - FlagErrors = False - PrintSettings.MarginLeft = 0.5 - PrintSettings.MarginTop = 0.5 - PrintSettings.MarginRight = 0.5 - PrintSettings.MarginBottom = 0.5 - TabOrder = 1 - OnHotClick = HTMLViewerHotClick - end end diff --git a/components/fpspreadsheet/reference/BIFFExplorer/beabout.pas b/components/fpspreadsheet/reference/BIFFExplorer/beabout.pas index d482482bf..5b23d7e5f 100644 --- a/components/fpspreadsheet/reference/BIFFExplorer/beabout.pas +++ b/components/fpspreadsheet/reference/BIFFExplorer/beabout.pas @@ -16,13 +16,13 @@ type Bevel1: TBevel; BtnClose: TButton; IconImage: TImage; - HTMLViewer: TIpHtmlPanel; LblTitle: TLabel; Panel1: TPanel; procedure FormCreate(Sender: TObject); procedure HTMLViewerHotClick(Sender: TObject); private { private declarations } + FHTMLViewer: TIpHtmlPanel; function CreateCredits: String; public { public declarations } @@ -101,6 +101,8 @@ begin )); EndBulletList; + AddEmptyLine; + EndDocument; Result := Lines.Text; @@ -127,13 +129,19 @@ begin ico.Free; end; - HTMLViewer.SetHTMLFromStr(CreateCredits); + FHTMLViewer := TIpHtmlPanel.Create(self); + FHTMLViewer.Parent := self; + FHTMLViewer.Align := alClient; + FHTMLViewer.DefaultFontSize := 9; + FHTMLViewer.OnHotClick := @HTMLViewerHotClick; + + FHTMLViewer.SetHTMLFromStr(CreateCredits); end; procedure TAboutForm.HTMLViewerHotClick(Sender: TObject); begin - OpenURL(HTMLViewer.HotURL); + OpenURL((Sender as TIpHtmlPanel).HotURL); end; diff --git a/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas b/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas index 7d165414e..42edfec63 100644 --- a/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas +++ b/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas @@ -30,6 +30,8 @@ type procedure ShowBottomMargin; procedure ShowCalcCount; procedure ShowCalcMode; + procedure ShowCellAddress; + procedure ShowCellAddressRange; procedure ShowClrtClient; procedure ShowCodePage; procedure ShowColInfo; @@ -45,6 +47,9 @@ type procedure ShowDSF; procedure ShowEOF; procedure ShowExcel9File; + procedure ShowExternalBook; + procedure ShowExternCount; + procedure ShowExternSheet; procedure ShowFileSharing; procedure ShowFnGroupCount; procedure ShowFont; @@ -128,6 +133,9 @@ uses fpsutils, beBIFFUtils; +const + ABS_REL: array[boolean] of string = ('abs', 'rel'); + constructor TBIFFGrid.Create(AOwner: TComponent); begin inherited Create(AOwner); @@ -270,6 +278,10 @@ begin ShowHeader; $0015: ShowFooter; + $0016: + ShowExternCount; + $0017: + ShowExternSheet; $0018, $0218: ShowDefinedName; $0019: @@ -370,6 +382,8 @@ begin ShowTabID; $0161: ShowDSF; + $01AE: + ShowExternalBook; $01AF: ShowProt4Rev; $01B7: @@ -683,6 +697,186 @@ begin end; +procedure TBIFFGrid.ShowCellAddress; +var + numBytes: Word; + b: Byte; + w: Word; + r,c: Integer; + s: String; +begin + numBytes := 2; + Move(FBuffer[FBufferIndex], w, numBytes); // row --> w + r := WordLEToN(w); + if FFormat = sfExcel8 then begin + numBytes := 2; + Move(FBuffer[FBufferIndex+2], w, numBytes); // column --w1 + c := WordLEToN(w); + if FCurrRow = Row then begin + FDetails.Add('RowIndex information:'#13); + FDetails.Add(Format('RowIndex = %d (%s)', [r, ABS_REL[c and $4000 <> 0]])); + end; + s := Format('%d ($%.4x)', [r, r]); + ShowInRow(FCurrRow, FBufferIndex, numbytes, s, 'Row index'); + if FCurrRow = Row then begin + FDetails.Add('ColIndex information:'#13); + FDetails.Add(Format('Bits 0-13: ColIndex = %d (%s)', [c and $3FFF, ABS_REL[c and $8000 <> 0]])); + if c and $4000 = 0 + then FDetails.Add('Bit 14=0: absolute row index') + else FDetails.Add('Bit 14=1: relative row index'); + if c and $8000 = 0 + then FDetails.Add('Bit 15=0: absolute column index') + else FDetails.Add('Bit 15=1: relative column index'); + end; + s := Format('%d ($%.4x)', [c, c]); + ShowInRow(FCurrRow, FBufferIndex, numBytes, s, 'Column index'); + end else begin + numbytes := 1; + Move(FBuffer[FBufferIndex+2], b, numBytes); + c := b; + if FCurrRow = Row then begin + FDetails.Add('RowIndex information:'#13); + FDetails.Add(Format('Bits 0-13: RowIndex = %d (%s)', [r and $3FFF, ABS_REL[r and $4000 <> 0]])); + if r and $4000 = 0 + then FDetails.Add('Bit 14=0: absolute row index') + else FDetails.Add('Bit 14=1: relative row index'); + if r and $8000 = 0 + then FDetails.Add('Bit 15=0: absolute column index') + else FDetails.Add('Bit 15=1: relative column index'); + end; + //s := Format('$%.4x (%d, %s)', [r, r and $3FFF, ABS_REL[r and $4000 <> 0]]); + s := Format('%d ($%.4x)', [r, r]); + ShowInRow(FCurrRow, FBufferIndex, 2, s, 'Row index'); + if FCurrRow = Row then begin + FDetails.Add('ColIndex information:'#13); + FDetails.Add(Format('ColIndex = %d (%s)', [c, ABS_REL[r and $8000 <> 0]])); + end; + //s := Format('$%.2x (%d, %s)', [c, c, ABS_REL[r and $8000 <> 0]]); + s := Format('%d ($%.4x)', [c, c]); + ShowInRow(FCurrRow, FBufferIndex, numBytes, s, 'Column index'); + end; +end; + + +procedure TBIFFGrid.ShowCellAddressRange; +var + numbytes: Word; + b: Byte; + w: Word; + r, c, r2, c2: Integer; + s: String; +begin + if FFormat = sfExcel8 then begin + numBytes := 2; + Move(FBuffer[FBufferIndex], w, numBytes); + r := WordLEToN(w); + if FCurrRow = Row then begin + FDetails.Add('RowIndex information:'#13); + FDetails.Add(Format('RowIndex = %d (%s)', [r, ABS_REL[c and $4000 <> 0]])); + end; + s := Format('%d ($%.4x)', [r, r]); + ShowInRow(FCurrRow, FBufferIndex, numbytes, s, 'First row index'); + + Move(FBuffer[FBufferIndex], w, numBytes); + r2 := WordLEToN(w); + if FCurrRow = Row then begin + FDetails.Add('RowIndex information:'#13); + FDetails.Add(Format('RowIndex = %d (%s)', [r2, ABS_REL[c and $4000 <> 0]])); + end; + s := Format('%d ($%.4x)', [r2, r2]); + ShowInRow(FCurrRow, FBufferIndex, numbytes, s, 'Last row index'); + + Move(FBuffer[FBufferIndex], w, numBytes); // column + c := WordLEToN(w); + Move(FBuffer[FBufferIndex+2], w, numBytes); + c2 := WordLEToN(w); + + if FCurrRow = Row then begin + FDetails.Add('ColIndex information:'#13); + FDetails.Add(Format('Bits 0-13: ColIndex = %d (%s)', [c and $3FFF, ABS_REL[c and $8000 <> 0]])); + if c and $4000 = 0 + then FDetails.Add('Bit 14=0: absolute row index') + else FDetails.Add('Bit 14=1: relative row index'); + if c and $8000 = 0 + then FDetails.Add('Bit 15=0: absolute column index') + else FDetails.Add('Bit 15=1: relative column index'); + end; + s := Format('%d ($%.4x)', [c, c]); + ShowInRow(FCurrRow, FBufferIndex, numBytes, s, 'First column index'); + + if FCurrRow = Row then + begin + FDetails.Add('ColIndex information:'#13); + FDetails.Add(Format('Bits 0-13: ColIndex = %d (%s)', [c2 and $3FFF, ABS_REL[c2 and $8000 <> 0]])); + if c2 and $4000 = 0 + then FDetails.Add('Bit 14=0: absolute row index') + else FDetails.Add('Bit 14=1: relative row index'); + if c2 and $8000 = 0 + then FDetails.Add('Bit 15=0: absolute column index') + else FDetails.Add('Bit 15=1: relative column index'); + end; + s := Format('%d ($%.4x)', [c2, c2]); + ShowInRow(FCurrRow, FBufferIndex, numBytes, s, 'Last column index'); + end + else + begin + numBytes := 2; + Move(FBuffer[FBufferIndex], w, numBytes); + r := WordLEToN(w); + Move(FBuffer[FBufferIndex+2], w, numBytes); + r2 := WordLEToN(w); + + numbytes := 1; + c := FBuffer[FBufferIndex+4]; + c2 := FBuffer[FBufferIndex+5]; + + if FCurrRow = Row then + begin + FDetails.Add('RowIndex information:'#13); + FDetails.Add(Format('Bits 0-13: RowIndex = %d (%s)', [r and $3FFF, ABS_REL[r and $4000 <> 0]])); + if r and $4000 = 0 + then FDetails.Add('Bit 14=0: absolute row index') + else FDetails.Add('Bit 14=1: relative row index'); + if r and $8000 = 0 + then FDetails.Add('Bit 15=0: absolute column index') + else FDetails.Add('Bit 15=1: relative column index'); + end; + s := Format('%d ($%.4x)', [r, r]); + ShowInRow(FCurrRow, FBufferIndex, 2, s, 'First row index'); + + if FCurrRow = Row then + begin + FDetails.Add('RowIndex information:'#13); + FDetails.Add(Format('Bits 0-13: RowIndex = %d (%s)', [r2 and $3FFF, ABS_REL[r2 and $4000 <> 0]])); + if r2 and $4000 = 0 + then FDetails.Add('Bit 14=0: absolute row index') + else FDetails.Add('Bit 14=1: relative row index'); + if r2 and $8000 = 0 + then FDetails.Add('Bit 15=0: absolute column index') + else FDetails.Add('Bit 15=1: relative column index'); + end; + s := Format('%d ($%.4x)', [r2, r2]); + ShowInRow(FCurrRow, FBufferIndex, 2, s, 'Last row index'); + + if FCurrRow = Row then + begin + FDetails.Add('ColIndex information:'#13); + FDetails.Add(Format('ColIndex = %d (%s)', [c, ABS_REL[r and $8000 <> 0]])); + end; + s := Format('%d ($%.4x)', [c, c]); + ShowInRow(FCurrRow, FBufferIndex, numBytes, s, 'First column index'); + + if FCurrRow = Row then + begin + FDetails.Add('ColIndex information:'#13); + FDetails.Add(Format('ColIndex = %d (%s)', [c2, ABS_REL[r2 and $8000 <> 0]])); + end; + s := Format('%d ($%.4x)', [c2, c2]); + ShowInRow(FCurrRow, FBufferIndex, numBytes, s, 'Last column index'); + end; +end; + + procedure TBIFFGrid.ShowClrtClient; var w: Word; @@ -888,10 +1082,18 @@ var widestr: WideString; s: String; macro: Boolean; + formulaSize: Word; + firstTokenBufIdx: Integer; + token: Byte; + r,c, r2,c2: Integer; begin - if FFormat = sfExcel2 then begin - RowCount := FixedRows + 7; + BeginUpdate; + RowCount := FixedRows + 1000; + // Brute force simplification because of unknown row count at this point + // Will be reduced at the end. + if FFormat = sfExcel2 then + begin numBytes := 1; b := FBuffer[FBufferIndex]; isFuncMacro := b and $02 <> 0; @@ -934,13 +1136,10 @@ begin b := FBuffer[FBufferIndex]; ShowInRow(FCurrRow, FBUfferIndex, numBytes, IntToStr(b), 'Size of the formula data'); - - ShowInRow(FCurrRow, FBufferIndex, 1, '', - 'Formula data follow...'); - end else + formulaSize := b; + end + else begin - RowCount := FixedRows + 12; - numBytes := 2; Move(FBuffer[FBufferIndex], w, numBytes); w := WordLEToN(w); @@ -1008,6 +1207,7 @@ begin w := WordLEToN(w); ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(w), 'Size of the formula data'); + formulaSize := w; numBytes := 2; Move(FBuffer[FBufferIndex], w, numBytes); @@ -1065,18 +1265,70 @@ begin Move(FBuffer[FBufferIndex + 1], wideStr[1], lenName*SizeOf(WideChar)); s := UTF8Encode(WideStringLEToN(wideStr)); end; -{ - numBytes := lenName * SizeOf(wideChar); - SetLength(wideStr, lenName); - Move(FBuffer[FBufferIndex], wideStr[1], numBytes); - } ShowInRow(FCurrRow, FBufferIndex, numbytes, s, 'Name (Unicode string without length field)'); end; - - ShowInRow(FCurrRow, FBufferIndex, 1, '', - 'Formula data follow...'); end; + + firstTokenBufIdx := FBufferIndex; + while FBufferIndex < firstTokenBufIdx + formulaSize do begin + token := FBuffer[FBufferIndex]; + numBytes := 1; + case token of + $3A, $3B, $5A, $5B, $7A, $7B: + begin + case token of + $3A: s := 'Token tRef3dR for "3D or external reference to a cell" (R = Reference)'; + $5A: s := 'Token tRef3dV for "3D or external reference to a cell" (V = Value)'; + $7A: s := 'Token tRef3dA for "3D or external reference to a cell" (A = Area)'; + $3B: s := 'Token tArea3dR for "3D or external reference to a cell range" (R = Reference)'; + $5B: s := 'Token tArea3dV for "3D or external reference to a cell range" (V = Value)'; + $7B: s := 'Token tArea3dA for "3D or external reference to a cell range" (A = Area)'; + end; + ShowInRow(FCurrRow, FBufferIndex, numbytes, Format('$%.2x', [token]), s); + + numbytes := 2; + Move(FBuffer[FBufferIndex], w, numBytes); + w := WordLEToN(w); + if FFormat = sfExcel5 then begin + if w and $8000 <> 0 then begin // negative value --> 3D reference + ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(SmallInt(w)), + '3D reference, 1-based index to EXTERNSHEET record'); + numBytes := 8; + ShowInRow(FCurrRow, FBufferIndex, numBytes, '', 'Not used'); + numBytes := 2; + Move(FBuffer[FBufferIndex], w, numBytes); + ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)), + 'Index to first referenced sheet ($FFFF = deleted sheet)'); + Move(FBuffer[FBufferIndex], w, numBytes); + ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)), + 'Index to last referenced sheet ($FFFF = deleted sheet)'); + end else + begin + ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(w), + 'External reference, 1-based index to EXTERNSHEET record'); + numBytes := 12; + ShowInRow(FCurrRow, FBufferIndex, numBytes, '', 'Not used'); + end; + end else + ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(w), + 'Index to REF entry in EXTERNSHEET record'); + + if token in [$3A, $5A, $7A] then + ShowCellAddress // Cell address + else + ShowCellAddressRange; // Cell range + end; + + else + numBytes := 1; + ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [token]), + '(unknown token)'); + end; // case + end; // while + + RowCount := FCurrRow; + EndUpdate(true); end; procedure TBIFFGrid.ShowDefRowHeight; @@ -1217,6 +1469,141 @@ begin end; +procedure TBIFFGrid.ShowExternalBook; +var + numBytes: Integer; + w: Word; + wideStr: WideString; + ansiStr: AnsiString; + s: String; + i, n: Integer; +begin + BeginUpdate; + RowCount := FixedRows + 1000; + + numBytes := 2; + Move(FBuffer[FBufferIndex], w, numBytes); + n := WordLEToN(w); + + ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(n), + 'Number of sheet names / number of sheets'); + + if Length(FBuffer) - FBufferIndex = 2 then begin + SetLength(ansiStr, 1); + Move(FBuffer[FBufferIndex], ansiStr[1], 1); + + ShowInRow(FCurrRow, FBufferIndex, numBytes, s, + '(relict of BIFF5)'); + end else begin + ExtractString(FBufferIndex, 2, true, s, numBytes); + if Row = FCurrRow then begin + FDetails.Add('Encoded URL without sheet name:'#13); + case s[1] of + #0: FDetails.Add('First character = #00: Reference relative to current sheet'); + #1: FDetails.Add('First character = #01: Encoded URL follows'); + #2: if FFormat = sfExcel8 then + FDetails.Add('First character = #02: Reference to a sheet in own document; sheet name follows') + else + FDetails.Add('First character = #02: Reference to the corrent sheet (nothing will follow)'); + #3: if FFormat = sfExcel5 then + FDetails.Add('First character = #03: Reference to a sheet in own document; sheet name follows') + else + FDetails.Add('First character = #03: not used'); + #4: if FFormat = sfExcel5 then + FDetails.ADd('First character = #03: Reference to the own workbook, sheet is unspecified (nothing will follow)') + else + FDetails.Add('First character = #03: not used'); + end; + end; + if s[1] in [#0, #1, #2, #3, #4] then Delete(s, 1, 1); + ShowInRow(FCurrRow, FBufferIndex, numBytes, s, + 'Encoded URL without sheet name (Unicode string, 16-bit string length)'); + + for i:=0 to n-1 do begin + ExtractString(FBufferIndex, 2, true, s, numBytes); + ShowInRow(FCurrRow, FBufferIndex, numBytes, s, + 'Sheet name (Unicode string with 16-bit string length)'); + end; + end; + + RowCount := FCurrRow; + EndUpdate(true); +end; + + +procedure TBIFFGrid.ShowExternCount; +var + numBytes: Integer; + w: Word; +begin + RowCount := FixedRows + 1; + numBytes := 2; + Move(FBuffer[FBufferIndex], w, numBytes); + ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)), + 'Number of following EXTERNSHEET records'); +end; + + +procedure TBIFFGrid.ShowExternSheet; +var + numBytes: Integer; + w: Word; + s: String; + nREF: Integer; + i: Integer; + len: Byte; + ansiStr: AnsiString; +begin + if FFormat <= sfExcel5 then begin + RowCount := FixedRows + 1; + len := FBuffer[0]; + if FBuffer[1] = $03 then inc(len); + numBytes := len*SizeOf(AnsiChar) + 1; + SetLength(ansiStr, len); + Move(FBuffer[1], ansiStr[1], len*SizeOf(AnsiChar)); + s := AnsiToUTF8(ansiStr); + if FCurrRow = Row then begin + FDetails.Add('Encoded document and sheet name:'#13); + if s[1] = #03 then begin + FDetails.Add('First character = $03: EXTERNSHEET stores a reference to one of the own sheets'); + FDetails.Add('Document name: ' + Copy(s, 2, Length(s))); + end else + if (s[1] = ':') and (Length(s) = 1) then begin + FDetails.Add('Special EXTERNSHEET record for an add-in function. EXTERNName record with the name of the function follows.'); + end else + FDetails.Add('Document name: ' + s); + end; + if s[1] = #03 then + Delete(s, 1, 1); + ShowInRow(FCurrRow, FBufferIndex, numBytes, s, + 'Encoded document and sheet name (Byte string, 8-bit string length)'); + end else begin + numBytes := 2; + Move(FBuffer[FBufferIndex], w, numBytes); + nREF := WordLEToN(w); + + RowCount := FixedRows + 1 + nREF*3; + + ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(nREF), + 'Number of following REF structures'); + + for i:=1 to nREF do begin + Move(FBuffer[FBufferIndex], w, numBytes); + ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)), + Format('REF #%d: Index to EXTERNALBOOK record', [i])); + + Move(FBuffer[FBufferIndex], w, numBytes); + ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)), + Format('REF #%d: Index to first sheet in EXTERNALBOOK sheet list', [i])); + + Move(FBuffer[FBufferIndex], w, numBytes); + ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)), + Format('REF #%d: Index to last sheet in EXTERNALBOOK sheet list', [i])); + end; + end; +end; + + procedure TBIFFGrid.ShowFileSharing; var numbytes: Integer; @@ -1537,8 +1924,6 @@ end; procedure TBIFFGrid.ShowFormula; -const - ABS_REL: array[boolean] of string = ('abs', 'rel'); var numBytes: Integer; b: Byte; @@ -1694,79 +2079,7 @@ begin end; end; end; - (* - if (FFormat > sfExcel2) then begin - if wordarr[3] <> $FFFF then begin - if FCurrRow = Row then begin - FDetails.Add('Formula result:'#13); - FDetails.Add(Format('Bytes 0-7: $%.15x --> IEEE 764 floating-point value, 64-bit double precision'#13+ - ' = %g', [q, dbl])); - end; - ShowInRow(FCurrRow, FBufferIndex, numBytes, FloatToStr(dbl), - 'Result of formula (IEEE 764 floating-point value, 64-bit double precision)'); - end else begin - case bytearr[0] of - 0: begin - if FCurrRow = Row then begin - FDetails.Add('Formula result:'#13); - FDetails.Add('Byte 0 = 0 --> Result is string, follows in STRING record'); - FDetails.Add('Byte 1-5: Not used'); - FDetails.Add('Byte 6&7: $FFFF --> no floating point number'); - end; - ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.16x', [q]), - 'Result is a string, follows in STRING record'); - end; - 1: begin - if FCurrRow = Row then begin - FDetails.Add('Formula result:'#13); - FDetails.Add('Byte 0 = 1 --> Result is BOOLEAN'); - FDetails.Add('Byte 1: Not used'); - if bytearr[2] = 0 - then FDetails.Add('Byte 2 = 0 --> FALSE') - else FDetails.Add('Byte 2 = 1 --> TRUE'); - FDetails.Add('Bytes 3-5: Not used'); - FDetails.Add('Bytes 6&7: $FFFF --> no floating point number'); - end; - ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.16x', [q]), - 'Result is BOOLEAN'); - end; - 2: begin - if FCurrRow = Row then begin - FDetails.Add('Formula result:'#13); - FDetails.Add('Byte 0 = 2 --> Result is an ERROR value'); - FDetails.Add('Byte 1: Not used'); - case bytearr[2] of - $00: FDetails.Add('Byte 2 = $00 --> #NULL! Intersection of two cell ranges is empty'); - $07: FDetails.Add('Byte 2 = $07 --> #DIV/0! Division by zero'); - $0F: FDetails.Add('Byte 2 = $0F --> #VALUE! Wrong type of operand'); - $17: FDetails.Add('Byte 2 = $17 --> #REF! Illegal or deleted cell reference'); - $1D: FDetails.Add('Byte 2 = $1D --> #NAME? Wrong function or range name'); - $24: FDetails.Add('Byte 2 = $24 --> #NUM! Value range overflow'); - $2A: FDetails.Add('Byte 2 = $2A --> #N/A Argument or function not available'); - end; - FDetails.Add('Bytes 6&7: $FFFF --> no floating point number'); - end; - ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.16x', [q]), - 'Result is an ERROR value'); - end; - 3: begin - if FCurrRow = Row then begin - FDetails.Add('Formula result:'#13); - FDetails.Add('Byte 0 = 3 --> Result is an empty cell, for example an empty string'); - FDetails.Add('Byte 1-5: Not used'); - FDetails.Add('Bytes 6&7: $FFFF --> no floating point number'); - end; - ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.16x', [q]), - 'Result is an EMPTY cell (empty string)'); - end; - end; - end; - end - else begin // Excel 2 - ShowInRow(FCurrRow, FBufferIndex, numBytes, FloatToStr(dbl), - 'Result of formula (IEEE 764 floating-point value, 64-bit double precision)'); - end; - *) + // Option flags if FFormat = sfExcel2 then begin numBytes := 1; @@ -1882,8 +2195,6 @@ begin 'Token "&" (concat)'); $09: ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [token]), 'Token "<" (less than)'); - $15: ShowInRow(FCurrRow, FBufferIndex, numbytes, Format('$%.2x', [token]), - 'Token "()" (operator in parenthesis)'); $0A: ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [token]), 'Token "<=" (less equal)'); $0B: ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [token]), @@ -1906,6 +2217,8 @@ begin 'Token "-" (unary minus)'); $14: ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [token]), 'Token "%" (percent)'); + $15: ShowInRow(FCurrRow, FBufferIndex, numbytes, Format('$%.2x', [token]), + 'Token "()" (operator in parenthesis)'); $16: ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [token]), 'Token "missing argument"'); $17: begin @@ -2022,56 +2335,7 @@ begin end; ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [token]), Format('Token tREF (Cell %s)', [s])); - numBytes := 2; - Move(FBuffer[FBufferIndex], w, numBytes); // row --> w - r := WordLEToN(w); - if FFormat = sfExcel8 then begin - numBytes := 2; - Move(FBuffer[FBufferIndex+2], w, numBytes); // column --w1 - c := WordLEToN(w); - if FCurrRow = Row then begin - FDetails.Add('RowIndex information:'#13); - FDetails.Add(Format('RowIndex = %d (%s)', [r, ABS_REL[c and $4000 <> 0]])); - end; - s := Format('%d ($%.4x)', [r, r]); - ShowInRow(FCurrRow, FBufferIndex, numbytes, s, 'Row index'); - if FCurrRow = Row then begin - FDetails.Add('ColIndex information:'#13); - FDetails.Add(Format('Bits 0-13: ColIndex = %d (%s)', [c and $3FFF, ABS_REL[c and $8000 <> 0]])); - if c and $4000 = 0 - then FDetails.Add('Bit 14=0: absolute row index') - else FDetails.Add('Bit 14=1: relative row index'); - if c and $8000 = 0 - then FDetails.Add('Bit 15=0: absolute column index') - else FDetails.Add('Bit 15=1: relative column index'); - end; - s := Format('%d ($%.4x)', [c, c]); - ShowInRow(FCurrRow, FBufferIndex, numBytes, s, 'Column index'); - end else begin - numbytes := 1; - Move(FBuffer[FBufferIndex+2], b, numBytes); - c := b; - if FCurrRow = Row then begin - FDetails.Add('RowIndex information:'#13); - FDetails.Add(Format('Bits 0-13: RowIndex = %d (%s)', [r and $3FFF, ABS_REL[r and $4000 <> 0]])); - if r and $4000 = 0 - then FDetails.Add('Bit 14=0: absolute row index') - else FDetails.Add('Bit 14=1: relative row index'); - if r and $8000 = 0 - then FDetails.Add('Bit 15=0: absolute column index') - else FDetails.Add('Bit 15=1: relative column index'); - end; - //s := Format('$%.4x (%d, %s)', [r, r and $3FFF, ABS_REL[r and $4000 <> 0]]); - s := Format('%d ($%.4x)', [r, r]); - ShowInRow(FCurrRow, FBufferIndex, 2, s, 'Row index'); - if FCurrRow = Row then begin - FDetails.Add('ColIndex information:'#13); - FDetails.Add(Format('ColIndex = %d (%s)', [c, ABS_REL[r and $8000 <> 0]])); - end; - //s := Format('$%.2x (%d, %s)', [c, c, ABS_REL[r and $8000 <> 0]]); - s := Format('%d ($%.4x)', [c, c]); - ShowInRow(FCurrRow, FBufferIndex, numBytes, s, 'Column index'); - end; + ShowCellAddress; end; $25, $45, $65: begin @@ -2082,138 +2346,7 @@ begin end; ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [token]), Format('Token tAREA (Cell range %s)', [s])); - - if FFormat = sfExcel8 then begin - numBytes := 2; - Move(FBuffer[FBufferIndex], w, numBytes); - r := WordLEToN(w); - if FCurrRow = Row then begin - FDetails.Add('RowIndex information:'#13); - FDetails.Add(Format('RowIndex = %d (%s)', [r, ABS_REL[c and $4000 <> 0]])); - end; - s := Format('%d ($%.4x)', [r, r]); - ShowInRow(FCurrRow, FBufferIndex, numbytes, s, 'First row index'); - - Move(FBuffer[FBufferIndex], w, numBytes); - r2 := WordLEToN(w); - if FCurrRow = Row then begin - FDetails.Add('RowIndex information:'#13); - FDetails.Add(Format('RowIndex = %d (%s)', [r2, ABS_REL[c and $4000 <> 0]])); - end; - s := Format('%d ($%.4x)', [r2, r2]); - ShowInRow(FCurrRow, FBufferIndex, numbytes, s, 'Last row index'); - - Move(FBuffer[FBufferIndex], w, numBytes); // column - c := WordLEToN(w); - Move(FBuffer[FBufferIndex+2], w, numBytes); - c2 := WordLEToN(w); - - if FCurrRow = Row then begin - FDetails.Add('ColIndex information:'#13); - FDetails.Add(Format('Bits 0-13: ColIndex = %d (%s)', [c and $3FFF, ABS_REL[c and $8000 <> 0]])); - if c and $4000 = 0 - then FDetails.Add('Bit 14=0: absolute row index') - else FDetails.Add('Bit 14=1: relative row index'); - if c and $8000 = 0 - then FDetails.Add('Bit 15=0: absolute column index') - else FDetails.Add('Bit 15=1: relative column index'); - end; - s := Format('%d ($%.4x)', [c, c]); - ShowInRow(FCurrRow, FBufferIndex, numBytes, s, 'First column index'); - - if FCurrRow = Row then begin - FDetails.Add('ColIndex information:'#13); - FDetails.Add(Format('Bits 0-13: ColIndex = %d (%s)', [c2 and $3FFF, ABS_REL[c2 and $8000 <> 0]])); - if c2 and $4000 = 0 - then FDetails.Add('Bit 14=0: absolute row index') - else FDetails.Add('Bit 14=1: relative row index'); - if c2 and $8000 = 0 - then FDetails.Add('Bit 15=0: absolute column index') - else FDetails.Add('Bit 15=1: relative column index'); - end; - s := Format('%d ($%.4x)', [c2, c2]); - ShowInRow(FCurrRow, FBufferIndex, numBytes, s, 'Last column index'); - - end else begin - - numBytes := 2; - Move(FBuffer[FBufferIndex], w, numBytes); - r := WordLEToN(w); - Move(FBuffer[FBufferIndex+2], w, numBytes); - r2 := WordLEToN(w); - - numbytes := 1; - c := FBuffer[FBufferIndex+4]; - c2 := FBuffer[FBufferIndex+5]; - - if FCurrRow = Row then begin - FDetails.Add('RowIndex information:'#13); - FDetails.Add(Format('Bits 0-13: RowIndex = %d (%s)', [r and $3FFF, ABS_REL[r and $4000 <> 0]])); - if r and $4000 = 0 - then FDetails.Add('Bit 14=0: absolute row index') - else FDetails.Add('Bit 14=1: relative row index'); - if r and $8000 = 0 - then FDetails.Add('Bit 15=0: absolute column index') - else FDetails.Add('Bit 15=1: relative column index'); - end; - s := Format('%d ($%.4x)', [r, r]); - ShowInRow(FCurrRow, FBufferIndex, 2, s, 'First row index'); - - if FCurrRow = Row then begin - FDetails.Add('RowIndex information:'#13); - FDetails.Add(Format('Bits 0-13: RowIndex = %d (%s)', [r2 and $3FFF, ABS_REL[r2 and $4000 <> 0]])); - if r2 and $4000 = 0 - then FDetails.Add('Bit 14=0: absolute row index') - else FDetails.Add('Bit 14=1: relative row index'); - if r2 and $8000 = 0 - then FDetails.Add('Bit 15=0: absolute column index') - else FDetails.Add('Bit 15=1: relative column index'); - end; - s := Format('%d ($%.4x)', [r2, r2]); - ShowInRow(FCurrRow, FBufferIndex, 2, s, 'Last row index'); - - if FCurrRow = Row then begin - FDetails.Add('ColIndex information:'#13); - FDetails.Add(Format('ColIndex = %d (%s)', [c, ABS_REL[r and $8000 <> 0]])); - end; - s := Format('%d ($%.4x)', [c, c]); - ShowInRow(FCurrRow, FBufferIndex, numBytes, s, 'First column index'); - - if FCurrRow = Row then begin - FDetails.Add('ColIndex information:'#13); - FDetails.Add(Format('ColIndex = %d (%s)', [c2, ABS_REL[r2 and $8000 <> 0]])); - end; - s := Format('%d ($%.4x)', [c2, c2]); - ShowInRow(FCurrRow, FBufferIndex, numBytes, s, 'Last column index'); - end; - { - if FFormat = sfExcel8 then begin - numBytes := 2; - Move(FBuffer[FBufferIndex+4], w, numBytes); - c := WordLEToN(w); - Move(FBuffer[FBufferIndex+6], w, numBytes); - c2 := WordLEToN(w); - s := Format('$%.4x (%d, %s)', [r, r, ABS_REL[c and $4000 <> 0]]); - ShowInRow(FCurrRow, FBufferIndex, 2, s, 'Index to first row'); - s := Format('$%.4x (%d, %s)', [r2, r2, ABS_REL[c2 and $4000 <> 0]]); - ShowInRow(FCurrRow, FBufferIndex, 2, s, 'Index to last row'); - s := Format('$%.4x (%d, %s)', [c, c and $3FFF, ABS_REL[c and $8000 <> 0]]); - ShowInRow(FCurrRow, FBufferIndex, 2, s, 'Index to first column'); - s := Format('$%.4x (%d, %s)', [c2, c2 and $3FFF, ABS_REL[c2 and $8000 <> 0]]); - ShowInRow(FCurrRow, FBufferIndex, 2, s, 'Index to last columns'); - end else begin - c := FBuffer[FBufferIndex+4]; - c2 := FBuffer[FBufferIndex+5]; - s := Format('$%.4x (%d, %s)', [r, r and $3FFF, ABS_REL[r and $4000 <> 0]]); - ShowInRow(FCurrRow, FBufferIndex, 2, s, 'Index to first row'); - s := Format('$%.4x (%d, %s)', [r2, r2 and $3FFF, ABS_REL[r2 and $4000 <> 0]]); - ShowInRow(FCurrRow, FBufferIndex, 2, s, 'Index to last row'); - s := Format('$%.2x (%d, %s)', [c, c, ABS_REL[r and $8000 <> 0]]); - ShowInRow(FCurrRow, FBufferIndex, 1, s, 'Index to first column'); - s := Format('$%.2x (%d, %s)', [c2, c2, ABS_REL[r2 and $8000 <> 0]]); - ShowInRow(FCurrRow, FBufferIndex, 1, s, 'Index to last column'); - end; - } + ShowCellAddressRange; end; else ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [token]), '(unknown)'); @@ -2222,7 +2355,6 @@ begin RowCount := FCurrRow; EndUpdate(true); - end; @@ -2363,6 +2495,11 @@ var numbytes: Integer; w: Word; begin + if FFormat < sfExcel8 then begin + RowCount := FixedRows; + exit; + end; + RowCount := FixedRows + 1; numbytes := 2; Move(FBuffer[FBufferIndex], w, numbytes); diff --git a/components/fpspreadsheet/reference/BIFFExplorer/bemain.lfm b/components/fpspreadsheet/reference/BIFFExplorer/bemain.lfm index 0311063a6..a4b1272d5 100644 --- a/components/fpspreadsheet/reference/BIFFExplorer/bemain.lfm +++ b/components/fpspreadsheet/reference/BIFFExplorer/bemain.lfm @@ -15,15 +15,18 @@ object MainForm: TMainForm LCLVersion = '1.3' object Splitter1: TSplitter Left = 419 - Height = 497 - Top = 26 + Height = 496 + Top = 27 Width = 5 end object ToolBar: TToolBar - Left = 0 - Height = 26 + Left = 4 + Height = 27 Top = 0 - Width = 1089 + Width = 1085 + AutoSize = True + BorderSpacing.Left = 4 + ButtonHeight = 25 Caption = 'ToolBar' Images = ImageList TabOrder = 1 @@ -54,17 +57,17 @@ object MainForm: TMainForm end object DetailPanel: TPanel Left = 424 - Height = 497 - Top = 26 + Height = 496 + Top = 27 Width = 665 Align = alClient BevelOuter = bvNone - ClientHeight = 497 + ClientHeight = 496 ClientWidth = 665 TabOrder = 2 object PageControl: TPageControl Left = 0 - Height = 497 + Height = 496 Top = 0 Width = 665 ActivePage = PgValues @@ -104,12 +107,12 @@ object MainForm: TMainForm end object PgValues: TTabSheet Caption = 'Values' - ClientHeight = 464 + ClientHeight = 463 ClientWidth = 657 object ValueGrid: TStringGrid Left = 0 Height = 158 - Top = 306 + Top = 305 Width = 657 Align = alBottom ColCount = 3 @@ -140,17 +143,17 @@ object MainForm: TMainForm end object HexPanel: TPanel Left = 0 - Height = 301 + Height = 300 Top = 0 Width = 657 Align = alClient Caption = 'HexPanel' - ClientHeight = 301 + ClientHeight = 300 ClientWidth = 657 TabOrder = 1 object HexGrid: TStringGrid Left = 1 - Height = 299 + Height = 298 Top = 1 Width = 390 Align = alClient @@ -238,7 +241,7 @@ object MainForm: TMainForm end object AlphaGrid: TStringGrid Left = 396 - Height = 299 + Height = 298 Top = 1 Width = 260 Align = alRight @@ -323,7 +326,7 @@ object MainForm: TMainForm end object HexDumpSplitter: TSplitter Left = 391 - Height = 299 + Height = 298 Top = 1 Width = 5 Align = alRight @@ -334,7 +337,7 @@ object MainForm: TMainForm Cursor = crVSplit Left = 0 Height = 5 - Top = 301 + Top = 300 Width = 657 Align = alBottom ResizeAnchor = akBottom @@ -344,19 +347,19 @@ object MainForm: TMainForm end object TreePanel: TPanel Left = 0 - Height = 497 - Top = 26 + Height = 496 + Top = 27 Width = 419 Align = alLeft BevelOuter = bvNone - ClientHeight = 497 + ClientHeight = 496 ClientWidth = 419 Constraints.MinWidth = 275 TabOrder = 3 object FindPanel: TPanel Left = 0 Height = 36 - Top = 461 + Top = 460 Width = 419 Align = alBottom BevelOuter = bvNone @@ -509,7 +512,7 @@ object MainForm: TMainForm end object BIFFTree: TVirtualStringTree Left = 0 - Height = 461 + Height = 460 Top = 0 Width = 419 Align = alClient diff --git a/components/fpspreadsheet/reference/BIFFExplorer/bemain.pas b/components/fpspreadsheet/reference/BIFFExplorer/bemain.pas index fd9d5e161..5f3695192 100644 --- a/components/fpspreadsheet/reference/BIFFExplorer/bemain.pas +++ b/components/fpspreadsheet/reference/BIFFExplorer/bemain.pas @@ -142,6 +142,7 @@ type FFontIndex: Integer; FFormatIndex: Integer; FRowIndex: Integer; + FExternSheetIndex: Integer; FLockHexDumpGrids: Integer; FAnalysisGrid: TBIFFGrid; FMRUMenuManager : TMRUMenuManager; @@ -467,7 +468,7 @@ begin data := TBiffNodeData(ptr^.Data); case Sender.GetNodeLevel(Node) of 0: if Column = 0 then - CellText := data.RecordName; + CellText := data.RecordName; 1: case Column of 0: CellText := IntToStr(data.Offset); 1: CellText := Format('$%.4x', [data.RecordID]); @@ -1112,6 +1113,7 @@ begin FFontIndex := -1; FFormatIndex := -1; FRowIndex := -1; + FExternSheetIndex := 0; // 1-based! AStream.Position := 0; while AStream.Position < AStream.Size do begin p := AStream.Position; @@ -1165,6 +1167,11 @@ begin inc(FXFIndex); data.Index := FXFIndex; end; + $0017: // EXTERNSHEET record + if FFormat < sfExcel8 then begin + inc(FExternSheetIndex); + data.Index := FExternSheetIndex; + end; $001E, $041E: // Format record begin inc(FFormatIndex);