diff --git a/components/fpspreadsheet/examples/excel2demo/excel2write.lpr b/components/fpspreadsheet/examples/excel2demo/excel2write.lpr
index 931e786b3..7f5c692f0 100644
--- a/components/fpspreadsheet/examples/excel2demo/excel2write.lpr
+++ b/components/fpspreadsheet/examples/excel2demo/excel2write.lpr
@@ -15,6 +15,7 @@ uses
var
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
+ MyRPNFormula: TsRPNFormula;
MyDir: string;
begin
// Open the output file
@@ -30,6 +31,24 @@ begin
MyWorksheet.WriteNumber(0, 2, 3.0);
MyWorksheet.WriteNumber(0, 3, 4.0);
+ // Write the formula E1 = ABS(A1)
+ SetLength(MyRPNFormula, 2);
+ MyRPNFormula[0].ElementKind := fekCell;
+ MyRPNFormula[0].Col := 0;
+ MyRPNFormula[0].Row := 0;
+ MyRPNFormula[1].ElementKind := fekABS;
+ MyWorksheet.WriteRPNFormula(0, 4, MyRPNFormula);
+
+ // Write the formula F1 = ROUND(A1, 0)
+ SetLength(MyRPNFormula, 3);
+ MyRPNFormula[0].ElementKind := fekCell;
+ MyRPNFormula[0].Col := 0;
+ MyRPNFormula[0].Row := 0;
+ MyRPNFormula[1].ElementKind := fekNum;
+ MyRPNFormula[1].DoubleValue := 0.0;
+ MyRPNFormula[2].ElementKind := fekROUND;
+ MyWorksheet.WriteRPNFormula(0, 5, MyRPNFormula);
+
// Write some string cells
MyWorksheet.WriteUTF8Text(1, 0, 'First');
MyWorksheet.WriteUTF8Text(1, 1, 'Second');
diff --git a/components/fpspreadsheet/examples/excel5demo/excel5write.lpi b/components/fpspreadsheet/examples/excel5demo/excel5write.lpi
index c2e02c20b..b264bb5f2 100644
--- a/components/fpspreadsheet/examples/excel5demo/excel5write.lpi
+++ b/components/fpspreadsheet/examples/excel5demo/excel5write.lpi
@@ -11,7 +11,7 @@
-
+
@@ -33,13 +33,13 @@
-
+
-
-
+
+
@@ -68,38 +68,34 @@
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
-
-
-
-
+
+
-
@@ -116,10 +112,10 @@
-
-
-
-
+
+
+
+
@@ -131,143 +127,158 @@
-
-
-
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/fpspreadsheet/examples/excel5demo/excel5write.lpr b/components/fpspreadsheet/examples/excel5demo/excel5write.lpr
index 71d8e02a4..501423d4d 100644
--- a/components/fpspreadsheet/examples/excel5demo/excel5write.lpr
+++ b/components/fpspreadsheet/examples/excel5demo/excel5write.lpr
@@ -55,6 +55,14 @@ begin
MyRPNFormula[2].ElementKind := fekAdd;
MyWorksheet.WriteRPNFormula(0, 4, MyRPNFormula);
+ // Write the formula F1 = ABS(A1)
+ SetLength(MyRPNFormula, 2);
+ MyRPNFormula[0].ElementKind := fekCell;
+ MyRPNFormula[0].Col := 0;
+ MyRPNFormula[0].Row := 0;
+ MyRPNFormula[1].ElementKind := fekABS;
+ MyWorksheet.WriteRPNFormula(0, 5, MyRPNFormula);
+
//MyFormula.FormulaStr := '';
// Creates a new worksheet
diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas
index 800555874..606a54aba 100755
--- a/components/fpspreadsheet/fpspreadsheet.pas
+++ b/components/fpspreadsheet/fpspreadsheet.pas
@@ -44,13 +44,22 @@ type
{@@ Expanded formula. Used by backend modules. Provides more information then the text only }
- TFEKind = (fekCell, fekAdd, fekSub, fekDiv, fekMul,
- fekOpSUM);
+ TFEKind = (
+ { Basic operands }
+ fekCell, fekNum,
+ { Basic operations }
+ fekAdd, fekSub, fekDiv, fekMul,
+ { Build-in Functions}
+ fekABS, fekROUND,
+ { Other operations }
+ fekOpSUM
+ );
TsFormulaElement = record
ElementKind: TFEKind;
Row, Row2: Word; // zero-based
Col, Col2: Byte; // zero-based
+ Param1, Param2: Word; // Extra parameters
DoubleValue: double;
end;
diff --git a/components/fpspreadsheet/laz_fpspreadsheet.lpk b/components/fpspreadsheet/laz_fpspreadsheet.lpk
index 576b79f47..62b7b9ad1 100644
--- a/components/fpspreadsheet/laz_fpspreadsheet.lpk
+++ b/components/fpspreadsheet/laz_fpspreadsheet.lpk
@@ -14,7 +14,7 @@
-
+
@@ -83,6 +83,10 @@
+
+
+
+
diff --git a/components/fpspreadsheet/laz_fpspreadsheet.pas b/components/fpspreadsheet/laz_fpspreadsheet.pas
index 4fe69695c..32374c3ec 100644
--- a/components/fpspreadsheet/laz_fpspreadsheet.pas
+++ b/components/fpspreadsheet/laz_fpspreadsheet.pas
@@ -7,13 +7,10 @@ unit laz_fpspreadsheet;
interface
uses
- fpolestorage, fpsallformats, fpsopendocument, fpspreadsheet, xlsbiff2,
- xlsbiff5, xlsbiff8, xlsxooxml, fpsutils, fpszipper,
- {$ifdef USE_NEW_OLE}
- uvirtuallayer_types,
+ fpolestorage, fpsallformats, fpsopendocument, fpspreadsheet, xlsbiff2,
+ xlsbiff5, xlsbiff8, xlsxooxml, fpsutils, fpszipper, uvirtuallayer_types,
uvirtuallayer, uvirtuallayer_ole, uvirtuallayer_ole_helpers,
- uvirtuallayer_ole_types, uvirtuallayer_stream, fpolebasic,
- {$endif}
+ uvirtuallayer_ole_types, uvirtuallayer_stream, fpolebasic, xlscommon,
LazarusPackageIntf;
implementation
diff --git a/components/fpspreadsheet/uvirtuallayer.pas b/components/fpspreadsheet/uvirtuallayer.pas
index 1eaff22b8..f97d76768 100644
--- a/components/fpspreadsheet/uvirtuallayer.pas
+++ b/components/fpspreadsheet/uvirtuallayer.pas
@@ -5,7 +5,10 @@ unit uvirtuallayer;
interface
uses
- Classes, SysUtils,strutils, Graphics,
+ Classes, SysUtils,strutils,
+ {$ifdef FPSUSELCL}
+ Graphics,
+ {$endif}
uvirtuallayer_types,uvirtuallayer_stream;
type
@@ -57,7 +60,9 @@ protected
function intfCopy(const ASourceFileName,ATargetFileName: UTF8String): Boolean; virtual;
function intfMove(const ASourceFileName,ATargetFileName: UTF8String): Boolean; virtual;
+ {$ifdef FPSUSELCL}
function IntfGetIcon(const APath: UTF8String): TIcon; virtual;
+ {$endif}
procedure Lock(); virtual;
procedure Unlock(); virtual;
@@ -94,7 +99,9 @@ public
property RootLayer: TVirtualLayer read GetRootLayer;
property ParentLayer: TVirtualLayer read FParentLayer write SetParentLayer;
+ {$ifdef FPSUSELCL}
function GetIcon(const APath: UTF8String): TIcon;
+ {$endif}
Constructor Create(const AVirtualLayerStream: TStream);
procedure PrepareDestroy(); virtual;
@@ -556,11 +563,13 @@ begin
MountPath+RemoveRootPathDelimiter(ATargetFileName));
end;
+{$ifdef FPSUSELCL}
function TVirtualLayer.IntfGetIcon(const APath: UTF8String): TIcon;
begin
Result:=nil;
if Length(APath)=0 then Result:=nil; //Avoid hint.
end;
+{$endif}
function TVirtualLayer.AcrossLayersMove(const ASourceFileName,
ATargetFileName: UTF8String): Boolean;
@@ -820,6 +829,7 @@ begin
Unlock();
end;
+{$ifdef FPSUSELCL}
function TVirtualLayer.GetIcon(const APath: UTF8String): TIcon;
var
VL: TVirtualLayer;
@@ -832,6 +842,7 @@ begin
Result:=IntfGetIcon(APath);
end;
end;
+{$endif}
function TVirtualLayer.PathToVirtualLayer(const APath: UTF8String
): TVirtualLayer;
diff --git a/components/fpspreadsheet/uvirtuallayer_ole.pas b/components/fpspreadsheet/uvirtuallayer_ole.pas
index 2487c789a..aadc3bb78 100644
--- a/components/fpspreadsheet/uvirtuallayer_ole.pas
+++ b/components/fpspreadsheet/uvirtuallayer_ole.pas
@@ -63,8 +63,11 @@ unit uvirtuallayer_ole;
interface
uses
- Classes, SysUtils, Masks
- ,uvirtuallayer_types
+ Classes, SysUtils,
+ {.$ifdef FPSUSELCL}
+ Masks,
+ {.$endif}
+ uvirtuallayer_types
,uvirtuallayer
,uvirtuallayer_ole_helpers
,uvirtuallayer_ole_types
diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas
index bc824b75d..58623f855 100755
--- a/components/fpspreadsheet/xlsbiff2.pas
+++ b/components/fpspreadsheet/xlsbiff2.pas
@@ -31,7 +31,7 @@ interface
uses
Classes, SysUtils,
- fpspreadsheet, fpsutils;
+ fpspreadsheet, xlscommon, fpsutils;
type
@@ -54,7 +54,7 @@ type
TsSpreadBIFF2Writer = class(TsCustomSpreadWriter)
private
- function FEKindToExcelID(AElement: TFEKind): Byte;
+ function FEKindToExcelID(AElement: TFEKind; var AParamsNum, AFuncNum: Byte): Byte;
public
{ General writing methods }
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); override;
@@ -86,34 +86,34 @@ const
INT_EXCEL_CHART = $0020;
INT_EXCEL_MACRO_SHEET = $0040;
-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;
-
{ TsSpreadBIFF2Writer }
-function TsSpreadBIFF2Writer.FEKindToExcelID(AElement: TFEKind): Byte;
+function TsSpreadBIFF2Writer.FEKindToExcelID(AElement: TFEKind; var AParamsNum, AFuncNum: Byte): Byte;
begin
+ AFuncNum := 0;
+
case AElement of
+ { Operands }
fekCell: Result := INT_EXCEL_TOKEN_TREFV;
+ fekNum: Result := INT_EXCEL_TOKEN_TNUM;
+ { Operators }
fekAdd: Result := INT_EXCEL_TOKEN_TADD;
fekSub: Result := INT_EXCEL_TOKEN_TSUB;
fekDiv: Result := INT_EXCEL_TOKEN_TDIV;
fekMul: Result := INT_EXCEL_TOKEN_TMUL;
+ { Build-in functions }
+ fekABS:
+ begin
+ Result := INT_EXCEL_TOKEN_FUNCVAR_V;
+ AParamsNum := 1;
+ AFuncNum := INT_EXCEL_SHEET_FUNC_ABS;
+ end;
+ fekROUND:
+ begin
+ Result := INT_EXCEL_TOKEN_FUNCVAR_V;
+ AParamsNum := 2;
+ AFuncNum := INT_EXCEL_SHEET_FUNC_ROUND;
+ end;
end;
end;
@@ -185,7 +185,7 @@ var
i: Integer;
RPNLength: Word;
TokenArraySizePos, RecordSizePos, FinalPos: Cardinal;
- FormulaKind: Byte;
+ FormulaKind, ParamsNum, ExtraInfo: Byte;
begin
RPNLength := 0;
FormulaResult := 0.0;
@@ -223,7 +223,7 @@ begin
for i := 0 to Length(AFormula) - 1 do
begin
{ Token identifier }
- FormulaKind := FEKindToExcelID(AFormula[i].ElementKind);
+ FormulaKind := FEKindToExcelID(AFormula[i].ElementKind, ParamsNum, ExtraInfo);
AStream.WriteByte(FormulaKind);
Inc(RPNLength);
@@ -248,6 +248,13 @@ begin
Inc(RPNLength, 3);
end;
+ INT_EXCEL_TOKEN_FUNCVAR_V:
+ begin
+ AStream.WriteByte(ParamsNum);
+ AStream.WriteByte(ExtraInfo);
+ Inc(RPNLength, 2);
+ end;
+
end;
end;
diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas
index c878dd133..0903d7094 100755
--- a/components/fpspreadsheet/xlsbiff5.pas
+++ b/components/fpspreadsheet/xlsbiff5.pas
@@ -58,6 +58,7 @@ interface
uses
Classes, SysUtils, fpcanvas,
fpspreadsheet,
+ xlscommon,
{$ifdef USE_NEW_OLE}
fpolebasic,
{$else}
@@ -98,7 +99,7 @@ type
TsSpreadBIFF5Writer = class(TsCustomSpreadWriter)
private
- function FEKindToExcelID(AElement: TFEKind): Byte;
+ function FEKindToExcelID(AElement: TFEKind; var AParamsNum: Byte; var AExtra: Word): Byte;
public
// constructor Create;
// destructor Destroy; override;
@@ -222,38 +223,39 @@ 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;
+function TsSpreadBIFF5Writer.FEKindToExcelID(AElement: TFEKind;
+ var AParamsNum: Byte; var AExtra: Word): Byte;
begin
+ AExtra := 0;
+
case AElement of
+ { Operands }
fekCell: Result := INT_EXCEL_TOKEN_TREFV;
+ fekNum: Result := INT_EXCEL_TOKEN_TNUM;
+ { Operators }
fekAdd: Result := INT_EXCEL_TOKEN_TADD;
fekSub: Result := INT_EXCEL_TOKEN_TSUB;
fekDiv: Result := INT_EXCEL_TOKEN_TDIV;
fekMul: Result := INT_EXCEL_TOKEN_TMUL;
+ { Build-in Function }
+ fekABS:
+ begin
+ Result := INT_EXCEL_TOKEN_FUNCVAR_V;
+ AParamsNum := 1;
+ AExtra := INT_EXCEL_SHEET_FUNC_ABS;
+ end;
+ fekROUND:
+ begin
+ Result := INT_EXCEL_TOKEN_FUNCVAR_V;
+ AParamsNum := 2;
+ AExtra := INT_EXCEL_SHEET_FUNC_ROUND;
+ end;
end;
end;
@@ -588,7 +590,8 @@ var
i: Integer;
RPNLength: Word;
TokenArraySizePos, RecordSizePos, FinalPos: Int64;
- FormulaKind: Byte;
+ FormulaKind, ParamsNum: Byte;
+ ExtraInfo: Word;
begin
RPNLength := 0;
FormulaResult := 0.0;
@@ -626,7 +629,7 @@ begin
for i := 0 to Length(AFormula) - 1 do
begin
{ Token identifier }
- FormulaKind := FEKindToExcelID(AFormula[i].ElementKind);
+ FormulaKind := FEKindToExcelID(AFormula[i].ElementKind, ParamsNum, ExtraInfo);
AStream.WriteByte(FormulaKind);
Inc(RPNLength);
@@ -651,6 +654,26 @@ begin
Inc(RPNLength, 3);
end;
+ {
+ sOffset Size Contents
+ 0 1 22H (tFuncVarR), 42H (tFuncVarV), 62H (tFuncVarA)
+ 1 1 Number of arguments
+ Bit Mask Contents
+ 6-0 7FH Number of arguments
+ 7 80H 1 = User prompt for macro commands (shown by a question mark
+ following the command name)
+ 2 2 Index to a sheet function
+ Bit Mask Contents
+ 14-0 7FFFH Index to a built-in sheet function (➜3.11) or a macro command
+ 15 8000H 0 = Built-in function; 1 = Macro command
+ }
+ INT_EXCEL_TOKEN_FUNCVAR_V:
+ begin
+ AStream.WriteByte(ParamsNum);
+ AStream.WriteWord(WordToLE(ExtraInfo));
+ Inc(RPNLength, 3);
+ end;
+
end;
end;
diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas
new file mode 100644
index 000000000..6f81a6405
--- /dev/null
+++ b/components/fpspreadsheet/xlscommon.pas
@@ -0,0 +1,37 @@
+unit xlscommon;
+
+{$mode objfpc}{$H+}
+
+interface
+
+const
+ { Formula constants 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;
+
+ { Function Tokens }
+ INT_EXCEL_TOKEN_FUNCVAR_R = $22;
+ INT_EXCEL_TOKEN_FUNCVAR_V = $42;
+ INT_EXCEL_TOKEN_FUNCVAR_A = $62;
+
+ { Built-in functions }
+ INT_EXCEL_SHEET_FUNC_ABS = 24;
+ INT_EXCEL_SHEET_FUNC_ROUND = 27;
+
+implementation
+
+end.
+