fpspreadsheet: Add headers and footers to the pagelayout record, implemented for all Excel formats (reading & writing).

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4104 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2015-05-01 15:14:25 +00:00
parent 82117326a4
commit e66caefbe0
9 changed files with 402 additions and 151 deletions

View File

@ -877,6 +877,20 @@ begin
nodeName := node.NodeName; nodeName := node.NodeName;
if nodeName = 'style:page-layout-properties' then if nodeName = 'style:page-layout-properties' then
begin begin
s := GetAttrValue(node, 'style:print-orientation');
if s = 'landscape' then
FPageLayout.Orientation := spoLandscape
else if s = 'portrait' then
FPageLayout.Orientation := spoPortrait;
s := GetAttrValue(node, 'fo:page-width');
if s <> '' then
FPageLayout.PageWidth := PtsToMM(HTMLLengthStrToPts(s));
s := GetAttrValue(node, 'fo:page-height');
if s <> '' then
FPageLayout.PageHeight := PtsToMM(HTMLLengthStrToPts(s));
s := GetAttrValue(node, 'fo:margin-top'); s := GetAttrValue(node, 'fo:margin-top');
if s <> '' then if s <> '' then
FPageLayout.TopMargin := PtsToMM(HTMLLengthStrToPts(s)); FPageLayout.TopMargin := PtsToMM(HTMLLengthStrToPts(s));

View File

@ -2923,6 +2923,19 @@ begin
AStrings.Add (' Start page number=automatic'); AStrings.Add (' Start page number=automatic');
AStrings.Add(Format(' Scaling factor=%.0f%%', [ASheet.PageLayout.ScalingFactor])); AStrings.Add(Format(' Scaling factor=%.0f%%', [ASheet.PageLayout.ScalingFactor]));
AStrings.Add(Format(' Copies=%d', [ASheet.PageLayout.Copies])); AStrings.Add(Format(' Copies=%d', [ASheet.PageLayout.Copies]));
if (ASheet.PageLayout.Options * [poDifferentOddEven, poDifferentFirst] <> []) then
begin
AStrings.Add(Format(' Header (first)=%s', [ASheet.PageLayout.Headers[0]]));
AStrings.Add(Format(' Header (odd)=%s', [ASheet.PageLayout.Headers[1]]));
AStrings.Add(Format(' Header (even)=%s', [ASheet.PageLayout.Headers[2]]));
AStrings.Add(Format(' Footer (first)=%s', [ASheet.PageLayout.Footers[0]]));
AStrings.Add(Format(' Footer (odd)=%s', [ASheet.PageLayout.Footers[1]]));
AStrings.Add(Format(' Footer (even)=%s', [ASheet.PageLayout.Footers[2]]));
end else
begin
AStrings.Add(Format(' Header=%s', [ASheet.PageLayout.Headers[1]]));
AStrings.Add(Format(' Footer=%s', [ASheet.PageLayout.Footers[1]]));
end;
s := ''; s := '';
for po in TsPrintOption do for po in TsPrintOption do
if po in ASheet.PageLayout.Options then s := s + '; ' + GetEnumName(typeInfo(TsPrintOption), ord(po)); if po in ASheet.PageLayout.Options then s := s + '; ' + GetEnumName(typeInfo(TsPrintOption), ord(po));

View File

@ -668,20 +668,12 @@ type
cctError : (ErrorValue: TsErrorValue); cctError : (ErrorValue: TsErrorValue);
end; end;
{
TsPaperSize = (psUndefined, psLetter, psLetterSmall, psTabloid, psLedger,
psLegal, psStatement, psExecutive, psA3, psA4, psA4small, psA5, psB4, psB5,
psFolie, psQuarto, ps10x14, ps11x17, psNote, psEnvelope9, psEnvelope10,
psEnvelope11, psEnvelope12, psEnvelope14, psC, psD, psE, psEnvelopeDL,
psEnvelopeC5, psEnvelopeC3, psEnvelopeC4, psEnvelopeC6, psEnvelopeC6C5,
psB4ISO, psB5ISO, psB6ISO,
}
TsPageOrientation = (spoPortrait, spoLandscape); TsPageOrientation = (spoPortrait, spoLandscape);
TsPrintOption = (poPrintGridLines, poPrintHeaders, poPrintPagesByRows, TsPrintOption = (poPrintGridLines, poPrintHeaders, poPrintPagesByRows,
poMonochrome, poDraftQuality, poPrintCellComments, poDefaultOrientation, poMonochrome, poDraftQuality, poPrintCellComments, poDefaultOrientation,
poUseStartPageNumber, poCommentsAtEnd, poHorCentered, poVertCentered); poUseStartPageNumber, poCommentsAtEnd, poHorCentered, poVertCentered,
poDifferentOddEven, poDifferentFirst);
TsPrintOptions = set of TsPrintOption; TsPrintOptions = set of TsPrintOption;
@ -701,8 +693,35 @@ type
FitHeightToPages: Integer; FitHeightToPages: Integer;
Copies: Integer; Copies: Integer;
Options: TsPrintOptions; 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;
end; end;
const
{@@ Indexes to be used for the various headers and footers }
HEADER_FOOTER_INDEX_FIRST = 0;
HEADER_FOOTER_INDEX_ODD = 1;
HEADER_FOOTER_INDEX_EVEN = 2;
HEADER_FOOTER_INDEX_ODDEVEN = 1;
HEADER_FOOTER_INDEX_ALL = 1;
function BuildFormatStringFromSection(const ASection: TsNumFormatSection): String; function BuildFormatStringFromSection(const ASection: TsNumFormatSection): String;

View File

@ -2408,6 +2408,8 @@ end;
Initializes the fields of a TsPageLayout record Initializes the fields of a TsPageLayout record
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
procedure InitPageLayout(out APageLayout: TsPageLayout); procedure InitPageLayout(out APageLayout: TsPageLayout);
var
i: Integer;
begin begin
with APageLayout do begin with APageLayout do begin
Orientation := spoPortrait; Orientation := spoPortrait;
@ -2425,6 +2427,8 @@ begin
FitHeightToPages := 0; FitHeightToPages := 0;
Copies := 1; Copies := 1;
Options := []; Options := [];
for i:=0 to 2 do Headers[i] := '';
for i:=0 to 2 do Footers[i] := '';
end; end;
end; end;

View File

@ -457,28 +457,30 @@ begin
INT_EXCEL_ID_BLANK : ReadBlank(AStream); INT_EXCEL_ID_BLANK : ReadBlank(AStream);
INT_EXCEL_ID_BOF : ; INT_EXCEL_ID_BOF : ;
INT_EXCEL_ID_BOOLERROR : ReadBool(AStream); INT_EXCEL_ID_BOOLERROR : ReadBool(AStream);
INT_EXCEL_ID_BOTTOMMARGIN: ReadBottomMargin(AStream); INT_EXCEL_ID_BOTTOMMARGIN: ReadMargin(AStream, 3);
INT_EXCEL_ID_CODEPAGE : ReadCodePage(AStream); INT_EXCEL_ID_CODEPAGE : ReadCodePage(AStream);
INT_EXCEL_ID_COLWIDTH : ReadColWidth(AStream); INT_EXCEL_ID_COLWIDTH : ReadColWidth(AStream);
INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream); INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
INT_EXCEL_ID_EOF : BIFF2EOF := True; INT_EXCEL_ID_EOF : BIFF2EOF := True;
INT_EXCEL_ID_FONT : ReadFont(AStream); INT_EXCEL_ID_FONT : ReadFont(AStream);
INT_EXCEL_ID_FONTCOLOR : ReadFontColor(AStream); INT_EXCEL_ID_FONTCOLOR : ReadFontColor(AStream);
INT_EXCEL_ID_FOOTER : ReadHeaderFooter(AStream, false);
INT_EXCEL_ID_FORMAT : ReadFormat(AStream); INT_EXCEL_ID_FORMAT : ReadFormat(AStream);
INT_EXCEL_ID_FORMULA : ReadFormula(AStream); INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
INT_EXCEL_ID_HEADER : ReadHeaderFooter(AStream, true);
INT_EXCEL_ID_INTEGER : ReadInteger(AStream); INT_EXCEL_ID_INTEGER : ReadInteger(AStream);
INT_EXCEL_ID_IXFE : ReadIXFE(AStream); INT_EXCEL_ID_IXFE : ReadIXFE(AStream);
INT_EXCEL_ID_LABEL : ReadLabel(AStream); INT_EXCEL_ID_LABEL : ReadLabel(AStream);
INT_EXCEL_ID_LEFTMARGIN : ReadLeftMargin(AStream); INT_EXCEL_ID_LEFTMARGIN : ReadMargin(AStream, 0);
INT_EXCEL_ID_NOTE : ReadComment(AStream); INT_EXCEL_ID_NOTE : ReadComment(AStream);
INT_EXCEL_ID_NUMBER : ReadNumber(AStream); INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
INT_EXCEL_ID_PANE : ReadPane(AStream); INT_EXCEL_ID_PANE : ReadPane(AStream);
INT_EXCEL_ID_PRINTGRID : ReadPrintGridLines(AStream); INT_EXCEL_ID_PRINTGRID : ReadPrintGridLines(AStream);
INT_EXCEL_ID_PRINTHEADERS: ReadPrintHeaders(AStream); INT_EXCEL_ID_PRINTHEADERS: ReadPrintHeaders(AStream);
INT_EXCEL_ID_RIGHTMARGIN : ReadRightMargin(AStream); INT_EXCEL_ID_RIGHTMARGIN : ReadMargin(AStream, 1);
INT_EXCEL_ID_ROW : ReadRowInfo(AStream); INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
INT_EXCEL_ID_STRING : ReadStringRecord(AStream); INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
INT_EXCEL_ID_TOPMARGIN : ReadTopMargin(AStream); INT_EXCEL_ID_TOPMARGIN : ReadMargin(AStream, 2);
INT_EXCEL_ID_DEFROWHEIGHT: ReadDefRowHeight(AStream); INT_EXCEL_ID_DEFROWHEIGHT: ReadDefRowHeight(AStream);
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream); INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
INT_EXCEL_ID_XF : ReadXF(AStream); INT_EXCEL_ID_XF : ReadXF(AStream);
@ -1241,11 +1243,12 @@ begin
WriteFonts(AStream); WriteFonts(AStream);
// Page settings block // Page settings block
WriteLeftMargin(AStream); WriteHeaderFooter(AStream, true); // true = header
WriteRightMargin(AStream); WriteHeaderFooter(AStream, false); // false = footer
WriteTopMargin(AStream); WriteMargin(AStream, 0); // 0 = left margin
WriteBottomMargin(AStream); WriteMargin(AStream, 1); // 1 = right margin
// WritePageSetup(AStream); // does not exist in BIFF2 WriteMargin(AStream, 2); // 2 = top margin
WriteMargin(AStream, 3); // 3 = bottom margin
WriteFormatCount(AStream); WriteFormatCount(AStream);
WriteNumFormats(AStream); WriteNumFormats(AStream);
@ -1264,7 +1267,7 @@ begin
WriteWindow1(AStream); WriteWindow1(AStream);
// { -- currently not working // { -- currently not working
WriteWindow2(AStream, FWorksheet); WriteWindow2(AStream, FWorksheet);
WritePane(AStream, FWorksheet, false, pane); // false for "is not BIFF5 or BIFF8" WritePane(AStream, FWorksheet, false, pane); // false = "is not BIFF5 or BIFF8"
WriteSelections(AStream, FWorksheet); WriteSelections(AStream, FWorksheet);
//} //}
WriteEOF(AStream); WriteEOF(AStream);

