From 0f73aed718c6d6b89d019dad44b4e642fbcbd27e Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Sat, 19 Apr 2014 16:58:44 +0000 Subject: [PATCH] fpspreadsheet: Implement reading of cell borders. Delete test.xls in examples/excel8demo. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2950 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../examples/excel8demo/test.xls | Bin 6144 -> 0 bytes components/fpspreadsheet/xlsbiff8.pas | 114 +++++++++++++++++- 2 files changed, 111 insertions(+), 3 deletions(-) delete mode 100644 components/fpspreadsheet/examples/excel8demo/test.xls diff --git a/components/fpspreadsheet/examples/excel8demo/test.xls b/components/fpspreadsheet/examples/excel8demo/test.xls deleted file mode 100644 index 301e0ee97ba54334cf1a1d88330d48de5c7606ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6144 zcmeHLOK%%h6h1Q^2d5!%;wB++9LK4hx{wBNLV1%WsELHsNT^N(RASLm1EFmSsf*|W z;Z64lR)_`SCm1oQ@05-ZZ{eQM)+=J;hQDvt>vfkD!R=oA7mdL0@Rjoy^X4&* zE9d++AOUm&`vCUYYyZ6wI3XACsY*^3WDVDKxs2IvzYR*<@<%0z4ZDatcwXyvJ3R&K z>vC33s~=}~k=*_`C3aw+er)eyW?u2^o1gx5tUq>t*Oha|IL`ggd1e>?)63GCvIxO_QwjYqz=$8<-p%6l`< zjy$N0B~RNW?BlEWRe$46FVM%WdBpBjIVI(~lWW(6&F_S@zF8eM`O<*GC3_ z4gcO3&jMv|Q=>!PR}I%1f8b_gV*{6(Y;A4H=H@1|*MB6gYit#{QO}9|hRn=KID)pv z-oWTI+4Dtt5xpy# z$4_g$=En8jNL=r-Iiu0`Iy&Ui%@2uV z4~T=rHi=@^TGk4Or_{qj9~@-6zMlp4Ar6MSgRL;<*kd||N$C=6O`exBhL>eZ75X_L z6;-njt_;eLKY#mp_4E%a#D!uITE-c9-V=gGlbX%6<#1UY zPC-F7q+m*mnt!|8>~|LCCL-ptFc&atE{jMu5iysAxqyMWlGfU~ z7P*a{#A;Z_`&IPspHqlE72`bQVf>&hoS$7;S^4!S)f9Bpv7~oW)BFwvs40fjOu#oz z9>NUO_%YxK^@g6ks^tYoasr}<0#P2a?H+OhX*Ns09ekS)F~?@A!ap_QVsYcFW1Cck yhY5vKJWR^Edl;q9-~sz{kD@;pFeON{KhGHSUqnQ|1iFgH^tnmC{Yw4T^!x*#1~bqA diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas index 530e01e25..494fc7d0c 100755 --- a/components/fpspreadsheet/xlsbiff8.pas +++ b/components/fpspreadsheet/xlsbiff8.pas @@ -66,6 +66,19 @@ type TXFRecordData = class public FormatIndex: Integer; + Borders: TsCellBorders; + { + FontIndex: Integer; + Border: TsBorder; + XFType_Protection: Word; + Align_TextBreak: Byte; + XF_Rotation: Byte; + Indent_Shrink_TextDir: Byte; + UsedAttrib: Byte; + Border_Background1: DWord; + Border_Background2: DWord; + Border_Background3: Word; + } end; TFormatRecordData = class @@ -87,6 +100,7 @@ type FXFList: TFPList; // of TXFRecordData FFormatList: TFPList; // of TFormatRecordData function DecodeRKValue(const ARK: DWORD): Double; + procedure ApplyCellFormatting(ARow, ACol: Cardinal; XFIndex: Integer); procedure ExtractNumberFormat(AXFIndex: WORD; out ANumberFormat: TsNumberFormat; out ADecimals: Word; out ANumberFormatStr: String); @@ -1972,6 +1986,9 @@ begin FWorksheet.WriteDateTime(ARow, ACol, lDateTime, nf, nfs) else FWorksheet.WriteNumber(ARow, ACol, Number, nf); + + {Add attributes} + ApplyCellFormatting(ARow, ACol, XF); end; procedure TsSpreadBIFF8Reader.ReadMulRKValues(const AStream: TStream); @@ -2021,6 +2038,26 @@ begin AXF:=WordLEtoN(AStream.ReadWord); end; +{ Applies the XF formatting given by the given index to the specified cell } +procedure TsSpreadBIFF8Reader.ApplyCellFormatting(ARow, ACol: Cardinal; + XFIndex: Integer); +var + lCell: PCell; + XFData: TXFRecordData; +begin + lCell := FWorksheet.FindCell(ARow, ACol); + if Assigned(lCell) then begin + XFData := TXFRecordData(FXFList.Items[XFIndex]); + + // Borders + if XFData.Borders <> [] then begin + Include(lCell^.UsedFormattingFields, uffBorder); + lCell^.Border := XFData.Borders; + end else + Exclude(lCell^.UsedFormattingFields, uffBorder); + end; +end; + function TsSpreadBIFF8Reader.ReadString(const AStream: TStream; const ALength: WORD): UTF8String; begin @@ -2150,22 +2187,31 @@ begin if SizeOf(Double)<>8 then Raise Exception.Create('Double is not 8 bytes'); Move(Data[0],ResultFormula,sizeof(Data)); FWorksheet.WriteNumber(ARow,ACol,ResultFormula); + + {Add attributes} + ApplyCellFormatting(ARow, ACol, XF); end; procedure TsSpreadBIFF8Reader.ReadLabel(AStream: TStream); var L: Word; StringFlags: BYTE; - ARow, ACol: Word; + ARow, ACol, XF: Word; WideStrValue: WideString; AnsiStrValue: AnsiString; begin - { BIFF Record data } +(* +{ BIFF Record data } ARow := WordLEToN(AStream.ReadWord); ACol := WordLEToN(AStream.ReadWord); { Index to XF record, not used } AStream.ReadWord(); +*) + { BIFF Record header } + { BIFF Record data } + { Index to XF Record } + ReadRowColXF(AStream,ARow,ACol,XF); { Byte String with 16-bit size } L := WordLEtoN(AStream.ReadWord()); @@ -2175,6 +2221,9 @@ begin { Save the data } FWorksheet.WriteUTF8Text(ARow, ACol, UTF16ToUTF8(WideStrValue)); + + {Add attributes} + ApplyCellFormatting(ARow, ACol, XF); end; procedure TsSpreadBIFF8Reader.ReadNumber(AStream: TStream); @@ -2200,6 +2249,9 @@ begin FWorksheet.WriteDateTime(ARow, ACol, lDateTime, nf, nfs) else FWorksheet.WriteNumber(ARow,ACol,AValue,nf,nd); + + {Add attributes} + ApplyCellFormatting(ARow, ACol, XF); end; procedure TsSpreadBIFF8Reader.ReadRichString(const AStream: TStream); @@ -2223,6 +2275,9 @@ begin AStream.ReadWord; // First formatted character AStream.ReadWord; // Index to FONT record end; + + {Add attributes} + ApplyCellFormatting(ARow, ACol, XF); end; procedure TsSpreadBIFF8Reader.ReadSST(const AStream: TStream); @@ -2303,14 +2358,52 @@ begin Raise Exception.CreateFmt('Index %d in SST out of range (0-%d)',[Integer(SSTIndex),FSharedStringTable.Count-1]); end; FWorksheet.WriteUTF8Text(ARow, ACol, FSharedStringTable[SSTIndex]); + + {Add attributes} + ApplyCellFormatting(ARow, ACol, XF); end; procedure TsSpreadBIFF8Reader.ReadXF(const AStream: TStream); +type + TXFRecord = packed record // see p. 224 + FontIndex: Word; // Offset 0, Size 2 + FormatIndex: Word; // Offset 2, Size 2 + XFType_CellProt_ParentStyleXF: Word; // Offset 4, Size 2 + Align_TextBreak: Byte; // Offset 6, Size 1 + XFRotation: Byte; // Offset 7, Size 1 + Indent_Shrink_TextDir: Byte; // Offset 8, Size 1 + UnusedAttrib: Byte; // Offset 9, Size 1 + Border_Background_1: DWord; // Offset 10, Size 4 + Border_Background_2: DWord; // Offset 14, Size 4 + Border_Background_3: DWord; // Offset 18, Size 2 + end; var lData: TXFRecordData; + xf: TXFRecord; begin + AStream.ReadBuffer(xf, SizeOf(xf)); +{ xf.FormatIndex := WordLEToN(xf.FormatIndex); + xf.XFType_CellProt_ParentStyleXF := WordLEToN(xf.XFType_CellProt_ParentStyleXF); + } lData := TXFRecordData.Create; + // Format index + lData.FormatIndex := WordLEToN(xf.FormatIndex); + // Cell borders + xf.Border_Background_1 := DWordLEToN(xf.Border_Background_1); + xf.Border_Background_2 := DWordLEToN(xf.Border_Background_2); + xf.Border_Background_3 := WordLEToN(xf.Border_Background_3); + lData.Borders := []; + if xf.Border_Background_1 and $0000000F <> 0 then + Include(lData.Borders, cbWest); + if xf.Border_Background_1 and $000000F0 <> 0 then + Include(lData.Borders, cbEast); + if xf.Border_Background_1 and $00000F00 <> 0 then + Include(lData.Borders, cbNorth); + if xf.Border_Background_1 and $0000F000 <> 0 then + Include(lData.Borders, cbSouth); + + (* // Record XF, BIFF8: // Offset Size Contents // 0 2 Index to FONT record (➜5.45)) @@ -2319,11 +2412,26 @@ begin // 2 2 Index to FORMAT record (➜5.49)) lData.FormatIndex := WordLEtoN(AStream.ReadWord); + // 4 2 XF type, cell protection, and parent style XF + // Bit Mask Contents + // 2-0 0007H XF_TYPE_PROT – XF type, cell protection (see above) + // 15-4 FFF0H Index to parent style XF (always FFFH in style XFs) + WordLEtoN(AStream.ReadWord); + + // 6 1 Alignment and text break: + // Bit Mask Contents + // 2-0 07H XF_HOR_ALIGN – Horizontal alignment (see above) + // 3 08H 1 = Text is wrapped at right border + // 6-4 70H XF_VERT_ALIGN – Vertical alignment (see above) + // 7 80H 1 = Justify last line in justified or distibuted text + b + { Offset Size Contents 4 2 XF type, cell protection, and parent style XF: Bit Mask Contents 2-0 0007H XF_TYPE_PROT – XF type, cell protection (see above) 15-4 FFF0H Index to parent style XF (always FFFH in style XFs) + 6 1 Alignment and text break: Bit Mask Contents 2-0 07H XF_HOR_ALIGN – Horizontal alignment (see above) @@ -2341,7 +2449,7 @@ begin ; 1 = Left-to-right; 2 = Right-to-left 9 1 Flags for used attribute groups: ....} - + *) // Add the XF to the list FXFList.Add(lData); end;