fpspreadsheet: Extend BIFFExplorer to show details on hyperlink and hyperlink tooltip records in BIFF8.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3950 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2015-02-18 17:33:52 +00:00
parent dd4e66216a
commit 3d3c0e766f
3 changed files with 267 additions and 15 deletions

View File

@ -380,7 +380,7 @@ const
); );
type type
{@@ Style of fill style for cell backgrounds } {@@ Style of fill pattern for cell backgrounds }
TsFillStyle = (fsNoFill, fsSolidFill, TsFillStyle = (fsNoFill, fsSolidFill,
fsGray75, fsGray50, fsGray25, fsGray12, fsGray6, fsGray75, fsGray50, fsGray25, fsGray12, fsGray6,
fsStripeHor, fsStripeVert, fsStripeDiagUp, fsStripeDiagDown, fsStripeHor, fsStripeVert, fsStripeDiagUp, fsStripeDiagDown,
@ -389,12 +389,13 @@ type
{@@ Fill pattern record } {@@ Fill pattern record }
TsFillPattern = record TsFillPattern = record
Style: TsFillStyle; Style: TsFillStyle; // pattern type
FgColor: TsColor; // pattern color FgColor: TsColor; // pattern color
BgColor: TsColor; // background color BgColor: TsColor; // background color
end; end;
const const
{@@ Parameters for a non-filled cell background }
EMPTY_FILL: TsFillPattern = ( EMPTY_FILL: TsFillPattern = (
Style: fsNoFill; Style: fsNoFill;
FgColor: scTransparent; FgColor: scTransparent;

View File

@ -33,7 +33,7 @@ type
procedure ShowCalcCount; procedure ShowCalcCount;
procedure ShowCalcMode; procedure ShowCalcMode;
procedure ShowCellAddress; procedure ShowCellAddress;
procedure ShowCellAddressRange; procedure ShowCellAddressRange(AFormat: TsSpreadsheetFormat);
procedure ShowClrtClient; procedure ShowClrtClient;
procedure ShowCodePage; procedure ShowCodePage;
procedure ShowColInfo; procedure ShowColInfo;
@ -65,6 +65,8 @@ type
procedure ShowGCW; procedure ShowGCW;
procedure ShowHeader; procedure ShowHeader;
procedure ShowHideObj; procedure ShowHideObj;
procedure ShowHyperLink;
procedure ShowHyperLinkTooltip;
procedure ShowInteger; procedure ShowInteger;
procedure ShowInterfaceEnd; procedure ShowInterfaceEnd;
procedure ShowInterfaceHdr; procedure ShowInterfaceHdr;
@ -432,6 +434,8 @@ begin
ShowTXO; ShowTXO;
$01B7: $01B7:
ShowRefreshAll; ShowRefreshAll;
$01B8:
ShowHyperlink;
$01BC: $01BC:
ShowProt4RevPass; ShowProt4RevPass;
$01C0: $01C0:
@ -442,6 +446,8 @@ begin
ShowStyle; ShowStyle;
$04BC: $04BC:
ShowSharedFormula; ShowSharedFormula;
$0800:
ShowHyperlinkTooltip;
$087C: $087C:
ShowXFCRC; ShowXFCRC;
$087D: $087D:
@ -918,9 +924,12 @@ begin
end; end;
procedure TBIFFGrid.ShowCellAddressRange; procedure TBIFFGrid.ShowCellAddressRange(AFormat: TsSpreadsheetFormat);
{ Note: The bitmask assignment to relative column/row is reversed in relation { Note: The bitmask assignment to relative column/row is reversed in relation
to OpenOffice documentation in order to match with Excel files. } to OpenOffice documentation in order to match with Excel files.
The spreadsheet format is passed as a parameter because some BIFF8 records
used these fields in BIFF5 format. }
var var
numbytes: Word; numbytes: Word;
b: Byte; b: Byte;
@ -928,7 +937,7 @@ var
r, c, r2, c2: Integer; r, c, r2, c2: Integer;
s: String; s: String;
begin begin
if FFormat = sfExcel8 then begin if AFormat = sfExcel8 then begin
numBytes := 2; numBytes := 2;
Move(FBuffer[FBufferIndex], w, numBytes); Move(FBuffer[FBufferIndex], w, numBytes);
r := WordLEToN(w); r := WordLEToN(w);
@ -1571,7 +1580,7 @@ begin
if token in [$3A, $5A, $7A] then if token in [$3A, $5A, $7A] then
ShowCellAddress // Cell address ShowCellAddress // Cell address
else else
ShowCellAddressRange; // Cell range ShowCellAddressRange(FFormat); // Cell range
end; end;
else else
@ -2618,7 +2627,7 @@ begin
end; end;
ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [token]), ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [token]),
Format('Token tAREA (Cell range %s)', [s])); Format('Token tAREA (Cell range %s)', [s]));
ShowCellAddressRange; ShowCellAddressRange(FFormat);
end; end;
$2C, $4C, $6C: $2C, $4C, $6C:
begin begin
@ -2803,6 +2812,248 @@ begin
end; end;
procedure TBIFFGrid.ShowHyperlink;
var
numbytes: Word;
w: Word;
dw: DWord;
n: Integer;
guid: TGUID;
flags: DWord;
nchar, size: DWord;
widestr: WideString;
ansistr: ansistring;
s: String;
begin
n := 0;
RowCount := FixedRows + 1000;
ShowCellAddressRange(FFormat);
inc(n, 4);
numbytes := 16;
Move(FBuffer[FBufferIndex], guid, numbytes);
s := GuidToString(guid);
ShowInRow(FCurrRow, FBufferIndex, numbytes, GuidToString(guid), 'GUID of standard link');
inc(n);
numbytes := 4;
Move(FBuffer[FBufferIndex], dw, numbytes);
dw := DWordToLE(dw);
ShowInRow(FCurrRow, FBufferIndex, numbytes, Format('$%.8x (%d)', [dw, dw]), 'Unknown');
inc(n);
numbytes := 4;
Move(FBuffer[FBufferIndex], dw, numbytes);
flags := DWordToLE(dw);
if FCurrRow = row then begin
FDetails.Add('Option flags:'#13);
if flags and $0001 = 0
then FDetails.Add(' Bit $0001=0: No link')
else FDetails.ADd('* Bit $0001=1: File link or URL');
if flags and $0002 = 0
then FDetails.Add(' Bit $0002=0: Relative path')
else FDetails.Add('* Bit $0002=1: Absolute path');
if flags and $0014 = 0
then FDetails.Add(' Bits $0014=0: No desriptions')
else FDetails.Add('* Bits $0014=1: Description (both bits)');
if flags and $0008 = 0
then FDetails.Add(' Bit $0008=0: No text mark')
else FDetails.Add('* Bit $0008=1: Text mark');
if flags and $0080 = 0
then FDetails.Add(' Bit $0080=0: No target frame')
else FDetails.Add('* Bit $0080=1: Target frame');
if flags and $0100 = 0
then FDetails.Add(' Bit $0100=0: File link or URL')
else FDetails.Add('* Bit $0100=1: UNC path (incl server name)');
end;
ShowInRow(FCurrRow, FBufferIndex, numbytes, Format('$%.8x (%d)', [flags, flags]),
'Option flags');
inc(n);
if flags and $0014 = $0014 then // hyperlink has description
begin
numBytes := 4;
Move(FBuffer[FBufferIndex], dw, numbytes);
nchar := DWordToLE(dw);
ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(nchar),
'Character count of description text, incl trailing zero word');
inc(n);
numbytes := 2*nchar;
SetLength(widestr, nchar);
Move(FBuffer[FBufferIndex], widestr[1], 2*nchar);
s := UTF16ToUTF8(widestr);
ShowInRow(FCurrRow, FBufferIndex, numbytes, s,
'Character array of description text (no unicode string header, always 16-bit characters, zero-terminated)');
inc(n);
end;
if flags and $0080 <> 0 then // Hyperlink has target frame
begin
numBytes := 4;
Move(FBuffer[FBufferIndex], dw, numbytes);
nchar := DWordToLE(dw);
ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(nchar),
'Character count of target frame, incl trailing zero word');
inc(n);
numbytes := 2*nchar;
SetLength(widestr, nchar);
Move(FBuffer[FBufferIndex], widestr[1], 2*nchar);
s := UTF16ToUTF8(widestr);
ShowInRow(FCurrRow, FBufferIndex, numbytes, s,
'Character array of target frame (no unicode string header, always 16-bit characters, zero-terminated)');
inc(n);
end;
if flags and $0011 <> 0 then // hyperlink contains URL ***OR*** a local file
begin
numbytes := 16;
Move(FBuffer[FBufferIndex], guid, numbytes);
s := GuidToString(guid);
if s = '{79EAC9E0-BAF9-11CE-8C82-00AA004BA90B}' then // case: URL
begin
ShowInRow(FCurrRow, FBufferIndex, numbytes, s,
'GUID of URL Moniker');
inc(n);
numBytes := 4;
Move(FBuffer[FBufferIndex], dw, numbytes);
size := DWordToLE(dw);
nchar := size div 2 - 1;
ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(size),
'Size of URL character array, incl. trailing zero word');
inc(n);
numbytes := 2*nchar;
SetLength(widestr, nchar);
Move(FBuffer[FBufferIndex], widestr[1], 2*nchar);
s := UTF16ToUTF8(widestr);
ShowInRow(FCurrRow, FBufferIndex, numbytes, s,
'Character array of the URL (no unicode string header, always 16-bit characters, zero-terminated');
inc(n);
end else
if s = '{00000303-0000-0000-C000-000000000046}' then // case: local file
begin
ShowInRow(FCurrRow, FBufferIndex, numbytes, s,
'GUID of File Moniker');
inc(n);
numbytes := 2;
Move(FBuffer[FBufferIndex], w, numbytes);
ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(w),
'Directory up-level count. Each leading "..\" in the file link is deleted and increases this counter.');
inc(n);
numBytes := 4;
Move(FBuffer[FBufferIndex], dw, numbytes);
nchar := DWordToLE(dw);
ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(size),
'Character count of the shortened file path and name, incl trailing zero byte.');
inc(n);
numbytes := nchar;
SetLength(ansistr, nchar);
Move(FBuffer[FBufferIndex], ansistr[1], nchar);
s := AnsiToUTF8(ansistr);
ShowInRow(FCurrRow, FBufferIndex, numbytes, s,
'Character array of the shortened file path and name (no unicode string header, always 8-bit characters, zero-terminated)');
inc(n);
for w := 1 to 6 do begin
numbytes := 4;
Move(FBuffer[FBufferIndex], dw, numbytes);
ShowInRow(FCurrRow, FBufferIndex, numbytes, Format('$%.8x', [DWordToLE(dw)]),
'Unknown');
inc(n);
end;
numBytes := 4;
Move(FBuffer[FBufferIndex], dw, numbytes);
size := DWordToLE(dw);
ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(size),
'Size of following file link field incl string length field and additional data field');
inc(n);
if size > 0 then begin
numBytes := 4;
Move(FBuffer[FBufferIndex], dw, numbytes);
size := DWordToLE(dw);
nchar := size div 2;
ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(size),
'Size of extended file path and name character array');
inc(n);
numBytes := 2;
Move(FBuffer[FBufferIndex], w, numbytes);
ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(WordToLE(w)),
'Unknown');
inc(n);
numBytes := size;
SetLength(widestr, nchar);
Move(FBuffer[FBufferIndex], widestr[1], numbytes);
s := UTF16ToUTF8(widestr);
ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(size),
'Character array of extended file path and array (No unicode string header, always 16-bit characters, NOT zero-terminated)');
inc(n);
end;
end;
end // if flags and $0011 <> 0
else begin
// case: Hyperlink to current workbook
end;
if flags and $0008 <> 0 then // hyperlink contains text mark field
begin
numBytes := 4;
Move(FBuffer[FBufferIndex], dw, numbytes);
nchar := DWordToLE(dw);
ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(nchar),
'Character count of the text mark, incl trailing zero word');
inc(n);
numbytes := 2*nchar;
SetLength(widestr, nchar);
Move(FBuffer[FBufferIndex], widestr[1], 2*nchar);
s := UTF16ToUTF8(widestr);
ShowInRow(FCurrRow, FBufferIndex, numbytes, s,
'Character array of the text mark, without "#" sign, no unicode string header, always 16-bit characters, zero-terminated)');
inc(n);
end;
RowCount := FixedRows + n;
end;
procedure TBIFFGrid.ShowHyperlinkTooltip;
var
numbytes: Word;
w: Word;
widestr: widestring;
s: string;
begin
RowCount := FixedRows + 6;
numbytes := 2;
Move(FBuffer[FBufferIndex], w, numbytes);
w := WordToLE(w);
ShowInRow(FCurrRow, FBufferIndex, numbytes, Format('$%.4x (%d)', [w, w]),
'Repeated record ID');
ShowCellAddressRange(sfExcel8);
numbytes := Length(FBuffer) - FBufferIndex;
SetLength(widestr, numbytes div 2);
Move(FBuffer[FBufferIndex], widestr[1], numbytes);
s := UTF16toUTF8(widestr);
ShowInRow(FCurrRow, FBufferIndex, numbytes, s,
'Character array of the tool tip, no Unicode string header, always 16-bit characters, zero-terminated');
end;
procedure TBIFFGrid.ShowInRow(var ARow: Integer; var AOffs: LongWord; procedure TBIFFGrid.ShowInRow(var ARow: Integer; var AOffs: LongWord;
ASize: Word; AValue,ADescr: String; ADescrOnly: Boolean = false); ASize: Word; AValue,ADescr: String; ADescrOnly: Boolean = false);
begin begin

