FPSpreadsheet: Add more unit test cases for COUNTIF and SUMIF.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9605 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
35839d3bc3
commit
e66040bd5c
@ -855,10 +855,11 @@ function TokenName(AToken: TsTokenType): String;
|
||||
function ResultTypeName(AResult: TsResultType): String;
|
||||
function CharToResultType(C: Char): TsResultType;
|
||||
function BuiltinIdentifiers: TsBuiltInExpressionManager;
|
||||
function ArgToBoolean(Arg: TsExpressionResult): Boolean;
|
||||
function ArgToBoolean(Arg: TsExpressionResult; Strict: Boolean): Boolean;
|
||||
function ArgToCell(Arg: TsExpressionResult): PCell;
|
||||
function ArgToDateTime(Arg: TsExpressionResult): TDateTime;
|
||||
function ArgToInt(Arg: TsExpressionResult): Integer;
|
||||
function ArgToError(Arg: TsExpressionResult): TsErrorValue;
|
||||
function ArgToFloat(Arg: TsExpressionResult): TsExprFloat;
|
||||
function ArgToFloatOrNaN(Arg: TsExpressionResult): TsExprFloat;
|
||||
function ArgToString(Arg: TsExpressionResult): String;
|
||||
@ -4786,7 +4787,7 @@ end;
|
||||
{ Conversion of arguments to simple data types }
|
||||
{------------------------------------------------------------------------------}
|
||||
|
||||
function ArgToBoolean(Arg: TsExpressionResult): Boolean;
|
||||
function ArgToBoolean(Arg: TsExpressionResult; Strict: Boolean): Boolean;
|
||||
var
|
||||
cell: PCell;
|
||||
x: Double;
|
||||
@ -4804,10 +4805,14 @@ begin
|
||||
cctBool:
|
||||
Result := cell^.BoolValue;
|
||||
else
|
||||
x := ArgToFloatOrNaN(Arg);
|
||||
Result := not IsNaN(x) and (x <> 0.0);
|
||||
if not Strict then
|
||||
begin
|
||||
x := ArgToFloatOrNaN(Arg);
|
||||
Result := not IsNaN(x) and (x <> 0.0);
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
if not Strict then
|
||||
begin
|
||||
x := ArgToFloatOrNaN(Arg);
|
||||
Result := not IsNaN(x) and (x <> 0.0);
|
||||
@ -4848,6 +4853,23 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function ArgToError(Arg: TsExpressionResult): TsErrorValue;
|
||||
var
|
||||
cell: PCell;
|
||||
begin
|
||||
Result := errOK;
|
||||
case Arg.ResultType of
|
||||
rtError:
|
||||
Result := Arg.ResError;
|
||||
rtCell:
|
||||
begin
|
||||
cell := ArgToCell(Arg);
|
||||
if Assigned(cell) and (cell^.ContentType = cctError) then
|
||||
Result := cell^.ErrorValue;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Utility function for the built-in math functions. Accepts also integers and
|
||||
other data types in place of floating point arguments. To be called in
|
||||
builtins or user-defined callbacks having float results or arguments. }
|
||||
|
@ -75,7 +75,7 @@ end;
|
||||
|
||||
type
|
||||
TsFuncType = (ftCountIF, ftCountIFS, ftSumIF, ftSUMIFS, ftAverageIF, ftAverageIFS);
|
||||
TsCompareType = (ctNumber, ctString, ctEmpty);
|
||||
TsCompareType = (ctNumber, ctString, ctBoolean, ctEmpty, ctError);
|
||||
|
||||
{ Helper class for calculating COUNTIF(S) or SUMIF(S) or AVERAGEIF(S) formulas.
|
||||
|
||||
@ -101,14 +101,19 @@ type
|
||||
FCompareOperation: TsCompareOperation;
|
||||
FCompareType: TsCompareType;
|
||||
FCompareNumber: Double;
|
||||
FCompareBoolean: Boolean;
|
||||
FCompareError: TsErrorValue;
|
||||
FCompareString: String;
|
||||
FFormatSettings: TFormatSettings;
|
||||
FError: TsErrorValue;
|
||||
protected
|
||||
function CompareArg(ArgIndex: Integer): Boolean;
|
||||
function CompareBoolean(AValue: Boolean): Boolean;
|
||||
function CompareCell(ASheet: TsBasicWorksheet; ARow, ACol: Integer): Boolean;
|
||||
function CompareEmpty(AEmpty: Boolean): Boolean;
|
||||
function CompareError(AError: TsErrorValue): Boolean;
|
||||
function CompareNumber(ANumber: Double): Boolean;
|
||||
function CompareString(AString: String): Boolean;
|
||||
function CompareEmpty(AEmpty: Boolean): Boolean;
|
||||
function GetArgValue(ArgIndex: Integer): Double;
|
||||
function GetCellValue(ASheet: TsBasicWorksheet; ARow, ACol: Integer): Double;
|
||||
procedure GetCompareParams(ArgIndex: Integer);
|
||||
@ -136,6 +141,21 @@ begin
|
||||
FFuncType := AFuncType;
|
||||
end;
|
||||
|
||||
function TsFuncComparer.CompareBoolean(AValue: Boolean): Boolean;
|
||||
var
|
||||
val: Double;
|
||||
begin
|
||||
Result := false;
|
||||
case FCompareOperation of
|
||||
coEqual : if AValue = FCompareBoolean then Result := true;
|
||||
coLess : if AValue < FCompareBoolean then Result := true;
|
||||
coGreater : if AValue > FCompareBoolean then Result := true;
|
||||
coLessEqual : if AValue <= FCompareBoolean then Result := true;
|
||||
coGreaterEqual : if AValue >= FCompareBoolean then Result := true;
|
||||
coNotEqual : if AValue <> FCompareBoolean then Result := true;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsFuncComparer.CompareNumber(ANumber: Double): Boolean;
|
||||
begin
|
||||
Result := false;
|
||||
@ -172,12 +192,23 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsFuncComparer.CompareError(AError: TsErrorValue): Boolean;
|
||||
begin
|
||||
Result := false;
|
||||
case FCompareOperation of
|
||||
coEqual : Result := AError = FCompareError;
|
||||
coNotEqual: Result := AError <> FCompareError;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsFuncComparer.CompareArg(ArgIndex: Integer): Boolean;
|
||||
begin
|
||||
case FCompareType of
|
||||
ctNumber : Result := CompareNumber(ArgToFloat(FArgs[ArgIndex]));
|
||||
ctString : Result := CompareString(ArgToString(FArgs[ArgIndex]));
|
||||
ctBoolean: Result := CompareBoolean(ArgToBoolean(FArgs[ArgIndex], true));
|
||||
ctEmpty : Result := CompareEmpty((ArgToString(FArgs[ArgIndex])) = '');
|
||||
ctError : Result := CompareError(ArgToError(FArgs[ArgIndex]));
|
||||
else Result := false;
|
||||
end
|
||||
end;
|
||||
@ -185,6 +216,7 @@ end;
|
||||
function TsFuncComparer.CompareCell(ASheet: TsBasicWorksheet; ARow, ACol: Integer): Boolean;
|
||||
var
|
||||
cell: PCell;
|
||||
value: Double;
|
||||
begin
|
||||
Result := false;
|
||||
cell := TsWorksheet(ASheet).FindCell(ARow, ACol);
|
||||
@ -203,7 +235,17 @@ begin
|
||||
cctDateTime:
|
||||
Result := CompareNumber(cell^.DateTimeValue);
|
||||
cctBool:
|
||||
Result := CompareNumber(IfThen(cell^.Boolvalue, 1, 0));
|
||||
if FFuncType <> ftCountIF then
|
||||
Result := CompareBoolean(cell^.Boolvalue);
|
||||
cctUTF8String:
|
||||
begin
|
||||
if TryStrToFloat(cell^.UTF8StringValue, value) then
|
||||
Result := CompareNumber(value);
|
||||
{
|
||||
if not TryStrToFloat(cell^.UTF8StringValue, value) then value := 0.0;
|
||||
Result := CompareNumber(value);
|
||||
}
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
ctString:
|
||||
@ -215,8 +257,20 @@ begin
|
||||
if (cell^.ContentType = cctUTF8String) then
|
||||
Result := CompareString(cell^.Utf8StringValue);
|
||||
end;
|
||||
ctBoolean:
|
||||
if (FCompareOperation = coNotEqual) and ((cell = nil) or (cell^.ContentType <> cctBool)) then
|
||||
Result := true
|
||||
else
|
||||
if (cell <> nil) and (cell^.ContentType = cctBool) then
|
||||
Result := CompareBoolean(cell^.BoolValue);
|
||||
ctEmpty:
|
||||
Result := CompareEmpty((cell = nil) or ((cell <> nil) and (cell^.ContentType = cctEmpty)));
|
||||
ctError:
|
||||
if (FCompareOperation = coNotEqual) and ((cell = nil) or (cell^.ContentType <> cctError)) then
|
||||
Result := true
|
||||
else
|
||||
if (cell <> nil) and (cell^.ContentType = cctError) then
|
||||
REsult := CompareError(cell^.ErrorValue);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -231,9 +285,10 @@ var
|
||||
valueSheet: TsBasicWorksheet;
|
||||
matches: Boolean;
|
||||
count: Integer;
|
||||
sum: Double;
|
||||
val, sum: Double;
|
||||
begin
|
||||
Result := ErrorResult(errArgError);
|
||||
FError := errOK;
|
||||
|
||||
if not ValidParams(Result) then
|
||||
exit;
|
||||
@ -304,7 +359,16 @@ begin
|
||||
inc(count);
|
||||
case FArgs[FValueRangeIndex].ResultType of
|
||||
rtCell: sum := sum + GetArgValue(FValueRangeIndex);
|
||||
rtCellRange: sum := sum + GetCellValue(valuesheet, r, c);
|
||||
rtCellRange:
|
||||
begin
|
||||
val := GetCellValue(valuesheet, r, c);
|
||||
if not (FFuncType in [ftCountIF, ftCountIFS]) and (FError <> errOK) then
|
||||
begin
|
||||
Result := ErrorResult(FError);
|
||||
exit;
|
||||
end;
|
||||
sum := sum + val;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end; // for c
|
||||
@ -342,6 +406,8 @@ begin
|
||||
cctNumber : Result := cell^.NumberValue;
|
||||
cctDateTime: Result := cell^.DateTimeValue;
|
||||
cctBool : if cell^.BoolValue then Result := 1.0;
|
||||
cctUTF8String : if not TryStrToFloat(cell^.UTF8StringValue, Result) then Result := 0.0;
|
||||
cctError: FError := cell^.ErrorValue;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -377,8 +443,8 @@ begin
|
||||
end;
|
||||
cctBool:
|
||||
begin
|
||||
if cell^.BoolValue then FCompareNumber := 1.0 else FCompareNumber := 0.0;
|
||||
FCompareType := ctNumber;
|
||||
FCompareBoolean := cell^.BoolValue;
|
||||
FCompareType := ctBoolean;
|
||||
end;
|
||||
cctUTF8String:
|
||||
begin
|
||||
@ -390,7 +456,10 @@ begin
|
||||
FCompareType := ctEmpty;
|
||||
end;
|
||||
cctError:
|
||||
; // what to do here?
|
||||
begin
|
||||
FCompareError := cell^.ErrorValue;
|
||||
FCompareType := ctError;
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
@ -400,6 +469,16 @@ begin
|
||||
if s = '' then
|
||||
FCompareType := ctEmpty
|
||||
else
|
||||
if (FArgs[ArgIndex].ResultType = rtError) then
|
||||
begin
|
||||
FCompareError := FArgs[ArgIndex].ResError;
|
||||
FCompareType := ctError;
|
||||
end else
|
||||
if (FArgs[ArgIndex].ResultType = rtBoolean) then
|
||||
begin
|
||||
FCompareBoolean := FArgs[ArgIndex].ResBoolean;
|
||||
FCompareType := ctBoolean;
|
||||
end else
|
||||
if TryStrToInt(s, n) then
|
||||
begin
|
||||
FCompareNumber := n;
|
||||
@ -1965,7 +2044,7 @@ begin
|
||||
Result := ErrorResult(errWrongType);
|
||||
exit;
|
||||
end;
|
||||
if not ArgToBoolean(Args[i]) then begin
|
||||
if not ArgToBoolean(Args[i], false) then begin
|
||||
b := false;
|
||||
break;
|
||||
end;
|
||||
@ -1997,13 +2076,13 @@ begin
|
||||
begin
|
||||
if IsError(Args[2], Result) then
|
||||
exit;
|
||||
if ArgToBoolean(Args[0]) then
|
||||
if ArgToBoolean(Args[0], false) then
|
||||
Result := Args[1]
|
||||
else
|
||||
Result := Args[2];
|
||||
end else
|
||||
begin
|
||||
if ArgToBoolean(Args[0]) then
|
||||
if ArgToBoolean(Args[0], false) then
|
||||
Result := Args[1]
|
||||
else
|
||||
Result.ResBoolean := false;
|
||||
@ -2027,7 +2106,7 @@ begin
|
||||
Result := ErrorResult(errWrongType);
|
||||
exit;
|
||||
end;
|
||||
if ArgToBoolean(Args[i]) then
|
||||
if ArgToBoolean(Args[i], false) then
|
||||
begin
|
||||
Result := Args[i+1];
|
||||
break;
|
||||
@ -2044,7 +2123,7 @@ begin
|
||||
if (Args[0].ResultType = rtString) then
|
||||
Result := ErrorResult(errWrongType)
|
||||
else
|
||||
Result.ResBoolean := not ArgToBoolean(Args[0]);
|
||||
Result.ResBoolean := not ArgToBoolean(Args[0], false);
|
||||
end;
|
||||
|
||||
// OR( condition1, [condition2], ... )
|
||||
@ -2064,7 +2143,7 @@ begin
|
||||
Result := ErrorResult(errWrongType);
|
||||
exit;
|
||||
end;
|
||||
if ArgToBoolean(Args[i]) then begin
|
||||
if ArgToBoolean(Args[i], false) then begin
|
||||
b := true;
|
||||
break;
|
||||
end;
|
||||
@ -2345,8 +2424,10 @@ var
|
||||
begin
|
||||
if IsError(Args[0], AResult) then
|
||||
exit;
|
||||
{ Excel still calculates the formula if the "condition" argument contains an error
|
||||
if IsError(Args[1], AResult) then
|
||||
exit;
|
||||
}
|
||||
if (Length(Args) = 3) and IsError(Args[0], AResult) then
|
||||
exit;
|
||||
|
||||
@ -3018,7 +3099,7 @@ begin
|
||||
|
||||
A1Dialect := true;
|
||||
if (Length(Args) > 3) and (Args[3].ResultType <> rtMissingArg) then
|
||||
A1Dialect := ArgToBoolean(Args[3]);
|
||||
A1Dialect := ArgToBoolean(Args[3], false);
|
||||
|
||||
sheet := '';
|
||||
if Length(Args) > 4 then
|
||||
|
@ -27,6 +27,7 @@ type
|
||||
procedure Test_COUNT;
|
||||
procedure Test_COUNTA;
|
||||
procedure Test_COUNTBLANK;
|
||||
procedure Test_COUNTIF;
|
||||
procedure Test_DATE;
|
||||
procedure Test_ERRORTYPE;
|
||||
procedure Test_EVEN;
|
||||
@ -53,6 +54,7 @@ type
|
||||
procedure Test_STDEV;
|
||||
procedure Test_STDEVP;
|
||||
procedure Test_SUM;
|
||||
procedure Test_SUMIF;
|
||||
procedure Test_SUMSQ;
|
||||
procedure Test_TIME;
|
||||
procedure Test_VAR;
|
||||
@ -87,10 +89,10 @@ begin
|
||||
CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula ABS(-10) result mismatch');
|
||||
|
||||
// Error propagation
|
||||
FWorksheet.WriteFormula(0, 0, '=1/0');
|
||||
FWorksheet.WriteErrorValue(0, 0, errIllegalRef);
|
||||
FWorksheet.WriteFormula(0, 1, 'ABS(A1)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula ABS(1/0) result mismatch');
|
||||
CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula ABS(1/0) result mismatch');
|
||||
|
||||
// Empty argument
|
||||
FWorksheet.WriteBlank(0, 0);
|
||||
@ -139,9 +141,13 @@ begin
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(cell), 'Formula #9 AND("abc",TRUE) result mismatch');
|
||||
|
||||
cell := FWorksheet.WriteFormula(0, 1, 'AND(1/0,1/0)');
|
||||
cell := FWorksheet.WriteFormula(0, 1, 'AND(1/0,0)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #10 AND(1/0,1/0) result mismatch');
|
||||
CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #10 AND(1/0,0) result mismatch');
|
||||
|
||||
cell := FWorksheet.WriteFormula(0, 1, 'AND(#REF!,#DIV/0!)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(cell), 'Formula #11 AND(#REF!,#DIV/0!) result mismatch');
|
||||
end;
|
||||
|
||||
procedure TCalcFormulaTests.Test_AVEDEV;
|
||||
@ -538,6 +544,74 @@ begin
|
||||
CheckEquals(1, FWorksheet.ReadAsNumber(4, 1), 'Formula #6 COUNTBLANK(A1:A4) result mismatch');
|
||||
end;
|
||||
|
||||
procedure TCalcFormulaTests.Test_COUNTIF;
|
||||
begin
|
||||
// Test data, range A1:B5
|
||||
FWorksheet.WriteNumber (0, 0, 10); FWorksheet.WriteFormula(0, 1, '=SQRT(-1)'); // --> #NUM!
|
||||
FWorksheet.WriteNumber (1, 0, -20); FWorksheet.WriteBlank (1, 1);
|
||||
FWorksheet.WriteFormula(2, 0, '=(1=1)'); FWorksheet.WriteNumber (2, 1, 0);
|
||||
FWorksheet.WriteText (3, 0, ''); FWorksheet.WriteText (3, 1, '5');
|
||||
FWorksheet.WriteText (4, 0, 'abc'); FWorksheet.WriteText (4, 1, 'ABC');
|
||||
FWorksheet.WriteBoolValue(5, 0, false); FWorksheet.WriteErrorValue(5, 1, errOverflow); // --> #NUM!
|
||||
|
||||
// Counts the elements in A1:B6 which are equal to "abc" (case-insensitive)
|
||||
FWorksheet.WriteFormula(0, 2, '=COUNTIF(A1:B6,"abc")');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #1 COUNTIF(A1:B6,"abc") result mismatch');
|
||||
|
||||
// Counts the elements in A1:B6 which are < 0
|
||||
FWorksheet.WriteFormula(0, 2, '=COUNTIF(A1:B6,"<0")');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #2 COUNTIF(A1:B6,"<0") result mismatch');
|
||||
|
||||
// Counts empty elements in A1:B6
|
||||
FWorksheet.WriteFormula(0, 2, '=COUNTIF(A1:B6,"")');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #3 COUNTIF(A1:B6,"") result mismatch');
|
||||
|
||||
// Counts the elements in A1:B6 which are equal to 0
|
||||
FWorksheet.WriteFormula(0, 2, '=COUNTIF(A1:B6,0)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #4 COUNTIF(A1:B6,0) result mismatch');
|
||||
|
||||
// Counts the elements in A1:B6 which are TRUE
|
||||
FWorksheet.WriteFormula(0, 2, '=COUNTIF(A1:B6,TRUE)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #5 COUNTIF(A1:B6,TRUE) result mismatch');
|
||||
|
||||
// Counts the elements in A1:B6 which are FALSE
|
||||
FWorksheet.WriteFormula(0, 2, '=COUNTIF(A1:B6,FALSE)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #4 COUNTIF(A1:B6,FALSE) result mismatch');
|
||||
|
||||
// Counts the elements in A1:B5 which are #NUM!
|
||||
FWorksheet.WriteFormula(0, 2, '=COUNTIF(A1:B6,#NUM!)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #6 COUNTIF(A1:B6,#NUM!) result mismatch');
|
||||
|
||||
// Count the elements in A1:B6 which are equal to cell A15 (empty)
|
||||
FWorksheet.WriteFormula(0, 2, '=COUNTIF(A1:B6,A15)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #7 COUNTIF(A1:B6,A15) (A15 empty) result mismatch');
|
||||
|
||||
// Count the elements in A1:B6 which are equal to cell A15 (value 10)
|
||||
FWorksheet.WriteNumber(14, 0, 10);
|
||||
FWorksheet.WriteFormula(0, 2, '=COUNTIF(A1:B6,A15)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #8 COUNTIF(A1:B6,A15) (A15 = 10) result mismatch');
|
||||
|
||||
// Count the elements in A1:B6 which are < cell A15 (value 10)
|
||||
FWorksheet.WriteFormula(0, 2, '=COUNTIF(A1:B6,"<"&A15)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(3, FWorksheet.ReadAsNumber(0, 2), 'Formula #9 COUNTIF(A1:B6,"<"&A15) (A15 = 10) result mismatch');
|
||||
|
||||
// Count the elements in A1:B6 which are equal to cell A15 (error value #NUM!)
|
||||
FWorksheet.WriteErrorValue(14, 0, errOverflow);
|
||||
FWorksheet.WriteFormula(0, 2, '=COUNTIF(A1:B6,A15)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #10 COUNTIF(A1:B6,A15) (A15 = #NUM!) result mismatch');
|
||||
end;
|
||||
|
||||
procedure TCalcFormulaTests.Test_DATE;
|
||||
var
|
||||
actualDate, expectedDate: TDate;
|
||||
@ -1843,43 +1917,7 @@ begin
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 PRODUCT(A:A6) result mismatch');
|
||||
end;
|
||||
(*
|
||||
procedure TCalcFormulaTests.Test_PRODUCT;
|
||||
begin
|
||||
FWorksheet.WriteFormula(0, 1, '=PRODUCT(1)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 PRODUCT(1) result mismatch');
|
||||
|
||||
FWorksheet.WriteFormula(0, 1, '=PRODUCT(1,2,3,4)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(24, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 PRODUCT(1,2,3,4) result mismatch');
|
||||
|
||||
FWorksheet.WriteNumber(0, 0, 1);
|
||||
FWorksheet.WriteNumber(1, 0, 2);
|
||||
FWorksheet.WriteNumber(2, 0, 3);
|
||||
FWorksheet.WriteNumber(3, 0, 4);
|
||||
|
||||
FWorksheet.WriteFormula(4, 0, '=PRODUCT(A1)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(1, FWorksheet.ReadAsNumber(4, 0), 'Formula #3 PRODUCT(A1) result mismatch');
|
||||
|
||||
FWorksheet.WriteFormula(4, 0, '=PRODUCT(A1,A2)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(2, FWorksheet.ReadAsNumber(4, 0), 'Formula #4 PRODUCT(A1,A2) result mismatch');
|
||||
|
||||
FWorksheet.WriteFormula(4, 0, '=PRODUCT(A1:A4)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(24, FWorksheet.ReadAsNumber(4, 0), 'Formula #5 PRODUCT(A1:A4) result mismatch');
|
||||
|
||||
FWorksheet.WriteFormula(4, 0, '=PRODUCT(A1,A2:A4)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(24, FWorksheet.ReadAsNumber(4, 0), 'Formula #6 PRODUCT(A1,A2:A4) result mismatch');
|
||||
|
||||
FWorksheet.WriteFormula(4, 0, '=PRODUCT(A1, 1/0, A2)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(4, 0), 'Formula #7 PRODUCT(A1, 1/0, A2) result mismatch');
|
||||
end;
|
||||
*)
|
||||
procedure TCalcFormulaTests.Test_ROUND;
|
||||
begin
|
||||
// Round positive value.
|
||||
@ -2188,8 +2226,137 @@ begin
|
||||
CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 SUM(A:A6) result mismatch');
|
||||
end;
|
||||
|
||||
{ Counts the sum of numeric elements.
|
||||
Cases checked with Excel }
|
||||
procedure TCalcFormulaTests.Test_SUMIF;
|
||||
begin
|
||||
// Test data, range A1:B5
|
||||
FWorksheet.WriteNumber (0, 0, 10); FWorksheet.WriteNumber (0, 1, -1);
|
||||
FWorksheet.WriteNumber (1, 0, 20); FWorksheet.WriteNumber (1, 1, -2);
|
||||
FWorksheet.WriteNumber (2, 0, 40); FWorksheet.WriteNumber (2, 1, 6);
|
||||
FWorksheet.WriteText (3, 0, '-40'); FWorksheet.WriteText (3, 1, '5');
|
||||
FWorksheet.WriteText (4, 0, 'abc'); FWorksheet.WriteText (4, 1, 'ABC');
|
||||
|
||||
// Work data, range A8:B12
|
||||
FWorksheet.WriteNumber ( 7, 0, 100); FWorksheet.WriteNumber ( 7, 1, -100);
|
||||
FWorksheet.WriteNumber ( 8, 0, 200); FWorksheet.WriteNumber ( 8, 1, -200);
|
||||
FWorksheet.WriteNumber ( 9, 0, 300); FWorksheet.WriteNumber ( 9, 1, -300);
|
||||
FWorksheet.WriteText (10, 0, '400'); FWorksheet.WriteText (10, 1, '-500');
|
||||
FWorksheet.WriteText (11, 0, 'xyz'); FWorksheet.WriteText (11, 1, 'XYZ');
|
||||
|
||||
|
||||
// *** Range contains numbers only ***
|
||||
|
||||
// Calculate sum of the elements in A1:B3 which are equal to 0
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B3,0)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(0, FWorksheet.ReadAsNumber(0, 2), 'Formula #1 SUMIF(A1:B3,0) result mismatch');
|
||||
|
||||
// Calculate sum of the elements in A1:B3 which are < 0
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B3,"<0")');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(-3, FWorksheet.ReadAsNumber(0, 2), 'Formula #2 SUMIF(A1:B3,"<0") result mismatch');
|
||||
|
||||
// Calculate sum of the elements in A8:B10 for which the elements in A1:B3 are equal to 10
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B3,10,A8:B10)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(100, FWorksheet.ReadAsNumber(0, 2), 'Formula #3 SUMIF(A1:B3,10,A8:B10) result mismatch');
|
||||
|
||||
// Compare cell A15
|
||||
FWorksheet.WriteNumber( 14, 0, 10);
|
||||
|
||||
// Calculate sum of the elements in A1:B3 which are equal to cell A15 (value 10)
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B3,A15)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(10, FWorksheet.ReadAsNumber(0, 2), 'Formula #4 SUMIF(A1:B3,A15) result mismatch');
|
||||
|
||||
// Calculate sum of the elements in A1:B3 which are < cell A15
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B3,"<"&A15)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(3, FWorksheet.ReadAsNumber(0, 2), 'Formula #5 SUMIF(A1:B3,"<"&A15) result mismatch');
|
||||
|
||||
// Calculate sum of the elements in A8:B10 for which the elements in A1:B3 are equal to 10
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B3,"<"&A15,A8:B10)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(-600, FWorksheet.ReadAsNumber(0, 2), 'Formula #6 SUMIF(A1:B3,"<"&A15,A8:B10) result mismatch');
|
||||
|
||||
|
||||
// *** Range contains also numeric strings ***
|
||||
|
||||
// Calculate sum of the elements in A1:B4 which are equal to -40
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B4,-40)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(-40, FWorksheet.ReadAsNumber(0, 2), 'Formula #7 SUMIF(A1:B4,-40) result mismatch');
|
||||
|
||||
// Calculate sum of the elements in A1:B4 which are < 0
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B4,"<0")');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(-43, FWorksheet.ReadAsNumber(0, 2), 'Formula #8 SUMIF(A1:B4,"<0") result mismatch');
|
||||
|
||||
// Calculate sum of the elements in A8:B11 for which the elements in A1:B4 are equal to -40
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B4,-40,A8:B11)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(400, FWorksheet.ReadAsNumber(0, 2), 'Formula #9 SUMIF(A1:B4,-40,A8:B11) result mismatch');
|
||||
|
||||
// Compare cell A15
|
||||
FWorksheet.WriteNumber( 14, 0, -40);
|
||||
|
||||
// Calculate sum of the elements in A1:B4 which are equal to cell A15
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B4,A15)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(-40, FWorksheet.ReadAsNumber(0, 2), 'Formula #10 SUMIF(A1:B4,A15) result mismatch');
|
||||
|
||||
// Calculate sum of the elements in A1:B4 which are equal <= cell A15
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B4,"<="&A15)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(-40, FWorksheet.ReadAsNumber(0, 2), 'Formula #11 SUMIF(A1:B4,"<="&A15) result mismatch');
|
||||
|
||||
// Calculate sum of the elements in A8:B11 for which the elements in A1:B4 are equal to cell A15
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B4,A15,A8:B11)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(400, FWorksheet.ReadAsNumber(0, 2), 'Formula #12 SUMIF(A1:B4,A15,A8:B11) result mismatch');
|
||||
|
||||
|
||||
// *** Range contains also non-numeric strings ***
|
||||
|
||||
// Calculate sum of the elements in A1:B5 which are equal to -40
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B5,-40)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(-40, FWorksheet.ReadAsNumber(0, 2), 'Formula #13 SUMIF(A1:B5,-40) result mismatch');
|
||||
|
||||
// Calculate sum of the elements in A1:B5 which are < 0
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B5,"<0")');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(-43, FWorksheet.ReadAsNumber(0, 2), 'Formula #14 SUMIF(A1:B5,"<0") result mismatch');
|
||||
|
||||
// Calculate sum of the elements in A8:B12 for which the elements in A1:B5 are equal to -40
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B5,-40,A8:B12)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(400, FWorksheet.ReadAsNumber(0, 2), 'Formula #15 SUMIF(A1:B5,-40,A8:B12) result mismatch');
|
||||
|
||||
|
||||
// *** Range contains also error cells ***
|
||||
|
||||
// Calculate sum of the elements in A1:B5 which are equal to -40 --> error cell must be ignored
|
||||
FWorksheet.WriteErrorValue(0, 0, errIllegalRef); // add error to A1
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B5,-40)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(-40, FWorksheet.ReadAsNumber(0, 2), 'Formula #16 SUMIF(A1:B5,-40) result mismatch');
|
||||
|
||||
// Calculate sum of the elements in A8:B13 for which the elements in A1:B6 are equal to 40
|
||||
FWorksheet.WriteErrorValue(9, 0, errIllegalRef); // The value corresponding to 40 is an error now
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B5,40,A8:B12)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 2), 'Formula #17 SUMIF(A1:B5,40,A8:B12) result mismatch');
|
||||
|
||||
|
||||
// *** Compare cell contains an error (A15)
|
||||
FWorksheet.WriteFormula( 14, 0, '=1/0');
|
||||
|
||||
// Calculate sum of the elements in A1:B5 which are equal to cell A15 (containing #DIV/0!)
|
||||
FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B5,A15)');
|
||||
FWorksheet.CalcFormulas;
|
||||
CheckEquals(0, FWorksheet.ReadAsNumber(0, 2), 'Formula #18 SUMIF(A1:B5,A15) result mismatch');
|
||||
end;
|
||||
|
||||
procedure TCalcFormulaTests.Test_SUMSQ;
|
||||
begin
|
||||
// Test data
|
||||
|
Loading…
Reference in New Issue
Block a user