fpspreadsheet: Move PageLayout to separate unit (fpsPageLayout). Move PrintRanges and RepeatedRows/Cols to PageLayout. Some simplifiations because TsPageLayout is a class now. Prepare for images in header/footer.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4530 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2016-03-04 23:01:21 +00:00
parent e3ee61aec5
commit f1c07951dd
10 changed files with 718 additions and 409 deletions

View File

@@ -42,7 +42,7 @@ uses
fpszipper,
{$ENDIF}
fpstypes, fpspreadsheet, fpsReaderWriter, fpsutils, fpsHeaderFooterParser,
fpsNumFormat, fpsNumFormatParser, fpsxmlcommon;
fpsNumFormat, fpsNumFormatParser, fpsxmlcommon, fpsPagelayout;
type
TDateModeODS=(
@@ -131,7 +131,8 @@ type
procedure ReadAutomaticStyles(AStylesNode: TDOMNode);
procedure ReadMasterStyles(AStylesNode: TDOMNode);
procedure ReadNumFormats(AStylesNode: TDOMNode);
function ReadPageLayout(AStylesNode: TDOMNode; ATableStyleName: String): PsPageLayout;
procedure ReadPageLayout(AStylesNode: TDOMNode; ATableStyleName: String;
APageLayout: TsPageLayout);
procedure ReadSettings(AOfficeSettingsNode: TDOMNode);
procedure ReadStyles(AStylesNode: TDOMNode);
{ Record writing methods }
@@ -356,8 +357,23 @@ type
public
Name: String;
PageLayout: TsPageLayout;
constructor Create;
destructor Destroy; override;
end;
constructor TPageLayoutData.Create;
begin
inherited;
PageLayout := TsPageLayout.Create(nil);
end;
destructor TPageLayoutData.destroy;
begin
PageLayout.Free;
inherited;
end;
type
{ MasterPage items stored in MasterPageList }
TMasterPageData = class
public
@@ -404,6 +420,7 @@ type
StyleName: String;
end;
{******************************************************************************}
{ TsSpreadOpenDocHeaderFooterParser }
{******************************************************************************}
@@ -1278,6 +1295,7 @@ var
fntSize: Double;
fntStyle: TsHeaderFooterFontStyles;
fntColor: TsColor;
n: Integer;
begin
if not Assigned(AStylesNode) then
exit;
@@ -1309,7 +1327,6 @@ begin
begin
// Read page layout parameters
data := TPageLayoutData.Create;
InitPageLayout(data.PageLayout);
data.Name := GetAttrValue(layoutNode, 'style:name');
node := layoutNode.FirstChild;
@@ -1355,51 +1372,52 @@ begin
begin
if s[Length(s)] = '%' then Delete(s, Length(s), 1);
data.PageLayout.ScalingFactor := round(StrToFloat(s, FPointSeparatorSettings));
Exclude(data.PageLayout.Options, poFitPages);
with data.PageLayout do Options := Options - [poFitPages];
end;
s := GetAttrValue(node, 'style:scale-to-X');
if s <> '' then
begin
data.PageLayout.FitWidthToPages := StrToInt(s);
Include(data.PageLayout.Options, poFitPages);
with data.PageLayout do Options := Options + [poFitPages];
end;
s := GetAttrValue(node, 'style:scale-to-Y');
if s <> '' then
begin
data.PageLayout.FitHeightToPages := StrToInt(s);
Include(data.PageLayout.Options, poFitPages);
with data.PageLayout do Options := Options + [poFitPages];
end;
s := GetAttrValue(node, 'style:table-centering');
case s of
'both':
data.PageLayout.Options := data.PageLayout.Options + [poHorCentered, poVertCentered];
with data.PageLayout do Options := Options + [poHorCentered, poVertCentered];
'horizontal':
data.PageLayout.Options := data.PageLayout.Options + [poHorCentered] - [poVertCentered];
with data.PageLayout do Options := Options + [poHorCentered] - [poVertCentered];
'vertical':
data.PageLayout.Options := data.PageLayout.Options - [poHorCentered] + [poVertCentered];
with data.PageLayout do Options := Options - [poHorCentered] + [poVertCentered];
end;
s := GetAttrValue(node, 'style:print');
if pos('grid', s) > 0 then
Include(data.PageLayout.Options, poPrintGridLines);
with data.PageLayout do Options := Options + [poPrintGridLines];
if pos('headers', s) > 0 then
Include(data.PageLayout.Options, poPrintHeaders);
with data.PageLayout do Options := Options + [poPrintHeaders];
if pos('annotations', s) > 0 then
Include(data.PageLayout.Options, poPrintCellComments);
with data.PageLayout do Options := Options + [poPrintCellComments];
s := GetAttrValue(node, 'style:print-page-order');
if s = 'ltr' then // "left-to-right", the other option is "ttb = top-to-bottom"
Include(data.PageLayout.Options, poPrintPagesByRows);
with data.PageLayout do Options := Options + [poPrintPagesByRows];
s := GetAttrValue(node, 'style:first-page-number');
if s = 'continue' then
Exclude(data.PageLayout.Options, poUseStartPageNumber)
with Data.PageLayout do Options := Options - [poUseStartPageNumber]
else
if TryStrToInt(s, data.PageLayout.StartPageNumber) then
Include(data.PageLayout.Options, poUseStartPageNumber);
if TryStrToInt(s, n) then
data.PageLayout.StartPageNumber := n;
// Sets poUseStartPageNumber automatically
FPageLayoutList.Add(data);
end else
@@ -1459,7 +1477,7 @@ var
nodeName: String;
s: String;
data: TMasterPageData;
pagelayout: PsPageLayout;
pagelayout: TsPageLayout;
j: Integer;
begin
@@ -1478,13 +1496,13 @@ begin
for j:=0 to FPageLayoutList.Count-1 do
if TPageLayoutData(FPageLayoutList[j]).Name = s then
begin
pageLayout := @TPageLayoutData(FPageLayoutList[j]).PageLayout;
pageLayout := TPageLayoutData(FPageLayoutList[j]).PageLayout;
break;
end;
if pagelayout = nil then
exit;
data := TMasterPageData.create;
data := TMasterPageData.Create;
data.Name := GetAttrValue(masternode, 'style:name');
data.PageLayoutName := s;
FMasterPageList.Add(data);
@@ -1496,37 +1514,37 @@ begin
begin
s := ReadHeaderFooterText(styleNode);
if s <> '' then
pageLayout^.Headers[HEADER_FOOTER_INDEX_ODD] := s;
pageLayout.Headers[HEADER_FOOTER_INDEX_ODD] := s;
end else
if nodeName = 'style:header-left' then
begin
s := ReadHeaderFooterText(styleNode);
if s <> '' then
begin
pageLayout^.Headers[HEADER_FOOTER_INDEX_EVEN] := s;
Include(pageLayout^.Options, poDifferentOddEven);
pageLayout.Headers[HEADER_FOOTER_INDEX_EVEN] := s;
with pageLayout do Options := Options + [poDifferentOddEven];
end;
s := GetAttrValue(styleNode, 'style:display');
if s = 'false' then
Exclude(pagelayout^.Options, poDifferentOddEven);
with pageLayout do Options := Options - [poDifferentOddEven];
end else
if nodeName = 'style:footer' then
begin
s := ReadHeaderFooterText(styleNode);
if s <> '' then
pageLayout^.Footers[HEADER_FOOTER_INDEX_ODD] := s;
pageLayout.Footers[HEADER_FOOTER_INDEX_ODD] := s;
end else
if nodeName = 'style:footer-left' then
begin
s := ReadHeaderFooterText(styleNode);
if s <> '' then
begin
pageLayout^.Footers[HEADER_FOOTER_INDEX_EVEN] := s;
Include(pageLayout^.Options, poDifferentOddEven);
pageLayout.Footers[HEADER_FOOTER_INDEX_EVEN] := s;
with pageLayout do Options := Options + [poDifferentOddEven];
end;
s := GetAttrValue(styleNode, 'style:display');
if s = 'false' then
Exclude(pagelayout^.Options, poDifferentOddEven);
with pagelayout do Options := Options - [poDifferentOddEven];
end;
styleNode := styleNode.NextSibling;
end;
@@ -2142,7 +2160,6 @@ var
StylesNode: TDOMNode;
OfficeSettingsNode: TDOMNode;
nodename: String;
pageLayout: PsPageLayout;
XMLStream: TStream;
sheet: TsWorksheet;
tablestyleName: String;
@@ -2225,14 +2242,10 @@ begin
// Process each row inside the sheet and process each cell of the row
ReadRowsAndCells(TableNode);
// Read page layout
pageLayout := ReadPageLayout(StylesNode, GetAttrValue(TableNode, 'table:style-name'));
if pageLayout <> nil then
begin
FWorksheet.PageLayout := pagelayout^;
// Repeated cols/rows already have been determined.
FWorksheet.PageLayout.RepeatedRows := FRepeatedRows;
FWorksheet.PageLayout.RepeatedCols := FRepeatedCols;
end;
ReadPageLayout(StylesNode, GetAttrValue(TableNode, 'table:style-name'), FWorksheet.PageLayout);
// Repeated cols/rows already have been determined.
FWorksheet.PageLayout.SetRepeatedRows(FRepeatedRows.FirstIndex, FRepeatedRows.LastIndex);
FWorksheet.PageLayout.SetRepeatedCols(FRepeatedCols.FirstIndex, FRepeatedCols.LastIndex);
// Read print ranges
ReadPrintRanges(TableNode, FWorksheet);
// Apply table style
@@ -2925,8 +2938,8 @@ end;
Then seeks the FMasterPageList for the entry with the determined master page
name. This entry contains the name of the associated PageLayoutData stored in
the PageLayoutList which, finally, contains the requested PageLayout record. }
function TsSpreadOpenDocReader.ReadPageLayout(AStylesNode: TDOMNode;
ATableStyleName: String): PsPageLayout;
procedure TsSpreadOpenDocReader.ReadPageLayout(AStylesNode: TDOMNode;
ATableStyleName: String; APageLayout: TsPageLayout);
var
nodeName, s: String;
node: TDOMNode;
@@ -2935,8 +2948,6 @@ var
pageLayoutData: TPageLayoutData;
i, j: Integer;
begin
Result := nil;
if AStylesNode = nil then
exit;
@@ -2971,7 +2982,7 @@ begin
if pageLayoutData.Name = masterPageData.PageLayoutName then
begin
{ Found: Return a pointer to the PageLayout record stored in the list }
Result := @pageLayoutData.PageLayout;
APageLayout.Assign(pageLayoutData.PageLayout);
exit;
end;
end;
@@ -3057,7 +3068,7 @@ begin
end;
end;
// Add found range to worksheet
ASheet.AddPrintRange(r1, c1, r2, c2);
ASheet.PageLayout.AddPrintRange(r1, c1, r2, c2);
end;
finally
L.Free;
@@ -4804,9 +4815,9 @@ begin
// Cell block of print range
srng := '';
for j := 0 to ASheet.NumPrintRanges - 1 do
for j := 0 to ASheet.PageLayout.NumPrintRanges - 1 do
begin
prng := ASheet.GetPrintRange(j);
prng := ASheet.PageLayout.PrintRange[j];
srng := srng + ';' + Format('[$%s.%s]', [
sheetname, GetCellRangeString(prng.Row1, prng.Col1, prng.Row2, prng.Col2, [])
]);
@@ -5638,7 +5649,7 @@ var
begin
hasHeader := false;
hasFooter := false;
for i:=0 to High(APageLayout.Headers) do
for i:=0 to 2 do
begin
if APageLayout.Headers[i] <> '' then hasHeader := true;
if APageLayout.Footers[i] <> '' then hasFooter := true;
@@ -5742,12 +5753,12 @@ var
srng: String;
sheetName: String;
begin
if ASheet.NumPrintRanges > 0 then
if ASheet.PageLayout.NumPrintRanges > 0 then
begin
srng := '';
for i := 0 to ASheet.NumPrintRanges - 1 do
for i := 0 to ASheet.PageLayout.NumPrintRanges - 1 do
begin
rng := ASheet.GetPrintRange(i);
rng := ASheet.PageLayout.PrintRange[i];
if pos(' ', ASheet.Name) > 0 then
sheetName := '&apos;' + UTF8TextToXMLText(ASheet.Name) + '&apos;' else
sheetname := UTF8TextToXMLText(ASheet.Name);

