You've already forked lazarus-ccr
fpspreadsheet: Complete rpn calculations (COUNTA). Remaining missing function probably will not be implemented because calculation is beyond units (math, strutils, dateutils; if needed they can still be implemented at application level by registering the corresponding function).
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3296 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -11,6 +11,8 @@ type
|
||||
TsArgumentType = (atCell, atCellRange, atNumber, atString,
|
||||
atBool, atError, atEmpty);
|
||||
|
||||
TsArgumentTypes = set of TsArgumentType;
|
||||
|
||||
TsArgBoolArray = array of boolean;
|
||||
TsArgNumberArray = array of double;
|
||||
TsArgStringArray = array of string;
|
||||
@ -128,6 +130,7 @@ function fpsYEAR (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsAVEDEV (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsAVERAGE (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsCOUNT (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsCOUNTA (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsCOUNTBLANK (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsCOUNTIF (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsMAX (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
@ -1534,7 +1537,7 @@ end;
|
||||
function fpsCOUNT(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
{ counts the number of cells that contain numbers as well as the number of
|
||||
arguments that contain numbers.
|
||||
COUNT( argument1, [argument2, ... argument_n] )
|
||||
COUNT( argument1 [, argument2, ... argument_n] )
|
||||
}
|
||||
var
|
||||
data: TsArgNumberArray;
|
||||
@ -1543,6 +1546,38 @@ begin
|
||||
Result := CreateNumberArg(Length(data));
|
||||
end;
|
||||
|
||||
function fpsCOUNTA(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
// COUNTA (argument1 [, argument2, ... argument_n] )
|
||||
// Counts the number of non-empty cells specified by arguments of misc type.
|
||||
var
|
||||
arg: TsArgument;
|
||||
counter: Integer;
|
||||
r, c: Integer;
|
||||
cell: PCell;
|
||||
n: Integer;
|
||||
begin
|
||||
n := 0;
|
||||
// The order of arguments is not important for counting --> we just pop them from the stack.
|
||||
for counter := 1 to NumArgs do begin
|
||||
arg := Args.Pop;
|
||||
case arg.ArgumentType of
|
||||
atCell:
|
||||
if arg.Cell^.ContentType <> cctEmpty then inc(n);
|
||||
atCellRange:
|
||||
for r := arg.FirstRow to arg.LastRow do
|
||||
for c := arg.FirstCol to arg.LastCol do begin
|
||||
cell := arg.Worksheet.FindCell(r, c);
|
||||
if (cell <> nil) and (cell^.ContentType <> cctEmpty) then inc(n);
|
||||
end;
|
||||
atString:
|
||||
if arg.StringValue <> '' then inc(n);
|
||||
atNumber, atBool, atError:
|
||||
inc(n);
|
||||
end;
|
||||
end;
|
||||
Result := CreateNumberArg(n);
|
||||
end;
|
||||
|
||||
function fpsCOUNTBLANK(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
// COUNTBLANK( range )
|
||||
// counts the number of empty cells in a range.
|
||||
|
@ -1152,7 +1152,7 @@ var
|
||||
(Symbol:'<'; MinParams:2; MaxParams:2; Func:fpsLess), // fekLess
|
||||
(Symbol:'<='; MinParams:2; MaxParams:2; Func:fpsLessEqual), // fekLessEqual
|
||||
(Symbol:'<>'; MinParams:2; MaxParams:2; Func:fpsNotEqual), // fekNotEqual
|
||||
(Symbol:''; MinParams:1; MaxParams:1; Func:nil), // fekParen
|
||||
(Symbol:''; MinParams:1; MaxParams:1; Func:nil), // fekParen -- no need to calculate!
|
||||
{ math }
|
||||
(Symbol:'ABS'; MinParams:1; MaxParams:1; Func:fpsABS), // fekABS
|
||||
(Symbol:'ACOS'; MinParams:1; MaxParams:1; Func:fpsACOS), // fekACOS
|
||||
@ -1203,7 +1203,7 @@ var
|
||||
(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:fpsCOUNT), // fekCOUNT
|
||||
(Symbol:'COUNTA'; MinParams:0; MaxParams:30; Func:nil), // fekCOUNTA
|
||||
(Symbol:'COUNTA'; MinParams:0; MaxParams:30; Func:fpsCOUNTA), // fekCOUNTA
|
||||
(Symbol:'COUNTBLANK';MinParams:1; MaxParams:1; Func:fpsCOUNTBLANK), // fekCOUNTBLANK
|
||||
(Symbol:'COUNTIF'; MinParams:2; MaxParams:2; Func:fpsCOUNTIF), // fekCOUNTIF
|
||||
(Symbol:'MAX'; MinParams:1; MaxParams:30; Func:fpsMAX), // fekMAX
|
||||
|
@ -80,7 +80,6 @@
|
||||
<Unit1>
|
||||
<Filename Value="datetests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="datetests"/>
|
||||
</Unit1>
|
||||
<Unit2>
|
||||
<Filename Value="stringtests.pas"/>
|
||||
@ -89,12 +88,10 @@
|
||||
<Unit3>
|
||||
<Filename Value="numberstests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="numberstests"/>
|
||||
</Unit3>
|
||||
<Unit4>
|
||||
<Filename Value="manualtests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="manualtests"/>
|
||||
</Unit4>
|
||||
<Unit5>
|
||||
<Filename Value="testsutility.pas"/>
|
||||
|
@ -1286,6 +1286,42 @@
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumberArg(2);
|
||||
|
||||
// COUNTA
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=COUNTA(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(fekCOUNTA, 5, nil))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumberArg(5);
|
||||
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=COUNTA(1, 1.1, 1.2, 0.9, 0.8, "A", "B")');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNNumber(1.1,
|
||||
RPNNumber(1.2,
|
||||
RPNNumber(0.9,
|
||||
RPNNumber(0.8,
|
||||
RPNString('A',
|
||||
RPNString('B',
|
||||
RPNFunc(fekCOUNTA, 7, nil))))))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumberArg(7);
|
||||
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=COUNTA(A1:C2,1,2,"A")');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNCellRange('A1:C2',
|
||||
RPNNumber(1,
|
||||
RPNNumber(2,
|
||||
RPNString('A',
|
||||
RPNFunc(fekCOUNTA, 4, nil)))))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumberArg(7);
|
||||
|
||||
if AFormat <> sfExcel2 then begin
|
||||
// COUNTBLANK
|
||||
inc(Row);
|
||||
|
Reference in New Issue
Block a user