You've already forked lazarus-ccr
fpspreadsheet: Add writing support of page breaks to ODS format. Related ODS tests still failing.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7073 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -112,7 +112,6 @@ type
|
|||||||
function FindNumFormatByName(ANumFmtName: String): Integer;
|
function FindNumFormatByName(ANumFmtName: String): Integer;
|
||||||
function FindRowStyleByName(AStyleName: String): Integer;
|
function FindRowStyleByName(AStyleName: String): Integer;
|
||||||
function FindTableStyleByName(AStyleName: String): Integer;
|
function FindTableStyleByName(AStyleName: String): Integer;
|
||||||
// procedure FixFormulas;
|
|
||||||
procedure ReadCell(ANode: TDOMNode; ARow, ACol: Integer;
|
procedure ReadCell(ANode: TDOMNode; ARow, ACol: Integer;
|
||||||
AFormatIndex: Integer; out AColsRepeated: Integer);
|
AFormatIndex: Integer; out AColsRepeated: Integer);
|
||||||
procedure ReadCellImages(ANode: TDOMNode; ARow, ACol: Cardinal);
|
procedure ReadCellImages(ANode: TDOMNode; ARow, ACol: Cardinal);
|
||||||
@ -242,12 +241,15 @@ type
|
|||||||
procedure AddBuiltinNumFormats; override;
|
procedure AddBuiltinNumFormats; override;
|
||||||
procedure CreateStreams;
|
procedure CreateStreams;
|
||||||
procedure DestroyStreams;
|
procedure DestroyStreams;
|
||||||
|
function FindRowStyle(ASheet: TsBasicWorksheet; ARowIndex: Integer): Integer;
|
||||||
procedure GetHeaderFooterImageName(APageLayout: TsPageLayout;
|
procedure GetHeaderFooterImageName(APageLayout: TsPageLayout;
|
||||||
out AHeader, AFooter: String);
|
out AHeader, AFooter: String);
|
||||||
procedure GetHeaderFooterImagePosStr(APagelayout: TsPageLayout;
|
procedure GetHeaderFooterImagePosStr(APagelayout: TsPageLayout;
|
||||||
out AHeader, AFooter: String);
|
out AHeader, AFooter: String);
|
||||||
|
{
|
||||||
procedure GetRowStyleAndHeight(ASheet: TsBasicWorksheet; ARowIndex: Integer;
|
procedure GetRowStyleAndHeight(ASheet: TsBasicWorksheet; ARowIndex: Integer;
|
||||||
out AStyleName: String; out AHeight: Single);
|
out AStyleName: String; out AHeight: Single);
|
||||||
|
}
|
||||||
procedure InternalWriteToStream(AStream: TStream);
|
procedure InternalWriteToStream(AStream: TStream);
|
||||||
procedure ListAllColumnStyles;
|
procedure ListAllColumnStyles;
|
||||||
procedure ListAllHeaderFooterFonts;
|
procedure ListAllHeaderFooterFonts;
|
||||||
@ -1461,52 +1463,6 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
Result := -1;
|
Result := -1;
|
||||||
end;
|
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);
|
procedure TsSpreadOpenDocReader.ReadAutomaticStyles(AStylesNode: TDOMNode);
|
||||||
var
|
var
|
||||||
@ -4876,82 +4832,67 @@ end;
|
|||||||
procedure TsSpreadOpenDocWriter.ListAllColumnStyles;
|
procedure TsSpreadOpenDocWriter.ListAllColumnStyles;
|
||||||
var
|
var
|
||||||
i, j, c: Integer;
|
i, j, c: Integer;
|
||||||
|
book: TsWorkbook;
|
||||||
sheet: TsWorksheet;
|
sheet: TsWorksheet;
|
||||||
found: Boolean;
|
found: Boolean;
|
||||||
colstyle: TColumnStyleData;
|
colstyle: TColumnStyleData;
|
||||||
|
item: TColumnStyleData;
|
||||||
|
colPageBreak: Boolean;
|
||||||
w: Double;
|
w: Double;
|
||||||
|
wDef: Double; // Default column width
|
||||||
col: PCol;
|
col: PCol;
|
||||||
begin
|
begin
|
||||||
|
book := TsWorkbook(FWorkbook);
|
||||||
|
sheet := book.GetFirstWorksheet;
|
||||||
|
if sheet = nil then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
wDef := sheet.ReadDefaultColWidth(book.Units);
|
||||||
|
|
||||||
{ At first, add the default column width }
|
{ At first, add the default column width }
|
||||||
colStyle := TColumnStyleData.Create;
|
colStyle := TColumnStyleData.Create;
|
||||||
colStyle.Name := 'co1';
|
colStyle.Name := 'co1';
|
||||||
colStyle.ColWidth := TsWorkbook(Workbook).ConvertUnits(12, suChars, FWorkbook.Units);
|
colStyle.ColWidth := wDef;
|
||||||
FColumnStyleList.Add(colStyle);
|
FColumnStyleList.Add(colStyle);
|
||||||
|
|
||||||
{ Then iterate through all sheets and all columns and store the unique
|
{ Then iterate through all sheets and all columns and store the unique
|
||||||
column widths in the FColumnStyleList. }
|
column widths in the FColumnStyleList. }
|
||||||
for i:=0 to (Workbook as TsWorkbook).GetWorksheetCount-1 do
|
for i:=0 to book.GetWorksheetCount-1 do
|
||||||
begin
|
begin
|
||||||
sheet := TsWorkbook(Workbook).GetWorksheetByIndex(i);
|
sheet := book.GetWorksheetByIndex(i);
|
||||||
|
wDef := sheet.ReadDefaultColWidth(book.Units);
|
||||||
for c := 0 to sheet.Cols.Count-1 do
|
for c := 0 to sheet.Cols.Count-1 do
|
||||||
begin
|
begin
|
||||||
col := PCol(sheet.Cols[c]);
|
col := PCol(sheet.Cols[c]);
|
||||||
if (col <> nil) and (col^.ColWidthType = cwtCustom) then
|
if (col^.ColWidthType = cwtCustom) or (croPageBreak in col^.Options) then
|
||||||
begin
|
begin
|
||||||
|
colPageBreak := (croPageBreak in col^.Options); // has page break?
|
||||||
w := col^.Width; // is in workbook units
|
w := col^.Width; // is in workbook units
|
||||||
// Look for this width in the current ColumnStyleList
|
// Look for this width in the current ColumnStyleList
|
||||||
found := false;
|
found := false;
|
||||||
for j := 0 to FColumnStyleList.Count - 1 do
|
for j := 0 to FColumnStyleList.Count - 1 do begin
|
||||||
if SameValue(TColumnStyleData(FColumnstyleList[j]).ColWidth, w, COLWIDTH_EPS) then
|
item := TColumnStyleData(FColumnStyleList[j]);
|
||||||
|
if SameValue(item.ColWidth, w, COLWIDTH_EPS) and (item.PageBreak = colPageBreak) then
|
||||||
begin
|
begin
|
||||||
found := true;
|
found := true;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
// Not found? Then add the column as a new column style
|
// Not found? Then add the column as a new column style
|
||||||
if not found then
|
if not found then
|
||||||
begin
|
begin
|
||||||
colStyle := TColumnStyleData.Create;
|
colStyle := TColumnStyleData.Create;
|
||||||
colStyle.Name := Format('co%d', [FColumnStyleList.Count + 1]);
|
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);
|
FColumnStyleList.Add(colStyle);
|
||||||
end;
|
end;
|
||||||
end;
|
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;
|
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;
|
end;
|
||||||
|
|
||||||
{ Collects the fonts used by headers and footers in the FHeaderFooterFontList }
|
{ Collects the fonts used by headers and footers in the FHeaderFooterFontList }
|
||||||
@ -5012,10 +4953,13 @@ var
|
|||||||
row: PRow;
|
row: PRow;
|
||||||
found: Boolean;
|
found: Boolean;
|
||||||
rowstyle: TRowStyleData;
|
rowstyle: TRowStyleData;
|
||||||
|
item: TRowStyleData;
|
||||||
|
rowPageBreak: Boolean;
|
||||||
h: Double;
|
h: Double;
|
||||||
book: TsWorkbook;
|
book: TsWorkbook;
|
||||||
begin
|
begin
|
||||||
book := FWorkbook as TsWorkbook;
|
book := FWorkbook as TsWorkbook;
|
||||||
|
|
||||||
{ At first, add the default row height }
|
{ At first, add the default row height }
|
||||||
{ Initially, row height units will be the same as in the workbook }
|
{ Initially, row height units will be the same as in the workbook }
|
||||||
rowStyle := TRowStyleData.Create;
|
rowStyle := TRowStyleData.Create;
|
||||||
@ -5032,23 +4976,28 @@ begin
|
|||||||
row := sheet.FindRow(r);
|
row := sheet.FindRow(r);
|
||||||
if row <> nil then
|
if row <> nil then
|
||||||
begin
|
begin
|
||||||
|
rowPageBreak := (croPageBreak in row^.Options);
|
||||||
h := sheet.GetRowHeight(r, FWorkbook.Units);
|
h := sheet.GetRowHeight(r, FWorkbook.Units);
|
||||||
// Look for this height in the current RowStyleList
|
// Look for this height in the current RowStyleList
|
||||||
found := false;
|
found := false;
|
||||||
for j:=0 to FRowStyleList.Count-1 do
|
for j:=0 to FRowStyleList.Count-1 do begin
|
||||||
if SameValue(TRowStyleData(FRowStyleList[j]).RowHeight, h, ROWHEIGHT_EPS)
|
item := TRowStyleData(FRowStyleList[j]);
|
||||||
and (TRowStyleData(FRowStyleList[j]).RowHeightType = row^.RowHeightType)
|
if SameValue(item.RowHeight, h, ROWHEIGHT_EPS) and
|
||||||
then begin
|
(item.RowHeightType = row^.RowHeightType) and
|
||||||
|
(item.PageBreak = rowPageBreak) then
|
||||||
|
begin
|
||||||
found := true;
|
found := true;
|
||||||
break;
|
break;
|
||||||
end;
|
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
|
if not found then
|
||||||
begin
|
begin
|
||||||
rowStyle := TRowStyleData.Create;
|
rowStyle := TRowStyleData.Create;
|
||||||
rowStyle.Name := Format('ro%d', [FRowStyleList.Count+1]);
|
rowStyle.Name := Format('ro%d', [FRowStyleList.Count+1]);
|
||||||
rowStyle.RowHeight := h;
|
rowStyle.RowHeight := h;
|
||||||
rowStyle.RowHeightType := row^.RowHeightType;
|
rowStyle.RowHeightType := row^.RowHeightType;
|
||||||
|
rowStyle.PageBreak := rowPageBreak;
|
||||||
FRowStyleList.Add(rowStyle);
|
FRowStyleList.Add(rowStyle);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -5545,7 +5494,10 @@ procedure TsSpreadOpenDocWriter.WriteColStyles(AStream: TStream);
|
|||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
colstyle: TColumnStyleData;
|
colstyle: TColumnStyleData;
|
||||||
|
book: TsWorkbook;
|
||||||
begin
|
begin
|
||||||
|
book := TsWorkbook(FWorkbook);
|
||||||
|
|
||||||
if FColumnStyleList.Count = 0 then
|
if FColumnStyleList.Count = 0 then
|
||||||
begin
|
begin
|
||||||
AppendToStream(AStream,
|
AppendToStream(AStream,
|
||||||
@ -5565,9 +5517,11 @@ begin
|
|||||||
|
|
||||||
// Column width
|
// Column width
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<style:table-column-properties style:column-width="%.3fmm" fo:break-before="auto"/>',
|
'<style:table-column-properties style:column-width="%.3fmm" fo:break-before="%s"/>', [
|
||||||
[TsWorkbook(FWorkbook).ConvertUnits(colStyle.ColWidth, FWorkbook.Units, suMillimeters)],
|
colStyle.ColWidth,
|
||||||
FPointSeparatorSettings));
|
PAGE_BREAK[colStyle.PageBreak]
|
||||||
|
], FPointSeparatorSettings)
|
||||||
|
);
|
||||||
|
|
||||||
// End
|
// End
|
||||||
AppendToStream(AStream,
|
AppendToStream(AStream,
|
||||||
@ -5588,9 +5542,10 @@ var
|
|||||||
firstRepeatedPrintCol, lastRepeatedPrintCol: Longint;
|
firstRepeatedPrintCol, lastRepeatedPrintCol: Longint;
|
||||||
headerCols: Boolean;
|
headerCols: Boolean;
|
||||||
isHidden1, isHidden: Boolean;
|
isHidden1, isHidden: Boolean;
|
||||||
|
isPageBreak1, isPageBreak: Boolean;
|
||||||
colHiddenStr: String;
|
colHiddenStr: String;
|
||||||
|
colStyleData: TColumnStyleData;
|
||||||
begin
|
begin
|
||||||
// widthMultiplier := Workbook.GetFont(0).Size / 2;
|
|
||||||
lastCol := sheet.GetLastColIndex;
|
lastCol := sheet.GetLastColIndex;
|
||||||
firstRepeatedPrintCol := longInt(sheet.PageLayout.RepeatedCols.FirstIndex);
|
firstRepeatedPrintCol := longInt(sheet.PageLayout.RepeatedCols.FirstIndex);
|
||||||
lastRepeatedPrintCol := longint(sheet.PageLayout.RepeatedCols.LastIndex);
|
lastRepeatedPrintCol := longint(sheet.PageLayout.RepeatedCols.LastIndex);
|
||||||
@ -5605,6 +5560,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
w1 := sheet.GetColWidth(c, FWorkbook.Units);
|
w1 := sheet.GetColWidth(c, FWorkbook.Units);
|
||||||
isHidden1 := sheet.ColHidden(c) or (w1 = 0);
|
isHidden1 := sheet.ColHidden(c) or (w1 = 0);
|
||||||
|
isPageBreak1 := sheet.IsPageBreakCol(c);
|
||||||
|
|
||||||
if (c = firstRepeatedPrintCol) then
|
if (c = firstRepeatedPrintCol) then
|
||||||
begin
|
begin
|
||||||
@ -5614,11 +5570,21 @@ begin
|
|||||||
|
|
||||||
// Find width in ColumnStyleList to retrieve corresponding style name
|
// Find width in ColumnStyleList to retrieve corresponding style name
|
||||||
styleName := '';
|
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
|
if SameValue(TColumnStyleData(FColumnStyleList[k]).ColWidth, w1, COLWIDTH_EPS) then begin
|
||||||
styleName := TColumnStyleData(FColumnStyleList[k]).Name;
|
styleName := TColumnStyleData(FColumnStyleList[k]).Name;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
if stylename = '' then
|
if stylename = '' then
|
||||||
stylename := 'co1';
|
stylename := 'co1';
|
||||||
{
|
{
|
||||||
@ -5634,7 +5600,8 @@ begin
|
|||||||
begin
|
begin
|
||||||
w := sheet.GetColWidth(k, FWorkbook.Units);
|
w := sheet.GetColWidth(k, FWorkbook.Units);
|
||||||
isHidden := sheet.ColHidden(k) or (w = 0);
|
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)
|
inc(colsRepeated)
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
@ -5645,7 +5612,8 @@ begin
|
|||||||
begin
|
begin
|
||||||
w := sheet.GetColWidth(k, FWorkbook.Units);
|
w := sheet.GetColWidth(k, FWorkbook.Units);
|
||||||
isHidden := sheet.ColHidden(k) or (w = 0);
|
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)
|
inc(colsRepeated)
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
@ -6273,10 +6241,30 @@ var
|
|||||||
fmtIndex: integer;
|
fmtIndex: integer;
|
||||||
sheet: TsWorksheet absolute ASheet;
|
sheet: TsWorksheet absolute ASheet;
|
||||||
rowHiddenStr: String;
|
rowHiddenStr: String;
|
||||||
|
styleIdx: Integer;
|
||||||
|
rowStyleData: TRowStyleData;
|
||||||
begin
|
begin
|
||||||
// Get row
|
// Get row
|
||||||
row := sheet.FindRow(ARowIndex);
|
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
|
// Get style and height of row
|
||||||
GetRowStyleAndHeight(ASheet, ARowIndex, stylename, h);
|
GetRowStyleAndHeight(ASheet, ARowIndex, stylename, h);
|
||||||
|
|
||||||
@ -6285,7 +6273,7 @@ begin
|
|||||||
rowHiddenStr := ' table:visibility="collapse"'
|
rowHiddenStr := ' table:visibility="collapse"'
|
||||||
else
|
else
|
||||||
rowHiddenStr := '';
|
rowHiddenStr := '';
|
||||||
|
}
|
||||||
// Write opening row tag. We don't support repeatedRows here.
|
// Write opening row tag. We don't support repeatedRows here.
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<table:table-row table:style-name="%s"%s>', [stylename, rowHiddenStr]));
|
'<table:table-row table:style-name="%s"%s>', [stylename, rowHiddenStr]));
|
||||||
@ -6416,21 +6404,53 @@ var
|
|||||||
rowsRepeatedStr: String;
|
rowsRepeatedStr: String;
|
||||||
rowHiddenStr: String;
|
rowHiddenStr: String;
|
||||||
isHidden1, isHidden: Boolean;
|
isHidden1, isHidden: Boolean;
|
||||||
|
isPageBreak1, isPageBreak: Boolean;
|
||||||
|
styleIdx: Integer;
|
||||||
|
rowStyleData: TRowStyleData;
|
||||||
begin
|
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
|
// Get style and height of row
|
||||||
GetRowStyleAndHeight(ASheet, ARowIndex, stylename, h);
|
GetRowStyleAndHeight(ASheet, ARowIndex, stylename, h);
|
||||||
|
}
|
||||||
|
|
||||||
// Determine how often this row is repeated
|
// Determine how often this row is repeated
|
||||||
row := sheet.FindRow(ARowIndex);
|
row := sheet.FindRow(ARowIndex);
|
||||||
|
if Assigned(row) then begin
|
||||||
isHidden1 := (round(h) = 0) or ((row <> nil) and (croHidden in row^.Options));
|
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"', '');
|
rowHiddenStr := IfThen(isHidden1, ' table:visibility="collapse"', '');
|
||||||
|
|
||||||
// Rows with format are not repeated - too complicated...
|
// Rows with format are not repeated - too complicated...
|
||||||
if (row <> nil) and (row^.FormatIndex > 0) then
|
if (row <> nil) and (row^.FormatIndex > 0) then
|
||||||
ARowsRepeated := 1
|
ARowsRepeated := 1
|
||||||
else
|
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
|
if ALastRowIndex > -1 then begin
|
||||||
r := ARowIndex + 1;
|
r := ARowIndex + 1;
|
||||||
while r <= ALastRowIndex do
|
while r <= ALastRowIndex do
|
||||||
@ -6438,9 +6458,13 @@ begin
|
|||||||
if not sheet.IsEmptyRow(r) then
|
if not sheet.IsEmptyRow(r) then
|
||||||
break;
|
break;
|
||||||
row := sheet.FindRow(r);
|
row := sheet.FindRow(r);
|
||||||
|
isPageBreak := (row <> nil) and (croPageBreak in row^.Options);
|
||||||
isHidden := (row <> nil) and
|
isHidden := (row <> nil) and
|
||||||
((croHidden in row^.Options) 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
|
if ((row <> nil) and (row^.FormatIndex > 0)) or
|
||||||
|
(isHidden <> isHidden1) or
|
||||||
|
(isPageBreak <> isPageBreak1)
|
||||||
|
then
|
||||||
break;
|
break;
|
||||||
h1 := sheet.GetRowHeight(r, FWorkbook.Units);
|
h1 := sheet.GetRowHeight(r, FWorkbook.Units);
|
||||||
if not SameValue(h, h1, ROWHEIGHT_EPS) then
|
if not SameValue(h, h1, ROWHEIGHT_EPS) then
|
||||||
@ -6527,6 +6551,36 @@ begin
|
|||||||
'</table:table-row>');
|
'</table:table-row>');
|
||||||
end;
|
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;
|
procedure TsSpreadOpenDocWriter.GetRowStyleAndHeight(ASheet: TsBasicWorksheet;
|
||||||
ARowIndex: Integer; out AStyleName: String; out AHeight: Single);
|
ARowIndex: Integer; out AStyleName: String; out AHeight: Single);
|
||||||
var
|
var
|
||||||
@ -6541,11 +6595,19 @@ begin
|
|||||||
AHeight := row^.Height; // row height in workbook units
|
AHeight := row^.Height; // row height in workbook units
|
||||||
for k := 0 to FRowStyleList.Count-1 do begin
|
for k := 0 to FRowStyleList.Count-1 do begin
|
||||||
rowStyleData := TRowStyleData(FRowStyleList[k]);
|
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
|
if SameValue(rowStyleData.RowHeight, AHeight, ROWHEIGHT_EPS) and
|
||||||
(rowstyleData.RowHeightType = row^.RowHeightType) and
|
(rowstyleData.RowHeightType = row^.RowHeightType) and
|
||||||
(rowstyleData.RowHeightType <> rhtDefault)
|
(rowstyleData.RowHeightType <> rhtDefault) and
|
||||||
then begin
|
(rowstyleData.PageBreak = isPageBreak) then
|
||||||
|
}
|
||||||
|
begin
|
||||||
AStyleName := rowStyleData.Name;
|
AStyleName := rowStyleData.Name;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
@ -6556,6 +6618,7 @@ begin
|
|||||||
AHeight := (ASheet as TsWorksheet).ReadDefaultRowHeight(FWorkbook.Units);
|
AHeight := (ASheet as TsWorksheet).ReadDefaultRowHeight(FWorkbook.Units);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
{ Write the style nodes for rows ("ro1", "ro2", ...); they contain only
|
{ Write the style nodes for rows ("ro1", "ro2", ...); they contain only
|
||||||
row height information. "ro1" is the default row height }
|
row height information. "ro1" is the default row height }
|
||||||
@ -6563,7 +6626,12 @@ procedure TsSpreadOpenDocWriter.WriteRowStyles(AStream: TStream);
|
|||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
rowstyle: TRowStyleData;
|
rowstyle: TRowStyleData;
|
||||||
|
book: TsWorkbook;
|
||||||
|
sheet: TsWorksheet;
|
||||||
begin
|
begin
|
||||||
|
book := TsWorkbook(FWorkbook);
|
||||||
|
sheet := TsWorksheet(FWorksheet);
|
||||||
|
|
||||||
if FRowStyleList.Count = 0 then
|
if FRowStyleList.Count = 0 then
|
||||||
begin
|
begin
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
@ -6571,7 +6639,7 @@ begin
|
|||||||
'<style:table-row-properties style:row-height="%.3fmm" ' +
|
'<style:table-row-properties style:row-height="%.3fmm" ' +
|
||||||
'fo:break-before="auto" style:use-optimal-row-height="true"/>' +
|
'fo:break-before="auto" style:use-optimal-row-height="true"/>' +
|
||||||
'</style:style>',
|
'</style:style>',
|
||||||
[(FWorksheet as TsWorksheet).ReadDefaultRowHeight(suMillimeters)]
|
[sheet.ReadDefaultRowHeight(suMillimeters)]
|
||||||
));
|
));
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@ -6587,12 +6655,12 @@ begin
|
|||||||
// Row height
|
// Row height
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<style:table-row-properties style:row-height="%.3fmm" ',
|
'<style:table-row-properties style:row-height="%.3fmm" ',
|
||||||
[TsWorkbook(FWorkbook).ConvertUnits(rowStyle.RowHeight, FWorkbook.Units, suMillimeters)],
|
[book.ConvertUnits(rowStyle.RowHeight, book.Units, suMillimeters)],
|
||||||
FPointSeparatorSettings));
|
FPointSeparatorSettings));
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'style:use-optimal-row-height="%s" ', [FALSE_TRUE[rowstyle.RowHeightType <> rhtCustom]]));
|
'style:use-optimal-row-height="%s" ', [FALSE_TRUE[rowstyle.RowHeightType <> rhtCustom]]));
|
||||||
AppendToStream(AStream,
|
AppendToStream(AStream, Format(
|
||||||
'fo:break-before="auto"/>');
|
'fo:break-before="%s"/>', [PAGE_BREAK[rowStyle.PageBreak]]));
|
||||||
|
|
||||||
// End
|
// End
|
||||||
AppendToStream(AStream,
|
AppendToStream(AStream,
|
||||||
|
@ -306,6 +306,11 @@ type
|
|||||||
procedure TestWriteRead_AddPageBreak_Row_XML;
|
procedure TestWriteRead_AddPageBreak_Row_XML;
|
||||||
procedure TestWriteRead_AddPageBreak_RowHidden_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
|
// Remove a page break column
|
||||||
procedure TestWriteRead_RemovePageBreak_Col_BIFF2;
|
procedure TestWriteRead_RemovePageBreak_Col_BIFF2;
|
||||||
procedure TestWriteRead_RemovePageBreak_Row_BIFF2;
|
procedure TestWriteRead_RemovePageBreak_Row_BIFF2;
|
||||||
@ -329,6 +334,11 @@ type
|
|||||||
procedure TestWriteRead_RemovePageBreak_ColHidden_XML;
|
procedure TestWriteRead_RemovePageBreak_ColHidden_XML;
|
||||||
procedure TestWriteRead_RemovePageBreak_Row_XML;
|
procedure TestWriteRead_RemovePageBreak_Row_XML;
|
||||||
procedure TestWriteRead_RemovePageBreak_RowHidden_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;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -2334,6 +2344,23 @@ begin
|
|||||||
TestWriteRead_AddPageBreak_Row(true, sfExcelXML);
|
TestWriteRead_AddPageBreak_Row(true, sfExcelXML);
|
||||||
end;
|
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
|
{ Remove page break
|
||||||
- Hidden: set the Hidden flag in the options to test whether it is damaged
|
- Hidden: set the Hidden flag in the options to test whether it is damaged
|
||||||
@ -2561,6 +2588,23 @@ begin
|
|||||||
TestWriteRead_RemovePageBreak_Row(true, sfExcelXML);
|
TestWriteRead_RemovePageBreak_Row(true, sfExcelXML);
|
||||||
end;
|
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
|
initialization
|
||||||
RegisterTest(TSpreadWriteRead_ColRow_Tests);
|
RegisterTest(TSpreadWriteRead_ColRow_Tests);
|
||||||
InitTestData;
|
InitTestData;
|
||||||
|
Reference in New Issue
Block a user