You've already forked lazarus-ccr
fpspreadsheet: Move writing of BLANK and NUMBER records from xlsbiff5 and xlsbiff8 to xlscommon. No regression.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2990 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -109,8 +109,10 @@ type
|
||||
WorkBookEncoding: TsEncoding;
|
||||
protected
|
||||
{ Record writing methods }
|
||||
{
|
||||
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
ACell: PCell); override;
|
||||
}
|
||||
procedure WriteBOF(AStream: TStream; ADataType: Word);
|
||||
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
|
||||
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
||||
@ -120,8 +122,6 @@ type
|
||||
procedure WriteIndex(AStream: TStream);
|
||||
procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: string; ACell: PCell); override;
|
||||
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: double; ACell: PCell); override;
|
||||
procedure WriteRPNFormula(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AFormula: TsRPNFormula; ACell: PCell); override;
|
||||
procedure WriteStyle(AStream: TStream);
|
||||
@ -133,7 +133,6 @@ type
|
||||
AWordWrap: Boolean = false; AddBackground: Boolean = false;
|
||||
ABackgroundColor: TsColor = scSilver);
|
||||
procedure WriteXFFieldsForFormattingStyles(AStream: TStream);
|
||||
procedure WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
procedure WriteXFRecords(AStream: TStream);
|
||||
public
|
||||
{ General writing methods }
|
||||
@ -221,17 +220,13 @@ implementation
|
||||
|
||||
const
|
||||
{ Excel record IDs }
|
||||
INT_EXCEL_ID_BLANK = $0201;
|
||||
INT_EXCEL_ID_BOF = $0809;
|
||||
INT_EXCEL_ID_BOUNDSHEET = $0085; // Renamed to SHEET in the latest OpenOffice docs
|
||||
INT_EXCEL_ID_EOF = $000A;
|
||||
INT_EXCEL_ID_DIMENSIONS = $0200;
|
||||
INT_EXCEL_ID_FONT = $0031;
|
||||
INT_EXCEL_ID_FORMAT = $041E;
|
||||
INT_EXCEL_ID_FORMULA = $0006;
|
||||
INT_EXCEL_ID_INDEX = $020B;
|
||||
INT_EXCEL_ID_LABEL = $0204;
|
||||
INT_EXCEL_ID_NUMBER = $0203;
|
||||
INT_EXCEL_ID_ROWINFO = $0208;
|
||||
INT_EXCEL_ID_STYLE = $0293;
|
||||
INT_EXCEL_ID_WINDOW1 = $003D;
|
||||
@ -434,7 +429,7 @@ begin
|
||||
|
||||
SetLength(Boundsheets, 0);
|
||||
end;
|
||||
|
||||
(*
|
||||
{*******************************************************************
|
||||
* TsSpreadBIFF5Writer.WriteBlank
|
||||
*
|
||||
@ -455,7 +450,7 @@ begin
|
||||
{ Index to XF record }
|
||||
WriteXFIndex(AStream, ACell);
|
||||
end;
|
||||
|
||||
*)
|
||||
{*******************************************************************
|
||||
* TsSpreadBIFF5Writer.WriteBOF ()
|
||||
*
|
||||
@ -927,49 +922,6 @@ begin
|
||||
}
|
||||
end;
|
||||
|
||||
{*******************************************************************
|
||||
* TsSpreadBIFF5Writer.WriteNumber ()
|
||||
*
|
||||
* DESCRIPTION: Writes an Excel 5 NUMBER record
|
||||
*
|
||||
* Writes a number (64-bit floating point) to the sheet
|
||||
*
|
||||
*******************************************************************}
|
||||
procedure TsSpreadBIFF5Writer.WriteNumber(AStream: TStream; const ARow,
|
||||
ACol: Cardinal; const AValue: double; ACell: PCell);
|
||||
begin
|
||||
{ BIFF Record header }
|
||||
AStream.WriteWord(WordToLE(INT_EXCEL_ID_NUMBER));
|
||||
AStream.WriteWord(WordToLE(14));
|
||||
|
||||
{ BIFF Record data }
|
||||
AStream.WriteWord(WordToLE(ARow));
|
||||
AStream.WriteWord(WordToLE(ACol));
|
||||
|
||||
{ Index to XF record }
|
||||
WriteXFIndex(AStream, ACell);
|
||||
|
||||
{ IEE 754 floating-point value }
|
||||
AStream.WriteBuffer(AValue, 8);
|
||||
end;
|
||||
(*
|
||||
{*******************************************************************
|
||||
* TsSpreadBIFF2Writer.WriteDateTime ()
|
||||
*
|
||||
* DESCRIPTION: Writes a date/time value as a text
|
||||
* ISO 8601 format is used to preserve interoperability
|
||||
* between locales.
|
||||
*
|
||||
* Note: this should be replaced by writing actual date/time values
|
||||
*
|
||||
*******************************************************************}
|
||||
procedure TsSpreadBIFF5Writer.WriteDateTime(AStream: TStream;
|
||||
const ARow, ACol: Cardinal; const AValue: TDateTime; ACell: PCell);
|
||||
begin
|
||||
WriteLabel(AStream, ARow, ACol, FormatDateTime(ISO8601Format, AValue), ACell);
|
||||
end;
|
||||
*)
|
||||
|
||||
{*******************************************************************
|
||||
* TsSpreadBIFF5Writer.WriteStyle ()
|
||||
*
|
||||
@ -1285,56 +1237,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Index to XF record, according to formatting }
|
||||
procedure TsSpreadBIFF5Writer.WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
var
|
||||
lIndex: Integer;
|
||||
lXFIndex: Word;
|
||||
begin
|
||||
// First try the fast methods for default formats
|
||||
if ACell^.UsedFormattingFields = [] then
|
||||
begin
|
||||
AStream.WriteWord(WordToLE(15)); //XF15; see TsSpreadBIFF8Writer.AddDefaultFormats
|
||||
Exit;
|
||||
end;
|
||||
(*
|
||||
if ACell^.UsedFormattingFields = [uffTextRotation] then
|
||||
begin
|
||||
case ACell^.TextRotation of
|
||||
rt90DegreeCounterClockwiseRotation: AStream.WriteWord(WordToLE(16)); //XF_16
|
||||
rt90DegreeClockwiseRotation: AStream.WriteWord(WordToLE(17)); //XF_17
|
||||
else
|
||||
AStream.WriteWord(WordToLE(15)); //XF_15
|
||||
end;
|
||||
Exit;
|
||||
end;
|
||||
*)
|
||||
|
||||
{
|
||||
uffNumberFormat does not seem to have default XF indexes, but perhaps look at XF_21
|
||||
if ACell^.UsedFormattingFields = [uffNumberFormat] then
|
||||
begin
|
||||
case ACell^.NumberFormat of
|
||||
nfShortDate: AStream.WriteWord(WordToLE(???)); //what XF index?
|
||||
nfShortDateTime: AStream.WriteWord(WordToLE(???)); //what XF index?
|
||||
else
|
||||
AStream.WriteWord(WordToLE(15)); //e.g. nfGeneral: XF_15
|
||||
end;
|
||||
Exit;
|
||||
end;
|
||||
}
|
||||
|
||||
// If not, then we need to search in the list of dynamic formats
|
||||
lIndex := FindFormattingInList(ACell);
|
||||
// Carefully check the index
|
||||
if (lIndex < 0) or (lIndex > Length(FFormattingStyles)) then
|
||||
raise Exception.Create('[TsSpreadBIFF5Writer.WriteXFIndex] Invalid Index, this should not happen!');
|
||||
|
||||
lXFIndex := FFormattingStyles[lIndex].Row;
|
||||
|
||||
AStream.WriteWord(WordToLE(lXFIndex));
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF5Writer.WriteXFRecords(AStream: TStream);
|
||||
begin
|
||||
// XF0
|
||||
|
@ -107,12 +107,10 @@ type
|
||||
TsSpreadBIFF8Writer = class(TsSpreadBIFFWriter)
|
||||
private
|
||||
// Writes index to XF record according to cell's formatting
|
||||
procedure WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
//procedure WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
procedure WriteXFFieldsForFormattingStyles(AStream: TStream);
|
||||
protected
|
||||
{ Record writing methods }
|
||||
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
ACell: PCell); override;
|
||||
procedure WriteBOF(AStream: TStream; ADataType: Word);
|
||||
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
|
||||
// procedure WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
@ -126,8 +124,6 @@ type
|
||||
procedure WriteIndex(AStream: TStream);
|
||||
procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: string; ACell: PCell); override;
|
||||
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: double; ACell: PCell); override;
|
||||
procedure WriteRPNFormula(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AFormula: TsRPNFormula; ACell: PCell); override;
|
||||
procedure WriteStyle(AStream: TStream);
|
||||
@ -223,7 +219,6 @@ implementation
|
||||
|
||||
const
|
||||
{ Excel record IDs }
|
||||
INT_EXCEL_ID_BLANK = $0201;
|
||||
INT_EXCEL_ID_BOF = $0809;
|
||||
INT_EXCEL_ID_BOUNDSHEET = $0085; // Renamed to SHEET in the latest OpenOffice docs
|
||||
INT_EXCEL_ID_COUNTRY = $008C;
|
||||
@ -231,8 +226,6 @@ const
|
||||
INT_EXCEL_ID_DIMENSIONS = $0200;
|
||||
INT_EXCEL_ID_FORMULA = $0006;
|
||||
INT_EXCEL_ID_INDEX = $020B;
|
||||
INT_EXCEL_ID_LABEL = $0204;
|
||||
INT_EXCEL_ID_NUMBER = $0203;
|
||||
INT_EXCEL_ID_ROWINFO = $0208;
|
||||
INT_EXCEL_ID_STYLE = $0293;
|
||||
INT_EXCEL_ID_WINDOW1 = $003D;
|
||||
@ -308,57 +301,6 @@ const
|
||||
|
||||
{ TsSpreadBIFF8Writer }
|
||||
|
||||
{ Index to XF record, according to formatting }
|
||||
procedure TsSpreadBIFF8Writer.WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
var
|
||||
lIndex: Integer;
|
||||
lXFIndex: Word;
|
||||
begin
|
||||
// First try the fast methods for default formats
|
||||
if ACell^.UsedFormattingFields = [] then
|
||||
begin
|
||||
AStream.WriteWord(WordToLE(15)); //XF15; see TsSpreadBIFF8Writer.AddDefaultFormats
|
||||
Exit;
|
||||
end;
|
||||
|
||||
{
|
||||
if ACell^.UsedFormattingFields = [uffTextRotation] then
|
||||
begin
|
||||
case ACell^.TextRotation of
|
||||
rt90DegreeCounterClockwiseRotation: AStream.WriteWord(WordToLE(16)); //XF_16
|
||||
rt90DegreeClockwiseRotation: AStream.WriteWord(WordToLE(17)); //XF_17
|
||||
else
|
||||
AStream.WriteWord(WordToLE(15)); //XF_15
|
||||
end;
|
||||
Exit;
|
||||
end;
|
||||
}
|
||||
|
||||
{
|
||||
uffNumberFormat does not seem to have default XF indexes, but perhaps look at XF_21
|
||||
if ACell^.UsedFormattingFields = [uffNumberFormat] then
|
||||
begin
|
||||
case ACell^.NumberFormat of
|
||||
nfShortDate: AStream.WriteWord(WordToLE(???)); //what XF index?
|
||||
nfShortDateTime: AStream.WriteWord(WordToLE(???)); //what XF index?
|
||||
else
|
||||
AStream.WriteWord(WordToLE(15)); //e.g. nfGeneral: XF_15
|
||||
end;
|
||||
Exit;
|
||||
end;
|
||||
}
|
||||
|
||||
// If not, then we need to search in the list of dynamic formats
|
||||
lIndex := FindFormattingInList(ACell);
|
||||
// Carefully check the index
|
||||
if (lIndex < 0) or (lIndex > Length(FFormattingStyles)) then
|
||||
raise Exception.Create('[TsSpreadBIFF8Writer.WriteXFIndex] Invalid Index, this should not happen!');
|
||||
|
||||
lXFIndex := FFormattingStyles[lIndex].Row;
|
||||
|
||||
AStream.WriteWord(WordToLE(lXFIndex));
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF8Writer.WriteXFFieldsForFormattingStyles(AStream: TStream);
|
||||
var
|
||||
i: Integer;
|
||||
@ -574,27 +516,6 @@ begin
|
||||
SetLength(Boundsheets, 0);
|
||||
end;
|
||||
|
||||
{*******************************************************************
|
||||
* TsSpreadBIFF8Writer.WriteBlank
|
||||
*
|
||||
* DESCRIPTION: Writes the record for an empty cell
|
||||
*
|
||||
*******************************************************************}
|
||||
procedure TsSpreadBIFF8Writer.WriteBlank(AStream: TStream;
|
||||
const ARow, ACol: Cardinal; ACell: PCell);
|
||||
begin
|
||||
{ BIFF Record header }
|
||||
AStream.WriteWord(WordToLE(INT_EXCEL_ID_BLANK));
|
||||
AStream.WriteWord(WordToLE(6));
|
||||
|
||||
{ BIFF Record data }
|
||||
AStream.WriteWord(WordToLE(ARow));
|
||||
AStream.WriteWord(WordToLE(ACol));
|
||||
|
||||
{ Index to XF record, according to formatting }
|
||||
WriteXFIndex(AStream, ACell);
|
||||
end;
|
||||
|
||||
|
||||
{*******************************************************************
|
||||
* TsSpreadBIFF8Writer.WriteBOF ()
|
||||
@ -1167,32 +1088,6 @@ begin
|
||||
}
|
||||
end;
|
||||
|
||||
{*******************************************************************
|
||||
* TsSpreadBIFF8Writer.WriteNumber ()
|
||||
*
|
||||
* DESCRIPTION: Writes an Excel 8 NUMBER record
|
||||
*
|
||||
* Writes a number (64-bit floating point) to the sheet
|
||||
*
|
||||
*******************************************************************}
|
||||
procedure TsSpreadBIFF8Writer.WriteNumber(AStream: TStream; const ARow,
|
||||
ACol: Cardinal; const AValue: double; ACell: PCell);
|
||||
begin
|
||||
{ BIFF Record header }
|
||||
AStream.WriteWord(WordToLE(INT_EXCEL_ID_NUMBER));
|
||||
AStream.WriteWord(WordToLE(14)); //total record size
|
||||
|
||||
{ BIFF Record data }
|
||||
AStream.WriteWord(WordToLE(ARow));
|
||||
AStream.WriteWord(WordToLE(ACol));
|
||||
|
||||
{ Index to XF record, according to formatting }
|
||||
WriteXFIndex(AStream, ACell);
|
||||
|
||||
{ IEE 754 floating-point value (is different in BIGENDIAN???) }
|
||||
AStream.WriteBuffer(AValue, 8);
|
||||
end;
|
||||
|
||||
{*******************************************************************
|
||||
* TsSpreadBIFF8Writer.WriteStyle ()
|
||||
*
|
||||
|
@ -23,6 +23,11 @@ const
|
||||
INT_EXCEL_ID_PALETTE = $0092;
|
||||
INT_EXCEL_ID_XF = $00E0;
|
||||
|
||||
{ RECORD IDs which did not change across versions 5-8 }
|
||||
INT_EXCEL_ID_BLANK = $0201;
|
||||
INT_EXCEL_ID_NUMBER = $0203;
|
||||
INT_EXCEL_ID_LABEL = $0204;
|
||||
|
||||
{ FONT record constants }
|
||||
INT_FONT_WEIGHT_NORMAL = $0190;
|
||||
INT_FONT_WEIGHT_BOLD = $02BC;
|
||||
@ -371,6 +376,9 @@ type
|
||||
function GetLastColIndex(AWorksheet: TsWorksheet): Word;
|
||||
function FormulaElementKindToExcelTokenID(AElementKind: TFEKind; out ASecondaryID: Word): Word;
|
||||
|
||||
// Write out BLANK cell record
|
||||
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
ACell: PCell); override;
|
||||
// Write out used codepage for character encoding
|
||||
procedure WriteCodepage(AStream: TStream; AEncoding: TsEncoding);
|
||||
// Writes out column info(s)
|
||||
@ -381,8 +389,13 @@ type
|
||||
// Writes out a TIME/DATE/TIMETIME
|
||||
procedure WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: TDateTime; ACell: PCell); override;
|
||||
// Writes out a floating point NUMBER record
|
||||
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: Double; ACell: PCell); override;
|
||||
// Writes out a PALETTE record containing all colors defined in the workbook
|
||||
procedure WritePalette(AStream: TStream);
|
||||
// Writes the index of the XF record used in the given cell
|
||||
procedure WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
|
||||
public
|
||||
constructor Create(AWorkbook: TsWorkbook); override;
|
||||
@ -1083,6 +1096,24 @@ begin
|
||||
Result := FLastCol;
|
||||
end;
|
||||
|
||||
{ Writes an empty ("blank") cell. Needed for formatting empty cells.
|
||||
Valid for BIFF5 and BIFF8. Needs to be overridden for BIFF2 which has a
|
||||
different record structure. }
|
||||
procedure TsSpreadBIFFWriter.WriteBlank(AStream: TStream;
|
||||
const ARow, ACol: Cardinal; ACell: PCell);
|
||||
begin
|
||||
{ BIFF Record header }
|
||||
AStream.WriteWord(WordToLE(INT_EXCEL_ID_BLANK));
|
||||
AStream.WriteWord(WordToLE(6));
|
||||
|
||||
{ Row and column index }
|
||||
AStream.WriteWord(WordToLE(ARow));
|
||||
AStream.WriteWord(WordToLE(ACol));
|
||||
|
||||
{ Index to XF record, according to formatting }
|
||||
WriteXFIndex(AStream, ACell);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFFWriter.WriteCodepage(AStream: TStream;
|
||||
AEncoding: TsEncoding);
|
||||
var
|
||||
@ -1107,6 +1138,8 @@ begin
|
||||
AStream.WriteWord(WordToLE(lCodepage));
|
||||
end;
|
||||
|
||||
{ Writes column info for the given column. Currently only the colum width is used.
|
||||
Valid for BIFF5 and BIFF8 (BIFF2 uses a different record. }
|
||||
procedure TsSpreadBIFFWriter.WriteColInfo(AStream: TStream; ACol: PCol);
|
||||
var
|
||||
w: Integer;
|
||||
@ -1126,6 +1159,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Writes the column info records for all used columns. }
|
||||
procedure TsSpreadBIFFWriter.WriteColInfos(AStream: TStream;
|
||||
ASheet: TsWorksheet);
|
||||
var
|
||||
@ -1167,6 +1201,26 @@ begin
|
||||
WriteNumber(AStream, ARow, ACol, ExcelDateSerial, ACell);
|
||||
end;
|
||||
|
||||
{ Writes a 64-bit floating point NUMBER record.
|
||||
Valid for BIFF5 and BIFF8 (BIFF2 has a different record structure.). }
|
||||
procedure TsSpreadBIFFWriter.WriteNumber(AStream: TStream;
|
||||
const ARow, ACol: Cardinal; const AValue: double; ACell: PCell);
|
||||
begin
|
||||
{ BIFF Record header }
|
||||
AStream.WriteWord(WordToLE(INT_EXCEL_ID_NUMBER));
|
||||
AStream.WriteWord(WordToLE(14));
|
||||
|
||||
{ BIFF Record data }
|
||||
AStream.WriteWord(WordToLE(ARow));
|
||||
AStream.WriteWord(WordToLE(ACol));
|
||||
|
||||
{ Index to XF record }
|
||||
WriteXFIndex(AStream, ACell);
|
||||
|
||||
{ IEE 754 floating-point value }
|
||||
AStream.WriteBuffer(AValue, 8);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFFWriter.WritePalette(AStream: TStream);
|
||||
var
|
||||
i, n: Integer;
|
||||
@ -1189,6 +1243,33 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
{ Write the index of the XF record, according to formatting of the given cell
|
||||
Valid for BIFF5 and BIFF8.
|
||||
BIFF2 is handled differently. }
|
||||
procedure TsSpreadBIFFWriter.WriteXFIndex(AStream: TStream; ACell: PCell);
|
||||
var
|
||||
lIndex: Integer;
|
||||
lXFIndex: Word;
|
||||
begin
|
||||
// First try the fast methods for default formats
|
||||
if ACell^.UsedFormattingFields = [] then begin
|
||||
AStream.WriteWord(WordToLE(15)); //XF15; see TsSpreadBIFF8Writer.AddDefaultFormats
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// If not, then we need to search in the list of dynamic formats
|
||||
lIndex := FindFormattingInList(ACell);
|
||||
|
||||
// Carefully check the index
|
||||
if (lIndex < 0) or (lIndex > Length(FFormattingStyles)) then
|
||||
raise Exception.Create('[TsSpreadBIFFWriter.WriteXFIndex] Invalid Index, this should not happen!');
|
||||
|
||||
lXFIndex := FFormattingStyles[lIndex].Row;
|
||||
|
||||
AStream.WriteWord(WordToLE(lXFIndex));
|
||||
end;
|
||||
|
||||
|
||||
{ Format checking procedures }
|
||||
|
||||
{ This simple parsing procedure of the Excel format string checks for a fixed
|
||||
|
Reference in New Issue
Block a user