From 2b601f687c45749d60eceb13273ff338cc52ee35 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Mon, 5 May 2014 23:05:08 +0000 Subject: [PATCH] fpspreadsheet: Write SELECTION records (but does not fix BIFF2 frozen col/row issue). Fix issue of BIFFExplorer with BIFF2 PANE records. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3011 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../examples/excel2demo/excel2write.lpr | 8 +- .../reference/BIFFExplorer/bebiffgrid.pas | 4 +- components/fpspreadsheet/xlsbiff2.pas | 1 + components/fpspreadsheet/xlscommon.pas | 85 ++++++++++++++++++- 4 files changed, 90 insertions(+), 8 deletions(-) diff --git a/components/fpspreadsheet/examples/excel2demo/excel2write.lpr b/components/fpspreadsheet/examples/excel2demo/excel2write.lpr index 7b506f7ca..9f6f595c7 100644 --- a/components/fpspreadsheet/examples/excel2demo/excel2write.lpr +++ b/components/fpspreadsheet/examples/excel2demo/excel2write.lpr @@ -34,11 +34,11 @@ begin // Turn off grid lines and hide headers MyWorksheet.Options := MyWorksheet.Options - [soShowGridLines, soShowHeaders]; - { -- currently not working - MyWorksheet.Options := MyWorksheet.Options + [soHasFrozenPanes]; +{ -- currently not working + //MyWorksheet.Options := MyWorksheet.Options + [soHasFrozenPanes]; MyWorksheet.LeftPaneWidth := 1; - MyWorksheet.TopPaneHeight := 2; - } + MyWorksheet.TopPaneHeight := 3; +} // Write some number cells MyWorksheet.WriteNumber(0, 0, 1.0); diff --git a/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas b/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas index f0b1e3574..9786f97ef 100644 --- a/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas +++ b/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas @@ -3179,6 +3179,7 @@ var dw : DWord; begin if FFormat = sfExcel2 then begin + RowCount := FixedRows + 9; numBytes := 1; b := FBuffer[FBufferIndex]; ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(b), @@ -3187,9 +3188,6 @@ begin ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(b), '0 = Do not show grid lines; 1 = Show grid lines'); b := FBuffer[FBufferIndex]; - ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(b), - '0 = Do not show grid lines; 1 = Show grid lines'); - b := FBuffer[FBufferIndex]; ShowInRow(FCurrRow, FBufferIndex, numbytes, IntToStr(b), '0 = Do not show sheet headers; 1 = Show sheet headers'); b := FBuffer[FBufferIndex]; diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas index 771933a60..d8c52dbcb 100755 --- a/components/fpspreadsheet/xlsbiff2.pas +++ b/components/fpspreadsheet/xlsbiff2.pas @@ -834,6 +834,7 @@ begin // { -- currently not working WriteWindow2(AStream, sheet); WritePane(AStream, sheet, false); // false for "is not BIFF5 or BIFF8" + WriteSelections(AStream, sheet); //} WriteEOF(AStream); end; diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas index 9fd416d10..3b164dcf9 100644 --- a/components/fpspreadsheet/xlscommon.pas +++ b/components/fpspreadsheet/xlscommon.pas @@ -16,6 +16,7 @@ uses const { RECORD IDs which didn't change across versions 2-8 } + INT_EXCEL_ID_SELECTION = $001D; INT_EXCEL_ID_FONT = $0031; INT_EXCEL_ID_PANE = $0041; INT_EXCEL_ID_CODEPAGE = $0042; @@ -424,6 +425,9 @@ type procedure WritePalette(AStream: TStream); // Writes out a PANE record procedure WritePane(AStream: TStream; ASheet: TsWorksheet; IsBiff58: Boolean); + // Writes out a SELECTION record + procedure WriteSelection(AStream: TStream; ASheet: TsWorksheet; APane: Byte); + procedure WriteSelections(AStream: TStream; ASheet: TsWorksheet); // Writes out a WINDOW1 record procedure WriteWindow1(AStream: TStream); virtual; // Writes the index of the XF record used in the given cell @@ -1381,7 +1385,11 @@ begin else AStream.WriteWord(WordToLE(0)); - { Identifier of pane with active cell cursor } + { Identifier of pane with active cell cursor + 0 = right-bottom + 1 = right-top + 2 = left-bottom + 3 = left-top } if (soHasFrozenPanes in ASheet.Options) then begin if (ASheet.LeftPaneWidth = 0) and (ASheet.TopPaneHeight = 0) then active_pane := 3 @@ -1402,6 +1410,81 @@ begin { Not used (BIFF5-BIFF8 only, not written in BIFF2-BIFF4 } end; +{ Writes an Excel 2-8 SELECTION record + Writes just reasonable default values + APane is 0..3 (see below) + Valid für BIFF2-BIFF8 } +procedure TsSpreadBIFFWriter.WriteSelection(AStream: TStream; + ASheet: TsWorksheet; APane: Byte); +var + activeCellRow, activeCellCol: Word; +begin + case APane of + 0: begin // right-bottom + activeCellRow := ASheet.TopPaneHeight; + activeCellCol := ASheet.LeftPaneWidth; + end; + 1: begin // right-top + activeCellRow := 0; + activeCellCol := ASheet.LeftPaneWidth; + end; + 2: begin // left-bottom + activeCellRow := ASheet.TopPaneHeight; + activeCellCol := 0; + end; + 3: begin // left-top + activeCellRow := 0; + activeCellCol := 0; + end; + end; + + { BIFF record header } + AStream.WriteWord(WordToLE(INT_EXCEL_ID_SELECTION)); + AStream.WriteWord(WordToLE(15)); + + { Pane identifier } + AStream.WriteByte(APane); + + { Index to row of the active cell } + AStream.WriteWord(WordToLE(activeCellRow)); + + { Index to column of the active cell } + AStream.WriteWord(WordToLE(activeCellCol)); + + { Index into the following cell range list to the entry that contains the active cell } + AStream.WriteWord(WordToLE(0)); // there's only 1 item + + { Cell range array } + + { Count of items } + AStream.WriteWord(WordToLE(1)); // only 1 item + + { Index to first and last row - are the same here } + + AStream.WriteWord(WordTOLE(activeCellRow)); + AStream.WriteWord(WordTOLE(activeCellRow)); + + { Index to first and last column - they are the same here again. } + { Note: BIFF8 writes bytes here! } + AStream.WriteByte(activeCellCol); + AStream.WriteByte(activeCellCol); +end; + +procedure TsSpreadBIFFWriter.WriteSelections(AStream: TStream; + ASheet: TsWorksheet); +begin + WriteSelection(AStream, ASheet, 3); + if (ASheet.LeftPaneWidth = 0) then begin + if ASheet.TopPaneHeight > 0 then WriteSelection(AStream, ASheet, 2); + end else begin + WriteSelection(AStream, ASheet, 1); + if ASheet.TopPaneHeight > 0 then begin + WriteSelection(AStream, ASheet, 2); + WriteSelection(AStream, ASheet, 0); + end; + end; +end; + { Writes an Excel 5/8 WINDOW1 record This record contains general settings for the document window and global workbook settings.