View File

@@ -0,0 +1,453 @@
unit fpsPageLayout;
interface
uses
SysUtils, fpsTypes;
type
{@@ Class defining parameters for printing by the Office applications }
TsPageLayout = class
private
FWorksheet: pointer;
FOrientation: TsPageOrientation;
FPageWidth: Double;
FPageHeight: Double;
FLeftMargin: Double;
FRightMargin: Double;
FTopMargin: Double;
FBottomMargin: Double;
FHeaderMargin: Double;
FFooterMargin: Double;
FStartPageNumber: Integer;
FScalingFactor: Integer;
FFitWidthToPages: Integer;
FFitHeightToPages: Integer;
FCopies: Integer;
FOptions: TsPrintOptions;
FHeaders: array[0..2] of String;
FFooters: array[0..2] of String;
FHeaderImages: array[TsHeaderFooterSection] of TsHeaderFooterImage;
FFooterImages: array[TsHeaderFooterSection] of TsHeaderFooterImage;
FRepeatedCols: TsRowColRange;
FRepeatedRows: TsRowColRange;
FPrintRanges: TsCellRangeArray;
function GetFooterImages(ASection: TsHeaderFooterSection): TsHeaderFooterImage;
function GetFooters(AIndex: Integer): String;
function GetHeaderImages(ASection: TsHeaderFooterSection): TsHeaderFooterImage;
function GetHeaders(AIndex: Integer): String;
procedure SetFitHeightToPages(AValue: Integer);
procedure SetFitWidthToPages(AValue: Integer);
procedure SetFooters(AIndex: Integer; const AValue: String);
procedure SetHeaders(AIndex: Integer; const AValue: String);
procedure SetScalingFactor(AValue: Integer);
procedure SetStartPageNumber(AValue: Integer);
public
constructor Create(AWorksheet: pointer);
procedure Assign(ASource: TsPageLayout);
{ Images embedded in header and/or footer }
procedure AddHeaderImage(ASection: TsHeaderFooterSection;
const AFilename: String);
procedure AddFooterImage(ASection: TsHeaderFooterSection;
const AFilename: String);
{ Repeated rows and columns }
function HasRepeatedCols: Boolean;
function HasRepeatedRows: Boolean;
procedure SetRepeatedCols(AFirstCol, ALastCol: Cardinal);
procedure SetRepeatedRows(AFirstRow, ALastRow: Cardinal);
{ 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);
{@@ Page orientation, portrait or landscape. Use spoPortrait or spoLandscape}
property Orientation: TsPageOrientation
read FOrientation write FOrientation;
{@@ Page width, in millimeters.
Defined for non-rotated orientation, mostly Portrait }
property PageWidth: Double
read FPageWidth write FPageWidth;
{@@ Page height, in millimeters.
Defined for non-rotated orientation, mostly Portrait }
property PageHeight: Double
read FPageHeight write FPageHeight;
{@@ Left page margin, in millimeters }
property LeftMargin: Double
read FLeftMargin write FLeftMargin;
{@@ Right page margin, in millimeters }
property RightMargin: Double
read FRightMargin write FRightMargin;
{@@ Top page margin, in millimeters }
property TopMargin: Double
read FTopMargin write FTopMargin;
{@@ Bottom page margin, in millimeters }
property BottomMargin: Double
read FBottomMargin write FBottomMargin;
{@@ Margin reserved for the header region, in millimeters }
property HeaderMargin: Double
read FHeaderMargin write FHeaderMargin;
{@@ Margin reserved for the footer region, in millimeters }
property FooterMargin: Double
read FFooterMargin write FFooterMargin;
{@@ Page number to be printed on the first page, default: 1 }
property StartPageNumber: Integer
read FStartPageNumber write SetStartPageNumber;
{@@ Scaling factor of the page, in percent.
PrintOptions must not contain poFitPages (is removed automatically) }
property ScalingFactor: Integer
read FScalingFactor write SetScalingFactor;
{@@ Count of pages scaled such they they fon on a single page height.
0 means: use as many pages as needed.
Options must contain poFitPages (is set automatically) }
property FitHeightToPages: Integer
read FFitHeightToPages write SetFitHeightToPages;
{@@ Count of pages scaled such that they fit on one page width.
0 means: use as many pages as needed.
Options must contain poFitPages (is set automatically) }
property FitWidthToPages: Integer
read FFitWidthToPages write SetFitWidthToPages;
{@@ Number of copies to be printed }
property Copies: Integer
read FCopies write FCopies;
{@@ A variety of options controlling the output - see TsPrintOption }
property Options: TsPrintOptions
read FOptions write FOptions;
{@@ Headers and footers are in Excel syntax:
- left/center/right sections begin with &L / &C / &R
- page number: &P
- page count: &N
- current date: &D
- current time: &T
- sheet name: &A
- file name without path: &F
- file path without file name: &Z
- image: &G (must be provided by "AddHeaderImage" or "AddFooterImage")
- bold/italic/underlining/double underlining/strike out/shadowed/
outlined/superscript/subscript on/off:
&B / &I / &U / &E / &S / &H
&O / &X / &Y
There can be three headers/footers, for first ([0]) page and
odd ([1])/even ([2]) page numbers.
This is activated by Options poDifferentOddEven and poDifferentFirst.
Array index 1 contains the strings if these options are not used. }
property Headers[AIndex: Integer]: String
read GetHeaders write SetHeaders;
property Footers[AIndex: Integer]: String
read GetFooters write SetFooters;
{@@ Count of worksheet columns repeated at the left of the printed page }
property RepeatedCols: TsRowColRange
read FRepeatedCols;
{@@ Count of worksheet rows repeated at the top of the printed page }
property RepeatedRows: TsRowColRange
read FRepeatedRows;
{@@ TsCellRange record of the print range with the specified index. }
property PrintRange[AIndex: Integer]: TsCellRange
read GetPrintRange;
{@@ Images inserted into footer }
property FooterImages[ASection: TsHeaderFooterSection]: TsHeaderFooterImage
read GetFooterImages;
{@@ Images inserted into header }
property HeaderImages[ASection: TsHeaderFooterSection]: TsHeaderFooterImage
read GetHeaderImages;
end;
implementation
uses
Math,
fpsUtils, fpSpreadsheet;
constructor TsPageLayout.Create(AWorksheet: Pointer);
var
hfs: TsHeaderFooterSection;
i: Integer;
begin
inherited Create;
FWorksheet := AWorksheet;
FOrientation := spoPortrait;
FPageWidth := 210;
FPageHeight := 297;
FLeftMargin := InToMM(0.7);
FRightMargin := InToMM(0.7);
FTopMargin := InToMM(0.78740157499999996);
FBottomMargin := InToMM(0.78740157499999996);
FHeaderMargin := InToMM(0.3);
FFooterMargin := InToMM(0.3);
FStartPageNumber := 1;
FScalingFactor := 100; // Percent
FFitWidthToPages := 0; // use as many pages as needed
FFitHeightToPages := 0;
FCopies := 1;
FOptions := [];
for i:=0 to 2 do FHeaders[i] := '';
for i:=0 to 2 do FFooters[i] := '';
for hfs in TsHeaderFooterSection do
begin
InitHeaderFooterImageRecord(FHeaderImages[hfs]);
InitHeaderFooterImageRecord(FFooterImages[hfs]);
end;
FRepeatedRows.FirstIndex := UNASSIGNED_ROW_COL_INDEX;
FRepeatedRows.LastIndex := UNASSIGNED_ROW_COL_INDEX;
FRepeatedCols.FirstIndex := UNASSIGNED_ROW_COL_INDEX;
FRepeatedCols.LastIndex := UNASSIGNED_ROW_COL_INDEX;
end;
{@@ Copies the data from the provided PageLayout ASource }
procedure TsPageLayout.Assign(ASource: TsPageLayout);
var
i: Integer;
hfs: TsHeaderFooterSection;
begin
FOrientation := ASource.Orientation;
FPageWidth := ASource.PageWidth;
FPageHeight := ASource.PageHeight;
FLeftMargin := ASource.LeftMargin;
FRightMargin := ASource.RightMargin;
FTopMargin := ASource.TopMargin;
FBottomMargin := ASource.BottomMargin;
FHeaderMargin := ASource.HeaderMargin;
FFooterMargin := ASource.FooterMargin;
FStartPageNumber := ASource.StartPageNumber;
FScalingFactor := ASource.ScalingFactor;
FFitWidthToPages := ASource.FitWidthToPages;
FFitHeightToPages := ASource.FitHeightToPages;
FCopies := ASource.Copies;
FOptions := ASource.Options;
for i:=0 to 2 do
begin
FHeaders[i] := ASource.Headers[i];
FFooters[i] := ASource.Footers[i];
end;
for hfs in TsHeaderFooterSection do
begin
FHeaderImages[hfs] := ASource.HeaderImages[hfs];
FFooterImages[hfs] := ASource.FooterImages[hfs];
end;
FRepeatedCols := ASource.RepeatedCols;
FRepeatedRows := ASource.RepeatedRows;
SetLength(FPrintRanges, Length(ASource.FPrintRanges));
for i:=0 to High(FPrintRanges) do
FPrintranges[i] := ASource.FPrintRanges[i];
end;
procedure TsPageLayout.AddHeaderImage(ASection: TsHeaderFooterSection;
const AFilename: String);
var
book: TsWorkbook;
idx: Integer;
begin
book := TsWorksheet(FWorksheet).Workbook;
idx := book.FindEmbeddedStream(AFilename);
if idx = -1 then
idx := book.AddEmbeddedStream(AFilename);
FHeaderImages[ASection].Index := idx;
end;
procedure TsPageLayout.AddFooterImage(ASection: TsHeaderFooterSection;
const AFileName: String);
var
book: TsWorkbook;
idx: Integer;
begin
book := TsWorksheet(FWorksheet).Workbook;
idx := book.FindEmbeddedStream(AFilename);
if idx = -1 then
idx := book.AddEmbeddedStream(AFilename);
FFooterImages[ASection].Index := idx;
end;
{@@ ----------------------------------------------------------------------------
Adds a print range defined by the row/column indexes of its corner cells.
-------------------------------------------------------------------------------}
function TsPageLayout.AddPrintRange(ARow1, ACol1, ARow2, ACol2: Cardinal): Integer;
begin
Result := Length(FPrintRanges);
SetLength(FPrintRanges, Result + 1);
with FPrintRanges[Result] do
begin
if ARow1 < ARow2 then
begin
Row1 := ARow1;
Row2 := ARow2;
end else
begin
Row1 := ARow2;
Row2 := ARow1;
end;
if ACol1 < ACol2 then
begin
Col1 := ACol1;
Col2 := ACol2;
end else
begin
Col1 := ACol2;
Col2 := ACol1;
end;
end;
end;
{@@ ----------------------------------------------------------------------------
Adds a print range defined by a TsCellRange record
-------------------------------------------------------------------------------}
function TsPageLayout.AddPrintRange(const ARange: TsCellRange): Integer;
begin
Result := AddPrintRange(ARange.Row1, ARange.Col1, ARange.Row2, ARange.Col2);
end;
function TsPageLayout.GetFooterImages(
ASection: TsHeaderFooterSection): TsHeaderFooterImage;
begin
Result := FFooterImages[ASection];
end;
function TsPageLayout.GetFooters(AIndex: Integer): String;
begin
if InRange(AIndex, 0, High(FFooters)) then
Result := FFooters[AIndex]
else
raise Exception.Create('[TsPageLayout.GetFooters] Illegal index.');
end;
function TsPageLayout.GetHeaderImages(
ASection: TsHeaderFooterSection): TsHeaderFooterImage;
begin
Result := FHeaderImages[ASection];
end;
function TsPageLayout.GetHeaders(AIndex: Integer): String;
begin
if InRange(AIndex, 0, High(FHeaders)) then
Result := FHeaders[AIndex]
else
raise Exception.Create('[TsPageLayout.GetHeaders] Illegal index.');
end;
{@@ ----------------------------------------------------------------------------
Returns the TsCellRange record of the print range with the specified index.
-------------------------------------------------------------------------------}
function TsPageLayout.GetPrintRange(AIndex: Integer): TsCellRange;
begin
if InRange(AIndex, 0, High(FPrintRanges)) then
Result := FPrintRanges[AIndex]
else
raise Exception.Create('[TsPageLayout.GetPrintRange] Illegal index.');
end;
{@@ ----------------------------------------------------------------------------
Checks whether the worksheet defines columns to be printed repeatedly at the
left of each printed page
-------------------------------------------------------------------------------}
function TsPageLayout.HasRepeatedCols: Boolean;
begin
Result := Cardinal(FRepeatedCols.FirstIndex) <> Cardinal(UNASSIGNED_ROW_COL_INDEX);
end;
{@@ ----------------------------------------------------------------------------
Checks whether the worksheet defines rows to be printed repeatedly at the
top of each printed page
-------------------------------------------------------------------------------}
function TsPageLayout.HasRepeatedRows: Boolean;
begin
Result := Cardinal(FRepeatedRows.FirstIndex) <> Cardinal(UNASSIGNED_ROW_COL_INDEX);
end;
{@@ ----------------------------------------------------------------------------
Returns the count of print ranges defined for this worksheet
-------------------------------------------------------------------------------}
function TsPageLayout.NumPrintRanges: Integer;
begin
Result := Length(FPrintRanges);
end;
{@@ ----------------------------------------------------------------------------
Removes the print range specified by the index
-------------------------------------------------------------------------------}
procedure TsPageLayout.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;
procedure TsPageLayout.SetFitHeightToPages(AValue: Integer);
begin
FFitHeightToPages := AValue;
Include(FOptions, poFitPages);
end;
procedure TsPageLayout.SetFitWidthToPages(AValue: Integer);
begin
FFitWidthToPages := AValue;
Include(FOptions, poFitPages);
end;
procedure TsPageLayout.SetFooters(AIndex: Integer; const AValue: String);
begin
FFooters[AIndex] := AValue;
end;
procedure TsPageLayout.SetHeaders(AIndex: Integer; const AValue: String);
begin
FHeaders[AIndex] := AValue;
end;
procedure TsPageLayout.SetRepeatedCols(AFirstCol, ALastCol: Cardinal);
begin
if AFirstCol < ALastCol then
begin
FRepeatedCols.FirstIndex := AFirstCol;
FRepeatedCols.LastIndex := ALastCol;
end else
begin
FRepeatedCols.FirstIndex := ALastCol;
FRepeatedCols.LastIndex := AFirstCol;
end;
end;
procedure TsPageLayout.SetRepeatedRows(AFirstRow, AlastRow: Cardinal);
begin
if AFirstRow < ALastRow then
begin
FRepeatedRows.FirstIndex := AFirstRow;
FRepeatedRows.LastIndex := ALastRow;
end else
begin
FRepeatedRows.FirstIndex := ALastRow;
FRepeatedRows.LastIndex := AFirstRow;
end;
end;
procedure TsPageLayout.SetScalingFactor(AValue: Integer);
begin
FScalingFactor := AValue;
Exclude(FOptions, poFitPages);
end;
procedure TsPageLayout.SetStartPageNumber(AValue: Integer);
begin
FStartPageNumber := AValue;
Include(FOptions, poUseStartPageNumber);
end;
end.

