diff --git a/components/fpspreadsheet/fpsopendocument.pas b/components/fpspreadsheet/fpsopendocument.pas
index 135054995..e82c9f6c9 100755
--- a/components/fpspreadsheet/fpsopendocument.pas
+++ b/components/fpspreadsheet/fpsopendocument.pas
@@ -66,6 +66,7 @@ type
FRowStyleList: TFPList;
FRowList: TFPList;
FDateMode: TDateMode;
+ FPageLayout: TsPageLayout;
// Applies internally stored column widths to current worksheet
procedure ApplyColWidths;
// Applies a style to a cell
@@ -91,6 +92,7 @@ type
protected
FPointSeparatorSettings: TFormatSettings;
procedure AddBuiltinNumFormats; override;
+ procedure ReadAutomaticStyles(AStylesNode: TDOMNode);
procedure ReadNumFormats(AStylesNode: TDOMNode);
procedure ReadSettings(AOfficeSettingsNode: TDOMNode);
procedure ReadStyles(AStylesNode: TDOMNode);
@@ -618,6 +620,8 @@ begin
Workbook.UseDefaultPalette;
// Initial base date in case it won't be read from file
FDateMode := dm1899;
+ // Initialize internal PageLayout record
+ InitPageLayout(FPageLayout);
end;
destructor TsSpreadOpenDocReader.Destroy;
@@ -850,6 +854,79 @@ begin
Result := -1;
end;
+procedure TsSpreadOpenDocReader.ReadAutomaticStyles(AStylesNode: TDOMNode);
+var
+ nodeName: String;
+ layoutNode: TDOMNode;
+ node: TDOMNode;
+ s: String;
+begin
+ if not Assigned(AStylesNode) then
+ exit;
+ layoutNode := AStylesNode.FirstChild;
+ while layoutNode <> nil do
+ begin
+ nodeName := layoutNode.NodeName;
+ if nodeName = 'style:page-layout' then begin
+ s := GetAttrValue(layoutNode, 'style:name');
+ if s = 'Mpm1' then
+ begin
+ node := layoutNode.FirstChild;
+ while node <> nil do
+ begin
+ nodeName := node.NodeName;
+ if nodeName = 'style:page-layout-properties' then
+ begin
+ s := GetAttrValue(node, 'fo:margin-top');
+ if s <> '' then
+ FPageLayout.TopMargin := PtsToMM(HTMLLengthStrToPts(s));
+
+ s := GetAttrValue(node, 'fo:margin-bottom');
+ if s <> '' then
+ FPageLayout.BottomMargin := PtsToMM(HTMLLengthStrToPts(s));
+
+ s := GetAttrValue(node, 'fo:margin-left');
+ if s <> '' then
+ FPageLayout.LeftMargin := PtsToMM(HTMLLengthStrToPts(s));
+
+ s := GetAttrValue(node, 'fo:margin-right');
+ if s <> '' then
+ FPageLayout.RightMargin := PtsToMM(HTMLLengthStrToPts(s));
+
+ s := GetAttrValue(node, 'style:scale-to');
+ if (s <> '') then
+ begin
+ if s[Length(s)] = '%' then Delete(s, Length(s), 1);
+ FPageLayout.ScalingFactor := StrToFloat(s, FPointSeparatorSettings);
+ end;
+
+ s := GetAttrValue(node, 'style:print');
+ if pos('grid', s) > 0 then
+ Include(FPageLayout.Options, poPrintGridLines);
+ if pos('headers', s) > 0 then
+ Include(FPageLayout.Options, poPrintHeaders);
+ if pos('annotations', s) > 0 then
+ Include(FPageLayout.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(FPageLayout.Options, poPrintPagesByRows);
+
+ s := GetAttrValue(node, 'style:first-page-number');
+ if s = 'continue' then
+ Exclude(FPageLayout.Options, poUseStartPageNumber)
+ else
+ if TryStrToInt(s, FPageLayout.StartPageNumber) then
+ Include(FPageLayout.Options, poUseStartPageNumber);
+ end;
+ node := node.NextSibling;
+ end;
+ end;
+ end;
+ layoutNode := layoutNode.NextSibling;
+ end;
+end;
+
procedure TsSpreadOpenDocReader.ReadBlank(ARow, ACol: Cardinal;
ACellNode: TDOMNode);
var
@@ -1317,6 +1394,9 @@ begin
ReadNumFormats(StylesNode);
ReadStyles(StylesNode);
+ StylesNode := Doc.DocumentElement.FindNode('office:automatic-styles');
+ ReadAutomaticStyles(StylesNode);
+
Doc.Free;
//process the content.xml file
@@ -1349,6 +1429,7 @@ begin
continue;
end;
FWorkSheet := FWorkbook.AddWorksheet(GetAttrValue(TableNode,'table:name'), true);
+ FWorksheet.PageLayout := FPageLayout;
// Collect column styles used
ReadColumns(TableNode);
// Process each row inside the sheet and process each cell of the row
diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas
index 59d9d9d6b..fe8361d3c 100755
--- a/components/fpspreadsheet/fpspreadsheet.pas
+++ b/components/fpspreadsheet/fpspreadsheet.pas
@@ -105,7 +105,6 @@ type
FDefaultColWidth: Single; // in "characters". Excel uses the width of char "0" in 1st font
FDefaultRowHeight: Single; // in "character heights", i.e. line count
FSortParams: TsSortParams; // Parameters of the current sorting operation
- FPageLayout: TsPageLayout;
FOnChangeCell: TsCellEvent;
FOnChangeFont: TsCellEvent;
FOnCompareCells: TsCellCompareEvent;
@@ -138,6 +137,9 @@ type
procedure ExchangeCells(ARow1, ACol1, ARow2, ACol2: Cardinal);
public
+ {@@ Page layout parameters for printing }
+ PageLayout: TsPageLayout;
+
{ Base methods }
constructor Create;
destructor Destroy; override;
@@ -468,8 +470,6 @@ type
{@@ The default row height is given in "line count" (height of the
default font }
property DefaultRowHeight: Single read FDefaultRowHeight write FDefaultRowHeight;
- {@@ Page layout parameters for printing }
- property PageLayout: TsPageLayout read FPageLayout write FPageLayout;
// These are properties to interface to TsWorksheetGrid
{@@ Parameters controlling visibility of grid lines and row/column headers,
@@ -1114,14 +1114,7 @@ begin
FMergedCells := TsMergedCells.Create;
FHyperlinks := TsHyperlinks.Create;
- with FPageLayout do begin
- LeftMargin := InToPts(0.7);
- RightMargin := InToPts(0.7);
- TopMargin := InToPts(0.78740157499999996);
- BottomMargin := InToPts(0.78740157499999996);
- HeaderDistance := InToPts(0.3);
- FooterDistance := InToPts(0.3);
- end;
+ InitPageLayout(PageLayout);
FDefaultColWidth := 12;
FDefaultRowHeight := 1;
@@ -6767,6 +6760,8 @@ begin
// Remember the workbook to which it belongs (This must occur before
// setting the workbook name because the workbook is needed there).
Result.FWorkbook := Self;
+ Result.FActiveCellRow := 0;
+ Result.FActiveCellCol := 0;
// Set the name of the new worksheet.
// For this we turn off notification of listeners. This is not necessary here
diff --git a/components/fpspreadsheet/fpspreadsheetctrls.pas b/components/fpspreadsheet/fpspreadsheetctrls.pas
index 0fd2f8dcd..a865d6164 100644
--- a/components/fpspreadsheet/fpspreadsheetctrls.pas
+++ b/components/fpspreadsheet/fpspreadsheetctrls.pas
@@ -2881,6 +2881,9 @@ end;
-------------------------------------------------------------------------------}
procedure TsSpreadsheetInspector.UpdateWorksheet(ASheet: TsWorksheet;
AStrings: TStrings);
+var
+ s: String;
+ po: TsPrintOption;
begin
if ASheet = nil then
begin
@@ -2891,6 +2894,7 @@ begin
AStrings.Add('Last column=');
AStrings.Add('Active cell=');
AStrings.Add('Selection=');
+ AStrings.Add('Page layout=');
end else
begin
AStrings.Add(Format('Name=%s', [ASheet.Name]));
@@ -2903,6 +2907,27 @@ begin
AStrings.Add(Format('Comments=%d items', [ASheet.Comments.Count]));
AStrings.Add(Format('Hyperlinks=%d items', [ASheet.Hyperlinks.Count]));
AStrings.Add(Format('MergedCells=%d items', [ASheet.MergedCells.Count]));
+ AStrings.Add('Page layout=');
+ AStrings.Add(Format(' Orientation=%s', [GetEnumName(TypeInfo(TsPageOrientation), ord(ASheet.PageLayout.Orientation))]));
+ AStrings.Add(Format(' Page width=%.1f mm', [ASheet.PageLayout.PageWidth]));
+ AStrings.Add(Format(' Page height=%.1f mm', [ASheet.PageLayout.PageHeight]));
+ AStrings.Add(Format(' Left margin=%.1f mm', [ASheet.PageLayout.LeftMargin]));
+ AStrings.Add(Format(' Right margin=%.1f mm', [ASheet.PageLayout.RightMargin]));
+ AStrings.Add(Format(' Top margin=%.1f mm', [ASheet.PageLayout.TopMargin]));
+ AStrings.Add(Format(' Bottom margin=%.1f mm', [ASheet.PageLayout.BottomMargin]));
+ AStrings.Add(Format(' Header distance=%.1f mm', [ASheet.PageLayout.HeaderMargin]));
+ AStrings.Add(Format(' Footer distance=%.1f mm', [ASheet.PageLayout.FooterMargin]));
+ if poUseStartPageNumber in ASheet.PageLayout.Options then
+ AStrings.Add(Format(' Start page number=%d', [ASheet.pageLayout.StartPageNumber]))
+ else
+ AStrings.Add (' Start page number=automatic');
+ AStrings.Add(Format(' Scaling factor=%.0f%%', [ASheet.PageLayout.ScalingFactor]));
+ AStrings.Add(Format(' Copies=%d', [ASheet.PageLayout.Copies]));
+ s := '';
+ for po in TsPrintOption do
+ if po in ASheet.PageLayout.Options then s := s + '; ' + GetEnumName(typeInfo(TsPrintOption), ord(po));
+ if s <> '' then Delete(s, 1, 2);
+ AStrings.Add(Format(' Options=%s', [s]));
end;
end;
diff --git a/components/fpspreadsheet/fpstypes.pas b/components/fpspreadsheet/fpstypes.pas
index 42154bc24..8a42fed07 100644
--- a/components/fpspreadsheet/fpstypes.pas
+++ b/components/fpspreadsheet/fpstypes.pas
@@ -668,13 +668,39 @@ type
cctError : (ErrorValue: TsErrorValue);
end;
- TsPageLayout = record
- LeftMargin: Double; // in Points
+{
+ 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);
+
+ TsPrintOption = (poPrintGridLines, poPrintHeaders, poPrintPagesByRows,
+ poMonochrome, poDraftQuality, poPrintCellComments, poDefaultOrientation,
+ poUseStartPageNumber, poCommentsAtEnd, poHorCentered, poVertCentered);
+
+ TsPrintOptions = set of TsPrintOption;
+
+ 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;
- HeaderDistance: Double;
- FooterDistance: Double;
+ HeaderMargin: Double;
+ FooterMargin: Double;
+ StartPageNumber: Integer;
+ ScalingFactor: Double; // in percent
+ FitWidthToPages: Integer;
+ FitHeightToPages: Integer;
+ Copies: Integer;
+ Options: TsPrintOptions;
end;
function BuildFormatStringFromSection(const ASection: TsNumFormatSection): String;
diff --git a/components/fpspreadsheet/fpsutils.pas b/components/fpspreadsheet/fpsutils.pas
index af14408d1..a951222e2 100644
--- a/components/fpspreadsheet/fpsutils.pas
+++ b/components/fpspreadsheet/fpsutils.pas
@@ -134,17 +134,19 @@ function TryStrToFloatAuto(AText: String; out ANumber: Double;
function TryFractionStrToFloat(AText: String; out ANumber: Double;
out AMaxDigits: Integer): Boolean;
-function TwipsToPts(AValue: Integer): Single;
-function PtsToTwips(AValue: Single): Integer;
-function cmToPts(AValue: Double): Double;
-function PtsToCm(AValue: Double): Double;
-function InToPts(AValue: Double): Double;
-function PtsToIn(AValue: Double): Double;
-function mmToPts(AValue: Double): Double;
-function PtsToMM(AValue: Double): Double;
-function pxToPts(AValue, AScreenPixelsPerInch: Integer): Double;
-function PtsToPx(AValue: Double; AScreenPixelsPerInch: Integer): Integer;
-function HTMLLengthStrToPts(AValue: String): Double;
+function TwipsToPts(AValue: Integer): Single; inline;
+function PtsToTwips(AValue: Single): Integer; inline;
+function cmToPts(AValue: Double): Double; inline;
+function PtsToCm(AValue: Double): Double; inline;
+function InToMM(AValue: Double): Double; inline;
+function InToPts(AValue: Double): Double; inline;
+function PtsToIn(AValue: Double): Double; inline;
+function mmToPts(AValue: Double): Double; inline;
+function mmToIn(AValue: Double): Double; inline;
+function PtsToMM(AValue: Double): Double; inline;
+function pxToPts(AValue, AScreenPixelsPerInch: Integer): Double; inline;
+function PtsToPx(AValue: Double; AScreenPixelsPerInch: Integer): Integer; inline;
+function HTMLLengthStrToPts(AValue: String; DefaultUnits: String = 'pt'): Double;
function HTMLColorStrToColor(AValue: String): TsColorValue;
function ColorToHTMLColorStr(AValue: TsColorValue; AExcelDialect: Boolean = false): String;
@@ -165,6 +167,7 @@ procedure FixHyperlinkPathDelims(var ATarget: String);
procedure InitCell(out ACell: TCell); overload;
procedure InitCell(ARow, ACol: Cardinal; out ACell: TCell); overload;
procedure InitFormatRecord(out AValue: TsCellFormat);
+procedure InitPageLayout(out APageLayout: TsPageLayout);
procedure AppendToStream(AStream: TStream; const AString: String); inline; overload;
procedure AppendToStream(AStream: TStream; const AString1, AString2: String); inline; overload;
@@ -1977,6 +1980,28 @@ begin
Result := AValue / 72 * 2.54;
end;
+{@@ ----------------------------------------------------------------------------
+ Converts inches to millimeters
+
+ @param AValue Length value in inches
+ @return Value converted to mm
+-------------------------------------------------------------------------------}
+function InToMM(AValue: Double): Double;
+begin
+ Result := AValue * 25.4;
+end;
+
+{@@ ----------------------------------------------------------------------------
+ Converts millimeters to inches
+
+ @param AValue Length value in millimeters
+ @return Value converted to inches
+-------------------------------------------------------------------------------}
+function mmToIn(AValue: Double): Double;
+begin
+ Result := AValue / 25.4;
+end;
+
{@@ ----------------------------------------------------------------------------
Converts inches to points (72 pts = 1 inch)
@@ -2052,9 +2077,11 @@ end;
such as '1.25in'. These unit codes are accepted:
'px' (pixels), 'pt' (points), 'in' (inches), 'mm' (millimeters),
'cm' (centimeters).
+ @param DefaultUnits String identifying the units to be used if not contained
+ in AValue.
@return Extracted length in points
-------------------------------------------------------------------------------}
-function HTMLLengthStrToPts(AValue: String): Double;
+function HTMLLengthStrToPts(AValue: String; DefaultUnits: String = 'pt'): Double;
var
units: String;
x: Double;
@@ -2062,10 +2089,11 @@ var
begin
if (Length(AValue) > 1) and (AValue[Length(AValue)] in ['a'..'z', 'A'..'Z']) then begin
units := lowercase(Copy(AValue, Length(AValue)-1, 2));
+ if units = '' then units := DefaultUnits;
val(copy(AValue, 1, Length(AValue)-2), x, res);
// No hasseling with the decimal point...
end else begin
- units := '';
+ units := DefaultUnits;
val(AValue, x, res);
end;
if res <> 0 then
@@ -2376,6 +2404,30 @@ begin
AValue.NumberFormatIndex := -1; // GENERAL format not contained in NumFormatList
end;
+{@@ ----------------------------------------------------------------------------
+ Initializes the fields of a TsPageLayout record
+-------------------------------------------------------------------------------}
+procedure InitPageLayout(out APageLayout: TsPageLayout);
+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 := [];
+ end;
+end;
+
{@@ ----------------------------------------------------------------------------
Appends a string to a stream
diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas
index 31c172a01..84e29b42f 100755
--- a/components/fpspreadsheet/xlsbiff2.pas
+++ b/components/fpspreadsheet/xlsbiff2.pas
@@ -455,27 +455,33 @@ begin
case RecordType of
INT_EXCEL_ID_BLANK : ReadBlank(AStream);
+ INT_EXCEL_ID_BOF : ;
INT_EXCEL_ID_BOOLERROR : ReadBool(AStream);
+ INT_EXCEL_ID_BOTTOMMARGIN: ReadBottomMargin(AStream);
INT_EXCEL_ID_CODEPAGE : ReadCodePage(AStream);
- INT_EXCEL_ID_NOTE : ReadComment(AStream);
+ INT_EXCEL_ID_COLWIDTH : ReadColWidth(AStream);
+ INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
+ INT_EXCEL_ID_EOF : BIFF2EOF := True;
INT_EXCEL_ID_FONT : ReadFont(AStream);
INT_EXCEL_ID_FONTCOLOR : ReadFontColor(AStream);
INT_EXCEL_ID_FORMAT : ReadFormat(AStream);
+ INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
INT_EXCEL_ID_INTEGER : ReadInteger(AStream);
INT_EXCEL_ID_IXFE : ReadIXFE(AStream);
- INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
INT_EXCEL_ID_LABEL : ReadLabel(AStream);
- INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
- INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
- INT_EXCEL_ID_COLWIDTH : ReadColWidth(AStream);
- INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
+ INT_EXCEL_ID_LEFTMARGIN : ReadLeftMargin(AStream);
+ INT_EXCEL_ID_NOTE : ReadComment(AStream);
+ INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
+ INT_EXCEL_ID_PANE : ReadPane(AStream);
+ INT_EXCEL_ID_PRINTGRID : ReadPrintGridLines(AStream);
+ INT_EXCEL_ID_PRINTHEADERS: ReadPrintHeaders(AStream);
+ INT_EXCEL_ID_RIGHTMARGIN : ReadRightMargin(AStream);
INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
+ INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
+ INT_EXCEL_ID_TOPMARGIN : ReadTopMargin(AStream);
INT_EXCEL_ID_DEFROWHEIGHT: ReadDefRowHeight(AStream);
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
- INT_EXCEL_ID_PANE : ReadPane(AStream);
INT_EXCEL_ID_XF : ReadXF(AStream);
- INT_EXCEL_ID_BOF : ;
- INT_EXCEL_ID_EOF : BIFF2EOF := True;
else
// nothing
end;
@@ -1229,8 +1235,18 @@ begin
raise Exception.Create(rsWorksheetNotFound1);
WriteBOF(AStream);
- WriteFonts(AStream);
WriteCodePage(AStream, FCodePage);
+ WritePrintHeaders(AStream);
+ WritePrintGridLines(AStream);
+ WriteFonts(AStream);
+
+ // Page settings block
+ WriteLeftMargin(AStream);
+ WriteRightMargin(AStream);
+ WriteTopMargin(AStream);
+ WriteBottomMargin(AStream);
+// WritePageSetup(AStream); // does not exist in BIFF2
+
WriteFormatCount(AStream);
WriteNumFormats(AStream);
WriteXFRecords(AStream);
diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas
index b632cacda..59e9818ba 100755
--- a/components/fpspreadsheet/xlsbiff5.pas
+++ b/components/fpspreadsheet/xlsbiff5.pas
@@ -390,25 +390,34 @@ begin
case RecordType of
INT_EXCEL_ID_BLANK : ReadBlank(AStream);
+ INT_EXCEL_ID_BOF : ;
INT_EXCEL_ID_BOOLERROR : ReadBool(AStream);
+ INT_EXCEL_ID_BOTTOMMARGIN : ReadBottomMargin(AStream);
+ INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
+ INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
+ INT_EXCEL_ID_EOF : SectionEOF := True;
+ INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
+ INT_EXCEL_ID_HCENTER : ReadHCENTER(AStream);
+ INT_EXCEL_ID_LABEL : ReadLabel(AStream);
+ INT_EXCEL_ID_LEFTMARGIN : ReadLeftMargin(AStream);
INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream);
+ INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream);
INT_EXCEL_ID_NOTE : ReadComment(AStream);
INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
- INT_EXCEL_ID_LABEL : ReadLabel(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_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_MULRK : ReadMulRKValues(AStream);
- INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
- INT_EXCEL_ID_STANDARDWIDTH : ReadStandardWidth(AStream, FWorksheet);
- INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
- INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
- INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
- INT_EXCEL_ID_SHAREDFMLA : ReadSharedFormula(AStream);
- INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
- INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
INT_EXCEL_ID_PANE : ReadPane(AStream);
- INT_EXCEL_ID_BOF : ;
- INT_EXCEL_ID_EOF : SectionEOF := True;
+ INT_EXCEL_ID_PAGESETUP : ReadPageSetup(AStream);
+ INT_EXCEL_ID_PRINTGRID : ReadPrintGridLines(AStream);
+ INT_EXCEL_ID_PRINTHEADERS : ReadPrintHeaders(AStream);
+ INT_EXCEL_ID_RIGHTMARGIN : ReadRightMargin(AStream);
+ 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_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_STANDARDWIDTH : ReadStandardWidth(AStream, FWorksheet);
+ INT_EXCEL_ID_TOPMARGIN : ReadTopMargin(AStream);
+ INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
+ INT_EXCEL_ID_VCENTER : ReadVCENTER(AStream);
+ INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
{$IFDEF FPSPREADDEBUG} // Only write out if debugging
else
@@ -1030,9 +1039,19 @@ begin
AStream.Position := CurrentPos;
WriteBOF(AStream, INT_BOF_SHEET);
-
WriteIndex(AStream);
-// WritePageSetup(AStream);
+ WritePrintHeaders(AStream);
+ WritePrintGridLines(AStream);
+
+ // Page settings block
+ WriteHCenter(AStream);
+ WriteVCenter(AStream);
+ WriteLeftMargin(AStream);
+ WriteRightMargin(AStream);
+ WriteTopMargin(AStream);
+ WriteBottomMargin(AStream);
+ WritePageSetup(AStream);
+
WriteColInfos(AStream, FWorksheet);
WriteDimensions(AStream, FWorksheet);
WriteWindow2(AStream, FWorksheet);
diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas
index 301499268..87bd2912b 100755
--- a/components/fpspreadsheet/xlsbiff8.pas
+++ b/components/fpspreadsheet/xlsbiff8.pas
@@ -120,6 +120,7 @@ type
TsSpreadBIFF8Writer = class(TsSpreadBIFFWriter)
protected
+ function GetPrintOptions: Word; override;
{ Record writing methods }
procedure WriteBOF(AStream: TStream; ADataType: Word);
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
@@ -675,39 +676,51 @@ begin
case RecordType of
- INT_EXCEL_ID_BLANK : ReadBlank(AStream);
- INT_EXCEL_ID_BOOLERROR : ReadBool(AStream);
- INT_EXCEL_ID_CONTINUE : ReadCONTINUE(AStream);
- INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
- INT_EXCEL_ID_HYPERLINK : ReadHyperlink(AStream);
- INT_EXCEL_ID_HLINKTOOLTIP: ReadHyperlinkToolTip(AStream);
- INT_EXCEL_ID_LABEL : ReadLabel(AStream);
- INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream);
- INT_EXCEL_ID_NOTE : ReadNOTE(AStream);
- INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
- INT_EXCEL_ID_OBJ : ReadOBJ(AStream);
- INT_EXCEL_ID_SHAREDFMLA : ReadSharedFormula(AStream);
- INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
- INT_EXCEL_ID_TXO : ReadTXO(AStream);
+ INT_EXCEL_ID_BLANK : ReadBlank(AStream);
+ INT_EXCEL_ID_BOF : ;
+ INT_EXCEL_ID_BOOLERROR : ReadBool(AStream);
+ INT_EXCEL_ID_BOTTOMMARGIN : ReadBottomMargin(AStream);
+ INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
+ INT_EXCEL_ID_CONTINUE : ReadCONTINUE(AStream);
+ INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
+ INT_EXCEL_ID_EOF : SectionEOF := True;
+ INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
+ INT_EXCEL_ID_HCENTER : ReadHCENTER(AStream);
+ INT_EXCEL_ID_HLINKTOOLTIP : ReadHyperlinkToolTip(AStream);
+ INT_EXCEL_ID_HYPERLINK : ReadHyperlink(AStream);
+ INT_EXCEL_ID_LABEL : ReadLabel(AStream);
+ INT_EXCEL_ID_LABELSST : ReadLabelSST(AStream);
+ INT_EXCEL_ID_LEFTMARGIN : ReadLeftMargin(AStream);
+ INT_EXCEL_ID_MERGEDCELLS : ReadMergedCells(AStream);
+ INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream);
+ INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream);
+ INT_EXCEL_ID_NOTE : ReadNOTE(AStream);
+ INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
+ INT_EXCEL_ID_OBJ : ReadOBJ(AStream);
+ INT_EXCEL_ID_PAGESETUP : ReadPageSetup(AStream);
+ INT_EXCEL_ID_PANE : ReadPane(AStream);
+ INT_EXCEL_ID_PRINTGRID : ReadPrintGridLines(AStream);
+ INT_EXCEL_ID_PRINTHEADERS : ReadPrintHeaders(AStream);
+ INT_EXCEL_ID_RIGHTMARGIN : ReadRightMargin(AStream);
+ INT_EXCEL_ID_ROW : ReadRowInfo(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);
+ INT_EXCEL_ID_RSTRING : ReadRichString(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);
- INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream);
- INT_EXCEL_ID_LABELSST : ReadLabelSST(AStream); //BIFF8 only
- INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
- INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
- INT_EXCEL_ID_MERGEDCELLS : ReadMergedCells(AStream);
- INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
- INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
- INT_EXCEL_ID_PANE : ReadPane(AStream);
- INT_EXCEL_ID_BOF : ;
- INT_EXCEL_ID_EOF : SectionEOF := True;
+ INT_EXCEL_ID_RK : ReadRKValue(AStream);
+
+ INT_EXCEL_ID_SHAREDFMLA : ReadSharedFormula(AStream);
+ INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
+ INT_EXCEL_ID_TOPMARGIN : ReadTopMargin(AStream);
+ INT_EXCEL_ID_TXO : ReadTXO(AStream);
+ INT_EXCEL_ID_VCENTER : ReadVCENTER(AStream);
+ INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
else
// nothing
end;
@@ -1614,6 +1627,17 @@ begin
FDateMode := Excel8Settings.DateMode;
end;
+function TsSpreadBIFF8Writer.GetPrintOptions: Word;
+Begin
+ Result := inherited GetPrintOptions;
+{ The following flags are valid for BIFF8 only:
+ Bit 9: 0 = Print notes as displayed; 1 = Print notes at end of sheet
+ Bit 11-10: 00 = Print errors as displayed; 1 = Do not print errors
+ 2 = Print errors as “--”; 3 = Print errors as “#N/A” }
+ if poCommentsAtEnd in FWorksheet.PageLayout.Options then
+ Result := Result or $0200;
+end;
+
{@@ ----------------------------------------------------------------------------
Writes an Excel BIFF8 file to the disc
@@ -1695,8 +1719,20 @@ begin
WriteBOF(AStream, INT_BOF_SHEET);
WriteIndex(AStream);
+ WritePrintHeaders(AStream);
+ WritePrintGridLines(AStream);
+
//WriteSheetPR(AStream);
-// WritePageSetup(AStream);
+
+ // Page setting block
+ WriteHCenter(AStream);
+ WriteVCenter(AStream);
+ WriteLeftMargin(AStream);
+ WriteRightMargin(AStream);
+ WriteTopMargin(AStream);
+ WriteBottomMargin(AStream);
+ WritePageSetup(AStream);
+
WriteColInfos(AStream, FWorksheet);
WriteDimensions(AStream, FWorksheet);
//WriteRowAndCellBlock(AStream, sheet);
diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas
index 5354bffc8..ca8ee2dc4 100644
--- a/components/fpspreadsheet/xlscommon.pas
+++ b/components/fpspreadsheet/xlscommon.pas
@@ -20,6 +20,12 @@ const
INT_EXCEL_ID_NOTE = $001C;
INT_EXCEL_ID_SELECTION = $001D;
INT_EXCEL_ID_DATEMODE = $0022;
+ INT_EXCEL_ID_LEFTMARGIN = $0026;
+ INT_EXCEL_ID_RIGHTMARGIN = $0027;
+ INT_EXCEL_ID_TOPMARGIN = $0028;
+ INT_EXCEL_ID_BOTTOMMARGIN= $0029;
+ INT_EXCEL_ID_PRINTHEADERS= $002A;
+ INT_EXCEL_ID_PRINTGRID = $002B;
INT_EXCEL_ID_CONTINUE = $003C;
INT_EXCEL_ID_WINDOW1 = $003D;
INT_EXCEL_ID_PANE = $0041;
@@ -33,6 +39,8 @@ const
{ RECORD IDs which did not change across version 3-8}
INT_EXCEL_ID_COLINFO = $007D; // does not exist in BIFF2
INT_EXCEL_ID_SHEETPR = $0081; // does not exist in BIFF2
+ INT_EXCEL_ID_HCENTER = $0083; // does not exist in BIFF2
+ INT_EXCEL_ID_VCENTER = $0084; // does not exist in BIFF2
INT_EXCEL_ID_COUNTRY = $008C; // does not exist in BIFF2
INT_EXCEL_ID_PALETTE = $0092; // does not exist in BIFF2
INT_EXCEL_ID_DIMENSIONS = $0200; // BIFF2: $0000
@@ -215,6 +223,100 @@ const
{ Index of last built-in XF format record }
LAST_BUILTIN_XF = 15;
+ PAPER_SIZES: array[0..90] of array[0..1] of Double = ( // Dimensions in mm
+ ( 0.0 , 0.0 ), // 0 - undefined
+ (2.54* 8.5 , 11.0 *2.54), // 1 - Letter
+ (2.54* 8.5 , 11.0 *2.54), // 2 - Letter small
+ (2.54* 11.0 , 17.0 *2.54), // 3 - Tabloid
+ (2.54* 17.0 , 11.0 *2.54), // 4 - Ledger
+ (2.54* 8.5 , 14.0 *2.54), // 5 - Legal
+ (2.54* 5.5 , 8.5 *2.54), // 6 - Statement
+ (2.54* 7.25 , 10.5 *2.54), // 7 - Executive
+ ( 297.0 , 420.0 ), // 8 - A3
+ ( 210.0 , 297.0 ), // 9 - A4
+ ( 210.0 , 297.0 ), // 10 - A4 small
+ ( 148.0 , 210.0 ), // 11 - A5
+ ( 257.0 , 364.0 ), // 12 - B4 (JIS)
+ ( 182.0 , 257.0 ), // 13 - B5 (JIS)
+ (2.54* 8.5 , 13.0 *2.54), // 14 - Folie
+ ( 215.0 , 275.0 ), // 15 - Quarto
+ (2.54* 10.0 , 14.0 *2.54), // 16 - 10x14
+ (2.54* 11.0 , 17.0 *2.54), // 17 - 11x17
+ (2.54* 8.5 , 11.0 *2.54), // 18 - Note
+ (2.54* 3.875, 8.875*2.54), // 19 - Envelope #9
+ (2.54* 4.125, 9.5 *2.54), // 20 - Envelope #10
+ (2.54* 4.5 , 10.375*2.54), // 21 - Envelope #11
+ (2.54* 4.75 , 11.0 *2.54), // 22 - Envelope #12
+ (2.54* 5.0 , 11.5 *2.54), // 23 - Envelope #14
+ (2.54* 17.0 , 22.0 *2.54), // 24 - C
+ (2.54* 22.0 , 34.0 *2.54), // 25 - D
+ (2.54* 34.0 , 44.0 *2.54), // 26 - E
+ ( 110.0 , 220.0 ), // 27 - Envelope DL
+ ( 162.0 , 229.0 ), // 28 - Envelope C5
+ ( 324.0 , 458.0 ), // 29 - Envelope C3
+ ( 229.0 , 324.0 ), // 30 - Envelope C4
+ ( 114.0 , 162.0 ), // 31 - Envelope C6
+ ( 114.0 , 229.0 ), // 32 - Envelope C6/C5
+ ( 250.0 , 353.0 ), // 33 - B4 (ISO)
+ ( 176.0 , 250.0 ), // 34 - B5 (ISO)
+ ( 125.0 , 176.0 ), // 35 - B6 (ISO)
+ ( 110.0 , 230.0 ), // 36 - Envelope Italy
+ (2.54* 3.875, 7.5 *2.54), // 37 - Envelope Monarch
+ (2.54* 3.625, 6.5 *2.54), // 38 - 6 3/4 Envelope
+ (2.54* 14.875, 11.0 *2.54), // 39 - US Standard Fanfold
+ (2.54* 8.5 , 12.0 *2.54), // 40 - German Std Fanfold
+ (2.54* 8.5 , 13.0 *2.54), // 41 - German Legal Fanfold
+ ( 250.0 , 353.0 ), // 42 - B4 (ISO)
+ ( 100.0 , 148.0 ), // 43 - Japanese Postcard
+ (2.54* 9.0 , 11.0 *2.54), // 44 - 9x11
+ (2.54* 10.0 , 11.0 *2.54), // 45 - 10x11
+ (2.54* 15.0 , 11.0 *2.54), // 46 - 15x11
+ ( 220.0 , 220.0 ), // 47 - Envelope Invite
+ ( 0.0 , 0.0 ), // 48 - undefined
+ ( 0.0 , 0.0 ), // 49 - undefined
+ (2.54* 9.5 , 11.0 *2.54), // 50 - Letter Extra
+ (2.54* 9.5 , 15.0 *2.54), // 51 - Legal Extra
+ (2.54* 11.6875, 18.0 *2.54), // 52 - Tabloid Extra
+ ( 235.0 , 322.0 ), // 53 - A4 Extra
+ (2.54* 8.5 , 11.0 *2.54), // 54 - Letter Transverse
+ ( 210.0 , 297.0 ), // 55 - A4 Transverse
+ (2.54* 9.5 , 11.0 *2.54), // 56 - Letter Extra Transverse
+ ( 227.0 , 356.0 ), // 57 - Super A/A4
+ ( 305.0 , 487.0 ), // 58 - Super B/B4
+ (2.54* 8.5 , 12.6875*2.54), // 59 - Letter plus
+ ( 210.0 , 330.0 ), // 60 - A4 plus
+ ( 148.0 , 210.0 ), // 61 - A5 transverse
+ ( 182.0 , 257.0 ), // 62 - B5 (JIS) transverse
+ ( 322.0 , 445.0 ), // 63 - A3 Extra
+ ( 174.0 , 235.0 ), // 64 - A5 Extra
+ ( 201.0 , 276.0 ), // 65 - B5 (ISO) Extra
+ ( 420.0 , 594.0 ), // 66 - A2
+ ( 297.0 , 420.0 ), // 67 - A3 Transverse
+ ( 322.0 , 445.0 ), // 68 - A3 Extra Transverse
+ ( 200.0 , 148.0 ), // 69 - Double Japanese Postcard
+ ( 105.0 , 148.0 ), // 70 - A6
+ ( 0.0 , 0.0 ), // 71 - undefined
+ ( 0.0 , 0.0 ), // 72 - undefined
+ ( 0.0 , 0.0 ), // 73 - undefined
+ ( 0.0 , 0.0 ), // 74 - undefined
+ (2.54* 11.0 , 8.5 *2.54), // 75 - Letter rotated
+ ( 420.0 , 297.0 ), // 76 - A3 rotated
+ ( 297.0 , 210.0 ), // 77 - A4 rotated
+ ( 210.0 , 148.0 ), // 78 - A5 rotated
+ ( 364.0 , 257.0 ), // 79 - B4 (JIS) rotated
+ ( 257.0 , 182.0 ), // 80 - B5 (JIS) rotated
+ ( 148.0 , 100.0 ), // 81 - Japanese Postcard rotated
+ ( 148.0 , 200.0 ), // 82 - Double Japanese Postcard rotated
+ ( 148.0 , 105.0 ), // 83 - A6 rotated
+ ( 0.0 , 0.0 ), // 84 - undefined
+ ( 0.0 , 0.0 ), // 85 - undefined
+ ( 0.0 , 0.0 ), // 86 - undefined
+ ( 0.0 , 0.0 ), // 87 - undefined
+ ( 128.0 , 182.0 ), // 88 - B6 (JIS)
+ ( 182.0 , 128.0 ), // 89 - B6 (JIS) rotated
+ (2.54* 12.0 , 11.0 *2.54) // 90 - 12x11
+ );
+
type
TDateMode=(dm1900,dm1904); //DATEMODE values, 5.28
@@ -263,6 +365,7 @@ type
// Read a blank cell
procedure ReadBlank(AStream: TStream); override;
procedure ReadBool(AStream: TStream); override;
+ procedure ReadBottomMargin(AStream: TStream);
procedure ReadCodePage(AStream: TStream);
// Read column info
procedure ReadColInfo(const AStream: TStream);
@@ -278,6 +381,8 @@ type
procedure ReadFormat(AStream: TStream); virtual;
// Read FORMULA record
procedure ReadFormula(AStream: TStream); override;
+ procedure ReadHCENTER(AStream: TStream);
+ procedure ReadLeftMargin(AStream: TStream);
// Read multiple blank cells
procedure ReadMulBlank(AStream: TStream);
// Read multiple RK cells
@@ -286,8 +391,13 @@ type
procedure ReadNumber(AStream: TStream); override;
// Read palette
procedure ReadPalette(AStream: TStream);
+ // Read page setup
+ procedure ReadPageSetup(AStream: TStream);
// Read PANE record
procedure ReadPane(AStream: TStream);
+ procedure ReadPrintGridLines(AStream: TStream);
+ procedure ReadPrintHeaders(AStream: TStream);
+ procedure ReadRightMargin(AStream: TStream);
// Read an RK value cell
procedure ReadRKValue(AStream: TStream);
// Read the row, column, and XF index at the current stream position
@@ -310,11 +420,13 @@ type
ASharedFormulaBase: PCell = nil): Boolean;
function ReadRPNTokenArraySize(AStream: TStream): word; virtual;
procedure ReadSharedFormula(AStream: TStream);
+ procedure ReadTopMargin(AStream: TStream);
// Helper function for reading a string with 8-bit length
function ReadString_8bitLen(AStream: TStream): String; virtual;
// Read STRING record (result of string formula)
procedure ReadStringRecord(AStream: TStream); virtual;
+ procedure ReadVCENTER(AStream: TStream);
// Read WINDOW2 record (gridlines, sheet headers)
procedure ReadWindow2(AStream: TStream); virtual;
@@ -335,6 +447,7 @@ type
function FixColor(AColor: TsColor): TsColor; override;
function GetLastRowIndex(AWorksheet: TsWorksheet): Integer;
function GetLastColIndex(AWorksheet: TsWorksheet): Word;
+ function GetPrintOptions: Word; virtual;
// Helper function for writing the BIFF header
procedure WriteBIFFHeader(AStream: TStream; ARecID, ARecSize: Word);
@@ -347,6 +460,8 @@ type
// Write out BOOLEAN cell record
procedure WriteBool(AStream: TStream; const ARow, ACol: Cardinal;
const AValue: Boolean; ACell: PCell); override;
+ // Writes out bottom page margin for printing
+ procedure WriteBottomMargin(AStream: TStream);
// Writes out used codepage for character encoding
procedure WriteCodePage(AStream: TStream; ACodePage: String); virtual;
// Writes out column info(s)
@@ -365,6 +480,9 @@ type
// Writes out a FORMULA record; formula is stored in cell already
procedure WriteFormula(AStream: TStream; const ARow, ACol: Cardinal;
ACell: PCell); override;
+ procedure WriteHCenter(AStream: TStream);
+ // Writes out left page margin for printing
+ procedure WriteLeftMargin(AStream: TStream);
// Writes out a FORMAT record
procedure WriteNumFormat(AStream: TStream; ANumFormatStr: String;
ANumFormatIndex: Integer); virtual;
@@ -379,6 +497,11 @@ type
// Writes out a PANE record
procedure WritePane(AStream: TStream; ASheet: TsWorksheet; IsBiff58: Boolean;
out ActivePane: Byte);
+ // Writes out whether grid lines are printed
+ procedure WritePrintGridLines(AStream: TStream);
+ procedure WritePrintHeaders(AStream: TStream);
+ // Writes out right page margin for printing
+ procedure WriteRightMargin(AStream: TStream);
// Writes out a ROW record
procedure WriteRow(AStream: TStream; ASheet: TsWorksheet;
ARowIndex, AFirstColIndex, ALastColIndex: Cardinal; ARow: PRow); virtual;
@@ -414,6 +537,9 @@ type
*)
procedure WriteSheetPR(AStream: TStream);
procedure WriteStringRecord(AStream: TStream; AString: String); virtual;
+ // Writes out the top page margin used when printing
+ procedure WriteTopMargin(AStream: TStream);
+ procedure WriteVCenter(AStream: TStream);
// Writes cell content received by workbook in OnNeedCellData event
procedure WriteVirtualCells(AStream: TStream);
// Writes out a WINDOW1 record
@@ -510,6 +636,7 @@ type
TextLen: Word;
end;
+
function ConvertExcelDateTimeToDateTime(const AExcelDateNum: Double;
ADateMode: TDateMode): TDateTime;
begin
@@ -851,6 +978,18 @@ begin
Workbook.OnReadCellData(Workbook, r, c, cell);
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
In BIFF8 it seams to always use the UTF-16 codepage
@@ -1141,6 +1280,30 @@ begin
Workbook.OnReadCellData(Workbook, ARow, ACol, cell);
end;
+{@@ ----------------------------------------------------------------------------
+ Reads whether the page is to be centered horizontally for printing
+-------------------------------------------------------------------------------}
+procedure TsSpreadBIFFReader.ReadHCENTER(AStream: TStream);
+var
+ w: word;
+begin
+ w := WordLEToN(AStream.ReadWord);
+ if w = 1 then Include(FWorksheet.PageLayout.Options, poHorCentered);
+end;
+
+
+{@@ ----------------------------------------------------------------------------
+ Reads the left page margin of the current worksheet (for printing).
+ The file value is in inches.
+-------------------------------------------------------------------------------}
+procedure TsSpreadBIFFReader.ReadLeftMargin(AStream: TStream);
+var
+ dbl: Double;
+begin
+ AStream.ReadBuffer(dbl, SizeOf(dbl));
+ FWorksheet.PageLayout.LeftMargin := InToMM(dbl);
+end;
+
{@@ ----------------------------------------------------------------------------
Reads multiple blank cell records
Valid for BIFF5 and BIFF8 (does not exist before)
@@ -1294,6 +1457,72 @@ begin
FPaletteFound := true;
end;
+{@@ ----------------------------------------------------------------------------
+ Reads the page setup record containing some parameters for printing
+-------------------------------------------------------------------------------}
+procedure TsSpreadBIFFReader.ReadPageSetup(AStream: TStream);
+var
+ w: Word;
+ dbl: Double;
+begin
+ // Paper size
+ w := WordLEToN(AStream.ReadWord);
+ if (w >= 0) and (w <= High(PAPER_SIZES)) then
+ begin
+ FWorksheet.PageLayout.PageWidth := PAPER_SIZES[w, 0];
+ FWorksheet.PageLayout.PageHeight := PAPER_SIZES[w, 1];
+ end;
+
+ // Scaling factor in percent
+ FWorksheet.PageLayout.ScalingFactor := WordLEToN(AStream.ReadWord);
+
+ // Start page number
+ FWorksheet.PageLayout.StartPageNumber := WordLEToN(AStream.ReadWord);
+
+ // Fit worksheet width to this number of pages (0 = use as many as neede)
+ FWorksheet.PageLayout.FitWidthToPages := WordLEToN(AStream.ReadWord);
+
+ // Fit worksheet height to this number of pages (0 = use as many as needed)
+ FWorksheet.PageLayout.FitHeightToPages := WordLEToN(AStream.ReadWord);
+
+ // 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);
+
+ // Print resolution in dpi -- ignoried
+ w := WordLEToN(AStream.ReadWord);
+
+ // Vertical print resolution in dpi -- ignored
+ w := WordLEToN(AStream.ReadWord);
+
+ // Header margin
+ AStream.ReadBuffer(dbl, SizeOf(dbl));
+ FWorksheet.PageLayout.HeaderMargin := InToMM(dbl);
+
+ // Footer margin
+ AStream.ReadBuffer(dbl, SizeOf(dbl));
+ FWorksheet.PageLayout.FooterMargin := InToMM(dbl);
+
+ // Number of copies
+ FWorksheet.PageLayout.Copies := WordLEToN(AStream.ReadWord);
+end;
+
{@@ ----------------------------------------------------------------------------
Reads pane sizes
Valid for all BIFF versions
@@ -1321,6 +1550,30 @@ begin
[9] 1 Not used (BIFF5-BIFF8 only, not written in BIFF2-BIFF4) }
end;
+{@@ ----------------------------------------------------------------------------
+ Reads whether the gridlines are printed or not
+-------------------------------------------------------------------------------}
+procedure TsSpreadBIFFReader.ReadPrintGridLines(AStream: TStream);
+var
+ w: Word;
+begin
+ w := WordLEToN(AStream.ReadWord);
+ if w = 1 then
+ Include(FWorksheet.PageLayout.Options, poPrintGridLines);
+end;
+
+{@@ ----------------------------------------------------------------------------
+ Reads whether the spreadsheet row/column headers are printed or not
+-------------------------------------------------------------------------------}
+procedure TsSpreadBIFFReader.ReadPrintHeaders(AStream: TStream);
+var
+ w: Word;
+begin
+ w := WordLEToN(AStream.ReadWord);
+ if w = 1 then
+ Include(FWorksheet.PageLayout.Options , poPrintHeaders);
+end;
+
{@@ ----------------------------------------------------------------------------
Reads the row, column and xf index
NOT VALID for BIFF2
@@ -1336,6 +1589,18 @@ begin
AXF := WordLEtoN(AStream.ReadWord);
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
Valid since BIFF3.
@@ -1799,6 +2064,29 @@ begin
Unused(AStream);
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
+-------------------------------------------------------------------------------}
+procedure TsSpreadBIFFReader.ReadVCENTER(AStream: TStream);
+var
+ w: word;
+begin
+ w := WordLEToN(AStream.ReadWord);
+ if w = 1 then Include(FWorksheet.PageLayout.Options, poVertCentered);
+end;
+
{@@ ----------------------------------------------------------------------------
Reads the WINDOW2 record containing information like "show grid lines",
"show sheet headers", "panes are frozen", etc.
@@ -1893,6 +2181,46 @@ begin
Result := AWorksheet.GetLastColIndex;
end;
+{@@ ----------------------------------------------------------------------------
+ Converts the Options of the worksheet's PageLayout to the bitmap required
+ by the PageSetup record
+ Is overridden by BIFF8 which uses more bits. Not used by BIFF2.
+-------------------------------------------------------------------------------}
+function TsSpreadBIFFWriter.GetPrintOptions: Word;
+begin
+ { Options:
+ Bit 0: 0 = Print pages in columns; 1 = Print pages in rows
+ Bit 1: 0 = Landscape; 1 = Portrait
+ Bit 2: 1 = Paper size, scaling factor, paper orientation (portrait/landscape),
+ print resolution and number of copies are not initialised
+ Bit 3: 0 = Print coloured; 1 = Print black and white
+ Bit 4: 0 = Default print quality; 1 = Draft quality
+ Bit 5: 0 = Do not print cell notes; 1 = Print cell notes
+ Bit 6: 0 = Use paper orientation (portrait/landscape) flag above
+ 1 = Use default paper orientation (landscape for chart sheets, portrait otherwise)
+ Bit 7: 0 = Automatic page numbers; 1 = Use start page number above
+
+ The following flags are valid for BIFF8 only:
+ Bit 9: 0 = Print notes as displayed; 1 = Print notes at end of sheet
+ Bit 11-10: 00 = Print errors as displayed; 1 = Do not print errors
+ 2 = Print errors as “--”; 3 = Print errors as “#N/A” }
+ Result := 0;
+ if poPrintPagesByRows in FWorksheet.PageLayout.Options then
+ Result := Result or $0001;
+ if FWorksheet.PageLayout.Orientation = spoPortrait then
+ Result := Result or $0002;
+ if poMonochrome in FWorksheet.PageLayout.Options then
+ Result := Result or $0008;
+ if poDraftQuality in FWorksheet.PageLayout.Options then
+ Result := Result or $0010;
+ if poPrintCellComments in FWorksheet.PageLayout.Options then
+ Result := Result or $0020;
+ if poDefaultOrientation in FWorksheet.PageLayout.Options then
+ Result := Result or $0040;
+ if poUseStartPageNumber in FWorksheet.PageLayout.Options then
+ Result := Result or $0080;
+end;
+
{@@ ----------------------------------------------------------------------------
Writes the BIFF record header consisting of the record ID and the size of
data to be written immediately afterwards.
@@ -1970,6 +2298,21 @@ begin
AStream.WriteBuffer(rec, SizeOf(rec));
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.
BIFF2 has to be overridden because is uses cp1252, but has a different
@@ -2192,6 +2535,21 @@ begin
AStream.WriteBuffer(rec, SizeOf(rec));
end;
+{@@ ----------------------------------------------------------------------------
+ Write the left margin of the printed page (in inches)
+-------------------------------------------------------------------------------}
+procedure TsSpreadBIFFWriter.WriteLeftMargin(AStream: TStream);
+var
+ dbl: double;
+begin
+ { BIFF record header }
+ WriteBIFFHeader(AStream, INT_EXCEL_ID_LEFTMARGIN, SizeOf(Double));
+
+ { Page margin value, written in inches }
+ dbl := mmToIn(FWorksheet.PageLayout.LeftMargin);
+ AStream.WriteBuffer(dbl, SizeOf(dbl));
+end;
+
{@@ ----------------------------------------------------------------------------
Writes a BIFF number format record defined in the specified format string
(in Excel dialect).
@@ -2245,6 +2603,22 @@ begin
SetLength(formula, 0);
end;
+{@@ ----------------------------------------------------------------------------
+ Writes an Excel HCENTER record which determines whether the page is to be
+ centered horizontally for printing
+-------------------------------------------------------------------------------}
+procedure TsSpreadBIFFWriter.WriteHCenter(AStream: TStream);
+var
+ w: Word;
+begin
+ { BIFF record header }
+ WriteBIFFHeader(AStream, INT_EXCEL_ID_HCENTER, SizeOf(w));
+
+ { Data }
+ if poHorCentered in FWorksheet.PageLayout.Options then w := 1 else w := 0;
+ AStream.WriteWord(WordToLE(w));
+end;
+
{@@ ----------------------------------------------------------------------------
Writes a 64-bit floating point NUMBER record.
Valid for BIFF5 and BIFF8 (BIFF2 has a different record structure).
@@ -2304,30 +2678,64 @@ end;
{@@ ----------------------------------------------------------------------------
Writes a PAGESETUP record containing information on printing
+ Valid for BIFF5-8
-------------------------------------------------------------------------------}
procedure TsSpreadBIFFWriter.WritePageSetup(AStream: TStream);
var
dbl: Double;
+ i: Integer;
+ w: Word;
begin
{ BIFF record header }
WriteBIFFHeader(AStream, INT_EXCEL_ID_PAGESETUP, 9*2 + 2*8);
{ Paper size }
- AStream.WriteWord(WordToLE(0)); // 1 = Letter, 9 = A4
+ w := 0;
+ for i:=0 to High(PAPER_SIZES) do
+ if (SameValue(PAPER_SIZES[i,0], FWorksheet.PageLayout.PageHeight) and
+ SameValue(PAPER_SIZES[i,1], FWorksheet.PageLayout.PageWidth))
+ or (SameValue(PAPER_SIZES[i,1], FWorksheet.PageLayout.PageHeight) and
+ SameValue(PAPER_SIZES[i,0], FWorksheet.PageLayout.PageWidth))
+ then begin
+ w := i;
+ break;
+ end;
+ AStream.WriteWord(WordToLE(w));
{ Scaling factor in percent }
- AStream.WriteWord(WordToLE(100)); // 100 %
+ w := Round(FWorksheet.PageLayout.ScalingFactor);
+ AStream.WriteWord(WordToLE(w));
{ Start page number }
- AStream.WriteWord(WordToLE(1)); // starting at page 1
+ w := FWorksheet.PageLayout.StartPageNumber;
+ AStream.WriteWord(WordToLE(w));
{ Fit worksheet width to this number of pages, 0 = use as many as needed }
- AStream.WriteWord(WordToLE(0));
+ w := FWorksheet.PageLayout.FitWidthToPages;
+ AStream.WriteWord(WordToLE(w));
{ Fit worksheet height to this number of pages, 0 = use as many as needed }
- AStream.WriteWord(WordToLE(0));
+ w := FWorksheet.PageLayout.FitHeightToPages;
+ AStream.WriteWord(WordToLE(w));
- AStream.WriteWord(WordToLE(0));
+ { Options:
+ Bit 0: 0 = Print pages in columns; 1 = Print pages in rows
+ Bit 1: 0 = Landscape; 1 = Portrait
+ Bit 2: 1 = Paper size, scaling factor, paper orientation (portrait/landscape),
+ print resolution and number of copies are not initialised
+ Bit 3: 0 = Print coloured; 1 = Print black and white
+ Bit 4: 0 = Default print quality; 1 = Draft quality
+ Bit 5: 0 = Do not print cell notes; 1 = Print cell notes
+ Bit 6: 0 = Use paper orientation (portrait/landscape) flag above
+ 1 = Use default paper orientation (landscape for chart sheets, portrait otherwise)
+ Bit 7: 0 = Automatic page numbers; 1 = Use start page number above
+
+ The following flags are valid for BIFF8 only:
+ Bit 9: 0 = Print notes as displayed; 1 = Print notes at end of sheet
+ Bit 11-10: 00 = Print errors as displayed; 1 = Do not print errors
+ 2 = Print errors as “--”; 3 = Print errors as “#N/A” }
+ w := GetPrintOptions;
+ AStream.WriteWord(WordToLE(w));
{ Print resolution in dpi }
AStream.WriteWord(WordToLE(600));
@@ -2336,13 +2744,16 @@ begin
AStream.WriteWord(WordToLE(600));
{ Header margin }
- dbl := 0.5;
+ dbl := mmToIn(FWorksheet.PageLayout.HeaderMargin);
AStream.WriteBuffer(dbl, SizeOf(dbl));
+
{ Footer margin }
+ dbl := mmToIn(FWorksheet.PageLayout.FooterMargin);
AStream.WriteBuffer(dbl, SizeOf(dbl));
{ Number of copies to print }
- AStream.WriteWord(WordToLE(1)); // 1 copy
+ w := FWorksheet.PageLayout.Copies;
+ AStream.WriteWord(WordToLE(w));
end;
{@@ ----------------------------------------------------------------------------
@@ -2418,6 +2829,36 @@ begin
{ Not used (BIFF5-BIFF8 only, not written in BIFF2-BIFF4 }
end;
+{@@ ----------------------------------------------------------------------------
+ Writes out whether grid lines are printed or not
+-------------------------------------------------------------------------------}
+procedure TsSpreadBIFFWriter.WritePrintGridLines(AStream: TStream);
+var
+ w: Word;
+begin
+ { Biff record header }
+ WriteBIFFHeader(AStream, INT_EXCEL_ID_PRINTGRID, SizeOf(w));
+
+ { Data }
+ if poPrintGridLines in FWorksheet.PageLayout.Options then w := 1 else w := 0;
+ AStream.WriteWord(WordToLE(w));
+end;
+
+{@@ ----------------------------------------------------------------------------
+ Writes out whether column and row headers are printed or not
+-------------------------------------------------------------------------------}
+procedure TsSpreadBIFFWriter.WritePrintHeaders(AStream: TStream);
+var
+ w: Word;
+begin
+ { Biff record header }
+ WriteBIFFHeader(AStream, INT_EXCEL_ID_PRINTHEADERS, SizeOf(w));
+
+ { Data }
+ if poPrintHeaders in FWorksheet.PageLayout.Options then w := 1 else w := 0;
+ AStream.WriteWord(WordToLE(w));
+end;
+
{@@ ----------------------------------------------------------------------------
Writes the address of a cell as used in an RPN formula and returns the
count of bytes written.
@@ -2426,7 +2867,7 @@ end;
function TsSpreadBIFFWriter.WriteRPNCellAddress(AStream: TStream;
ARow, ACol: Cardinal; AFlags: TsRelFlags): Word;
var
- r: Cardinal; // row index containing encoded relativ/absolute address info
+ r: Cardinal; // row index containing encoded relative/absolute address info
begin
// Encoded row address
r := ARow and MASK_EXCEL_ROW;
@@ -2813,6 +3254,22 @@ begin
AStream.WriteWord(WordToLE(ASize));
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
Valid for BIFF3-BIFF8
@@ -3106,6 +3563,38 @@ begin
Unused(AStream, AString);
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
+ centered vertically for printing
+-------------------------------------------------------------------------------}
+procedure TsSpreadBIFFWriter.WriteVCenter(AStream: TStream);
+var
+ w: Word;
+begin
+ { BIFF record header }
+ WriteBIFFHeader(AStream, INT_EXCEL_ID_VCENTER, SizeOf(w));
+
+ { Data }
+ if poVertCentered in FWorksheet.PageLayout.Options then w := 1 else w := 0;
+ AStream.WriteWord(WordToLE(w));
+end;
+
+
procedure TsSpreadBIFFWriter.WriteVirtualCells(AStream: TStream);
var
r,c: Cardinal;
diff --git a/components/fpspreadsheet/xlsxooxml.pas b/components/fpspreadsheet/xlsxooxml.pas
index 199595cfe..1db5356a7 100755
--- a/components/fpspreadsheet/xlsxooxml.pas
+++ b/components/fpspreadsheet/xlsxooxml.pas
@@ -79,6 +79,7 @@ type
procedure ReadNumFormats(ANode: TDOMNode);
procedure ReadPageMargins(ANode: TDOMNode; AWorksheet: TsWorksheet);
procedure ReadPalette(ANode: TDOMNode);
+ procedure ReadPrintOptions(ANode: TDOMNode; AWorksheet: TsWorksheet);
procedure ReadRowHeight(ANode: TDOMNode; AWorksheet: TsWorksheet);
procedure ReadSharedStrings(ANode: TDOMNode);
procedure ReadSheetFormatPr(ANode: TDOMNode; AWorksheet: TsWorksheet);
@@ -131,7 +132,10 @@ type
procedure WriteNumFormatList(AStream: TStream);
procedure WritePalette(AStream: TStream);
procedure WritePageMargins(AStream: TStream; AWorksheet: TsWorksheet);
+ procedure WritePageSetup(AStream: TStream; AWorksheet: TsWorksheet);
+ procedure WritePrintOptions(AStream: TStream; AWorksheet: TsWorksheet);
procedure WriteSheetData(AStream: TStream; AWorksheet: TsWorksheet);
+ procedure WriteSheetPr(AStream: TStream; AWorksheet: TsWorksheet);
procedure WriteSheetViews(AStream: TStream; AWorksheet: TsWorksheet);
procedure WriteStyleList(AStream: TStream; ANodeName: String);
procedure WriteVmlDrawings(AWorksheet: TsWorksheet);
@@ -1307,38 +1311,33 @@ procedure TsSpreadOOXMLReader.ReadPageMargins(ANode: TDOMNode;
AWorksheet: TsWorksheet);
var
s: String;
- layout: TsPageLayout;
begin
- if ANode = nil then
+ if (ANode = nil) or (AWorksheet = nil) then // just to make sure...
exit;
- layout := AWorksheet.PageLayout;
-
s := GetAttrValue(ANode, 'left');
if s <> '' then
- layout.LeftMargin := HtmlLengthStrToPts(s);
+ AWorksheet.PageLayout.LeftMargin := PtsToMM(HtmlLengthStrToPts(s, 'in'));
s := GetAttrValue(ANode, 'right');
if s <> '' then
- layout.RightMargin := HtmlLengthStrToPts(s);
+ AWorksheet.PageLayout.RightMargin := PtsToMM(HtmlLengthStrToPts(s, 'in'));
s := GetAttrValue(ANode, 'top');
if s <> '' then
- layout.TopMargin := HtmlLengthStrToPts(s);
+ AWorksheet.PageLayout.TopMargin := PtsToMM(HtmlLengthStrToPts(s, 'in'));
s := GetAttrValue(ANode, 'bottom');
if s <> '' then
- layout.BottomMargin := HtmlLengthStrToPts(s);
+ AWorksheet.PageLayout.BottomMargin := PtsToMM(HtmlLengthStrToPts(s, 'in'));
s := GetAttrValue(ANode, 'header');
if s <> '' then
- layout.HeaderDistance := HtmlLengthStrToPts(s);
+ AWorksheet.PageLayout.HeaderMargin := PtsToMM(HtmlLengthStrToPts(s, 'in'));
s := GetAttrValue(ANode, 'footer');
if s <> '' then
- layout.FooterDistance := HtmlLengthStrToPts(s);
-
- AWorksheet.PageLayout := layout;
+ AWorksheet.PageLayout.FooterMargin := PtsToMM(HtmlLengthStrToPts(s, 'in'));
end;
procedure TsSpreadOOXMLReader.ReadPalette(ANode: TDOMNode);
@@ -1385,6 +1384,22 @@ begin
end;
end;
+procedure TsSpreadOOXMLReader.ReadPrintOptions(ANode: TDOMNode;
+ AWorksheet: TsWorksheet);
+var
+ s: String;
+begin
+ if ANode = nil then
+ exit;
+ s := GetAttrValue(ANode, 'headings');
+ if (s = '1') then
+ Include(AWorksheet.PageLayout.Options, poPrintHeaders);
+
+ s := GetAttrValue(ANode, 'gridLines');
+ if (s = '1') then
+ Include(AWorksheet.PageLayout.Options, poPrintGridLines);
+end;
+
procedure TsSpreadOOXMLReader.ReadRowHeight(ANode: TDOMNode; AWorksheet: TsWorksheet);
var
s: String;
@@ -1709,6 +1724,7 @@ begin
ReadWorksheet(Doc.DocumentElement.FindNode('sheetData'), FWorksheet);
ReadMergedCells(Doc.DocumentElement.FindNode('mergeCells'), FWorksheet);
ReadHyperlinks(Doc.DocumentElement.FindNode('hyperlinks'));
+ ReadPrintOptions(Doc.DocumentElement.FindNode('printOptions'), FWorksheet);
ReadPageMargins(Doc.DocumentElement.FindNode('pageMargins'), FWorksheet);
FreeAndNil(Doc);
@@ -2309,12 +2325,87 @@ begin
with AWorksheet.PageLayout do
AppendToStream(AStream, Format(
'', [
- PtsToIn(LeftMargin), PtsToIn(RightMargin), PtsToIn(TopMargin), PtsToIn(BottomMargin),
- PtsToIn(HeaderDistance), PtsToIn(FooterDistance) ],
+ mmToIn(LeftMargin), mmToIn(RightMargin), mmToIn(TopMargin), mmToIn(BottomMargin),
+ mmToIn(HeaderMargin), mmToIn(FooterMargin) ],
FPointSeparatorSettings
));
end;
+procedure TsSpreadOOXMLWriter.WritePageSetup(AStream: TStream;
+ AWorksheet: TsWorksheet);
+var
+ s: String;
+ i: Integer;
+begin
+ s := '';
+
+ // Paper size
+ for i:=0 to High(PAPER_SIZES) do
+ if (SameValue(PAPER_SIZES[i,0], AWorksheet.PageLayout.PageHeight) and
+ SameValue(PAPER_SIZES[i,1], AWorksheet.PageLayout.PageWidth))
+ or (SameValue(PAPER_SIZES[i,1], AWorksheet.PageLayout.PageHeight) and
+ SameValue(PAPER_SIZES[i,0], AWorksheet.PageLayout.PageWidth))
+ then begin
+ s := Format('%s paperSize="%d"', [s, i]);
+ break;
+ end;
+
+ // Scaling factor
+ if AWorksheet.PageLayout.ScalingFactor <> 100 then
+ s := Format('%s scale="%.0f" fitToHeight="0" fitToWidth="0"', [
+ s, AWorksheet.PageLayout.ScalingFactor
+ ], FPointSeparatorSettings);
+
+ // Fit width pages
+ if AWorksheet.PageLayout.FitWidthToPages > 0 then
+ s := Format('%s fitToWidth="%d"', [s, AWorksheet.PageLayout.FitWidthToPages]);
+
+ // Fit height pages
+ if AWorksheet.PageLayout.FitHeightToPages > 0 then
+ s := Format('%s fitToHeight="%d"', [s, AWorksheet.PageLayout.FitHeightToPages]);
+
+ // Orientation
+ s := Format('%s orientation="%s"', [
+ s, IfThen(AWorksheet.PageLayout.Orientation = spoPortrait, 'portrait', 'landscape')
+ ]);
+
+ // First page number
+ if poUseStartPageNumber in FWorksheet.PageLayout.Options then
+ s := Format('%s useFirstPageNumber="%d"', [s, AWorksheet.PageLayout.StartPageNumber]);
+
+ // Print order
+ if poPrintPagesByRows in AWorksheet.PageLayout.Options then
+ s := s + ' pageOrder="overThenDown"';
+
+ // Monochrome
+ if poMonochrome in AWorksheet.PageLayout.Options then
+ s := s + ' blackAndWhite="1"';
+
+ // Quality
+ if poDraftQuality in AWOrksheet.PageLayout.Options then
+ s := s + ' draft="1"';
+
+ if s <> '' then
+ AppendToStream(AStream,
+ '');
+end;
+
+procedure TsSpreadOOXMLWriter.WritePrintOptions(AStream: TStream;
+ AWorksheet: TsWorksheet);
+var
+ s: String;
+begin
+ s := '';
+ if poPrintGridLines in AWorksheet.PageLayout.Options then
+ s := s + ' gridLines="1"';
+ if poPrintHeaders in AWorksheet.PageLayout.Options then
+ s := s + ' headings="1"';
+
+ if s <> '' then
+ AppendToStream(AStream,
+ '');
+end;
+
procedure TsSpreadOOXMLWriter.WriteSheetData(AStream: TStream;
AWorksheet: TsWorksheet);
var
@@ -2424,6 +2515,21 @@ begin
'');
end;
+procedure TsSpreadOOXMLWriter.WriteSheetPr(AStream: TStream; AWorksheet: TsWorksheet);
+var
+ s: String;
+begin
+ s := '';
+ if (AWorksheet.PageLayout.FitWidthToPages > 0) or
+ (AWorksheet.PageLayout.FitHeightToPages > 0) then
+ s := s + ' fitToPage="1"';
+ if s <> '' then s := '';
+
+ if s <> '' then
+ AppendToStream(AStream,
+ '' + s + '');
+end;
+
procedure TsSpreadOOXMLWriter.WriteSheetViews(AStream: TStream;
AWorksheet: TsWorksheet);
var
@@ -2936,13 +3042,16 @@ begin
AppendToStream(FSSheets[FCurSheetNum], Format(
'', [SCHEMAS_SPREADML, SCHEMAS_DOC_RELS]));
+ WriteSheetPr(FSSheets[FCurSheetNum], AWorksheet);
WriteDimension(FSSheets[FCurSheetNum], AWorksheet);
WriteSheetViews(FSSheets[FCurSheetNum], AWorksheet);
WriteCols(FSSheets[FCurSheetNum], AWorksheet);
WriteSheetData(FSSheets[FCurSheetNum], AWorksheet);
WriteHyperlinks(FSSheets[FCurSheetNum], AWorksheet);
WriteMergedCells(FSSheets[FCurSheetNum], AWorksheet);
+ WritePrintOptions(FSSheets[FCurSheetNum], AWorksheet);
WritePageMargins(FSSheets[FCurSheetNum], AWorksheet);
+ WritePageSetup(FSSheets[FCurSheetNum], AWorksheet);
// Footer
if AWorksheet.Comments.Count > 0 then