From c5be1f5910a5aa83e1bc4ec483e621885a6735a9 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Wed, 17 May 2023 11:21:15 +0000 Subject: [PATCH] fpspreadsheet: Remove dummy "rows-repeated" at the end of the table from ods (https://forum.lazarus.freepascal.org/index.php/topic,63385.msg479999.html) git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8820 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../source/common/fpsopendocument.pas | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/components/fpspreadsheet/source/common/fpsopendocument.pas b/components/fpspreadsheet/source/common/fpsopendocument.pas index a153493f4..c821ed41f 100644 --- a/components/fpspreadsheet/source/common/fpsopendocument.pas +++ b/components/fpspreadsheet/source/common/fpsopendocument.pas @@ -147,6 +147,8 @@ type AFont: TsFont; var AFormat: TsCellFormat); procedure ReadTableStyle(AStyleNode: TDOMNode); + procedure RemoveDummyRows(ATableNode: TDOMNode); + protected FPointSeparatorSettings: TFormatSettings; procedure AddBuiltinNumFormats; override; @@ -2864,6 +2866,8 @@ begin ReadShapes(TableNode); // Collect column styles used ReadColumns(TableNode); + // Remove excess rows added at the end + RemoveDummyRows(TableNode); // Process each row inside the sheet and process each cell of the row ReadRowsAndCells(TableNode); // Read conditional formats @@ -4886,6 +4890,43 @@ begin end; end; +{ Removes excess rows added at the end of the data block, as usually happens + by export to ods from Excel. Since FPSpreadsheet creates a cell for each of + these dummy cells there would be an extreme time and memory penalty. } +procedure TsSpreadOpenDocReader.RemoveDummyRows(ATableNode: TDOMNode); +var + rowNode, prevNode: TDOMNode; + nodeName: String; + s: String; + rowsRepeated: Integer; +begin + // Read table from the read and remove the rows with a large "number-rows-repeated" + // attribute. + rowNode := ATableNode.LastChild; + while rowNode <> nil do + begin + nodeName := rowNode.NodeName; + if nodeName = 'table:table-row' then + begin + // If, coming from the end, we find a row with a large "number-rows-repeated" + // value + s := GetAttrValue(rowNode, 'table:number-rows-repeated'); + if s <> '' then + begin + rowsRepeated := StrToInt(s); + if rowsRepeated > 1000 then // 1000 ok? + begin + prevNode := rowNode.PreviousSibling; + rowNode.Free; + rowNode := prevNode; + continue; + end; + end + end; + rowNode := rowNode.PreviousSibling; + end; +end; + procedure TsSpreadOpenDocReader.ReadStyle_ParagraphProperties(ANode: TDOMNode; var AFormat: TsCellFormat); var