diff --git a/components/fpspreadsheet/source/common/fpsopendocument.pas b/components/fpspreadsheet/source/common/fpsopendocument.pas index eb23b4387..1529049f3 100644 --- a/components/fpspreadsheet/source/common/fpsopendocument.pas +++ b/components/fpspreadsheet/source/common/fpsopendocument.pas @@ -6270,7 +6270,7 @@ begin GetRowStyleAndHeight(ASheet, ARowIndex, stylename, h); // Row hidden? - if (round(h) = 0) or (Assigned(row) and row^.Hidden) then + if (round(h) = 0) or (Assigned(row) and (croHidden in row^.Options)) then rowHiddenStr := ' table:visibility="collapse"' else rowHiddenStr := ''; @@ -6412,7 +6412,7 @@ begin // Determine how often this row is repeated row := sheet.FindRow(ARowIndex); - isHidden1 := (round(h) = 0) or ((row <> nil) and row^.Hidden); + isHidden1 := (round(h) = 0) or ((row <> nil) and (croHidden in row^.Options)); rowHiddenStr := IfThen(isHidden1, ' table:visibility="collapse"', ''); // Rows with format are not repeated - too complicated... @@ -6428,7 +6428,7 @@ begin break; row := sheet.FindRow(r); isHidden := (row <> nil) and - (row^.Hidden or ((row^.RowHeightType=rhtCustom) and (row^.Height = 0))); + ((croHidden in row^.Options) or ((row^.RowHeightType=rhtCustom) and (row^.Height = 0))); if ((row <> nil) and (row^.FormatIndex > 0)) or (isHidden <> isHidden1) then break; h1 := sheet.GetRowHeight(r, FWorkbook.Units); diff --git a/components/fpspreadsheet/source/common/fpspreadsheet.pas b/components/fpspreadsheet/source/common/fpspreadsheet.pas index 91b95c873..cb55adc56 100644 --- a/components/fpspreadsheet/source/common/fpspreadsheet.pas +++ b/components/fpspreadsheet/source/common/fpspreadsheet.pas @@ -489,6 +489,11 @@ type procedure WriteColWidth(ACol: Cardinal; AWidth: Single; AColWidthType: TsColWidthType = cwtCustom); overload; deprecated 'Use version with parameter AUnits'; + procedure AddPageBreakToCol(ACol: Cardinal); + procedure AddPageBreakToRow(ARow: Cardinal); + procedure RemovePageBreakFromCol(ACol: Cardinal); + procedure RemovePageBreakFromRow(ARow: Cardinal); + // Sorting function DefaultCompareCells(ACell1, ACell2: PCell; ASortKey: TsSortKey): Integer; procedure Sort(const ASortParams: TsSortParams; @@ -7742,7 +7747,7 @@ var c: PCol; begin c := FindCol(ACol); - Result := Assigned(c) and c^.Hidden; + Result := Assigned(c) and (croHidden in c^.Options); end; {@@ ---------------------------------------------------------------------------- @@ -7753,7 +7758,7 @@ var r: PRow; begin r := FindRow(ARow); - Result := Assigned(r) and r^.Hidden; + Result := Assigned(r) and (croHidden in r^.Options); end; {@@ ---------------------------------------------------------------------------- @@ -7764,8 +7769,8 @@ var c: PCol; begin c := GetCol(ACol); - if not c^.Hidden then begin - c^.Hidden := true; + if not (croHidden in c^.Options) then begin + Include(c^.Options, croHidden); ChangedCell(0, ACol); end; end; @@ -7778,8 +7783,8 @@ var r: PRow; begin r := GetRow(ARow); - if not r^.Hidden then begin - r^.Hidden := true; + if not (croHidden in r^.Options) then begin + Include(r^.Options, croHidden); ChangedCell(ARow, 0); end; end; @@ -7792,8 +7797,8 @@ var c: PCol; begin c := FindCol(ACol); - if Assigned(c) and c^.Hidden then begin - c^.Hidden := false; + if Assigned(c) and (croHidden in c^.Options) then begin + Exclude(c^.Options, croHidden); ChangedCell(0, ACol); end; end; @@ -7806,8 +7811,8 @@ var r: PRow; begin r := FindRow(ARow); - if Assigned(r) and r^.Hidden then begin - r^.Hidden := false; + if Assigned(r) and (croHidden in r^.Options) then begin + Exclude(r^.Options, croHidden); ChangedCell(ARow, 0); end; end; @@ -8225,7 +8230,7 @@ begin lRow^.Height := AData.Height; lRow^.RowHeightType := AData.RowHeightType; lRow^.FormatIndex := AData.FormatIndex; - lRow^.Hidden := AData.Hidden; + lRow^.Options := AData.Options; ChangedRow(ARow); end; @@ -8302,7 +8307,7 @@ begin lCol^.Width := AData.Width; lCol^.ColWidthType := AData.ColWidthType; lCol^.FormatIndex := AData.FormatIndex; - lCol^.Hidden := AData.Hidden; + lCol^.Options := AData.Options; ChangedCol(ACol); end; @@ -8386,6 +8391,69 @@ begin FDefaultRowHeight := FWorkbook.ConvertUnits(AValue, AUnits, FWorkbook.Units); end; +{@@ ---------------------------------------------------------------------------- + Sets the PageBreak flag for the column record with the specified column index. + This means that, when printed, a page break will occur before this column. + Note that FPS currently does not support printing by itself. +-------------------------------------------------------------------------------} +procedure TsWorksheet.AddPageBreakToCol(ACol: Cardinal); +var + lCol: PCol; +begin + lCol := AddCol(ACol); + Include(lCol^.Options, croPageBreak); + ChangedCol(ACol); +end; + +{@@ ---------------------------------------------------------------------------- + Sets the PageBreak flag for the row record with the specified row index. + This means that, when printed, a page break will occur before this row. + Note that FPS currently does not support printing by itself. +-------------------------------------------------------------------------------} +procedure TsWorksheet.AddPageBreakToRow(ARow: Cardinal); +var + lRow: PRow; +begin + lRow := AddRow(ARow); + Include(lRow^.Options, croPageBreak); + ChangedRow(ARow); +end; + +{@@ ---------------------------------------------------------------------------- + Removes the PageBreak flag for the column record with the specified column + index. + This means that, during printing, page break handling of this column will be + automatic. + Note that FPS currently does not support printing by itself. +-------------------------------------------------------------------------------} +procedure TsWorksheet.RemovePageBreakFromCol(ACol: Cardinal); +var + lCol: PCol; +begin + lCol := FindCol(ACol); + if lCol <> nil then begin + Exclude(lCol^.Options, croPageBreak); + ChangedCol(ACol); + end; +end; + +{@@ ---------------------------------------------------------------------------- + Removes the PageBreak flag for the row record with the specified row index. + This means that, during printing, page break handling of this row will be + automatic. + Note that FPS currently does not support printing by itself. +-------------------------------------------------------------------------------} +procedure TsWorksheet.RemovePageBreakFromRow(ARow: Cardinal); +var + lRow: PRow; +begin + lRow := FindRow(ARow); + if lRow <> nil then begin + Exclude(lRow^.Options, croPageBreak); + ChangedRow(ARow); + end; +end; + {==============================================================================} { TsWorkbook } diff --git a/components/fpspreadsheet/source/common/fpsreaderwriter.pas b/components/fpspreadsheet/source/common/fpsreaderwriter.pas index c54af67f7..86215b829 100644 --- a/components/fpspreadsheet/source/common/fpsreaderwriter.pas +++ b/components/fpspreadsheet/source/common/fpsreaderwriter.pas @@ -404,7 +404,7 @@ begin break; if sheet.FindNextCellInCol(0, lCol^.Col) <> nil then break; - if lCol^.Hidden then + if (lCol^.Options <> []) then break; sheet.RemoveCol(lCol^.Col); dec(c); @@ -431,10 +431,11 @@ begin // to the DefaultColWidth ... sheet.WriteDefaultColWidth(w, FWorkbook.Units); - // ...and delete all column records with non-default format + // ...and delete all visible column records with default format for c := sheet.Cols.Count-1 downto 0 do begin lCol := PCol(sheet.Cols[c]); - if (lCol^.FormatIndex = 0) and (not lCol^.Hidden) then sheet.RemoveCol(lCol^.Col); + if (lCol^.FormatIndex = 0) and not (croHidden in lCol^.Options) then + sheet.RemoveCol(lCol^.Col); end; end; end; @@ -481,7 +482,7 @@ begin // ... and delete all visible row records with default format. for r := sheet.Rows.Count-1 downto 0 do begin lRow := PRow(sheet.Rows[r]); - if (lRow^.FormatIndex = 0) and (not lRow^.Hidden) then + if (lRow^.FormatIndex = 0) and not (croHidden in lRow^.Options) then sheet.RemoveRow(lRow^.Row); end; end; diff --git a/components/fpspreadsheet/source/common/fpstypes.pas b/components/fpspreadsheet/source/common/fpstypes.pas index 85b9f1a9a..700195756 100644 --- a/components/fpspreadsheet/source/common/fpstypes.pas +++ b/components/fpspreadsheet/source/common/fpstypes.pas @@ -774,6 +774,12 @@ type in the grid, or by changed by code) } TsColWidthtype = (cwtDefault, cwtCustom); + {@@ Column or row options + croHidden - Column or row is hidden + croPageBreak - Enforces a pagebreak before this column/row during printing } + TsColRowOption = (croHidden, croPageBreak); + TsColRowOptions = set of TsColRowOption; + {@@ The record TRow contains information about a spreadsheet row: @param Row The index of the row (beginning with 0) @param Height The height of the row (expressed in the units defined @@ -782,14 +788,15 @@ type automatic height @param FormatIndex Row default format, index into the workbook's FCellFormatList - @param Hidden Indicates that the row is hidden - Only rows with non-default height or non-default format have a row record. } + @param Options @See TsColRowOption + Only rows with non-default height or non-default format or non-default + Options have a row record. } TRow = record Row: Cardinal; Height: Single; RowHeightType: TsRowHeightType; FormatIndex: Integer; - Hidden: Boolean; + Options: TsColRowOptions; end; {@@ Pointer to a TRow record } @@ -802,14 +809,15 @@ type @param ColWidthType Specifies whether the column has default or custom width @param FormatIndex Column default format, index into the workbook's FCellFormatlist - @param Hidden Indicates that the column is hidden - Only columns with non-default width or non-default format have a column record. } + @param Options @see TsColRowOptions + Only columns with non-default width or non-default format or non-default + Options have a column record. } TCol = record Col: Cardinal; Width: Single; ColWidthType: TsColWidthType; FormatIndex: Integer; - Hidden: Boolean; + Options: TsColRowOptions; end; {@@ Pointer to a TCol record } diff --git a/components/fpspreadsheet/source/common/xlscommon.pas b/components/fpspreadsheet/source/common/xlscommon.pas index 97e353753..baf7d1f68 100644 --- a/components/fpspreadsheet/source/common/xlscommon.pas +++ b/components/fpspreadsheet/source/common/xlscommon.pas @@ -1674,6 +1674,7 @@ var fmt: PsCellFormat; book: TsWorkbook; sheet: TsWorksheet; + col: PCol; begin book := FWorkbook as TsWorkbook; sheet := FWorksheet as TsWorksheet; @@ -1689,24 +1690,36 @@ begin { Calculate width in workbook units } lCol.Width := book.ConvertUnits(w / 256, suChars, FWorkbook.Units); if SameValue(lCol.Width, sheet.ReadDefaultColWidth(FWorkbook.Units), EPS) then - lCol.ColWidthType := cwtDefault else + lCol.ColWidthType := cwtDefault + else lCol.ColWidthType := cwtCustom; { Read xf record index } xf := WordLEToN(AStream.ReadWord); idx := FCellFormatList.FindIndexOfID(xf); - if idx > -1 then begin + if idx > -1 then + begin fmt := FCellFormatList.Items[idx]; lCol.FormatIndex := book.AddCellFormat(fmt^); end else lCol.FormatIndex := 0; + { Get current value of column options to keep already set PageBreak option } + col := TsWorksheet(FWorksheet).FindCol(c); + if col <> nil then + lCol.Options := col^.Options + else + lCol.Options := []; + { Read column visibility } flags := WordLEToN(AStream.ReadWord); - lCol.Hidden := (flags and $0001 <> 0); + if flags and $0001 = $0001 then + Include(lCol.Options, croHidden) + else + Exclude(lCol.Options, croHidden); { Assign width and format to columns, but only if different from defaults } - if (lCol.FormatIndex > 0) or (lCol.ColWidthType = cwtCustom) or lCol.Hidden then + if (lCol.FormatIndex > 0) or (lCol.ColWidthType = cwtCustom) or (lCol.Options <> []) then for c := c1 to c2 do sheet.WriteColInfo(c, lCol); end; @@ -2544,6 +2557,7 @@ type var rowrec: TRowRecord; lRow: TRow; + row: PRow; h: word; hpts: Single; hdef: Single; @@ -2583,12 +2597,21 @@ begin // Find the format with ID xf lRow.FormatIndex := XFToFormatIndex(xf); + { Get current value of row Options to keep Pagebreak already written } + row := TsWorksheet(FWorksheet).FindRow(rowRec.RowIndex); + if row <> nil then + lRow.Options := row^.Options + else + lRow.Options := []; { Row visibility } - lRow.Hidden := rowRec.Flags and $00000020 <> 0; + if rowRec.Flags and $00000020 <> 0 then + Include(lRow.Options, croHidden) + else + Exclude(lRow.Options, croHidden); // We only create a row record for fpspreadsheet if the row has a // non-standard height (i.e. different from default row height) or format. - if isNonDefaultHeight or hasFormat or lRow.Hidden then + if isNonDefaultHeight or hasFormat or (lRow.Options <> []) then TsWorksheet(FWorksheet).WriteRowInfo(rowrec.RowIndex, lRow); end; @@ -3988,7 +4011,7 @@ begin w := round(width * 256); optn := 0; - if ACol^.Hidden then optn := optn + $0001; + if (croHidden in ACol^.Options) then optn := optn + $0001; // outline, collapsed flags are not used rec.ColWidth := WordToLE(w); @@ -4851,7 +4874,7 @@ begin { Option flags } dw := $00000100; // bit 8 is always 1 - if Assigned(ARow) and ARow^.Hidden then dw := dw or $00000020; + if Assigned(ARow) and (croHidden in ARow^.Options) then dw := dw or $00000020; if spaceabove then dw := dw or $10000000; if spacebelow then dw := dw or $20000000; if (ARow <> nil) and (ARow^.RowHeightType = rhtCustom) then // Custom row height diff --git a/components/fpspreadsheet/source/common/xlsxooxml.pas b/components/fpspreadsheet/source/common/xlsxooxml.pas index 35c6be988..a3a1a4c48 100644 --- a/components/fpspreadsheet/source/common/xlsxooxml.pas +++ b/components/fpspreadsheet/source/common/xlsxooxml.pas @@ -1187,10 +1187,12 @@ begin end else lCol.FormatIndex := 0; + lCol.Options := []; s := GetAttrValue(colNode, 'hidden'); - lCol.Hidden := StrIsTrue(s); + if StrIsTrue(s) then + Include(lCol.Options, croHidden); - if (lCol.ColWidthType = cwtCustom) or (lCol.FormatIndex > 0) or lCol.Hidden then + if (lCol.ColWidthType = cwtCustom) or (lCol.FormatIndex > 0) or (lCol.Options <> []) then for col := col1 to Min(col2, FLastCol) do sheet.WriteColInfo(col, lCol); end; @@ -2015,11 +2017,13 @@ begin end; { Row visibility } + lRow.Options := []; s := GetAttrvalue(ANode, 'hidden'); - lRow.Hidden := StrIsTrue(s); + if StrIsTrue(s) then + Include(lRow.Options, croHidden); { Write out } - if (lRow.RowHeightType <> rhtDefault) or (lRow.FormatIndex <> 0) or lRow.Hidden then + if (lRow.RowHeightType <> rhtDefault) or (lRow.FormatIndex <> 0) or (lRow.Options <> []) then (AWorksheet as TsWorksheet).WriteRowInfo(r, lRow); end; @@ -3059,7 +3063,7 @@ begin end; if lCol^.FormatIndex > 0 then customStyle := Format('style="%d" ', [lCol^.FormatIndex]); - if lCol^.Hidden then hiddenStr := ' hidden="1"'; + if (croHidden in lCol^.Options) then hiddenStr := ' hidden="1"'; end; AppendToStream(AStream, Format( '