diff --git a/components/fpspreadsheet/examples/excel5demo/excel5write.lpi b/components/fpspreadsheet/examples/excel5demo/excel5write.lpi
index eb6ea9847..c2e02c20b 100644
--- a/components/fpspreadsheet/examples/excel5demo/excel5write.lpi
+++ b/components/fpspreadsheet/examples/excel5demo/excel5write.lpi
@@ -11,7 +11,7 @@
-
+
@@ -38,8 +38,8 @@
-
-
+
+
@@ -68,8 +68,8 @@
-
-
+
+
@@ -86,8 +86,8 @@
-
-
+
+
@@ -116,8 +116,8 @@
-
-
+
+
@@ -150,123 +150,123 @@
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
-
+
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/components/fpspreadsheet/examples/excel5demo/excel5write.lpr b/components/fpspreadsheet/examples/excel5demo/excel5write.lpr
index db6d9426b..71d8e02a4 100644
--- a/components/fpspreadsheet/examples/excel5demo/excel5write.lpr
+++ b/components/fpspreadsheet/examples/excel5demo/excel5write.lpr
@@ -16,7 +16,7 @@ uses
var
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
- MyFormula: TsFormula;
+ MyRPNFormula: TsRPNFormula;
MyDir: string;
i: Integer;
begin
@@ -45,8 +45,17 @@ begin
}
// Write the formula E1 = A1 + B1
-// MyFormula.FormulaStr := '';
-// MyWorksheet.WriteFormula(0, 4, MyFormula);
+ SetLength(MyRPNFormula, 3);
+ MyRPNFormula[0].ElementKind := fekCell;
+ MyRPNFormula[0].Col := 0;
+ MyRPNFormula[0].Row := 0;
+ MyRPNFormula[1].ElementKind := fekCell;
+ MyRPNFormula[1].Col := 1;
+ MyRPNFormula[1].Row := 0;
+ MyRPNFormula[2].ElementKind := fekAdd;
+ MyWorksheet.WriteRPNFormula(0, 4, MyRPNFormula);
+
+ //MyFormula.FormulaStr := '';
// Creates a new worksheet
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet 2');
diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas
index b1ffe73fa..800555874 100755
--- a/components/fpspreadsheet/fpspreadsheet.pas
+++ b/components/fpspreadsheet/fpspreadsheet.pas
@@ -49,24 +49,31 @@ type
TsFormulaElement = record
ElementKind: TFEKind;
- Row1, Row2: Word;
- Col1, Col2: Byte;
+ Row, Row2: Word; // zero-based
+ Col, Col2: Byte; // zero-based
DoubleValue: double;
end;
TsExpandedFormula = array of TsFormulaElement;
+ {@@ RPN formula. Similar to the expanded formula, but in RPN notation.
+ Simplifies the task of format writers which need RPN }
+
+ TsRPNFormula = array of TsFormulaElement;
+
{@@ Describes the type of content of a cell on a TsWorksheet }
- TCellContentType = (cctEmpty, cctFormula, cctNumber, cctUTF8String);
+ TCellContentType = (cctEmpty, cctFormula, cctRPNFormula, cctNumber, cctUTF8String);
{@@ Cell structure for TsWorksheet }
TCell = record
- Col: Byte;
- Row: Word;
+ Col: Byte; // zero-based
+ Row: Word; // zero-based
ContentType: TCellContentType;
+ { Possible values for the cells }
FormulaValue: TsFormula;
+ RPNFormulaValue: TsRPNFormula;
NumberValue: double;
UTF8StringValue: ansistring;
end;
@@ -101,6 +108,7 @@ type
procedure WriteUTF8Text(ARow, ACol: Cardinal; AText: ansistring);
procedure WriteNumber(ARow, ACol: Cardinal; ANumber: double);
procedure WriteFormula(ARow, ACol: Cardinal; AFormula: TsFormula);
+ procedure WriteRPNFormula(ARow, ACol: Cardinal; AFormula: TsRPNFormula);
end;
{ TsWorkbook }
@@ -165,7 +173,8 @@ type
procedure WriteToFile(AFileName: string; AData: TsWorkbook); virtual;
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); virtual;
{ Record writing methods }
- procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); virtual; abstract;
+ procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); virtual;
+ procedure WriteRPNFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsRPNFormula); virtual;
procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); virtual; abstract;
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); virtual; abstract;
end;
@@ -500,6 +509,17 @@ begin
ACell^.FormulaValue := AFormula;
end;
+procedure TsWorksheet.WriteRPNFormula(ARow, ACol: Cardinal;
+ AFormula: TsRPNFormula);
+var
+ ACell: PCell;
+begin
+ ACell := GetCell(ARow, ACol);
+
+ ACell^.ContentType := cctRPNFormula;
+ ACell^.RPNFormulaValue := AFormula;
+end;
+
{ TsWorkbook }
{@@
@@ -810,9 +830,10 @@ begin
AStream := TStream(arg);
case ACell.ContentType of
- cctFormula: WriteFormula(AStream, ACell^.Row, ACell^.Col, ACell^.FormulaValue);
cctNumber: WriteNumber(AStream, ACell^.Row, ACell^.Col, ACell^.NumberValue);
cctUTF8String: WriteLabel(AStream, ACell^.Row, ACell^.Col, ACell^.UTF8StringValue);
+ cctFormula: WriteFormula(AStream, ACell^.Row, ACell^.Col, ACell^.FormulaValue);
+ cctRPNFormula: WriteRPNFormula(AStream, ACell^.Row, ACell^.Col, ACell^.RPNFormulaValue);
end;
end;
@@ -861,6 +882,18 @@ begin
end;
+procedure TsCustomSpreadWriter.WriteFormula(AStream: TStream; const ARow,
+ ACol: Word; const AFormula: TsFormula);
+begin
+
+end;
+
+procedure TsCustomSpreadWriter.WriteRPNFormula(AStream: TStream; const ARow,
+ ACol: Word; const AFormula: TsRPNFormula);
+begin
+
+end;
+
finalization
SetLength(GsSpreadFormats, 0);
diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas
index 0aa06c860..bc824b75d 100755
--- a/components/fpspreadsheet/xlsbiff2.pas
+++ b/components/fpspreadsheet/xlsbiff2.pas
@@ -53,13 +53,15 @@ type
{ TsSpreadBIFF2Writer }
TsSpreadBIFF2Writer = class(TsCustomSpreadWriter)
+ private
+ function FEKindToExcelID(AElement: TFEKind): Byte;
public
{ General writing methods }
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); override;
{ Record writing methods }
procedure WriteBOF(AStream: TStream);
procedure WriteEOF(AStream: TStream);
- procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); override;
+ procedure WriteRPNFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsRPNFormula); override;
procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override;
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override;
end;
@@ -84,17 +86,6 @@ const
INT_EXCEL_CHART = $0020;
INT_EXCEL_MACRO_SHEET = $0040;
- { Types and constants for formulas }
-type
- TRPNItem = record
- TokenID: Byte;
- Col: Byte;
- Row: Word;
- DoubleValue: Double;
- end;
-
- TRPNFormula = array of TRPNItem;
-
const
{ TokenID values }
@@ -115,6 +106,17 @@ const
{ TsSpreadBIFF2Writer }
+function TsSpreadBIFF2Writer.FEKindToExcelID(AElement: TFEKind): Byte;
+begin
+ case AElement of
+ fekCell: Result := INT_EXCEL_TOKEN_TREFV;
+ fekAdd: Result := INT_EXCEL_TOKEN_TADD;
+ fekSub: Result := INT_EXCEL_TOKEN_TSUB;
+ fekDiv: Result := INT_EXCEL_TOKEN_TDIV;
+ fekMul: Result := INT_EXCEL_TOKEN_TMUL;
+ end;
+end;
+
{
Writes an Excel 2 file to a stream
@@ -176,15 +178,16 @@ end;
MyFormula[1].Row := 0;
MyFormula[2].TokenID := INT_EXCEL_TOKEN_TADD; +
}
-procedure TsSpreadBIFF2Writer.WriteFormula(AStream: TStream; const ARow,
- ACol: Word; const AFormula: TsFormula);
-{var
+procedure TsSpreadBIFF2Writer.WriteRPNFormula(AStream: TStream; const ARow,
+ ACol: Word; const AFormula: TsRPNFormula);
+var
FormulaResult: double;
i: Integer;
RPNLength: Word;
- TokenArraySizePos, RecordSizePos, FinalPos: Cardinal;}
+ TokenArraySizePos, RecordSizePos, FinalPos: Cardinal;
+ FormulaKind: Byte;
begin
-(* RPNLength := 0;
+ RPNLength := 0;
FormulaResult := 0.0;
{ BIFF Record header }
@@ -220,11 +223,12 @@ begin
for i := 0 to Length(AFormula) - 1 do
begin
{ Token identifier }
- AStream.WriteByte(AFormula[i].TokenID);
+ FormulaKind := FEKindToExcelID(AFormula[i].ElementKind);
+ AStream.WriteByte(FormulaKind);
Inc(RPNLength);
{ Additional data }
- case AFormula[i].TokenID of
+ case FormulaKind of
{ binary operation tokens }
@@ -253,7 +257,7 @@ begin
AStream.WriteByte(RPNLength);
AStream.Position := RecordSizePos;
AStream.WriteWord(WordToLE(17 + RPNLength));
- AStream.position := FinalPos;*)
+ AStream.position := FinalPos;
end;
{*******************************************************************
diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas
index 08558269a..c878dd133 100755
--- a/components/fpspreadsheet/xlsbiff5.pas
+++ b/components/fpspreadsheet/xlsbiff5.pas
@@ -97,6 +97,8 @@ type
{ TsSpreadBIFF5Writer }
TsSpreadBIFF5Writer = class(TsCustomSpreadWriter)
+ private
+ function FEKindToExcelID(AElement: TFEKind): Byte;
public
// constructor Create;
// destructor Destroy; override;
@@ -109,7 +111,7 @@ type
procedure WriteDimensions(AStream: TStream);
procedure WriteEOF(AStream: TStream);
procedure WriteFont(AStream: TStream; AFont: TFPCustomFont);
- procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); override;
+ procedure WriteRPNFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsRPNFormula); override;
procedure WriteIndex(AStream: TStream);
procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override;
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override;
@@ -220,12 +222,41 @@ const
MASK_XF_VERT_ALIGN = $70;
+const
+ { TokenID values }
+
+ { Binary Operator Tokens }
+ INT_EXCEL_TOKEN_TADD = $03;
+ INT_EXCEL_TOKEN_TSUB = $04;
+ INT_EXCEL_TOKEN_TMUL = $05;
+ INT_EXCEL_TOKEN_TDIV = $06;
+ INT_EXCEL_TOKEN_TPOWER = $07;
+
+ { Constant Operand Tokens }
+ INT_EXCEL_TOKEN_TNUM = $1F;
+
+ { Operand Tokens }
+ INT_EXCEL_TOKEN_TREFR = $24;
+ INT_EXCEL_TOKEN_TREFV = $44;
+ INT_EXCEL_TOKEN_TREFA = $64;
+
{
Exported functions
}
{ TsSpreadBIFF5Writer }
+function TsSpreadBIFF5Writer.FEKindToExcelID(AElement: TFEKind): Byte;
+begin
+ case AElement of
+ fekCell: Result := INT_EXCEL_TOKEN_TREFV;
+ fekAdd: Result := INT_EXCEL_TOKEN_TADD;
+ fekSub: Result := INT_EXCEL_TOKEN_TSUB;
+ fekDiv: Result := INT_EXCEL_TOKEN_TDIV;
+ fekMul: Result := INT_EXCEL_TOKEN_TMUL;
+ end;
+end;
+
{*******************************************************************
* TsSpreadBIFF5Writer.WriteToFile ()
*
@@ -550,15 +581,16 @@ end;
* AFormula array
*
*******************************************************************}
-procedure TsSpreadBIFF5Writer.WriteFormula(AStream: TStream; const ARow,
- ACol: Word; const AFormula: TsFormula);
-{var
+procedure TsSpreadBIFF5Writer.WriteRPNFormula(AStream: TStream; const ARow,
+ ACol: Word; const AFormula: TsRPNFormula);
+var
FormulaResult: double;
i: Integer;
RPNLength: Word;
- TokenArraySizePos, RecordSizePos, FinalPos: Int64;}
+ TokenArraySizePos, RecordSizePos, FinalPos: Int64;
+ FormulaKind: Byte;
begin
-(* RPNLength := 0;
+ RPNLength := 0;
FormulaResult := 0.0;
{ BIFF Record header }
@@ -594,11 +626,12 @@ begin
for i := 0 to Length(AFormula) - 1 do
begin
{ Token identifier }
- AStream.WriteByte(AFormula[i].TokenID);
+ FormulaKind := FEKindToExcelID(AFormula[i].ElementKind);
+ AStream.WriteByte(FormulaKind);
Inc(RPNLength);
{ Additional data }
- case AFormula[i].TokenID of
+ case FormulaKind of
{ binary operation tokens }
@@ -627,7 +660,7 @@ begin
AStream.WriteByte(RPNLength);
AStream.Position := RecordSizePos;
AStream.WriteWord(WordToLE(22 + RPNLength));
- AStream.position := FinalPos;*)
+ AStream.position := FinalPos;
end;
{*******************************************************************