View File

@ -392,14 +392,16 @@ begin
INT_EXCEL_ID_BLANK : ReadBlank(AStream); INT_EXCEL_ID_BLANK : ReadBlank(AStream);
INT_EXCEL_ID_BOF : ; INT_EXCEL_ID_BOF : ;
INT_EXCEL_ID_BOOLERROR : ReadBool(AStream); INT_EXCEL_ID_BOOLERROR : ReadBool(AStream);
INT_EXCEL_ID_BOTTOMMARGIN : ReadBottomMargin(AStream); INT_EXCEL_ID_BOTTOMMARGIN : ReadMargin(AStream, 3);
INT_EXCEL_ID_COLINFO : ReadColInfo(AStream); INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream); INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
INT_EXCEL_ID_EOF : SectionEOF := True; INT_EXCEL_ID_EOF : SectionEOF := True;
INT_EXCEL_ID_FOOTER : ReadHeaderFooter(AStream, false);
INT_EXCEL_ID_FORMULA : ReadFormula(AStream); INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
INT_EXCEL_ID_HEADER : ReadHeaderFooter(AStream, true);
INT_EXCEL_ID_HCENTER : ReadHCENTER(AStream); INT_EXCEL_ID_HCENTER : ReadHCENTER(AStream);
INT_EXCEL_ID_LABEL : ReadLabel(AStream); INT_EXCEL_ID_LABEL : ReadLabel(AStream);
INT_EXCEL_ID_LEFTMARGIN : ReadLeftMargin(AStream); INT_EXCEL_ID_LEFTMARGIN : ReadMargin(AStream, 0);
INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream); INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream);
INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream); INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream);
INT_EXCEL_ID_NOTE : ReadComment(AStream); INT_EXCEL_ID_NOTE : ReadComment(AStream);
@ -408,13 +410,13 @@ begin
INT_EXCEL_ID_PAGESETUP : ReadPageSetup(AStream); INT_EXCEL_ID_PAGESETUP : ReadPageSetup(AStream);
INT_EXCEL_ID_PRINTGRID : ReadPrintGridLines(AStream); INT_EXCEL_ID_PRINTGRID : ReadPrintGridLines(AStream);
INT_EXCEL_ID_PRINTHEADERS : ReadPrintHeaders(AStream); INT_EXCEL_ID_PRINTHEADERS : ReadPrintHeaders(AStream);
INT_EXCEL_ID_RIGHTMARGIN : ReadRightMargin(AStream); INT_EXCEL_ID_RIGHTMARGIN : ReadMargin(AStream, 1);
INT_EXCEL_ID_RK : ReadRKValue(AStream); //(RK) This record represents a cell that contains an RK value (encoded integer or floating-point value). If a floating-point value cannot be encoded to an RK value, a NUMBER record will be written. This record replaces the record INTEGER written in BIFF2. INT_EXCEL_ID_RK : ReadRKValue(AStream); //(RK) This record represents a cell that contains an RK value (encoded integer or floating-point value). If a floating-point value cannot be encoded to an RK value, a NUMBER record will be written. This record replaces the record INTEGER written in BIFF2.
INT_EXCEL_ID_ROW : ReadRowInfo(AStream); INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
INT_EXCEL_ID_RSTRING : ReadRichString(AStream); //(RSTRING) This record stores a formatted text cell (Rich-Text). In BIFF8 it is usually replaced by the LABELSST record. Excel still uses this record, if it copies formatted text cells to the clipboard. INT_EXCEL_ID_RSTRING : ReadRichString(AStream); //(RSTRING) This record stores a formatted text cell (Rich-Text). In BIFF8 it is usually replaced by the LABELSST record. Excel still uses this record, if it copies formatted text cells to the clipboard.
INT_EXCEL_ID_SHAREDFMLA : ReadSharedFormula(AStream); INT_EXCEL_ID_SHAREDFMLA : ReadSharedFormula(AStream);
INT_EXCEL_ID_STANDARDWIDTH : ReadStandardWidth(AStream, FWorksheet); INT_EXCEL_ID_STANDARDWIDTH : ReadStandardWidth(AStream, FWorksheet);
INT_EXCEL_ID_TOPMARGIN : ReadTopMargin(AStream); INT_EXCEL_ID_TOPMARGIN : ReadMargin(AStream, 2);
INT_EXCEL_ID_STRING : ReadStringRecord(AStream); INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
INT_EXCEL_ID_VCENTER : ReadVCENTER(AStream); INT_EXCEL_ID_VCENTER : ReadVCENTER(AStream);
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream); INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
@ -1044,12 +1046,14 @@ begin
WritePrintGridLines(AStream); WritePrintGridLines(AStream);
// Page settings block // Page settings block
WriteHeaderFooter(AStream, true);
WriteHeaderFooter(AStream, false);
WriteHCenter(AStream); WriteHCenter(AStream);
WriteVCenter(AStream); WriteVCenter(AStream);
WriteLeftMargin(AStream); WriteMargin(AStream, 0); // 0 = left margin
WriteRightMargin(AStream); WriteMargin(AStream, 1); // 1 = right margin
WriteTopMargin(AStream); WriteMargin(AStream, 2); // 2 = top margin
WriteBottomMargin(AStream); WriteMargin(AStream, 3); // 3 = bottom margin
WritePageSetup(AStream); WritePageSetup(AStream);
WriteColInfos(AStream, FWorksheet); WriteColInfos(AStream, FWorksheet);

