You've already forked lazarus-ccr
fpspreadsheet: Add printranges and repeated header cols/rows (for printing) to worksheet. Implement writing to xlsx and ods. (Request from the forum http://forum.lazarus.freepascal.org/index.php/topic,31496.0.html).
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4496 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@@ -165,6 +165,7 @@ type
|
|||||||
procedure WriteColumns(AStream: TStream; ASheet: TsWorksheet);
|
procedure WriteColumns(AStream: TStream; ASheet: TsWorksheet);
|
||||||
procedure WriteFontNames(AStream: TStream);
|
procedure WriteFontNames(AStream: TStream);
|
||||||
procedure WriteMasterStyles(AStream: TStream);
|
procedure WriteMasterStyles(AStream: TStream);
|
||||||
|
procedure WriteNamedExpressions(AStream: TStream; ASheet: TsWorksheet);
|
||||||
procedure WriteNumFormats(AStream: TStream);
|
procedure WriteNumFormats(AStream: TStream);
|
||||||
procedure WriteRowStyles(AStream: TStream);
|
procedure WriteRowStyles(AStream: TStream);
|
||||||
procedure WriteRowsAndCells(AStream: TStream; ASheet: TsWorksheet);
|
procedure WriteRowsAndCells(AStream: TStream; ASheet: TsWorksheet);
|
||||||
@@ -183,6 +184,7 @@ type
|
|||||||
function WriteHeaderFooterFontXMLAsString(AFont: TsHeaderFooterFont): String;
|
function WriteHeaderFooterFontXMLAsString(AFont: TsHeaderFooterFont): String;
|
||||||
function WriteHorAlignmentStyleXMLAsString(const AFormat: TsCellFormat): String;
|
function WriteHorAlignmentStyleXMLAsString(const AFormat: TsCellFormat): String;
|
||||||
function WritePageLayoutAsXMLString(AStyleName: String; const APageLayout: TsPageLayout): String;
|
function WritePageLayoutAsXMLString(AStyleName: String; const APageLayout: TsPageLayout): String;
|
||||||
|
function WritePrintRangesAsXMLString(ASheet: TsWorksheet): String;
|
||||||
function WriteTextRotationStyleXMLAsString(const AFormat: TsCellFormat): String;
|
function WriteTextRotationStyleXMLAsString(const AFormat: TsCellFormat): String;
|
||||||
function WriteVertAlignmentStyleXMLAsString(const AFormat: TsCellFormat): String;
|
function WriteVertAlignmentStyleXMLAsString(const AFormat: TsCellFormat): String;
|
||||||
function WriteWordwrapStyleXMLAsString(const AFormat: TsCellFormat): String;
|
function WriteWordwrapStyleXMLAsString(const AFormat: TsCellFormat): String;
|
||||||
@@ -4286,8 +4288,8 @@ begin
|
|||||||
|
|
||||||
// Header
|
// Header
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<table:table table:name="%s" table:style-name="ta%d">', [
|
'<table:table table:name="%s" table:style-name="ta%d" %s>', [
|
||||||
FWorkSheet.Name, ASheetIndex+1
|
FWorkSheet.Name, ASheetIndex+1, WritePrintRangesAsXMLString(FWorksheet)
|
||||||
]));
|
]));
|
||||||
|
|
||||||
// columns
|
// columns
|
||||||
@@ -4302,6 +4304,9 @@ begin
|
|||||||
end else
|
end else
|
||||||
WriteRowsAndCells(AStream, FWorksheet);
|
WriteRowsAndCells(AStream, FWorksheet);
|
||||||
|
|
||||||
|
// named expressions, i.e. print range, repeated cols/rows
|
||||||
|
WriteNamedExpressions(AStream, FWorksheet);
|
||||||
|
|
||||||
// Footer
|
// Footer
|
||||||
AppendToStream(AStream,
|
AppendToStream(AStream,
|
||||||
'</table:table>');
|
'</table:table>');
|
||||||
@@ -4412,23 +4417,38 @@ procedure TsSpreadOpenDocWriter.WriteColumns(AStream: TStream;
|
|||||||
ASheet: TsWorksheet);
|
ASheet: TsWorksheet);
|
||||||
var
|
var
|
||||||
lastCol: Integer;
|
lastCol: Integer;
|
||||||
j, k: Integer;
|
c, k: Integer;
|
||||||
w, w_mm: Double;
|
w, w_mm: Double;
|
||||||
widthMultiplier: Double;
|
widthMultiplier: Double;
|
||||||
styleName: String;
|
styleName: String;
|
||||||
colsRepeated: Integer;
|
colsRepeated: Integer;
|
||||||
colsRepeatedStr: String;
|
colsRepeatedStr: String;
|
||||||
|
firstRepeatedPrintCol, lastRepeatedPrintCol: Cardinal;
|
||||||
|
headerCols: Boolean;
|
||||||
begin
|
begin
|
||||||
widthMultiplier := Workbook.GetFont(0).Size / 2;
|
widthMultiplier := Workbook.GetFont(0).Size / 2;
|
||||||
lastCol := ASheet.GetLastColIndex;
|
lastCol := ASheet.GetLastColIndex;
|
||||||
|
firstRepeatedPrintCol := ASheet.PageLayout.RepeatedCols.FirstIndex;
|
||||||
|
lastRepeatedPrintCol := ASheet.PageLayout.RepeatedCols.LastIndex;
|
||||||
|
if (firstRepeatedPrintCol <> UNASSIGNED_ROW_COL_INDEX) and
|
||||||
|
(lastRepeatedPrintCol = UNASSIGNED_ROW_COL_INDEX)
|
||||||
|
then
|
||||||
|
lastRepeatedPrintCol := firstRepeatedPrintCol;
|
||||||
|
|
||||||
j := 0;
|
headerCols := false;
|
||||||
while (j <= lastCol) do
|
c := 0;
|
||||||
|
while (c <= lastCol) do
|
||||||
begin
|
begin
|
||||||
w := ASheet.GetColWidth(j);
|
w := ASheet.GetColWidth(c);
|
||||||
// Convert to mm
|
// Convert to mm
|
||||||
w_mm := PtsToMM(w * widthMultiplier);
|
w_mm := PtsToMM(w * widthMultiplier);
|
||||||
|
|
||||||
|
if (c = firstRepeatedPrintCol) then
|
||||||
|
begin
|
||||||
|
headerCols := true;
|
||||||
|
AppendToStream(AStream, '<table:table-header-columns>');
|
||||||
|
end;
|
||||||
|
|
||||||
// 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
|
||||||
@@ -4441,22 +4461,38 @@ begin
|
|||||||
|
|
||||||
// Determine value for "number-columns-repeated"
|
// Determine value for "number-columns-repeated"
|
||||||
colsRepeated := 1;
|
colsRepeated := 1;
|
||||||
k := j+1;
|
k := c+1;
|
||||||
while (k <= lastCol) do
|
if headerCols then
|
||||||
begin
|
while (k <= lastCol) and (k <= lastRepeatedPrintCol) do
|
||||||
if ASheet.GetColWidth(k) = w then
|
begin
|
||||||
inc(colsRepeated)
|
if ASheet.GetColWidth(k) = w then
|
||||||
else
|
inc(colsRepeated)
|
||||||
break;
|
else
|
||||||
inc(k);
|
break;
|
||||||
end;
|
inc(k);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
while (k <= lastCol) do
|
||||||
|
begin
|
||||||
|
if ASheet.GetColWidth(k) = w then
|
||||||
|
inc(colsRepeated)
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
inc(k);
|
||||||
|
end;
|
||||||
colsRepeatedStr := IfThen(colsRepeated = 1, '', Format(' table:number-columns-repeated="%d"', [colsRepeated]));
|
colsRepeatedStr := IfThen(colsRepeated = 1, '', Format(' table:number-columns-repeated="%d"', [colsRepeated]));
|
||||||
|
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<table:table-column table:style-name="%s"%s table:default-cell-style-name="Default" />',
|
'<table:table-column table:style-name="%s"%s table:default-cell-style-name="Default" />',
|
||||||
[styleName, colsRepeatedStr]));
|
[styleName, colsRepeatedStr]));
|
||||||
|
|
||||||
j := j + colsRepeated;
|
if headerCols and (k-1 = lastRepeatedPrintCol) then
|
||||||
|
begin
|
||||||
|
AppendToStream(AStream, '</table:table-header-columns>');
|
||||||
|
headerCols := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
c := c + colsRepeated;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -4617,6 +4653,84 @@ begin
|
|||||||
defFnt.Free;
|
defFnt.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{<table:named-expressions>
|
||||||
|
<table:named-expression table:name="_xlnm.Print_Area" table:base-cell-address="$Sheet1.$A$1" table:expression="[$Sheet1.$A$2:.$F$6];[$Sheet1.$A$11:.$K$21]" />
|
||||||
|
<table:named-expression table:name="_xlnm.Print_Titles" table:base-cell-address="$Sheet1.$A$1" table:expression="[$Sheet1.$A$1:.$D$1048576];[$Sheet1.$A$1:.$AMJ$2]" />
|
||||||
|
</table:named-expressions>}
|
||||||
|
|
||||||
|
procedure TsSpreadOpenDocWriter.WriteNamedExpressions(AStream: TStream;
|
||||||
|
ASheet: TsWorksheet);
|
||||||
|
var
|
||||||
|
stotal, srng: String;
|
||||||
|
j: Integer;
|
||||||
|
prng: TsCellRange;
|
||||||
|
begin
|
||||||
|
stotal := '';
|
||||||
|
|
||||||
|
// Cell block of print range
|
||||||
|
srng := '';
|
||||||
|
for j := 0 to ASheet.NumPrintRanges - 1 do
|
||||||
|
begin
|
||||||
|
prng := ASheet.GetPrintRange(j);
|
||||||
|
srng := srng + ';' + Format('[$%s.%s]', [
|
||||||
|
ASheet.Name, GetCellRangeString(prng.Row1, prng.Col1, prng.Row2, prng.Col2, [])
|
||||||
|
]);
|
||||||
|
end;
|
||||||
|
if srng <> '' then
|
||||||
|
begin
|
||||||
|
Delete(srng, 1, 1);
|
||||||
|
stotal := stotal + Format(
|
||||||
|
'<table:named-expression table:name="_xlnm.Print_Area" table:base-cell-address="$%s.$A$1" table:expression="%s" />',
|
||||||
|
[ASheet.Name, srng]
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Next commented part appears only in files converted from Excel
|
||||||
|
|
||||||
|
{
|
||||||
|
// repeated columns ...
|
||||||
|
srng := '';
|
||||||
|
if ASheet.PageLayout.RepeatedCols.FirstIndex <> UNASSIGNED_ROW_COL_INDEX then
|
||||||
|
begin
|
||||||
|
if ASheet.PageLayout.RepeatedCols.LastIndex = UNASSIGNED_ROW_COL_INDEX then
|
||||||
|
srng := srng + ';' + Format('[$%s.$%s]',
|
||||||
|
[ASheet.Name, GetColString(ASheet.pageLayout.RepeatedCols.FirstIndex)]
|
||||||
|
)
|
||||||
|
else
|
||||||
|
srng := srng + ';' + Format('[$%s.$%s1:.$%s1048576]', [ // [$Sheet1.$A$1:.$D$1048576]
|
||||||
|
ASheet.Name,
|
||||||
|
GetColString(ASheet.Pagelayout.RepeatedCols.FirstIndex),
|
||||||
|
GetColString(ASheet.PageLayout.RepeatedCols.LastIndex)
|
||||||
|
]);
|
||||||
|
end;
|
||||||
|
// ... and repeated rows
|
||||||
|
if ASheet.PageLayout.RepeatedRows.FirstIndex <> UNASSIGNED_ROW_COL_INDEX then
|
||||||
|
begin
|
||||||
|
if ASheet.PageLayout.RepeatedRows.LastIndex = UNASSIGNED_ROW_COL_INDEX then
|
||||||
|
srng := srng + ';' + Format('[$%s.$%d]',
|
||||||
|
[ASheet.Name, ASheet.pageLayout.RepeatedRows.FirstIndex]
|
||||||
|
)
|
||||||
|
else
|
||||||
|
srng := srng + ';' + Format('[$%s.$A$%d:.$AMJ$%d]', [ // [$Sheet1.$A$1:.$AMJ$2]"
|
||||||
|
ASheet.Name,
|
||||||
|
ASheet.Pagelayout.RepeatedRows.FirstIndex+1,
|
||||||
|
ASheet.PageLayout.RepeatedRows.LastIndex+1
|
||||||
|
]);
|
||||||
|
end;
|
||||||
|
if srng <> '' then begin
|
||||||
|
Delete(srng, 1,1);
|
||||||
|
stotal := stotal + Format(
|
||||||
|
'<table:named-expression table:name="_xlnm.Print_Titles" table:bases-cell-address="$%s.$A$1" table:expression="%s" />',
|
||||||
|
[ASheet.Name, srng]
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
// Write to stream if any defined names exist
|
||||||
|
if stotal <> '' then
|
||||||
|
AppendtoStream(AStream,
|
||||||
|
'<table:named-expressions>' + stotal + '</table:named-expressions>');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.WriteNumFormats(AStream: TStream);
|
procedure TsSpreadOpenDocWriter.WriteNumFormats(AStream: TStream);
|
||||||
var
|
var
|
||||||
i, p: Integer;
|
i, p: Integer;
|
||||||
@@ -4657,20 +4771,38 @@ var
|
|||||||
colsRepeatedStr: String;
|
colsRepeatedStr: String;
|
||||||
rowsRepeatedStr: String;
|
rowsRepeatedStr: String;
|
||||||
firstCol, firstRow, lastCol, lastRow: Cardinal;
|
firstCol, firstRow, lastCol, lastRow: Cardinal;
|
||||||
|
firstRepeatedPrintRow, lastRepeatedPrintRow: Cardinal;
|
||||||
rowStyleData: TRowStyleData;
|
rowStyleData: TRowStyleData;
|
||||||
defFontSize: Single;
|
defFontSize: Single;
|
||||||
emptyRowsAbove: Boolean;
|
emptyRowsAbove: Boolean;
|
||||||
|
headerRows: Boolean;
|
||||||
begin
|
begin
|
||||||
// some abbreviations...
|
// some abbreviations...
|
||||||
defFontSize := Workbook.GetFont(0).Size;
|
defFontSize := Workbook.GetFont(0).Size;
|
||||||
GetSheetDimensions(ASheet, firstRow, lastRow, firstCol, lastCol);
|
GetSheetDimensions(ASheet, firstRow, lastRow, firstCol, lastCol);
|
||||||
emptyRowsAbove := firstRow > 0;
|
emptyRowsAbove := firstRow > 0;
|
||||||
|
|
||||||
|
headerRows := false;
|
||||||
|
firstRepeatedPrintRow := ASheet.PageLayout.RepeatedRows.FirstIndex;
|
||||||
|
lastRepeatedPrintRow := ASheet.PageLayout.RepeatedRows.LastIndex;
|
||||||
|
if (firstRepeatedPrintRow <> UNASSIGNED_ROW_COL_INDEX) and
|
||||||
|
(lastRepeatedPrintRow = UNASSIGNED_ROW_COL_INDEX)
|
||||||
|
then
|
||||||
|
lastRepeatedPrintRow := firstRepeatedPrintRow;
|
||||||
|
|
||||||
// Now loop through all rows
|
// Now loop through all rows
|
||||||
r := firstRow;
|
r := firstRow;
|
||||||
while (r <= lastRow) do
|
while (r <= lastRow) do
|
||||||
begin
|
begin
|
||||||
rowsRepeated := 1;
|
rowsRepeated := 1;
|
||||||
|
|
||||||
|
// Header rows need a special tag
|
||||||
|
if (r = firstRepeatedPrintRow) then
|
||||||
|
begin
|
||||||
|
AppendToStream(AStream, '<table:table-header-rows>');
|
||||||
|
headerRows := true;
|
||||||
|
end;
|
||||||
|
|
||||||
// Look for the row style of the current row (r)
|
// Look for the row style of the current row (r)
|
||||||
row := ASheet.FindRow(r);
|
row := ASheet.FindRow(r);
|
||||||
if row = nil then
|
if row = nil then
|
||||||
@@ -4738,6 +4870,14 @@ begin
|
|||||||
[styleName, rowsRepeatedStr, colsRepeatedStr]));
|
[styleName, rowsRepeatedStr, colsRepeatedStr]));
|
||||||
|
|
||||||
r := rr;
|
r := rr;
|
||||||
|
|
||||||
|
// Header rows need a special tag
|
||||||
|
if headerRows and (r-1 = lastRepeatedPrintRow) then
|
||||||
|
begin
|
||||||
|
AppendToStream(AStream, '</table:table-header-rows>');
|
||||||
|
headerRows := false;
|
||||||
|
end;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -4788,6 +4928,13 @@ begin
|
|||||||
AppendToStream(AStream,
|
AppendToStream(AStream,
|
||||||
'</table:table-row>');
|
'</table:table-row>');
|
||||||
|
|
||||||
|
// Header rows need a special tag
|
||||||
|
if headerRows and (r = lastRepeatedPrintRow) then
|
||||||
|
begin
|
||||||
|
AppendToStream(AStream, '</table:table-header-rows>');
|
||||||
|
headerRows := false;
|
||||||
|
end;
|
||||||
|
|
||||||
// Next row
|
// Next row
|
||||||
inc(r, rowsRepeated);
|
inc(r, rowsRepeated);
|
||||||
end;
|
end;
|
||||||
@@ -5453,6 +5600,32 @@ begin
|
|||||||
'</style:page-layout>';
|
'</style:page-layout>';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsSpreadOpenDocWriter.WritePrintRangesAsXMLString(ASheet: TsWorksheet): String;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
rng: TsCellRange;
|
||||||
|
srng: String;
|
||||||
|
begin
|
||||||
|
if ASheet.NumPrintRanges > 0 then
|
||||||
|
begin
|
||||||
|
srng := '';
|
||||||
|
for i := 0 to ASheet.NumPrintRanges - 1 do
|
||||||
|
begin
|
||||||
|
rng := ASheet.GetPrintRange(i);
|
||||||
|
Result := Result + ' ' + Format('%s.%s:%s.%s', [
|
||||||
|
ASheet.Name, GetCellString(rng.Row1,rng.Col1),
|
||||||
|
ASheet.Name, GetCellString(rng.Row2,rng.Col2)
|
||||||
|
]);
|
||||||
|
end;
|
||||||
|
if Result <> '' then
|
||||||
|
begin
|
||||||
|
Delete(Result, 1, 1);
|
||||||
|
Result := 'table:print-ranges="' + Result + '"';
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
Result := '';
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.WriteTableSettings(AStream: TStream);
|
procedure TsSpreadOpenDocWriter.WriteTableSettings(AStream: TStream);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
@@ -127,6 +127,7 @@ type
|
|||||||
FDefaultRowHeight: Single; // in "character heights", i.e. line count
|
FDefaultRowHeight: Single; // in "character heights", i.e. line count
|
||||||
FSortParams: TsSortParams; // Parameters of the current sorting operation
|
FSortParams: TsSortParams; // Parameters of the current sorting operation
|
||||||
FBiDiMode: TsBiDiMode;
|
FBiDiMode: TsBiDiMode;
|
||||||
|
FPrintRanges: TsCellRangeArray;
|
||||||
FOnChangeCell: TsCellEvent;
|
FOnChangeCell: TsCellEvent;
|
||||||
FOnChangeFont: TsCellEvent;
|
FOnChangeFont: TsCellEvent;
|
||||||
FOnCompareCells: TsCellCompareEvent;
|
FOnCompareCells: TsCellCompareEvent;
|
||||||
@@ -488,6 +489,16 @@ type
|
|||||||
procedure UnmergeCells(ARow, ACol: Cardinal); overload;
|
procedure UnmergeCells(ARow, ACol: Cardinal); overload;
|
||||||
procedure UnmergeCells(ARange: String); overload;
|
procedure UnmergeCells(ARange: String); overload;
|
||||||
|
|
||||||
|
// Print ranges
|
||||||
|
function AddPrintRange(ARow1, ACol1, ARow2, ACol2: Cardinal): Integer; overload;
|
||||||
|
function AddPrintRange(const ARange: TsCellRange): Integer; overload;
|
||||||
|
function GetPrintRange(AIndex: Integer): TsCellRange;
|
||||||
|
function NumPrintRanges: Integer;
|
||||||
|
procedure RemovePrintRange(AIndex: Integer);
|
||||||
|
|
||||||
|
procedure SetRepeatedPrintCols(AFirstCol: Cardinal; ALastCol: Cardinal = UNASSIGNED_ROW_COL_INDEX);
|
||||||
|
procedure SetRepeatedPrintRows(AFirstRow: Cardinal; ALastRow: Cardinal = UNASSIGNED_ROW_COL_INDEX);
|
||||||
|
|
||||||
// Notification of changed cells
|
// Notification of changed cells
|
||||||
procedure ChangedCell(ARow, ACol: Cardinal);
|
procedure ChangedCell(ARow, ACol: Cardinal);
|
||||||
procedure ChangedFont(ARow, ACol: Cardinal);
|
procedure ChangedFont(ARow, ACol: Cardinal);
|
||||||
@@ -3278,6 +3289,91 @@ begin
|
|||||||
Result := (ACell <> nil) and (cfMerged in ACell^.Flags);
|
Result := (ACell <> nil) and (cfMerged in ACell^.Flags);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Adds a print range defined by the row/column indexes of its corner cells.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
function TsWorksheet.AddPrintRange(ARow1, ACol1, ARow2, ACol2: Cardinal): Integer;
|
||||||
|
begin
|
||||||
|
Result := Length(FPrintRanges);
|
||||||
|
SetLength(FPrintRanges, Result + 1);
|
||||||
|
with FPrintRanges[Result] do
|
||||||
|
begin
|
||||||
|
Row1 := ARow1;
|
||||||
|
Col1 := ACol1;
|
||||||
|
Row2 := ARow2;
|
||||||
|
Col2 := ACol2;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Adds a print range defined by a TsCellRange record
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
function TsWorksheet.AddPrintRange(const ARange: TsCellRange): Integer;
|
||||||
|
begin
|
||||||
|
Result := AddPrintRange(ARange.Row1, ARange.Col1, ARange.Row2, ARange.Col2);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Returns the TsCellRange record of the print range with the specified index.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
function TsWorksheet.GetPrintRange(AIndex: Integer): TsCellRange;
|
||||||
|
begin
|
||||||
|
Result := FPrintRanges[AIndex];
|
||||||
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Returns the count of print ranges defined for this worksheet
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
function TsWorksheet.NumPrintRanges: Integer;
|
||||||
|
begin
|
||||||
|
Result := Length(FPrintRanges);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Removes the print range specified by the index
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsWorksheet.RemovePrintRange(AIndex: Integer);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
if not InRange(AIndex, 0, High(FPrintRanges)) then exit;
|
||||||
|
for i := AIndex + 1 to High(FPrintRanges) do
|
||||||
|
FPrintRanges[i - 1] := FPrintRanges[i];
|
||||||
|
SetLength(FPrintRanges, Length(FPrintRanges)-1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Defines a range of header columns for printing repeated on every page
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsWorksheet.SetRepeatedPrintCols(AFirstCol, ALastCol: Cardinal);
|
||||||
|
begin
|
||||||
|
if AFirstCol < ALastCol then
|
||||||
|
begin
|
||||||
|
PageLayout.RepeatedCols.FirstIndex := AFirstCol;
|
||||||
|
PageLayout.RepeatedCols.LastIndex := ALastCol;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
PageLayout.RepeatedCols.FirstIndex := ALastCol;
|
||||||
|
PageLayout.RepeatedCols.LastIndex := AFirstCol;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Defines a range of header rows for printing repeated on every page
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsWorksheet.SetRepeatedPrintRows(AFirstRow, ALastRow: Cardinal);
|
||||||
|
begin
|
||||||
|
if AFirstRow < ALastRow then
|
||||||
|
begin
|
||||||
|
PageLayout.RepeatedRows.FirstIndex := AFirstRow;
|
||||||
|
PageLayout.RepeatedRows.LastIndex := ALastRow;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
PageLayout.RepeatedRows.FirstIndex := ALastRow;
|
||||||
|
PageLayout.RepeatedRows.LastIndex := AFirstRow;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Removes the comment from a cell and releases the memory occupied by the node.
|
Removes the comment from a cell and releases the memory occupied by the node.
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
|
@@ -560,7 +560,7 @@ type
|
|||||||
Row, Col: Cardinal;
|
Row, Col: Cardinal;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@ Record combining row and column cornder indexes of a range of cells }
|
{@@ Record combining row and column corner indexes of a range of cells }
|
||||||
TsCellRange = record
|
TsCellRange = record
|
||||||
Row1, Col1, Row2, Col2: Cardinal;
|
Row1, Col1, Row2, Col2: Cardinal;
|
||||||
end;
|
end;
|
||||||
@@ -569,6 +569,11 @@ type
|
|||||||
{@@ Array with cell ranges }
|
{@@ Array with cell ranges }
|
||||||
TsCellRangeArray = array of TsCellRange;
|
TsCellRangeArray = array of TsCellRange;
|
||||||
|
|
||||||
|
{@@ Record containing limiting indexes of column or row range }
|
||||||
|
TsRowColRange = record
|
||||||
|
FirstIndex, LastIndex: Cardinal;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ Options for sorting }
|
{@@ Options for sorting }
|
||||||
TsSortOption = (ssoDescending, ssoCaseInsensitive);
|
TsSortOption = (ssoDescending, ssoCaseInsensitive);
|
||||||
{@@ Set of options for sorting }
|
{@@ Set of options for sorting }
|
||||||
@@ -705,6 +710,8 @@ type
|
|||||||
Array index 1 contains the strings if these options are not used. }
|
Array index 1 contains the strings if these options are not used. }
|
||||||
Headers: array[0..2] of string;
|
Headers: array[0..2] of string;
|
||||||
Footers: array[0..2] of string;
|
Footers: array[0..2] of string;
|
||||||
|
RepeatedCols: TsRowColRange;
|
||||||
|
RepeatedRows: TsRowColRange;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@ Pointer to a page layout record }
|
{@@ Pointer to a page layout record }
|
||||||
|
@@ -172,6 +172,8 @@ function SameFont(AFont1, AFont2: TsFont): Boolean; overload;
|
|||||||
function SameFont(AFont: TsFont; AFontName: String; AFontSize: Single;
|
function SameFont(AFont: TsFont; AFontName: String; AFontSize: Single;
|
||||||
AStyle: TsFontStyles; AColor: TsColor; APos: TsFontPosition): Boolean; overload;
|
AStyle: TsFontStyles; AColor: TsColor; APos: TsFontPosition): Boolean; overload;
|
||||||
|
|
||||||
|
function Range(ARow1, ACol1, ARow2, ACol2: Cardinal): TsCellRange;
|
||||||
|
|
||||||
//function GetUniqueTempDir(Global: Boolean): String;
|
//function GetUniqueTempDir(Global: Boolean): String;
|
||||||
|
|
||||||
procedure AppendToStream(AStream: TStream; const AString: String); inline; overload;
|
procedure AppendToStream(AStream: TStream; const AString: String); inline; overload;
|
||||||
@@ -2127,6 +2129,10 @@ begin
|
|||||||
Options := [];
|
Options := [];
|
||||||
for i:=0 to 2 do Headers[i] := '';
|
for i:=0 to 2 do Headers[i] := '';
|
||||||
for i:=0 to 2 do Footers[i] := '';
|
for i:=0 to 2 do Footers[i] := '';
|
||||||
|
RepeatedRows.FirstIndex := UNASSIGNED_ROW_COL_INDEX;
|
||||||
|
RepeatedRows.LastIndex := UNASSIGNED_ROW_COL_INDEX;
|
||||||
|
RepeatedCols.FirstIndex := UNASSIGNED_ROW_COL_INDEX;
|
||||||
|
RepeatedCols.LastIndex := UNASSIGNED_ROW_COL_INDEX;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -2238,6 +2244,15 @@ begin
|
|||||||
(AFont.Color = AColor) and
|
(AFont.Color = AColor) and
|
||||||
(AFont.Position = APos);
|
(AFont.Position = APos);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function Range(ARow1, ACol1, ARow2, ACol2: Cardinal): TsCellRange;
|
||||||
|
begin
|
||||||
|
Result.Row1 := ARow1;
|
||||||
|
Result.Col1 := ACol1;
|
||||||
|
Result.Row2 := ARow2;
|
||||||
|
Result.Col2 := ACol2;
|
||||||
|
end;
|
||||||
|
|
||||||
(*
|
(*
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Constructs a string of length "Len" containing random uppercase characters
|
Constructs a string of length "Len" containing random uppercase characters
|
||||||
|
@@ -128,6 +128,7 @@ type
|
|||||||
procedure WriteBorderList(AStream: TStream);
|
procedure WriteBorderList(AStream: TStream);
|
||||||
procedure WriteCols(AStream: TStream; AWorksheet: TsWorksheet);
|
procedure WriteCols(AStream: TStream; AWorksheet: TsWorksheet);
|
||||||
procedure WriteComments(AWorksheet: TsWorksheet);
|
procedure WriteComments(AWorksheet: TsWorksheet);
|
||||||
|
procedure WriteDefinedNames(AStream: TStream);
|
||||||
procedure WriteDimension(AStream: TStream; AWorksheet: TsWorksheet);
|
procedure WriteDimension(AStream: TStream; AWorksheet: TsWorksheet);
|
||||||
procedure WriteFillList(AStream: TStream);
|
procedure WriteFillList(AStream: TStream);
|
||||||
procedure WriteFont(AStream: TStream; AFont: TsFont; UseInStyleNode: Boolean);
|
procedure WriteFont(AStream: TStream; AFont: TsFont; UseInStyleNode: Boolean);
|
||||||
@@ -251,6 +252,7 @@ const
|
|||||||
{%H-}MIME_XML = 'application/xml';
|
{%H-}MIME_XML = 'application/xml';
|
||||||
MIME_RELS = 'application/vnd.openxmlformats-package.relationships+xml';
|
MIME_RELS = 'application/vnd.openxmlformats-package.relationships+xml';
|
||||||
MIME_OFFICEDOCUMENT = 'application/vnd.openxmlformats-officedocument';
|
MIME_OFFICEDOCUMENT = 'application/vnd.openxmlformats-officedocument';
|
||||||
|
MIME_CORE = 'application/vnd.openxmlformats-package.core-properties+xml';
|
||||||
MIME_SPREADML = MIME_OFFICEDOCUMENT + '.spreadsheetml';
|
MIME_SPREADML = MIME_OFFICEDOCUMENT + '.spreadsheetml';
|
||||||
MIME_SHEET = MIME_SPREADML + '.sheet.main+xml';
|
MIME_SHEET = MIME_SPREADML + '.sheet.main+xml';
|
||||||
MIME_WORKSHEET = MIME_SPREADML + '.worksheet+xml';
|
MIME_WORKSHEET = MIME_SPREADML + '.worksheet+xml';
|
||||||
@@ -3349,6 +3351,7 @@ begin
|
|||||||
'<bookViews>' +
|
'<bookViews>' +
|
||||||
'<workbookView xWindow="480" yWindow="90" windowWidth="15195" windowHeight="12525" ' + actTab + '/>' +
|
'<workbookView xWindow="480" yWindow="90" windowWidth="15195" windowHeight="12525" ' + actTab + '/>' +
|
||||||
'</bookViews>');
|
'</bookViews>');
|
||||||
|
|
||||||
AppendToStream(FSWorkbook,
|
AppendToStream(FSWorkbook,
|
||||||
'<sheets>');
|
'<sheets>');
|
||||||
for counter:=1 to Workbook.GetWorksheetCount do
|
for counter:=1 to Workbook.GetWorksheetCount do
|
||||||
@@ -3357,6 +3360,9 @@ begin
|
|||||||
[Workbook.GetWorksheetByIndex(counter-1).Name, counter, counter]));
|
[Workbook.GetWorksheetByIndex(counter-1).Name, counter, counter]));
|
||||||
AppendToStream(FSWorkbook,
|
AppendToStream(FSWorkbook,
|
||||||
'</sheets>');
|
'</sheets>');
|
||||||
|
|
||||||
|
WriteDefinedNames(FSWorkbook);
|
||||||
|
|
||||||
AppendToStream(FSWorkbook,
|
AppendToStream(FSWorkbook,
|
||||||
'<calcPr calcId="114210" />');
|
'<calcPr calcId="114210" />');
|
||||||
AppendToStream(FSWorkbook,
|
AppendToStream(FSWorkbook,
|
||||||
@@ -3421,10 +3427,81 @@ begin
|
|||||||
'<Override PartName="/xl/styles.xml" ContentType="' + MIME_STYLES + '" />');
|
'<Override PartName="/xl/styles.xml" ContentType="' + MIME_STYLES + '" />');
|
||||||
AppendToStream(FSContentTypes,
|
AppendToStream(FSContentTypes,
|
||||||
'<Override PartName="/xl/sharedStrings.xml" ContentType="' + MIME_STRINGS + '" />');
|
'<Override PartName="/xl/sharedStrings.xml" ContentType="' + MIME_STRINGS + '" />');
|
||||||
|
{
|
||||||
|
AppendToStream(FSContentTypes,
|
||||||
|
'<Override PartName="/docProps/core.xml" ContentType="' + MIME_CORE + '" />');
|
||||||
|
}
|
||||||
AppendToStream(FSContentTypes,
|
AppendToStream(FSContentTypes,
|
||||||
'</Types>');
|
'</Types>');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadOOXMLWriter.WriteDefinedNames(AStream: TStream);
|
||||||
|
var
|
||||||
|
sheet: TsWorksheet;
|
||||||
|
stotal, srng: String;
|
||||||
|
i, j: Integer;
|
||||||
|
prng: TsCellRange;
|
||||||
|
firstIndex, lastIndex: Integer;
|
||||||
|
begin
|
||||||
|
stotal := '';
|
||||||
|
|
||||||
|
// Write print ranges and repeatedly printed rows and columns
|
||||||
|
for i := 0 to Workbook.GetWorksheetCount-1 do
|
||||||
|
begin
|
||||||
|
sheet := Workbook.GetWorksheetByIndex(i);
|
||||||
|
|
||||||
|
// Cell block of print range
|
||||||
|
srng := '';
|
||||||
|
for j := 0 to sheet.numPrintRanges - 1 do
|
||||||
|
begin
|
||||||
|
prng := sheet.GetPrintRange(j);
|
||||||
|
// prng.Col2 := Min(prng.Col2, sheet.GetLastColIndex);
|
||||||
|
// prng.Row2 := Min(prng.Row2, sheet.GetLastColIndex);
|
||||||
|
srng := srng + ',' + Format('%s!%s', [
|
||||||
|
sheet.Name, GetCellRangeString(prng.Row1, prng.Col1, prng.Row2, prng.Col2, [])
|
||||||
|
]);
|
||||||
|
end;
|
||||||
|
if srng <> '' then
|
||||||
|
begin
|
||||||
|
Delete(srng, 1, 1);
|
||||||
|
stotal := stotal + Format(
|
||||||
|
'<definedName name="_xlnm.Print_Area" localSheetId="%d">%s</definedName>',
|
||||||
|
[i, srng]
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// repeated columns ...
|
||||||
|
srng := '';
|
||||||
|
if sheet.PageLayout.RepeatedCols.FirstIndex <> UNASSIGNED_ROW_COL_INDEX then
|
||||||
|
begin
|
||||||
|
firstindex := sheet.PageLayout.RepeatedCols.FirstIndex;
|
||||||
|
lastindex := IfThen(sheet.PageLayout.RepeatedCols.LastIndex = UNASSIGNED_ROW_COL_INDEX,
|
||||||
|
firstindex, sheet.PageLayout.RepeatedCols.LastIndex);
|
||||||
|
srng := srng + ',' + Format('%s!$%s:$%s', [sheet.Name, GetColString(firstindex), GetColString(lastindex)]);
|
||||||
|
end;
|
||||||
|
// ... and repeated rows
|
||||||
|
if sheet.PageLayout.RepeatedRows.FirstIndex <> UNASSIGNED_ROW_COL_INDEX then
|
||||||
|
begin
|
||||||
|
firstindex := sheet.PageLayout.RepeatedRows.FirstIndex;
|
||||||
|
lastindex := IfThen(sheet.PageLayout.RepeatedRows.LastIndex = UNASSIGNED_ROW_COL_INDEX,
|
||||||
|
firstindex, sheet.PageLayout.RepeatedRows.LastIndex);
|
||||||
|
srng := srng + ',' + Format('%s!$%d:$%d', [sheet.Name, firstindex+1, lastindex+1]);
|
||||||
|
end;
|
||||||
|
if srng <> '' then begin
|
||||||
|
Delete(srng, 1,1);
|
||||||
|
stotal := stotal + Format(
|
||||||
|
'<definedName name="_xlnm.Print_Titles" localSheetId="%d">%s</definedName>',
|
||||||
|
[i, srng]
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Write to stream if any defined names exist
|
||||||
|
if stotal <> '' then
|
||||||
|
AppendtoStream(FSWorkbook,
|
||||||
|
'<definedNames>' + stotal + '</definedNames>');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOOXMLWriter.WriteWorksheet(AWorksheet: TsWorksheet);
|
procedure TsSpreadOOXMLWriter.WriteWorksheet(AWorksheet: TsWorksheet);
|
||||||
begin
|
begin
|
||||||
FCurSheetNum := Length(FSSheets);
|
FCurSheetNum := Length(FSSheets);
|
||||||
|
Reference in New Issue
Block a user