lazarus-ccr/components/fpspreadsheet/source/common/fpspagelayout.pas

739 lines
26 KiB
ObjectPascal

unit fpsPageLayout;
{$mode objfpc}{$H+}
interface
uses
Classes, 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: TsHeaderFooterImages;
FFooterImages: TsHeaderFooterImages;
FRepeatedCols: TsRowColRange;
FRepeatedRows: TsRowColRange;
FPrintRanges: TsCellRangeArray;
function GetFooterImages(ASection: TsHeaderFooterSectionIndex): TsHeaderFooterImage;
function GetFooters(AIndex: Integer): String;
function GetHeaderImages(ASection: TsHeaderFooterSectionIndex): 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);
function HasFooter: Boolean;
function HasHeader: Boolean;
{ Images embedded in header and/or footer }
function AddHeaderImage(AHeaderIndex: Integer; ASection: TsHeaderFooterSectionIndex;
const AFilename: String): Integer; overload;
function AddHeaderImage(AHeaderIndex: Integer; ASection: TsHeaderFooterSectionIndex;
AStream: TStream): Integer; overload;
procedure AddHeaderImage(AHeaderIndex: Integer; ASection: TsHeaderFooterSectionIndex;
AImageIndex: Integer); overload;
function AddFooterImage(AFooterIndex: Integer; ASection: TsHeaderFooterSectionIndex;
const AFilename: String): Integer; overload;
function AddFooterImage(AFooterIndex: integer; ASection: TsHeaderFooterSectionIndex;
AStream: TStream): Integer; overload;
procedure AddFooterImage(AFooterIndex: Integer;
ASection: TsHeaderFooterSectionIndex; AImageIndex: Integer); overload;
function JoinHeaderFooterText(const ALeft, ACenter, ARight: String): String;
procedure SplitHeaderFooterText(const AText: String; out ALeft, ACenter, ARight: String);
procedure GetImageSections(out AHeaderTags, AFooterTags: String);
function HasHeaderFooterImages: Boolean;
{ 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 (filename 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: TsHeaderFooterSectionIndex]: TsHeaderFooterImage
read GetFooterImages;
{@@ Images inserted into header }
property HeaderImages[ASection: TsHeaderFooterSectionIndex]: TsHeaderFooterImage
read GetHeaderImages;
end;
implementation
uses
Math,
fpsUtils, fpsHeaderFooterParser, fpSpreadsheet;
constructor TsPageLayout.Create(AWorksheet: Pointer);
var
sec: TsHeaderFooterSectionIndex;
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 sec in TsHeaderFooterSectionIndex do
begin
InitHeaderFooterImageRecord(FHeaderImages[sec]);
InitHeaderFooterImageRecord(FFooterImages[sec]);
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;
sec: TsHeaderFooterSectionIndex;
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 sec in TsHeaderFooterSectionIndex do
begin
FHeaderImages[sec] := ASource.HeaderImages[sec];
FFooterImages[sec] := ASource.FooterImages[sec];
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;
{@@ ----------------------------------------------------------------------------
Adds an image to the header.
@param AHeaderIndex 0 = header of first page, 1 = header of odd pages,
2 = header of even pages
@param ASection Specifies whether the image is inserted in the left
(hfsLeft), center (hfsCenter) or right (hfsRight) part
of the header.
@param AFileName Name of the file containing the image
@return Index of the image data in the workbook's EmbeddedObjList. Useful
if the same image will be used in another header or footer.
-------------------------------------------------------------------------------}
function TsPageLayout.AddHeaderImage(AHeaderIndex: Integer;
ASection: TsHeaderFooterSectionIndex; const AFilename: String): Integer;
var
book: TsWorkbook;
begin
if FWorksheet = nil then
raise Exception.Create('[TsPageLayout.AddHeaderImage] Worksheet is nil.');
book := TsWorksheet(FWorksheet).Workbook;
Result := book.FindEmbeddedObj(AFilename);
if Result = -1 then
Result := book.AddEmbeddedObj(AFilename);
if Result > -1 then
AddHeaderImage(AHeaderIndex, ASection, Result);
end;
{@@ ----------------------------------------------------------------------------
Adds an image to the header.
@param AHeaderIndex 0 = header of first page, 1 = header of odd pages,
2 = header of even pages
@param ASection Specifies whether the image is inserted in the left
(hfsLeft), center (hfsCenter) or right (hfsRight) part
of the header.
@param AStream Stream from which the image is read and copied
@return Index of the image data in the workbook's EmbeddedObjList. Useful
if the same image will be used in another header or footer.
-------------------------------------------------------------------------------}
function TsPageLayout.AddHeaderImage(AHeaderIndex: Integer;
ASection: TsHeaderFooterSectionIndex; AStream: TStream): Integer;
var
book: TsWorkbook;
begin
if FWorksheet = nil then
raise Exception.Create('[TsPageLayout.AddHeaderImage] Worksheet is nil.');
book := TsWorksheet(FWorksheet).Workbook;
Result := book.AddEmbeddedObj(AStream);
if Result > -1 then
AddHeaderImage(AHeaderIndex, ASection, Result);
end;
{@@ ----------------------------------------------------------------------------
Adds an image to the header.
@param AHeaderIndex 0 = header of first page, 1 = header of odd pages,
2 = header of even pages
@param ASection Specifies whether the image is inserted in the left
(hfsLeft), center (hfsCenter) or right (hfsRight) part
of the header.
@param AImageIndex Index of the image data into the workbooks EmbeddedObjList
-------------------------------------------------------------------------------}
procedure TsPageLayout.AddHeaderImage(AHeaderIndex: Integer;
ASection: TsHeaderFooterSectionIndex; AImageIndex: Integer);
var
s: Array[TsHeaderFooterSectionIndex] of string;
begin
FHeaderImages[ASection].Index := AImageIndex;
SplitHeaderFooterText(FHeaders[AHeaderIndex], s[hfsLeft], s[hfsCenter], s[hfsRight]);
// Add the symbol &G only once!
if (pos('&G', s[ASection]) < 1) or (pos('&g', s[ASection]) < 1) then begin
s[ASection] := s[ASection] + '&G';
FHeaders[AHeaderIndex] := JoinHeaderFooterText(s[hfsLeft], s[hfsCenter], s[hfsRight]);
end;
end;
{@@ ----------------------------------------------------------------------------
Adds an image to the footer,
@param AFooterIndex 0 = footer of first page, 1 = footer of odd pages,
2 = footer of even pages
@param ASection Specifies whether the image is inserted in the left
(hfsLeft), center (hfsCenter) or right (hfsRight) part
of the footer.
@param AFilename Name of the file containing the image
@return Index of the image data in the workbook's EmbeddedObjList. Useful
if the same image will be used in another header or footer.
-------------------------------------------------------------------------------}
function TsPageLayout.AddFooterImage(AFooterIndex: Integer;
ASection: TsHeaderFooterSectionIndex; const AFileName: String): Integer;
var
book: TsWorkbook;
begin
if FWorksheet = nil then
raise Exception.Create('[TsPageLayout.AddFooterImage] Worksheet is nil.');
book := TsWorksheet(FWorksheet).Workbook;
Result := book.FindEmbeddedObj(AFilename);
if Result = -1 then
Result := book.AddEmbeddedObj(AFilename);
if Result = -1 then // Image not found? Unsupported file format?
exit;
AddFooterImage(AFooterIndex, ASection, Result);
end;
{@@ ----------------------------------------------------------------------------
Adds an image to the footer,
@param AFooterIndex 0 = footer of first page, 1 = footer of odd pages,
2 = footer of even pages
@param ASection Specifies whether the image is inserted in the left
(hfsLeft), center (hfsCenter) or right (hfsRight) part
of the footer.
@param AStream Stream from which the image is copied
@return Index of the image data in the workbook's EmbeddedObjList. Useful
if the same image will be used in another header or footer.
-------------------------------------------------------------------------------}
function TsPageLayout.AddFooterImage(AFooterIndex: Integer;
ASection: TsHeaderFooterSectionIndex; AStream: TStream): Integer;
var
book: TsWorkbook;
begin
if FWorksheet = nil then
raise Exception.Create('[TsPageLayout.AddFooterImage] Worksheet is nil.');
book := TsWorksheet(FWorksheet).Workbook;
Result := book.AddEmbeddedObj(AStream);
if Result > -1 then
AddFooterImage(AFooterIndex, ASection, Result);
end;
{@@ ----------------------------------------------------------------------------
Adds an image to the footer,
@param AFooterIndex 0 = footer of first page, 1 = footer of odd pages,
2 = footer of even pages
@param ASection Specifies whether the image is inserted in the left
(hfsLeft), center (hfsCenter) or right (hfsRight) part
of the footer.
@param AImageIndex Index of the image data into the workbooks EmbeddedObjList
-------------------------------------------------------------------------------}
procedure TsPageLayout.AddFooterImage(AFooterIndex: Integer;
ASection: TsHeaderFooterSectionIndex; AImageIndex: Integer);
var
s: Array[TsHeaderFooterSectionIndex] of string;
begin
FFooterImages[ASection].Index := AImageIndex;
SplitHeaderFooterText(FFooters[AFooterIndex], s[hfsLeft], s[hfsCenter], s[hfsRight]);
// Add the symbol &G only once!
if (pos('&G', s[ASection]) < 1) or (pos('&g', s[ASection]) < 1) then begin
s[ASection] := s[ASection] + '&G';
FFooters[AFooterIndex] := JoinHeaderFooterText(s[hfsLeft], s[hfsCenter], s[hfsRight]);
end;
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: TsHeaderFooterSectionIndex): 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;
{@@ ----------------------------------------------------------------------------
Checks all sections of the headers and footers for images.
Creates a 3-character-string for the header and the footer containing an "L"
at the first position if any of the three header texts contains a "%G" in
the left section.
Dto. for the other sections.
Only one image per section is allowed! Sections violating this are marked by "x"
-------------------------------------------------------------------------------}
procedure TsPageLayout.GetImageSections(out AHeaderTags, AFooterTags: String);
procedure Process(AText: String; var ATags: String);
var
hfp: TsHeaderFooterParser;
begin
hfp := TsHeaderFooterParser.Create(AText); //, booknil, nil);
try
if hfp.IsImageInSection(hfsLeft) then
ATags[1] := IfThen(ATags[1] = ' ', 'L', 'x');
if hfp.IsImageInSection(hfsCenter) then
ATags[2] := IfThen(ATags[2] = ' ', 'C', 'x');
if hfp.IsImageInSection(hfsRight) then
ATags[3] := IfThen(ATags[3] = ' ', 'R', 'x');
finally
hfp.Free;
end;
end;
var
i: Integer;
begin
AHeaderTags := ' ';
for i:=0 to 2 do
Process(FHeaders[i], AHeaderTags);
AFooterTags := ' ';
for i:=0 to 2 do
Process(FFooters[i], AFooterTags);
end;
function TsPageLayout.GetHeaderImages(
ASection: TsHeaderFooterSectionIndex): 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 footer of the worksheet is enabled
-------------------------------------------------------------------------------}
function TsPageLayout.HasFooter: Boolean;
begin
Result := (FFooters[0] <> '') or (FFooters[1] <> '') or (FFooters[2] <> '');
end;
{@@ ----------------------------------------------------------------------------
Checks whether the header of the worksheet is enabled
-------------------------------------------------------------------------------}
function TsPageLayout.HasHeader: Boolean;
begin
Result := (FHeaders[0] <> '') or (FHeaders[1] <> '') or (FHeaders[2] <> '');
end;
{@@ ----------------------------------------------------------------------------
Checks whether the header or footer of the worksheet contains embedded images
-------------------------------------------------------------------------------}
function TsPageLayout.HasHeaderFooterImages: Boolean;
var
sec: TsHeaderFooterSectionIndex;
begin
Result := true;
for sec in TsHeaderFooterSectionIndex do
begin
if FHeaderImages[sec].Index >= 0 then Exit;
if FFooterImages[sec].Index >= 0 then Exit;
end;
Result := false;
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;
{@@ ----------------------------------------------------------------------------
Combines the three strings for the left, center and right header/footer
sections to a valid header/footer string. Inserts "&L", "&C" and "&R" codes.
-------------------------------------------------------------------------------}
function TsPageLayout.JoinHeaderFooterText(
const ALeft, ACenter, ARight: String): String;
begin
Result := '';
if (ALeft = '') and (ARight = '') then
begin
Result := ACenter;
exit;
end;
if (ALeft <> '') then Result := '&L' + ALeft;
if (ACenter <> '') then Result := Result + '&C' + ACenter;
if (ARight <> '') then Result := Result + '&R' + ARight;
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;
procedure TsPageLayout.SplitHeaderFooterText(const AText: String;
out ALeft, ACenter, ARight: String);
var
pL, pC, pR, n: Integer;
P, PStart: PChar;
begin
ALeft := '';
ACenter := '';
ARight := '';
if AText = '' then
exit;
P := PChar(AText);
PStart := P;
pL := 0;
pC := 0;
pR := 0;
while (P^ <> #0) do begin
if P^ = '&' then
begin
inc(P);
if (P^ = 'L') or (P^ = 'l') then
pL := {%H-}PtrUInt(P) - {%H-}PtrUInt(PStart)
else
if (P^ = 'C') or (P^ = 'c') then
pC := {%H-}PtrUInt(P) - {%H-}PtrUInt(PStart)
else
if (P^ = 'R') or (P^ = 'r') then
pR := {%H-}PtrUInt(P) - {%H-}PtrUInt(PStart);
end;
inc(P);
end;
if (pL > 0) then
begin
if pC > 0 then n := pC - pL - 2 else
if pR > 0 then n := pR - pL - 2 else n := MaxInt;
ALeft := Copy(AText, pL+2, n);
end;
if (pC > 0) then
begin
if pR > 0 then n := pR - pC - 2 else n := MaxInt;
ACenter := Copy(AText, pC+2, n);
end;
if (pR > 0) then
ARight := Copy(AText, pR+2, MaxInt);
end;
end.