View File

@ -87,6 +87,7 @@ type
procedure ReadCONTINUE(const AStream: TStream); procedure ReadCONTINUE(const AStream: TStream);
procedure ReadFONT(const AStream: TStream); procedure ReadFONT(const AStream: TStream);
procedure ReadFORMAT(AStream: TStream); override; procedure ReadFORMAT(AStream: TStream); override;
procedure ReadHeaderFooter(AStream: TStream; AIsHeader: Boolean); override;
procedure ReadHyperLink(AStream: TStream); procedure ReadHyperLink(AStream: TStream);
procedure ReadHyperlinkToolTip(AStream: TStream); procedure ReadHyperlinkToolTip(AStream: TStream);
procedure ReadLABEL(AStream: TStream); override; procedure ReadLABEL(AStream: TStream); override;
@ -130,12 +131,13 @@ type
procedure WriteEOF(AStream: TStream); procedure WriteEOF(AStream: TStream);
procedure WriteFont(AStream: TStream; AFont: TsFont); procedure WriteFont(AStream: TStream; AFont: TsFont);
procedure WriteFonts(AStream: TStream); procedure WriteFonts(AStream: TStream);
procedure WriteIndex(AStream: TStream); procedure WriteHeaderFooter(AStream: TStream; AIsHeader: Boolean); override;
procedure WriteHyperlink(AStream: TStream; AHyperlink: PsHyperlink; procedure WriteHyperlink(AStream: TStream; AHyperlink: PsHyperlink;
AWorksheet: TsWorksheet); AWorksheet: TsWorksheet);
procedure WriteHyperlinks(AStream: TStream; AWorksheet: TsWorksheet); procedure WriteHyperlinks(AStream: TStream; AWorksheet: TsWorksheet);
procedure WriteHyperlinkToolTip(AStream: TStream; const ARow, ACol: Cardinal; procedure WriteHyperlinkToolTip(AStream: TStream; const ARow, ACol: Cardinal;
const ATooltip: String); const ATooltip: String);
procedure WriteIndex(AStream: TStream);
procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal; procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal;
const AValue: string; ACell: PCell); override; const AValue: string; ACell: PCell); override;
procedure WriteMergedCells(AStream: TStream; AWorksheet: TsWorksheet); procedure WriteMergedCells(AStream: TStream; AWorksheet: TsWorksheet);
@ -679,18 +681,20 @@ begin
INT_EXCEL_ID_BLANK : ReadBlank(AStream); INT_EXCEL_ID_BLANK : ReadBlank(AStream);
INT_EXCEL_ID_BOF : ; INT_EXCEL_ID_BOF : ;
INT_EXCEL_ID_BOOLERROR : ReadBool(AStream); INT_EXCEL_ID_BOOLERROR : ReadBool(AStream);
INT_EXCEL_ID_BOTTOMMARGIN : ReadBottomMargin(AStream); INT_EXCEL_ID_BOTTOMMARGIN : ReadMargin(AStream, 3);
INT_EXCEL_ID_COLINFO : ReadColInfo(AStream); INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
INT_EXCEL_ID_CONTINUE : ReadCONTINUE(AStream); INT_EXCEL_ID_CONTINUE : ReadCONTINUE(AStream);
INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream); INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
INT_EXCEL_ID_EOF : SectionEOF := True; INT_EXCEL_ID_EOF : SectionEOF := True;
INT_EXCEL_ID_FOOTER : ReadHeaderFooter(AStream, false);
INT_EXCEL_ID_FORMULA : ReadFormula(AStream); INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
INT_EXCEL_ID_HCENTER : ReadHCENTER(AStream); INT_EXCEL_ID_HCENTER : ReadHCENTER(AStream);
INT_EXCEL_ID_HEADER : ReadHeaderFooter(AStream, true);
INT_EXCEL_ID_HLINKTOOLTIP : ReadHyperlinkToolTip(AStream); INT_EXCEL_ID_HLINKTOOLTIP : ReadHyperlinkToolTip(AStream);
INT_EXCEL_ID_HYPERLINK : ReadHyperlink(AStream); INT_EXCEL_ID_HYPERLINK : ReadHyperlink(AStream);
INT_EXCEL_ID_LABEL : ReadLabel(AStream); INT_EXCEL_ID_LABEL : ReadLabel(AStream);
INT_EXCEL_ID_LABELSST : ReadLabelSST(AStream); INT_EXCEL_ID_LABELSST : ReadLabelSST(AStream);
INT_EXCEL_ID_LEFTMARGIN : ReadLeftMargin(AStream); INT_EXCEL_ID_LEFTMARGIN : ReadMargin(AStream, 0);
INT_EXCEL_ID_MERGEDCELLS : ReadMergedCells(AStream); INT_EXCEL_ID_MERGEDCELLS : ReadMergedCells(AStream);
INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream); INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream);
INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream); INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream);
@ -701,7 +705,7 @@ begin
INT_EXCEL_ID_PANE : ReadPane(AStream); INT_EXCEL_ID_PANE : ReadPane(AStream);
INT_EXCEL_ID_PRINTGRID : ReadPrintGridLines(AStream); INT_EXCEL_ID_PRINTGRID : ReadPrintGridLines(AStream);
INT_EXCEL_ID_PRINTHEADERS : ReadPrintHeaders(AStream); INT_EXCEL_ID_PRINTHEADERS : ReadPrintHeaders(AStream);
INT_EXCEL_ID_RIGHTMARGIN : ReadRightMargin(AStream); INT_EXCEL_ID_RIGHTMARGIN : ReadMargin(AStream, 1);
INT_EXCEL_ID_ROW : ReadRowInfo(AStream); INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
//(RSTRING) This record stores a formatted text cell (Rich-Text). //(RSTRING) This record stores a formatted text cell (Rich-Text).
@ -717,7 +721,7 @@ begin
INT_EXCEL_ID_SHAREDFMLA : ReadSharedFormula(AStream); INT_EXCEL_ID_SHAREDFMLA : ReadSharedFormula(AStream);
INT_EXCEL_ID_STRING : ReadStringRecord(AStream); INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
INT_EXCEL_ID_TOPMARGIN : ReadTopMargin(AStream); INT_EXCEL_ID_TOPMARGIN : ReadMargin(AStream, 2);
INT_EXCEL_ID_TXO : ReadTXO(AStream); INT_EXCEL_ID_TXO : ReadTXO(AStream);
INT_EXCEL_ID_VCENTER : ReadVCENTER(AStream); INT_EXCEL_ID_VCENTER : ReadVCENTER(AStream);
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream); INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
@ -1444,6 +1448,30 @@ begin
NumFormatList[fmtIndex] := fmtString; NumFormatList[fmtIndex] := fmtString;
end; end;
{@@ ----------------------------------------------------------------------------
Reads the header/footer to be used for printing.
Overriden for BIFF8 because of wide strings
-------------------------------------------------------------------------------}
procedure TsSpreadBIFF8Reader.ReadHeaderFooter(AStream: TStream;
AIsHeader: Boolean);
var
s: widestring;
len: word;
begin
if RecordSize = 0 then
exit;
len := WordLEToN(AStream.ReadWord);
s := ReadWideString(AStream, len);
if AIsHeader then
FWorksheet.PageLayout.Headers[1] := UTF8Encode(s)
else
FWOrksheet.PageLayout.Footers[1] := UTF8Encode(s);
{ Options poDifferentFirst and poDifferentOddEvent are not used, BIFF supports
only common headers/footers }
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Reads a HYPERLINK record Reads a HYPERLINK record
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
@ -1725,12 +1753,14 @@ begin
//WriteSheetPR(AStream); //WriteSheetPR(AStream);
// Page setting block // Page setting block
WriteHeaderFooter(AStream, true);
WriteHeaderFooter(AStream, false);
WriteHCenter(AStream); WriteHCenter(AStream);
WriteVCenter(AStream); WriteVCenter(AStream);
WriteLeftMargin(AStream); WriteMargin(AStream, 0); // 0 = left margin
WriteRightMargin(AStream); WriteMargin(AStream, 1); // 1 = right margin
WriteTopMargin(AStream); WriteMargin(AStream, 2); // 2 = top margin
WriteBottomMargin(AStream); WriteMargin(AStream, 3); // 3 = bottom margin
WritePageSetup(AStream); WritePageSetup(AStream);
WriteColInfos(AStream, FWorksheet); WriteColInfos(AStream, FWorksheet);
@ -2384,6 +2414,46 @@ begin
{ OBS: It seems to be no problem just ignoring this part of the record } { OBS: It seems to be no problem just ignoring this part of the record }
end; end;
{@@ ----------------------------------------------------------------------------
Writes an Excel 8 HEADER or FOOTER record, depending on AIsHeader.
Overridden because of wide string
-------------------------------------------------------------------------------}
procedure TsSpreadBIFF8Writer.WriteHeaderFooter(AStream: TStream;
AIsHeader: Boolean);
var
wideStr: WideString;
len: Integer;
id: Word;
begin
with FWorksheet.PageLayout do
if AIsHeader then
begin
if (Headers[HEADER_FOOTER_INDEX_ALL] = '') then
exit;
wideStr := UTF8Decode(Headers[HEADER_FOOTER_INDEX_ALL]);
id := INT_EXCEL_ID_HEADER;
end else
begin
if (Footers[HEADER_FOOTER_INDEX_ALL] = '') then
exit;
wideStr := UTF8Decode(Footers[HEADER_FOOTER_INDEX_ALL]);
id := INT_EXCEL_ID_FOOTER;
end;
len := Length(wideStr);
{ BIFF record header }
WriteBiffHeader(AStream, id, 3 + len*sizeOf(wideChar));
{ 16-bit string length }
AStream.WriteWord(WordToLE(len));
{ Widestring flags, 1=regular unicode LE string }
AStream.WriteByte(1);
{ Characters }
AStream.WriteBuffer(WideStringToLE(wideStr)[1], len * SizeOf(WideChar));
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Writes an Excel 8 HYPERLINK record Writes an Excel 8 HYPERLINK record
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}

