From 0e97c6bec0f6503ec856ff14999bef2fb667166e Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Mon, 22 Sep 2014 13:35:19 +0000 Subject: [PATCH] fpspreadsheet: Fix biff8 incorrectly reading non-contiguous shared formulas. Fix biff8 writing only contiguous shared formulas. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3594 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- components/fpspreadsheet/fpspreadsheet.pas | 15 +++++------ components/fpspreadsheet/xlsbiff8.pas | 2 +- components/fpspreadsheet/xlscommon.pas | 30 +++------------------- 3 files changed, 12 insertions(+), 35 deletions(-) diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index d8b4af859..92bfa8fc9 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -2885,6 +2885,9 @@ end; {@@ ---------------------------------------------------------------------------- Determines the cell block sharing the same formula which is used by a given cell + Note: the block may not be contiguous. The function returns the outer edges + of the range. + @param ACell Pointer to the cell being investigated @param ARow1 (output) Top row index of the shared formula block @param ACol1 (outout) Left column index of the shared formula block @@ -2912,21 +2915,17 @@ begin ACol1 := base^.Col; ACol2 := ACol1; // ... and go along first COLUMN to find the end of the shared formula block, ... - for c := ACol1+1 to GetLastColIndex do + for c := ACol1+1 to GetLastOccupiedColIndex do begin cell := FindCell(ARow1, c); - if (cell = nil) or (cell^.SharedFormulaBase <> base) then - break - else + if (cell <> nil) and (cell^.SharedFormulaBase = base) then ACol2 := c; end; // ... and go along first ROW to find the end of the shared formula block - for r := ARow1 + 1 to GetLastRowIndex do + for r := ARow1 + 1 to GetLastOccupiedRowIndex do begin cell := FindCell(r, ACol1); - if (cell = nil) or (cell^.SharedFormulaBase <> base) then - break - else + if (cell <> nil) and (cell^.SharedFormulaBase = base) then ARow2 := r; end; diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas index bc400cad9..c21fd5bc2 100755 --- a/components/fpspreadsheet/xlsbiff8.pas +++ b/components/fpspreadsheet/xlsbiff8.pas @@ -1024,7 +1024,7 @@ end; *******************************************************************} procedure TsSpreadBIFF8Writer.WriteStyle(AStream: TStream); begin - { BIFF Record header } + { BIFF record header } AStream.WriteWord(WordToLE(INT_EXCEL_ID_STYLE)); AStream.WriteWord(WordToLE(4)); diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas index 3327cfa78..3c4db063e 100644 --- a/components/fpspreadsheet/xlscommon.pas +++ b/components/fpspreadsheet/xlscommon.pas @@ -2769,38 +2769,16 @@ var begin RPNLength := 0; - // Determine cell range covered by the shared formula in ACell. - // Find range of cells using this shared formula - r1 := ACell^.Row; r2 := r1; - c1 := ACell^.Col; c2 := c1; - r := r1; - c := c1; - while c <= FWorksheet.GetLastColIndex do - begin - cell := FWorksheet.FindCell(r, c); - if (cell <> nil) and (cell^.SharedFormulaBase = ACell^.SharedFormulaBase) then - c2 := c - else - break; - inc(c); - end; - c := c1; - while r <= FWorksheet.GetLastRowIndex do - begin - cell := FWorksheet.FindCell(r, c); - if (cell <> nil) and (cell^.SharedFormulaBase = ACell^.SharedFormulaBase) then - r2 := r - else - break; - inc(r); - end; - // Write BIFF record ID and size AStream.WriteWord(WordToLE(INT_EXCEL_ID_SHAREDFMLA)); recordSizePos := AStream.Position; AStream.WriteWord(0); // This is the record size which is not yet known here startPos := AStream.Position; + // Determine (maximum) cell range covered by the shared formula in ACell. + // Note: it is possible that the range is not contiguous. + FWorksheet.FindSharedFormulaRange(ACell, r1, c1, r2, c2); + // Write borders of cell range covered by the formula WriteSharedFormulaRange(AStream, r1, c1, r2, c2);