From ff9deb89c20b6a39169b9cebfa7b2aa6dbd26eca Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Tue, 5 Jun 2018 23:34:16 +0000 Subject: [PATCH] fpspreadsheet: Fix pasting of multiselection from clipboard (was related to incorrect recordsize of BIFF SELECTION record). git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6468 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../fpspreadsheet/source/common/xlsbiff8.pas | 19 ++++++++++++ .../fpspreadsheet/source/common/xlscommon.pas | 29 ++++++++++++------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/components/fpspreadsheet/source/common/xlsbiff8.pas b/components/fpspreadsheet/source/common/xlsbiff8.pas index 74d1fd0c4..ca7ab742c 100644 --- a/components/fpspreadsheet/source/common/xlsbiff8.pas +++ b/components/fpspreadsheet/source/common/xlsbiff8.pas @@ -251,6 +251,7 @@ type AFlags: TsRelFlags): Word; override; function WriteRPNSheetIndex(AStream: TStream; ADocumentURL: String; ASheet1, ASheet2: Integer): Word; override; +// procedure WriteSelectionRange(AStream: TStream; ARange: TsCellRange); override; procedure WriteSST(AStream: TStream); function WriteString_8bitLen(AStream: TStream; AString: String): Integer; override; procedure WriteSTRINGRecord(AStream: TStream; AString: string); override; @@ -4242,6 +4243,24 @@ begin // If the procedure gets to this point the buffer has been written completely. Result := true; end; + (* +{@@ ---------------------------------------------------------------------------- + Writes a selection range as part of the SELECTION record. + Special BIFF8 version. +-------------------------------------------------------------------------------} +procedure TsSpreadBIFF8Writer.WriteSelectionRange(AStream: TStream; + ARange: TsCellRange); +begin + // Index to first and last row of this selected range + AStream.WriteWord(WordToLE(Word(ARange.Row1))); + AStream.WriteWord(WordToLE(Word(ARange.Row2))); + + // Index to first and last column of this selected range + // NOTE: The BIFF8 specification uses only a byte here for the value (256 cols) + // but writes 2 bytes! + AStream.WriteWord(WordToLE(Byte(ARange.Col1))); + AStream.WriteWord(WordToLE(Byte(ARange.Col2))); +end; *) {@@ ---------------------------------------------------------------------------- Writes the SharedStringTable (SST) to the stream diff --git a/components/fpspreadsheet/source/common/xlscommon.pas b/components/fpspreadsheet/source/common/xlscommon.pas index ef3818065..6680a5b8f 100644 --- a/components/fpspreadsheet/source/common/xlscommon.pas +++ b/components/fpspreadsheet/source/common/xlscommon.pas @@ -5247,7 +5247,7 @@ procedure TsSpreadBIFFWriter.WriteSELECTION(AStream: TStream; ASheet: TsBasicWorksheet; APane: Byte); var activeCellRow, activeCellCol: Word; - i, n: Integer; + i, n, recsize: Integer; sel: TsCellRange; book: TsWorkbook; sheet: TsWorksheet; @@ -5279,8 +5279,16 @@ begin end; end; + n := sheet.GetSelectionCount; + { BIFF record header } - WriteBIFFHeader(AStream, INT_EXCEL_ID_SELECTION, 15); + recsize := 1 + { pane } + 2 + 2 + { active cell row/col } + 2 + { index of active cell in range list } + 2 + { Count of selections } + Max(1, n) * 6; { 2 word for rows and 2 bytes for cols } + + WriteBIFFHeader(AStream, INT_EXCEL_ID_SELECTION, recsize); { Pane identifier } AStream.WriteByte(APane); @@ -5304,10 +5312,11 @@ begin // Count of cell ranges AStream.WriteWord(WordToLE(1)); // Index to first and last row - are the same here - AStream.WriteWord(WordTOLE(activeCellRow)); - AStream.WriteWord(WordTOLE(activeCellRow)); + 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! This is ok because BIFF supports only 256 columns + // NOTE: excelfileformat.pdf is WRONG here! AStream.WriteByte(activeCellCol); AStream.WriteByte(activeCellCol); end else @@ -5316,16 +5325,14 @@ begin // Count of cell ranges AStream.WriteWord(WordToLE(n)); // Write each selected cell range - for i := 0 to n-1 do - begin + for i := 0 to n-1 do begin sel := sheet.GetSelection[i]; // Index to first and last row of this selected range - AStream.WriteWord(WordToLE(sel.Row1)); - AStream.WriteWord(WordToLE(sel.Row2)); + AStream.WriteWord(WordToLE(word(sel.Row1))); + AStream.WriteWord(WordToLE(word(sel.Row2))); // Index to first and last column - // Note: Even BIFF8 writes bytes here! This is ok because BIFF supports only 256 columns - AStream.WriteByte(sel.Col1); - AStream.WriteByte(sel.Col2); + AStream.WriteByte(byte(sel.Col1)); + AStream.WriteByte(byte(sel.Col2)); end; end; end;