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:
wp_xxyyzz
2014-05-02 19:55:55 +00:00
parent 3eac7b8066
commit d777029bec
3 changed files with 86 additions and 208 deletions

View File

@ -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

View File

@ -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 ()
*

View File

@ -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