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