diff --git a/components/fpspreadsheet/source/common/fpsopendocument.pas b/components/fpspreadsheet/source/common/fpsopendocument.pas
index 80886b0f7..3981caeed 100644
--- a/components/fpspreadsheet/source/common/fpsopendocument.pas
+++ b/components/fpspreadsheet/source/common/fpsopendocument.pas
@@ -112,7 +112,6 @@ type
function FindNumFormatByName(ANumFmtName: String): Integer;
function FindRowStyleByName(AStyleName: String): Integer;
function FindTableStyleByName(AStyleName: String): Integer;
-// procedure FixFormulas;
procedure ReadCell(ANode: TDOMNode; ARow, ACol: Integer;
AFormatIndex: Integer; out AColsRepeated: Integer);
procedure ReadCellImages(ANode: TDOMNode; ARow, ACol: Cardinal);
@@ -242,12 +241,15 @@ type
procedure AddBuiltinNumFormats; override;
procedure CreateStreams;
procedure DestroyStreams;
+ function FindRowStyle(ASheet: TsBasicWorksheet; ARowIndex: Integer): Integer;
procedure GetHeaderFooterImageName(APageLayout: TsPageLayout;
out AHeader, AFooter: String);
procedure GetHeaderFooterImagePosStr(APagelayout: TsPageLayout;
out AHeader, AFooter: String);
+ {
procedure GetRowStyleAndHeight(ASheet: TsBasicWorksheet; ARowIndex: Integer;
out AStyleName: String; out AHeight: Single);
+ }
procedure InternalWriteToStream(AStream: TStream);
procedure ListAllColumnStyles;
procedure ListAllHeaderFooterFonts;
@@ -1461,52 +1463,6 @@ begin
exit;
Result := -1;
end;
- (*
-procedure TsSpreadOpenDocReader.FixFormulas;
-
- procedure FixCell(ACell: PCell);
- var
- parser: TsSpreadsheetParser;
- begin
- parser := TsSpreadsheetParser.Create(TsWorksheet(ACell^.Worksheet));
- try
- try
- parser.Dialect := fdOpenDocument;
- parser.LocalizedExpression[FPointSeparatorSettings] := ACell^.FormulaValue;
- parser.Dialect := fdExcelA1;
- ACell^.FormulaValue := parser.Expression;
- except
- on E:EExprParser do
- begin
- FWorkbook.AddErrorMsg(E.Message);
- ACell^.FormulaValue := '';
- if (boAbortReadOnFormulaError in Workbook.Options) then raise;
- end;
- on E:ECalcEngine do
- begin
- Workbook.AddErrorMsg(E.Message);
- ACell^.FormulaValue := '';
- if (boAbortReadOnFormulaError in Workbook.Options) then raise;
- end;
- end;
- finally
- parser.Free;
- end;
- end;
-
-var
- i: Integer;
- sheet: TsWorksheet;
- cell: PCell;
-begin
- if (boIgnoreFormulas in FWorkbook.Options) then
- exit;
- for i:=0 to (FWorkbook as TsWorkbook).GetWorksheetCount-1 do begin
- sheet := (FWorkbook as TsWorkbook).GetWorksheetByIndex(i);
- for cell in sheet.Cells do
- if HasFormula(cell) then FixCell(cell);
- end;
-end; *)
procedure TsSpreadOpenDocReader.ReadAutomaticStyles(AStylesNode: TDOMNode);
var
@@ -4876,82 +4832,67 @@ end;
procedure TsSpreadOpenDocWriter.ListAllColumnStyles;
var
i, j, c: Integer;
+ book: TsWorkbook;
sheet: TsWorksheet;
found: Boolean;
colstyle: TColumnStyleData;
+ item: TColumnStyleData;
+ colPageBreak: Boolean;
w: Double;
+ wDef: Double; // Default column width
col: PCol;
begin
+ book := TsWorkbook(FWorkbook);
+ sheet := book.GetFirstWorksheet;
+ if sheet = nil then
+ exit;
+
+ wDef := sheet.ReadDefaultColWidth(book.Units);
+
{ At first, add the default column width }
colStyle := TColumnStyleData.Create;
colStyle.Name := 'co1';
- colStyle.ColWidth := TsWorkbook(Workbook).ConvertUnits(12, suChars, FWorkbook.Units);
+ colStyle.ColWidth := wDef;
FColumnStyleList.Add(colStyle);
{ Then iterate through all sheets and all columns and store the unique
column widths in the FColumnStyleList. }
- for i:=0 to (Workbook as TsWorkbook).GetWorksheetCount-1 do
+ for i:=0 to book.GetWorksheetCount-1 do
begin
- sheet := TsWorkbook(Workbook).GetWorksheetByIndex(i);
+ sheet := book.GetWorksheetByIndex(i);
+ wDef := sheet.ReadDefaultColWidth(book.Units);
for c := 0 to sheet.Cols.Count-1 do
begin
col := PCol(sheet.Cols[c]);
- if (col <> nil) and (col^.ColWidthType = cwtCustom) then
+ if (col^.ColWidthType = cwtCustom) or (croPageBreak in col^.Options) then
begin
+ colPageBreak := (croPageBreak in col^.Options); // has page break?
w := col^.Width; // is in workbook units
// Look for this width in the current ColumnStyleList
found := false;
- for j := 0 to FColumnStyleList.Count - 1 do
- if SameValue(TColumnStyleData(FColumnstyleList[j]).ColWidth, w, COLWIDTH_EPS) then
+ for j := 0 to FColumnStyleList.Count - 1 do begin
+ item := TColumnStyleData(FColumnStyleList[j]);
+ if SameValue(item.ColWidth, w, COLWIDTH_EPS) and (item.PageBreak = colPageBreak) then
begin
found := true;
break;
end;
+ end;
// Not found? Then add the column as a new column style
if not found then
begin
colStyle := TColumnStyleData.Create;
colStyle.Name := Format('co%d', [FColumnStyleList.Count + 1]);
- colStyle.ColWidth := w;
+ if col^.ColWidthType = cwtDefault then
+ colStyle.ColWidth := wDef
+ else
+ colStyle.ColWidth := w;
+ colStyle.PageBreak := colPageBreak;
FColumnStyleList.Add(colStyle);
end;
end;
end;
- {
- for c:=0 to sheet.GetLastColIndex do
- begin
- w := sheet.GetColWidth(c, FWorkbook.Units);
- // Look for this width in the current ColumnStyleList
- found := false;
- for j := 0 to FColumnStyleList.Count-1 do
- if SameValue(TColumnStyleData(FColumnStyleList[j]).ColWidth, w, COLWIDTH_EPS)
- then begin
- found := true;
- break;
- end;
- // Not found? Then add the column as new column style
- if not found then
- begin
- colStyle := TColumnStyleData.Create;
- colStyle.Name := Format('co%d', [FColumnStyleList.Count+1]);
- colStyle.ColWidth := w;
- FColumnStyleList.Add(colStyle);
- end;
- end;
- }
end;
- (*
- { fpspreadsheet's column width is the count of '0' characters of the
- default font. On average, the width of the '0' is about half of the
- point size of the font. --> we can convert the fps col width to pts and
- then to millimeters. }
- multiplier := Workbook.GetFont(0).Size / 2;
- for i:=0 to FColumnStyleList.Count-1 do
- begin
- w := TColumnStyleData(FColumnStyleList[i]).ColWidth * multiplier;
- TColumnStyleData(FColumnStyleList[i]).ColWidth := PtsToMM(w);
- end;
- *)
end;
{ Collects the fonts used by headers and footers in the FHeaderFooterFontList }
@@ -5012,10 +4953,13 @@ var
row: PRow;
found: Boolean;
rowstyle: TRowStyleData;
+ item: TRowStyleData;
+ rowPageBreak: Boolean;
h: Double;
book: TsWorkbook;
begin
book := FWorkbook as TsWorkbook;
+
{ At first, add the default row height }
{ Initially, row height units will be the same as in the workbook }
rowStyle := TRowStyleData.Create;
@@ -5032,23 +4976,28 @@ begin
row := sheet.FindRow(r);
if row <> nil then
begin
+ rowPageBreak := (croPageBreak in row^.Options);
h := sheet.GetRowHeight(r, FWorkbook.Units);
// Look for this height in the current RowStyleList
found := false;
- for j:=0 to FRowStyleList.Count-1 do
- if SameValue(TRowStyleData(FRowStyleList[j]).RowHeight, h, ROWHEIGHT_EPS)
- and (TRowStyleData(FRowStyleList[j]).RowHeightType = row^.RowHeightType)
- then begin
+ for j:=0 to FRowStyleList.Count-1 do begin
+ item := TRowStyleData(FRowStyleList[j]);
+ if SameValue(item.RowHeight, h, ROWHEIGHT_EPS) and
+ (item.RowHeightType = row^.RowHeightType) and
+ (item.PageBreak = rowPageBreak) then
+ begin
found := true;
break;
end;
- // Not found? Then add the row as a new row style
+ end;
+ // Not found? --> Add the row as a new row style
if not found then
begin
rowStyle := TRowStyleData.Create;
rowStyle.Name := Format('ro%d', [FRowStyleList.Count+1]);
rowStyle.RowHeight := h;
rowStyle.RowHeightType := row^.RowHeightType;
+ rowStyle.PageBreak := rowPageBreak;
FRowStyleList.Add(rowStyle);
end;
end;
@@ -5545,7 +5494,10 @@ procedure TsSpreadOpenDocWriter.WriteColStyles(AStream: TStream);
var
i: Integer;
colstyle: TColumnStyleData;
+ book: TsWorkbook;
begin
+ book := TsWorkbook(FWorkbook);
+
if FColumnStyleList.Count = 0 then
begin
AppendToStream(AStream,
@@ -5565,9 +5517,11 @@ begin
// Column width
AppendToStream(AStream, Format(
- '',
- [TsWorkbook(FWorkbook).ConvertUnits(colStyle.ColWidth, FWorkbook.Units, suMillimeters)],
- FPointSeparatorSettings));
+ '', [
+ colStyle.ColWidth,
+ PAGE_BREAK[colStyle.PageBreak]
+ ], FPointSeparatorSettings)
+ );
// End
AppendToStream(AStream,
@@ -5588,9 +5542,10 @@ var
firstRepeatedPrintCol, lastRepeatedPrintCol: Longint;
headerCols: Boolean;
isHidden1, isHidden: Boolean;
+ isPageBreak1, isPageBreak: Boolean;
colHiddenStr: String;
+ colStyleData: TColumnStyleData;
begin
-// widthMultiplier := Workbook.GetFont(0).Size / 2;
lastCol := sheet.GetLastColIndex;
firstRepeatedPrintCol := longInt(sheet.PageLayout.RepeatedCols.FirstIndex);
lastRepeatedPrintCol := longint(sheet.PageLayout.RepeatedCols.LastIndex);
@@ -5605,6 +5560,7 @@ begin
begin
w1 := sheet.GetColWidth(c, FWorkbook.Units);
isHidden1 := sheet.ColHidden(c) or (w1 = 0);
+ isPageBreak1 := sheet.IsPageBreakCol(c);
if (c = firstRepeatedPrintCol) then
begin
@@ -5614,11 +5570,21 @@ begin
// Find width in ColumnStyleList to retrieve corresponding style name
styleName := '';
- for k := 0 to FColumnStyleList.Count-1 do
+ for k := 0 to FColumnStyleList.Count-1 do begin
+ colStyleData := TColumnStyleData(FColumnStyleList[k]);
+ if SameValue(colStyleData.ColWidth, w1, COLWIDTH_EPS) and
+ (colStyleData.PageBreak = isPageBreak1) then
+ begin
+ styleName := colStyleData.Name;
+ break;
+ end;
+ end;
+ {
if SameValue(TColumnStyleData(FColumnStyleList[k]).ColWidth, w1, COLWIDTH_EPS) then begin
styleName := TColumnStyleData(FColumnStyleList[k]).Name;
break;
end;
+ }
if stylename = '' then
stylename := 'co1';
{
@@ -5634,7 +5600,8 @@ begin
begin
w := sheet.GetColWidth(k, FWorkbook.Units);
isHidden := sheet.ColHidden(k) or (w = 0);
- if (w = w1) and (isHidden = isHidden1) then
+ isPageBreak := sheet.IsPageBreakCol(k);
+ if (w = w1) and (isHidden = isHidden1) and (isPageBreak = isPageBreak1) then
inc(colsRepeated)
else
break;
@@ -5645,7 +5612,8 @@ begin
begin
w := sheet.GetColWidth(k, FWorkbook.Units);
isHidden := sheet.ColHidden(k) or (w = 0);
- if (w = w1) and (isHidden = isHidden1) then
+ isPageBreak := sheet.IsPageBreakCol(k);
+ if (w = w1) and (isHidden = isHidden1) and (isPageBreak = isPageBreak1) then
inc(colsRepeated)
else
break;
@@ -6273,10 +6241,30 @@ var
fmtIndex: integer;
sheet: TsWorksheet absolute ASheet;
rowHiddenStr: String;
+ styleIdx: Integer;
+ rowStyleData: TRowStyleData;
begin
// Get row
row := sheet.FindRow(ARowIndex);
+ // Get row style
+ styleIdx := FindRowStyle(ASheet, ARowIndex);
+ if styleIdx = -1 then
+ begin
+ stylename := 'ro1'; // Default row style - see ListAllRowStyles
+ rowHiddenStr := '';
+ end else
+ begin
+ rowStyleData := TRowStyleData(FRowStyleList[styleIdx]);
+ styleName := rowStyleData.Name;
+ if (croHidden in row^.Options) or (
+ (round(rowStyleData.RowHeight) = 0) and (rowStyleData.RowHeightType = rhtCustom))
+ then
+ rowHiddenStr := ' table:visibility="collapse"'
+ end;
+
+
+{
// Get style and height of row
GetRowStyleAndHeight(ASheet, ARowIndex, stylename, h);
@@ -6285,7 +6273,7 @@ begin
rowHiddenStr := ' table:visibility="collapse"'
else
rowHiddenStr := '';
-
+ }
// Write opening row tag. We don't support repeatedRows here.
AppendToStream(AStream, Format(
'', [stylename, rowHiddenStr]));
@@ -6416,21 +6404,53 @@ var
rowsRepeatedStr: String;
rowHiddenStr: String;
isHidden1, isHidden: Boolean;
+ isPageBreak1, isPageBreak: Boolean;
+ styleIdx: Integer;
+ rowStyleData: TRowStyleData;
begin
+ // Get row style
+ styleIdx := FindRowStyle(ASheet, ARowIndex);
+ if styleIdx = -1 then
+ begin
+ stylename := 'ro1'; // Default row style - see ListAllRowStyles
+ h := -1;
+ end else
+ begin
+ rowStyleData := TRowStyleData(FRowStyleList[styleIdx]);
+ styleName := rowStyleData.Name;
+ if rowStyleData.RowHeightType = rhtCustom then
+ h := rowStyleData.RowHeight
+ else
+ h := -1;
+ {
+ if (croHidden in row^.Options) or (
+ (round(rowStyleData.RowHeight) = 0) and (rowStyleData.RowHeightType = rhtCustom))
+ then
+ rowHiddenStr := ' table:visibility="collapse"'
+ }
+ end;
+ {
+
// Get style and height of row
GetRowStyleAndHeight(ASheet, ARowIndex, stylename, h);
+ }
// Determine how often this row is repeated
row := sheet.FindRow(ARowIndex);
-
- isHidden1 := (round(h) = 0) or ((row <> nil) and (croHidden in row^.Options));
+ if Assigned(row) then begin
+ isPageBreak1 := (croPageBreak in row^.Options);
+ isHidden1 := (round(h) = 0) or ((row <> nil) and (croHidden in row^.Options));
+ end else begin
+ isPageBreak1 := false;
+ isHidden1 := false;
+ end;
rowHiddenStr := IfThen(isHidden1, ' table:visibility="collapse"', '');
// Rows with format are not repeated - too complicated...
if (row <> nil) and (row^.FormatIndex > 0) then
ARowsRepeated := 1
else
- // Count how many rows are empty and have the same height
+ // Count how many rows are empty and have the row record values
if ALastRowIndex > -1 then begin
r := ARowIndex + 1;
while r <= ALastRowIndex do
@@ -6438,9 +6458,13 @@ begin
if not sheet.IsEmptyRow(r) then
break;
row := sheet.FindRow(r);
+ isPageBreak := (row <> nil) and (croPageBreak in row^.Options);
isHidden := (row <> nil) and
((croHidden in row^.Options) or ((row^.RowHeightType=rhtCustom) and (row^.Height = 0)));
- if ((row <> nil) and (row^.FormatIndex > 0)) or (isHidden <> isHidden1) then
+ if ((row <> nil) and (row^.FormatIndex > 0)) or
+ (isHidden <> isHidden1) or
+ (isPageBreak <> isPageBreak1)
+ then
break;
h1 := sheet.GetRowHeight(r, FWorkbook.Units);
if not SameValue(h, h1, ROWHEIGHT_EPS) then
@@ -6527,6 +6551,36 @@ begin
'');
end;
+function TsSpreadOpenDocWriter.FindRowStyle(ASheet: TsBasicWorksheet;
+ ARowIndex: Integer): Integer;
+var
+ row: PRow;
+ k: Integer;
+ rowStyleData: TRowStyleData;
+begin
+ Result := -1;
+
+ row := (ASheet as TsWorksheet).FindRow(ARowIndex);
+ if row = nil then
+ exit;
+
+ for k := 0 to FRowStyleList.Count - 1 do
+ begin
+ rowStyleData := TRowStyleData(FRowStyleList[k]);
+ // Compare elements of row records. Be aware of rounding error when comparing
+ // the row height
+ if (rowStyleData.PageBreak = (croPageBreak in row^.Options)) and
+ ( (rowStyleData.RowHeightType = rhtDefault) or
+ (rowStyleData.RowHeightType = row^.RowHeightType) and
+ SameValue(rowStyleData.RowHeight, row^.Height, ROWHEIGHT_EPS) ) then
+ begin
+ Result := k;
+ exit;
+ end;
+ end;
+end;
+
+{
procedure TsSpreadOpenDocWriter.GetRowStyleAndHeight(ASheet: TsBasicWorksheet;
ARowIndex: Integer; out AStyleName: String; out AHeight: Single);
var
@@ -6541,11 +6595,19 @@ begin
AHeight := row^.Height; // row height in workbook units
for k := 0 to FRowStyleList.Count-1 do begin
rowStyleData := TRowStyleData(FRowStyleList[k]);
- // Compare row heights, but be aware of rounding errors
+ // Compare elements of row records. Be aware of rounding errors
+ if (rowStyleData.PageBreak = (croPageBreak in row^.Options)) and
+ ( (rowStyleData.RowHeightType = rhtDefault) or
+ (rowStyleData.RowHeightType = row^.RowHeightType) and
+ SameValue(rowStyleData.RowHeight, AHeight, ROWHEIGHT_EPS)
+ ) then
+ {
if SameValue(rowStyleData.RowHeight, AHeight, ROWHEIGHT_EPS) and
(rowstyleData.RowHeightType = row^.RowHeightType) and
- (rowstyleData.RowHeightType <> rhtDefault)
- then begin
+ (rowstyleData.RowHeightType <> rhtDefault) and
+ (rowstyleData.PageBreak = isPageBreak) then
+ }
+ begin
AStyleName := rowStyleData.Name;
break;
end;
@@ -6556,6 +6618,7 @@ begin
AHeight := (ASheet as TsWorksheet).ReadDefaultRowHeight(FWorkbook.Units);
end;
end;
+}
{ Write the style nodes for rows ("ro1", "ro2", ...); they contain only
row height information. "ro1" is the default row height }
@@ -6563,7 +6626,12 @@ procedure TsSpreadOpenDocWriter.WriteRowStyles(AStream: TStream);
var
i: Integer;
rowstyle: TRowStyleData;
+ book: TsWorkbook;
+ sheet: TsWorksheet;
begin
+ book := TsWorkbook(FWorkbook);
+ sheet := TsWorksheet(FWorksheet);
+
if FRowStyleList.Count = 0 then
begin
AppendToStream(AStream, Format(
@@ -6571,7 +6639,7 @@ begin
'' +
'',
- [(FWorksheet as TsWorksheet).ReadDefaultRowHeight(suMillimeters)]
+ [sheet.ReadDefaultRowHeight(suMillimeters)]
));
exit;
end;
@@ -6587,12 +6655,12 @@ begin
// Row height
AppendToStream(AStream, Format(
' rhtCustom]]));
- AppendToStream(AStream,
- 'fo:break-before="auto"/>');
+ AppendToStream(AStream, Format(
+ 'fo:break-before="%s"/>', [PAGE_BREAK[rowStyle.PageBreak]]));
// End
AppendToStream(AStream,
diff --git a/components/fpspreadsheet/tests/colrowtests.pas b/components/fpspreadsheet/tests/colrowtests.pas
index c9342eb05..7b10d51dd 100644
--- a/components/fpspreadsheet/tests/colrowtests.pas
+++ b/components/fpspreadsheet/tests/colrowtests.pas
@@ -306,6 +306,11 @@ type
procedure TestWriteRead_AddPageBreak_Row_XML;
procedure TestWriteRead_AddPageBreak_RowHidden_XML;
+ procedure TestWriteRead_AddPageBreak_Col_ODS;
+ procedure TestWriteRead_AddPageBreak_ColHidden_ODS;
+ procedure TestWriteRead_AddPageBreak_Row_ODS;
+ procedure TestWriteRead_AddPageBreak_RowHidden_ODS;
+
// Remove a page break column
procedure TestWriteRead_RemovePageBreak_Col_BIFF2;
procedure TestWriteRead_RemovePageBreak_Row_BIFF2;
@@ -329,6 +334,11 @@ type
procedure TestWriteRead_RemovePageBreak_ColHidden_XML;
procedure TestWriteRead_RemovePageBreak_Row_XML;
procedure TestWriteRead_RemovePageBreak_RowHidden_XML;
+
+ procedure TestWriteRead_RemovePageBreak_Col_ODS;
+ procedure TestWriteRead_RemovePageBreak_ColHidden_ODS;
+ procedure TestWriteRead_RemovePageBreak_Row_ODS;
+ procedure TestWriteRead_RemovePageBreak_RowHidden_ODS;
end;
implementation
@@ -2334,6 +2344,23 @@ begin
TestWriteRead_AddPageBreak_Row(true, sfExcelXML);
end;
+procedure TSpreadWriteRead_ColRow_Tests.TestWriteRead_AddPageBreak_Col_ODS;
+begin
+ TestWriteRead_AddPageBreak_Col(false, sfOpenDocument);
+end;
+procedure TSpreadWriteRead_ColRow_Tests.TestWriteRead_AddPageBreak_Row_ODS;
+begin
+ TestWriteRead_AddPageBreak_Row(false, sfOpenDocument);
+end;
+procedure TSpreadWriteRead_ColRow_Tests.TestWriteRead_AddPageBreak_ColHidden_ODS;
+begin
+ TestWriteRead_AddPageBreak_Col(true, sfOpenDocument);
+end;
+procedure TSpreadWriteRead_ColRow_Tests.TestWriteRead_AddPageBreak_RowHidden_ODS;
+begin
+ TestWriteRead_AddPageBreak_Row(true, sfOpenDocument);
+end;
+
{ Remove page break
- Hidden: set the Hidden flag in the options to test whether it is damaged
@@ -2561,6 +2588,23 @@ begin
TestWriteRead_RemovePageBreak_Row(true, sfExcelXML);
end;
+procedure TSpreadWriteRead_ColRow_Tests.TestWriteRead_RemovePageBreak_Col_ODS;
+begin
+ TestWriteRead_RemovePageBreak_Col(false, sfOpenDocument);
+end;
+procedure TSpreadWriteRead_ColRow_Tests.TestWriteRead_RemovePageBreak_Row_ODS;
+begin
+ TestWriteRead_RemovePageBreak_Row(false, sfOpenDocument);
+end;
+procedure TSpreadWriteRead_ColRow_Tests.TestWriteRead_RemovePageBreak_ColHidden_ODS;
+begin
+ TestWriteRead_RemovePageBreak_Col(true, sfOpenDocument);
+end;
+procedure TSpreadWriteRead_ColRow_Tests.TestWriteRead_RemovePageBreak_RowHidden_ODS;
+begin
+ TestWriteRead_RemovePageBreak_Row(true, sfOpenDocument);
+end;
+
initialization
RegisterTest(TSpreadWriteRead_ColRow_Tests);
InitTestData;