View File

@ -17,6 +17,8 @@ uses
const const
{ RECORD IDs which didn't change across versions 2-8 } { RECORD IDs which didn't change across versions 2-8 }
INT_EXCEL_ID_EOF = $000A; INT_EXCEL_ID_EOF = $000A;
INT_EXCEL_ID_HEADER = $0014;
INT_EXCEL_ID_FOOTER = $0015;
INT_EXCEL_ID_NOTE = $001C; INT_EXCEL_ID_NOTE = $001C;
INT_EXCEL_ID_SELECTION = $001D; INT_EXCEL_ID_SELECTION = $001D;
INT_EXCEL_ID_DATEMODE = $0022; INT_EXCEL_ID_DATEMODE = $0022;
@ -365,7 +367,6 @@ type
// Read a blank cell // Read a blank cell
procedure ReadBlank(AStream: TStream); override; procedure ReadBlank(AStream: TStream); override;
procedure ReadBool(AStream: TStream); override; procedure ReadBool(AStream: TStream); override;
procedure ReadBottomMargin(AStream: TStream);
procedure ReadCodePage(AStream: TStream); procedure ReadCodePage(AStream: TStream);
// Read column info // Read column info
procedure ReadColInfo(const AStream: TStream); procedure ReadColInfo(const AStream: TStream);
@ -382,7 +383,8 @@ type
// Read FORMULA record // Read FORMULA record
procedure ReadFormula(AStream: TStream); override; procedure ReadFormula(AStream: TStream); override;
procedure ReadHCENTER(AStream: TStream); procedure ReadHCENTER(AStream: TStream);
procedure ReadLeftMargin(AStream: TStream); procedure ReadHeaderFooter(AStream: TStream; AIsHeader: Boolean); virtual;
procedure ReadMargin(AStream: TStream; AMargin: Integer);
// Read multiple blank cells // Read multiple blank cells
procedure ReadMulBlank(AStream: TStream); procedure ReadMulBlank(AStream: TStream);
// Read multiple RK cells // Read multiple RK cells
@ -397,7 +399,6 @@ type
procedure ReadPane(AStream: TStream); procedure ReadPane(AStream: TStream);
procedure ReadPrintGridLines(AStream: TStream); procedure ReadPrintGridLines(AStream: TStream);
procedure ReadPrintHeaders(AStream: TStream); procedure ReadPrintHeaders(AStream: TStream);
procedure ReadRightMargin(AStream: TStream);
// Read an RK value cell // Read an RK value cell
procedure ReadRKValue(AStream: TStream); procedure ReadRKValue(AStream: TStream);
// Read the row, column, and XF index at the current stream position // Read the row, column, and XF index at the current stream position
@ -420,7 +421,6 @@ type
ASharedFormulaBase: PCell = nil): Boolean; ASharedFormulaBase: PCell = nil): Boolean;
function ReadRPNTokenArraySize(AStream: TStream): word; virtual; function ReadRPNTokenArraySize(AStream: TStream): word; virtual;
procedure ReadSharedFormula(AStream: TStream); procedure ReadSharedFormula(AStream: TStream);
procedure ReadTopMargin(AStream: TStream);
// Helper function for reading a string with 8-bit length // Helper function for reading a string with 8-bit length
function ReadString_8bitLen(AStream: TStream): String; virtual; function ReadString_8bitLen(AStream: TStream): String; virtual;
@ -460,8 +460,6 @@ type
// Write out BOOLEAN cell record // Write out BOOLEAN cell record
procedure WriteBool(AStream: TStream; const ARow, ACol: Cardinal; procedure WriteBool(AStream: TStream; const ARow, ACol: Cardinal;
const AValue: Boolean; ACell: PCell); override; const AValue: Boolean; ACell: PCell); override;
// Writes out bottom page margin for printing
procedure WriteBottomMargin(AStream: TStream);
// Writes out used codepage for character encoding // Writes out used codepage for character encoding
procedure WriteCodePage(AStream: TStream; ACodePage: String); virtual; procedure WriteCodePage(AStream: TStream; ACodePage: String); virtual;
// Writes out column info(s) // Writes out column info(s)
@ -481,8 +479,9 @@ type
procedure WriteFormula(AStream: TStream; const ARow, ACol: Cardinal; procedure WriteFormula(AStream: TStream; const ARow, ACol: Cardinal;
ACell: PCell); override; ACell: PCell); override;
procedure WriteHCenter(AStream: TStream); procedure WriteHCenter(AStream: TStream);
// Writes out left page margin for printing procedure WriteHeaderFooter(AStream: TStream; AIsHeader: Boolean); virtual;
procedure WriteLeftMargin(AStream: TStream); // Writes out page margin for printing
procedure WriteMARGIN(AStream: TStream; AMargin: Integer);
// Writes out a FORMAT record // Writes out a FORMAT record
procedure WriteNumFormat(AStream: TStream; ANumFormatStr: String; procedure WriteNumFormat(AStream: TStream; ANumFormatStr: String;
ANumFormatIndex: Integer); virtual; ANumFormatIndex: Integer); virtual;
@ -500,8 +499,6 @@ type
// Writes out whether grid lines are printed // Writes out whether grid lines are printed
procedure WritePrintGridLines(AStream: TStream); procedure WritePrintGridLines(AStream: TStream);
procedure WritePrintHeaders(AStream: TStream); procedure WritePrintHeaders(AStream: TStream);
// Writes out right page margin for printing
procedure WriteRightMargin(AStream: TStream);
// Writes out a ROW record // Writes out a ROW record
procedure WriteRow(AStream: TStream; ASheet: TsWorksheet; procedure WriteRow(AStream: TStream; ASheet: TsWorksheet;
ARowIndex, AFirstColIndex, ALastColIndex: Cardinal; ARow: PRow); virtual; ARowIndex, AFirstColIndex, ALastColIndex: Cardinal; ARow: PRow); virtual;
@ -537,8 +534,6 @@ type
*) *)
procedure WriteSheetPR(AStream: TStream); procedure WriteSheetPR(AStream: TStream);
procedure WriteStringRecord(AStream: TStream; AString: String); virtual; procedure WriteStringRecord(AStream: TStream; AString: String); virtual;
// Writes out the top page margin used when printing
procedure WriteTopMargin(AStream: TStream);
procedure WriteVCenter(AStream: TStream); procedure WriteVCenter(AStream: TStream);
// Writes cell content received by workbook in OnNeedCellData event // Writes cell content received by workbook in OnNeedCellData event
procedure WriteVirtualCells(AStream: TStream); procedure WriteVirtualCells(AStream: TStream);
@ -978,18 +973,6 @@ begin
Workbook.OnReadCellData(Workbook, r, c, cell); Workbook.OnReadCellData(Workbook, r, c, cell);
end; end;
{@@ ----------------------------------------------------------------------------
Reads the bottom page margin of the current worksheet (for printing).
The file value is in inches.
-------------------------------------------------------------------------------}
procedure TsSpreadBIFFReader.ReadBottomMargin(AStream: TStream);
var
dbl: Double;
begin
AStream.ReadBuffer(dbl, SizeOf(dbl));
FWorksheet.PageLayout.BottomMargin := InToMM(dbl);
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Reads the code page used in the xls file Reads the code page used in the xls file
In BIFF8 it seams to always use the UTF-16 codepage In BIFF8 it seams to always use the UTF-16 codepage
@ -1291,17 +1274,50 @@ begin
if w = 1 then Include(FWorksheet.PageLayout.Options, poHorCentered); if w = 1 then Include(FWorksheet.PageLayout.Options, poHorCentered);
end; end;
{@@ ----------------------------------------------------------------------------
Reads the header/footer to be used for printing.
Valid for BIFF2-BIFF5, override for BIFF8
-------------------------------------------------------------------------------}
procedure TsSpreadBIFFReader.ReadHeaderFooter(AStream: TStream;
AIsHeader: Boolean);
var
s: ansistring;
len: Byte;
begin
if RecordSize = 0 then
exit;
Len := AStream.ReadByte;
SetLength(s, len*SizeOf(ansichar));
AStream.ReadBuffer(s[1], len*SizeOf(ansichar));
if AIsHeader then
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] := '';
end;
Exclude(FWorksheet.PageLayout.Options, poDifferentOddEven);
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Reads the left page margin of the current worksheet (for printing). Reads a page margin of the current worksheet (for printing). The margin is
identified by the parameter "AMargin" (0=left, 1=right, 2=top, 3=bottom)
The file value is in inches. The file value is in inches.
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
procedure TsSpreadBIFFReader.ReadLeftMargin(AStream: TStream); procedure TsSpreadBIFFReader.ReadMargin(AStream: TStream; AMargin: Integer);
var var
dbl: Double; dbl: Double;
begin begin
AStream.ReadBuffer(dbl, SizeOf(dbl)); AStream.ReadBuffer(dbl, SizeOf(dbl));
FWorksheet.PageLayout.LeftMargin := InToMM(dbl); case AMargin of
0: FWorksheet.PageLayout.LeftMargin := InToMM(dbl);
1: FWorksheet.PageLayout.RightMargin := InToMM(dbl);
2: FWorksheet.PageLayout.TopMargin := InToMM(dbl);
3: FWorksheet.PageLayout.BottomMargin := InToMM(dbl);
end;
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
@ -1589,18 +1605,6 @@ begin
AXF := WordLEtoN(AStream.ReadWord); AXF := WordLEtoN(AStream.ReadWord);
end; end;
{@@ ----------------------------------------------------------------------------
Reads the right page margin of the current worksheet (for printing).
The file value is in inches.
-------------------------------------------------------------------------------}
procedure TsSpreadBIFFReader.ReadRightMargin(AStream: TStream);
var
dbl: Double;
begin
AStream.ReadBuffer(dbl, SizeOf(dbl));
FWorksheet.PageLayout.RightMargin := InToMM(dbl);
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Reads an RK value cell from the stream Reads an RK value cell from the stream
Valid since BIFF3. Valid since BIFF3.
@ -2064,18 +2068,6 @@ begin
Unused(AStream); Unused(AStream);
end; end;
{@@ ----------------------------------------------------------------------------
Reads the top page margin of the current worksheet (for printing).
The file value is in inches.
-------------------------------------------------------------------------------}
procedure TsSpreadBIFFReader.ReadTopMargin(AStream: TStream);
var
dbl: Double;
begin
AStream.ReadBuffer(dbl, SizeOf(dbl));
FWorksheet.PageLayout.TopMargin := InToMM(dbl);
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Reads whether the page is to be centered vertically for printing Reads whether the page is to be centered vertically for printing
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
@ -2298,21 +2290,6 @@ begin
AStream.WriteBuffer(rec, SizeOf(rec)); AStream.WriteBuffer(rec, SizeOf(rec));
end; end;
{@@ ----------------------------------------------------------------------------
Write the bottom margin of the printed page (in inches)
-------------------------------------------------------------------------------}
procedure TsSpreadBIFFWriter.WriteBottomMargin(AStream: TStream);
var
dbl: double;
begin
{ BIFF record header }
WriteBIFFHeader(AStream, INT_EXCEL_ID_BOTTOMMARGIN, SizeOf(Double));
{ Page margin value, written in inches }
dbl := mmToIn(FWorksheet.PageLayout.BottomMargin);
AStream.WriteBuffer(dbl, SizeOf(dbl));
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Writes the code page identifier defined by the workbook to the stream. Writes the code page identifier defined by the workbook to the stream.
BIFF2 has to be overridden because is uses cp1252, but has a different BIFF2 has to be overridden because is uses cp1252, but has a different
@ -2536,17 +2513,26 @@ begin
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Write the left margin of the printed page (in inches) Writes the a margin record for printing (margin is in inches).
The margin is identified by the parameter AMargin:
0=left, 1=right, 2=top, 3=bottom
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
procedure TsSpreadBIFFWriter.WriteLeftMargin(AStream: TStream); procedure TsSpreadBIFFWriter.WriteMargin(AStream: TStream; AMargin: Integer);
var var
dbl: double; dbl: double;
begin begin
{ BIFF record header } { BIFF record header }
WriteBIFFHeader(AStream, INT_EXCEL_ID_LEFTMARGIN, SizeOf(Double)); WriteBIFFHeader(AStream, INT_EXCEL_ID_LEFTMARGIN + AMargin, SizeOf(Double));
// the MARGIN IDs are consecutive beginning with the one for left margin
{ Page margin value, written in inches } { Page margin value, written in inches }
dbl := mmToIn(FWorksheet.PageLayout.LeftMargin); case AMargin of
0: dbl := FWorksheet.PageLayout.LeftMargin;
1: dbl := FWorksheet.PageLayout.RightMargin;
2: dbl := FWorksheet.PageLayout.TopMargin;
3: dbl := FWorksheet.PageLayout.Bottommargin;
end;
dbl := mmToIn(dbl);
AStream.WriteBuffer(dbl, SizeOf(dbl)); AStream.WriteBuffer(dbl, SizeOf(dbl));
end; end;
@ -2619,6 +2605,44 @@ begin
AStream.WriteWord(WordToLE(w)); AStream.WriteWord(WordToLE(w));
end; end;
{@@ ----------------------------------------------------------------------------
Writes an Excel HEADER or FOOTER record, depending on AIsHeader.
Valid for BIFF2-5. Override for BIFF7 because of WideStrings
-------------------------------------------------------------------------------}
procedure TsSpreadBIFFWriter.WriteHeaderFooter(AStream: TStream;
AIsHeader: Boolean);
var
s: AnsiString;
len: Integer;
id: Word;
begin
with FWorksheet.PageLayout do
if AIsHeader then
begin
if (Headers[HEADER_FOOTER_INDEX_ALL] = '') then
exit;
s := ConvertEncoding(Headers[HEADER_FOOTER_INDEX_ALL], 'utf8', FCodePage);
id := INT_EXCEL_ID_HEADER;
end else
begin
if (Footers[HEADER_FOOTER_INDEX_ALL] = '') then
exit;
s := ConvertEncoding(Footers[HEADER_FOOTER_INDEX_ALL], 'utf8', FCodePage);
id := INT_EXCEL_ID_FOOTER;
end;
len := Length(s);
{ BIFF record header }
WriteBiffHeader(AStream, id, 1 + len*sizeOf(AnsiChar));
{ 8-bit string length }
AStream.WriteByte(len);
{ Characters }
AStream.WriteBuffer(s[1], len * SizeOf(AnsiChar));
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Writes a 64-bit floating point NUMBER record. Writes a 64-bit floating point NUMBER record.
Valid for BIFF5 and BIFF8 (BIFF2 has a different record structure). Valid for BIFF5 and BIFF8 (BIFF2 has a different record structure).
@ -3254,22 +3278,6 @@ begin
AStream.WriteWord(WordToLE(ASize)); AStream.WriteWord(WordToLE(ASize));
end; end;
{@@ ----------------------------------------------------------------------------
Writes the right margin of the printed page (in inches)
-------------------------------------------------------------------------------}
procedure TsSpreadBIFFWriter.WriteRightMargin(AStream: TStream);
var
dbl: double;
begin
{ BIFF record header }
WriteBIFFHeader(AStream, INT_EXCEL_ID_RIGHTMARGIN, SizeOf(Double));
{ Page margin value, written in inches }
dbl := mmToIn(FWorksheet.PageLayout.RightMargin);
AStream.WriteBuffer(dbl, SizeOf(dbl));
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Writes an Excel 3-8 ROW record Writes an Excel 3-8 ROW record
Valid for BIFF3-BIFF8 Valid for BIFF3-BIFF8
@ -3563,21 +3571,6 @@ begin
Unused(AStream, AString); Unused(AStream, AString);
end; end;
{@@ ----------------------------------------------------------------------------
Write the top margin of the printed page (in inches)
-------------------------------------------------------------------------------}
procedure TsSpreadBIFFWriter.WriteTopMargin(AStream: TStream);
var
dbl: double;
begin
{ BIFF record header }
WriteBIFFHeader(AStream, INT_EXCEL_ID_TOPMARGIN, SizeOf(Double));
{ Page margin value, written in inches }
dbl := mmToIn(FWorksheet.PageLayout.TopMargin);
AStream.WriteBuffer(dbl, SizeOf(dbl));
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Writes an Excel VCENTER record which determines whether the page is to be Writes an Excel VCENTER record which determines whether the page is to be
centered vertically for printing centered vertically for printing

