You've already forked lazarus-ccr
fpspreadsheet: Write printranges and repeated cells to biff5 files. Related improvements in BIFFExplorer.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4501 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -13,7 +13,7 @@ type
|
|||||||
TBIFFDetailsEvent = procedure(Sender: TObject; ADetails: TStrings) of object;
|
TBIFFDetailsEvent = procedure(Sender: TObject; ADetails: TStrings) of object;
|
||||||
|
|
||||||
TRichTextFormattingRun = packed record
|
TRichTextFormattingRun = packed record
|
||||||
FirstIndex, fontIndex: Word;
|
FirstIndex, FontIndex: Word;
|
||||||
end;
|
end;
|
||||||
TRichTextFormattingRuns = array of TRichTextFormattingRun;
|
TRichTextFormattingRuns = array of TRichTextFormattingRun;
|
||||||
|
|
||||||
@ -153,7 +153,6 @@ type
|
|||||||
constructor Create(AOwner: TComponent); override;
|
constructor Create(AOwner: TComponent); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure SetBIFFNodeData(AData: TBIFFNodeData; ABuffer: TBIFFBuffer; AFormat: TsSpreadsheetFormat);
|
procedure SetBIFFNodeData(AData: TBIFFNodeData; ABuffer: TBIFFBuffer; AFormat: TsSpreadsheetFormat);
|
||||||
// procedure SetRecordType(ARecType: Word; ABuffer: TBIFFBuffer; AFormat: TsSpreadsheetFormat);
|
|
||||||
|
|
||||||
published
|
published
|
||||||
property OnDetails: TBIFFDetailsEvent read FOnDetails write FOnDetails;
|
property OnDetails: TBIFFDetailsEvent read FOnDetails write FOnDetails;
|
||||||
@ -1676,8 +1675,7 @@ begin
|
|||||||
numBytes := lenName * sizeOf(ansiChar);
|
numBytes := lenName * sizeOf(ansiChar);
|
||||||
SetLength(ansiStr, lenName);
|
SetLength(ansiStr, lenName);
|
||||||
Move(FBuffer[FBufferIndex], ansiStr[1], numbytes);
|
Move(FBuffer[FBufferIndex], ansiStr[1], numbytes);
|
||||||
ShowInRow(FCurrRow, FBufferIndex, numBytes, ansiStr,
|
s := AnsiToUTF8(ansistr);
|
||||||
'Character array of the name');
|
|
||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
if (FBuffer[FBufferIndex] and $01 = 0) //and (not IgnoreCompressedFlag)
|
if (FBuffer[FBufferIndex] and $01 = 0) //and (not IgnoreCompressedFlag)
|
||||||
@ -1692,29 +1690,29 @@ begin
|
|||||||
Move(FBuffer[FBufferIndex + 1], wideStr[1], lenName*SizeOf(WideChar));
|
Move(FBuffer[FBufferIndex + 1], wideStr[1], lenName*SizeOf(WideChar));
|
||||||
s := UTF8Encode(WideStringLEToN(wideStr));
|
s := UTF8Encode(WideStringLEToN(wideStr));
|
||||||
end;
|
end;
|
||||||
if builtinName and (Length(s) = 1) then begin
|
|
||||||
s := Format('%s ($%x --> ', [s, ord(s[1])]);
|
|
||||||
case ord(s[1]) of
|
|
||||||
0: s := s + 'Consolidate_Area)';
|
|
||||||
1: s := s + 'Auto_Open)';
|
|
||||||
2: s := s + 'Auto_Close)';
|
|
||||||
3: s := s + 'Extract)';
|
|
||||||
4: s := s + 'Database)';
|
|
||||||
5: s := s + 'Citeria)';
|
|
||||||
6: s := s + 'Print_Area)';
|
|
||||||
7: s := s + 'Print_Titles)';
|
|
||||||
8: s := s + 'Recorder)';
|
|
||||||
9: s := s + 'Data_Form)';
|
|
||||||
10: s := s + 'Auto_Activate)';
|
|
||||||
11: s := s + 'Auto_Deactivate)';
|
|
||||||
12: s := s + 'Sheet_Title)';
|
|
||||||
13: s := s + '_FilterDatabase)';
|
|
||||||
else s := s + 'unknown meaning)';
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
ShowInRow(FCurrRow, FBufferIndex, numbytes, s,
|
|
||||||
'Name (Unicode string without length field)');
|
|
||||||
end;
|
end;
|
||||||
|
if builtinName and (Length(s) = 1) then begin
|
||||||
|
s := Format('%s ($%x --> ', [s, ord(s[1])]);
|
||||||
|
case ord(s[1]) of
|
||||||
|
0: s := s + 'Consolidate_Area)';
|
||||||
|
1: s := s + 'Auto_Open)';
|
||||||
|
2: s := s + 'Auto_Close)';
|
||||||
|
3: s := s + 'Extract)';
|
||||||
|
4: s := s + 'Database)';
|
||||||
|
5: s := s + 'Citeria)';
|
||||||
|
6: s := s + 'Print_Area)';
|
||||||
|
7: s := s + 'Print_Titles)';
|
||||||
|
8: s := s + 'Recorder)';
|
||||||
|
9: s := s + 'Data_Form)';
|
||||||
|
10: s := s + 'Auto_Activate)';
|
||||||
|
11: s := s + 'Auto_Deactivate)';
|
||||||
|
12: s := s + 'Sheet_Title)';
|
||||||
|
13: s := s + '_FilterDatabase)';
|
||||||
|
else s := s + 'unknown meaning)';
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
ShowInRow(FCurrRow, FBufferIndex, numbytes, s,
|
||||||
|
'Name (Unicode string without length field)');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
firstTokenBufIdx := FBufferIndex;
|
firstTokenBufIdx := FBufferIndex;
|
||||||
@ -1770,16 +1768,16 @@ begin
|
|||||||
if FFormat = sfExcel5 then begin
|
if FFormat = sfExcel5 then begin
|
||||||
if w and $8000 <> 0 then begin // negative value --> 3D reference
|
if w and $8000 <> 0 then begin // negative value --> 3D reference
|
||||||
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(SmallInt(w)),
|
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(SmallInt(w)),
|
||||||
'3D reference, 1-based index to EXTERNSHEET record');
|
'negative --> 3D reference, 1-based index to EXTERNSHEET record = ' + IntToStr(-SmallInt(w)));
|
||||||
numBytes := 8;
|
numBytes := 8;
|
||||||
ShowInRow(FCurrRow, FBufferIndex, numBytes, '', 'Not used');
|
ShowInRow(FCurrRow, FBufferIndex, numBytes, '', 'Not used');
|
||||||
numBytes := 2;
|
numBytes := 2;
|
||||||
Move(FBuffer[FBufferIndex], w, numBytes);
|
Move(FBuffer[FBufferIndex], w, numBytes);
|
||||||
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)),
|
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)),
|
||||||
'Index to first referenced sheet ($FFFF = deleted sheet)');
|
'Zero-based index to first referenced sheet ($FFFF = deleted sheet)');
|
||||||
Move(FBuffer[FBufferIndex], w, numBytes);
|
Move(FBuffer[FBufferIndex], w, numBytes);
|
||||||
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)),
|
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)),
|
||||||
'Index to last referenced sheet ($FFFF = deleted sheet)');
|
'Zero-based index to last referenced sheet ($FFFF = deleted sheet)');
|
||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(w),
|
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(w),
|
||||||
@ -2050,13 +2048,15 @@ begin
|
|||||||
FDetails.Add('First character = $03: EXTERNSHEET stores a reference to one of the own sheets');
|
FDetails.Add('First character = $03: EXTERNSHEET stores a reference to one of the own sheets');
|
||||||
FDetails.Add('Document name: ' + Copy(s, 2, Length(s)));
|
FDetails.Add('Document name: ' + Copy(s, 2, Length(s)));
|
||||||
end else
|
end else
|
||||||
if (s[1] = ':') and (Length(s) = 1) then begin
|
if (Length(s) = 1) and (s[1] = ':') then begin
|
||||||
FDetails.Add('Special EXTERNSHEET record for an add-in function. EXTERNName record with the name of the function follows.');
|
FDetails.Add('Special EXTERNSHEET record for an add-in function. EXTERNName record with the name of the function follows.');
|
||||||
end else
|
end else
|
||||||
FDetails.Add('Document name: ' + s);
|
FDetails.Add('Document name: ' + s);
|
||||||
end;
|
end;
|
||||||
if s[1] = #03 then
|
if s[1] = #03 then begin
|
||||||
Delete(s, 1, 1);
|
Delete(s, 1, 1);
|
||||||
|
s := '<#03>' + s;
|
||||||
|
end;
|
||||||
ShowInRow(FCurrRow, FBufferIndex, numBytes, s,
|
ShowInRow(FCurrRow, FBufferIndex, numBytes, s,
|
||||||
'Encoded document and sheet name (Byte string, 8-bit string length)');
|
'Encoded document and sheet name (Byte string, 8-bit string length)');
|
||||||
end else begin
|
end else begin
|
||||||
|
@ -49,7 +49,7 @@ AUTHORS: Felipe Monteiro de Carvalho
|
|||||||
unit xlsbiff5;
|
unit xlsbiff5;
|
||||||
|
|
||||||
{$ifdef fpc}
|
{$ifdef fpc}
|
||||||
{$mode delphi}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
{$define USE_NEW_OLE}
|
{$define USE_NEW_OLE}
|
||||||
@ -101,6 +101,8 @@ type
|
|||||||
{ Record writing methods }
|
{ Record writing methods }
|
||||||
procedure WriteBOF(AStream: TStream; ADataType: Word);
|
procedure WriteBOF(AStream: TStream; ADataType: Word);
|
||||||
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
|
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
|
||||||
|
procedure WriteDefinedName(AStream: TStream; AWorksheet: TsWorksheet;
|
||||||
|
const AName: String; AIndexToREF: Word); override;
|
||||||
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
||||||
procedure WriteEOF(AStream: TStream);
|
procedure WriteEOF(AStream: TStream);
|
||||||
procedure WriteFont(AStream: TStream; AFont: TsFont);
|
procedure WriteFont(AStream: TStream; AFont: TsFont);
|
||||||
@ -1007,11 +1009,14 @@ begin
|
|||||||
|
|
||||||
WriteBOF(AStream, INT_BOF_WORKBOOK_GLOBALS);
|
WriteBOF(AStream, INT_BOF_WORKBOOK_GLOBALS);
|
||||||
|
|
||||||
WriteCodepage(AStream, FCodePage);
|
WriteCODEPAGE(AStream, FCodePage);
|
||||||
WriteWindow1(AStream);
|
WriteEXTERNCOUNT(AStream);
|
||||||
|
WriteEXTERNSHEET(AStream);
|
||||||
|
WriteDefinedNames(AStream);
|
||||||
|
WriteWINDOW1(AStream);
|
||||||
WriteFonts(AStream);
|
WriteFonts(AStream);
|
||||||
WriteNumFormats(AStream);
|
WriteNumFormats(AStream);
|
||||||
WritePalette(AStream);
|
WritePALETTE(AStream);
|
||||||
WriteXFRecords(AStream);
|
WriteXFRecords(AStream);
|
||||||
WriteStyle(AStream);
|
WriteStyle(AStream);
|
||||||
|
|
||||||
@ -1204,6 +1209,145 @@ begin
|
|||||||
AStream.WriteBuffer(xlsSheetName[1], Len);
|
AStream.WriteBuffer(xlsSheetName[1], Len);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Writes out a DEFINEDNAMES record
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsSpreadBIFF5Writer.WriteDefinedName(AStream: TStream;
|
||||||
|
AWorksheet: TsWorksheet; const AName: String; AIndexToREF: Word);
|
||||||
|
|
||||||
|
procedure WriteRangeFormula(MemStream: TMemoryStream; ARange: TsCellRange;
|
||||||
|
AIndexToREF, ACounter: Word);
|
||||||
|
var
|
||||||
|
sheetIdx: Integer;
|
||||||
|
begin
|
||||||
|
sheetIdx := FWorkbook.GetWorksheetIndex(AWorksheet);
|
||||||
|
|
||||||
|
{ Token for tArea3dR }
|
||||||
|
MemStream.WriteByte($3B);
|
||||||
|
|
||||||
|
{ 1-based sheet index, negative to indicate 3D reference }
|
||||||
|
MemStream.WriteWord(WordToLE(-(sheetIdx+1)));
|
||||||
|
|
||||||
|
{ 8 bytes not used }
|
||||||
|
MemStream.WriteDWord(0);
|
||||||
|
MemStream.WriteDWord(0);
|
||||||
|
|
||||||
|
{ Index to first reference worksheet }
|
||||||
|
MemStream.WriteWord(WordToLE(sheetIdx)); // THIS IS ONLY VALID FOR PRINTRANGE!
|
||||||
|
|
||||||
|
{ Index to last reference worksheet }
|
||||||
|
MemStream.WriteWord(WordToLE(sheetIdx)); // THIS IS ONLY VALID FOR PRINTRANGE!
|
||||||
|
|
||||||
|
{ First row index }
|
||||||
|
MemStream.WriteWord(WordToLE(ARange.Row1));
|
||||||
|
|
||||||
|
{ Last row index }
|
||||||
|
MemStream.WriteWord(WordToLE(ARange.Row2));
|
||||||
|
|
||||||
|
{ First column index }
|
||||||
|
MemStream.WriteByte(ARange.Col1);
|
||||||
|
|
||||||
|
{ Last column index }
|
||||||
|
MemStream.WriteByte(ARange.Col2);
|
||||||
|
|
||||||
|
{ Token for list if formula refers to more than 1 range }
|
||||||
|
if ACounter > 1 then
|
||||||
|
MemStream.WriteByte($10);
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
memstream: TMemoryStream;
|
||||||
|
rng: TsCellRange;
|
||||||
|
j: Integer;
|
||||||
|
idx: Integer;
|
||||||
|
begin
|
||||||
|
// Since this is a variable length record we begin by writing the formula
|
||||||
|
// to a memory stream
|
||||||
|
|
||||||
|
memstream := TMemoryStream.Create;
|
||||||
|
try
|
||||||
|
case AName of
|
||||||
|
#06: begin // Print range
|
||||||
|
for j := 0 to AWorksheet.NumPrintRanges-1 do
|
||||||
|
begin
|
||||||
|
rng := AWorksheet.GetPrintRange(j);
|
||||||
|
WriteRangeFormula(memstream, rng, AIndexToRef, j+1);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
#07: begin
|
||||||
|
j := 1;
|
||||||
|
if AWorksheet.HasRepeatedPrintCols then
|
||||||
|
begin
|
||||||
|
rng.Col1 := AWorksheet.PageLayout.RepeatedCols.FirstIndex;
|
||||||
|
rng.Col2 := AWorksheet.PageLayout.RepeatedCols.LastIndex;
|
||||||
|
if rng.Col2 = UNASSIGNED_ROW_COL_INDEX then rng.Col2 := rng.Col1;
|
||||||
|
rng.Row1 := 0;
|
||||||
|
rng.Row2 := 65535;
|
||||||
|
WriteRangeFormula(memstream, rng, AIndexToRef, j);
|
||||||
|
inc(j);
|
||||||
|
end;
|
||||||
|
if AWorksheet.HasRepeatedPrintRows then
|
||||||
|
begin
|
||||||
|
rng.Row1 := AWorksheet.PageLayout.RepeatedRows.FirstIndex;
|
||||||
|
rng.Row2 := AWorksheet.PageLayout.RepeatedRows.LastIndex;
|
||||||
|
if rng.Row2 = UNASSIGNED_ROW_COL_INDEX then rng.Row2 := rng.Row1;
|
||||||
|
rng.Col1 := 0;
|
||||||
|
rng.Col2 := 255;
|
||||||
|
WriteRangeFormula(memstream, rng, AIndexToRef, j);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
else raise Exception.Create('Name not supported');
|
||||||
|
end; // case
|
||||||
|
|
||||||
|
idx := FWorkbook.GetWorksheetIndex(AWorksheet);
|
||||||
|
|
||||||
|
{ BIFF record header }
|
||||||
|
WriteBIFFHeader(AStream, INT_EXCEL_ID_DEFINEDNAME, 14 + Length(AName) + memstream.Size);
|
||||||
|
|
||||||
|
{ Option flags: built-in defined names only }
|
||||||
|
AStream.WriteWord(WordToLE($0020));
|
||||||
|
|
||||||
|
{ Keyboard shortcut (only for command macro names) }
|
||||||
|
AStream.WriteByte(0);
|
||||||
|
|
||||||
|
{ Length of name (character count). Always 1 for built-in names }
|
||||||
|
AStream.WriteByte(Length(AName));
|
||||||
|
|
||||||
|
{ Size of formula data }
|
||||||
|
AStream.WriteWord(WordToLE(memstream.Size));
|
||||||
|
|
||||||
|
{ Global name, otherwise index to EXTERNSHEET record (1-based) }
|
||||||
|
AStream.WriteWord(WordToLE(AIndexToREF+1));
|
||||||
|
|
||||||
|
{ Global name, otherwise index to sheet (1-based) }
|
||||||
|
AStream.WriteWord(WordToLE(idx+1));
|
||||||
|
|
||||||
|
{ Length of menu text }
|
||||||
|
AStream.WriteByte(0);
|
||||||
|
|
||||||
|
{ Length of description text }
|
||||||
|
AStream.WriteByte(0);
|
||||||
|
|
||||||
|
{ Length of help topic text }
|
||||||
|
AStream.WriteByte(0);
|
||||||
|
|
||||||
|
{ Length of status bar text }
|
||||||
|
AStream.WriteByte(0);
|
||||||
|
|
||||||
|
{ Name }
|
||||||
|
if (Length(AName) = 1) and (AName[1] < #32) then
|
||||||
|
AStream.WriteByte(ord(AName[1])) else
|
||||||
|
raise Exception.Create('Name not supported.');
|
||||||
|
|
||||||
|
{ Formula }
|
||||||
|
memstream.Position := 0;
|
||||||
|
AStream.CopyFrom(memstream, memstream.Size);
|
||||||
|
|
||||||
|
finally
|
||||||
|
memstream.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Writes an Excel 5 DIMENSIONS record
|
Writes an Excel 5 DIMENSIONS record
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ AUTHORS: Felipe Monteiro de Carvalho
|
|||||||
unit xlsbiff8;
|
unit xlsbiff8;
|
||||||
|
|
||||||
{$ifdef fpc}
|
{$ifdef fpc}
|
||||||
{$mode delphi}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
// The new OLE code is much better, so always use it
|
// The new OLE code is much better, so always use it
|
||||||
@ -132,12 +132,11 @@ type
|
|||||||
procedure WriteComment(AStream: TStream; ACell: PCell); override;
|
procedure WriteComment(AStream: TStream; ACell: PCell); override;
|
||||||
procedure WriteComments(AStream: TStream; AWorksheet: TsWorksheet);
|
procedure WriteComments(AStream: TStream; AWorksheet: TsWorksheet);
|
||||||
procedure WriteDefinedName(AStream: TStream; AWorksheet: TsWorksheet;
|
procedure WriteDefinedName(AStream: TStream; AWorksheet: TsWorksheet;
|
||||||
AIndexToREF: Word; AKind: Byte);
|
const AName: String; AIndexToREF: Word); override;
|
||||||
procedure WriteDefinedNames(AStream: TStream);
|
|
||||||
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
||||||
procedure WriteEOF(AStream: TStream);
|
procedure WriteEOF(AStream: TStream);
|
||||||
procedure WriteEXTERNBOOK(AStream: TStream);
|
procedure WriteEXTERNBOOK(AStream: TStream);
|
||||||
procedure WriteEXTERNSHEET(AStream: TStream);
|
procedure WriteEXTERNSHEET(AStream: TStream); override;
|
||||||
procedure WriteFONT(AStream: TStream; AFont: TsFont);
|
procedure WriteFONT(AStream: TStream; AFont: TsFont);
|
||||||
procedure WriteFonts(AStream: TStream);
|
procedure WriteFonts(AStream: TStream);
|
||||||
procedure WriteFORMAT(AStream: TStream; ANumFormatStr: String;
|
procedure WriteFORMAT(AStream: TStream; ANumFormatStr: String;
|
||||||
@ -658,8 +657,8 @@ var
|
|||||||
i: Integer;
|
i: Integer;
|
||||||
j: Integer; //j: SizeUInt;
|
j: Integer; //j: SizeUInt;
|
||||||
lLen: SizeInt;
|
lLen: SizeInt;
|
||||||
RecordType: WORD;
|
recType: WORD;
|
||||||
RecordSize: WORD;
|
recSize: WORD;
|
||||||
C: WideChar;
|
C: WideChar;
|
||||||
begin
|
begin
|
||||||
StringFlags := AStream.ReadByte;
|
StringFlags := AStream.ReadByte;
|
||||||
@ -699,12 +698,12 @@ begin
|
|||||||
Dec(PendingRecordSize);
|
Dec(PendingRecordSize);
|
||||||
if (PendingRecordSize <= 0) and (i < lLen) then begin
|
if (PendingRecordSize <= 0) and (i < lLen) then begin
|
||||||
//A CONTINUE may have happened here
|
//A CONTINUE may have happened here
|
||||||
RecordType := WordLEToN(AStream.ReadWord);
|
recType := WordLEToN(AStream.ReadWord);
|
||||||
RecordSize := WordLEToN(AStream.ReadWord);
|
recSize := WordLEToN(AStream.ReadWord);
|
||||||
if RecordType <> INT_EXCEL_ID_CONTINUE then begin
|
if recType <> INT_EXCEL_ID_CONTINUE then begin
|
||||||
Raise Exception.Create('[TsSpreadBIFF8Reader.ReadWideString] CONTINUE record expected, but not found.');
|
Raise Exception.Create('[TsSpreadBIFF8Reader.ReadWideString] CONTINUE record expected, but not found.');
|
||||||
end else begin
|
end else begin
|
||||||
PendingRecordSize := RecordSize;
|
PendingRecordSize := recSize;
|
||||||
DecomprStrValue := copy(DecomprStrValue,1,i) + ReadWideString(AStream, ALength-i, ARichTextParams);
|
DecomprStrValue := copy(DecomprStrValue,1,i) + ReadWideString(AStream, ALength-i, ARichTextParams);
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
@ -718,12 +717,12 @@ begin
|
|||||||
for j := 0 to SmallInt(RunsCounter) - 1 do begin
|
for j := 0 to SmallInt(RunsCounter) - 1 do begin
|
||||||
if (PendingRecordSize <= 0) then begin
|
if (PendingRecordSize <= 0) then begin
|
||||||
// A CONTINUE may happened here
|
// A CONTINUE may happened here
|
||||||
RecordType := WordLEToN(AStream.ReadWord);
|
recType := WordLEToN(AStream.ReadWord);
|
||||||
RecordSize := WordLEToN(AStream.ReadWord);
|
recSize := WordLEToN(AStream.ReadWord);
|
||||||
if RecordType <> INT_EXCEL_ID_CONTINUE then begin
|
if recType <> INT_EXCEL_ID_CONTINUE then begin
|
||||||
Raise Exception.Create('[TsSpreadBIFF8Reader.ReadWideString] CONTINUE record expected, but not found.');
|
Raise Exception.Create('[TsSpreadBIFF8Reader.ReadWideString] CONTINUE record expected, but not found.');
|
||||||
end else begin
|
end else begin
|
||||||
PendingRecordSize := RecordSize;
|
PendingRecordSize := recSize;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
// character start index: 0-based in file, 1-based in fps
|
// character start index: 0-based in file, 1-based in fps
|
||||||
@ -2239,7 +2238,7 @@ end;
|
|||||||
Implements only the builtin defined names for print ranges and titles!
|
Implements only the builtin defined names for print ranges and titles!
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsSpreadBIFF8Writer.WriteDefinedName(AStream: TStream;
|
procedure TsSpreadBIFF8Writer.WriteDefinedName(AStream: TStream;
|
||||||
AWorksheet: TsWorksheet; AIndexToREF: Word; AKind: Byte);
|
AWorksheet: TsWorksheet; const AName: String; AIndexToREF: Word);
|
||||||
|
|
||||||
procedure WriteRangeFormula(MemStream: TMemoryStream; ARange: TsCellRange;
|
procedure WriteRangeFormula(MemStream: TMemoryStream; ARange: TsCellRange;
|
||||||
AIndexToRef, ACounter: Word);
|
AIndexToRef, ACounter: Word);
|
||||||
@ -2277,15 +2276,15 @@ begin
|
|||||||
|
|
||||||
memstream := TMemoryStream.Create;
|
memstream := TMemoryStream.Create;
|
||||||
try
|
try
|
||||||
case AKind of
|
case AName of
|
||||||
$06: begin // Print range
|
#06: begin // Print range
|
||||||
for j := 0 to AWorksheet.NumPrintRanges-1 do
|
for j := 0 to AWorksheet.NumPrintRanges-1 do
|
||||||
begin
|
begin
|
||||||
rng := AWorksheet.GetPrintRange(j);
|
rng := AWorksheet.GetPrintRange(j);
|
||||||
WriteRangeFormula(memstream, rng, AIndexToRef, j+1);
|
WriteRangeFormula(memstream, rng, AIndexToRef, j+1);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
$07: begin
|
#07: begin // Print titles
|
||||||
j := 1;
|
j := 1;
|
||||||
if AWorksheet.HasRepeatedPrintCols then
|
if AWorksheet.HasRepeatedPrintCols then
|
||||||
begin
|
begin
|
||||||
@ -2307,6 +2306,8 @@ begin
|
|||||||
WriteRangeFormula(memstream, rng, AIndexToRef, j);
|
WriteRangeFormula(memstream, rng, AIndexToRef, j);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
else
|
||||||
|
raise Exception.Create('Name not supported');
|
||||||
end; // case
|
end; // case
|
||||||
|
|
||||||
{ BIFF record header }
|
{ BIFF record header }
|
||||||
@ -2344,7 +2345,9 @@ begin
|
|||||||
AStream.WriteByte(0);
|
AStream.WriteByte(0);
|
||||||
|
|
||||||
{ Name }
|
{ Name }
|
||||||
AStream.WriteWord(WordToLE(AKind shl 8));
|
if (Length(AName) = 1) and (AName[1] < #32) then
|
||||||
|
AStream.WriteWord(WordToLE(ord(AName[1]) shl 8)) else
|
||||||
|
raise Exception.Create('Name not supported.');
|
||||||
|
|
||||||
{ Formula }
|
{ Formula }
|
||||||
memstream.Position := 0;
|
memstream.Position := 0;
|
||||||
@ -2355,29 +2358,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadBIFF8Writer.WriteDefinedNames(AStream: TStream);
|
|
||||||
var
|
|
||||||
sheet: TsWorksheet;
|
|
||||||
i: Integer;
|
|
||||||
n: Word;
|
|
||||||
begin
|
|
||||||
n := 0;
|
|
||||||
for i:=0 to FWorkbook.GetWorksheetCount-1 do
|
|
||||||
begin
|
|
||||||
sheet := FWorkbook.GetWorksheetByIndex(i);
|
|
||||||
if (sheet.NumPrintRanges > 0) or
|
|
||||||
sheet.HasRepeatedPrintCols or sheet.HasRepeatedPrintRows then
|
|
||||||
begin
|
|
||||||
if sheet.NumPrintRanges > 0 then
|
|
||||||
WriteDefinedName(AStream, sheet, n, $06);
|
|
||||||
if sheet.HasRepeatedPrintCols or sheet.HasRepeatedPrintRows then
|
|
||||||
WriteDefinedName(AStream, sheet, n, $07);
|
|
||||||
inc(n);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Writes an Excel 8 DIMENSIONS record
|
Writes an Excel 8 DIMENSIONS record
|
||||||
|
|
||||||
|
@ -35,9 +35,12 @@ const
|
|||||||
INT_EXCEL_ID_CODEPAGE = $0042;
|
INT_EXCEL_ID_CODEPAGE = $0042;
|
||||||
INT_EXCEL_ID_DEFCOLWIDTH = $0055;
|
INT_EXCEL_ID_DEFCOLWIDTH = $0055;
|
||||||
|
|
||||||
|
{ RECORD IDs which did not changed across versions 2-5 }
|
||||||
|
INT_EXCEL_ID_EXTERNCOUNT = $0016; // does not exist in BIFF8
|
||||||
|
|
||||||
{ RECORD IDs which did not change across versions 2, 5, 8}
|
{ RECORD IDs which did not change across versions 2, 5, 8}
|
||||||
INT_EXCEL_ID_FORMULA = $0006; // BIFF3: $0206, BIFF4: $0406
|
INT_EXCEL_ID_FORMULA = $0006; // BIFF3: $0206, BIFF4: $0406
|
||||||
INT_EXCEL_ID_DEFINEDNAME = $0018; // BIFF3: $0218, BIFF4: $0218
|
INT_EXCEL_ID_DEFINEDNAME = $0018; // BIFF3-4: $0218
|
||||||
INT_EXCEL_ID_FONT = $0031; // BIFF3-4: $0231
|
INT_EXCEL_ID_FONT = $0031; // BIFF3-4: $0231
|
||||||
|
|
||||||
{ RECORD IDs which did not change across version 3-8}
|
{ RECORD IDs which did not change across version 3-8}
|
||||||
@ -499,10 +502,18 @@ type
|
|||||||
procedure WriteDateMode(AStream: TStream);
|
procedure WriteDateMode(AStream: TStream);
|
||||||
// Writes out a TIME/DATE/TIMETIME
|
// Writes out a TIME/DATE/TIMETIME
|
||||||
procedure WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal;
|
procedure WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal;
|
||||||
const AValue: TDateTime; ACell: PCell); override;
|
const AValue: TDateTime; ACell: PCell); override;
|
||||||
|
// Writes out DEFINEDNAMES records
|
||||||
|
procedure WriteDefinedName(AStream: TStream; AWorksheet: TsWorksheet;
|
||||||
|
const AName: String; AIndexToREF: Word); virtual;
|
||||||
|
procedure WriteDefinedNames(AStream: TStream);
|
||||||
// Writes out ERROR cell record
|
// Writes out ERROR cell record
|
||||||
procedure WriteError(AStream: TStream; const ARow, ACol: Cardinal;
|
procedure WriteError(AStream: TStream; const ARow, ACol: Cardinal;
|
||||||
const AValue: TsErrorValue; ACell: PCell); override;
|
const AValue: TsErrorValue; ACell: PCell); override;
|
||||||
|
// Writes out an EXTERNCOUNT record
|
||||||
|
procedure WriteEXTERNCOUNT(AStream: TStream);
|
||||||
|
// Writes out an EXTERNSHEET record
|
||||||
|
procedure WriteEXTERNSHEET(AStream: TStream); virtual;
|
||||||
// Writes out a FORMAT record
|
// Writes out a FORMAT record
|
||||||
procedure WriteFORMAT(AStream: TStream; ANumFormatStr: String;
|
procedure WriteFORMAT(AStream: TStream; ANumFormatStr: String;
|
||||||
ANumFormatIndex: Integer); virtual;
|
ANumFormatIndex: Integer); virtual;
|
||||||
@ -2884,6 +2895,34 @@ begin
|
|||||||
WriteNumber(AStream, ARow, ACol, ExcelDateSerial, ACell);
|
WriteNumber(AStream, ARow, ACol, ExcelDateSerial, ACell);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadBIFFWriter.WriteDefinedName(AStream: TStream;
|
||||||
|
AWorksheet: TsWorksheet; const AName: String; AIndexToREF: Word);
|
||||||
|
begin
|
||||||
|
// Override
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadBIFFWriter.WriteDefinedNames(AStream: TStream);
|
||||||
|
var
|
||||||
|
sheet: TsWorksheet;
|
||||||
|
i: Integer;
|
||||||
|
n: Word;
|
||||||
|
begin
|
||||||
|
n := 0;
|
||||||
|
for i:=0 to FWorkbook.GetWorksheetCount-1 do
|
||||||
|
begin
|
||||||
|
sheet := FWorkbook.GetWorksheetByIndex(i);
|
||||||
|
if (sheet.NumPrintRanges > 0) or
|
||||||
|
sheet.HasRepeatedPrintCols or sheet.HasRepeatedPrintRows then
|
||||||
|
begin
|
||||||
|
if sheet.NumPrintRanges > 0 then
|
||||||
|
WriteDefinedName(AStream, sheet, #6, n);
|
||||||
|
if sheet.HasRepeatedPrintCols or sheet.HasRepeatedPrintRows then
|
||||||
|
WriteDefinedName(AStream, sheet, #7, n);
|
||||||
|
inc(n);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Writes an ERROR cell record.
|
Writes an ERROR cell record.
|
||||||
Valid for BIFF3-BIFF8. Override for BIFF2.
|
Valid for BIFF3-BIFF8. Override for BIFF2.
|
||||||
@ -2915,6 +2954,64 @@ begin
|
|||||||
AStream.WriteBuffer(rec, SizeOf(rec));
|
AStream.WriteBuffer(rec, SizeOf(rec));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Writes a BIFF EXTERNCOUNT record.
|
||||||
|
Valid for BIFF2-BIFF5.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsSpreadBIFFWriter.WriteEXTERNCOUNT(AStream: TStream);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
n: Word;
|
||||||
|
sheet: TsWorksheet;
|
||||||
|
begin
|
||||||
|
n := 0;
|
||||||
|
for i := 0 to FWorkbook.GetWorksheetCount-1 do
|
||||||
|
begin
|
||||||
|
sheet := FWorkbook.GetWorksheetByIndex(i);
|
||||||
|
if (sheet.NumPrintRanges > 0) or
|
||||||
|
sheet.HasRepeatedPrintCols or sheet.HasRepeatedPrintRows then inc(n);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if n < 1 then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
{ BIFF record header }
|
||||||
|
WriteBIFFHeader(AStream, INT_EXCEL_ID_EXTERNCOUNT, 2);
|
||||||
|
|
||||||
|
{ Count of EXTERNSHEET records following }
|
||||||
|
AStream.WriteWord(WordToLE(n));
|
||||||
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Writes a BIFF EXTERNSHEET record.
|
||||||
|
Valid for BIFF2-BIFF5.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsSpreadBIFFWriter.WriteEXTERNSHEET(AStream: TStream);
|
||||||
|
var
|
||||||
|
sheet: TsWorksheet;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i := 0 to FWorkbook.GetWorksheetCount-1 do
|
||||||
|
begin
|
||||||
|
sheet := FWorkbook.GetWorksheetByIndex(i);
|
||||||
|
if (sheet.NumPrintRanges > 0) or
|
||||||
|
sheet.HasRepeatedPrintCols or sheet.HasRepeatedPrintRows then
|
||||||
|
begin
|
||||||
|
{ BIFF record header }
|
||||||
|
WriteBIFFHeader(AStream, INT_EXCEL_ID_EXTERNSHEET, 2 + Length(sheet.Name));
|
||||||
|
|
||||||
|
{ Character count in worksheet name }
|
||||||
|
AStream.WriteByte(Length(sheet.Name));
|
||||||
|
|
||||||
|
{ Flag for identification as own sheet }
|
||||||
|
AStream.WriteByte($03);
|
||||||
|
|
||||||
|
{ Sheet name }
|
||||||
|
AStream.WriteBuffer(sheet.Name[1], Length(sheet.Name));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Writes the a margin record for printing (margin is in inches).
|
Writes the a margin record for printing (margin is in inches).
|
||||||
The margin is identified by the parameter AMargin:
|
The margin is identified by the parameter AMargin:
|
||||||
|
Reference in New Issue
Block a user