fpspreadsheet: Add column width support (reading & writing) to biff2. Add column width test cases for BIFF2 and BIFF8 -> pass.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2964 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-04-24 23:05:00 +00:00
parent 887b34383a
commit 988b80b4a4
5 changed files with 115 additions and 17 deletions

View File

@@ -25,9 +25,12 @@ begin
MyWorkbook := TsWorkbook.Create;
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet');
//MyWorksheet.WriteColWidth(0, 5);
//MyWorksheet.WriteColWidth(1, 30);
// Write some number cells
MyWorksheet.WriteNumber(0, 0, 1.0);
MyWorksheet.WriteFont(0, 0, 'Arial', 11, [fssBold, fssItalic], scBlack);
// MyWorksheet.WriteFont(0, 0, 'Arial', 11, [fssBold, fssItalic], scBlack);
MyWorksheet.WriteNumber(0, 1, 2.0);
MyWorksheet.WriteNumber(0, 2, 3.0);

View File

@@ -356,6 +356,7 @@ type
procedure RemoveAllCols;
procedure WriteRowInfo(ARow: Cardinal; AData: TRow);
procedure WriteColInfo(ACol: Cardinal; AData: TCol);
procedure WriteColWidth(ACol: Cardinal; AWidth: Single);
{ Properties }
property Cells: TAVLTree read FCells;
property Cols: TIndexedAVLTree read FCols;
@@ -1574,6 +1575,15 @@ begin
AElement^.Width := AData.Width;
end;
procedure TsWorksheet.WriteColWidth(ACol: Cardinal; AWidth: Single);
var
AElement: PCol;
begin
AElement := GetCol(ACol);
AElement^.Width := AWidth;
end;
{ TsWorkbook }
{@@

View File

@@ -41,6 +41,7 @@ type
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure TestWriteReadColWidths(AFormat: TsSpreadsheetFormat);
published
// Writes out numbers & reads back.
// If previous read tests are ok, this effectively tests writing.
@@ -48,7 +49,8 @@ type
// Repeat with date/times
procedure TestWriteReadDateTimeFormats;
// Test column width
procedure TestWriteReadColWidths;
procedure TestWriteReadBIFF2_ColWidths;
procedure TestWriteReadBIFF8_ColWidths;
// Test word wrapping
procedure TestWriteReadWordWrap;
// Test alignments
@@ -60,6 +62,7 @@ implementation
const
FmtNumbersSheet = 'NumbersFormat'; //let's distinguish it from the regular numbers sheet
FmtDateTimesSheet = 'DateTimesFormat';
ColWidthSheet = 'ColWidths';
// Initialize array with variables that represent the values
// we expect to be in the test spreadsheet files.
@@ -234,7 +237,7 @@ begin
DeleteFile(TempFile);
end;
procedure TSpreadWriteReadFormatTests.TestWriteReadColWidths;
procedure TSpreadWriteReadFormatTests.TestWriteReadColWidths(AFormat: TsSpreadsheetFormat);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
@@ -251,18 +254,21 @@ begin
}
// Write out all test values
MyWorkbook := TsWorkbook.Create;
MyWorkSheet:= MyWorkBook.AddWorksheet(FmtNumbersSheet);
MyWorkSheet:= MyWorkBook.AddWorksheet(ColWidthSheet);
for Col := Low(SollColWidths) to High(SollColWidths) do begin
lCol.Width := SollColWidths[Col];
MyWorksheet.WriteColInfo(Col, lCol);
end;
MyWorkBook.WriteToFile(TempFile,sfExcel8,true);
MyWorkBook.WriteToFile(TempFile, AFormat, true);
MyWorkbook.Free;
// Open the spreadsheet, as biff8
MyWorkbook := TsWorkbook.Create;
MyWorkbook.ReadFromFile(TempFile, sfExcel8);
MyWorksheet:=GetWorksheetByName(MyWorkBook, FmtNumbersSheet);
MyWorkbook.ReadFromFile(TempFile, AFormat);
if AFormat = sfExcel2 then
MyWorksheet := MyWorkbook.GetFirstWorksheet
else
MyWorksheet := GetWorksheetByName(MyWorkBook, ColWidthSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
for Col := Low(SollColWidths) to High(SollColWidths) do begin
@@ -396,6 +402,16 @@ begin
DeleteFile(TempFile);
end;
procedure TSpreadWriteReadFormatTests.TestWriteReadBIFF2_ColWidths;
begin
TestWriteReadColWidths(sfExcel2);
end;
procedure TSpreadWriteReadFormatTests.TestWriteReadBIFF8_ColWidths;
begin
TestWriteReadColWidths(sfExcel8);
end;
initialization
RegisterTest(TSpreadWriteReadFormatTests);
InitSollFmtData;

View File

@@ -52,8 +52,9 @@ type
procedure ApplyCellFormatting(ARow, ACol: Word; XF, AFormat, AFont, AStyle: Byte);
procedure ReadRowColStyle(AStream: TStream; out ARow, ACol: Word;
out XF, AFormat, AFont, AStyle: byte);
{ Record writing methods }
{ Record reading methods }
procedure ReadBlank(AStream: TStream); override;
procedure ReadColWidth(AStream: TStream);
procedure ReadFont(AStream: TStream);
procedure ReadFontColor(AStream: TStream);
procedure ReadFormula(AStream: TStream); override;
@@ -76,6 +77,8 @@ type
{ Record writing methods }
procedure WriteBOF(AStream: TStream);
procedure WriteCellFormatting(AStream: TStream; ACell: PCell; XFIndex: Word);
procedure WriteColWidth(AStream: TStream; ACol: PCol);
procedure WriteColWidths(AStream: TStream);
procedure WriteEOF(AStream: TStream);
procedure WriteFont(AStream: TStream; AFontIndex: Integer);
procedure WriteFonts(AStream: TStream);
@@ -122,6 +125,7 @@ const
INT_EXCEL_ID_ROWINFO = $0008;
INT_EXCEL_ID_BOF = $0009;
INT_EXCEL_ID_EOF = $000A;
INT_EXCEL_ID_COLWIDTH = $0024;
INT_EXCEL_ID_XF = $0043;
INT_EXCEL_ID_IXFE = $0044;
INT_EXCEL_ID_FONTCOLOR = $0045;
@@ -225,6 +229,41 @@ begin
AStream.WriteByte(b);
end;
{
Writes an Excel 2 COLWIDTH record
}
procedure TsSpreadBIFF2Writer.WriteColWidth(AStream: TStream; ACol: PCol);
var
w: Integer;
begin
if Assigned(ACol) then begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_COLWIDTH)); // BIFF record header
AStream.WriteWord(WordToLE(4)); // Record size
AStream.WriteByte(ACol^.Col); // start column
AStream.WriteByte(ACol^.Col); // end column
{ calculate width to be in units of 1/256 of pixel width of character "0" }
w := round(ACol^.Width * 256);
AStream.WriteWord(WordToLE(w)); // write width
end;
end;
{
Write COLWIDTH records for all columns
}
procedure TsSpreadBIFF2Writer.WriteColWidths(AStream: TStream);
var
j: Integer;
sheet: TsWorksheet;
col: PCol;
begin
sheet := Workbook.GetFirstWorksheet;
for j := 0 to sheet.Cols.Count-1 do begin
col := PCol(sheet.Cols[j]);
WriteColWidth(AStream, col);
end;
end;
{
Writes an Excel 2 IXFE record
This record contains the "real" XF index if it is > 62.
@@ -249,6 +288,7 @@ begin
WriteFonts(AStream);
WriteXFRecords(AStream);
WriteColWidths(AStream);
WriteCellsToStream(AStream, Workbook.GetFirstWorksheet.Cells);
WriteEOF(AStream);
@@ -858,6 +898,26 @@ begin
ApplyCellFormatting(ARow, ACol, XF, AFormat, AFont, AStyle);
end;
procedure TsSpreadBIFF2Reader.ReadColWidth(AStream: TStream);
var
c, c1, c2: Cardinal;
w: Word;
col: TCol;
sheet: TsWorksheet;
begin
sheet := Workbook.GetFirstWorksheet;
// read column start and end index of column range
c1 := AStream.ReadByte;
c2 := AStream.ReadByte;
// read col width in 1/256 of the width of "0" character
w := WordLEToN(AStream.ReadWord);
// calculate width in units of "characters"
col.Width := w / 256;
// assign width to columns
for c := c1 to c2 do
sheet.WriteColInfo(c, col);
end;
procedure TsSpreadBIFF2Reader.ReadFont(AStream: TStream);
var
lHeight: Word;
@@ -929,6 +989,7 @@ begin
INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
INT_EXCEL_ID_LABEL : ReadLabel(AStream);
INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
INT_EXCEL_ID_COLWIDTH : ReadColWidth(AStream);
INT_EXCEL_ID_ROWINFO : ReadRowInfo(AStream);
INT_EXCEL_ID_XF : ReadXF(AStream);
INT_EXCEL_ID_BOF : ;

View File

@@ -165,7 +165,8 @@ type
procedure WriteBOF(AStream: TStream; ADataType: Word);
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
// procedure WriteCodepage in xlscommon; Workbook Globals record
procedure WriteColInfo(AStream: TStream; ASheet: TsWorksheet; ACol: PCol);
procedure WriteColInfo(AStream: TStream; ACol: PCol);
procedure WriteColInfos(AStream: TStream; ASheet: TsWorksheet);
procedure WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal;
const AValue: TDateTime; ACell: PCell); override;
// procedure WriteDateMode in xlscommon; Workbook Globals record
@@ -682,10 +683,7 @@ begin
WriteIndex(AStream);
for j := 0 to sheet.Cols.Count-1 do begin
col := PCol(sheet.Cols[j]);
WriteColInfo(AStream, sheet, col);
end;
WriteColInfos(AStream, sheet);
WriteDimensions(AStream, sheet);
@@ -803,16 +801,15 @@ begin
end;
{*******************************************************************
* TsSpreadBIFF8Writer.WriteColumn ()
* TsSpreadBIFF8Writer.WriteColInfo ()
*
* DESCRIPTION: Writes a COLINFO record
*******************************************************************}
procedure TsSpreadBIFF8Writer.WriteColInfo(AStream: TStream;
ASheet: TsWorkSheet; ACol: PCol);
procedure TsSpreadBIFF8Writer.WriteColInfo(AStream: TStream; ACol: PCol);
var
w: Integer;
begin
if Assigned(ACol) and Assigned(ASheet) then begin
if Assigned(ACol) then begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_COLINFO)); // BIFF record header
AStream.WriteWord(WordToLE(12)); // Record size
@@ -827,6 +824,17 @@ begin
end;
end;
procedure TsSpreadBIFF8Writer.WriteColInfos(AStream: TStream;
ASheet: TsWorksheet);
var
j: Integer;
col: PCol;
begin
for j := 0 to ASheet.Cols.Count-1 do begin
col := PCol(ASheet.Cols[j]);
WriteColInfo(AStream, col);
end;
end;
{*******************************************************************
* TsSpreadBIFF8Writer.WriteDateTime ()