From 038d2240343e2e06448f9f70905266216642415c Mon Sep 17 00:00:00 2001 From: sekelsenmat Date: Wed, 25 May 2011 13:40:53 +0000 Subject: [PATCH] Adds a initial implementation of border support in FPSpreadsheet git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1641 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../excel8demo/excel8write_format.lpi | 178 ++++++++++++++++++ .../excel8demo/excel8write_format.pas | 64 +++++++ components/fpspreadsheet/fpspreadsheet.pas | 18 +- components/fpspreadsheet/xlsbiff8.pas | 87 ++++++--- 4 files changed, 316 insertions(+), 31 deletions(-) create mode 100644 components/fpspreadsheet/examples/excel8demo/excel8write_format.lpi create mode 100644 components/fpspreadsheet/examples/excel8demo/excel8write_format.pas diff --git a/components/fpspreadsheet/examples/excel8demo/excel8write_format.lpi b/components/fpspreadsheet/examples/excel8demo/excel8write_format.lpi new file mode 100644 index 000000000..381488aa5 --- /dev/null +++ b/components/fpspreadsheet/examples/excel8demo/excel8write_format.lpi @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/fpspreadsheet/examples/excel8demo/excel8write_format.pas b/components/fpspreadsheet/examples/excel8demo/excel8write_format.pas new file mode 100644 index 000000000..b7da69603 --- /dev/null +++ b/components/fpspreadsheet/examples/excel8demo/excel8write_format.pas @@ -0,0 +1,64 @@ +{ +excel8write.dpr + +Demonstrates how to write an Excel 8+ file using the fpspreadsheet library + +Adds formatting to the file + +AUTHORS: Felipe Monteiro de Carvalho +} +program excel8write_format; + +{$mode delphi}{$H+} + +uses + Classes, SysUtils, fpspreadsheet, xlsbiff8, + laz_fpspreadsheet, fpsconvencoding; + +var + MyWorkbook: TsWorkbook; + MyWorksheet: TsWorksheet; + MyDir: string; + MyCell: PCell; +begin + MyDir := ExtractFilePath(ParamStr(0)); + + // Create the spreadsheet + MyWorkbook := TsWorkbook.Create; + MyWorksheet := MyWorkbook.AddWorksheet('Worksheet1'); + + // Write some cells + MyWorksheet.WriteUTF8Text(1, 0, 'Border');// A2 + MyWorksheet.WriteUTF8Text(1, 1, '[]'); // B2 + MyWorksheet.WriteUTF8Text(1, 2, '[North]');// C2 + MyWorksheet.WriteUTF8Text(1, 3, '[West]');// D2 + MyWorksheet.WriteUTF8Text(1, 4, '[East]');// E2 + MyWorksheet.WriteUTF8Text(1, 5, '[South]');// F2 + + // Format them + + MyCell := MyWorksheet.GetCell(1, 1); + MyCell^.Border := []; + MyCell^.UsedFormattingFields := [uffBorder]; + + MyCell := MyWorksheet.GetCell(1, 2); + MyCell^.Border := [cbNorth]; + MyCell^.UsedFormattingFields := [uffBorder]; + + MyCell := MyWorksheet.GetCell(1, 3); + MyCell^.Border := [cbWest]; + MyCell^.UsedFormattingFields := [uffBorder]; + + MyCell := MyWorksheet.GetCell(1, 4); + MyCell^.Border := [cbEast]; + MyCell^.UsedFormattingFields := [uffBorder]; + + MyCell := MyWorksheet.GetCell(1, 5); + MyCell^.Border := [cbSouth]; + MyCell^.UsedFormattingFields := [uffBorder]; + + // Save the spreadsheet to a file + MyWorkbook.WriteToFile(MyDir + 'test3.xls', sfExcel8, False); + MyWorkbook.Free; +end. + diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index 1eff563ee..2a118e9e5 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -88,17 +88,29 @@ type {@@ List of possible formatting fields } - TsUsedFormattingField = (uffTextRotation, uffBold); + TsUsedFormattingField = (uffTextRotation, uffBold, uffBorder{, uffBackgroundColor}); {@@ Describes which formatting fields are active } TsUsedFormattingFields = set of TsUsedFormattingField; - {@@ Text rotation formatting} + {@@ Text rotation formatting } TsTextRotation = (trHorizontal, rt90DegreeClockwiseRotation, rt90DegreeCounterClockwiseRotation); + {@@ Indicates the border for a cell } + + TsCellBorder = (cbNorth, cbWest, cbEast, cbSouth); + + {@@ Indicates the border for a cell } + + TsCellBorders = set of TsCellBorder; + + {.@@ Colors in FPSpreadsheet as given by a list of possible default values } + + //TsColor = (); + {@@ Cell structure for TsWorksheet Never suppose that all *Value fields are valid, @@ -120,6 +132,8 @@ type { Formatting fields } UsedFormattingFields: TsUsedFormattingFields; TextRotation: TsTextRotation; + Border: TsCellBorders; + //BackgroundColor: TsColor; end; PCell = ^TCell; diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas index 9e3e60760..781af4db5 100755 --- a/components/fpspreadsheet/xlsbiff8.pas +++ b/components/fpspreadsheet/xlsbiff8.pas @@ -123,7 +123,7 @@ type procedure WriteWindow1(AStream: TStream); procedure WriteWindow2(AStream: TStream; ASheetSelected: Boolean); procedure WriteXF(AStream: TStream; AFontIndex: Word; - AXF_TYPE_PROT, ATextRotation: Byte); + AXF_TYPE_PROT, ATextRotation: Byte; ABorders: TsCellBorders); end; implementation @@ -324,43 +324,51 @@ begin end; // XF0 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF1 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF2 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF3 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF4 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF5 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF6 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF7 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF8 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF9 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF10 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF11 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF12 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF13 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); // XF14 - WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL); - // XF15 - WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL); - // XF16 - WriteXF(AStream, 0, 0, XF_ROTATION_90_DEGREE_COUNTERCLOCKWISE); - // XF17 - WriteXF(AStream, 0, 0, XF_ROTATION_90_DEGREE_CLOCKWISE); - // XF18 - WriteXF(AStream, 1, 0, XF_ROTATION_HORIZONTAL); + WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF, XF_ROTATION_HORIZONTAL, []); + // XF15 - Default, no formatting + WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, []); + // XF16 - Rotated + WriteXF(AStream, 0, 0, XF_ROTATION_90_DEGREE_COUNTERCLOCKWISE, []); + // XF17 - Rotated + WriteXF(AStream, 0, 0, XF_ROTATION_90_DEGREE_CLOCKWISE, []); + // XF18 - Bold + WriteXF(AStream, 1, 0, XF_ROTATION_HORIZONTAL, []); + // XF19 - Border + WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbNorth]); + // XF20 - Border + WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbWest]); + // XF21 - Border + WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbEast]); + // XF22 - Border + WriteXF(AStream, 0, 0, XF_ROTATION_HORIZONTAL, [cbSouth]); WriteStyle(AStream); @@ -753,6 +761,14 @@ begin begin AStream.WriteWord(WordToLE(18)); end + else if ACell^.UsedFormattingFields = [uffBorder] then + begin + if ACell^.Border = [] then AStream.WriteWord(WordToLE(15)) + else if ACell^.Border = [cbNorth] then AStream.WriteWord(WordToLE(19)) + else if ACell^.Border = [cbWest] then AStream.WriteWord(WordToLE(20)) + else if ACell^.Border = [cbEast] then AStream.WriteWord(WordToLE(21)) + else if ACell^.Border = [cbSouth] then AStream.WriteWord(WordToLE(22)); + end else AStream.WriteWord(WordToLE(15)); @@ -930,10 +946,11 @@ end; * *******************************************************************} procedure TsSpreadBIFF8Writer.WriteXF(AStream: TStream; AFontIndex: Word; - AXF_TYPE_PROT, ATextRotation: Byte); + AXF_TYPE_PROT, ATextRotation: Byte; ABorders: TsCellBorders); var XFOptions: Word; XFAlignment, XFOrientationAttrib: Byte; + XFBorderDWord1, XFBorderDWord2: DWord; begin { BIFF Record header } AStream.WriteWord(WordToLE(INT_EXCEL_ID_XF)); @@ -976,10 +993,22 @@ begin AStream.WriteByte(XFOrientationAttrib); { Cell border lines and background area } - AStream.WriteDWord(DWordToLE($00000000)); - AStream.WriteDWord(DWordToLE($00000000)); - AStream.WriteByte(0); - AStream.WriteByte(0); + + // Left and Right line colors, use black + XFBorderDWord1 := 8 * $10000 {left line - black} + 8 * $800000 {right line - black}; + + if cbNorth in ABorders then XFBorderDWord1 := XFBorderDWord1 or $100; + if cbWest in ABorders then XFBorderDWord1 := XFBorderDWord1 or $1; + if cbEast in ABorders then XFBorderDWord1 := XFBorderDWord1 or $10; + if cbSouth in ABorders then XFBorderDWord1 := XFBorderDWord1 or $1000; + + AStream.WriteDWord(DWordToLE(XFBorderDWord1)); + + // Top and Bottom line colors, use black + XFBorderDWord2 := 8 {top line - black} + 8 * $80 {bottom line - black}; + AStream.WriteDWord(DWordToLE(XFBorderDWord2)); + // Background Pattern Color, always zeroed + AStream.WriteWord(0); end; { TsSpreadBIFF8Reader }