View File

@@ -34,7 +34,7 @@ uses
clocale,
{$endif}{$endif}{$endif}
Classes, SysUtils, fpimage, AVL_Tree, avglvltree, lconvencoding,
fpsTypes, fpsClasses, fpsNumFormat;
fpsTypes, fpsClasses, fpsNumFormat, fpsPageLayout;
type
{ Forward declarations }
@@ -128,7 +128,7 @@ type
FDefaultRowHeight: Single; // in "character heights", i.e. line count
FSortParams: TsSortParams; // Parameters of the current sorting operation
FBiDiMode: TsBiDiMode;
FPrintRanges: TsCellRangeArray;
FPageLayout: TsPageLayout;
FOnChangeCell: TsCellEvent;
FOnChangeFont: TsCellEvent;
FOnCompareCells: TsCellCompareEvent;
@@ -162,9 +162,6 @@ type
procedure ExchangeCells(ARow1, ACol1, ARow2, ACol2: Cardinal);
public
{@@ Page layout parameters for printing }
PageLayout: TsPageLayout;
{ Base methods }
constructor Create;
destructor Destroy; override;
@@ -505,18 +502,6 @@ type
AOffsetX: Integer = 0; AOffsetY: Integer = 0;
AScaleX: Double = 1.0; AScaleY: Double = 1.0): Integer;
{ 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);
function HasRepeatedPrintCols: Boolean;
function HasRepeatedPrintRows: Boolean;
// Notification of changed cells
procedure ChangedCell(ARow, ACol: Cardinal);
procedure ChangedFont(ARow, ACol: Cardinal);
@@ -539,6 +524,8 @@ type
{@@ Name of the sheet. In the popular spreadsheet applications this is
displayed at the tab of the sheet. }
property Name: string read FName write SetName;
{@@ Parameters to be used for printing by the Office applications }
property PageLayout: TsPageLayout read FPageLayout write FPageLayout;
{@@ List of all row records of the worksheet having a non-standard row height }
property Rows: TIndexedAVLTree read FRows;
{@@ Workbook to which the worksheet belongs }
@@ -1028,7 +1015,7 @@ begin
FHyperlinks := TsHyperlinks.Create;
FImages := TFPList.Create;
InitPageLayout(PageLayout);
FPageLayout := TsPageLayout.Create(self);
FDefaultColWidth := 12;
FDefaultRowHeight := 1;
@@ -1038,8 +1025,8 @@ begin
FLastRowIndex := UNASSIGNED_ROW_COL_INDEX;
FLastColIndex := UNASSIGNED_ROW_COL_INDEX;
FActiveCellRow := UNASSIGNED_ROW_COL_INDEX; // Cardinal(-1);
FActiveCellCol := UNASSIGNED_ROW_COL_INDEX; // Cardinal(-1);
FActiveCellRow := UNASSIGNED_ROW_COL_INDEX;
FActiveCellCol := UNASSIGNED_ROW_COL_INDEX;
FOptions := [soShowGridLines, soShowHeaders];
end;
@@ -1056,6 +1043,7 @@ begin
RemoveAllRows;
RemoveAllCols;
FPageLayout.Free;
FCells.Free;
FRows.Free;
FCols.Free;
@@ -3482,121 +3470,6 @@ begin
RemoveImage(i);
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
if ARow1 < ARow2 then
begin
Row1 := ARow1;
Row2 := ARow2;
end else
begin
Row1 := ARow2;
Row2 := ARow1;
end;
if ACol1 < ACol2 then
begin
Col1 := ACol1;
Col2 := ACol2;
end else
begin
Col1 := ACol2;
Col2 := ACol1;
end;
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;
{@@ ----------------------------------------------------------------------------
Determines whether the worksheet defines repeated print header columns
-------------------------------------------------------------------------------}
function TsWorksheet.HasRepeatedPrintCols: Boolean;
begin
Result := Cardinal(PageLayout.RepeatedCols.FirstIndex) <> Cardinal(UNASSIGNED_ROW_COL_INDEX);
end;
{@@ ----------------------------------------------------------------------------
Determines whether the worksheet defines repeated print header rows
-------------------------------------------------------------------------------}
function TsWorksheet.HasRepeatedPrintRows: Boolean;
begin
Result := Cardinal(PageLayout.RepeatedRows.FirstIndex) <> Cardinal(UNASSIGNED_ROW_COL_INDEX);
end;
{@@ ----------------------------------------------------------------------------
Removes the comment from a cell and releases the memory occupied by the node.
-------------------------------------------------------------------------------}

