diff --git a/components/fpspreadsheet/reference/BIFFExplorer/BIFFExplorer.lpi b/components/fpspreadsheet/reference/BIFFExplorer/BIFFExplorer.lpi index 011054dc2..ae8bd0e7a 100644 --- a/components/fpspreadsheet/reference/BIFFExplorer/BIFFExplorer.lpi +++ b/components/fpspreadsheet/reference/BIFFExplorer/BIFFExplorer.lpi @@ -164,7 +164,6 @@ - diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas index d58ad14e9..df0f19238 100755 --- a/components/fpspreadsheet/xlsbiff5.pas +++ b/components/fpspreadsheet/xlsbiff5.pas @@ -119,7 +119,6 @@ type procedure WriteIndex(AStream: TStream); procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal; const AValue: string; ACell: PCell); override; - procedure WriteSharedFormulaRange(AStream: TStream; const ARange: TRect); override; procedure WriteStringRecord(AStream: TStream; AString: String); override; procedure WriteStyle(AStream: TStream); procedure WriteWindow2(AStream: TStream; ASheet: TsWorksheet); @@ -380,7 +379,6 @@ var CurrentPos: Int64; Boundsheets: array of Int64; i, len: Integer; - sheet : TsWorksheet; pane: Byte; begin { Store some data about the workbook that other routines need } @@ -414,7 +412,7 @@ begin for i := 0 to Workbook.GetWorksheetCount - 1 do begin - sheet := Workbook.GetWorksheetByIndex(i); + FWorksheet := Workbook.GetWorksheetByIndex(i); { First goes back and writes the position of the BOF of the sheet on the respective BOUNDSHEET record } @@ -427,18 +425,18 @@ begin WriteIndex(AStream); // WritePageSetup(AStream); - WriteColInfos(AStream, sheet); - WriteDimensions(AStream, sheet); - WriteWindow2(AStream, sheet); - WritePane(AStream, sheet, true, pane); // true for "is BIFF5 or BIFF8" - WriteSelection(AStream, sheet, pane); + WriteColInfos(AStream, FWorksheet); + WriteDimensions(AStream, FWorksheet); + WriteWindow2(AStream, FWorksheet); + WritePane(AStream, FWorksheet, true, pane); // true for "is BIFF5 or BIFF8" + WriteSelection(AStream, FWorksheet, pane); //WriteRows(AStream, sheet); if (boVirtualMode in Workbook.Options) then WriteVirtualCells(AStream) else begin - WriteRows(AStream, sheet); - WriteCellsToStream(AStream, sheet.Cells); + WriteRows(AStream, FWorksheet); + WriteCellsToStream(AStream, FWorksheet.Cells); end; WriteEOF(AStream); @@ -838,18 +836,6 @@ begin SetLength(buf, 0); end; -{ Writes the borders of the cell range covered by a shared formula. - Needs to be overridden to write the column data (2 bytes in case of BIFF8). } -procedure TsSpreadBIFF5Writer.WriteSharedFormulaRange(AStream: TStream; - const ARange: TRect); -begin - inherited WriteSharedFormulaRange(AStream, ARange); - // Index to first column - AStream.WriteByte(ARange.Left); - // Index to last rcolumn - AStream.WriteByte(ARange.Right); -end; - { Writes an Excel 5 STRING record which immediately follows a FORMULA record when the formula result is a string. BIFF5 writes a byte-string, but uses a 16-bit length here! } diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas index d28ba11f9..37f640c62 100755 --- a/components/fpspreadsheet/xlsbiff8.pas +++ b/components/fpspreadsheet/xlsbiff8.pas @@ -127,7 +127,7 @@ type AFlags: TsRelFlags): Word; override; function WriteRPNCellRangeAddress(AStream: TStream; ARow1, ACol1, ARow2, ACol2: Cardinal; AFlags: TsRelFlags): Word; override; - procedure WriteSharedFormulaRange(AStream: TStream; const ARange: TRect); override; +// procedure WriteSharedFormulaRange(AStream: TStream; const ARange: TRect); override; function WriteString_8bitLen(AStream: TStream; AString: String): Integer; override; procedure WriteStringRecord(AStream: TStream; AString: string); override; procedure WriteStyle(AStream: TStream); @@ -435,7 +435,6 @@ const var CurrentPos: Int64; Boundsheets: array of Int64; - sheet: TsWorksheet; i, len: Integer; pane: Byte; begin @@ -465,8 +464,7 @@ begin for i := 0 to Workbook.GetWorksheetCount - 1 do begin - sheet := Workbook.GetWorksheetByIndex(i); - FWorksheet := sheet; + FWorksheet := Workbook.GetWorksheetByIndex(i); { First goes back and writes the position of the BOF of the sheet on the respective BOUNDSHEET record } @@ -479,20 +477,20 @@ begin WriteIndex(AStream); //WriteSheetPR(AStream); // WritePageSetup(AStream); - WriteColInfos(AStream, sheet); - WriteDimensions(AStream, sheet); + WriteColInfos(AStream, FWorksheet); + WriteDimensions(AStream, FWorksheet); //WriteRowAndCellBlock(AStream, sheet); if (boVirtualMode in Workbook.Options) then WriteVirtualCells(AStream) else begin - WriteRows(AStream, sheet); - WriteCellsToStream(AStream, sheet.Cells); + WriteRows(AStream, FWorksheet); + WriteCellsToStream(AStream, FWorksheet.Cells); end; - WriteWindow2(AStream, sheet); - WritePane(AStream, sheet, isBIFF8, pane); - WriteSelection(AStream, sheet, pane); + WriteWindow2(AStream, FWorksheet); + WritePane(AStream, FWorksheet, isBIFF8, pane); + WriteSelection(AStream, FWorksheet, pane); WriteEOF(AStream); end; @@ -800,13 +798,15 @@ end; function TsSpreadBIFF8Writer.WriteRPNCellOffset(AStream: TStream; ARowOffset, AColOffset: Integer; AFlags: TsRelFlags): Word; var - c: Word; + c: word; + r: SmallInt; begin // row address - AStream.WriteWord(WordToLE(Word(Lo(ARowOffset)))); + r := SmallInt(ARowOffset); + AStream.WriteWord(WordToLE(Word(r))); // Encoded column address - c := word(Lo(AColOffset)) and MASK_EXCEL_COL_BITS_BIFF8; + c := word(SmallInt(AColOffset)) and MASK_EXCEL_COL_BITS_BIFF8; if (rfRelRow in AFlags) then c := c or MASK_EXCEL_RELATIVE_ROW_BIFF8; if (rfRelCol in AFlags) then c := c or MASK_EXCEL_RELATIVE_COL_BIFF8; AStream.WriteWord(WordToLE(c)); @@ -836,18 +836,21 @@ begin Result := 8; end; - + (* { Writes the borders of the cell range covered by a shared formula. Needs to be overridden to write the column data (2 bytes in case of BIFF8). } procedure TsSpreadBIFF8Writer.WriteSharedFormulaRange(AStream: TStream; const ARange: TRect); begin inherited WriteSharedFormulaRange(AStream, ARange); + { // Index to first column AStream.WriteWord(WordToLE(ARange.Left)); // Index to last rcolumn AStream.WriteWord(WordToLE(ARange.Right)); + } end; +*) { Helper function for writing a string with 8-bit length. Overridden version for BIFF8. Called for writing rpn formula string tokens. diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas index e8ec2c955..e35f62069 100644 --- a/components/fpspreadsheet/xlscommon.pas +++ b/components/fpspreadsheet/xlscommon.pas @@ -2555,13 +2555,13 @@ end; { Is called from WriteRPNFormula in the case that the cell uses a shared formula and writes the token "array" pointing to the shared formula base. - This implementation is valid for BIFF5 and BIFF8. BIFF2 does not support - shared formulas; the BIFF2 writer must copy the formula found in the + This implementation is valid for BIFF3-BIFF8. BIFF2 is different, but does not + support shared formulas; the BIFF2 writer must copy the formula found in the SharedFormulaBase field of the cell and adjust the relative references. } procedure TsSpreadBIFFWriter.WriteRPNSharedFormulaLink(AStream: TStream; ACell: PCell; var RPNLength: Word); type - TSharedFormulaLinkRecord = record + TSharedFormulaLinkRecord = packed record FormulaSize: Word; // Size of token array Token: Byte; // 1st (and only) token of the rpn formula array Row: Word; // row of cell containing the shared formula @@ -2570,6 +2570,7 @@ type var rec: TSharedFormulaLinkRecord; begin + FillChar(rec, SizeOf(rec), 0); rec.FormulaSize := WordToLE(5); rec.Token := INT_EXCEL_TOKEN_TEXP; // Marks the cell for using a shared formula rec.Row := WordToLE(ACell^.SharedFormulaBase.Row); @@ -2636,7 +2637,7 @@ begin begin n := WriteRPNCellOffset( AStream, - AFormula[i].Row, AFormula[i].Col, + integer(AFormula[i].Row), integer(AFormula[i].Col), AFormula[i].RelFlags ); inc(RPNLength, n); @@ -2928,6 +2929,12 @@ begin // Write borders of cell range covered by the formula WriteSharedFormulaRange(AStream, range); + // Not used + AStream.WriteByte(0); + + // Number of existing formula records + AStream.WriteByte((range.Right-range.Left+1)*(range.Bottom-range.Top+1)); + // Copy the formula (we don't want to overwrite the cell formulas) // and adjust relative references SetLength(formula, Length(ACell^.SharedFormulaBase^.RPNFormulaValue)); @@ -2936,7 +2943,7 @@ begin FixRelativeReferences(ACell, formula[i]); end; // Writes the (copied) rpn token array - WriteRPNTokenArray(AStream, formula, false, RPNLength); + WriteRPNTokenArray(AStream, formula, true, RPNLength); { Write record size at the end after we known it } finalPos := AStream.Position; @@ -2946,9 +2953,8 @@ begin end; { Writes the borders of the cell range covered by a shared formula. - Needs to be overridden by BIFF5 and BIFF8 to write the column data - (1 byte in BIFF5, 2 bytes in BIFF8). No need for BIFF2 which does not - support shared formulas. } + Valid for BIFF5 and BIFF8 - BIFF8 writes 8-bit column index as well. + No need for BIFF2 which does not support shared formulas. } procedure TsSpreadBIFFWriter.WriteSharedFormulaRange(AStream: TStream; const ARange: TRect); begin @@ -2956,8 +2962,10 @@ begin AStream.WriteWord(WordToLE(ARange.Top)); // Index to last row AStream.WriteWord(WordToLE(ARange.Bottom)); - - // column indexes follow in overridden procedure! + // Index to first column + AStream.WriteByte(Lo(ARange.Left)); + // Index to last rcolumn + AStream.WriteByte(Lo(ARange.Right)); end;