You've already forked lazarus-ccr
fpspreadsheet: Calculate most statistical and some string functions in rpn formulas. Beginning to handle missing arguments correctly.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3256 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -33,10 +33,6 @@ type
|
||||
procedure Delete(AIndex: Integer);
|
||||
end;
|
||||
|
||||
procedure FixMissingBool (var Arg: TsArgument; ABool: Boolean);
|
||||
procedure FixMissingNumber(var Arg: TsArgument; ANumber: Double);
|
||||
procedure FixMissingString(var Arg: TsArgument; AString: String);
|
||||
|
||||
function CreateBool(AValue: Boolean): TsArgument;
|
||||
function CreateNumber(AValue: Double): TsArgument;
|
||||
function CreateString(AValue: String): TsArgument;
|
||||
@ -90,13 +86,30 @@ function fpsSINH (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsSQRT (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsTAN (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsTANH (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
{ Logic }
|
||||
{ Statistical functions }
|
||||
function fpsAVEDEV (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsAVERAGE (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsCOUNT (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsMAX (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsMIN (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsPRODUCT (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsSTDEV (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsSTDEVP (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsSUM (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsSUMSQ (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsVAR (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsVARP (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
{ Logical functions }
|
||||
function fpsAND (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsFALSE (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsIF (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsNOT (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsOR (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsTRUE (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
{ String functions }
|
||||
function fpsLOWER (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsTRIM (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsUPPER (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
|
||||
implementation
|
||||
|
||||
@ -104,9 +117,9 @@ uses
|
||||
Math;
|
||||
|
||||
type
|
||||
TBoolArray = array of boolean;
|
||||
TBoolArray = array of boolean;
|
||||
TFloatArray = array of double;
|
||||
TStrArray = array of string;
|
||||
TStrArray = array of string;
|
||||
|
||||
{ TsArgumentStack }
|
||||
|
||||
@ -194,39 +207,6 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
{ Missing arguments }
|
||||
|
||||
{@@
|
||||
Replaces a missing boolean argument by the passed boolean value
|
||||
@param Arg Argument to be considered
|
||||
@param ABool Replacement for the missing value
|
||||
}
|
||||
procedure FixMissingBool(var Arg: TsArgument; ABool: Boolean);
|
||||
begin
|
||||
if Arg.IsMissing then Arg.BoolValue := ABool;
|
||||
end;
|
||||
|
||||
{@@
|
||||
Replaces a missing number argument by the passed number value
|
||||
@param Arg Argument to be considered
|
||||
@param ANumber Replacement for the missing value
|
||||
}
|
||||
procedure FixMissingNumber(var Arg: TsArgument; ANumber: Double);
|
||||
begin
|
||||
if Arg.IsMissing then Arg.NumberValue := ANumber;
|
||||
end;
|
||||
|
||||
{@@
|
||||
Replaces a missing string argument by the passed string value
|
||||
@param Arg Argument to be considered
|
||||
@param AString Replacement for the missing value
|
||||
}
|
||||
procedure FixMissingString(var Arg: TsArgument; AString: String);
|
||||
begin
|
||||
if Arg.IsMissing then Arg.StringValue := AString;
|
||||
end;
|
||||
|
||||
|
||||
{ Preparing arguments }
|
||||
|
||||
function GetBoolFromArgument(Arg: TsArgument; var AValue: Boolean): TsErrorValue;
|
||||
@ -265,29 +245,34 @@ function CreateBool(AValue: Boolean): TsArgument;
|
||||
begin
|
||||
Result.ArgumentType := atBool;
|
||||
Result.Boolvalue := AValue;
|
||||
Result.IsMissing := false;
|
||||
end;
|
||||
|
||||
function CreateNumber(AValue: Double): TsArgument;
|
||||
begin
|
||||
Result.ArgumentType := atNumber;
|
||||
Result.NumberValue := AValue;
|
||||
Result.IsMissing := false;
|
||||
end;
|
||||
|
||||
function CreateString(AValue: String): TsArgument;
|
||||
begin
|
||||
Result.ArgumentType := atString;
|
||||
Result.StringValue := AValue;
|
||||
Result.IsMissing := false;
|
||||
end;
|
||||
|
||||
function CreateError(AError: TsErrorValue): TsArgument;
|
||||
begin
|
||||
Result.ArgumentType := atError;
|
||||
Result.ErrorValue := AError;
|
||||
Result.IsMissing := false;
|
||||
end;
|
||||
|
||||
function CreateEmpty: TsArgument;
|
||||
begin
|
||||
Result.ArgumentType := atEmpty;
|
||||
Result.IsMissing := false;
|
||||
end;
|
||||
|
||||
{@@
|
||||
@ -298,29 +283,47 @@ end;
|
||||
@param AValues (output) Array containing the retrieved boolean values.
|
||||
The array length is given by NumArgs. The data in the array
|
||||
are in the same order in which they were pushed onto the stack.
|
||||
Missing arguments are not included in the array, the case
|
||||
of missing arguments must be handled separately if the are
|
||||
important.
|
||||
@param AErrArg (output) Argument containing an error code, e.g. errWrongType
|
||||
if non-boolean data were met on the stack.
|
||||
@return TRUE if everything was ok, FALSE, if AErrArg reports an error. }
|
||||
function PopBoolValues(Args: TsArgumentStack; NumArgs: Integer;
|
||||
out AValues: TBoolArray; out AErrArg: TsArgument): Boolean;
|
||||
var
|
||||
arg: TsArgument;
|
||||
err: TsErrorValue;
|
||||
i: Integer;
|
||||
counter, j: Integer;
|
||||
b: Boolean;
|
||||
begin
|
||||
SetLength(AValues, NumArgs);
|
||||
// Pop the data in reverse order they were pushed! Otherwise they will be
|
||||
// applied to the function in the wrong order.
|
||||
for i := NumArgs-1 downto 0 do begin
|
||||
err := GetBoolFromArgument(Args.Pop, AValues[i]);
|
||||
if err <> errOK then begin
|
||||
Result := false;
|
||||
AErrArg := CreateError(err);
|
||||
SetLength(AValues, 0);
|
||||
exit;
|
||||
j := 0;
|
||||
for counter := 1 to NumArgs do begin
|
||||
arg := Args.Pop;
|
||||
if not arg.IsMissing then begin
|
||||
err := GetBoolFromArgument(arg, b);
|
||||
if err = errOK then begin
|
||||
AValues[j] := b;
|
||||
inc(j);
|
||||
end else begin
|
||||
Result := false;
|
||||
AErrArg := CreateError(err);
|
||||
SetLength(AValues, 0);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Result := true;
|
||||
AErrArg := CreateError(errOK);
|
||||
SetLength(AValues, j);
|
||||
// Flip array - we want to have the arguments in the array in the same order
|
||||
// they were pushed.
|
||||
for j:=0 to Length(AValues) div 2 - 1 do begin
|
||||
b := AValues[j];
|
||||
AValues[j] := AValues[High(AValues)-j];
|
||||
AValues[High(AValues)-j] := b;
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@
|
||||
@ -331,28 +334,46 @@ end;
|
||||
@param AValues (output) Array containing the retrieved float values.
|
||||
The array length is given by NumArgs. The data in the array
|
||||
are in the same order in which they were pushed onto the stack.
|
||||
Missing arguments are not included in the array, the case
|
||||
of missing arguments must be handled separately if the are
|
||||
important.
|
||||
@param AErrArg (output) Argument containing an error code, e.g. errWrongType
|
||||
if non-float data were met on the stack.
|
||||
@return TRUE if everything was ok, FALSE, if AErrArg reports an error. }
|
||||
function PopFloatValues(Args: TsArgumentStack; NumArgs: Integer;
|
||||
out AValues: TFloatArray; out AErrArg: TsArgument): Boolean;
|
||||
var
|
||||
arg: TsArgument;
|
||||
err: TsErrorValue;
|
||||
i: Integer;
|
||||
counter, j: Integer;
|
||||
val: double;
|
||||
begin
|
||||
SetLength(AValues, NumArgs);
|
||||
// Pop the data in reverse order they were pushed! Otherwise they will be
|
||||
// applied to the function in the wrong order.
|
||||
for i := NumArgs-1 downto 0 do begin
|
||||
err := GetNumberFromArgument(Args.Pop, AValues[i]);
|
||||
if err <> errOK then begin
|
||||
Result := false;
|
||||
SetLength(AValues, 0);
|
||||
AErrArg := CreateError(errWrongType);
|
||||
exit;
|
||||
j := 0;
|
||||
for counter := 1 to NumArgs do begin
|
||||
arg := Args.Pop;
|
||||
if not arg.IsMissing then begin
|
||||
err := GetNumberFromArgument(arg, val);
|
||||
if err = errOK then begin
|
||||
AValues[j] := val;
|
||||
inc(j);
|
||||
end else begin
|
||||
Result := false;
|
||||
SetLength(AValues, 0);
|
||||
AErrArg := CreateError(errWrongType);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Result := true;
|
||||
SetLength(AValues, j);
|
||||
// Flip array - we want to have the arguments in the array in the same order
|
||||
// they were pushed.
|
||||
for j:=0 to Length(AValues) div 2 - 1 do begin
|
||||
val := AValues[j];
|
||||
AValues[j] := AValues[High(AValues)-j];
|
||||
AValues[High(AValues)-j] := val;
|
||||
end;
|
||||
AErrArg := CreateError(errOK);
|
||||
end;
|
||||
|
||||
@ -364,29 +385,47 @@ end;
|
||||
@param AValues (output) Array containing the retrieved strings. The array
|
||||
length is given by NumArgs. The data in the array are in the
|
||||
same order in which they were pushed onto the stack.
|
||||
Missing arguments are not included in the array, the case
|
||||
of missing arguments must be handled separately if the are
|
||||
important.
|
||||
@param AErrArg (output) Argument containing an error code , e.g. errWrongType
|
||||
if non-string data were met on the stack.
|
||||
@return TRUE if everything was ok, FALSE, if AErrArg reports an error. }
|
||||
function PopStringValues(Args: TsArgumentStack; NumArgs: Integer;
|
||||
out AValues: TStrArray; out AErrArg: TsArgument): Boolean;
|
||||
var
|
||||
arg: TsArgument;
|
||||
err: TsErrorValue;
|
||||
i: Integer;
|
||||
counter, j: Integer;
|
||||
s: String;
|
||||
begin
|
||||
SetLength(AValues, NumArgs);
|
||||
// Pop the data in reverse order they were pushed! Otherwise they will be
|
||||
// applied to the function in the wrong order.
|
||||
for i := NumArgs-1 downto 0 do begin
|
||||
err := GetStringFromArgument(Args.Pop, AValues[i]);
|
||||
if err <> errOK then begin
|
||||
Result := false;
|
||||
AErrArg := CreateError(errWrongType);
|
||||
SetLength(AValues, 0);
|
||||
exit;
|
||||
j := 0;
|
||||
for counter := 1 to NumArgs do begin
|
||||
arg := Args.Pop;
|
||||
if not arg.IsMissing then begin
|
||||
err := GetStringFromArgument(arg, s);
|
||||
if err = errOK then begin
|
||||
AValues[j] := s;
|
||||
inc(j);
|
||||
end else begin
|
||||
Result := false;
|
||||
AErrArg := CreateError(errWrongType);
|
||||
SetLength(AValues, 0);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Result :=true;
|
||||
Result := true;
|
||||
AErrArg := CreateError(errOK);
|
||||
SetLength(AValues, j);
|
||||
// Flip array - we want to have the arguments in the array in the same order
|
||||
// they were pushed.
|
||||
for j:=0 to Length(AValues) div 2 - 1 do begin
|
||||
s := AValues[j];
|
||||
AValues[j] := AValues[High(AValues)-j];
|
||||
AValues[High(AValues)-j] := s;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
@ -826,6 +865,122 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
{ Statistical functions }
|
||||
|
||||
function fpsAVEDEV(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
// Average value of absolute deviations of data from their mean.
|
||||
var
|
||||
data: TFloatArray;
|
||||
m: Double;
|
||||
i: Integer;
|
||||
begin
|
||||
if PopFloatValues(Args, NumArgs, data, Result) then begin
|
||||
m := Mean(data);
|
||||
for i:=0 to High(data) do
|
||||
data[i] := abs(data[i] - m);
|
||||
m := Mean(data);
|
||||
Result := CreateNumber(m)
|
||||
end;
|
||||
end;
|
||||
|
||||
function fpsAVERAGE(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, NumArgs, data, Result) then
|
||||
Result := CreateNumber(Mean(data))
|
||||
end;
|
||||
|
||||
function fpsCOUNT(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
{ Count non-missing arguments }
|
||||
var
|
||||
n, i: Integer;
|
||||
begin
|
||||
n := 0;
|
||||
for i:=1 to NumArgs do
|
||||
if not Args.Pop.IsMissing then inc(n);
|
||||
Result := CreateNumber(n);
|
||||
end;
|
||||
|
||||
function fpsMAX(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, NumArgs, data, Result) then
|
||||
Result := CreateNumber(MaxValue(data))
|
||||
end;
|
||||
|
||||
function fpsMIN(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, NumArgs, data, Result) then
|
||||
Result := CreateNumber(MinValue(data))
|
||||
end;
|
||||
|
||||
function fpsPRODUCT(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
i: Integer;
|
||||
p: Double;
|
||||
begin
|
||||
if PopFloatValues(Args, NumArgs, data, Result) then begin
|
||||
p := 1.0;
|
||||
for i:=0 to High(data) do
|
||||
p := p * data[i];
|
||||
Result := CreateNumber(p);
|
||||
end;
|
||||
end;
|
||||
|
||||
function fpsSTDEV(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, NumArgs, data, Result) then
|
||||
Result := CreateNumber(StdDev(data))
|
||||
end;
|
||||
|
||||
function fpsSTDEVP(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, NumArgs, data, Result) then
|
||||
Result := CreateNumber(PopnStdDev(data))
|
||||
end;
|
||||
|
||||
function fpsSUM(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, NumArgs, data, Result) then
|
||||
Result := CreateNumber(Sum(data))
|
||||
end;
|
||||
|
||||
function fpsSUMSQ(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, NumArgs, data, Result) then
|
||||
Result := CreateNumber(SumOfSquares(data))
|
||||
end;
|
||||
|
||||
function fpsVAR(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, NumArgs, data, Result) then
|
||||
Result := CreateNumber(Variance(data))
|
||||
end;
|
||||
|
||||
function fpsVARP(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, NumArgs, data, Result) then
|
||||
Result := CreateNumber(PopnVariance(data))
|
||||
end;
|
||||
|
||||
|
||||
{ Logical functions }
|
||||
|
||||
function fpsAND(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
@ -901,4 +1056,31 @@ begin
|
||||
Result := CreateBool(true);
|
||||
end;
|
||||
|
||||
|
||||
{ String functions }
|
||||
|
||||
function fpsLOWER(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TStrArray;
|
||||
begin
|
||||
if PopStringValues(Args, NumArgs, data, Result) then
|
||||
Result := CreateString(lowercase(data[0]));
|
||||
end;
|
||||
|
||||
function fpsTRIM(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TStrArray;
|
||||
begin
|
||||
if PopStringValues(Args, NumArgs, data, Result) then
|
||||
Result := CreateString(trim(data[0]));
|
||||
end;
|
||||
|
||||
function fpsUPPER(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TStrArray;
|
||||
begin
|
||||
if PopStringValues(Args, NumArgs, data, Result) then
|
||||
Result := CreateString(uppercase(data[0]));
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -1164,30 +1164,30 @@ const
|
||||
(Symbol:'WEEKDAY'; MinParams:1; MaxParams:2; Func:nil), // fekWEEKDAY
|
||||
(Symbol:'YEAR'; MinParams:1; MaxParams:1; Func:nil), // fekYEAR
|
||||
{ statistical }
|
||||
(Symbol:'AVEDEV'; MinParams:1; MaxParams:30; Func:nil), // fekAVEDEV
|
||||
(Symbol:'AVERAGE'; MinParams:1; MaxParams:30; Func:nil), // fekAVERAGE
|
||||
(Symbol:'AVEDEV'; MinParams:1; MaxParams:30; Func:fpsAVEDEV), // fekAVEDEV
|
||||
(Symbol:'AVERAGE'; MinParams:1; MaxParams:30; Func:fpsAVERAGE), // fekAVERAGE
|
||||
(Symbol:'BETADIST'; MinParams:3; MaxParams:5; Func:nil), // fekBETADIST
|
||||
(Symbol:'BETAINV'; MinParams:3; MaxParams:5; Func:nil), // fekBETAINV
|
||||
(Symbol:'BINOMDIST'; MinParams:4; MaxParams:4; Func:nil), // fekBINOMDIST
|
||||
(Symbol:'CHIDIST'; MinParams:2; MaxParams:2; Func:nil), // fekCHIDIST
|
||||
(Symbol:'CHIINV'; MinParams:2; MaxParams:2; Func:nil), // fekCHIINV
|
||||
(Symbol:'COUNT'; MinParams:0; MaxParams:30; Func:nil), // fekCOUNT
|
||||
(Symbol:'COUNT'; MinParams:0; MaxParams:30; Func:fpsCOUNT), // fekCOUNT
|
||||
(Symbol:'COUNTA'; MinParams:0; MaxParams:30; Func:nil), // fekCOUNTA
|
||||
(Symbol:'COUNTBLANK';MinParams:1; MaxParams:1; Func:nil), // fekCOUNTBLANK
|
||||
(Symbol:'COUNTIF'; MinParams:2; MaxParams:2; Func:nil), // fekCOUNTIF
|
||||
(Symbol:'MAX'; MinParams:1; MaxParams:30; Func:nil), // fekMAX
|
||||
(Symbol:'MAX'; MinParams:1; MaxParams:30; Func:fpsMAX), // fekMAX
|
||||
(Symbol:'MEDIAN'; MinParams:1; MaxParams:30; Func:nil), // fekMEDIAN
|
||||
(Symbol:'MIN'; MinParams:1; MaxParams:30; Func:nil), // fekMIN
|
||||
(Symbol:'MIN'; MinParams:1; MaxParams:30; Func:fpsMIN), // fekMIN
|
||||
(Symbol:'PERMUT'; MinParams:2; MaxParams:2; Func:nil), // fekPERMUT
|
||||
(Symbol:'POISSON'; MinParams:3; MaxParams:3; Func:nil), // fekPOISSON
|
||||
(Symbol:'PRODUCT'; MinParams:0; MaxParams:30; Func:nil), // fekPRODUCT
|
||||
(Symbol:'STDEV'; MinParams:1; MaxParams:30; Func:nil), // fekSTDEV
|
||||
(Symbol:'STDEVP'; MinParams:1; MaxParams:30; Func:nil), // fekSTDEVP
|
||||
(Symbol:'SUM'; MinParams:0; MaxParams:30; Func:nil), // fekSUM
|
||||
(Symbol:'SUMIF'; MinParams:2; MaxParams:3; Func:nil), // fekSUMIF
|
||||
(Symbol:'SUMSQ'; MinParams:0; MaxParams:30; Func:nil), // fekSUMSQ
|
||||
(Symbol:'VAR'; MinParams:1; MaxParams:30; Func:nil), // fekVAR
|
||||
(Symbol:'VARP'; MinParams:1; MaxParams:30; Func:nil), // fekVARP
|
||||
(Symbol:'PRODUCT'; MinParams:0; MaxParams:30; Func:fpsPRODUCT), // fekPRODUCT
|
||||
(Symbol:'STDEV'; MinParams:1; MaxParams:30; Func:fpsSTDEV), // fekSTDEV
|
||||
(Symbol:'STDEVP'; MinParams:1; MaxParams:30; Func:fpsSTDEVP), // fekSTDEVP
|
||||
(Symbol:'SUM'; MinParams:0; MaxParams:30; Func:fpsSUM), // fekSUM
|
||||
(Symbol:'SUMIF'; MinParams:2; MaxParams:3; Func:nil), // fekSUMIF
|
||||
(Symbol:'SUMSQ'; MinParams:0; MaxParams:30; Func:fpsSUMSQ), // fekSUMSQ
|
||||
(Symbol:'VAR'; MinParams:1; MaxParams:30; Func:fpsVAR), // fekVAR
|
||||
(Symbol:'VARP'; MinParams:1; MaxParams:30; Func:fpsVARP), // fekVARP
|
||||
{ financial }
|
||||
(Symbol:'FV'; MinParams:3; MaxParams:5; Func:nil), // fekFV
|
||||
(Symbol:'NPER'; MinParams:3; MaxParams:5; Func:nil), // fekNPER
|
||||
@ -1205,14 +1205,14 @@ const
|
||||
(Symbol:'CHAR'; MinParams:1; MaxParams:1; Func:nil), // fekCHAR
|
||||
(Symbol:'CODE'; MinParams:1; MaxParams:1; Func:nil), // fekCODE
|
||||
(Symbol:'LEFT'; MinParams:1; MaxParams:2; Func:nil), // fekLEFT
|
||||
(Symbol:'LOWER'; MinParams:1; MaxParams:1; Func:nil), // fekLOWER
|
||||
(Symbol:'LOWER'; MinParams:1; MaxParams:1; Func:fpsLOWER), // fekLOWER
|
||||
(Symbol:'MID'; MinParams:3; MaxParams:3; Func:nil), // fekMID
|
||||
(Symbol:'PROPER'; MinParams:1; MaxParams:1; Func:nil), // fekPROPER
|
||||
(Symbol:'REPLACE'; MinParams:4; MaxParams:4; Func:nil), // fekREPLACE
|
||||
(Symbol:'RIGHT'; MinParams:1; MaxParams:2; Func:nil), // fekRIGHT
|
||||
(Symbol:'SUBSTITUTE';MinParams:3; MaxParams:4; Func:nil), // fekSUBSTITUTE
|
||||
(Symbol:'TRIM'; MinParams:1; MaxParams:1; Func:nil), // fekTRIM
|
||||
(Symbol:'UPPER'; MinParams:1; MaxParams:1; Func:nil), // fekUPPER
|
||||
(Symbol:'TRIM'; MinParams:1; MaxParams:1; Func:fpsTRIM), // fekTRIM
|
||||
(Symbol:'UPPER'; MinParams:1; MaxParams:1; Func:fpsUPPER), // fekUPPER
|
||||
{ lookup/reference }
|
||||
(Symbol:'COLUMN'; MinParams:0; MaxParams:1; Func:nil), // fekCOLUMN
|
||||
(Symbol:'COLUMNS'; MinParams:1; MaxParams:1; Func:nil), // fekCOLUMNS
|
||||
|
@ -680,6 +680,193 @@
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(tanh(0.1));
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ Statistical functions }
|
||||
{------------------------------------------------------------------------------}
|
||||
|
||||
// AVEDEV
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=AVEDEV(1, 1.1, 1.2, 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekAVEDEV, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(mean([0.0, 0.1, 0.2, 0.1, 0.2]));
|
||||
// these values are the absolute deviations from mean (1.0)
|
||||
// AVERAGE
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=AVERAGE(1, 1.1, 1.2, 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekAVERAGE, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(mean([1.0, 1.1, 1.2, 0.9, 0.8]));
|
||||
|
||||
// COUNT (no missing values)
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=COUNT(1, 1.1, 1.2, 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekCOUNT, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(5);
|
||||
|
||||
// COUNT (with missing values)
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=COUNT(1, , 1.2, , 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNMissingArg(
|
||||
RPNNumber(1.2,
|
||||
RPNMissingArg(
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekCOUNT, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(3);
|
||||
|
||||
// MAX
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=MAX(1, 1.1, 1.2, 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekMAX, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(MaxValue([1.0, 1.1, 1.2, 0.9, 0.8]));
|
||||
|
||||
// MAX (with missing values)
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=MAX(1, , , 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNMissingArg(
|
||||
RPNMissingArg(
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekMAX, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(MaxValue([1.0, {1.1, 1.2,} 0.9, 0.8]));
|
||||
|
||||
// MIN
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=MIN(1, 1.1, 1.2, 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekMIN, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(MinValue([1.0, 1.1, 1.2, 0.9, 0.8]));
|
||||
|
||||
// PRODUCT
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=PRODUCT(1, 1.1, 1.2, 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekPRODUCT, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(1.0*1.1*1.2*0.9*0.8);
|
||||
|
||||
// STDEV
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=STDEV(1, 1.1, 1.2, 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekSTDEV, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(StdDev([1.0, 1.1, 1.2, 0.9, 0.8]));
|
||||
|
||||
// STDEVP
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=STDEVP(1, 1.1, 1.2, 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekSTDEVP, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(PopnStdDev([1.0, 1.1, 1.2, 0.9, 0.8]));
|
||||
|
||||
// SUM
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=SUM(1, 1.1, 1.2, 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekSUM, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(Sum([1.0, 1.1, 1.2, 0.9, 0.8]));
|
||||
|
||||
// SUMSQ
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=SUMSQ(1, 1.1, 1.2, 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekSUMSQ, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(SumOfSquares([1.0, 1.1, 1.2, 0.9, 0.8]));
|
||||
|
||||
// VAR
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=VAR(1, 1.1, 1.2, 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekVAR, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(Variance([1.0, 1.1, 1.2, 0.9, 0.8]));
|
||||
|
||||
// VARP
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=VARP(1, 1.1, 1.2, 0.9, 0.8)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNFunc(fekVARP, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(PopnVariance([1.0, 1.1, 1.2, 0.9, 0.8]));
|
||||
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ Logical functions }
|
||||
{------------------------------------------------------------------------------}
|
||||
@ -854,3 +1041,34 @@
|
||||
sollValues[Row] := CreateString('A');
|
||||
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ String functions }
|
||||
{------------------------------------------------------------------------------}
|
||||
|
||||
// Lower case
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=LOWER("Hallo word")');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNString('Hallo world',
|
||||
RPNFunc(fekLOWER, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateString(LowerCase('Hallo world'));
|
||||
|
||||
// Trim
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=TRIM(" Hallo word ")');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNString(' Hallo world ',
|
||||
RPNFunc(fekTRIM, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateString(Trim(' Hallo world '));
|
||||
|
||||
// Upper case
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=UPPER("Hallo word")');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNString('Hallo world',
|
||||
RPNFunc(fekUPPER, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateString(UpperCase('Hallo world'));
|
||||
|
||||
|
Reference in New Issue
Block a user