From d2510c29615d3b02280dbac5f7747365ae7e8bf7 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Mon, 21 Sep 2015 16:03:41 +0000 Subject: [PATCH] fpspreadsheet: Add PageLayout support to ExcelXML writer git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4348 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- components/fpspreadsheet/xlsxml.pas | 217 +++++++++++++++++----------- 1 file changed, 134 insertions(+), 83 deletions(-) diff --git a/components/fpspreadsheet/xlsxml.pas b/components/fpspreadsheet/xlsxml.pas index f0966e806..730296e72 100644 --- a/components/fpspreadsheet/xlsxml.pas +++ b/components/fpspreadsheet/xlsxml.pas @@ -4,7 +4,7 @@ Unit : xlsxml Implements a reader and writer for the SpreadsheetXML format. This document was introduced by Microsoft for Excel XP and 2003. -REFERENCE: https://msdn.microsoft.com/en-us/library/aa140066%28v=office.15%29.aspx +REFERENCE: http://msdn.microsoft.com/en-us/library/aa140066%28v=office.15%29.aspx AUTHOR : Werner Pamler @@ -39,11 +39,12 @@ type function GetIndexStr(AIndex: Integer): String; function GetMergeStr(ACell: PCell): String; function GetStyleStr(ACell: PCell): String; - procedure WriteCells(AStream: TStream; AWorksheet: TsWorksheet); procedure WriteExcelWorkbook(AStream: TStream); procedure WriteStyle(AStream: TStream; AIndex: Integer); procedure WriteStyles(AStream: TStream); + procedure WriteTable(AStream: TStream; AWorksheet: TsWorksheet); procedure WriteWorksheet(AStream: TStream; AWorksheet: TsWorksheet); + procedure WriteWorksheetOptions(AStream: TStream; AWorksheet: TsWorksheet); procedure WriteWorksheets(AStream: TStream); protected @@ -256,86 +257,6 @@ begin ])); end; -procedure TsSpreadExcelXMLWriter.WriteCells(AStream: TStream; AWorksheet: TsWorksheet); -var - c, c1, c2: Cardinal; - r, r1, r2: Cardinal; - cell: PCell; - rowheightStr: String; - colwidthStr: String; - defFnt: TsFont; - col: PCol; - row: PRow; - cw_fact, rh_fact: Double; -begin - defFnt := FWorkbook.GetDefaultFont; - cw_fact := defFnt.Size * 0.5; // ColWidthFactor = Approx width of "0" character in pts - rh_fact := defFnt.Size; // RowHeightFactor = Height of a single line - - r1 := 0; - c1 := 0; - r2 := AWorksheet.GetLastRowIndex; - c2 := AWorksheet.GetLastColIndex; - AppendToStream(AStream, TABLE_INDENT + Format( - '' + LF, - [ - AWorksheet.GetLastColIndex + 1, AWorksheet.GetLastRowIndex + 1, - FWorksheet.DefaultColWidth * cw_fact, - (FWorksheet.DefaultRowHeight + ROW_HEIGHT_CORRECTION) * rh_fact - ], - FPointSeparatorSettings - )); - - for c := c1 to c2 do - begin - col := FWorksheet.FindCol(c); - // column width in the worksheet is in multiples of the "0" character width. - // In the xml file, it is needed in pts. - if Assigned(col) then - colwidthStr := Format(' ss:Width="%0.2f"', - [col^.Width * cw_fact], - FPointSeparatorSettings) - else - colwidthStr := ''; - AppendToStream(AStream, COL_INDENT + Format( - '' + LF, [c+1, colWidthStr])); - end; - - for r := r1 to r2 do - begin - row := FWorksheet.FindRow(r); - // Row height in the worksheet is in multiples of the default font height - // In the xml file, it is needed in pts. - if Assigned(row) then - rowheightStr := Format(' ss:Height="%.2f"', - [(row^.Height + ROW_HEIGHT_CORRECTION) * rh_fact], - FPointSeparatorSettings - ) - else - rowheightStr := ''; - AppendToStream(AStream, ROW_INDENT + Format( - '' + LF, [rowheightStr])); - for c := c1 to c2 do - begin - cell := AWorksheet.FindCell(r, c); - if cell <> nil then - begin - if FWorksheet.IsMerged(cell) and not FWorksheet.IsMergeBase(cell) then - Continue; - WriteCellToStream(AStream, cell); - end; - end; - AppendToStream(AStream, ROW_INDENT + - '' + LF); - end; - - AppendToStream(AStream, TABLE_INDENT + - '
' + LF); -end; - procedure TsSpreadExcelXMLWriter.WriteCellToStream(AStream: TStream; ACell: PCell); begin case ACell^.ContentType of @@ -651,6 +572,86 @@ begin '' + LF); end; +procedure TsSpreadExcelXMLWriter.WriteTable(AStream: TStream; AWorksheet: TsWorksheet); +var + c, c1, c2: Cardinal; + r, r1, r2: Cardinal; + cell: PCell; + rowheightStr: String; + colwidthStr: String; + defFnt: TsFont; + col: PCol; + row: PRow; + cw_fact, rh_fact: Double; +begin + defFnt := FWorkbook.GetDefaultFont; + cw_fact := defFnt.Size * 0.5; // ColWidthFactor = Approx width of "0" character in pts + rh_fact := defFnt.Size; // RowHeightFactor = Height of a single line + + r1 := 0; + c1 := 0; + r2 := AWorksheet.GetLastRowIndex; + c2 := AWorksheet.GetLastColIndex; + AppendToStream(AStream, TABLE_INDENT + Format( + '' + LF, + [ + AWorksheet.GetLastColIndex + 1, AWorksheet.GetLastRowIndex + 1, + FWorksheet.DefaultColWidth * cw_fact, + (FWorksheet.DefaultRowHeight + ROW_HEIGHT_CORRECTION) * rh_fact + ], + FPointSeparatorSettings + )); + + for c := c1 to c2 do + begin + col := FWorksheet.FindCol(c); + // column width in the worksheet is in multiples of the "0" character width. + // In the xml file, it is needed in pts. + if Assigned(col) then + colwidthStr := Format(' ss:Width="%0.2f"', + [col^.Width * cw_fact], + FPointSeparatorSettings) + else + colwidthStr := ''; + AppendToStream(AStream, COL_INDENT + Format( + '' + LF, [c+1, colWidthStr])); + end; + + for r := r1 to r2 do + begin + row := FWorksheet.FindRow(r); + // Row height in the worksheet is in multiples of the default font height + // In the xml file, it is needed in pts. + if Assigned(row) then + rowheightStr := Format(' ss:Height="%.2f"', + [(row^.Height + ROW_HEIGHT_CORRECTION) * rh_fact], + FPointSeparatorSettings + ) + else + rowheightStr := ''; + AppendToStream(AStream, ROW_INDENT + Format( + '' + LF, [rowheightStr])); + for c := c1 to c2 do + begin + cell := AWorksheet.FindCell(r, c); + if cell <> nil then + begin + if FWorksheet.IsMerged(cell) and not FWorksheet.IsMergeBase(cell) then + Continue; + WriteCellToStream(AStream, cell); + end; + end; + AppendToStream(AStream, ROW_INDENT + + '' + LF); + end; + + AppendToStream(AStream, TABLE_INDENT + + '
' + LF); +end; + {@@ ---------------------------------------------------------------------------- Writes an ExcelXML document to the file -------------------------------------------------------------------------------} @@ -706,12 +707,62 @@ begin FWorksheet := AWorksheet; AppendToStream(AStream, Format( ' ' + LF, [AWorksheet.Name]) ); - WriteCells(AStream, AWorksheet); + WriteTable(AStream, AWorksheet); + WriteWorksheetOptions(AStream, AWorksheet); AppendToStream(AStream, ' ' + LF ); end; +procedure TsSpreadExcelXMLWriter.WriteWorksheetOptions(AStream: TStream; + AWorksheet: TsWorksheet); +const + ORIENTATION_NAME: Array[TsPageOrientation] of string = ('Portrait', 'Landscape'); +var + footerStr, headerStr: String; + hcenterStr, vcenterStr: String; + startpageStr: String; +begin + if (AWorksheet.PageLayout.Headers[HEADER_FOOTER_INDEX_ALL] <> '') then + headerStr := ' x:Data="' + UTF8TextToXMLText(AWorksheet.PageLayout.Headers[HEADER_FOOTER_INDEX_ALL]) + '"' else + headerStr := ''; + + if (AWorksheet.PageLayout.Footers[HEADER_FOOTER_INDEX_ALL] <> '') then + footerStr := ' x:Data="' + UTF8TextToXMLText(AWorksheet.PageLayout.Footers[HEADER_FOOTER_INDEX_ALL]) + '"' else + footerStr := ''; + + if (poHorCentered in AWorksheet.PageLayout.Options) then + hcenterStr := ' x:CenterHorizontal="1"' else + hcenterStr := ''; + + if (poVertCentered in AWorksheet.PageLayout.Options) then + vcenterStr := ' x:CenterVertical="1"' else + vcenterStr := ''; + + if (poUseStartPageNumber in AWorksheet.PageLayout.Options) then + startpageStr := ' x:StartPageNumber="' + IntToStr(AWorksheet.PageLayout.StartPageNumber) + '"' else + startpageStr := ''; + + + AppendToStream(AStream, INDENT2 + Format( + '' + LF + INDENT3 + + '' + LF + INDENT4 + + '' + LF + INDENT4 + + '
' + LF + INDENT4 + + '