From ead4186b6e416b97d73eecf0a7bf0ae5cc4d2fcc Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Thu, 31 Jul 2014 21:05:01 +0000 Subject: [PATCH] fpspreadsheet: OOXML reading support for cell borders and diagonals. Unit tests adapted. Passed. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3403 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../examples/spready/spready.lpi | 8 ++ .../fpspreadsheet/tests/formattests.pas | 12 ++ components/fpspreadsheet/xlsxooxml.pas | 135 ++++++++++++++++-- 3 files changed, 147 insertions(+), 8 deletions(-) diff --git a/components/fpspreadsheet/examples/spready/spready.lpi b/components/fpspreadsheet/examples/spready/spready.lpi index 39a334c0e..0a7efc66c 100644 --- a/components/fpspreadsheet/examples/spready/spready.lpi +++ b/components/fpspreadsheet/examples/spready/spready.lpi @@ -21,8 +21,12 @@ + + + + @@ -54,8 +58,12 @@ + + + + diff --git a/components/fpspreadsheet/tests/formattests.pas b/components/fpspreadsheet/tests/formattests.pas index d604aa41e..990727389 100644 --- a/components/fpspreadsheet/tests/formattests.pas +++ b/components/fpspreadsheet/tests/formattests.pas @@ -119,6 +119,8 @@ type procedure TestWriteRead_ODS_WordWrap; { OOXML Tests } + procedure TestWriteRead_OOXML_Border; + procedure TestWriteRead_OOXML_BorderStyles; procedure TestWriteRead_OOXML_DateTimeFormats; procedure TestWriteRead_OOXML_NumberFormats; @@ -645,6 +647,11 @@ begin TestWriteReadBorder(sfOpenDocument); end; +procedure TSpreadWriteReadFormatTests.TestWriteRead_OOXML_Border; +begin + TestWriteReadBorder(sfOOXML); +end; + { --- BorderStyle tests --- } @@ -782,6 +789,11 @@ begin TestWriteReadBorderStyles(sfOpenDocument); end; +procedure TSpreadWriteReadFormatTests.TestWriteRead_OOXML_BorderStyles; +begin + TestWriteReadBorderStyles(sfOOXML); +end; + { --- Column widths tests --- } diff --git a/components/fpspreadsheet/xlsxooxml.pas b/components/fpspreadsheet/xlsxooxml.pas index ce0e86908..a557dc896 100755 --- a/components/fpspreadsheet/xlsxooxml.pas +++ b/components/fpspreadsheet/xlsxooxml.pas @@ -65,6 +65,7 @@ type FFillList: TFPList; FBorderList: TFPList; FWrittenByFPS: Boolean; + procedure ReadBorders(ANode: TDOMNode); procedure ReadCell(ANode: TDOMNode; AWorksheet: TsWorksheet); procedure ReadCellXfs(ANode: TDOMNode); procedure ReadDateMode(ANode: TDOMNode); @@ -197,6 +198,11 @@ type BgColor: Tscolor; end; + TBorderListData = class + Borders: TsCellBorders; + BorderStyles: TsCellBorderStyles; + end; + TXFListData = class NumFmtIndex: Integer; FontIndex: Integer; @@ -321,6 +327,7 @@ var xf: TXfListData; numFmtData: TsNumFormatData; fillData: TFillListData; + borderData: TBorderListData; j: Integer; begin if Assigned(ACell) then begin @@ -350,15 +357,17 @@ begin else Exclude(ACell^.UsedFormattingFields, uffTextRotation); ACell^.TextRotation := xf.TextRotation; - + *) // Borders - ACell^.BorderStyles := xf.BorderStyles; - if xf.Borders <> [] then begin - Include(ACell^.UsedFormattingFields, uffBorder); - ACell^.Border := xf.Borders; - end else - Exclude(ACell^.UsedFormattingFields, uffBorder); - *) + borderData := FBorderList[xf.BorderIndex]; + if (borderData <> nil) then begin + ACell^.BorderStyles := borderData.BorderStyles; + if borderData.Borders <> [] then begin + Include(Acell^.UsedFormattingFields, uffBorder); + ACell^.Border := borderData.Borders; + end else + Exclude(ACell^.UsedFormattingFields, uffBorder); + end; // Background color fillData := FFillList[xf.FillIndex]; @@ -387,6 +396,115 @@ begin FNumFormatList := TsOOXMLNumFormatList.Create(Workbook); end; +procedure TsSpreadOOXMLReader.ReadBorders(ANode: TDOMNode); + + function ReadBorderStyle(ANode: TDOMNode; var ABorderStyle: TsCellBorderStyle): Boolean; + var + s: String; + colorNode: TDOMNode; + nodeName: String; + begin + Result := false; + + s := GetAttrValue(ANode, 'style'); + if s = '' then + exit; + + ABorderStyle.LineStyle := lsThin; + if s = 'thin' then + ABorderStyle.LineStyle := lsThin + else if s = 'medium' then + ABorderStyle.LineStyle := lsMedium + else if s = 'thick' then + ABorderStyle.LineStyle := lsThick + else if s = 'dotted' then + ABorderStyle.LineStyle := lsDotted + else if s = 'dashed' then + ABorderStyle.LineStyle := lsDashed + else if s = 'double' then + ABorderStyle.LineStyle := lsDouble + else if s = 'hair' then + ABorderStyle.LineStyle := lsHair; + + ABorderStyle.Color := scBlack; + colorNode := ANode.FirstChild; + while Assigned(colorNode) do begin + nodeName := colorNode.NodeName; + if nodeName = 'color' then begin + s := GetAttrValue(colorNode, 'rgb'); + if s <> '' then + ABorderStyle.Color := FWorkbook.AddColorToPalette(HTMLColorStrToColor('#' + s)) + else begin + s := GetAttrValue(colorNode, 'indexed'); + if s <> '' then + ABorderStyle.Color := StrToInt(s); + end; + end; + colorNode := colorNode.NextSibling; + end; + Result := true; + end; + +var + borderNode: TDOMNode; + edgeNode: TDOMNode; + nodeName: String; + borders: TsCellBorders; + borderStyles: TsCellBorderStyles; + borderData: TBorderListData; + s: String; + +begin + if ANode = nil then + exit; + + borderNode := ANode.FirstChild; + while Assigned(borderNode) do begin + nodeName := borderNode.NodeName; + if nodeName = 'border' then begin + borders := []; + s := GetAttrValue(borderNode, 'diagonalUp'); + if s = '1' then + Include(borders, cbDiagUp); + s := GetAttrValue(borderNode, 'diagonalDown'); + if s = '1' then + Include(borders, cbDiagDown); + edgeNode := borderNode.FirstChild; + while Assigned(edgeNode) do begin + nodeName := edgeNode.NodeName; + if nodeName = 'left' then begin + if ReadBorderStyle(edgeNode, borderStyles[cbWest]) then + Include(borders, cbWest); + end + else if nodeName = 'right' then begin + if ReadBorderStyle(edgeNode, borderStyles[cbEast]) then + Include(borders, cbEast); + end + else if nodeName = 'top' then begin + if ReadBorderStyle(edgeNode, borderStyles[cbNorth]) then + Include(borders, cbNorth); + end + else if nodeName = 'bottom' then begin + if ReadBorderStyle(edgeNode, borderStyles[cbSouth]) then + Include(borders, cbSouth); + end + else if nodeName = 'diagonal' then begin + if ReadBorderStyle(edgeNode, borderStyles[cbDiagUp]) then + borderStyles[cbDiagDown] := borderStyles[cbDiagUp]; + end; + edgeNode := edgeNode.NextSibling; + end; + + // add to border list + borderData := TBorderListData.Create; + borderData.Borders := borders; + borderData.BorderStyles := borderStyles; + FBorderList.Add(borderData); + end; + borderNode := borderNode.NextSibling; + end; +end; + procedure TsSpreadOOXMLReader.ReadCell(ANode: TDOMNode; AWorksheet: TsWorksheet); var s: String; @@ -869,6 +987,7 @@ begin ReadPalette(Doc.DocumentElement.FindNode('colors')); ReadFonts(Doc.DocumentElement.FindNode('fonts')); ReadFills(Doc.DocumentElement.FindNode('fills')); + ReadBorders(Doc.DocumentElement.FindNode('borders')); ReadNumFormats(Doc.DocumentElement.FindNode('numFmts')); ReadCellXfs(Doc.DocumentElement.FindNode('cellXfs')); FreeAndNil(Doc);