View File

@@ -674,6 +674,20 @@ type
{@@ Pointer to a TCell record }
PCell = ^TCell;
{@@ Embedded image }
TsImage = record
Row, Col: Cardinal;
Index: Integer;
OffsetX, OffsetY: Double; // mm
ScaleX, ScaleY: Double;
end;
PsImage = ^TsImage;
{@@ Image embedded in header or footer}
TsHeaderFooterImage = record
Index: Integer;
end;
{@@ Page orientation for printing }
TsPageOrientation = (spoPortrait, spoLandscape);
@@ -686,48 +700,8 @@ type
{@@ Set of options used by the page layout }
TsPrintOptions = set of TsPrintOption;
{@@ Record defining parameters for printing by the Office applications }
TsPageLayout = record // all lengths in mm
Orientation: TsPageOrientation;
PageWidth: Double; // for "normal" orientation (mostly portrait)
PageHeight: Double;
LeftMargin: Double;
RightMargin: Double;
TopMargin: Double;
BottomMargin: Double;
HeaderMargin: Double;
FooterMargin: Double;
StartPageNumber: Integer;
ScalingFactor: Integer; // in percent
FitWidthToPages: Integer;
FitHeightToPages: Integer;
Copies: Integer;
Options: TsPrintOptions;
{ Headers and footers are in Excel syntax:
- left/center/right sections begin with &L / &C / &R
- page number: &P
- page count: &N
- current date: &D
- current time: &T
- sheet name: &A
- file name without path: &F
- file path without file name: &Z
- bold/italic/underlining/double underlining/strike out/shadowed/
outlined/superscript/subscript on/off:
&B / &I / &U / &E / &S / &H
&O / &X / &Y
There can be three headers/footers, for first ([0]) page and
odd ([1])/even ([2]) page numbers.
This is activated by Options poDifferentOddEven and poDifferentFirst.
Array index 1 contains the strings if these options are not used. }
Headers: array[0..2] of string;
Footers: array[0..2] of string;
RepeatedCols: TsRowColRange;
RepeatedRows: TsRowColRange;
end;
{@@ Pointer to a page layout record }
PsPageLayout = ^TsPageLayout;
{@@ Headers and footers are divided into three parts: left, center and right }
TsHeaderFooterSection = (hfsLeft, hfsCenter, hfsRight);
const
{@@ Indexes to be used for the various headers and footers }
@@ -774,15 +748,6 @@ type
TsStreamParam = (spClipboard, spWindowsClipboardHTML);
TsStreamParams = set of TsStreamParam;
{@@ Embedded image }
TsImage = record
Row, Col: Cardinal;
Index: Integer;
OffsetX, OffsetY: Double; // mm
ScaleX, ScaleY: Double;
end;
PsImage = ^TsImage;
implementation

