You've already forked lazarus-ccr
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:
@ -380,7 +380,7 @@ const
|
||||
);
|
||||
|
||||
type
|
||||
{@@ Style of fill style for cell backgrounds }
|
||||
{@@ Style of fill pattern for cell backgrounds }
|
||||
TsFillStyle = (fsNoFill, fsSolidFill,
|
||||
fsGray75, fsGray50, fsGray25, fsGray12, fsGray6,
|
||||
fsStripeHor, fsStripeVert, fsStripeDiagUp, fsStripeDiagDown,
|
||||
@ -389,12 +389,13 @@ type
|
||||
|
||||
{@@ Fill pattern record }
|
||||
TsFillPattern = record
|
||||
Style: TsFillStyle;
|
||||
FgColor: TsColor; // pattern color
|
||||
BgColor: TsColor; // background color
|
||||
Style: TsFillStyle; // pattern type
|
||||
FgColor: TsColor; // pattern color
|
||||
BgColor: TsColor; // background color
|
||||
end;
|
||||
|
||||
const
|
||||
{@@ Parameters for a non-filled cell background }
|
||||
EMPTY_FILL: TsFillPattern = (
|
||||
Style: fsNoFill;
|
||||
FgColor: scTransparent;
|
||||
|
@ -33,7 +33,7 @@ type
|
||||
procedure ShowCalcCount;
|
||||
procedure ShowCalcMode;
|
||||
procedure ShowCellAddress;
|
||||
procedure ShowCellAddressRange;
|
||||
procedure ShowCellAddressRange(AFormat: TsSpreadsheetFormat);
|
||||
procedure ShowClrtClient;
|
||||
procedure ShowCodePage;
|
||||
procedure ShowColInfo;
|
||||
@ -65,6 +65,8 @@ type
|
||||
procedure ShowGCW;
|
||||
procedure ShowHeader;
|
||||
procedure ShowHideObj;
|
||||
procedure ShowHyperLink;
|
||||
procedure ShowHyperLinkTooltip;
|
||||
procedure ShowInteger;
|
||||
procedure ShowInterfaceEnd;
|
||||
procedure ShowInterfaceHdr;
|
||||
@ -432,6 +434,8 @@ begin
|
||||
ShowTXO;
|
||||
$01B7:
|
||||
ShowRefreshAll;
|
||||
$01B8:
|
||||
ShowHyperlink;
|
||||
$01BC:
|
||||
ShowProt4RevPass;
|
||||
$01C0:
|
||||
@ -442,6 +446,8 @@ begin
|
||||
ShowStyle;
|
||||
$04BC:
|
||||
ShowSharedFormula;
|
||||
$0800:
|
||||
ShowHyperlinkTooltip;
|
||||
$087C:
|
||||
ShowXFCRC;
|
||||
$087D:
|
||||
@ -918,9 +924,12 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
procedure TBIFFGrid.ShowCellAddressRange;
|
||||
procedure TBIFFGrid.ShowCellAddressRange(AFormat: TsSpreadsheetFormat);
|
||||
{ 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
|
||||
numbytes: Word;
|
||||
b: Byte;
|
||||
@ -928,7 +937,7 @@ var
|
||||
r, c, r2, c2: Integer;
|
||||
s: String;
|
||||
begin
|
||||
if FFormat = sfExcel8 then begin
|
||||
if AFormat = sfExcel8 then begin
|
||||
numBytes := 2;
|
||||
Move(FBuffer[FBufferIndex], w, numBytes);
|
||||
r := WordLEToN(w);
|
||||
@ -1571,7 +1580,7 @@ begin
|
||||
if token in [$3A, $5A, $7A] then
|
||||
ShowCellAddress // Cell address
|
||||
else
|
||||
ShowCellAddressRange; // Cell range
|
||||
ShowCellAddressRange(FFormat); // Cell range
|
||||
end;
|
||||
|
||||
else
|
||||
@ -2618,7 +2627,7 @@ begin
|
||||
end;
|
||||
ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [token]),
|
||||
Format('Token tAREA (Cell range %s)', [s]));
|
||||
ShowCellAddressRange;
|
||||
ShowCellAddressRange(FFormat);
|
||||
end;
|
||||
$2C, $4C, $6C:
|
||||
begin
|
||||
@ -2803,6 +2812,248 @@ begin
|
||||
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;
|
||||
ASize: Word; AValue,ADescr: String; ADescrOnly: Boolean = false);
|
||||
begin
|
||||
|
@ -367,10 +367,10 @@ begin
|
||||
$0203: Result := 'NUMBER: Cell value, floating-point cell';
|
||||
$0204: Result := 'LABEL: Cell value, string constant';
|
||||
$0205: Result := 'BOOLERR: Cell Value, boolean or error';
|
||||
$0206: Result := 'Formula';
|
||||
$0206: Result := 'FORMULA: Formula';
|
||||
$0207: Result := 'STRING: String value of a formula';
|
||||
$0208: Result := 'ROW: Describes a row';
|
||||
$0209: Result := 'BOF';
|
||||
$0209: Result := 'BOF: Begin of file';
|
||||
$020B: Result := 'INDEX: Index record';
|
||||
$0218: Result := 'NAME: Defined name';
|
||||
$0221: Result := 'ARRAY: Array-entered formula';
|
||||
@ -383,11 +383,11 @@ begin
|
||||
$027E: Result := 'RK: Cell value, RK number';
|
||||
$0293: Result := 'STYLE: Style information';
|
||||
$0406: Result := 'FORMULA: Cell formula';
|
||||
$0409: Result := 'BOF';
|
||||
$0409: Result := 'BOF: Begin of file';
|
||||
$041E: Result := 'FORMAT: Number format';
|
||||
$0443: Result := 'XF';
|
||||
$0443: Result := 'XF: Extended format';
|
||||
$04BC: Result := 'SHAREDFMLA: Shared formula';
|
||||
$0800: Result := 'HLINKTOOLTOP: Hyperlink tooltip';
|
||||
$0800: Result := 'HLINKTOOLTIP: Hyperlink tooltip';
|
||||
$0801: Result := 'WEBPUB: Web publish item';
|
||||
$0802: Result := 'QSISXTAG: PivotTable and query table extensions';
|
||||
$0803: Result := 'DBQUERYEXT: Database query extensions';
|
||||
|
Reference in New Issue
Block a user