View File

@ -367,10 +367,10 @@ begin
$0203: Result := 'NUMBER: Cell value, floating-point cell'; $0203: Result := 'NUMBER: Cell value, floating-point cell';
$0204: Result := 'LABEL: Cell value, string constant'; $0204: Result := 'LABEL: Cell value, string constant';
$0205: Result := 'BOOLERR: Cell Value, boolean or error'; $0205: Result := 'BOOLERR: Cell Value, boolean or error';
$0206: Result := 'Formula'; $0206: Result := 'FORMULA: Formula';
$0207: Result := 'STRING: String value of a formula'; $0207: Result := 'STRING: String value of a formula';
$0208: Result := 'ROW: Describes a row'; $0208: Result := 'ROW: Describes a row';
$0209: Result := 'BOF'; $0209: Result := 'BOF: Begin of file';
$020B: Result := 'INDEX: Index record'; $020B: Result := 'INDEX: Index record';
$0218: Result := 'NAME: Defined name'; $0218: Result := 'NAME: Defined name';
$0221: Result := 'ARRAY: Array-entered formula'; $0221: Result := 'ARRAY: Array-entered formula';
@ -383,11 +383,11 @@ begin
$027E: Result := 'RK: Cell value, RK number'; $027E: Result := 'RK: Cell value, RK number';
$0293: Result := 'STYLE: Style information'; $0293: Result := 'STYLE: Style information';
$0406: Result := 'FORMULA: Cell formula'; $0406: Result := 'FORMULA: Cell formula';
$0409: Result := 'BOF'; $0409: Result := 'BOF: Begin of file';
$041E: Result := 'FORMAT: Number format'; $041E: Result := 'FORMAT: Number format';
$0443: Result := 'XF'; $0443: Result := 'XF: Extended format';
$04BC: Result := 'SHAREDFMLA: Shared formula'; $04BC: Result := 'SHAREDFMLA: Shared formula';
$0800: Result := 'HLINKTOOLTOP: Hyperlink tooltip'; $0800: Result := 'HLINKTOOLTIP: Hyperlink tooltip';
$0801: Result := 'WEBPUB: Web publish item'; $0801: Result := 'WEBPUB: Web publish item';
$0802: Result := 'QSISXTAG: PivotTable and query table extensions'; $0802: Result := 'QSISXTAG: PivotTable and query table extensions';
$0803: Result := 'DBQUERYEXT: Database query extensions'; $0803: Result := 'DBQUERYEXT: Database query extensions';