View File

@ -28,7 +28,8 @@ AUTHORS: Felipe Monteiro de Carvalho, Reinier Olislagers, Werner Pamler
unit xlsxooxml; unit xlsxooxml;
{$ifdef fpc} {$ifdef fpc}
{$mode delphi} {$mode objfpc}{$H+}
// {$mode delphi}
{$endif} {$endif}
interface interface
@ -74,10 +75,12 @@ type
procedure ReadFills(ANode: TDOMNode); procedure ReadFills(ANode: TDOMNode);
procedure ReadFont(ANode: TDOMNode); procedure ReadFont(ANode: TDOMNode);
procedure ReadFonts(ANode: TDOMNode); procedure ReadFonts(ANode: TDOMNode);
procedure ReadHeaderFooter(ANode: TDOMNode; AWorksheet: TsWorksheet);
procedure ReadHyperlinks(ANode: TDOMNode); procedure ReadHyperlinks(ANode: TDOMNode);
procedure ReadMergedCells(ANode: TDOMNode; AWorksheet: TsWorksheet); procedure ReadMergedCells(ANode: TDOMNode; AWorksheet: TsWorksheet);
procedure ReadNumFormats(ANode: TDOMNode); procedure ReadNumFormats(ANode: TDOMNode);
procedure ReadPageMargins(ANode: TDOMNode; AWorksheet: TsWorksheet); procedure ReadPageMargins(ANode: TDOMNode; AWorksheet: TsWorksheet);
procedure ReadPageSetup(ANode: TDOMNode; AWorksheet: TsWorksheet);
procedure ReadPalette(ANode: TDOMNode); procedure ReadPalette(ANode: TDOMNode);
procedure ReadPrintOptions(ANode: TDOMNode; AWorksheet: TsWorksheet); procedure ReadPrintOptions(ANode: TDOMNode; AWorksheet: TsWorksheet);
procedure ReadRowHeight(ANode: TDOMNode; AWorksheet: TsWorksheet); procedure ReadRowHeight(ANode: TDOMNode; AWorksheet: TsWorksheet);
@ -127,6 +130,7 @@ type
procedure WriteDimension(AStream: TStream; AWorksheet: TsWorksheet); procedure WriteDimension(AStream: TStream; AWorksheet: TsWorksheet);
procedure WriteFillList(AStream: TStream); procedure WriteFillList(AStream: TStream);
procedure WriteFontList(AStream: TStream); procedure WriteFontList(AStream: TStream);
procedure WriteHeaderFooter(AStream: TStream; AWorksheet: TsWorksheet);
procedure WriteHyperlinks(AStream: TStream; AWorksheet: TsWorksheet); procedure WriteHyperlinks(AStream: TStream; AWorksheet: TsWorksheet);
procedure WriteMergedCells(AStream: TStream; AWorksheet: TsWorksheet); procedure WriteMergedCells(AStream: TStream; AWorksheet: TsWorksheet);
procedure WriteNumFormatList(AStream: TStream); procedure WriteNumFormatList(AStream: TStream);
@ -799,7 +803,7 @@ begin
if (s1 <> '') and (s2 <> '0') then if (s1 <> '') and (s2 <> '0') then
begin begin
fillIndex := StrToInt(s1); fillIndex := StrToInt(s1);
fillData := FFillList[fillIndex]; fillData := TFillListData(FFillList[fillIndex]);
if (fillData <> nil) and (fillData.PatternType <> 'none') then begin if (fillData <> nil) and (fillData.PatternType <> 'none') then begin
fmt.Background.FgColor := fillData.FgColor; fmt.Background.FgColor := fillData.FgColor;
fmt.Background.BgColor := fillData.BgColor; fmt.Background.BgColor := fillData.BgColor;
@ -818,7 +822,7 @@ begin
if (s1 <> '') and (s2 <> '0') then if (s1 <> '') and (s2 <> '0') then
begin begin
borderIndex := StrToInt(s1); borderIndex := StrToInt(s1);
borderData := FBorderList[borderIndex]; borderData := TBorderListData(FBorderList[borderIndex]);
if (borderData <> nil) then if (borderData <> nil) then
begin begin
fmt.BorderStyles := borderData.BorderStyles; fmt.BorderStyles := borderData.BorderStyles;
@ -1182,6 +1186,40 @@ begin
end; end;
end; end;
procedure TsSpreadOOXMLReader.ReadHeaderFooter(ANode: TDOMNode;
AWorksheet: TsWorksheet);
var
node: TDOMNode;
nodeName: String;
s: String;
begin
if ANode = nil then
exit;
s := GetAttrValue(ANode, 'differentOddEven');
if s = '1' then
Include(AWorksheet.PageLayout.Options, poDifferentOddEven);
s := GetAttrValue(ANode, 'differentFirst');
if s = '1' then
Include(AWorksheet.PageLayout.Options, poDifferentFirst);
node := ANode.FirstChild;
while node <> nil do
begin
nodeName := node.NodeName;
case nodeName of
'firstHeader': AWorksheet.PageLayout.Headers[0] := GetNodeValue(node);
'oddHeader' : AWorksheet.PageLayout.Headers[1] := GetNodeValue(node);
'evenHeader' : AWorksheet.PageLayout.Headers[2] := GetNodeValue(node);
'firstFooter': AWorksheet.PageLayout.Footers[0] := GetNodeValue(node);
'oddFooter' : AWorksheet.PageLayout.Footers[1] := GetNodeValue(node);
'evenFooter' : AWorksheet.PageLayout.Footers[2] := GetNodeValue(node);
end;
node := node.NextSibling;
end;
end;
procedure TsSpreadOOXMLReader.ReadHyperlinks(ANode: TDOMNode); procedure TsSpreadOOXMLReader.ReadHyperlinks(ANode: TDOMNode);
var var
node: TDOMNode; node: TDOMNode;
@ -1340,6 +1378,33 @@ begin
AWorksheet.PageLayout.FooterMargin := PtsToMM(HtmlLengthStrToPts(s, 'in')); AWorksheet.PageLayout.FooterMargin := PtsToMM(HtmlLengthStrToPts(s, 'in'));
end; end;
procedure TsSpreadOOXMLReader.ReadPageSetup(ANode: TDOMNode;
AWorksheet: TsWorksheet);
var
s: String;
n: Integer;
begin
if ANode = nil then
exit;
s := GetAttrValue(ANode, 'paperSize');
if s <> '' then
begin
n := StrToInt(s);
if (n >= 0) and (n <= High(PAPER_SIZES)) then
begin
AWorksheet.PageLayout.PageWidth := PAPER_SIZES[n, 0];
AWorksheet.PageLayout.PageHeight := PAPER_SIZES[n, 1];
end;
end;
s:= GetAttrValue(ANode, 'orientation');
if s = 'portrait' then
AWorksheet.PageLayout.Orientation := spoPortrait
else if s = 'landscape' then
AWorksheet.PageLayout.Orientation := spoLandscape;
end;
procedure TsSpreadOOXMLReader.ReadPalette(ANode: TDOMNode); procedure TsSpreadOOXMLReader.ReadPalette(ANode: TDOMNode);
var var
node, colornode: TDOMNode; node, colornode: TDOMNode;
@ -1726,6 +1791,8 @@ begin
ReadHyperlinks(Doc.DocumentElement.FindNode('hyperlinks')); ReadHyperlinks(Doc.DocumentElement.FindNode('hyperlinks'));
ReadPrintOptions(Doc.DocumentElement.FindNode('printOptions'), FWorksheet); ReadPrintOptions(Doc.DocumentElement.FindNode('printOptions'), FWorksheet);
ReadPageMargins(Doc.DocumentElement.FindNode('pageMargins'), FWorksheet); ReadPageMargins(Doc.DocumentElement.FindNode('pageMargins'), FWorksheet);
ReadPageSetup(Doc.DocumentElement.FindNode('pageSetup'), FWorksheet);
ReadHeaderFooter(Doc.DocumentElement.FindNode('headerFooter'), FWorksheet);
FreeAndNil(Doc); FreeAndNil(Doc);
@ -1817,7 +1884,7 @@ var
fmt: PsCellFormat; fmt: PsCellFormat;
begin begin
// No cell, or border-less --> index 0 // No cell, or border-less --> index 0
if (AFormat = nil) or not (uffBorder in AFormat.UsedFormattingFields) then begin if (AFormat = nil) or not (uffBorder in AFormat^.UsedFormattingFields) then begin
Result := 0; Result := 0;
exit; exit;
end; end;
@ -1991,8 +2058,9 @@ begin
for i:=1 to High(FBorderList) do begin for i:=1 to High(FBorderList) do begin
diag := ''; diag := '';
if (cbDiagUp in FBorderList[i].Border) then diag := diag + ' diagonalUp="1"'; if (cbDiagUp in FBorderList[i]^.Border) then
if (cbDiagDown in FBorderList[i].Border) then diag := diag + ' diagonalDown="1"'; diag := diag + ' diagonalUp="1"';
if (cbDiagDown in FBorderList[i]^.Border) then diag := diag + ' diagonalDown="1"';
AppendToStream(AStream, AppendToStream(AStream,
'<border' + diag + '>'); '<border' + diag + '>');
WriteBorderStyle(AStream, FBorderList[i], cbWest, 'left'); WriteBorderStyle(AStream, FBorderList[i], cbWest, 'left');
@ -2026,7 +2094,7 @@ begin
if col <> nil then if col <> nil then
AppendToStream(AStream, Format( AppendToStream(AStream, Format(
'<col min="%d" max="%d" width="%g" customWidth="1" />', '<col min="%d" max="%d" width="%g" customWidth="1" />',
[c+1, c+1, col.Width], FPointSeparatorSettings) [c+1, c+1, col^.Width], FPointSeparatorSettings)
); );
end; end;
@ -2133,7 +2201,7 @@ begin
fc := 'auto="1"' fc := 'auto="1"'
else else
fc := Format('rgb="%s"', [Copy(Workbook.GetPaletteColorAsHTMLStr(FFillList[i]^.Background.FgColor), 2, 255)]); fc := Format('rgb="%s"', [Copy(Workbook.GetPaletteColorAsHTMLStr(FFillList[i]^.Background.FgColor), 2, 255)]);
if FFillList[i].Background.BgColor = scTransparent then if FFillList[i]^.Background.BgColor = scTransparent then
bc := 'auto="1"' bc := 'auto="1"'
else else
bc := Format('rgb="%s"', [Copy(Workbook.GetPaletteColorAsHTMLStr(FFillList[i]^.Background.BgColor), 2, 255)]); bc := Format('rgb="%s"', [Copy(Workbook.GetPaletteColorAsHTMLStr(FFillList[i]^.Background.BgColor), 2, 255)]);
@ -2198,6 +2266,68 @@ begin
'</fonts>'); '</fonts>');
end; end;
procedure TsSpreadOOXMLWriter.WriteHeaderFooter(AStream: TStream;
AWorksheet: TsWorksheet);
var
hasHeader: Boolean;
hasFooter: Boolean;
i: Integer;
s: String;
begin
hasHeader := false;
hasFooter := false;
with AWorksheet.PageLayout do
begin
for i:=HEADER_FOOTER_INDEX_FIRST to HEADER_FOOTER_INDEX_EVEN do
begin
if Headers[i] <> '' then
hasHeader := true;
if Footers[i] <> '' then
hasFooter := true;
end;
if not (hasHeader or hasFooter) then
exit;
s := '';
if poDifferentFirst in Options then
s := s + ' differentFirst="1"';
if poDifferentOddEven in Options then
s := s + ' differentOddEven="1"';
AppendToStream(AStream,
'<headerFooter' + s);
if Headers[HEADER_FOOTER_INDEX_ODD] <> '' then
AppendToStream(AStream,
'<oddHeader>' + Headers[HEADER_FOOTER_INDEX_ODD] + '</oddHeader>');
if Footers[HEADER_FOOTER_INDEX_ODD] <> '' then
AppendToStream(AStream,
'<oddFooter>' + Footers[HEADER_FOOTER_INDEX_ODD] + '</oddFooter>');
if poDifferentFirst in AWorksheet.PageLayout.Options then
begin
if Headers[HEADER_FOOTER_INDEX_FIRST] <> '' then
AppendToStream(AStream,
'<firstHeader>' + Headers[HEADER_FOOTER_INDEX_FIRST] + '</firstHeader>');
if Footers[HEADER_FOOTER_INDEX_FIRST] <> '' then
AppendToStream(AStream,
'<firstFooter>' + Footers[HEADER_FOOTER_INDEX_FIRST] + '</firstFooter>');
end;
if poDifferentOddEven in Options then
begin
AppendToStream(AStream,
'<evenHeader>' + Headers[HEADER_FOOTER_INDEX_EVEN] + '</evenHeader>');
AppendToStream(AStream,
'<evenFooter>' + Footers[HEADER_FOOTER_INDEX_EVEN] + '</evenFooter>');
end;
AppendToStream(AStream,
'</headerFooter>');
end;
end;
procedure TsSpreadOOXMLWriter.WriteHyperlinks(AStream: TStream; procedure TsSpreadOOXMLWriter.WriteHyperlinks(AStream: TStream;
AWorksheet: TsWorksheet); AWorksheet: TsWorksheet);
var var
@ -2258,7 +2388,7 @@ begin
'<mergeCells count="%d">', [n]) ); '<mergeCells count="%d">', [n]) );
for rng in AWorksheet.MergedCells do for rng in AWorksheet.MergedCells do
AppendToStream(AStream, Format( AppendToStream(AStream, Format(
'<mergeCell ref="%s" />', [GetCellRangeString(rng.Row1, rng.Col1, rng.Row2, rng.Col2)])); '<mergeCell ref="%s" />', [GetCellRangeString(rng^.Row1, rng^.Col1, rng^.Row2, rng^.Col2)]));
AppendToStream(AStream, AppendToStream(AStream,
'</mergeCells>'); '</mergeCells>');
end; end;
@ -2662,7 +2792,7 @@ begin
{ Text alignment } { Text alignment }
if (uffHorAlign in fmt^.UsedFormattingFields) and (fmt^.HorAlignment <> haDefault) if (uffHorAlign in fmt^.UsedFormattingFields) and (fmt^.HorAlignment <> haDefault)
then then
case fmt.HorAlignment of case fmt^.HorAlignment of
haLeft : sAlign := sAlign + 'horizontal="left" '; haLeft : sAlign := sAlign + 'horizontal="left" ';
haCenter: sAlign := sAlign + 'horizontal="center" '; haCenter: sAlign := sAlign + 'horizontal="center" ';
haRight : sAlign := sAlign + 'horizontal="right" '; haRight : sAlign := sAlign + 'horizontal="right" ';
@ -2670,7 +2800,7 @@ begin
if (uffVertAlign in fmt^.UsedFormattingFields) and (fmt^.VertAlignment <> vaDefault) if (uffVertAlign in fmt^.UsedFormattingFields) and (fmt^.VertAlignment <> vaDefault)
then then
case fmt.VertAlignment of case fmt^.VertAlignment of
vaTop : sAlign := sAlign + 'vertical="top" '; vaTop : sAlign := sAlign + 'vertical="top" ';
vaCenter: sAlign := sAlign + 'vertical="center" '; vaCenter: sAlign := sAlign + 'vertical="center" ';
vaBottom: sAlign := sAlign + 'vertical="bottom" '; vaBottom: sAlign := sAlign + 'vertical="bottom" ';
@ -2680,7 +2810,7 @@ begin
sAlign := sAlign + 'wrapText="1" '; sAlign := sAlign + 'wrapText="1" ';
{ Fill } { Fill }
if (uffBackground in fmt.UsedFormattingFields) then if (uffBackground in fmt^.UsedFormattingFields) then
begin begin
fillID := FindFillInList(fmt); fillID := FindFillInList(fmt);
if fillID = -1 then fillID := 0; if fillID = -1 then fillID := 0;
@ -2913,7 +3043,7 @@ procedure TsSpreadOOXMLWriter.WriteContent;
var var
i, counter: Integer; i, counter: Integer;
begin begin
{ --- WorkbookRels --- { --- WorkbookRels --- }
{ Workbook relations - Mark relation to all sheets } { Workbook relations - Mark relation to all sheets }
counter := 0; counter := 0;
AppendToStream(FSWorkbookRels, AppendToStream(FSWorkbookRels,
@ -3052,6 +3182,7 @@ begin
WritePrintOptions(FSSheets[FCurSheetNum], AWorksheet); WritePrintOptions(FSSheets[FCurSheetNum], AWorksheet);
WritePageMargins(FSSheets[FCurSheetNum], AWorksheet); WritePageMargins(FSSheets[FCurSheetNum], AWorksheet);
WritePageSetup(FSSheets[FCurSheetNum], AWorksheet); WritePageSetup(FSSheets[FCurSheetNum], AWorksheet);
WriteHeaderFooter(FSSheets[FCurSheetNum], AWorksheet);
// Footer // Footer
if AWorksheet.Comments.Count > 0 then if AWorksheet.Comments.Count > 0 then