diff --git a/components/fpspreadsheet/fpsfunc.pas b/components/fpspreadsheet/fpsfunc.pas index a587d4359..f17407d8a 100644 --- a/components/fpspreadsheet/fpsfunc.pas +++ b/components/fpspreadsheet/fpsfunc.pas @@ -128,6 +128,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 fpsCOUNTBLANK (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; @@ -1414,6 +1415,31 @@ begin Result := CreateNumber(Length(data)); end; +function fpsCOUNTBLANK(Args: TsArgumentStack; NumArgs: Integer): TsArgument; +// COUNTBLANK( range ) +// counts the number of empty cells in a range. +var + arg: TsArgument; + r, c, n: Cardinal; + cell: PCell; +begin + arg := Args.Pop; + case arg.ArgumentType of + atCell: + if arg.Cell = nil then Result := CreateNumber(1) else Result := CreateNumber(0); + atCellRange: + begin + n := 0; + for r := arg.FirstRow to arg.LastRow do + for c := arg.FirstCol to arg.LastCol do + if arg.Worksheet.FindCell(r, c) = nil then inc(n); + Result := CreateNumber(n); + end; + else + Result := CreateError(errWrongType); + end; +end; + function fpsMAX(Args: TsArgumentStack; NumArgs: Integer): TsArgument; // MAX( number1, number2, ... number_n ) var diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index 98e0fda6e..2a98c9b1d 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -1195,7 +1195,7 @@ var (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:'COUNTBLANK';MinParams:1; MaxParams:1; Func:nil), // fekCOUNTBLANK + (Symbol:'COUNTBLANK';MinParams:1; MaxParams:1; Func:fpsCOUNTBLANK), // fekCOUNTBLANK (Symbol:'COUNTIF'; MinParams:2; MaxParams:2; Func:nil), // fekCOUNTIF (Symbol:'MAX'; MinParams:1; MaxParams:30; Func:fpsMAX), // fekMAX (Symbol:'MEDIAN'; MinParams:1; MaxParams:30; Func:nil), // fekMEDIAN diff --git a/components/fpspreadsheet/tests/testcases_calcrpnformula.inc b/components/fpspreadsheet/tests/testcases_calcrpnformula.inc index 4109ee1b0..b90fa07a1 100644 --- a/components/fpspreadsheet/tests/testcases_calcrpnformula.inc +++ b/components/fpspreadsheet/tests/testcases_calcrpnformula.inc @@ -14,9 +14,10 @@ RPNFunc(fekAdd, nil))))); SetLength(sollValues, Row+1); sollValues[Row] := CreateNumber(1.0+1.0); // B1 = 2 -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// DO NOT CHANGE THIS FORMULA - ITS RESULT (2) IS HARD-CODED IN OTHER TESTS ! -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // don't refer to the cell contents here because they have not yet been calculated! +{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!! DO NOT CHANGE THIS FORMULA - ITS RESULT (-9) IS HARD-CODED IN OTHER TESTS !! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!} // Subtraction inc(Row); @@ -27,9 +28,10 @@ RPNFunc(fekSub, nil))))); SetLength(sollValues, Row+1); sollValues[Row] := CreateNumber(1-10); // B2 = -9 -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// DO NOT CHANGE THIS FORMULA - ITS RESULT (-9) IS HARD-CODED IN OTHER TESTS ! -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // don't refer to the cell contents here because they have not yet been calculated! +{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!! DO NOT CHANGE THIS FORMULA - ITS RESULT (-9) IS HARD-CODED IN OTHER TESTS !! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!} // Add cell values - relative addresses inc(Row); @@ -40,7 +42,6 @@ RPNFunc(fekAdd, nil))))); SetLength(sollValues, Row+1); sollValues[Row] := CreateNumber(-7); -// don't refer to the cell contents here because they have not yet been calculated! // Add cell values - absolute addresses inc(Row); @@ -1124,11 +1125,11 @@ 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, + 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); @@ -1137,8 +1138,8 @@ inc(Row); MyWorksheet.WriteUTF8Text(Row, 0, '=COUNT(B1:B2)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( - RPNCellrange('B1:B2', - RPNFunc(fekCOUNT, 1, nil)))); + RPNCellrange('B1:B2', + RPNFunc(fekCOUNT, 1, nil)))); SetLength(sollValues, Row+1); sollValues[Row] := CreateNumber(2); @@ -1146,8 +1147,8 @@ inc(Row); MyWorksheet.WriteUTF8Text(Row, 0, '=COUNT(A1:B2)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( - RPNCellrange('A1:B2', - RPNFunc(fekCOUNT, 1, nil)))); + RPNCellrange('A1:B2', + RPNFunc(fekCOUNT, 1, nil)))); SetLength(sollValues, Row+1); sollValues[Row] := CreateNumber(2); @@ -1155,11 +1156,20 @@ inc(Row); MyWorksheet.WriteUTF8Text(Row, 0, '=COUNT(B1:C2)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( - RPNCellrange('B1:C2', - RPNFunc(fekCOUNT, 1, nil)))); + RPNCellrange('B1:C2', + RPNFunc(fekCOUNT, 1, nil)))); SetLength(sollValues, Row+1); sollValues[Row] := CreateNumber(2); + // COUNT + inc(Row); + MyWorksheet.WriteUTF8Text(Row, 0, '=COUNTBLANK(A1:D2)'); + MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( + RPNCellRange('A1:D2', + RPNFunc(fekCOUNTBLANK, nil)))); + SetLength(sollValues, Row+1); + sollValues[Row] := CreateNumber(4); + // MAX inc(Row); MyWorksheet.WriteUTF8Text(Row, 0, '=MAX(1, 1.1, 1.2, 0.9, 0.8)');