View File

@@ -163,7 +163,7 @@ procedure InitCell(ARow, ACol: Cardinal; out ACell: TCell); overload;
procedure InitFormatRecord(out AValue: TsCellFormat);
procedure InitImageRecord(out AValue: TsImage; ARow, ACol: Cardinal;
AOffsetX, AOffsetY, AScaleX, AScaleY: Double);
procedure InitPageLayout(out APageLayout: TsPageLayout);
procedure InitHeaderFooterImageRecord(out AImage: TsHeaderFooterImage);
procedure CopyCellValue(AFromCell, AToCell: PCell);
function HasFormula(ACell: PCell): Boolean;
@@ -2091,34 +2091,15 @@ begin
end;
{@@ ----------------------------------------------------------------------------
Initializes the fields of a TsPageLayout record
Initializes the fields of a TsHeaderFooterImage record
-------------------------------------------------------------------------------}
procedure InitPageLayout(out APageLayout: TsPageLayout);
var
i: Integer;
procedure InitHeaderFooterImageRecord(out AImage: TsHeaderFooterImage);
begin
with APageLayout do begin
Orientation := spoPortrait;
PageWidth := 210;
PageHeight := 297;
LeftMargin := InToMM(0.7);
RightMargin := InToMM(0.7);
TopMargin := InToMM(0.78740157499999996);
BottomMargin := InToMM(0.78740157499999996);
HeaderMargin := InToMM(0.3);
FooterMargin := InToMM(0.3);
StartPageNumber := 1;
ScalingFactor := 100; // Percent
FitWidthToPages := 0; // use as many pages as needed
FitHeightToPages := 0;
Copies := 1;
Options := [];
for i:=0 to 2 do Headers[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;
with AImage do
begin
Index := -1;
//ScaleX := 1.0;
//ScaleY := 1.0;
end;
end;

View File

@@ -358,7 +358,7 @@ implementation
uses
typinfo, contnrs, strutils,
fpsutils, fpsHeaderFooterParser;
fpsutils, fpsHeaderFooterParser, fpsPageLayout;
// uriparser, lazfileutils, fpsutils;
const
@@ -402,74 +402,79 @@ var
begin
TempFile := GetTempFileName;
InitPageLayout(sollPageLayout);
with SollPageLayout do
begin
TopMargin := 20;
BottomMargin := 30;
LeftMargin := 21;
RightMargin := 22;
HeaderMargin := 10;
FooterMargin := 11;
case AHeaderFooterMode of
0: ; // header and footer already are empty strings
1: Headers[HEADER_FOOTER_INDEX_ALL] := 'Test header';
2: Footers[HEADER_FOOTER_INDEX_ALL] := 'Test footer';
3: begin
Headers[HEADER_FOOTER_INDEX_ALL] := 'Test header';
Footers[HEADER_FOOTER_INDEX_ALL] := 'Test footer';
end;
end;
end;
MyWorkbook := TsWorkbook.Create;
sollPageLayout := TsPageLayout.Create(nil);
try
col := 0;
for p := 1 to ANumSheets do
with SollPageLayout do
begin
MyWorkSheet:= MyWorkBook.AddWorksheet(PageLayoutSheet+IntToStr(p));
for row := 0 to 9 do
Myworksheet.WriteNumber(row, 0, row+col*100+p*10000 );
MyWorksheet.PageLayout := SollPageLayout;
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
for p := 0 to MyWorkbook.GetWorksheetCount-1 do
begin
MyWorksheet := MyWorkBook.GetWorksheetByIndex(p);
if MyWorksheet=nil then
fail('Error in test code. Failed to get worksheet by index');
actualPageLayout := MyWorksheet.PageLayout;
CheckEquals(sollPageLayout.TopMargin, actualPageLayout.TopMargin, EPS, 'Top margin mismatch, sheet "'+MyWorksheet.Name+'"');
CheckEquals(sollPageLayout.BottomMargin, actualPageLayout.Bottommargin, EPS, 'Bottom margin mismatch, sheet "'+MyWorksheet.Name+'"');
CheckEquals(sollPageLayout.LeftMargin, actualPageLayout.LeftMargin, EPS, 'Left margin mismatch, sheet "'+MyWorksheet.Name+'"');
CheckEquals(sollPageLayout.RightMargin, actualPageLayout.RightMargin, EPS, 'Right margin mismatch, sheet "'+MyWorksheet.Name+'"');
if (AFormat <> sfExcel2) then // No header/footer margin in BIFF2
begin
if AHeaderFooterMode in [1, 3] then
CheckEquals(sollPageLayout.HeaderMargin, actualPageLayout.HeaderMargin, EPS, 'Header margin mismatch, sheet "'+MyWorksheet.Name+'"');
if AHeaderFooterMode in [2, 3] then
CheckEquals(sollPageLayout.FooterMargin, actualPageLayout.FooterMargin, EPS, 'Footer margin mismatch, sheet "'+MyWorksheet.Name+'"');
TopMargin := 20;
BottomMargin := 30;
LeftMargin := 21;
RightMargin := 22;
HeaderMargin := 10;
FooterMargin := 11;
case AHeaderFooterMode of
0: ; // header and footer already are empty strings
1: Headers[HEADER_FOOTER_INDEX_ALL] := 'Test header';
2: Footers[HEADER_FOOTER_INDEX_ALL] := 'Test footer';
3: begin
Headers[HEADER_FOOTER_INDEX_ALL] := 'Test header';
Footers[HEADER_FOOTER_INDEX_ALL] := 'Test footer';
end;
end;
end;
MyWorkbook := TsWorkbook.Create;
try
col := 0;
for p := 1 to ANumSheets do
begin
MyWorkSheet:= MyWorkBook.AddWorksheet(PageLayoutSheet+IntToStr(p));
for row := 0 to 9 do
Myworksheet.WriteNumber(row, 0, row+col*100+p*10000 );
MyWorksheet.PageLayout.Assign(SollPageLayout);
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
for p := 0 to MyWorkbook.GetWorksheetCount-1 do
begin
MyWorksheet := MyWorkBook.GetWorksheetByIndex(p);
if MyWorksheet=nil then
fail('Error in test code. Failed to get worksheet by index');
actualPageLayout := MyWorksheet.PageLayout;
CheckEquals(sollPageLayout.TopMargin, actualPageLayout.TopMargin, EPS, 'Top margin mismatch, sheet "'+MyWorksheet.Name+'"');
CheckEquals(sollPageLayout.BottomMargin, actualPageLayout.Bottommargin, EPS, 'Bottom margin mismatch, sheet "'+MyWorksheet.Name+'"');
CheckEquals(sollPageLayout.LeftMargin, actualPageLayout.LeftMargin, EPS, 'Left margin mismatch, sheet "'+MyWorksheet.Name+'"');
CheckEquals(sollPageLayout.RightMargin, actualPageLayout.RightMargin, EPS, 'Right margin mismatch, sheet "'+MyWorksheet.Name+'"');
if (AFormat <> sfExcel2) then // No header/footer margin in BIFF2
begin
if AHeaderFooterMode in [1, 3] then
CheckEquals(sollPageLayout.HeaderMargin, actualPageLayout.HeaderMargin, EPS, 'Header margin mismatch, sheet "'+MyWorksheet.Name+'"');
if AHeaderFooterMode in [2, 3] then
CheckEquals(sollPageLayout.FooterMargin, actualPageLayout.FooterMargin, EPS, 'Footer margin mismatch, sheet "'+MyWorksheet.Name+'"');
end;
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
SollPageLayout.Free;
end;
end;
{ ------------------------------------------------------------------------------
Main page layout test: it writes a file with a specific page layout and reads it
back. The written pagelayout ("Solllayout") must match the read pagelayout.
back. The written pagelayout ("SollLayout") must match the read pagelayout.
ATestMode:
0 - Landscape page orientation for sheets 0 und 2, sheet 1 is portrait
@@ -539,7 +544,7 @@ begin
SetLength(SollPageLayout, ANumSheets);
for p:=0 to High(SollPageLayout) do
begin
InitPageLayout(sollPageLayout[p]);
sollPageLayout[p] := TsPageLayout.Create(nil);
with SollPageLayout[p] do
begin
case ATestMode of
@@ -557,7 +562,6 @@ begin
begin
if p = 0 then ScalingFactor := 50 else
if p = 1 then ScalingFactor := 200;
Exclude(Options, poFitPages);
end;
3: // Scale width to n pages
begin
@@ -566,7 +570,6 @@ begin
1: FitWidthToPages := 3;
2: FitWidthToPages := 1;
end;
Include(Options, poFitPages);
end;
4: // Scale height to n pages
begin
@@ -575,14 +578,12 @@ begin
1: FitHeightToPages := 3;
2: FitHeightToPages := 1;
end;
Include(Options, poFitPages);
end;
5: // Page number of first pge
begin
Options := Options + [poUseStartPageNumber];
case p of
0: StartPageNumber := 3;
1: Exclude(Options, poUseStartPageNumber);
1: Options := Options - [poUseStartPageNumber];
2: StartPageNumber := 1;
end;
Headers[HEADER_FOOTER_INDEX_ALL] := '&LPage &P of &N';
@@ -652,7 +653,7 @@ begin
for row := 0 to 99 do
for col := 0 to 29 do
Myworksheet.WriteNumber(row, col, (row+1)+(col+1)*100+(p+1)*10000 );
MyWorksheet.PageLayout := SollPageLayout[p];
MyWorksheet.PageLayout.Assign(SollPageLayout[p]);
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
@@ -731,6 +732,9 @@ begin
MyWorkbook.Free;
DeleteFile(TempFile);
end;
for p:=0 to High(SollPageLayout) do
sollPageLayout[p].Free;
end;
{
@@ -764,7 +768,7 @@ begin
sheetname := PageLayoutSheet + IfThen(ASpaceInName, ' ', '') + IntToStr(i);
MyWorksheet := MyWorkbook.AddWorksheet(sheetname);
for j:=1 to ANumRanges do
MyWorksheet.AddPrintRange(SollRanges[j]);
MyWorksheet.PageLayout.AddPrintRange(SollRanges[j]);
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
@@ -779,10 +783,10 @@ begin
for i := 1 to ANumSheets do
begin
MyWorksheet := MyWorkbook.GetWorksheetByIndex(i-1);
CheckEquals(ANumRanges, MyWorksheet.NumPrintRanges, 'Print range count mismatch');
CheckEquals(ANumRanges, MyWorksheet.PageLayout.NumPrintRanges, 'Print range count mismatch');
for j:=1 to ANumRanges do
begin
rng := MyWorksheet.GetPrintRange(j-1);
rng := MyWorksheet.PageLayout.GetPrintRange(j-1);
CheckEquals(SollRanges[j].Row1, rng.Row1, Format('Row1 mismatch at i=%d, j=%d', [i, j]));
CheckEquals(SollRanges[j].Row2, rng.Row2, Format('Row2 mismatch at i=%d, j=%d', [i, j]));
CheckEquals(SollRanges[j].Col1, rng.Col1, Format('Col1 mismatch at i=%d, j=%d', [i, j]));
@@ -815,8 +819,8 @@ begin
for r := 0 to 10 do
for c := 0 to 10 do
MyWorksheet.WriteNumber(r, c, r*100+c);
MyWorksheet.SetRepeatedPrintRows(AFirstRow, ALastRow);
MyWorksheet.SetRepeatedPrintCols(AFirstCol, ALastCol);
MyWorksheet.PageLayout.SetRepeatedRows(AFirstRow, ALastRow);
MyWorksheet.PageLayout.SetRepeatedCols(AFirstCol, ALastCol);
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;

View File

@@ -1368,15 +1368,15 @@ begin
try
case AName of
#06: begin // Print range
for j := 0 to AWorksheet.NumPrintRanges-1 do
for j := 0 to AWorksheet.PageLayout.NumPrintRanges-1 do
begin
rng := AWorksheet.GetPrintRange(j);
rng := AWorksheet.PageLayout.PrintRange[j];
WriteRangeFormula(memstream, rng, AIndexToRef, j+1);
end;
end;
#07: begin
j := 1;
if AWorksheet.HasRepeatedPrintCols then
if AWorksheet.PageLayout.HasRepeatedCols then
begin
rng.Col1 := AWorksheet.PageLayout.RepeatedCols.FirstIndex;
rng.Col2 := AWorksheet.PageLayout.RepeatedCols.LastIndex;
@@ -1386,7 +1386,7 @@ begin
WriteRangeFormula(memstream, rng, AIndexToRef, j);
inc(j);
end;
if AWorksheet.HasRepeatedPrintRows then
if AWorksheet.PageLayout.HasRepeatedRows then
begin
rng.Row1 := AWorksheet.PageLayout.RepeatedRows.FirstIndex;
rng.Row2 := AWorksheet.PageLayout.RepeatedRows.LastIndex;

View File

@@ -2390,15 +2390,15 @@ begin
try
case AName of
#06: begin // Print range
for j := 0 to AWorksheet.NumPrintRanges-1 do
for j := 0 to AWorksheet.PageLayout.NumPrintRanges-1 do
begin
rng := AWorksheet.GetPrintRange(j);
rng := AWorksheet.PageLayout.PrintRange[j];
WriteRangeFormula(memstream, rng, AIndexToRef, j+1);
end;
end;
#07: begin // Print titles
j := 1;
if AWorksheet.HasRepeatedPrintCols then
if AWorksheet.PageLayout.HasRepeatedCols then
begin
rng.Col1 := AWorksheet.PageLayout.RepeatedCols.FirstIndex;
rng.Col2 := AWorksheet.PageLayout.RepeatedCols.LastIndex;
@@ -2408,7 +2408,7 @@ begin
WriteRangeFormula(memstream, rng, AIndexToRef, j);
inc(j);
end;
if AWorksheet.HasRepeatedPrintRows then
if AWorksheet.PageLayout.HasRepeatedRows then
begin
rng.Row1 := AWorksheet.PageLayout.RepeatedRows.FirstIndex;
rng.Row2 := AWorksheet.PageLayout.RepeatedRows.LastIndex;
@@ -2539,13 +2539,15 @@ var
sheet: TsWorksheet;
i: Integer;
n: Word;
writeIt: Boolean;
begin
n := 0;
SetLength(sheets, FWorkbook.GetWorksheetCount);
for i := 0 to FWorkbook.GetWorksheetCount-1 do begin
sheet := FWorkbook.GetWorksheetByIndex(i);
if (sheet.NumPrintRanges > 0) or
sheet.HasRepeatedPrintCols or sheet.HasRepeatedPrintRows then
with sheet.PageLayout do
writeIt := (NumPrintRanges > 0) or HasRepeatedCols or HasRepeatedRows;
if writeIt then
begin
sheets[n] := i;
inc(n);

View File

@@ -627,7 +627,7 @@ uses
AVL_Tree, Math, Variants,
{%H-}fpspatches, fpsStrings, fpsClasses, fpsNumFormat, xlsConst,
//fpsrpn,
fpsExprParser;
fpsExprParser, fpsPageLayout;
const
{ Helper table for rpn formulas:
@@ -1105,7 +1105,7 @@ begin
begin
rng := defName.Ranges;
for i := 0 to High(rng) do
AWorksheet.AddPrintRange(rng[i].Row1, rng[i].Col1, rng[i].Row2, rng[i].Col2);
AWorksheet.PageLayout.AddPrintRange(rng[i].Row1, rng[i].Col1, rng[i].Row2, rng[i].Col2);
end;
end;
@@ -1123,10 +1123,10 @@ begin
for i := 0 to High(rng) do
begin
if (rng[i].Col2 <> Cardinal(-1)) then
AWorksheet.SetRepeatedPrintCols(rng[i].Col1, rng[i].Col2)
AWorksheet.PageLayout.SetRepeatedCols(rng[i].Col1, rng[i].Col2)
else
if (rng[i].Row2 <> Cardinal(-1)) then
AWorksheet.SetRepeatedPrintRows(rng[i].Row1, rng[i].Row2);
AWorksheet.PageLayout.SetRepeatedRows(rng[i].Row1, rng[i].Row2);
end;
end;
end;
@@ -1660,7 +1660,9 @@ var
w: word;
begin
w := WordLEToN(AStream.ReadWord);
if w = 1 then Include(FWorksheet.PageLayout.Options, poHorCentered);
if w = 1 then
with FWorksheet.PageLayout do
Options := Options + [poHorCentered];
end;
{@@ ----------------------------------------------------------------------------
@@ -1679,16 +1681,19 @@ begin
Len := AStream.ReadByte;
SetLength(s, len*SizeOf(ansichar));
AStream.ReadBuffer(s[1], len*SizeOf(ansichar));
if AIsHeader then
with FWorksheet.PageLayout do
begin
FWorksheet.PageLayout.Headers[1] := ConvertEncoding(s, FCodePage, 'utf8');
FWorksheet.PageLayout.Headers[2] := '';
end else
begin
FWorksheet.PageLayout.Footers[1] := ConvertEncoding(s, FCodePage, 'utf8');
FWorksheet.PageLayout.Footers[2] := '';
if AIsHeader then
begin
Headers[1] := ConvertEncoding(s, FCodePage, 'utf8');
Headers[2] := '';
end else
begin
Footers[1] := ConvertEncoding(s, FCodePage, 'utf8');
Footers[2] := '';
end;
Options := Options - [poDifferentOddEven];
end;
Exclude(FWorksheet.PageLayout.Options, poDifferentOddEven);
end;
{@@ ----------------------------------------------------------------------------
@@ -1867,7 +1872,12 @@ procedure TsSpreadBIFFReader.ReadPageSetup(AStream: TStream);
var
w: Word;
dbl: Double = 0.0;
optns: TsPrintOptions;
begin
// Store current pagelayout options, they already can contain the poFitPages
// which gets altered when reading FitWidthToPages and FitHeightToPages
optns := FWorksheet.PageLayout.Options;
// Paper size
w := WordLEToN(AStream.ReadWord);
if (w <= High(PAPER_SIZES)) then
@@ -1893,23 +1903,27 @@ begin
// Option flags
w := WordLEToN(AStream.ReadWord);
if w and $0001 <> 0 then
Include(FWorksheet.pageLayout.Options, poPrintPagesByRows);
if w and $0002 <> 0 then
FWorksheet.PageLayout.Orientation := spoPortrait else
FWorksheet.PageLayout.Orientation := spoLandscape;
if w and $0008 <> 0 then
Include(FWorksheet.PageLayout.Options, poMonochrome);
if w and $0010 <> 0 then
Include(FWorksheet.PageLayout.Options, poDraftQuality);
if w and $0020 <> 0 then
Include(FWorksheet.PageLayout.Options, poPrintCellComments);
if w and $0040 <> 0 then
Include(FWorksheet.PageLayout.Options, poDefaultOrientation);
if w and $0080 <> 0 then
Include(FWorksheet.PageLayout.Options, poUseStartPageNumber);
if w and $0200 <> 0 then
Include(FWorksheet.Pagelayout.Options, poCommentsAtEnd);
with FWorksheet.PageLayout do
begin
Options := optns;
if w and $0001 <> 0 then
Options := Options + [poPrintPagesByRows];
if w and $0002 <> 0 then
Orientation := spoPortrait else
Orientation := spoLandscape;
if w and $0008 <> 0 then
Options := Options + [poMonochrome];
if w and $0010 <> 0 then
Options := Options + [poDraftQuality];
if w and $0020 <> 0 then
Options := Options + [poPrintCellComments];
if w and $0040 <> 0 then
Options := Options + [poDefaultOrientation];
if w and $0080 <> 0 then
Options := Options + [poUseStartPageNumber];
if w and $0200 <> 0 then
Options := Options + [poCommentsAtEnd];
end;
// Print resolution in dpi -- ignoried
w := WordLEToN(AStream.ReadWord);
@@ -1969,7 +1983,8 @@ var
begin
w := WordLEToN(AStream.ReadWord);
if w = 1 then
Include(FWorksheet.PageLayout.Options, poPrintGridLines);
with FWorksheet.PageLayout do
Options := Options + [poPrintGridLines];
end;
{@@ ----------------------------------------------------------------------------
@@ -1981,7 +1996,8 @@ var
begin
w := WordLEToN(AStream.ReadWord);
if w = 1 then
Include(FWorksheet.PageLayout.Options , poPrintHeaders);
with FWorksheet.PageLayout do
Options := Options + [poPrintHeaders];
end;
{@@ ----------------------------------------------------------------------------
@@ -2667,8 +2683,11 @@ var
flags: Word;
begin
flags := WordLEToN(AStream.ReadWord);
if flags and $0100 <> 0 then
Include(FWorksheet.PageLayout.Options, poFitPages);
with FWorksheet.PageLayout do
if flags and $0100 <> 0 then
Options := Options + [poFitPages]
else
Options := Options - [poFitPages];
// The other flags are ignored, so far.
end;
@@ -2706,7 +2725,9 @@ var
w: word;
begin
w := WordLEToN(AStream.ReadWord);
if w = 1 then Include(FWorksheet.PageLayout.Options, poVertCentered);
if w = 1 then
with FWorksheet.PageLayout do
Options := Options + [poVertCentered];
end;
{@@ ----------------------------------------------------------------------------
@@ -3294,12 +3315,12 @@ begin
for i:=0 to FWorkbook.GetWorksheetCount-1 do
begin
sheet := FWorkbook.GetWorksheetByIndex(i);
if (sheet.NumPrintRanges > 0) or
sheet.HasRepeatedPrintCols or sheet.HasRepeatedPrintRows then
if (sheet.PageLayout.NumPrintRanges > 0) or
sheet.PageLayout.HasRepeatedCols or sheet.PageLayout.HasRepeatedRows then
begin
if sheet.NumPrintRanges > 0 then
if sheet.PageLayout.NumPrintRanges > 0 then
WriteDefinedName(AStream, sheet, #6, n);
if sheet.HasRepeatedPrintCols or sheet.HasRepeatedPrintRows then
if sheet.PageLayout.HasRepeatedCols or sheet.PageLayout.HasRepeatedRows then
WriteDefinedName(AStream, sheet, #7, n);
inc(n);
end;
@@ -3351,8 +3372,8 @@ begin
for i := 0 to FWorkbook.GetWorksheetCount-1 do
begin
sheet := FWorkbook.GetWorksheetByIndex(i);
if (sheet.NumPrintRanges > 0) or
sheet.HasRepeatedPrintCols or sheet.HasRepeatedPrintRows then inc(n);
with sheet.PageLayout do
if (NumPrintRanges > 0) or HasRepeatedCols or HasRepeatedRows then inc(n);
end;
if n < 1 then
@@ -3373,12 +3394,14 @@ procedure TsSpreadBIFFWriter.WriteEXTERNSHEET(AStream: TStream);
var
sheet: TsWorksheet;
i: Integer;
writeIt: Boolean;
begin
for i := 0 to FWorkbook.GetWorksheetCount-1 do
begin
sheet := FWorkbook.GetWorksheetByIndex(i);
if (sheet.NumPrintRanges > 0) or
sheet.HasRepeatedPrintCols or sheet.HasRepeatedPrintRows then
with sheet.PageLayout do
writeIt := (NumPrintRanges > 0) or HasRepeatedCols or HasRepeatedRows;
if writeIt then
begin
{ BIFF record header }
WriteBIFFHeader(AStream, INT_EXCEL_ID_EXTERNSHEET, 2 + Length(sheet.Name));

View File

@@ -1110,7 +1110,7 @@ begin
end;
ParseSheetCellString(Copy(s, 1, p-1), sheetname, r1, c1);
ParseSheetCellString(Copy(s, p+1, MaxInt), sheetname, r2, c2);
sheet.AddPrintRange(r1, c1, r2, c2);
sheet.PageLayout.AddPrintRange(r1, c1, r2, c2);
end;
finally
L.Free;
@@ -1138,9 +1138,9 @@ begin
if not ParseCellRowString(copy(s, p+1, MaxInt), r2) then
r2 := UNASSIGNED_ROW_COL_INDEX;
if (r1 <> cardinal(UNASSIGNED_ROW_COL_INDEX)) then
sheet.SetRepeatedPrintRows(r1, r2);
sheet.PageLayout.SetRepeatedRows(r1, r2);
if (c1 <> cardinal(UNASSIGNED_ROW_COL_INDEX)) then
sheet.SetRepeatedPrintCols(c1, c2);
sheet.PageLayout.SetRepeatedCols(c1, c2);
end;
finally
L.Free;
@@ -1385,11 +1385,11 @@ begin
s := GetAttrValue(ANode, 'differentOddEven');
if s = '1' then
Include(AWorksheet.PageLayout.Options, poDifferentOddEven);
with AWorksheet.PageLayout do Options := Options + [poDifferentOddEven];
s := GetAttrValue(ANode, 'differentFirst');
if s = '1' then
Include(AWorksheet.PageLayout.Options, poDifferentFirst);
with AWorksheet.PageLayout do Options := Options + [poDifferentFirst];
node := ANode.FirstChild;
while node <> nil do
@@ -1596,49 +1596,46 @@ begin
// Scaling factor
s := GetAttrValue(ANode, 'scale');
if s <> '' then
begin
AWorksheet.PageLayout.ScalingFactor := StrToInt(s);
Exclude(AWorksheet.PageLayout.Options, poFitPages);
end;
// poFitPages is automatically excluded
// Fit print job to pages
s := GetAttrValue(ANode, 'fitToHeight');
if s <> '' then
begin
AWorksheet.PageLayout.FitHeightToPages := StrToInt(s);
Include(AWorksheet.PageLayout.Options, poFitPages);
end;
// poFitPages is automatically included.
s := GetAttrValue(ANode, 'fitToWidth');
if s <> '' then
begin
AWorksheet.PageLayout.FitWidthToPages := StrToInt(s);
Include(AWorksheet.PageLayout.Options, poFitPages);
end;
// poFitPages is automatially included.
// First page number
s := GetAttrValue(ANode, 'useFirstPageNumber');
if s = '1' then
Include(AWorksheet.PageLayout.Options, poUseStartPageNumber);
s := GetAttrValue(ANode, 'firstPageNumber');
if s <> '' then
AWorksheet.PageLayout.StartPageNumber := StrToInt(s);
s := GetAttrValue(ANode, 'useFirstPageNumber');
with AWorksheet.PageLayout do
if s = '1' then
Options := Options + [poUseStartPageNumber]
else
Options := Options - [poUseStartPageNumber];
// Print order
s := GetAttrValue(ANode, 'pageOrder');
if s = 'overThenDown' then
Include(AWorksheet.PageLayout.Options, poPrintPagesByRows);
with AWorksheet.PageLayout do Options := Options + [poPrintPagesByRows];
// Monochrome
s := GetAttrValue(ANode, 'blackAndWhite');
if s = '1' then
Include(AWorksheet.PageLayout.Options, poMonochrome);
with AWorksheet.PageLayout do Options := Options + [poMonochrome];
// Quality
s := GetAttrValue(ANode, 'draft');
if s = '1' then
Include(AWorksheet.PageLayout.Options, poDraftQuality);
with AWorksheet.PageLayout do Options := Options + [poDraftQuality];
end;
procedure TsSpreadOOXMLReader.ReadPalette(ANode: TDOMNode);
@@ -1700,11 +1697,11 @@ begin
exit;
s := GetAttrValue(ANode, 'headings');
if (s = '1') then
Include(AWorksheet.PageLayout.Options, poPrintHeaders);
with AWorksheet.PageLayout do Options := Options + [poPrintHeaders];
s := GetAttrValue(ANode, 'gridLines');
if (s = '1') then
Include(AWorksheet.PageLayout.Options, poPrintGridLines);
with AWorksheet.PageLayout do Options := Options + [poPrintGridLines];
end;
procedure TsSpreadOOXMLReader.ReadRowHeight(ANode: TDOMNode; AWorksheet: TsWorksheet);
@@ -3759,9 +3756,9 @@ begin
// Cell block of print range
srng := '';
for j := 0 to sheet.numPrintRanges - 1 do
for j := 0 to sheet.PageLayout.NumPrintRanges - 1 do
begin
prng := sheet.GetPrintRange(j);
prng := sheet.PageLayout.GetPrintRange(j);
srng := srng + ',' + Format('%s!%s', [
sheetname, GetCellRangeString(prng.Row1, prng.Col1, prng.Row2, prng.Col2, [])
]);