diff --git a/components/fpspreadsheet/unit-tests/common/calcformulatests.pas b/components/fpspreadsheet/unit-tests/common/calcformulatests.pas index 4e2001be1..6d24e5614 100644 --- a/components/fpspreadsheet/unit-tests/common/calcformulatests.pas +++ b/components/fpspreadsheet/unit-tests/common/calcformulatests.pas @@ -20,31 +20,30 @@ type procedure SetUp; override; procedure TearDown; override; published - procedure Test_ABS; - procedure Test_ACOS; - procedure Test_ADDRESS; - procedure Test_AND; - procedure Test_ASIN; - procedure Test_ATAN; - procedure Test_AVEDEV; - procedure Test_AVERAGE; - procedure Test_AVERAGEIF; - procedure Test_CEILING; - procedure Test_COLUMN; - procedure Test_CONCATENATE; - procedure Test_COUNT; - procedure Test_COUNTA; - procedure Test_COUNTBLANK; - procedure Test_COUNTIF; + end; + + TCalcDateTimeFormulaTests = class(TCalcFormulaTests) + published procedure Test_DATE; +// procedure Test_DATEDIF; to be written +// procedure Test_DATEVALUE; to be written +// procedure Test_DAY; to be written +// procedure Test_HOUR; to be written +// procedure Test_MINUTE; to be written +// procedure Test_MONTH; to be written +// procedure Test_NOW; to be written +// procedure Test_SECOND; to be written + procedure Test_TIME; +// procedure Test_TIMEVALUE; to be written +// procedure Test_TODAY; to be written +// procedure Test_WEEKDAY; to be written +// procedure Test_YEAR; to be written + end; + + TCalcInfoFormulaTests = class(TCalcFormulaTests) + published procedure Test_ERRORTYPE; - procedure Test_EVEN; - procedure Test_EXACT; - procedure Test_FLOOR; - procedure Test_IF; procedure Test_IFERROR; - procedure Test_INDEX; - procedure Test_INDIRECT; procedure Test_ISBLANK; procedure Test_ISERR; procedure Test_ISERROR; @@ -54,33 +53,112 @@ type procedure Test_ISNUMBER; procedure Test_ISREF; procedure Test_ISTEXT; - procedure Test_LEN; + end; + + TCalcLogicalFormulaTests = class(TCalcFormulaTests) + published + procedure Test_AND; +// procedure Test_FALSE; to be written + procedure Test_IF; +// procedure Test_XLFN.IFS; to be written + procedure Test_NOT; + procedure Test_OR; +// procedure Test_TRUE; to be written + end; + + TCalcLookupFormulaTests = class(TCalcFormulaTests) + published + procedure Test_ADDRESS; + procedure Test_COLUMN; + // procedure Test_HYPERLINK -- to be written + procedure Test_INDEX; + procedure Test_INDIRECT; + procedure Test_MATCH; + procedure Test_ROW; + end; + + TCalcMathFormulaTests = class(TCalcFormulaTests) + published + procedure Test_ABS; + procedure Test_ACOS; +// procedure Test_ACOSH; to be written + procedure Test_ASIN; +// procedure Test_ASINH; to be written + procedure Test_ATAN; +// procedure Test_ATANH; to be written + procedure Test_CEILING; +// procedure Test_COS; to be written +// procedure Test_COSH; to be written +// procedure Test_DEGREES; to be written + procedure Test_EVEN; +// procedure Test_EXP; to be written +// procedure Test_FACT; to be written + procedure Test_FLOOR; +// procedure Test_INT; to be written +// procedure Test_LN; to be written procedure Test_LOG; procedure Test_LOG10; - procedure Test_LOWER; - procedure Test_MATCH; +// procedure Test_MOD; to be written + procedure Test_ODD; +// procedure Test_PI; to be written + procedure Test_POWER; + procedure Test_RADIANS; +// procedure Test_RAND; to be written + procedure Test_ROUND; +// procedure Test_ROUNDDOWN; to be written +// procedure Test_ROUNDUP; to be written +// procedure Test_SIGN; to be written +// procedure Test_SIN; to be written +// procedure Test_SINH; to be written + procedure Test_SQRT; +// procedure Test_TAN; to be written +// procedure Test_TANH; to be written + end; + + TCalcStatsFormulaTests = class(TCalcFormulaTests) + published + procedure Test_AVEDEV; + procedure Test_AVERAGE; + procedure Test_AVERAGEIF; + // procedure Test_AVERAGEIFS; to be written + procedure Test_COUNT; + procedure Test_COUNTA; + procedure Test_COUNTBLANK; + procedure Test_COUNTIF; +// procedure Test_COUNITFS; to be written procedure Test_MAX; procedure Test_MIN; - procedure Test_NOT; - procedure Test_ODD; - procedure Test_OR; - procedure Test_POWER; procedure Test_PRODUCT; - procedure Test_RADIANS; - procedure Test_ROUND; - procedure Test_ROW; - procedure Test_SQRT; procedure Test_STDEV; procedure Test_STDEVP; procedure Test_SUM; procedure Test_SUMIF; +// procedure Test_SUMIFS; to be written procedure Test_SUMSQ; - procedure Test_TIME; - procedure Test_UPPER; procedure Test_VAR; procedure Test_VARP; end; + TCalcTextFormulaTests = class(TCalcFormulaTests) + published +// procedure Test_CHAR; to be written +// procedure Test_CODE; to be written + procedure Test_CONCATENATE; + procedure Test_EXACT; +// procedure Test_LEFT; to be written + procedure Test_LEN; + procedure Test_LOWER; +// procedure Test_MID; to be written +// procedure Test_REPLACE; to be written +// procedure Test_REPT; to be written +// procedure Test_RIGHT; to be written +// procedure Test_SUBSTITUTE; to be written +// procedure Test_TEXT; to be written +// procedure Test_TRIM; to be written + procedure Test_UPPER; +// procedure Test_VALUE; to be written + end; + implementation procedure TCalcFormulaTests.Setup; @@ -95,3987 +173,34 @@ begin FWorkbook.Free; end; -procedure TCalcFormulaTests.Test_ABS; -begin - // Positive value - FWorksheet.WriteNumber(0, 0, +10); - FWorksheet.WriteFormula(0, 1, 'ABS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula ABS(10) result mismatch'); +// *** Date/time formula tests +{$I testcases_calcdatetimeformulas.inc} - // Negative value - FWorksheet.WriteNumber(0, 0, -10); - FWorksheet.WriteFormula(0, 1, 'ABS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula ABS(-10) result mismatch'); +// *** Information formula tests +{$I testcases_calcinfoformulas.inc} - // Error propagation - FWorksheet.WriteErrorValue(0, 0, errIllegalRef); - FWorksheet.WriteFormula(0, 1, 'ABS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula ABS(1/0) result mismatch'); +// *** Logical formula tests +{$I testcases_calclogicalformulas.inc} - // Empty argument - FWorksheet.WriteBlank(0, 0); - FWorksheet.WriteFormula(0, 1, 'ABS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula ABS([blank_cell]) result mismatch'); -end; +// *** Lookup formula tests +{$I testcases_calclookupformulas.inc} -procedure TCalcFormulaTests.Test_ACOS; -begin - FWorksheet.WriteFormula(0, 1, '=ACOS(0.5)'); - FWorksheet.CalcFormulas; - CheckEquals(pi/3, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #1 ACOS(0.5) result mismatch'); +// *** Math formula tests +{$I testcases_calcmathformulas.inc} - FWorksheet.WriteFormula(0, 1, '=ACOS(0)'); - FWorksheet.CalcFormulas; - CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #2 ACOS(0) result mismatch'); +// *** Statistical formula tests +{$I testcases_calcstatsformulas.inc} - FWorksheet.WriteFormula(0, 1, '=ACOS(1)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #3 ACOS(1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ACOS(-1)'); - FWorksheet.CalcFormulas; - CheckEquals(pi, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #4 ACOS(-1) result mismatch'); - - // Out-of-domain - FWorksheet.WriteFormula(0, 1, '=ACOS(2)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #5 ACOS(2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ACOS(-2)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #6 ACOS(-2) result mismatch'); - - // Boolean argument - FWorksheet.WriteFormula(0, 1, '=ACOS(FALSE)'); - FWorksheet.CalcFormulas; - CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #7 ACOS(FALSE) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ACOS(TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #8 ACOS(TRUE) result mismatch'); - - // Numeric string - FWorksheet.WriteFormula(0, 1, '=ACOS("1")'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #9 ACOS("1") result mismatch'); - - // Non-numeric string - FWorksheet.WriteFormula(0, 1, '=ACOS("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #10 ACOS("abc") result mismatch'); - - // Error argument - FWorksheet.WriteFormula(0, 1, '=ACOS(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #11 ACOS(1/0) result mismatch'); - - // Cell with boolean value - FWorksheet.WriteFormula(0, 0, '=(1=1)'); - FWorksheet.WriteFormula(0, 1, '=ACOS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #12 ACOS(A1) (A1: (1=1)) result mismatch'); - - // Cell with numeric string - FWorksheet.WriteText(0, 0, '1'); - FWorksheet.WriteFormula(0, 1, '=ACOS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #13 ACOS(A1) (A1: "1") result mismatch'); - - // Cell with non-numeric string - FWorksheet.WriteText(0, 0, 'abc'); - FWorksheet.WriteFormula(0, 1, '=ACOS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #14 ACOS(A1) (A1: "abc") result mismatch'); - - // Empty cell - FWorksheet.WriteBlank(0, 0); // Empty A1 - FWorksheet.WriteFormula(0, 1, '=ACOS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 'Formula #15 ACOS(A1) (A1: empty) result mismatch'); - - // Cell with error - FWorksheet.WriteErrorValue(0, 0, errIllegalRef); - FWorksheet.WriteFormula(0, 1, '=ACOS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #16 ACOS(A1) (A1: #REF!) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_ADDRESS; -begin - // Default values only - FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,1)'); - FWorksheet.CalcFormulas; - CheckEquals('$A$1', FWorksheet.ReadAsText(0, 1), 'Formula #1 ADDRESS(1,1) result mismatch'); - - // 3rd parameter --> absolute address - FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,1)'); - FWorksheet.CalcFormulas; - CheckEquals('$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #2 ADDRESS(1,2,1) result mismatch'); - - // 3rd parameter --> absolute row - FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,2)'); - FWorksheet.CalcFormulas; - CheckEquals('B$1', FWorksheet.ReadAsText(0, 1), 'Formula #3 ADDRESS(1,2,2) result mismatch'); - - // 3rd parameter --> absolute col - FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,3)'); - FWorksheet.CalcFormulas; - CheckEquals('$B1', FWorksheet.ReadAsText(0, 1), 'Formula 43 ADDRESS(1,2,3) result mismatch'); - - // 3rd parameter --> relative address - FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,4)'); - FWorksheet.CalcFormulas; - CheckEquals('B1', FWorksheet.ReadAsText(0, 1), 'Formula #5 ADDRESS(1,2,4) result mismatch'); - - // missing 3rd parameter --> absolute address - FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,)'); - FWorksheet.CalcFormulas; - CheckEquals('$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #6 ADDRESS(1,2,) result mismatch'); - - // Combined with ROW() and COLUMN() formulas - FWorksheet.WriteFormula(0, 1, '=ADDRESS(ROW(),COLUMN())'); - FWorksheet.CalcFormulas; - CheckEquals('$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #7 ADDRESS(ROW(), COLUMN()) result mismatch'); - - // A1 dialect - FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,1,TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals('$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #8 ADDRESS(1,2,1,TRUE) result mismatch'); - - // R1C1 dialect - FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,1,FALSE)'); - FWorksheet.CalcFormulas; - CheckEquals('R1C2', FWorksheet.ReadAsText(0, 1), 'Formula #9 ADDRESS(1,2,1,FALSE) result mismatch'); - - // Missing dialect argument (must use A1 then) - FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,1,)'); - FWorksheet.CalcFormulas; - CheckEquals('$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #10 ADDRESS(1,2,1,) result mismatch'); - - // Sheet name - FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,1,TRUE,"Sheet1")'); - FWorksheet.CalcFormulas; - CheckEquals('Sheet1!$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #11 ADDRESS(1,2,1,TRUE,"Sheet1") result mismatch'); - - // Quoted sheet name - FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,1,TRUE,"Sheet 1")'); - FWorksheet.CalcFormulas; - CheckEquals('''Sheet 1''!$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #12 ADDRESS(1,2,1,TRUE,"Sheet 1") result mismatch'); - - // Elements of address in cells - FWorksheet.WriteNumber(0, 0, 1); // Row (1) - FWorksheet.WriteNumber(1, 0, 2); // Column (2) - FWorksheet.WriteNumber(2, 0, 4); // Flags (relative) - FWorksheet.WriteBoolValue(3, 0, FALSE); // Dialect (R1C1) - FWorksheet.WriteText(4, 0, 'Sheet 1'); // Worksheet - FWorksheet.WriteFormula(0, 1, '=ADDRESS(A1,A2,A3,A4,A5)'); - FWorksheet.CalcFormulas; - CheckEquals('''Sheet 1''!R[1]C[2]', FWorksheet.ReadAsText(0, 1), 'Formula #13 ADDRESS(A1,A2,A3,A4,A5) result mismatch'); - - // dto., Sheetname cell empty - FWorksheet.WriteFormula(0, 1, '=ADDRESS(A1,A2,A3,A4,A10)'); - FWorksheet.CalcFormulas; - CheckEquals('R[1]C[2]', FWorksheet.ReadAsText(0, 1), 'Formula #13 ADDRESS(A1,A2,A3,A4,A10) (A10 blank) result mismatch'); - - // dto., Dialect cell empty (--> is assume to be 0 --> RC dialect) - FWorksheet.WriteFormula(0, 1, '=ADDRESS(A1,A2,A3,A9,A10)'); - FWorksheet.CalcFormulas; - CheckEquals('R[1]C[2]', FWorksheet.ReadAsText(0, 1), 'Formula #13 ADDRESS(A1,A2,A3,A9,A11) (A9,A10 blank) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_AND; -var - cell: PCell; -begin - cell := FWorksheet.WriteFormula(0, 1, 'AND(1=1,2=2)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 AND(1=1,2=2) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'AND(1=2,2=2)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #2 AND(1=2,2=2) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'AND(1=1,2=1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 AND(1=1,2=1) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'AND(1=2,2=1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #4 AND(1=2,2=1) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'AND(1/0,2=2)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #5 AND(1/0,2=2) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'AND(1,TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #6 AND(1,TRUE) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'AND(0,TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #7 AND(0,TRUE) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'AND("0",TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(cell), 'Formula #8 AND("0",TRUE) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'AND("abc",TRUE)'); - 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,0)'); - FWorksheet.CalcFormulas; - 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_ASIN; -begin - FWorksheet.WriteFormula(0, 1, '=ASIN(0.5)'); - FWorksheet.CalcFormulas; - CheckEquals(pi/6, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #1 ASIN(0.5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ASIN(0)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #2 ASIN(0) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ASIN(1)'); - FWorksheet.CalcFormulas; - CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #3 ASIN(1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ASIN(-1)'); - FWorksheet.CalcFormulas; - CheckEquals(-pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #4 ASIN(-1) result mismatch'); - - // Out-of-domain - FWorksheet.WriteFormula(0, 1, '=ASIN(2)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #5 ASIN(2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ASIN(-2)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #6 ASIN(-2) result mismatch'); - - // Boolean argument - FWorksheet.WriteFormula(0, 1, '=ASIN(FALSE)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #7 ASIN(FALSE) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ASIN(TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #8 ASIN(TRUE) result mismatch'); - - // Numeric string - FWorksheet.WriteFormula(0, 1, '=ASIN("1")'); - FWorksheet.CalcFormulas; - CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #9 ASIN("1") result mismatch'); - - // Non-numeric string - FWorksheet.WriteFormula(0, 1, '=ASIN("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #10 ASIN("abc") result mismatch'); - - // Error argument - FWorksheet.WriteFormula(0, 1, '=ASIN(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #11 ASIN(1/0) result mismatch'); - - // Cell with boolean value - FWorksheet.WriteFormula(0, 0, '=(1=1)'); - FWorksheet.WriteFormula(0, 1, '=ASIN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #12 ASIN(A1) (A1: (1=1)) result mismatch'); - - // Cell with numeric string - FWorksheet.WriteText(0, 0, '1'); - FWorksheet.WriteFormula(0, 1, '=ASIN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #13 ASIN(A1) (A1: "1") result mismatch'); - - // Cell with non-numeric string - FWorksheet.WriteText(0, 0, 'abc'); - FWorksheet.WriteFormula(0, 1, '=ASIN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #14 ASIN(A1) (A1: "abc") result mismatch'); - - // Empty cell - FWorksheet.WriteBlank(0, 0); // Empty A1 - FWorksheet.WriteFormula(0, 1, '=ASIN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #15 ASIN(A1) (A1: empty) result mismatch'); - - // Cell with error - FWorksheet.WriteErrorValue(0, 0, errIllegalRef); - FWorksheet.WriteFormula(0, 1, '=ASIN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #16 ASIN(A1) (A1: #REF!) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_ATAN; -begin - FWorksheet.WriteFormula(0, 1, '=ATAN(0)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #1 ATAN(0) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ATAN(1)'); - FWorksheet.CalcFormulas; - // Soll result from Wolfram Alpha - CheckEquals(0.78539816339744830961566084, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #2 ATAN(1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ATAN(-1)'); - FWorksheet.CalcFormulas; - // Soll result from Wolfram Alpha - CheckEquals(-0.78539816339744830961566084, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #3 ATAN(-1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ATAN(1E300)'); - FWorksheet.CalcFormulas; - CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #4 ATAN(1E300) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ATAN(-1E300)'); - FWorksheet.CalcFormulas; - CheckEquals(-pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #5 ATAN(-1E300) result mismatch'); - - // Boolean argument - FWorksheet.WriteFormula(0, 1, '=ATAN(FALSE)'); - FWorksheet.CalcFormulas; - CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #6 ATAN(FALSE) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ATAN(TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(0.78539816339744830961566084, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #7 ATAN(TRUE) result mismatch'); - - // Numeric string - FWorksheet.WriteFormula(0, 1, '=ATAN("1")'); - FWorksheet.CalcFormulas; - CheckEquals(0.78539816339744830961566084, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #8 ATAN("1") result mismatch'); - - // Non-numeric string - FWorksheet.WriteFormula(0, 1, '=ATAN("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #9 ATAN("abc") result mismatch'); - - // Error argument - FWorksheet.WriteFormula(0, 1, '=ATAN(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #10 ATAN(1/0) result mismatch'); - - // Cell with boolean value - FWorksheet.WriteFormula(0, 0, '=(1=1)'); - FWorksheet.WriteFormula(0, 1, '=ATAN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0.78539816339744830961566084, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #11 ATAN(A1) (A1: (1=1)) result mismatch'); - - // Cell with numeric string - FWorksheet.WriteText(0, 0, '1'); - FWorksheet.WriteFormula(0, 1, '=ATAN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0.78539816339744830961566084, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #12 ATAN(A1) (A1: "1") result mismatch'); - - // Cell with non-numeric string - FWorksheet.WriteText(0, 0, 'abc'); - FWorksheet.WriteFormula(0, 1, '=ATAN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #13 ATAN(A1) (A1: "abc") result mismatch'); - - // Empty cell - FWorksheet.WriteBlank(0, 0); // Empty A1 - FWorksheet.WriteFormula(0, 1, '=ATAN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 ATAN(A1) (A1: empty) result mismatch'); - - // Cell with error - FWorksheet.WriteErrorValue(0, 0, errIllegalRef); - FWorksheet.WriteFormula(0, 1, '=ATAN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #15 ATAN(A1) (A1: #REF!) result mismatch'); -end; - - -procedure TCalcFormulaTests.Test_AVEDEV; -const - EPS = 1E-8; -begin - // Test data - FWorksheet.WriteNumber (0, 0, 1); - FWorksheet.WriteNumber (1, 0, -2); - FWorksheet.WriteNumber (2, 0, -3); - FWorksheet.WriteText (3, 0, '4'); - FWorksheet.WriteText (4, 0, 'abc'); - FWorksheet.WriteFormula(5, 0, '=1/0'); - - // Literal values - FWorksheet.WriteFormula(0, 1, '=AVEDEV(1)'); - FWorksheet.CalcFormulas; - CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 AVEDEV(1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV(1,-2)'); - FWorksheet.CalcFormulas; - CheckEquals(1.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #2 AVEDEV(1,-2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV("4")'); // although string considered to be numeric - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 AVEDEV("4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV(1,-2,-3,"4")'); - FWorksheet.CalcFormulas; - CheckEquals(2.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #4 AVEDEV(1,2,3,"4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 AVEDEV("abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV("")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 AVEDEV("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV(1,-2,-3,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 AVEDEV(1,-2,-3,"abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 AVEDEV(1/0) result mismatch'); - - // Cell references - FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 AVEDEV(A1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV(A10)'); // empty cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #8 AVEDEV(A10)(A10=empty) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals(1.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #9 AVEDEV(A1,A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1:A3)'); // "real" numeric values - FWorksheet.CalcFormulas; - CheckEquals(1.555555556, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #10 AVEDEV(A1:A3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1,A2:A3)'); // several ranges - FWorksheet.CalcFormulas; - CheckEquals(1.555555556, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #11 AVEDEV(A1,A2:A3) result mismatch'); - - // Cell references pointing to string cells - FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1:A4)'); // real and string numeric values - FWorksheet.CalcFormulas; - CheckEquals(2.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #12 AVEDEV(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1:A5)'); // real and string values --> ignore string - FWorksheet.CalcFormulas; - CheckEquals(2.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #13 AVEDEV(A1:A5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1:A4,A8:A10)'); // real and string values and blanks - FWorksheet.CalcFormulas; - CheckEquals(2.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #14 AVEDEV(A1:A4,A8:A10) result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1, 1/0, A2)'); // error in argument - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 AVEDEV(A1, 1/0, A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1:A6)'); // error in cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 AVEDEV(A1:A6) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_AVERAGE; -begin - // Test data - FWorksheet.WriteNumber (0, 0, 10); - FWorksheet.WriteNumber (1, 0, 20); - FWorksheet.WriteNumber (2, 0, 30); - FWorksheet.WriteText (3, 0, '40'); - FWorksheet.WriteText (4, 0, 'abc'); - FWorksheet.WriteFormula(5, 0, '=1/0'); - - // Literal values - FWorksheet.WriteFormula(0, 1, '=AVERAGE(10)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 AVERAGE(10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE(10,20)'); - FWorksheet.CalcFormulas; - CheckEquals(15, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 AVERAGE(10,20) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE("40")'); // although string considered to be numeric - FWorksheet.CalcFormulas; - CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 AVERAGE("40") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE(10,20,30,"40")'); - FWorksheet.CalcFormulas; - CheckEquals(25, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 AVERAGE(10,20,30,"40") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 AVERAGE("abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE("")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 AVERAGE("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE(10,20,30,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 AVERAGE(10,20,30,"abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 AVERAGE(1/0) result mismatch'); - - // Cell references - FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 AVERAGE(A1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE(A10)'); // empty cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 AVERAGE(A10)(A10=empty) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals(15, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 AVERAGE(A1,A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1:A3)'); // "real" numeric values - FWorksheet.CalcFormulas; - CheckEquals(20, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 AVERAGE(A1:A3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1,A2:A3)'); // several ranges - FWorksheet.CalcFormulas; - CheckEquals(20, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 AVERAGE(A1,A2:A3) result mismatch'); - - // Cell references pointing to string cells - FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1:A4)'); // real and string numeric values - FWorksheet.CalcFormulas; - CheckEquals(25, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 AVERAGE(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1:A5)'); // real and string values --> ignore string - FWorksheet.CalcFormulas; - CheckEquals(25, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 AVERAGE(A1:A5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1:A4,A8:A10)'); // real and string values and blanks - FWorksheet.CalcFormulas; - CheckEquals(25, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 AVERAGE(A1:A4,A8:A10) result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1, 1/0, A2)'); // error in argument - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 AVERAGE(A1, 1/0, A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1:A6)'); // error in cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 AVERAGE(A:A6) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_AVERAGEIF; -const - EPS = 1E-8; -begin - // Test data, value range A1:B9 - // A1:A9 - compare values // B1:B9 -- calculation values - FWorksheet.WriteText(0, 0, 'Abc'); FWorksheet.WriteNumber (0, 1, 100); - FWorksheet.WriteText(1, 0, 'Abc'); FWorksheet.WriteNumber (1, 1, 200); - FWorksheet.WriteText(2, 0, 'bc'); FWorksheet.WriteNumber (2, 1, 300); - FWorksheet.WriteText(3, 0, 'a'); FWorksheet.WriteNumber (3, 1, 400); - FWorksheet.WriteText(4, 0, 'bc'); FWorksheet.WriteText (4, 1, '500'); - FWorksheet.WriteText(5, 0, 'abc'); FWorksheet.WriteText (5, 1, 'no number'); - FWorksheet.WriteText(6, 0, ''); FWorksheet.WriteNumber (6, 1, 600); - FWorksheet.WriteDateTime(7, 0, EncodeDate(2025,2,1)); FWorksheet.WriteNumber (7, 1, 700); - FWorksheet.WriteText(8, 0, 'abc'); FWorksheet.WriteBoolValue (8, 1, TRUE); - FWorksheet.WriteText(9, 0, 'abc'); FWorksheet.WriteErrorValue(9, 1, errIllegalRef); - - // *** two-argument calls - - // Average value of all cells in the second column with are <=200 - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(B1:B8,"<=200")'); - FWorksheet.CalcFormulas; - CheckEquals(150, FWorksheet.ReadAsNumber(0, 2), 'Formula #1 AVERAGEIF(B1:B8,"<=200") result mismatch'); - - // Average value of all cells in the second column with are >=400 - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(B1:B8,">=400")'); - FWorksheet.CalcFormulas; - CheckEquals(550, FWorksheet.ReadAsNumber(0, 2), 'Formula #2 AVERAGEIF(B1:B8,">=400") result mismatch'); - - // Average value of all cells in the second column with are <0 - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(B1:B9,"<0")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #3 AVERAGEIF(B1:B9,"<0") result mismatch'); - - // *** three-argument calls - - // Average value of all cells in the second column for which the first column cell is 'abc' (case-insensitive)' - // ... numeric cells only (incl numeric text cell) - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A5,"abc",B1:B5)'); - FWorksheet.CalcFormulas; - CheckEquals(150, FWorksheet.ReadAsNumber(0, 2), 'Formula #4 AVERAGEIF(A1:A5,"abc",B1:B5) result mismatch'); - - // ... dto, but check case-insensitivity of search phrase - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A5,"ABC",B1:B5)'); - FWorksheet.CalcFormulas; - CheckEquals(150, FWorksheet.ReadAsNumber(0, 2), 'Formula #5 AVERAGEIF(A1:A5,"ABC",B1:B5) result mismatch'); - - // ... including non-numeric text cell - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A7,"abc",B1:B7)'); - FWorksheet.CalcFormulas; - CheckEquals(150, FWorksheet.ReadAsNumber(0, 2), 'Formula #6 AVERAGEIF(A1:A7,"abc",B1:B7) result mismatch'); - - // ... including boolean cell - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A9,"abc",B1:B9)'); - FWorksheet.CalcFormulas; - CheckEquals(150, FWorksheet.ReadAsNumber(0, 2), 'Formula #7 AVERAGEIF(A1:A9,"abc",B1:B9) result mismatch'); - - // ... including error cell - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A10,"abc",B1:B10)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 2), 'Formula #8 AVERAGEIF(A1:A10,"abc",B1:B10) result mismatch'); - - // ToDo: CompareStringsWithWildcards does not handle a mask such as "*b" like Excel - { - // Search for text cells by wildcards - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A8,"*bc",B1:B8)'); - FWorksheet.CalcFormulas; - CheckEquals(275, FWorksheet.ReadAsNumber(0, 2), 'Formula #9 AVERAGEIF(A1:A8,"*bc",B1:B8) result mismatch'); - } - - // Search for date cells (matching cell found) - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A8,DATE(2025,2,1),B1:B8)'); - FWorksheet.CalcFormulas; - CheckEquals(700, FWorksheet.ReadAsNumber(0, 2), 'Formula #9 AVERAGEIF(A1:A8,DATE(2025,2,1),B1:B8) result mismatch'); - - // Search for date cell (no matching cell found) - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A8,DATE(2000,2,1),B1:B8)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #9 AVERAGEIF(A1:A8,DATE(2000,2,1),B1:B8) result mismatch'); - - // Search for empty cells - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A8,"",B1:B8)'); - FWorksheet.CalcFormulas; - CheckEquals(600, FWorksheet.ReadAsNumber(0, 2), 'Formula #10 AVERAGEIF(A1:A8,"",B1:B8) result mismatch'); - - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A8,"=",B1:B8)'); - FWorksheet.CalcFormulas; - CheckEquals(600, FWorksheet.ReadAsNumber(0, 2), 'Formula #11 AVERAGEIF(A1:A8,"Abc",B1:B8) result mismatch'); - - // Search for non-empty cells - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A8,"<>",B1:B8)'); - FWorksheet.CalcFormulas; - CheckEquals(2200/6, FWorksheet.ReadAsNumber(0, 2), EPS, 'Formula #12 AVERAGEIF(A1:A8,"<>",B1:B8) result mismatch'); - - // Compare with reference cell A20 - FWorksheet.WriteText(19, 0, 'abc'); // A20 = "abc" - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A9,A20,B1:B9)'); - FWorksheet.CalcFormulas; - CheckEquals(150, FWorksheet.ReadAsNumber(0, 2), 'Formula #13 AVERAGEIF(A1:A9,A20,B1:B9) (A20="abc") result mismatch'); - - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A9,"<>"&A20,B1:B9)'); - FWorksheet.CalcFormulas; - CheckEquals(500, FWorksheet.ReadAsNumber(0, 2), 'Formula #13 AVERAGEIF(A1:A9,"<>"&A20,B1:B9) (A20="abc") result mismatch'); - - // Error in first argument - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(#DIV/0!,"<10")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #14 AVERAGEIF(#DIV/0,"<10") result mismatch'); - - // Error in second argument - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A9,#DIV/0!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #15 AVERAGEIF(A1:A9,#DIV/0) result mismatch'); - - // Error in third argument - FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A9,"=",#DIV/0!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #16 AVERAGEIF(A1:A9,"=",#DIV/0) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_CEILING; -begin - // Examples from https://exceljet.net/functions/ceiling-function - FWorksheet.WriteFormula(0, 1, '=CEILING(10,3)'); - FWorksheet.CalcFormulas; - CheckEquals(12, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 CEILING(10,3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=CEILING(36,7)'); - FWorksheet.CalcFormulas; - CheckEquals(42, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 CEILING(36,7) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=CEILING(610,100)'); - FWorksheet.CalcFormulas; - CheckEquals(700, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 CEILING(610,100) result mismatch'); - - // Negative arguments - FWorksheet.WriteFormula(0, 1, '=CEILING(-5.4,-1)'); - FWorksheet.CalcFormulas; - CheckEquals(-5, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 CEILING(-5.4,-1) result mismatch'); - - // Zero significance - FWorksheet.WriteFormula(0, 1, '=CEILING(-5.4,0)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 CEILING(-5.4,0) result mismatch'); - - // Different signs of the arguments - FWorksheet.WriteFormula(0, 1, '=CEILING(-5.4,1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #6 CEILING(-5.4,1) result mismatch'); - - // Arguments as string - FWorksheet.WriteFormula(0, 1, '=CEILING("A",1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 CEILING("A",1) result mismatch'); - FWorksheet.WriteFormula(0, 1, '=CEILING(5.4,"A")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #8 CEILING(5.4,"A") result mismatch'); - - // Arguments as boolean - FWorksheet.WriteFormula(0, 1, '=CEILING(TRUE(),1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #9 CEILING(TRUE(),1) result mismatch'); - FWorksheet.WriteFormula(0, 1, '=CEILING(5.4, TRUE())'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #10 CEILING(5.4, TRUE()) result mismatch'); - - // Arguments with errors - FWorksheet.WriteFormula(0, 1, '=CEILING(1/0,1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #11 CEILING(1/0, 1) result mismatch'); - FWorksheet.WriteFormula(0, 1, '=CEILING(5.4, 1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #12 CEILING(5.4, 1/0) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_COLUMN; -begin - // Get column number of specified cell - FWorksheet.WriteFormula(0, 1, '=COLUMN(B2)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 COLUMN(B2) result mismatch'); - - // Get col of the formula cell --- NOT CORRECTLY IMPLEMENTED IN FPS - FWorksheet.WriteFormula(0, 1, '=COLUMN()'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 COLUMN() result mismatch'); // This would be the Excel result! - //CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #2 COLUMN() result mismatch'); - - // Error value as argument - FWorksheet.WriteFormula(0, 1, '=COLUMN(#REF!)'); - FWorksheet.CalcFormulas; - //CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 COLUMN() result mismatch'); - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #3 COLUMN(#REF!) result mismatch'); - - // Cell containing an error as argument - FWorksheet.WriteFormula(1, 1, '=1/0'); // cell B2 - FWorksheet.WriteFormula(0, 2, '=COLUMN(B2)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #4 COLUMN(B2) (B2 contains error) result mismatch'); - -end; - -procedure TCalcFormulaTests.Test_CONCATENATE; -begin - // Test data - FWorksheet.WriteText (0, 0, 'abc'); // A1 - FWorksheet.WriteText (1, 0, 'def'); // A2 - FWorksheet.WriteNumber (2, 0, 123); // A3 - FWorksheet.WriteBoolValue (3, 0, true); // A4 - FWorksheet.WriteErrorvalue(4, 0, errIllegalRef); // A5 - - // Concatenate 2 literal strings - FWorksheet.WriteFormula(0, 1, '=CONCATENATE("abc","def")'); - FWorksheet.CalcFormulas; - CheckEquals('abcdef', FWorksheet.ReadAsText(0, 1), 'Formula #1 CONCATENATE("abc","def") result mismatch'); - - // Concatenate 3 literal strings - FWorksheet.WriteFormula(0, 1, '=CONCATENATE("abc","def","ghi")'); - FWorksheet.CalcFormulas; - CheckEquals('abcdefghi', FWorksheet.ReadAsText(0, 1), 'Formula #2 CONCATENATE("abc","def","ghi") result mismatch'); - - // Concatenate 2 literal strings and number - FWorksheet.WriteFormula(0, 1, '=CONCATENATE("abc","def",123)'); - FWorksheet.CalcFormulas; - CheckEquals('abcdef123', FWorksheet.ReadAsText(0, 1), 'Formula #3 CONCATENATE("abc","def",123) result mismatch'); - - // Concatenate two numbers - FWorksheet.WriteFormula(0, 1, '=CONCATENATE(123,456)'); - FWorksheet.CalcFormulas; - CheckEquals('123456', FWorksheet.ReadAsText(0, 1), 'Formula #4 CONCATENATE(123,456) result mismatch'); - - { -- this test will not work in the file because Excel writes a localized "TRUE" to the cell - // Concatenate string and boolean - FWorksheet.WriteFormula(0, 1, '=CONCATENATE("abc",TRUE())'); - FWorksheet.CalcFormulas; - CheckEquals('abcTRUE', FWorksheet.ReadAsText(0, 1), 'Formula #5 CONCATENATE("abc",TRUE()) result mismatch'); - } - - // Concatenate 2 string cells - FWorksheet.WriteFormula(0, 1, '=CONCATENATE(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals('abcdef', FWorksheet.ReadAsText(0, 1), 'Formula #5 CONCATENATE(A1,A2) result mismatch'); - - // Concatenate string and numeric cells - FWorksheet.WriteFormula(0, 1, '=CONCATENATE(A1,A3)'); - FWorksheet.CalcFormulas; - CheckEquals('abc123', FWorksheet.ReadAsText(0, 1), 'Formula #6 CONCATENATE(A1,A3) result mismatch'); - - // Concatenate string and error cells - FWorksheet.WriteFormula(0, 1, '=CONCATENATE(A1,A5)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #6 CONCATENATE(A1,A5) result mismatch'); - -end; - -procedure TCalcFormulaTests.Test_COUNT; -begin - // Test data - FWorksheet.WriteNumber (0, 0, 10); - FWorksheet.WriteNumber (1, 0, 20); - FWorksheet.WriteNumber (2, 0, 30); - FWorksheet.WriteText (3, 0, '40'); - FWorksheet.WriteText (4, 0, 'abc'); - FWorksheet.WriteFormula(5, 0, '=1/0'); - - // Count literal values - FWorksheet.WriteFormula(0, 1, '=COUNT(10)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 COUNT(10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNT(20,10,"abc",40)'); - FWorksheet.CalcFormulas; - CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 COUNT(20,10,"abc",40) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNT("40")'); // although string considered to be numeric - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 COUNT("40") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNT("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 COUNT("abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNT("")'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 COUNT("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNT(1/0)'); // argument error does NOT propagate to formula result - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #6 COUNT(1/0) result mismatch'); - - // Count in cell references - FWorksheet.WriteFormula(0, 1, '=COUNT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 COUNT(A1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNT(A10)'); // empty cell - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 COUNT(A10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNT(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 COUNT(A1,A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNT(A1:A3)'); // "real" numeric values - FWorksheet.CalcFormulas; - CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 COUNT(A1:A3) result mismatch'); - - // Cell references pointing to string cells - FWorksheet.WriteFormula(0, 1, '=COUNT(A1:A4)'); // "real" and string numeric values - FWorksheet.CalcFormulas; - CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 COUNT(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNT(A1:A5)'); // "real" and string values - FWorksheet.CalcFormulas; - CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 COUNT(A1:A5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNT(A1:A5,A8:A10)'); // real and string values and blanks - FWorksheet.CalcFormulas; - CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 COUNT(A1:A5,A8:A10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNT(A1,A2:A5)'); // several ranges - FWorksheet.CalcFormulas; - CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 COUNT(A1,A2:A5) result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 1, '=COUNT(A1, 1/0, A2)'); // error in argument - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #15 COUNT(A1, 1/0, A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNT(A1:A6)'); // error in cell - FWorksheet.CalcFormulas; - CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #15 COUNT(A1:A6) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_COUNTA; -begin - FWorksheet.WriteFormula(0, 1, '=COUNTA("")'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 COUNTA("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNTA(10)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 COUNTA(10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNTA(20,10,"abc",40)'); - FWorksheet.CalcFormulas; - CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 COUNTA(20,10,"abc",40) result mismatch'); - - FWorksheet.WriteNumber(0, 0, 20); - FWorksheet.WriteNumber(1, 0, 10); - FWorksheet.WriteText(2, 0, 'abc'); - FWorksheet.WriteNumber(3, 0, 40); - - FWorksheet.WriteFormula(4, 1, '=COUNTA(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(4, 1), 'Formula #4 COUNTA(A1) result mismatch'); - - FWorksheet.WriteFormula(4, 1, '=COUNTA(A10)'); // A10 is empty - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(4, 1), 'Formula #5 COUNTA(A10) result mismatch'); - - FWorksheet.WriteFormula(4, 1, '=COUNTA(A2,A3)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(4, 1), 'Formula #6 COUNTA(A2,A3) result mismatch'); - - FWorksheet.WriteFormula(4, 1, '=COUNTA(A1:A4)'); - FWorksheet.CalcFormulas; - CheckEquals(4, FWorksheet.ReadAsNumber(4, 1), 'Formula #7 COUNTA(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(4, 1, '=COUNTA(A1:A10)'); - FWorksheet.CalcFormulas; - CheckEquals(4, FWorksheet.ReadAsNumber(4, 1), 'Formula #8 COUNTA(A1:A10) result mismatch'); - - FWorksheet.WriteFormula(4, 1, '=COUNTA(A1,A2:A10)'); - FWorksheet.CalcFormulas; - CheckEquals(4, FWorksheet.ReadAsNumber(4, 1), 'Formula #9 COUNTA(A1,A2:A10) result mismatch'); - - FWorksheet.WriteFormula(4, 1, '=COUNTA(A1, 1/0, A3)'); - FWorksheet.CalcFormulas; - CheckEquals(3, FWorksheet.ReadAsNumber(4, 1), 'Formula #10 COUNTA(A1, 1/0, A3) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_COUNTBLANK; -begin - // The next 2 tests are successful, but not accepted by Excel which only wants - // a "range" as argument in COUNTBLANK. - - FWorksheet.WriteFormula(0, 1, '=COUNTBLANK("")'); // empty string is not "blank" - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 COUNTBLANK("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=COUNTBLANK(10)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 COUNTBLANK(10) result mismatch'); - - // The following tests are conformal to Excel. - - FWorksheet.WriteNumber(0, 0, 20); - FWorksheet.WriteText(1, 0, 'abc'); - - FWorksheet.WriteFormula(4, 1, '=COUNTBLANK(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(4, 1), 'Formula #3 COUNTBLANK(A1) result mismatch'); - - FWorksheet.WriteFormula(4, 1, '=COUNTBLANK(A10)'); // A10 is empty - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(4, 1), 'Formula #4 COUNTBLANK(A10) result mismatch'); - - FWorksheet.WriteFormula(4, 1, '=COUNTBLANK(A1:A4)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(4, 1), 'Formula #5 COUNTBLANK(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(2, 0, '=1/0'); - FWorksheet.WriteFormula(4, 1, '=COUNTBLANK(A1:A4)'); - FWorksheet.CalcFormulas; - 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'); - - // Error in 1st argument - FWorksheet.WriteFormula(0, 2, '=COUNTIF(#REF!,1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 2), 'Formula #7 COUNTIF(#REF!,1) result mismatch'); - - // Error in both arguments - FWorksheet.WriteFormula(0, 2, '=COUNTIF(#REF!,#REF!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 2), 'Formula #8 COUNTIF(#REF!,#REF!) 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 #9 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 #10 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 #11 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 #12 COUNTIF(A1:B6,A15) (A15 = #NUM!) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_DATE; -var - actualDate, expectedDate: TDate; -begin - // Normal date - FWorksheet.WriteFormula(0, 1, '=DATE(2025,1,22)'); - FWorksheet.CalcFormulas; - expectedDate := EncodeDate(2025, 1, 22); - FWorksheet.ReadAsDateTime(0, 1, actualDate); - CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#1 Formula DATE(2025,1,22) result mismatch'); - - // Two-digit year - FWorksheet.WriteFormula(0, 1, '=DATE(90,1,22)'); - FWorksheet.CalcFormulas; - expectedDate := EncodeDate(1990, 1, 22); - FWorksheet.ReadAsDateTime(0, 1, actualDate); - CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#2 Formula DATE(90,1,22) result mismatch'); - - // Negative year - FWorksheet.WriteFormula(0, 1, '=DATE(-2000,1,22)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), '#3 Formula DATE(90,1,22) result mismatch'); - - // Too-large year - FWorksheet.WriteFormula(0, 1, '=DATE(10000,1,22)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), '#4 Formula DATE(10000,1,22) result mismatch'); - - // Month > 12 - FWorksheet.WriteFormula(0, 1, '=DATE(2008,14,2)'); - FWorksheet.CalcFormulas; - expectedDate := EncodeDate(2009, 2, 2); - FWorksheet.ReadAsDateTime(0, 1, actualDate); - CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#5 Formula DATE(2008,14,2) result mismatch'); - - // Month < 1 - FWorksheet.WriteFormula(0, 1, '=DATE(2008,-3,2)'); - FWorksheet.CalcFormulas; - expectedDate := EncodeDate(2007, 9, 2); - FWorksheet.ReadAsDateTime(0, 1, actualDate); - CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#6 Formula DATE(2008,-3,2) result mismatch'); - - // Day > Days in month - FWorksheet.WriteFormula(0, 1, '=DATE(2008,1,35)'); - FWorksheet.CalcFormulas; - expectedDate := EncodeDate(2008, 2, 4); - FWorksheet.ReadAsDateTime(0, 1, actualDate); - CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#7 Formula DATE(2008,1,35) result mismatch'); - - // Day < 1 - FWorksheet.WriteFormula(0, 1, '=DATE(2008,1,-15)'); - FWorksheet.CalcFormulas; - expectedDate := EncodeDate(2007, 12, 16); - FWorksheet.ReadAsDateTime(0, 1, actualDate); - CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#8 Formula DATE(2008,1,-15) result mismatch'); - - // Month > 12 and Day > Days in month - FWorksheet.WriteFormula(0, 1, '=DATE(2008,14,50)'); - FWorksheet.CalcFormulas; - expectedDate := EncodeDate(2009, 3, 22); - FWorksheet.ReadAsDateTime(0, 1, actualDate); - CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#9 Formula DATE(2008,14,50) result mismatch'); - - // Month > 12 and Day < 1 - FWorksheet.WriteFormula(0, 1, '=DATE(2008,14,-10)'); - FWorksheet.CalcFormulas; - expectedDate := EncodeDate(2009, 1, 21); - FWorksheet.ReadAsDateTime(0, 1, actualDate); - CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#10 Formula DATE(2008,14,-10) result mismatch'); - - // Month < 1 and Day > Days in month - FWorksheet.WriteFormula(0, 1, '=DATE(2008,-3,50)'); - FWorksheet.CalcFormulas; - expectedDate := EncodeDate(2007,10,20); - FWorksheet.ReadAsDateTime(0, 1, actualDate); - CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#11 Formula DATE(2008,-3,50) result mismatch'); - - // Month < 1 and Day < 1 in month - FWorksheet.WriteFormula(0, 1, '=DATE(2008,-3,-10)'); - FWorksheet.CalcFormulas; - expectedDate := EncodeDate(2007,8,21); - FWorksheet.ReadAsDateTime(0, 1, actualDate); - CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#12 Formula DATE(2008,-3,-10) result mismatch'); - - // Error in year - FWorksheet.WriteFormula(0, 1, '=DATE(1/0,1,22)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), '#13 Formula DATE(1/0,1,22) result mismatch'); - - // Error in month - FWorksheet.WriteFormula(0, 1, '=DATE(2025, 1/0, 22)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), '#14 Formula DATE(2025, 1/0, 22) result mismatch'); - - // Error in day - FWorksheet.WriteFormula(0, 1, '=DATE(2025, 1, 1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), '#15 Formula DATE(2025, 1, 1/0) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_ERRORTYPE; -begin - // Explicit error type - FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(#REF!)'); - FWorksheet.CalcFormulas; - CheckEquals(ord(errIllegalRef), FWorksheet.ReadAsNumber(0, 1), 'Formula #1 ERROR.TYPE(#REF!) result mismatch'); - - // No error in cell --> #N/A - FWorksheet.WriteNumber(0, 0, 123); - FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 1), 'Formula #2 ERROR.TYPE (no error!) result mismatch'); - - // #NULL! error - FWorksheet.WriteNumber(0, 0, 12); - FWorksheet.WriteNumber(1, 0, -2); - - // ToDo: Space as argument separator not detected correctly! -{ - This currently is not handled by FPS... - FWorksheet.WriteFormula(2, 0, '=SUM(A1 A2)'); // missing comma --> #NULL! - FWorksheet.WriteFormula(2, 0, '=ERROR.TYPE(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(ord(errEmptyIntersection), FWorksheet.ReadAsNumber(2, 0), 'Formula #1 ERROR.TYPE (#NULL!) result mismatch'); -} - - // #REF! error - FWorksheet.WriteFormula(2, 0, '=SUM(A1,A2)'); - FWorksheet.DeleteRow(0); // This creates the #REF! error in the sum cell A2 - FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(A2)'); - FWorksheet.CalcFormulas; - CheckEquals(ord(errIllegalRef), FWorksheet.ReadAsNumber(0, 1), 'Formula #3 ERROR.TYPE (#REF!) result mismatch'); - - // #VALUE! error - FWorksheet.WriteText(0, 0, 'a'); - FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(1+A1)'); - FWorksheet.CalcFormulas; - CheckEquals(ord(errWrongType), FWorksheet.ReadAsNumber(0, 1), 'Formula #4 ERROR.TYPE #VALUE! result mismatch'); - - // #DIV/0! error - FWorksheet.WriteFormula(0, 0, '=1/0'); - FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(ord(errDivideByZero), FWorksheet.ReadAsNumber(0, 1), 'Formula #5 ERROR.TYPE #DIV/0! result mismatch'); - - // #NUM! error - FWorksheet.WriteFormula(0, 0, '=SQRT(-1)'); - FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(ord(errOverflow), FWorksheet.ReadAsNumber(0, 1), 'Formula #6 ERROR.TYPE #NUM! result mismatch'); - - // ToDo: Create #NAME? error node when identifier is not found. Parser always raises an exception during scanning - maybe there should be a TsErrorExprNode? - - { --- not correctly detected by FPS parser ... - // #NAME? error - FWorksheet.WriteFormula(0, 0, '=S_Q_R_T(-1)'); - FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(ord(errWrongName), FWorksheet.ReadAsNumber(0, 1), 'Formula #1 ERROR.TYPE #NAME? result mismatch'); - } - - // #N/A error - FWorksheet.WriteNumber(0, 0, 10); - FWorksheet.WriteNumber(1, 0, 20); - FWorksheet.WriteFormula(2, 0, '=MATCH(-10,A1:A2,0)'); - FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(A3)'); - FWorksheet.CalcFormulas; - CheckEquals(ord(errArgError), FWorksheet.ReadAsNumber(0, 1), 'Formula #7 ERROR.TYPE #N/A result mismatch'); -end; - -procedure TCalcFormulaTests.Test_EVEN; -begin - FWorksheet.WriteFormula(0, 1, '=EVEN(1.23)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 EVEN(1.23) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=EVEN(2.34)'); - FWorksheet.CalcFormulas; - CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 EVEN(2.34) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=EVEN(-1.23)'); - FWorksheet.CalcFormulas; - CheckEquals(-2, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 EVEN(-1.23) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=EVEN(-2.34)'); - FWorksheet.CalcFormulas; - CheckEquals(-4, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 EVEN(-2.34) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=EVEN(0.0)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 EVEN(0.0) result mismatch'); - - // String as argument - FWorksheet.WriteFormula(0, 1, '=EVEN("1")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 EVEN("1") result mismatch'); - - // Empty argument - FWorksheet.WriteFormula(0, 1, '=EVEN()'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 EVEND() result mismatch'); - - // Error in argument - FWorksheet.WriteFormula(0, 1, '=EVEN(#REF!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #8 EVEN(#REF!) result mismatch'); - - // Error in argument cell - FWorksheet.WriteErrorValue(0, 0, errIllegalRef); - FWorksheet.WriteFormula(0, 1, '=EVEN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #9 EVEN(A1) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_EXACT; -var - cell: PCell; -begin - // Test cells - FWorksheet.WriteText(0, 0, 'abc'); // A1 - FWorksheet.WriteText(1, 0, 'ABC'); // A2 - FWorksheet.WriteText(2, 0, 'abcd'); // A3 - FWorksheet.WriteText(3, 0, 'äöü'); // A4 - FWorksheet.WriteText(4, 0, 'Äöü'); // A5 - FWorksheet.WriteErrorValue(5, 0, errDivideByZero); // A6 - FWorksheet.WriteNumber(6, 0, 123); // A7 - FWorksheet.WriteText(7, 0, '123'); // A8 - - // Same literal strings - cell := FWorksheet.WriteFormula(0, 1, '=EXACT("abc", "abc")'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #1 EXACT("abc","abc") result type mismatch:'); - CheckEquals(true, cell^.BoolValue, 'Formula #1 EXACT("abc", "abc") result mismatch.'); - - // Same strings but different case - cell := FWorksheet.WriteFormula(0, 1, '=EXACT("abc", "ABC")'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #2 EXACT("abc","ABC") result type mismatch:'); - CheckEquals(false, cell^.BoolValue, 'Formula #2 EXACT("abc", "ABC") result mismatch.'); - - // Lengths different - cell := FWorksheet.WriteFormula(0, 1, '=EXACT("abc", "abcd")'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #3 EXACT("abc","abcd") result type mismatch:'); - CheckEquals(false, cell^.BoolValue, 'Formula #3 EXACT("abc", "abcd") result mismatch.'); - - // Same unicode chars - cell := FWorksheet.WriteFormula(0, 1, '=EXACT("äöü", "äöü")'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #4 EXACT("äöü","äöü") result type mismatch:'); - CheckEquals(true, cell^.BoolValue, 'Formula #4 EXACT("äöü", "äöü") result mismatch.'); - - // Different unicode case - cell := FWorksheet.WriteFormula(0, 1, '=EXACT("äöü", "Äöü")'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #5 EXACT("äöü","Äöü") result type mismatch:'); - CheckEquals(false, cell^.BoolValue, 'Formula #5 EXACT("äöü", "Äöü") result mismatch.'); - - // Cells with same ASCII strings - cell := FWorksheet.WriteFormula(0, 1, '=EXACT(A1, A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #6 EXACT(A1,A1) result type mismatch:'); - CheckEquals(true, cell^.BoolValue, 'Formula #6 EXACT(A1,A1) result mismatch.'); - - // Cells with same strings, but different case - cell := FWorksheet.WriteFormula(0, 1, '=EXACT(A1, A2)'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #7 EXACT(A1,A2) result type mismatch:'); - CheckEquals(false, cell^.BoolValue, 'Formula #7 EXACT(A1,A2) result mismatch.'); - - // Cells with almost same strings, but different lengths - cell := FWorksheet.WriteFormula(0, 1, '=EXACT(A1, A3)'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #8 EXACT(A1,A3) result type mismatch:'); - CheckEquals(false, cell^.BoolValue, 'Formula #8 EXACT(A1,A3) result mismatch.'); - - // Cells with ASCII and UTF8 - cell := FWorksheet.WriteFormula(0, 1, '=EXACT(A1, A4)'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #9 EXACT(A1,A4) result type mismatch:'); - CheckEquals(false, cell^.BoolValue, 'Formula #9 EXACT(A1,A4) result mismatch.'); - - // Cells with same Unicode strings - cell := FWorksheet.WriteFormula(0, 1, '=EXACT(A4, A4)'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #10 EXACT(A4,A4) result type mismatch:'); - CheckEquals(true, cell^.BoolValue, 'Formula #10 EXACT(A4,A4) result mismatch.'); - - // Cells with almost same Unicode strings, but different case - cell := FWorksheet.WriteFormula(0, 1, '=EXACT(A4, A5)'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #11 EXACT(A4,A5) result type mismatch:'); - CheckEquals(false, cell^.BoolValue, 'Formula #11 EXACT(A4,A5) result mismatch.'); - - // Error (#DIV/0!) in one cell - FWorksheet.WriteFormula(0, 1, '=EXACT(A6, A5)'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctError, 'Formula #12 EXACT(A6,A5) result type mismatch:'); - CheckEquals(true, cell^.ErrorValue = errDivideByZero, 'Formula #12 EXACT(A6,A5) result mismatch.'); - - // Compare numeric string with same number - FWorksheet.WriteFormula(0, 1, '=EXACT(12,"12")'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #13 EXACT(12,"12") result type mismatch:'); - CheckEquals(true, cell^.BoolValue, 'Formula #13 EXACT(12,"12") result mismatch.'); - - // dto with cells - FWorksheet.WriteFormula(0, 1, '=EXACT(A7,A8)'); - FWorksheet.CalcFormulas; - CheckEquals(true, cell^.ContentType = cctBool, 'Formula #14 EXACT(A7,A8) result type mismatch:'); - CheckEquals(true, cell^.BoolValue, 'Formula #14 EXACT(A7,A8) result mismatch.'); - -end; - -procedure TCalcFormulaTests.Test_FLOOR; -begin - FWorksheet.WriteFormula(0, 1, '=FLOOR(10,3)'); - FWorksheet.CalcFormulas; - CheckEquals(9, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 FLOOR(10,3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=FLOOR(36,7)'); - FWorksheet.CalcFormulas; - CheckEquals(35, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 FLOOR(36,7) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=FLOOR(610,100)'); - FWorksheet.CalcFormulas; - CheckEquals(600, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 FLOOR(610,100) result mismatch'); - - // Negative value, negative significance - FWorksheet.WriteFormula(0, 1, '=FLOOR(-5.4,-2)'); - FWorksheet.CalcFormulas; - CheckEquals(-4, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 FLOOR(-5.4,-2) result mismatch'); - - // Negative value, positive significance - FWorksheet.WriteFormula(0, 1, '=FLOOR(-5.4,2)'); - FWorksheet.CalcFormulas; - CheckEquals(-6, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 FLOOR(-5.4,2) result mismatch'); - - // Positive value, negative significance - FWorksheet.WriteFormula(0, 1, '=FLOOR(5.4,-2)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #6 FLOOR(5.4,-2) result mismatch'); - - // Zero significance - FWorksheet.WriteFormula(0, 1, '=FLOOR(-5.4,0)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 FLOOR(-5.4,0) result mismatch'); - - // Arguments as string - FWorksheet.WriteFormula(0, 1, '=FLOOR("A",1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #8 FLOOR("A",1) result mismatch'); - FWorksheet.WriteFormula(0, 1, '=FLOOR(5.4,"A")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #9 FLOOR(5.4,"A") result mismatch'); - - // Arguments as boolean - FWorksheet.WriteFormula(0, 1, '=FLOOR(TRUE(),1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #10 FLOOR(TRUE(),1) result mismatch'); - FWorksheet.WriteFormula(0, 1, '=FLOOR(5.4, TRUE())'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #11 FLOOR(5.4, TRUE()) result mismatch'); - - // Arguments with errors - FWorksheet.WriteFormula(0, 1, '=FLOOR(1/0,1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #12 FLOOR(1/0, 1) result mismatch'); - FWorksheet.WriteFormula(0, 1, '=FLOOR(5.4, 1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #13 FLOOR(5.4, 1/0) result mismatch'); - -end; - -procedure TCalcFormulaTests.Test_IF; -begin - FWorksheet.WriteNumber(0, 0, 256.0); - - // 3 arguments - FWorksheet.WriteFormula(0, 1, '=IF(A1>=100,"ok","not ok")'); - FWorksheet.CalcFormulas; - CheckEquals('ok', FWorksheet.ReadAsText(0, 1), 'Formula #1 IF(A1>=100,"ok","not ok") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=IF(A1<100,"ok","not ok")'); - FWorksheet.CalcFormulas; - CheckEquals('not ok', FWorksheet.ReadAsText(0, 1), 'Formula #2 IF(A1<100,"ok","not ok") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=IF(1,"ok","not ok")'); - FWorksheet.CalcFormulas; - CheckEquals('ok', FWorksheet.ReadAsText(0, 1), 'Formula #3 IF(1,"ok","not ok") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=IF(0,"ok","not ok")'); - FWorksheet.CalcFormulas; - CheckEquals('not ok', FWorksheet.ReadAsText(0, 1), 'Formula #4 IF(0,"ok","not ok") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=IF("1","ok","not ok")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 IF("1","ok","not ok") result mismatch'); - - // 2 arguments - FWorksheet.WriteFormula(0, 1, '=IF(A1>=100,"ok")'); - FWorksheet.CalcFormulas; - CheckEquals('ok', FWorksheet.ReadAsText(0, 1), 'Formula #6 IF(A1>=100,"ok") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=IF(A1<100,"ok")'); - FWorksheet.CalcFormulas; - CheckEquals('FALSE', FWorksheet.ReadAsText(0, 1), 'Formula #7 IF(A1<100,"ok") result mismatch'); - - // Error propagation: error in 3rd argument - result is non-error argument - FWorksheet.WriteFormula(0, 1, '=IF(A1>=100, "ok", 1/0)'); - FWorksheet.CalcFormulas; - CheckEquals('ok', FWorksheet.ReadAsText(0, 1), 'Formula #8 IF(A1>=100,"ok",1/0) result mismatch'); - - // Error propagation: error in 3rd argument - result is error argument - FWorksheet.WriteFormula(0, 1, '=IF(A1<100, "ok", 1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #9 IF(A1<100,"ok",1/0) result mismatch'); - - // Error propagation: error in 2nd argument - result is error argument - FWorksheet.WriteFormula(0, 1, '=IF(A1>=100, 1/0,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #10 IF(A1>=100,1/0,"abc") result mismatch'); - - // Error propagation: error in 2nd argument - result is 3rd argument - FWorksheet.WriteFormula(0, 1, '=IF(A1<100, 1/0,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals('abc', FWorksheet.ReadAsText(0, 1), 'Formula #11 IF(A1<100,1/0,"abc") result mismatch'); - - // Error propagaton: error in 1st argument - FWorksheet.WriteFormula(0, 0, '=1/0'); - FWorksheet.WriteFormula(0, 1, '=IF(A1>=100,"ok","not ok")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #12 IF(A1>=100,"ok","not ok") with A1=1/0 result mismatch'); -end; - -procedure TCalcFormulaTests.Test_IFERROR; -begin - FWorksheet.WriteFormula(0, 1, '=IFERROR("abc", "ERROR")'); - FWorksheet.CalcFormulas; - CheckEquals('abc', FWorksheet.ReadAsText(0, 1), 'Formula #1 IFERROR("abc","ERROR") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=IFERROR(#N/A, "ERROR")'); - FWorksheet.CalcFormulas; - CheckEquals('ERROR', FWorksheet.ReadAsText(0, 1), 'Formula #2 IFERROR(#N/A,"ERROR") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=IFERROR(#N/A, #DIV/0!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #3 IFERROR(#N/A,#DIV/0!) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_INDEX; -var - sh: TsWorksheet; -begin - // Sample adapted from https://www.ionos.de/digitalguide/online-marketing/verkaufen-im-internet/excel-index-funktion/ - sh := FWorksheet; - sh.WriteText(0, 0, 'Name'); sh.WriteText (0, 1, '1991'); sh.WriteText (0, 2, '1992'); - sh.WriteText(1, 0, 'Peter'); sh.WriteNumber(1, 1, 78); sh.WriteNumber(1, 2, 81); - sh.WriteText(2, 0, 'Frank'); sh.WriteNumber(2, 1, 55); sh.WriteNumber(2, 2, 66); - sh.WriteText(3, 0, 'Louise'); sh.WriteNumber(3, 1, 42); sh.WriteNumber(3, 2, 59); - sh.WriteText(4, 0, 'Valery'); sh.WriteNumber(4, 1, 12); sh.WriteNumber(4, 2, 33); - sh.Writetext(5, 0, 'Eva'); sh.WriteNumber(5, 1, 40); sh.WriteNumber(5, 2, 66); - - // Cell at third row and first column in range B2:C6 - FWorksheet.WriteFormula(10, 0, '=INDEX(B2:C6,3,1)'); - FWorksheet.CalcFormulas; - CheckEquals(42, FWorksheet.ReadAsNumber(10,0), 'Formula #1 INDEX(B2:F3,3,1) result mismatch'); - - // Sample similar to that in unit formulatests: - - FWorksheet.Clear; - FWorksheet.WriteText (0, 0, 'A'); // A1 - FWorksheet.WriteText (0, 1, 'B'); // B1 - FWorksheet.WriteText (0, 2, 'C'); // C1 - FWorksheet.WriteNumber(1, 0, 10); // A2 - FWorksheet.WriteNumber(1, 1, 20); // B2 - FWorksheet.WriteNumber(1, 2, 30); // C2 - FWorksheet.WriteNumber(2, 0, 11); // A3 - FWorksheet.WriteNumber(2, 1, 22); // B3 - FWorksheet.WriteNumber(2, 2, 33); // C4 - - FWorksheet.WriteFormula(0, 5, 'INDEX(A1:C3,1,1)'); - FWorksheet.CalcFormulas; - CheckEquals('A', FWorksheet.ReadAsText(0, 5), 'Formula #2 INDEX(A1:C3,1,1) result mismatch'); - - FWorksheet.WriteFormula(0, 5, 'INDEX(A1:C1,3)'); - FWorksheet.CalcFormulas; - CheckEquals('C', FWorksheet.ReadAsText(0, 5), 'Formula #3 INDEX(A1:C1,3) result mismatch'); - - FWorksheet.WriteFormula(0, 5, 'INDEX(A1:A3,2)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 5), 'Formula #4 INDEX(A1:A3,3) result mismatch'); - - FWorksheet.WriteFormula(0, 5, 'INDEX(A1:C2,1,10)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 5), 'Formula #5 INDEX(A1:C2,1,10) result mismatch'); - - FWorksheet.WriteFormula(0, 5, 'SUM(INDEX(A1:C3,0,2))'); // Sum of numbers in 2nd column of A1:C3 - FWorksheet.CalcFormulas; - CheckEquals(42, FWorksheet.ReadAsNumber(0, 5), 'Formula #6 SUM(INDEX(A1:C3,0,2)) result mismatch'); - - FWorksheet.WriteFormula(0, 5, 'SUM(INDEX(A1:C3,2,0))'); // Sum of numbers in 2nd row of A1:C3 - FWorksheet.CalcFormulas; - CheckEquals(60, FWorksheet.ReadAsNumber(0, 5), 'Formula #7 SUM(INDEX(A1:C3,2,0)) result mismatch'); - - // Now the same tests, but across sheets - FOtherWorksheet.WriteFormula(0, 5, 'INDEX(Sheet1!A1:C3,1,1)'); - FWorkbook.CalcFormulas; - CheckEquals('A', FOtherWorksheet.ReadAsText(0, 5), 'Formula #8 INDEX(Sheet1!A1:C3,1,1) result mismatch'); - - FOtherWorksheet.WriteFormula(0, 5, 'INDEX(Sheet1!A1:C1,3)'); - FWorkbook.CalcFormulas; - CheckEquals('C', FOtherWorksheet.ReadAsText(0, 5), 'Formula #9 INDEX(Sheet1!A1:C1,3) result mismatch'); - - FOtherWorksheet.WriteFormula(0, 5, 'INDEX(Sheet1!A1:A3,2)'); - FWorkbook.CalcFormulas; - CheckEquals(10, FOtherWorksheet.ReadAsNumber(0, 5), 'Formula #10 INDEX(Sheet1!A1:A3,3) result mismatch'); - - FOtherWorksheet.WriteFormula(0, 5, 'INDEX(Sheet1!A1:C2,1,10)'); - FWorkbook.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FOtherWorksheet.ReadAsText(0, 5), 'Formula #11 INDEX(Sheet1!A1:C2,1,10) result mismatch'); - - FOtherWorksheet.WriteFormula(0, 5, 'SUM(INDEX(Sheet1!A1:C3,0,2))'); // Sum of numbers in 2nd column of A1:C3 - FWorkbook.CalcFormulas; - CheckEquals(42, FOtherWorksheet.ReadAsNumber(0, 5), 'Formula #6 SUM(Sheet1!INDEX(A1:C3,0,2)) result mismatch'); - - FOtherWorksheet.WriteFormula(0, 5, 'SUM(INDEX(Sheet1!A1:C3,2,0))'); // Sum of numbers in 2nd row of A1:C3 - FWorkbook.CalcFormulas; - CheckEquals(60, FOtherWorksheet.ReadAsNumber(0, 5), 'Formula #7 SUM(Sheet1!INDEX(A1:C3,2,0)) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_INDIRECT; -begin - // *** Test data *** - FWorksheet.WriteNumber (0, 0, 10); // A1 - FWorksheet.WriteNumber (1, 0, 20); // A2 - FWorksheet.WriteNumber (2, 0, 30); // A3 - FWorksheet.WriteText (3, 0, 'A1'); // A4 - FWorksheet.WriteErrorValue(4, 0, errDivideByZero); // A5 - FWorksheet.WriteText (5, 0, 'A'); // A6 - FWorksheet.WriteNumber (6, 0, 1); // A7 - FWorksheet.WriteText (7, 0, 'Sheet2'); // A8 - FWorksheet.WriteText (8, 0, 'Sheet2!A1:A3'); // A9 - FWorksheet.WriteFormula(9, 0, '=A6&A7'); // A10 - FOtherWorksheet.WriteNumber(0, 0, 1000); // Sheet2!A1 - FOtherWorksheet.WriteNumber(1, 0, 2000); // Sheet2!A2 - FOtherWorksheet.WriteNumber(2, 0, 3000); // Sheet2!A3 - - // *** Single cell references *** - FWorksheet.WriteFormula(0, 1, '=INDIRECT("A1")'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 INDIRECT("A1") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=INDIRECT("A4")'); - FWorksheet.CalcFormulas; - CheckEquals('A1', FWorksheet.ReadAsText(0, 1), 'Formula #2 INDIRECT("A4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=INDIRECT(A4)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 INDIRECT(A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=INDIRECT("Sheet2!A1")'); - FWorksheet.CalcFormulas; - CheckEquals(1000, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 INDIRECT("Sheet2!A1") result mismatch'); - - // Constructing cell address from other cells - FWorksheet.WriteFormula(0, 1, '=INDIRECT(A6&A7)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 INDIRECT(A6&A7) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=INDIRECT(A10)'); // A10 = A6&A7 - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #6 INDIRECT(A10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=INDIRECT(A8&"!"&A6&A7)'); // --> "Sheet2!A1" - FWorksheet.CalcFormulas; - CheckEquals(1000, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 INDIRECT(A8&"!"&A6&A7) result mismatch'); - - // Constructing cell address from other cells and constant - FWorksheet.WriteFormula(0, 1, '=INDIRECT(A6&"1")'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 INDIRECT(A6&"1") result mismatch'); - - // Error in indirectly addressed cell - FWorksheet.WriteFormula(0, 1, '=INDIRECT(A5)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #9 INDIRECT(A5) result mismatch'); - - // Circular reference - FWorksheet.WriteFormula(0, 1, '=INDIRECT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #10 INDIRECT(A1) result mismatch'); - - - // *** Cell range references *** - - FWorksheet.WriteFormula(0, 1, '=SUM(INDIRECT("A1:A3"))'); - FWorksheet.CalcFormulas; - CheckEquals(60, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 SUM(INDIRECT("A1:A3")) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(INDIRECT("Sheet2!A1:A3"))'); - FWorksheet.CalcFormulas; - CheckEquals(6000, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 SUM(INDIRECT("Sheet2!A1:A3")) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(INDIRECT(A9))'); - FWorksheet.CalcFormulas; - CheckEquals(6000, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 SUM(INDIRECT(A9)) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(INDIRECT(A8&"!"&A4&":A3"))'); - FWorksheet.CalcFormulas; - CheckEquals(6000, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 SUM(INDIRECT(A8&"!"&A4&":A3")) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_ISBLANK; -var - cell: PCell; -begin - cell := FWorksheet.WriteFormula(0, 1, '=ISBLANK(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISBLANK(A1) with A1=blank result mismatch'); - - FWorksheet.WriteText(0, 0, ''); - cell := FWorksheet.WriteFormula(0, 1, '=ISBLANK(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISBLANK(A1) with A1='' result mismatch'); - - // No argument - { In Excel the "no argument" case is not accepted (runtime error, no error code) - cell := FWorksheet.WriteFormula(0, 1, '=ISBLANK()'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 ISBLANK() result mismatch'); - } - - // String - cell := FWorksheet.WriteFormula(0, 1, '=ISBLANK("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #4 ISBLANK("abc") result mismatch'); - - // Some Excel oddity: an empty string is not "blank"... - cell := FWorksheet.WriteFormula(0, 1, '=ISBLANK("")'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISBLANK("") result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 0, '=1/0'); - cell := FWorksheet.WriteFormula(0, 1, '=ISBLANK(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISBLANK(A1) with A1=1/0 result mismatch'); - CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #6 ISBLANK(A1) with A1=1/0 result mismatch'); -end; - -procedure TCalcFormulaTests.Test_ISERR; -var - cell: PCell; -begin - // Hard coded expression with error #DIV/0! - cell := FWorksheet.WriteFormula(0, 1, '=ISERR(#DIV/0!)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISERR(1/0) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, '=ISERR(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISERR(1/0) result mismatch'); - - // Hard coded expression without error - cell := FWorksheet.WriteFormula(0, 1, '=ISERR(0/1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 ISERR(0/1) result mismatch'); - - // Reference to cell with error - FWorksheet.WriteFormula(0, 0, '=1/0'); - cell := FWorksheet.WriteFormula(0, 1, '=ISERR(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #4 ISERR(A1) result mismatch'); - - // Reference to cell without error - FWorksheet.WriteText(0, 0, 'abc'); - cell := FWorksheet.WriteFormula(0, 1, '=ISERR(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISERR(A1) result mismatch (no error in cell)'); - - // No error as argument - cell := FWorksheet.WriteFormula(0, 1, '=ISERR("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISERR(A1) result mismatch (no error as argument)'); - - // #N/A error - cell := FWorksheet.WriteFormula(0, 1, '=ISERR(#N/A)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #7 ISERR(#N/A) result mismatch (#N/A as argument)'); - - FWorksheet.WriteNumber(0, 0, 10); - FWorksheet.WriteNumber(1, 0, 20); - FWorksheet.WriteFormula(2, 0, '=MATCH(-10, A1:A2, 0)'); // generates a #N/A error - cell := FWorksheet.WriteFormula(0, 1, '=ISERR(A3)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #8 ISERR(#N/A) result mismatch (#N/A as argument)'); -end; - -procedure TCalcFormulaTests.Test_ISERROR; -var - cell: PCell; -begin - // #DIV/0! as argument - cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(#DIV/0!)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISERROR(1/0) result mismatch'); - - // Cell with #DIV/0! error - FWorksheet.WriteFormula(0, 0, '=1/0'); - cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISERROR(A1) (A1 = 1/0) result mismatch'); - - // Hard coded expression without error - cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(0/1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 ISERROR(0/1) result mismatch'); - - // Reference to cell with error - FWorksheet.WriteFormula(0, 0, '=1/0'); - cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #4 ISERROR(A1) result mismatch'); - - // Reference to cell without error - FWorksheet.WriteText(0, 0, 'abc'); - cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISERROR(A1) result mismatch (no error in cell)'); - - // No error as argument - cell := FWorksheet.WriteFormula(0, 1, '=ISERROR("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISERROR(A1) result mismatch (no error as argument)'); - - // #N/A error - cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(#N/A)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #7 ISERROR(#N/A) result mismatch (#N/A as argument)'); - - FWorksheet.WriteNumber(0, 0, 10); - FWorksheet.WriteNumber(1, 0, 20); - FWorksheet.WriteFormula(2, 0, '=MATCH(-10, A1:A2, 0)'); // generates a #N/A error - cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(A3)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #8 ISERROR(#N/A) result mismatch (#N/A as argument)'); -end; - -procedure TCalcFormulaTests.Test_ISLOGICAL; -var - cell: PCell; -begin - // Boolean - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISLOGICAL result mismatch (true)'); - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(FALSE)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISLOGICAL result mismatch (false)'); - - FWorksheet.WriteBoolValue(0, 0, true); - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 ISLOGICAL result mismatch (bool cell)'); - - // Number - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(1.23)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #4 ISLOGICAL result mismatch (number)'); - - FWorksheet.WriteNumber(0, 0, 1.234); - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISLOGICAL result mismatch (number cell)'); - - // Date - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(DATE(2025,1,1))'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISLOGICAL result mismatch (date)'); - - FWorksheet.WriteDateTime(0, 0, EncodeDate(2025,1,1)); - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #7 ISLOGICAL result mismatch (date cell)'); - - // String (corresponding to 'true') - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL("TRUE")'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #8 ISLOGICAL result mismatch ("true" as string)'); - - FWorksheet.WriteText(0, 0, 'TRUE'); - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #9 ISLOGICAL result mismatch ("true" as string cell)'); - - // Blank - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL()'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #10 ISLOGICAL result mismatch (blank)'); - - FWorksheet.WriteBlank(0, 0); - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #11 ISLOGICAL result mismatch (blank cell)'); - - // Error - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #12 ISLOGICAL result mismatch (error value)'); - CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #12 ISLOGICAL result mismatch (error value)'); - - FWorksheet.WriteFormula(0, 0, '=1/0'); - cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #13 ISLOGICAL result mismatch (cell with error value)'); - CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #13 ISLOGICAL result mismatch (cell with error value)'); -end; - -procedure TCalcFormulaTests.Test_ISNA; -var - cell: PCell; -begin - // Check cell with #N/A error - FWorksheet.WriteNumber(0, 0, 10); - FWorksheet.WriteNumber(1, 0, 20); - FWorksheet.WriteFormula(2, 0, '=MATCH(-10,A1:A2,0)'); // This creates an #N/A error - cell := FWorksheet.WriteFormula(0, 1, '=ISNA(A3)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISNA result mismatch (#N/A error)'); - - // Cell with other error (#DIV/0!) - FWorksheet.WriteFormula(2, 0, '=1/0'); - cell := FWorksheet.WriteFormula(0, 1, '=ISNA(A3)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #2 ISNA result mismatch (other error)'); - - // Cell with no error - cell := FWorksheet.WriteFormula(0, 1, '=ISNA(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 ISNA result mismatch (no error)'); -end; - -procedure TCalcFormulaTests.Test_ISNONTEXT; -var - cell: PCell; -begin - // Number - cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(1.234)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISNONTEXT result mismatch (float)'); - - FWorksheet.WriteNumber(0, 0, 1.234); - cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISNONTEXT result mismatch (float cell)'); - - // Date - cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(DATE(2025,1,1))'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 ISNONTEXT result mismatch (date)'); - - FWorksheet.WriteDateTime(0, 0, EncodeDate(2025,1,1)); - cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #4 ISNONTEXT result mismatch (date cell)'); - - // String - cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISNONTEXT result mismatch (float as string)'); - - FWorksheet.WriteText(0, 0, 'abc'); - cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISNONTEXT result mismatch (float as string cell)'); - - // Boolean - cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #7 ISNONTEXT result mismatch (boolean)'); - - FWorksheet.WriteFormula(0, 0, '=(1=1)'); - cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #8 ISNONTEXT result mismatch (boolean cell)'); - - // Blank - cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT()'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #9 ISNONTEXT result mismatch (blank)'); - - FWorksheet.WriteBlank(0, 0); - cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #10 ISNONTEXT result mismatch (blank cell)'); - - // Error - cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #11 ISNONTEXT result mismatch (error value)'); - CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #11 ISNONTEXT result mismatch (error value)'); - - FWorksheet.WriteFormula(0, 0, '=1/0'); - cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #12 ISNONTEXT result mismatch (cell with error value)'); - CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #12 ISNONTEXT result mismatch (cell with error value)'); -end; - -procedure TCalcFormulaTests.Test_ISNUMBER; -var - cell: PCell; -begin - // Number - cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(1.234)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 IsNumber result mismatch (float)'); - - FWorksheet.WriteNumber(0, 0, 1.234); - cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 IsNumber result mismatch (float cell)'); - - // Date - cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(DATE(2025,1,1))'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 IsNumber result mismatch (date)'); - - FWorksheet.WriteDateTime(0, 0, EncodeDate(2025,1,1)); - cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #4 IsNumber result mismatch (date cell)'); - - // String (corresponds to number) - cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER("1.234")'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISNUMBER result mismatch (float as string)'); - - FWorksheet.WriteText(0, 0, '1.234'); - cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISNUMBER result mismatch (float as string cell)'); - - // Boolean - cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #7 ISNUMBER result mismatch (boolean)'); - - FWorksheet.WriteFormula(0, 0, '=(1=1)'); - cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #8 ISNUMBER result mismatch (boolean cell)'); - - // Blank - cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER()'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #9 ISNUMBER result mismatch (blank)'); - - FWorksheet.WriteBlank(0, 0); - cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #10 ISNUMBER result mismatch (blank ceöö)'); - - // Error - cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #11 ISNUMBER result mismatch (error value)'); - CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #11 ISNUMBER result mismatch (error value)'); - - FWorksheet.WriteFormula(0, 0, '=1/0'); - cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #12 ISNUMBER result mismatch (cell with error value)'); - CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #12 ISNUMBER result mismatch (cell with error value)'); -end; - -procedure TCalcFormulaTests.Test_ISREF; -var - cell: PCell; -begin - // Cell reference - cell := FWorksheet.WriteFormula(0, 1, '=ISREF(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISREF result mismatch (cell reference)'); - - // Cell range - cell := FWorksheet.WriteFormula(0, 1, '=ISREF(A1:A3)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISREF result mismatch (cell range reference)'); - - // 3d cell ref - cell := FWorksheet.WriteFormula(0, 1, '=ISREF(Sheet1!A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 ISREF result mismatch (3d cell reference)'); - - // 3d cell range ref - cell := FWorksheet.WriteFormula(0, 1, '=ISREF(Sheet1!A1:A3)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 ISREF result mismatch (3d cell range reference)'); - - // no ref - cell := FWorksheet.WriteFormula(0, 1, '=ISREF("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 ISREF result mismatch (string)'); -end; - -procedure TCalcFormulaTests.Test_ISTEXT; -var - cell: PCell; -begin - // Text - cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISTEXT result mismatch (text)'); - - FWorksheet.WriteText(0, 0, 'abc'); - cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISTEXT result mismatch (text cell)'); - - // Number - cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT(1.234)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 ISTEXT result mismatch (number)'); - - FWorksheet.WriteNumber(0, 0, 1.234); - cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #4 ISTEXT result mismatch (number cell)'); - - // Blank - cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT()'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISTEXT result mismatch (blank)'); - - FWorksheet.WriteBlank(0, 0); - cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISTEXT result mismatch (blank cell)'); - - // Error - cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #7 ISTEXT result mismatch (error value)'); - CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #7 ISTEXT result mismatch (error value)'); - - FWorksheet.WriteFormula(0, 0, '=1/0'); - cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #8 ISTEXT result mismatch (error value)'); - CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #8 ISTEXT result mismatch (error value)'); -end; - -procedure TCalcFormulaTests.Test_LEN; -begin - FWorksheet.WriteText(0, 0, 'abc'); // A1 - FWorksheet.WriteText(1, 0, 'Äbγ'); // A2 - FWorksheet.WriteErrorValue(2, 0, errIllegalRef); // A3 - - // Literal ASCII string - FWorksheet.WriteFormula(0, 1, '=LEN("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 LEN("abc") result mismatch'); - - // Literal Unicode string - FWorksheet.WriteFormula(0, 1, '=LEN("Äbγ")'); - FWorksheet.CalcFormulas; - CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 LEN("Äbc") result mismatch'); - - // Another Unicode string - FWorksheet.WriteFormula(0, 1, '=LEN("αβγδε")'); - FWorksheet.CalcFormulas; - CheckEquals(5, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 LEN("αβγδε") result mismatch'); - - // Cell with ASCII string - FWorksheet.WriteFormula(0, 1, '=LEN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 LEN(A1) result mismatch'); - - // Cell with unicode string - FWorksheet.WriteFormula(0, 1, '=LEN(A2)'); - FWorksheet.CalcFormulas; - CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 LEN(A2) result mismatch'); - - // Cell with error - FWorksheet.WriteFormula(0, 1, '=LEN(A3)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #6 LEN(A3) (#REF!) result mismatch'); - - // Empty cell - FWorksheet.WriteFormula(0, 1, '=LEN(A99)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 LEN(A99) (empty cell) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_LOG; -begin - // Correct formula - FWorksheet.WriteFormula(0, 1, '=LOG(10)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 LOG(10) result mismatch'); - - // Argument is zero - FWorksheet.WriteFormula(0, 1, '=LOG(0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #2 LOG(0) result mismatch'); - - // Negative argument - FWorksheet.WriteFormula(0, 1, '=LOG(-10)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #3 LOG(-10) result mismatch'); - - // Non-numeric argument - FWorksheet.WriteFormula(0, 1, '=LOG("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #4 LOG("abc") result mismatch'); - - // Error argument - FWorksheet.WriteFormula(0, 1, '=LOG(#REF!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #5 LOG(#REF!) result mismatch'); - - // Two argument cases - - // Correct formula - FWorksheet.WriteFormula(0, 1, '=LOG(8,2)'); - FWorksheet.CalcFormulas; - CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #6 LOG(8, 2) result mismatch'); - - // 2nd argument negative - FWorksheet.WriteFormula(0, 1, '=LOG(8,-2)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #7 LOG(8,-2) result mismatch'); - - // Non-numeric 2nd argument - FWorksheet.WriteFormula(0, 1, '=LOG(8,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #8 LOG(8,"abc") result mismatch'); - - // Missing 1st argument - FWorksheet.WriteFormula(0, 1, '=LOG(,2)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #9 LOG(,2) result mismatch'); - - // Missing 2nd argument - FWorksheet.WriteFormula(0, 1, '=LOG(10,)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #10 LOG(10,) result mismatch'); - - // Error in 2nd argument - FWorksheet.WriteFormula(0, 1, '=LOG(8,#REF!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #11 LOG(8,#REF!) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_LOG10; -begin - // Correct formula - FWorksheet.WriteFormula(0, 1, '=LOG10(10)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 LOG10(10) result mismatch'); - - // Argument is zero - FWorksheet.WriteFormula(0, 1, '=LOG10(0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #2 LOG10(0) result mismatch'); - - // Negative argument - FWorksheet.WriteFormula(0, 1, '=LOG10(-10)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #3 LOG10(-10) result mismatch'); - - // Non-numeric argument - FWorksheet.WriteFormula(0, 1, '=LOG10("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #4 LOG10("abc") result mismatch'); - - // Error argument - FWorksheet.WriteFormula(0, 1, '=LOG10(#REF!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #5 LOG10(#REF!) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_LOWER; -begin - FWorksheet.WriteText(0, 0, 'abc'); // A1 - FWorksheet.WriteText(1, 0, 'Äbγδ'); // A2 - FWorksheet.WriteErrorValue(2, 0, errIllegalRef); // A3 - - // ASCII, already lower case - FWorksheet.WriteFormula(0, 1, '=LOWER("abc")'); - FWorksheet.CalcFormulas; - CheckEquals('abc', FWorksheet.ReadAsText(0, 1), 'Formula #1 LOWER("abc") result mismatch'); - - // ASCII, mixed upper/lower case - FWorksheet.WriteFormula(0, 1, '=LOWER("Abc")'); - FWorksheet.CalcFormulas; - CheckEquals('abc', FWorksheet.ReadAsText(0, 1), 'Formula #2 LOWER("Abc") result mismatch'); - - // Unicode, already lower case - FWorksheet.WriteFormula(0, 1, '=LOWER("äöü αβγ")'); - FWorksheet.CalcFormulas; - CheckEquals('äöü αβγ', FWorksheet.ReadAsText(0, 1), 'Formula #3 LOWER("äöü αβγ") result mismatch'); - - // Unicode, mixed upper/lower case - FWorksheet.WriteFormula(0, 1, '=LOWER("Äöü αβΓ")'); - FWorksheet.CalcFormulas; - CheckEquals('äöü αβγ', FWorksheet.ReadAsText(0, 1), 'Formula #4 LOWER("Äöü αβΓ") result mismatch'); - - // Mixed unicode, ASCII, number - FWorksheet.WriteFormula(0, 1, '=LOWER("Äöü αβΓ 123")'); - FWorksheet.CalcFormulas; - CheckEquals('äöü αβγ 123', FWorksheet.ReadAsText(0, 1), 'Formula #5 LOWER("Äöü αβΓ 123") result mismatch'); - - // Error in argument - FWorksheet.WriteFormula(0, 1, '=LOWER(#REF!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #6 LOWER(#REF!) result mismatch'); - - // Cell with error - FWorksheet.WriteFormula(0, 1, '=LOWER(A3)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #7 LOWER(A3) (#REF!) result mismatch'); - - // Empty cell - FWorksheet.WriteFormula(0, 1, '=LOWER(A99)'); - FWorksheet.CalcFormulas; - CheckEquals('', FWorksheet.ReadAsText(0, 1), 'Formula #8 LOWER(A9) (empty) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_MATCH; -begin - // *** Match_Type 0, unsorted data in search range, find first value - - // Search range to be checked: B1:B4 - FWorksheet.WriteNumber(0, 1, 10); - FWorksheet.WriteNumber(1, 1, 20); - FWorksheet.WriteNumber(2, 1, 30); - FWorksheet.WriteNumber(3, 1, 15); - FWorksheet.WriteNumber(4, 1, 20); - - // Search range in other sheet - FOtherWorksheet.WriteNumber(0, 1, 100); - FOtherWorksheet.WriteNumber(1, 1, 200); - FOtherWorksheet.WriteNumber(2, 1, 300); - FOtherWorksheet.WriteNumber(3, 1, 150); - FOtherWorksheet.WriteNumber(4, 1, 200); - - // Search for constant, contained in search range - FWorksheet.WriteFormula(0, 2, '=MATCH(10, B1:B5, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #1 MATCH(10,B1:B5,0) mismatch, value in range'); - - // dto., but in other sheet - FWorksheet.WriteFormula(0, 2, '=MATCH(100, Sheet2!B1:B5, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #2 MATCH(100,Sheet2!B1:B5,0) mismatch, value in range'); - - // Search for constant, contained several times in search range - FWorksheet.WriteFormula(0, 2, '=MATCH(20, B1:B5, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #3 MATCH(20,B1:B5,0) mismatch, value above range'); - - // dto., but in other sheet - FWorksheet.WriteFormula(0, 2, '=MATCH(200, Sheet2!B1:B5, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #4 MATCH(200,Sheet2!B1:B5,0) mismatch, value above range'); - - // Search for constant, below search range - FWorksheet.WriteFormula(0, 2, '=MATCH(0, B1:B5, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #5 MATCH(0,B1:B5,0) mismatch, value below range'); - - // dto., but in other sheet - FWorksheet.WriteFormula(0, 2, '=MATCH(0, Sheet2!B1:B5, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #6 MATCH(0,Sheet2!B1:B5,0) mismatch, value below range'); - - // Search for constant, above search range - FWorksheet.WriteFormula(0, 2, '=MATCH(90, B1:B5, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #7 MATCH(90,B1:B5,0) mismatch, value above range'); - - // dto., but in other sheet - FWorksheet.WriteFormula(0, 2, '=MATCH(900, Sheet2!B1:B5, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #8 MATCH(900,Sheet2!B1:B5,0) mismatch, value above range'); - - // Search for cell with value in range - FWorksheet.WriteNumber(0, 0, 20); - FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B5, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #9 MATCH(A1,B1:B5,0) mismatch, cell value in range'); - - // dto, but in other sheet - FWorksheet.WriteNumber(0, 0, 200); - FWorksheet.WriteFormula(0, 2, '=MATCH(A1, Sheet2!B1:B5, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #10 MATCH(A1,Sheet2!B1:B5,0) mismatch, cell value in range'); - - // Search for cell, but cell is empty - FWorksheet.WriteFormula(0, 2, '=MATCH(A99, B1:B5, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #11 MATCH(A99,B1:B5,0) mismatch, empty cell'); - - // dto., but in other sheet - FWorksheet.WriteFormula(0, 2, '=MATCH(A99, Sheet2!B1:B5, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #12 MATCH(A99,Sheet2!B1:B5,0) mismatch, empty cell'); - - // Search range is empty - FWorksheet.WriteFormula(0, 2, '=MATCH(28, D1:D3, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #13 MATCH mismatch, match_type -1, empty search range'); - - // dto., but in other sheet - FWorksheet.WriteFormula(0, 2, '=MATCH(28, Sheet2!D1:D3, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #14 MATCH mismatch, match_type -1, empty search range'); - - // *** Match_Type 1 (find largest value in range <= value), ascending values in search range - - // Search range to be checked: B1:B3 - FWorksheet.WriteNumber(0, 1, 10); - FWorksheet.WriteNumber(1, 1, 20); - FWorksheet.WriteNumber(2, 1, 30); - FWorksheet.WriteBlank(3, 1); - - // Search for constant, contained in search range - FWorksheet.WriteFormula(0, 2, '=MATCH(28, B1:B3, 1)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #8 MATCH mismatch, match_type 1, in range'); - - // Search for constant, below search range - FWorksheet.WriteFormula(0, 2, '=MATCH(8, B1:B3, 1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #9 MATCH mismatch, match_type 1, below range'); - - // Search for constant, above search range - FWorksheet.WriteFormula(0, 2, '=MATCH(123, B1:B3, 1)'); - FWorksheet.CalcFormulas; - CheckEquals(3, FWorksheet.ReadAsNumber(0, 2), 'Formula MATCH #10 mismatch, match_type 1, above range'); - - // Search for cell with value in range - FWorksheet.WriteNumber(0, 0, 28); - FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B3, 1)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula MATCH #11 mismatch, match_type 1, cell in range'); - FWorksheet.WriteBlank(0, 0); - - // Search for cell, but cell is empty - FWorksheet.WriteBlank(0, 0); - FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B3, 1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #12 MATCH mismatch, match_type 1, empty cell'); - - // Search range is empty - FWorksheet.WriteFormula(0, 2, '=MATCH(28, D1:D3, -1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula MATCH #13 mismatch, match_type -1, empty search range'); - - - // *** Match_Type -1 (find smallest value in range >= value), descending values in search range - - // Search range to be checked: B1:B3 - FWorksheet.WriteNumber(0, 1, 30); - FWorksheet.WriteNumber(1, 1, 20); - FWorksheet.WriteNumber(2, 1, 10); - - // Search for constant, contained in search range - FWorksheet.WriteFormula(0, 2, '=MATCH(28, B1:B3, -1)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #14 MATCH mismatch, match_type -1, in range'); - - // Search for constant, below search range - FWorksheet.WriteFormula(0, 2, '=MATCH(8, B1:B3, -1)'); - FWorksheet.CalcFormulas; - CheckEquals(3, FWorksheet.ReadAsNumber(0, 2), 'Formula #15 MATCH mismatch, match_type -1, below range'); - - // Search for constant, above search range - FWorksheet.WriteFormula(0, 2, '=MATCH(123, B1:B3, -1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #16 MATCH mismatch, match_type -1, above range'); - - // Search for cell with value in range - FWorksheet.WriteNumber(0, 0, 28); - FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B3, -1)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #17 MATCH mismatch, match_type -1, cell in range'); - FWorksheet.WriteBlank(0, 0); - - // Search for cell, but cell is empty - FWorksheet.WriteBlank(0, 0); - FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B3, -1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #18 MATCH mismatch, match_type -1, empty cell'); - - // Search range is empty - FWorksheet.WriteFormula(0, 2, '=MATCH(28, D1:D3, -1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #19 MATCH mismatch, match_type -1, empty search range'); - - - // **** Error propagation - - // Search for cell, but cell contains error - FWorksheet.WriteFormula(0, 0, '=1/0'); - FWorksheet.WriteNumber(1, 1, 20); - FWorksheet.WriteNumber(2, 1, 30); - FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B4, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #20 MATCH mismatch, match_type 0, error cell'); - - // Match_type parameter contains error - FWorksheet.WriteNumber(0, 1, 10); - FWorksheet.WriteFormula(0, 5, '=1/0'); // F1 - FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B3, F1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #21 MATCH mismatch, match_type 0, error in search range'); - - // Cell range contains error - FWorksheet.WriteNumber(0, 1, 10); - FWorksheet.WriteFormula(1, 1, '=1/0'); // B2 contains a #DIV/0! error now - FWorksheet.WriteNumber(2, 1, 30); - // Search for constant, contained in search range - FWorksheet.WriteFormula(0, 2, '=MATCH(20, B1:B3, 0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #22 MATCH mismatch, match_type 0, error in search range'); - // ArgError because search value is not found - - - // **** Partial text - - FWorksheet.WriteText(0, 0, 'abc'); - FWorksheet.WriteText(1, 0, 'axy'); - FWorksheet.WriteText(2, 0, 'xxy'); - FWorksheet.WriteText(3, 0, 'ayc'); - FWorksheet.WriteText(4, 0, 'äbc'); - - FWorksheet.WriteFormula(0, 2, '=MATCH("a*",A1:A4,0)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #23 MATCH mismatch, partial text "a*"'); - - FWorksheet.WriteFormula(0, 2, '=MATCH("z*",A1:A4,0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #24 MATCH mismatch, partial text "z*"'); - - FWorksheet.WriteFormula(0, 2, '=MATCH("*y",A1:A4,0)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #25 MATCH mismatch, partial text "*y"'); - - FWorksheet.WriteFormula(0, 2, '=MATCH("*z",A1:A4,0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #26 MATCH mismatch, partial text "*z"'); - - FWorksheet.WriteFormula(0, 2, '=MATCH("*z*",A1:A4,0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #27 MATCH mismatch, partial text "*z*"'); - - FWorksheet.WriteFormula(0, 2, '=MATCH("ay?",A1:A4,0)'); - FWorksheet.CalcFormulas; - CheckEquals(4, FWorksheet.ReadAsNumber(0, 2), 'Formula #28 MATCH mismatch, partial text "ay?'); - - FWorksheet.WriteFormula(0, 2, '=MATCH("a?",A1:A4,0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #29 MATCH mismatch, partial text "a?'); - - FWorksheet.WriteFormula(0, 2, '=MATCH("Ä*",A1:A5,0)'); - FWorksheet.CalcFormulas; - CheckEquals(5, FWorksheet.ReadAsNumber(0, 2), 'Formula #30 MATCH mismatch, partial text "Ä*'); - -end; - -procedure TCalcFormulaTests.Test_MAX; -begin - // Test data - FWorksheet.WriteNumber (0, 0, 10); - FWorksheet.WriteNumber (1, 0, 20); - FWorksheet.WriteNumber (2, 0, 30); - FWorksheet.WriteText (3, 0, '40'); - FWorksheet.WriteText (4, 0, 'abc'); - FWorksheet.WriteFormula(5, 0, '=1/0'); - - // Literal values - FWorksheet.WriteFormula(0, 1, '=MAX(10)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 MAX(10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX(10,20)'); - FWorksheet.CalcFormulas; - CheckEquals(20, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 MAX(10,20) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX("40")'); // although string considered to be numeric - FWorksheet.CalcFormulas; - CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 MAX("40") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX(10,20,30,"40")'); - FWorksheet.CalcFormulas; - CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 MAX(10,20,30,"40") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 MAX("abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX("")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 MAX("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX(10,20,30,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 MAX(10,20,30,"abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 MAX(1/0) result mismatch'); - - // Cell references - FWorksheet.WriteFormula(0, 1, '=MAX(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 MAX(A1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX(A10)'); // empty cell - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 MAX(A10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals(20, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 MAX(A1,A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX(A1:A3)'); // "real" numeric values - FWorksheet.CalcFormulas; - CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 MAX(A1:A3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX(A1,A2:A3)'); // several ranges - FWorksheet.CalcFormulas; - CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 MAX(A1,A2:A3) result mismatch'); - - // Cell references pointing to string cells - FWorksheet.WriteFormula(0, 1, '=MAX(A1:A4)'); // real and string numeric values - FWorksheet.CalcFormulas; - CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 MAX(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX(A1:A5)'); // real and string values --> ignore string - FWorksheet.CalcFormulas; - CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 MAX(A1:A5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX(A1:A4,A8:A10)'); // real and string values and blanks - FWorksheet.CalcFormulas; - CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 MAX(A1:A4,A8:A10) result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 1, '=MAX(A1, 1/0, A2)'); // error in argument - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 MAX(A1, 1/0, A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX(A1:A6)'); // error in cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 MAX(A:A6) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_MIN; -begin - // Test data - FWorksheet.WriteNumber (0, 0, 10); - FWorksheet.WriteNumber (1, 0, 20); - FWorksheet.WriteNumber (2, 0, 30); - FWorksheet.WriteText (3, 0, '-40'); - FWorksheet.WriteText (4, 0, 'abc'); - FWorksheet.WriteFormula(5, 0, '=1/0'); - - // Literal values - FWorksheet.WriteFormula(0, 1, '=MIN(10)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 MIN(10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN(10,20)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 MIN(10,20) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN("40")'); // although string considered to be numeric - FWorksheet.CalcFormulas; - CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 MIN("40") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN(10,20,30,"40")'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 MIN(10,20,30,"40") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 MIN("abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN("")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 MIN("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN(10,20,30,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 MIN(10,20,30,"abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MAX(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 MAX(1/0) result mismatch'); - - // Cell references - FWorksheet.WriteFormula(0, 1, '=MIN(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 MIN(A1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN(A10)'); // empty cell - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 MIN(A10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 MIN(A1,A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN(A1:A3)'); // "real" numeric values - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 MIN(A1:A3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN(A1,A2:A3)'); // several ranges - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 MIN(A1,A2:A3) result mismatch'); - - // Cell references pointing to string cells - FWorksheet.WriteFormula(0, 1, '=MIN(A1:A4)'); // real and string numeric values - FWorksheet.CalcFormulas; - CheckEquals(-40, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 MIN(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN(A1:A5)'); // real and string values --> ignore string - FWorksheet.CalcFormulas; - CheckEquals(-40, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 MIN(A1:A5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN(A1:A4,A8:A10)'); // real and string values and blanks - FWorksheet.CalcFormulas; - CheckEquals(-40, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 MIN(A1:A4,A8:A10) result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 1, '=MIN(A1, 1/0, A2)'); // error in argument - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 MIN(A1, 1/0, A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=MIN(A1:A6)'); // error in cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 MIN(A:A6) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_NOT; -var - cell: PCell; -begin - cell := FWorksheet.WriteFormula(0, 1, 'NOT(1=1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #1 NOT(1=1) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'NOT(1=2)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 NOT(1=2) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'NOT(0)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 NOT(0) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'NOT(1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #4 NOT(1) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'NOT(12)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 NOT(12) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'NOT("0")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(cell), 'Formula #6 NOT("0") result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'NOT("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(cell), 'Formula #7 NOT("abc") result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'NOT(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #8 NOT(1/0) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_ODD; -begin - FWorksheet.WriteFormula(0, 1, '=ODD(0.5)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 ODD(0.5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ODD(1.5)'); - FWorksheet.CalcFormulas; - CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 ODD(1.5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ODD(-0.5)'); - FWorksheet.CalcFormulas; - CheckEquals(-1, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 ODD(-0.5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=ODD(0.0)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 ODD(0.0) result mismatch'); - - // String as argument - FWorksheet.WriteFormula(0, 1, '=ODD("1")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 ODD("1") result mismatch'); - - // Empty as argument - FWorksheet.WriteFormula(0, 1, '=ODD()'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 ODD() result mismatch'); - - // Error in argument - FWorksheet.WriteFormula(0, 1, '=ODD(#REF!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #7 ODD(#REF!) result mismatch'); - - // Error in argument cell - FWorksheet.WriteErrorValue(0, 0, errIllegalRef); - FWorksheet.WriteFormula(0, 1, '=ODD(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #8 ODD(A1) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_OR; -var - cell: PCell; -begin - cell := FWorksheet.WriteFormula(0, 1, 'OR(1=1,2=2)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 OR(1=1,2=2) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'OR(1=2,2=2)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 OR(1=2,2=2) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'OR(1=1,2=1)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 OR(1=1,2=1) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'OR(1=2,2=1)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #4 OR(1=2,2=1) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'OR(1/0,2=2)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #5 OR(1/0,2=2) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'OR(1,TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #6 OR(1,TRUE) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'OR(0,FALSE)'); - FWorksheet.CalcFormulas; - CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #7 OR(0,TRUE) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'OR("0",TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(cell), 'Formula #8 OR("0",TRUE) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'OR("abc",TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(cell), 'Formula #9 OR("abc",TRUE) result mismatch'); - - cell := FWorksheet.WriteFormula(0, 1, 'OR(1/0,1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #10 OR(1/0,1/0) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_POWER; -begin - FWorksheet.WriteFormula(0, 1, '=POWER(3,2)'); - FWorksheet.CalcFormulas; - CheckEquals(9, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 POWER(3,2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=POWER(2,-3)'); - FWorksheet.CalcFormulas; - CheckEquals(1/8, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 POWER(2,-3) result mismatch'); - - // x^0 - FWorksheet.WriteFormula(0, 1, '=POWER(2,0)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 POWER(2,0) result mismatch'); - - // 0^x - FWorksheet.WriteFormula(0, 1, '=POWER(0,2)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 POWER(0,2) result mismatch'); - - // 0^0 - FWorksheet.WriteFormula(0, 1, '=POWER(0,0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #5 POWER(0,0) result mismatch'); - - // Boolean argument - FWorksheet.WriteFormula(0, 1, '=POWER(TRUE,"2")'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #6 POWER(TRUE,"2") result mismatch'); - - // Numeric string arguments - FWorksheet.WriteFormula(0, 1, '=POWER("3",2)'); - FWorksheet.CalcFormulas; - CheckEquals(9, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 POWER("3",2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=POWER(3,"2")'); - FWorksheet.CalcFormulas; - CheckEquals(9, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 POWER(3,"2") result mismatch'); - - // Non-numeric string arguments - FWorksheet.WriteFormula(0, 1, '=POWER("abc",2)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #9 POWER("abc",2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=POWER(3,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #10 POWER(3,"abc") result mismatch'); -end; - -procedure TCalcFormulaTests.Test_PRODUCT; -begin - // Test data - FWorksheet.WriteNumber (0, 0, 1); - FWorksheet.WriteNumber (1, 0, 2); - FWorksheet.WriteNumber (2, 0, 3); - FWorksheet.WriteText (3, 0, '4'); - FWorksheet.WriteText (4, 0, 'abc'); - FWorksheet.WriteFormula(5, 0, '=1/0'); - - // Literal values - 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)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 PRODUCT(1,2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT("4")'); // although string considered to be numeric - FWorksheet.CalcFormulas; - CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 PRODUCT("4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT(1,2,3,"4")'); - FWorksheet.CalcFormulas; - CheckEquals(24, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 PRODUCT(1,2,3,"4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 PRODUCT("abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT("")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 PRODUCT("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT(1,2,3,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 PRODUCT(1,2,3,"abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 PRODUCT(1/0) result mismatch'); - - // Count in cell references - FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 PRODUCT(A1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT(A10)'); // empty cell - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 PRODUCT(A10) (A10 = empty) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 PRODUCT(A1,A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1:A3)'); // "real" numeric values - FWorksheet.CalcFormulas; - CheckEquals(6, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 PRODUCT(A1:A3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1,A2:A3)'); // several ranges - FWorksheet.CalcFormulas; - CheckEquals(6, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 PRODUCT(A1,A2:A3) result mismatch'); - - // Cell references pointing to string cells - FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1:A4)'); // real and string numeric values - FWorksheet.CalcFormulas; - CheckEquals(24, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 PRODUCT(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1:A5)'); // real and string values --> ignore string - FWorksheet.CalcFormulas; - CheckEquals(24, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 PRODUCT(A1:A5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1:A4,A8:A10)'); // real and string values and blanks - FWorksheet.CalcFormulas; - CheckEquals(24, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 PRODUCT(A1:A4,A8:A10) result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1, 1/0, A2)'); // error in argument - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 PRODUCT(A1, 1/0, A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1:A6)'); // error in cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 PRODUCT(A:A6) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_RADIANS; -begin - FWorksheet.WriteFormula(0, 1, '=RADIANS(90)'); - FWorksheet.CalcFormulas; - CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #1 RADIANS(90) result mismatch'); - - // Boolean argument - FWorksheet.WriteFormula(0, 1, '=RADIANS(TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(pi*1/180, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #2 RADIANS(TRUE) result mismatch'); - - // Numeric string - FWorksheet.WriteFormula(0, 1, '=RADIANS("90")'); - FWorksheet.CalcFormulas; - CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #3 RADIANS("90") result mismatch'); - - // Non-numeric string - FWorksheet.WriteFormula(0, 1, '=RADIANS("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #4 RADIANS("abc") result mismatch'); - - // Error argument - FWorksheet.WriteFormula(0, 1, '=RADIANS(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #5 RADIANS(1/0) result mismatch'); - - // Cell with boolean value - FWorksheet.WriteFormula(0, 0, '=(1=1)'); - FWorksheet.WriteFormula(0, 1, '=RADIANS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(pi*1/180, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #6 RADIANS(A1) (A1: (1=1)) result mismatch'); - - // Cell with numeric string - FWorksheet.WriteText(0, 0, '90'); - FWorksheet.WriteFormula(0, 1, '=RADIANS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #7 RADIANS(A1) (A1: "90") result mismatch'); - - // Cell with non-numeric string - FWorksheet.WriteText(0, 0, 'abc'); - FWorksheet.WriteFormula(0, 1, '=RADIANS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #8 RADIANS(A1) (A1: "abc") result mismatch'); - - // Empty cell - FWorksheet.WriteBlank(0, 0); // Empty A1 - FWorksheet.WriteFormula(0, 1, '=RADIANS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 RADIANS(A1) (A1: empty) result mismatch'); - - // Cell with error - FWorksheet.WriteErrorValue(0, 0, errIllegalRef); - FWorksheet.WriteFormula(0, 1, '=RADIANS(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #10 RADIANS(A1) (A1: #REF!) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_ROUND; -begin - // Round positive value. - FWorksheet.WriteFormula(0, 1, '=ROUND(123.432, 1)'); - FWorksheet.CalcFormulas; - CheckEquals(123.4, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #1 ROUND(123.432,1) result mismatch'); - - // Round positive value. Check that Banker's rounding is not applied - FWorksheet.WriteFormula(0, 1, '=ROUND(123.456, 2)'); - FWorksheet.CalcFormulas; - CheckEquals(123.46, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #2 ROUND(123.3456,2) result mismatch'); - - // Round negative value. - FWorksheet.WriteFormula(0, 1, '=ROUND(-123.432, 1)'); - FWorksheet.CalcFormulas; - CheckEquals(-123.4, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #3 ROUND(-123.432,1) result mismatch'); - - // Round negative value. Check that Banker's rounding is not applied - FWorksheet.WriteFormula(0, 1, '=ROUND(-123.456, 2)'); - FWorksheet.CalcFormulas; - CheckEquals(-123.46, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #4 ROUND(-123.456,2) result mismatch'); - - // Negative number of decimals for positive value - FWorksheet.WriteFormula(0, 1, '=ROUND(123.456, -2)'); - FWorksheet.CalcFormulas; - CheckEquals(100, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 ROUND(123.3456,-2) result mismatch'); - - // Negative number of decimals for negative value - FWorksheet.WriteFormula(0, 1, '=ROUND(-123.456, -2)'); - FWorksheet.CalcFormulas; - CheckEquals(-100, FWorksheet.ReadAsNumber(0, 1), 'Formula #6 ROUND(123.3456,-2) result mismatch'); - - // Error in 1st argument - FWorksheet.WriteFormula(0, 1, '=Round(1/0, 2)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #7 ROUND(1/0,2) result mismatch'); - - // Error in 2nd argument - FWorksheet.WriteFormula(0, 1, '=Round(123.456, 1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 ROUND(123.456, 1/0) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_ROW; -begin - // Get row of specified cell - FWorksheet.WriteFormula(0, 1, '=ROW(B2)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 ROW(B2) result mismatch'); - - // Get row of the formula cell --- NOT CORRECTLY IMPLEMENTED IN FPS - FWorksheet.WriteFormula(0, 1, '=ROW()'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 ROW() result mismatch'); // This would be the Excel result! - //CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #2 ROW() result mismatch'); - - // Error value as argument - FWorksheet.WriteFormula(0, 1, '=ROW(#REF!)'); - FWorksheet.CalcFormulas; - //CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 ROW() result mismatch'); - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #3 ROW(#REF!) result mismatch'); - - // Cell containing an error as argument - FWorksheet.WriteFormula(1, 1, '=1/0'); - FWorksheet.WriteFormula(0, 1, '=ROW(B2)'); - FWorksheet.CalcFormulas; - CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 ROW(B2) (B2 contains error) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_SQRT; -begin - FWorksheet.WriteFormula(0, 1, '=SQRT(0.0)'); - FWorksheet.CalcFormulas; - CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #1 SQRT(0.0) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SQRT(1.0)'); - FWorksheet.CalcFormulas; - CheckEquals(1.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #2 SQRT(1.0) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SQRT(16.0)'); - FWorksheet.CalcFormulas; - CheckEquals(4.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #3 SQRT(16.0) result mismatch'); - - // Out-of-domain - FWorksheet.WriteFormula(0, 1, '=SQRT(-1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #4 SQRT(-1) result mismatch'); - - // Boolean argument - FWorksheet.WriteFormula(0, 1, '=SQRT(FALSE)'); - FWorksheet.CalcFormulas; - CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #5 SQRT(FALSE) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SQRT(TRUE)'); - FWorksheet.CalcFormulas; - CheckEquals(1.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #6 SQRTS(TRUE) result mismatch'); - - // Numeric string - FWorksheet.WriteFormula(0, 1, '=SQRT("1")'); - FWorksheet.CalcFormulas; - CheckEquals(1.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #7 SQRT("1") result mismatch'); - - // Non-numeric string - FWorksheet.WriteFormula(0, 1, '=SQRT("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #8 SQRT("abc") result mismatch'); - - // Error argument - FWorksheet.WriteFormula(0, 1, '=SQRT(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #9 SQRT(1/0) result mismatch'); - - // Cell with boolean value - FWorksheet.WriteFormula(0, 0, '=(1=1)'); - FWorksheet.WriteFormula(0, 1, '=SQRT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(1.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #10 SQRT(A1) (A1: (1=1)) result mismatch'); - - // Cell with numeric string - FWorksheet.WriteText(0, 0, '1'); - FWorksheet.WriteFormula(0, 1, '=SQRT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(1.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #11 SQRTS(A1) (A1: "1") result mismatch'); - - // Cell with non-numeric string - FWorksheet.WriteText(0, 0, 'abc'); - FWorksheet.WriteFormula(0, 1, '=SQRT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #12 SQRT(A1) (A1: "abc") result mismatch'); - - // Empty cell - FWorksheet.WriteBlank(0, 0); // Empty A1 - FWorksheet.WriteFormula(0, 1, '=SQRT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 SQRT(A1) (A1: empty) result mismatch'); - - // Cell with error - FWorksheet.WriteErrorValue(0, 0, errIllegalRef); - FWorksheet.WriteFormula(0, 1, '=SQRT(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #14 SQRT(A1) (A1: #REF!) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_STDEV; -const - EPS = 1E-8; -begin - // Test data - FWorksheet.WriteNumber (0, 0, 1); - FWorksheet.WriteNumber (1, 0, -2); - FWorksheet.WriteNumber (2, 0, -3); - FWorksheet.WriteText (3, 0, '4'); - FWorksheet.WriteText (4, 0, 'abc'); - FWorksheet.WriteFormula(5, 0, '=1/0'); - - // Literal values - FWorksheet.WriteFormula(0, 1, '=STDEV(1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #1 STDEV(1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV(1,-2)'); - FWorksheet.CalcFormulas; - CheckEquals(2.121320344, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #2 STDEV(1,-2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV("4")'); // although string considered to be numeric - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #3 STDEV("4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV(1,-2,-3,"4")'); - FWorksheet.CalcFormulas; - CheckEquals(3.16227766, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #4 STDEV(1,2,3,"4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 STDEV("abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV("")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 STDEV("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV(1,-2,-3,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 STDEV(1,-2,-3,"abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 STDEV(1/0) result mismatch'); - - // Cell references - FWorksheet.WriteFormula(0, 1, '=STDEV(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #7 STDEV(A1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV(A10)'); // empty cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 STDEV(A10)(A10=empty) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals(2.121320344, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #9 STDEV(A1,A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV(A1:A3)'); // "real" numeric values - FWorksheet.CalcFormulas; - CheckEquals(2.081665999, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #10 STDEV(A1:A3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV(A1,A2:A3)'); // several ranges - FWorksheet.CalcFormulas; - CheckEquals(2.081665999, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #11 STDEV(A1,A2:A3) result mismatch'); - - // Cell references pointing to string cells - FWorksheet.WriteFormula(0, 1, '=STDEV(A1:A4)'); // real and string numeric values - FWorksheet.CalcFormulas; - CheckEquals(3.16227766, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #12 STDEV(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV(A1:A5)'); // real and string values --> ignore string - FWorksheet.CalcFormulas; - CheckEquals(3.16227766, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #13 STDEV(A1:A5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV(A1:A4,A8:A10)'); // real and string values and blanks - FWorksheet.CalcFormulas; - CheckEquals(3.16227766, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #14 STDEV(A1:A4,A8:A10) result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 1, '=STDEV(A1, 1/0, A2)'); // error in argument - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 STDEV(A1, 1/0, A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEV(A1:A6)'); // error in cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 STDEV(A:A6) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_STDEVP; -const - EPS = 1E-8; -begin - // Test data - FWorksheet.WriteNumber (0, 0, 1); - FWorksheet.WriteNumber (1, 0, -2); - FWorksheet.WriteNumber (2, 0, -3); - FWorksheet.WriteText (3, 0, '4'); - FWorksheet.WriteText (4, 0, 'abc'); - FWorksheet.WriteFormula(5, 0, '=1/0'); - - // Literal values - FWorksheet.WriteFormula(0, 1, '=STDEVP(1)'); - FWorksheet.CalcFormulas; - CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 STDEVP(1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP(1,-2)'); - FWorksheet.CalcFormulas; - CheckEquals(1.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #2 STDEVP(1,-2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP("4")'); // although string considered to be numeric - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 STDEVP("4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP(1,-2,-3,"4")'); - FWorksheet.CalcFormulas; - CheckEquals(2.738612788, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #4 STDEVP(1,2,3,"4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 STDEVP("abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP("")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 STDEVP("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP(1,-2,-3,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 STDEVP(1,-2,-3,"abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 STDEVP(1/0) result mismatch'); - - // Cell references - FWorksheet.WriteFormula(0, 1, '=STDEVP(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 STDEVP(A1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP(A10)'); // empty cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 STDEVP(A10)(A10=empty) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals(1.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #9 STDEVP(A1,A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP(A1:A3)'); // "real" numeric values - FWorksheet.CalcFormulas; - CheckEquals(1.699673171, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #10 STDEVP(A1:A3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP(A1,A2:A3)'); // several ranges - FWorksheet.CalcFormulas; - CheckEquals(1.699673171, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #11 STDEVP(A1,A2:A3) result mismatch'); - - // Cell references pointing to string cells - FWorksheet.WriteFormula(0, 1, '=STDEVP(A1:A4)'); // real and string numeric values - FWorksheet.CalcFormulas; - CheckEquals(2.738612788, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #12 STDEVP(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP(A1:A5)'); // real and string values --> ignore string - FWorksheet.CalcFormulas; - CheckEquals(2.738612788, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #13 STDEVP(A1:A5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP(A1:A4,A8:A10)'); // real and string values and blanks - FWorksheet.CalcFormulas; - CheckEquals(2.738612788, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #14 STDEVP(A1:A4,A8:A10) result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 1, '=STDEVP(A1, 1/0, A2)'); // error in argument - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 STDEVP(A1, 1/0, A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=STDEVP(A1:A6)'); // error in cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 STDEVP(A:A6) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_SUM; -begin - // Test data - FWorksheet.WriteNumber (0, 0, 10); - FWorksheet.WriteNumber (1, 0, 20); - FWorksheet.WriteNumber (2, 0, 30); - FWorksheet.WriteText (3, 0, '40'); - FWorksheet.WriteText (4, 0, 'abc'); - FWorksheet.WriteFormula(5, 0, '=1/0'); - - // Literal values - FWorksheet.WriteFormula(0, 1, '=SUM(10)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 SUM(10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(10,20)'); - FWorksheet.CalcFormulas; - CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 SUM(10,20) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM("40")'); // although string considered to be numeric - FWorksheet.CalcFormulas; - CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 SUM("40") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(10,20,30,"40")'); - FWorksheet.CalcFormulas; - CheckEquals(100, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 SUM(10,20,30,"40") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 SUM("abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM("")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 SUM("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(10,20,30,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 SUM(10,20,30,"abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 SUM(1/0) result mismatch'); - - // Count in cell references - FWorksheet.WriteFormula(0, 1, '=SUM(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 SUM(A1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(A10)'); // empty cell - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 SUM(A10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 SUM(A1,A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(A1:A3)'); // "real" numeric values - FWorksheet.CalcFormulas; - CheckEquals(60, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 SUM(A1:A3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(A1,A2:A3)'); // several ranges - FWorksheet.CalcFormulas; - CheckEquals(60, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 SUM(A1,A2:A3) result mismatch'); - - // Cell references pointing to string cells - FWorksheet.WriteFormula(0, 1, '=SUM(A1:A4)'); // real and string numeric values - FWorksheet.CalcFormulas; - CheckEquals(100, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 SUM(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(A1:A5)'); // real and string values --> ignore string - FWorksheet.CalcFormulas; - CheckEquals(100, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 SUM(A1:A5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(A1:A4,A8:A10)'); // real and string values and blanks - FWorksheet.CalcFormulas; - CheckEquals(100, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 SUM(A1:A4,A8:A10) result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 1, '=SUM(A1, 1/0, A2)'); // error in argument - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 SUM(A1, 1/0, A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUM(A1:A6)'); // error in cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 SUM(A:A6) result mismatch'); -end; - -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 in A10 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'); - - // *** Error in arguments - - // Error in first argument - FWorksheet.WriteFormula(0, 2, '=SUMIF(#DIV/0!,"<10")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #18 SUMIF(#DIV/0,"<10") result mismatch'); - - // Error in second argument - FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:A9,#DIV/0!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #19 SUMIF(A1:A9,#DIV/0) result mismatch'); - - // Error in third argument - FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:A9,"=",#DIV/0!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #20 SUMIF(A1:A9,"=",#DIV/0) result mismatch'); - - // Write compare cell to contain an error (A15) - FWorksheet.WriteFormula( 14, 0, '=1/0'); // A15 - - // Calculate sum of the elements in A1:B5 which are equal to cell A15 (containing #DIV/0!) - // but this error does not exist in any cell of A1:B5 - FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B5,A15)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 2), 'Formula #21 SUMIF(A1:B5,A15) (A15=#DIV/0!) result mismatch'); - - // Calculate sum of the elements in A1:B5 which are equal to cell A15 (containing #DIV/0!) - // Cell A1 does have this error, so we expect the result to be 1 (1 cell with #DIV/0! error) - FWorksheet.WriteFormula(0, 0, '=1/0'); - FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B5,A15)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #22 SUMIF(A1:B5,A15) (A1=A15=#DIV/0!) result mismatch'); - //CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #21 SUMIF(A1:B5,A15) (A15=#DIV/0!) result mismatch'); - -end; - -procedure TCalcFormulaTests.Test_SUMSQ; -begin - // Test data - FWorksheet.WriteNumber (0, 0, 1); - FWorksheet.WriteNumber (1, 0, 2); - FWorksheet.WriteNumber (2, 0, 3); - FWorksheet.WriteText (3, 0, '4'); - FWorksheet.WriteText (4, 0, 'abc'); - FWorksheet.WriteFormula(5, 0, '=1/0'); - - // Literal values - FWorksheet.WriteFormula(0, 1, '=SUMSQ(1)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 SUMSQ(1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ(1,2)'); - FWorksheet.CalcFormulas; - CheckEquals(5, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 SUMSQ(1,2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ("4")'); // although string considered to be numeric - FWorksheet.CalcFormulas; - CheckEquals(16, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 SUMSQ("4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ(1,2,3,"4")'); - FWorksheet.CalcFormulas; - CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 SUMSQ(1,2,3,"4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 SUMSQ("abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ("")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 SUMSQ("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ(1,2,3,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 SUMSQ(1,2,3,"abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 SUMSQ(1/0) result mismatch'); - - // Count in cell references - FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 SUMSQ(A1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ(A10)'); // empty cell - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 SUMSQ(A10) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals(5, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 SUMSQ(A1,A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1:A3)'); // "real" numeric values - FWorksheet.CalcFormulas; - CheckEquals(14, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 SUMSQ(A1:A3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1,A2:A3)'); // several ranges - FWorksheet.CalcFormulas; - CheckEquals(14, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 SUMSQ(A1,A2:A3) result mismatch'); - - // Cell references pointing to string cells - FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1:A4)'); // "real" and string numeric values - FWorksheet.CalcFormulas; - CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 SUMSQ(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1:A5)'); // "real" and string values --> ignore string - FWorksheet.CalcFormulas; - CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 SUMSQ(A1:A5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1:A4,A8:A10)'); // real and string values and blanks - FWorksheet.CalcFormulas; - CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 SUMSQ(A1:A4,A8:A10) result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1:A5,1/0)'); // error in argument --> error in result - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 SUMSQ(A1, 1/0, A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1:A6)'); // error in cell --> error in result - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 SUMSQ(A1:A6) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_TIME; -var - actualTime, expectedTime: TTime; -begin - // Normal time - FWorksheet.WriteFormula(0, 1, '=Time(6,32,57)'); - FWorksheet.CalcFormulas; - expectedTime := EncodeTime(6, 32, 57, 0); - FWorksheet.ReadAsDateTime(0, 1, actualTime); - CheckEquals(TimeToStr(expectedTime), TimeToStr(actualTime), 'Formula #1 TIME(6,32,57) result mismatch'); - - // Hours < 0 - FWorksheet.WriteFormula(0, 1, '=Time(-6,32,57)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #2 TIME(-6,32,57) result mismatch'); - - // Hours > 23 - FWorksheet.WriteFormula(0, 1, '=Time(15,32,57)'); - FWorksheet.CalcFormulas; - expectedTime := 0.647881944; // Value read from Excel - FWorksheet.ReadAsDateTime(0, 1, actualTime); - CheckEquals(TimeToStr(expectedTime), TimeToStr(actualTime), 'Formula #3 TIME(15,32,57) result mismatch'); - - // Minutes > 59 - FWorksheet.WriteFormula(0, 1, '=Time(6,100,57)'); - FWorksheet.CalcFormulas; - expectedTime := 0.320104167; // Value read from Excel - FWorksheet.ReadAsDateTime(0, 1, actualTime); - CheckEquals(TimeToStr(expectedTime), TimeToStr(actualTime), 'Formula #4 TIME(6,100,57) result mismatch'); - - // Minutes < 0 - FWorksheet.WriteFormula(0, 1, '=Time(6,-100,57)'); - FWorksheet.CalcFormulas; - expectedTime := 0.181215278; // Value read from Excel - FWorksheet.ReadAsDateTime(0, 1, actualTime); - CheckEquals(TimeToStr(expectedTime), TimeToStr(actualTime), 'Formula #5 TIME(6,-100,57) result mismatch'); - - // Seconds > 59 - FWorksheet.WriteFormula(0, 1, '=Time(6,32,100)'); - FWorksheet.CalcFormulas; - expectedTime := 0.27337963; // Value read from Excel - FWorksheet.ReadAsDateTime(0, 1, actualTime); - CheckEquals(TimeToStr(expectedTime), TimeToStr(actualTime), 'Formula #6 TIME(6,32,100) result mismatch'); - - // Seconds < 0 - FWorksheet.WriteFormula(0, 1, '=Time(6,32,-100)'); - FWorksheet.CalcFormulas; - expectedTime := 0.271064815; // Value read from Excel - FWorksheet.ReadAsDateTime(0, 1, actualTime); - CheckEquals(TimeToStr(expectedTime), TimeToStr(actualTime), 'Formula #7 TIME(6,32,-100) result mismatch'); - - // Error in hours - FWorksheet.WriteFormula(0, 1, '=Time(1/0,32,57)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 TIME(1/0,32,57) result mismatch'); - - // Error in minutes - FWorksheet.WriteFormula(0, 1, '=Time(6,1/0,57)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #9 TIME(6,1/0,57) result mismatch'); - - // Error in seconds - FWorksheet.WriteFormula(0, 1, '=Time(6,32,1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #10 TIME(6,32,1/0) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_UPPER; -begin - FWorksheet.WriteText(0, 0, 'abc'); // A1 - FWorksheet.WriteText(1, 0, 'Äbγδ'); // A2 - FWorksheet.WriteErrorValue(2, 0, errIllegalRef); // A3 - - // ASCII, already upper case - FWorksheet.WriteFormula(0, 1, '=UPPER("ABC")'); - FWorksheet.CalcFormulas; - CheckEquals('ABC', FWorksheet.ReadAsText(0, 1), 'Formula #1 UPPER("ABC") result mismatch'); - - // ASCII, mixed upper/lower case - FWorksheet.WriteFormula(0, 1, '=UPPER("Abc")'); - FWorksheet.CalcFormulas; - CheckEquals('ABC', FWorksheet.ReadAsText(0, 1), 'Formula #2 UPPER("Abc") result mismatch'); - - // Unicode, already upper case - FWorksheet.WriteFormula(0, 1, '=UPPER("ÄÖÜ ΓΔΣ")'); - FWorksheet.CalcFormulas; - CheckEquals('ÄÖÜ ΓΔΣ', FWorksheet.ReadAsText(0, 1), 'Formula #3 UPPER("ÄÖÜ ΓΔΣ") result mismatch'); - - // Unicode, mixed upper/lower case - FWorksheet.WriteFormula(0, 1, '=UPPER("Äöü Γδσ")'); - FWorksheet.CalcFormulas; - CheckEquals('ÄÖÜ ΓΔΣ', FWorksheet.ReadAsText(0, 1), 'Formula #4 UPPER("Äöü Γδσ") result mismatch'); - - // Mixed unicode, ASCII, number - FWorksheet.WriteFormula(0, 1, '=UPPER("Äöü Γδσ 123")'); - FWorksheet.CalcFormulas; - CheckEquals('ÄÖÜ ΓΔΣ 123', FWorksheet.ReadAsText(0, 1), 'Formula #5 UPPER("Äöü Γδσ 123") result mismatch'); - - // Error in argument - FWorksheet.WriteFormula(0, 1, '=UPPER(#REF!)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #6 UPPER(#REF!) result mismatch'); - - // Cell with error - FWorksheet.WriteFormula(0, 1, '=UPPER(A3)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #7 UPPER(A3) (#REF!) result mismatch'); - - // Empty cell - FWorksheet.WriteFormula(0, 1, '=UPPER(A99)'); - FWorksheet.CalcFormulas; - CheckEquals('', FWorksheet.ReadAsText(0, 1), 'Formula #8 UPPER(A9) (empty) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_VAR; -const - EPS = 1E-8; -begin - // Test data - FWorksheet.WriteNumber (0, 0, 1); - FWorksheet.WriteNumber (1, 0, -2); - FWorksheet.WriteNumber (2, 0, -3); - FWorksheet.WriteText (3, 0, '4'); - FWorksheet.WriteText (4, 0, 'abc'); - FWorksheet.WriteFormula(5, 0, '=1/0'); - - // Literal values - FWorksheet.WriteFormula(0, 1, '=VAR(1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #1 VAR(1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR(1,-2)'); - FWorksheet.CalcFormulas; - CheckEquals(4.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #2 VAR(1,-2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR("4")'); // although string considered to be numeric - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #3 VAR("4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR(1,-2,-3,"4")'); - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #4 VAR(1,-2,-3,"4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 VAR("abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR("")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 VAR("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR(1,-2,-3,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 VAR(1,-2,-3,"abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 VAR(1/0) result mismatch'); - - // Cell references - FWorksheet.WriteFormula(0, 1, '=VAR(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #7 VAR(A1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR(A10)'); // empty cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 VAR(A10)(A10=empty) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals(4.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #9 VAR(A1,A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR(A1:A3)'); // "real" numeric values - FWorksheet.CalcFormulas; - CheckEquals(4.333333333, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #10 VAR(A1:A3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR(A1,A2:A3)'); // several ranges - FWorksheet.CalcFormulas; - CheckEquals(4.333333333, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #11 VAR(A1,A2:A3) result mismatch'); - - // Cell references pointing to string cells - FWorksheet.WriteFormula(0, 1, '=VAR(A1:A4)'); // real and string numeric values - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #12 VAR(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR(A1:A5)'); // real and string values --> ignore string - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #13 VAR(A1:A5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR(A1:A4,A8:A10)'); // real and string values and blanks - FWorksheet.CalcFormulas; - CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #14 VAR(A1:A4,A8:A10) result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 1, '=VAR(A1, 1/0, A2)'); // error in argument - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 VAR(A1, 1/0, A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VAR(A1:A6)'); // error in cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 VAR(A:A6) result mismatch'); -end; - -procedure TCalcFormulaTests.Test_VARP; -const - EPS = 1E-8; -begin - // Test data - FWorksheet.WriteNumber (0, 0, 1); - FWorksheet.WriteNumber (1, 0, -2); - FWorksheet.WriteNumber (2, 0, -3); - FWorksheet.WriteText (3, 0, '4'); - FWorksheet.WriteText (4, 0, 'abc'); - FWorksheet.WriteFormula(5, 0, '=1/0'); - - // Literal values - FWorksheet.WriteFormula(0, 1, '=VARP(1)'); - FWorksheet.CalcFormulas; - CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #1 VAR(1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP(1,-2)'); - FWorksheet.CalcFormulas; - CheckEquals(2.25, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #2 VARP(1,-2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP("4")'); // although string considered to be numeric - FWorksheet.CalcFormulas; - CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #3 VARP("4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP(1,-2,-3,"4")'); - FWorksheet.CalcFormulas; - CheckEquals(7.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #4 VARP(1,-2,-3,"4") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP("abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 VARP("abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP("")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 VARP("") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP(1,-2,-3,"abc")'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 VARP(1,-2,-3,"abc") result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP(1/0)'); - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 VARP(1/0) result mismatch'); - - // Cell references - FWorksheet.WriteFormula(0, 1, '=VARP(A1)'); - FWorksheet.CalcFormulas; - CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #7 VARP(A1) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP(A10)'); // empty cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 VARP(A10)(A10=empty) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP(A1,A2)'); - FWorksheet.CalcFormulas; - CheckEquals(2.25, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #9 VARP(A1,A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP(A1:A3)'); // "real" numeric values - FWorksheet.CalcFormulas; - CheckEquals(2.888888889, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #10 VARP(A1:A3) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP(A1,A2:A3)'); // several ranges - FWorksheet.CalcFormulas; - CheckEquals(2.888888889, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #11 VARP(A1,A2:A3) result mismatch'); - - // Cell references pointing to string cells - FWorksheet.WriteFormula(0, 1, '=VARP(A1:A4)'); // real and string numeric values - FWorksheet.CalcFormulas; - CheckEquals(7.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #12 VARP(A1:A4) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP(A1:A5)'); // real and string values --> ignore string - FWorksheet.CalcFormulas; - CheckEquals(7.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #13 VARP(A1:A5) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP(A1:A4,A8:A10)'); // real and string values and blanks - FWorksheet.CalcFormulas; - CheckEquals(7.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #14 VARP(A1:A4,A8:A10) result mismatch'); - - // Error propagation - FWorksheet.WriteFormula(0, 1, '=VARP(A1, 1/0, A2)'); // error in argument - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 VARP(A1, 1/0, A2) result mismatch'); - - FWorksheet.WriteFormula(0, 1, '=VARP(A1:A6)'); // error in cell - FWorksheet.CalcFormulas; - CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 VARP(A:A6) result mismatch'); -end; +// *** Text formula tests +{$I testcases_calctextformulas.inc} initialization - RegisterTest(TCalcFormulaTests); + RegisterTest('TCalcFormulaTests', TCalcDateTimeFormulaTests); + RegisterTest('TCalcFormulaTests', TCalcInfoFormulaTests); + RegisterTest('TCalcFormulaTests', TCalcLogicalFormulaTests); + RegisterTest('TCalcFormulaTests', TCalcLookupFormulaTests); + RegisterTest('TCalcFormulaTests', TCalcMathFormulaTests); + RegisterTest('TCalcFormulaTests', TCalcStatsFormulaTests); + RegisterTest('TCalcFormulaTests', TCalcTextFormulaTests); end. diff --git a/components/fpspreadsheet/unit-tests/common/spreadtestgui.lpi b/components/fpspreadsheet/unit-tests/common/spreadtestgui.lpi index 70ccd4fb9..0b961890c 100644 --- a/components/fpspreadsheet/unit-tests/common/spreadtestgui.lpi +++ b/components/fpspreadsheet/unit-tests/common/spreadtestgui.lpi @@ -74,7 +74,7 @@ - + @@ -225,6 +225,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/fpspreadsheet/unit-tests/common/testcases_calcdatetimeformulas.inc b/components/fpspreadsheet/unit-tests/common/testcases_calcdatetimeformulas.inc new file mode 100644 index 000000000..a30fc55fc --- /dev/null +++ b/components/fpspreadsheet/unit-tests/common/testcases_calcdatetimeformulas.inc @@ -0,0 +1,170 @@ +{ included by CalcFormulaTests.pas } + +procedure TCalcDateTimeFormulaTests.Test_DATE; +var + actualDate, expectedDate: TDate; +begin + // Normal date + FWorksheet.WriteFormula(0, 1, '=DATE(2025,1,22)'); + FWorksheet.CalcFormulas; + expectedDate := EncodeDate(2025, 1, 22); + FWorksheet.ReadAsDateTime(0, 1, actualDate); + CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#1 Formula DATE(2025,1,22) result mismatch'); + + // Two-digit year + FWorksheet.WriteFormula(0, 1, '=DATE(90,1,22)'); + FWorksheet.CalcFormulas; + expectedDate := EncodeDate(1990, 1, 22); + FWorksheet.ReadAsDateTime(0, 1, actualDate); + CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#2 Formula DATE(90,1,22) result mismatch'); + + // Negative year + FWorksheet.WriteFormula(0, 1, '=DATE(-2000,1,22)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), '#3 Formula DATE(90,1,22) result mismatch'); + + // Too-large year + FWorksheet.WriteFormula(0, 1, '=DATE(10000,1,22)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), '#4 Formula DATE(10000,1,22) result mismatch'); + + // Month > 12 + FWorksheet.WriteFormula(0, 1, '=DATE(2008,14,2)'); + FWorksheet.CalcFormulas; + expectedDate := EncodeDate(2009, 2, 2); + FWorksheet.ReadAsDateTime(0, 1, actualDate); + CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#5 Formula DATE(2008,14,2) result mismatch'); + + // Month < 1 + FWorksheet.WriteFormula(0, 1, '=DATE(2008,-3,2)'); + FWorksheet.CalcFormulas; + expectedDate := EncodeDate(2007, 9, 2); + FWorksheet.ReadAsDateTime(0, 1, actualDate); + CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#6 Formula DATE(2008,-3,2) result mismatch'); + + // Day > Days in month + FWorksheet.WriteFormula(0, 1, '=DATE(2008,1,35)'); + FWorksheet.CalcFormulas; + expectedDate := EncodeDate(2008, 2, 4); + FWorksheet.ReadAsDateTime(0, 1, actualDate); + CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#7 Formula DATE(2008,1,35) result mismatch'); + + // Day < 1 + FWorksheet.WriteFormula(0, 1, '=DATE(2008,1,-15)'); + FWorksheet.CalcFormulas; + expectedDate := EncodeDate(2007, 12, 16); + FWorksheet.ReadAsDateTime(0, 1, actualDate); + CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#8 Formula DATE(2008,1,-15) result mismatch'); + + // Month > 12 and Day > Days in month + FWorksheet.WriteFormula(0, 1, '=DATE(2008,14,50)'); + FWorksheet.CalcFormulas; + expectedDate := EncodeDate(2009, 3, 22); + FWorksheet.ReadAsDateTime(0, 1, actualDate); + CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#9 Formula DATE(2008,14,50) result mismatch'); + + // Month > 12 and Day < 1 + FWorksheet.WriteFormula(0, 1, '=DATE(2008,14,-10)'); + FWorksheet.CalcFormulas; + expectedDate := EncodeDate(2009, 1, 21); + FWorksheet.ReadAsDateTime(0, 1, actualDate); + CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#10 Formula DATE(2008,14,-10) result mismatch'); + + // Month < 1 and Day > Days in month + FWorksheet.WriteFormula(0, 1, '=DATE(2008,-3,50)'); + FWorksheet.CalcFormulas; + expectedDate := EncodeDate(2007,10,20); + FWorksheet.ReadAsDateTime(0, 1, actualDate); + CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#11 Formula DATE(2008,-3,50) result mismatch'); + + // Month < 1 and Day < 1 in month + FWorksheet.WriteFormula(0, 1, '=DATE(2008,-3,-10)'); + FWorksheet.CalcFormulas; + expectedDate := EncodeDate(2007,8,21); + FWorksheet.ReadAsDateTime(0, 1, actualDate); + CheckEquals(DateToStr(expectedDate), DateToStr(actualDate), '#12 Formula DATE(2008,-3,-10) result mismatch'); + + // Error in year + FWorksheet.WriteFormula(0, 1, '=DATE(1/0,1,22)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), '#13 Formula DATE(1/0,1,22) result mismatch'); + + // Error in month + FWorksheet.WriteFormula(0, 1, '=DATE(2025, 1/0, 22)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), '#14 Formula DATE(2025, 1/0, 22) result mismatch'); + + // Error in day + FWorksheet.WriteFormula(0, 1, '=DATE(2025, 1, 1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), '#15 Formula DATE(2025, 1, 1/0) result mismatch'); +end; + +procedure TCalcDateTimeFormulaTests.Test_TIME; +var + actualTime, expectedTime: TTime; +begin + // Normal time + FWorksheet.WriteFormula(0, 1, '=Time(6,32,57)'); + FWorksheet.CalcFormulas; + expectedTime := EncodeTime(6, 32, 57, 0); + FWorksheet.ReadAsDateTime(0, 1, actualTime); + CheckEquals(TimeToStr(expectedTime), TimeToStr(actualTime), 'Formula #1 TIME(6,32,57) result mismatch'); + + // Hours < 0 + FWorksheet.WriteFormula(0, 1, '=Time(-6,32,57)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #2 TIME(-6,32,57) result mismatch'); + + // Hours > 23 + FWorksheet.WriteFormula(0, 1, '=Time(15,32,57)'); + FWorksheet.CalcFormulas; + expectedTime := 0.647881944; // Value read from Excel + FWorksheet.ReadAsDateTime(0, 1, actualTime); + CheckEquals(TimeToStr(expectedTime), TimeToStr(actualTime), 'Formula #3 TIME(15,32,57) result mismatch'); + + // Minutes > 59 + FWorksheet.WriteFormula(0, 1, '=Time(6,100,57)'); + FWorksheet.CalcFormulas; + expectedTime := 0.320104167; // Value read from Excel + FWorksheet.ReadAsDateTime(0, 1, actualTime); + CheckEquals(TimeToStr(expectedTime), TimeToStr(actualTime), 'Formula #4 TIME(6,100,57) result mismatch'); + + // Minutes < 0 + FWorksheet.WriteFormula(0, 1, '=Time(6,-100,57)'); + FWorksheet.CalcFormulas; + expectedTime := 0.181215278; // Value read from Excel + FWorksheet.ReadAsDateTime(0, 1, actualTime); + CheckEquals(TimeToStr(expectedTime), TimeToStr(actualTime), 'Formula #5 TIME(6,-100,57) result mismatch'); + + // Seconds > 59 + FWorksheet.WriteFormula(0, 1, '=Time(6,32,100)'); + FWorksheet.CalcFormulas; + expectedTime := 0.27337963; // Value read from Excel + FWorksheet.ReadAsDateTime(0, 1, actualTime); + CheckEquals(TimeToStr(expectedTime), TimeToStr(actualTime), 'Formula #6 TIME(6,32,100) result mismatch'); + + // Seconds < 0 + FWorksheet.WriteFormula(0, 1, '=Time(6,32,-100)'); + FWorksheet.CalcFormulas; + expectedTime := 0.271064815; // Value read from Excel + FWorksheet.ReadAsDateTime(0, 1, actualTime); + CheckEquals(TimeToStr(expectedTime), TimeToStr(actualTime), 'Formula #7 TIME(6,32,-100) result mismatch'); + + // Error in hours + FWorksheet.WriteFormula(0, 1, '=Time(1/0,32,57)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 TIME(1/0,32,57) result mismatch'); + + // Error in minutes + FWorksheet.WriteFormula(0, 1, '=Time(6,1/0,57)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #9 TIME(6,1/0,57) result mismatch'); + + // Error in seconds + FWorksheet.WriteFormula(0, 1, '=Time(6,32,1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #10 TIME(6,32,1/0) result mismatch'); +end; + + diff --git a/components/fpspreadsheet/unit-tests/common/testcases_calcinfoformulas.inc b/components/fpspreadsheet/unit-tests/common/testcases_calcinfoformulas.inc new file mode 100644 index 000000000..337e21dd1 --- /dev/null +++ b/components/fpspreadsheet/unit-tests/common/testcases_calcinfoformulas.inc @@ -0,0 +1,529 @@ +{ included by CalcFormulaTests.pas } + +procedure TCalcInfoFormulaTests.Test_ERRORTYPE; +begin + // Explicit error type + FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(#REF!)'); + FWorksheet.CalcFormulas; + CheckEquals(ord(errIllegalRef), FWorksheet.ReadAsNumber(0, 1), 'Formula #1 ERROR.TYPE(#REF!) result mismatch'); + + // No error in cell --> #N/A + FWorksheet.WriteNumber(0, 0, 123); + FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 1), 'Formula #2 ERROR.TYPE (no error!) result mismatch'); + + // #NULL! error + FWorksheet.WriteNumber(0, 0, 12); + FWorksheet.WriteNumber(1, 0, -2); + + // ToDo: Space as argument separator not detected correctly! +{ + This currently is not handled by FPS... + FWorksheet.WriteFormula(2, 0, '=SUM(A1 A2)'); // missing comma --> #NULL! + FWorksheet.WriteFormula(2, 0, '=ERROR.TYPE(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(ord(errEmptyIntersection), FWorksheet.ReadAsNumber(2, 0), 'Formula #1 ERROR.TYPE (#NULL!) result mismatch'); +} + + // #REF! error + FWorksheet.WriteFormula(2, 0, '=SUM(A1,A2)'); + FWorksheet.DeleteRow(0); // This creates the #REF! error in the sum cell A2 + FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(A2)'); + FWorksheet.CalcFormulas; + CheckEquals(ord(errIllegalRef), FWorksheet.ReadAsNumber(0, 1), 'Formula #3 ERROR.TYPE (#REF!) result mismatch'); + + // #VALUE! error + FWorksheet.WriteText(0, 0, 'a'); + FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(1+A1)'); + FWorksheet.CalcFormulas; + CheckEquals(ord(errWrongType), FWorksheet.ReadAsNumber(0, 1), 'Formula #4 ERROR.TYPE #VALUE! result mismatch'); + + // #DIV/0! error + FWorksheet.WriteFormula(0, 0, '=1/0'); + FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(ord(errDivideByZero), FWorksheet.ReadAsNumber(0, 1), 'Formula #5 ERROR.TYPE #DIV/0! result mismatch'); + + // #NUM! error + FWorksheet.WriteFormula(0, 0, '=SQRT(-1)'); + FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(ord(errOverflow), FWorksheet.ReadAsNumber(0, 1), 'Formula #6 ERROR.TYPE #NUM! result mismatch'); + + // ToDo: Create #NAME? error node when identifier is not found. Parser always raises an exception during scanning - maybe there should be a TsErrorExprNode? + + { --- not correctly detected by FPS parser ... + // #NAME? error + FWorksheet.WriteFormula(0, 0, '=S_Q_R_T(-1)'); + FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(ord(errWrongName), FWorksheet.ReadAsNumber(0, 1), 'Formula #1 ERROR.TYPE #NAME? result mismatch'); + } + + // #N/A error + FWorksheet.WriteNumber(0, 0, 10); + FWorksheet.WriteNumber(1, 0, 20); + FWorksheet.WriteFormula(2, 0, '=MATCH(-10,A1:A2,0)'); + FWorksheet.WriteFormula(0, 1, '=ERROR.TYPE(A3)'); + FWorksheet.CalcFormulas; + CheckEquals(ord(errArgError), FWorksheet.ReadAsNumber(0, 1), 'Formula #7 ERROR.TYPE #N/A result mismatch'); +end; + +procedure TCalcInfoFormulaTests.Test_IFERROR; +begin + FWorksheet.WriteFormula(0, 1, '=IFERROR("abc", "ERROR")'); + FWorksheet.CalcFormulas; + CheckEquals('abc', FWorksheet.ReadAsText(0, 1), 'Formula #1 IFERROR("abc","ERROR") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=IFERROR(#N/A, "ERROR")'); + FWorksheet.CalcFormulas; + CheckEquals('ERROR', FWorksheet.ReadAsText(0, 1), 'Formula #2 IFERROR(#N/A,"ERROR") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=IFERROR(#N/A, #DIV/0!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #3 IFERROR(#N/A,#DIV/0!) result mismatch'); +end; + + +procedure TCalcInfoFormulaTests.Test_ISBLANK; +var + cell: PCell; +begin + cell := FWorksheet.WriteFormula(0, 1, '=ISBLANK(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISBLANK(A1) with A1=blank result mismatch'); + + FWorksheet.WriteText(0, 0, ''); + cell := FWorksheet.WriteFormula(0, 1, '=ISBLANK(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISBLANK(A1) with A1='' result mismatch'); + + // No argument + { In Excel the "no argument" case is not accepted (runtime error, no error code) + cell := FWorksheet.WriteFormula(0, 1, '=ISBLANK()'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 ISBLANK() result mismatch'); + } + + // String + cell := FWorksheet.WriteFormula(0, 1, '=ISBLANK("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #4 ISBLANK("abc") result mismatch'); + + // Some Excel oddity: an empty string is not "blank"... + cell := FWorksheet.WriteFormula(0, 1, '=ISBLANK("")'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISBLANK("") result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 0, '=1/0'); + cell := FWorksheet.WriteFormula(0, 1, '=ISBLANK(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISBLANK(A1) with A1=1/0 result mismatch'); + CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #6 ISBLANK(A1) with A1=1/0 result mismatch'); +end; + +procedure TCalcInfoFormulaTests.Test_ISERR; +var + cell: PCell; +begin + // Hard coded expression with error #DIV/0! + cell := FWorksheet.WriteFormula(0, 1, '=ISERR(#DIV/0!)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISERR(1/0) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, '=ISERR(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISERR(1/0) result mismatch'); + + // Hard coded expression without error + cell := FWorksheet.WriteFormula(0, 1, '=ISERR(0/1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 ISERR(0/1) result mismatch'); + + // Reference to cell with error + FWorksheet.WriteFormula(0, 0, '=1/0'); + cell := FWorksheet.WriteFormula(0, 1, '=ISERR(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #4 ISERR(A1) result mismatch'); + + // Reference to cell without error + FWorksheet.WriteText(0, 0, 'abc'); + cell := FWorksheet.WriteFormula(0, 1, '=ISERR(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISERR(A1) result mismatch (no error in cell)'); + + // No error as argument + cell := FWorksheet.WriteFormula(0, 1, '=ISERR("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISERR(A1) result mismatch (no error as argument)'); + + // #N/A error + cell := FWorksheet.WriteFormula(0, 1, '=ISERR(#N/A)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #7 ISERR(#N/A) result mismatch (#N/A as argument)'); + + FWorksheet.WriteNumber(0, 0, 10); + FWorksheet.WriteNumber(1, 0, 20); + FWorksheet.WriteFormula(2, 0, '=MATCH(-10, A1:A2, 0)'); // generates a #N/A error + cell := FWorksheet.WriteFormula(0, 1, '=ISERR(A3)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #8 ISERR(#N/A) result mismatch (#N/A as argument)'); +end; + +procedure TCalcInfoFormulaTests.Test_ISERROR; +var + cell: PCell; +begin + // #DIV/0! as argument + cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(#DIV/0!)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISERROR(1/0) result mismatch'); + + // Cell with #DIV/0! error + FWorksheet.WriteFormula(0, 0, '=1/0'); + cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISERROR(A1) (A1 = 1/0) result mismatch'); + + // Hard coded expression without error + cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(0/1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 ISERROR(0/1) result mismatch'); + + // Reference to cell with error + FWorksheet.WriteFormula(0, 0, '=1/0'); + cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #4 ISERROR(A1) result mismatch'); + + // Reference to cell without error + FWorksheet.WriteText(0, 0, 'abc'); + cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISERROR(A1) result mismatch (no error in cell)'); + + // No error as argument + cell := FWorksheet.WriteFormula(0, 1, '=ISERROR("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISERROR(A1) result mismatch (no error as argument)'); + + // #N/A error + cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(#N/A)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #7 ISERROR(#N/A) result mismatch (#N/A as argument)'); + + FWorksheet.WriteNumber(0, 0, 10); + FWorksheet.WriteNumber(1, 0, 20); + FWorksheet.WriteFormula(2, 0, '=MATCH(-10, A1:A2, 0)'); // generates a #N/A error + cell := FWorksheet.WriteFormula(0, 1, '=ISERROR(A3)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #8 ISERROR(#N/A) result mismatch (#N/A as argument)'); +end; + +procedure TCalcInfoFormulaTests.Test_ISLOGICAL; +var + cell: PCell; +begin + // Boolean + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISLOGICAL result mismatch (true)'); + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(FALSE)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISLOGICAL result mismatch (false)'); + + FWorksheet.WriteBoolValue(0, 0, true); + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 ISLOGICAL result mismatch (bool cell)'); + + // Number + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(1.23)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #4 ISLOGICAL result mismatch (number)'); + + FWorksheet.WriteNumber(0, 0, 1.234); + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISLOGICAL result mismatch (number cell)'); + + // Date + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(DATE(2025,1,1))'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISLOGICAL result mismatch (date)'); + + FWorksheet.WriteDateTime(0, 0, EncodeDate(2025,1,1)); + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #7 ISLOGICAL result mismatch (date cell)'); + + // String (corresponding to 'true') + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL("TRUE")'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #8 ISLOGICAL result mismatch ("true" as string)'); + + FWorksheet.WriteText(0, 0, 'TRUE'); + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #9 ISLOGICAL result mismatch ("true" as string cell)'); + + // Blank + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL()'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #10 ISLOGICAL result mismatch (blank)'); + + FWorksheet.WriteBlank(0, 0); + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #11 ISLOGICAL result mismatch (blank cell)'); + + // Error + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #12 ISLOGICAL result mismatch (error value)'); + CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #12 ISLOGICAL result mismatch (error value)'); + + FWorksheet.WriteFormula(0, 0, '=1/0'); + cell := FWorksheet.WriteFormula(0, 1, '=ISLOGICAL(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #13 ISLOGICAL result mismatch (cell with error value)'); + CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #13 ISLOGICAL result mismatch (cell with error value)'); +end; + +procedure TCalcInfoFormulaTests.Test_ISNA; +var + cell: PCell; +begin + // Check cell with #N/A error + FWorksheet.WriteNumber(0, 0, 10); + FWorksheet.WriteNumber(1, 0, 20); + FWorksheet.WriteFormula(2, 0, '=MATCH(-10,A1:A2,0)'); // This creates an #N/A error + cell := FWorksheet.WriteFormula(0, 1, '=ISNA(A3)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISNA result mismatch (#N/A error)'); + + // Cell with other error (#DIV/0!) + FWorksheet.WriteFormula(2, 0, '=1/0'); + cell := FWorksheet.WriteFormula(0, 1, '=ISNA(A3)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #2 ISNA result mismatch (other error)'); + + // Cell with no error + cell := FWorksheet.WriteFormula(0, 1, '=ISNA(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 ISNA result mismatch (no error)'); +end; + +procedure TCalcInfoFormulaTests.Test_ISNONTEXT; +var + cell: PCell; +begin + // Number + cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(1.234)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISNONTEXT result mismatch (float)'); + + FWorksheet.WriteNumber(0, 0, 1.234); + cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISNONTEXT result mismatch (float cell)'); + + // Date + cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(DATE(2025,1,1))'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 ISNONTEXT result mismatch (date)'); + + FWorksheet.WriteDateTime(0, 0, EncodeDate(2025,1,1)); + cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #4 ISNONTEXT result mismatch (date cell)'); + + // String + cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISNONTEXT result mismatch (float as string)'); + + FWorksheet.WriteText(0, 0, 'abc'); + cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISNONTEXT result mismatch (float as string cell)'); + + // Boolean + cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #7 ISNONTEXT result mismatch (boolean)'); + + FWorksheet.WriteFormula(0, 0, '=(1=1)'); + cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #8 ISNONTEXT result mismatch (boolean cell)'); + + // Blank + cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT()'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #9 ISNONTEXT result mismatch (blank)'); + + FWorksheet.WriteBlank(0, 0); + cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #10 ISNONTEXT result mismatch (blank cell)'); + + // Error + cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #11 ISNONTEXT result mismatch (error value)'); + CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #11 ISNONTEXT result mismatch (error value)'); + + FWorksheet.WriteFormula(0, 0, '=1/0'); + cell := FWorksheet.WriteFormula(0, 1, '=ISNONTEXT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #12 ISNONTEXT result mismatch (cell with error value)'); + CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #12 ISNONTEXT result mismatch (cell with error value)'); +end; + +procedure TCalcInfoFormulaTests.Test_ISNUMBER; +var + cell: PCell; +begin + // Number + cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(1.234)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 IsNumber result mismatch (float)'); + + FWorksheet.WriteNumber(0, 0, 1.234); + cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 IsNumber result mismatch (float cell)'); + + // Date + cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(DATE(2025,1,1))'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 IsNumber result mismatch (date)'); + + FWorksheet.WriteDateTime(0, 0, EncodeDate(2025,1,1)); + cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #4 IsNumber result mismatch (date cell)'); + + // String (corresponds to number) + cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER("1.234")'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISNUMBER result mismatch (float as string)'); + + FWorksheet.WriteText(0, 0, '1.234'); + cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISNUMBER result mismatch (float as string cell)'); + + // Boolean + cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #7 ISNUMBER result mismatch (boolean)'); + + FWorksheet.WriteFormula(0, 0, '=(1=1)'); + cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #8 ISNUMBER result mismatch (boolean cell)'); + + // Blank + cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER()'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #9 ISNUMBER result mismatch (blank)'); + + FWorksheet.WriteBlank(0, 0); + cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #10 ISNUMBER result mismatch (blank ceöö)'); + + // Error + cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #11 ISNUMBER result mismatch (error value)'); + CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #11 ISNUMBER result mismatch (error value)'); + + FWorksheet.WriteFormula(0, 0, '=1/0'); + cell := FWorksheet.WriteFormula(0, 1, '=ISNUMBER(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #12 ISNUMBER result mismatch (cell with error value)'); + CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #12 ISNUMBER result mismatch (cell with error value)'); +end; + +procedure TCalcInfoFormulaTests.Test_ISREF; +var + cell: PCell; +begin + // Cell reference + cell := FWorksheet.WriteFormula(0, 1, '=ISREF(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISREF result mismatch (cell reference)'); + + // Cell range + cell := FWorksheet.WriteFormula(0, 1, '=ISREF(A1:A3)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISREF result mismatch (cell range reference)'); + + // 3d cell ref + cell := FWorksheet.WriteFormula(0, 1, '=ISREF(Sheet1!A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 ISREF result mismatch (3d cell reference)'); + + // 3d cell range ref + cell := FWorksheet.WriteFormula(0, 1, '=ISREF(Sheet1!A1:A3)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 ISREF result mismatch (3d cell range reference)'); + + // no ref + cell := FWorksheet.WriteFormula(0, 1, '=ISREF("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 ISREF result mismatch (string)'); +end; + +procedure TCalcInfoFormulaTests.Test_ISTEXT; +var + cell: PCell; +begin + // Text + cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 ISTEXT result mismatch (text)'); + + FWorksheet.WriteText(0, 0, 'abc'); + cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 ISTEXT result mismatch (text cell)'); + + // Number + cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT(1.234)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 ISTEXT result mismatch (number)'); + + FWorksheet.WriteNumber(0, 0, 1.234); + cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #4 ISTEXT result mismatch (number cell)'); + + // Blank + cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT()'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 ISTEXT result mismatch (blank)'); + + FWorksheet.WriteBlank(0, 0); + cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #6 ISTEXT result mismatch (blank cell)'); + + // Error + cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #7 ISTEXT result mismatch (error value)'); + CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #7 ISTEXT result mismatch (error value)'); + + FWorksheet.WriteFormula(0, 0, '=1/0'); + cell := FWorksheet.WriteFormula(0, 1, '=ISTEXT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #8 ISTEXT result mismatch (error value)'); + CheckNotEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #8 ISTEXT result mismatch (error value)'); +end; + diff --git a/components/fpspreadsheet/unit-tests/common/testcases_calclogicalformulas.inc b/components/fpspreadsheet/unit-tests/common/testcases_calclogicalformulas.inc new file mode 100644 index 000000000..2a5f6319f --- /dev/null +++ b/components/fpspreadsheet/unit-tests/common/testcases_calclogicalformulas.inc @@ -0,0 +1,195 @@ +{ included by CalcFormulaTests.pas } + +procedure TCalcLogicalFormulaTests.Test_AND; +var + cell: PCell; +begin + cell := FWorksheet.WriteFormula(0, 1, 'AND(1=1,2=2)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 AND(1=1,2=2) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'AND(1=2,2=2)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #2 AND(1=2,2=2) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'AND(1=1,2=1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #3 AND(1=1,2=1) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'AND(1=2,2=1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #4 AND(1=2,2=1) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'AND(1/0,2=2)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #5 AND(1/0,2=2) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'AND(1,TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #6 AND(1,TRUE) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'AND(0,TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #7 AND(0,TRUE) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'AND("0",TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(cell), 'Formula #8 AND("0",TRUE) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'AND("abc",TRUE)'); + 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,0)'); + FWorksheet.CalcFormulas; + 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 TCalcLogicalFormulaTests.Test_IF; +begin + FWorksheet.WriteNumber(0, 0, 256.0); + + // 3 arguments + FWorksheet.WriteFormula(0, 1, '=IF(A1>=100,"ok","not ok")'); + FWorksheet.CalcFormulas; + CheckEquals('ok', FWorksheet.ReadAsText(0, 1), 'Formula #1 IF(A1>=100,"ok","not ok") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=IF(A1<100,"ok","not ok")'); + FWorksheet.CalcFormulas; + CheckEquals('not ok', FWorksheet.ReadAsText(0, 1), 'Formula #2 IF(A1<100,"ok","not ok") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=IF(1,"ok","not ok")'); + FWorksheet.CalcFormulas; + CheckEquals('ok', FWorksheet.ReadAsText(0, 1), 'Formula #3 IF(1,"ok","not ok") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=IF(0,"ok","not ok")'); + FWorksheet.CalcFormulas; + CheckEquals('not ok', FWorksheet.ReadAsText(0, 1), 'Formula #4 IF(0,"ok","not ok") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=IF("1","ok","not ok")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 IF("1","ok","not ok") result mismatch'); + + // 2 arguments + FWorksheet.WriteFormula(0, 1, '=IF(A1>=100,"ok")'); + FWorksheet.CalcFormulas; + CheckEquals('ok', FWorksheet.ReadAsText(0, 1), 'Formula #6 IF(A1>=100,"ok") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=IF(A1<100,"ok")'); + FWorksheet.CalcFormulas; + CheckEquals('FALSE', FWorksheet.ReadAsText(0, 1), 'Formula #7 IF(A1<100,"ok") result mismatch'); + + // Error propagation: error in 3rd argument - result is non-error argument + FWorksheet.WriteFormula(0, 1, '=IF(A1>=100, "ok", 1/0)'); + FWorksheet.CalcFormulas; + CheckEquals('ok', FWorksheet.ReadAsText(0, 1), 'Formula #8 IF(A1>=100,"ok",1/0) result mismatch'); + + // Error propagation: error in 3rd argument - result is error argument + FWorksheet.WriteFormula(0, 1, '=IF(A1<100, "ok", 1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #9 IF(A1<100,"ok",1/0) result mismatch'); + + // Error propagation: error in 2nd argument - result is error argument + FWorksheet.WriteFormula(0, 1, '=IF(A1>=100, 1/0,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #10 IF(A1>=100,1/0,"abc") result mismatch'); + + // Error propagation: error in 2nd argument - result is 3rd argument + FWorksheet.WriteFormula(0, 1, '=IF(A1<100, 1/0,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals('abc', FWorksheet.ReadAsText(0, 1), 'Formula #11 IF(A1<100,1/0,"abc") result mismatch'); + + // Error propagaton: error in 1st argument + FWorksheet.WriteFormula(0, 0, '=1/0'); + FWorksheet.WriteFormula(0, 1, '=IF(A1>=100,"ok","not ok")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #12 IF(A1>=100,"ok","not ok") with A1=1/0 result mismatch'); +end; + +procedure TCalcLogicalFormulaTests.Test_NOT; +var + cell: PCell; +begin + cell := FWorksheet.WriteFormula(0, 1, 'NOT(1=1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #1 NOT(1=1) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'NOT(1=2)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 NOT(1=2) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'NOT(0)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 NOT(0) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'NOT(1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #4 NOT(1) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'NOT(12)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #5 NOT(12) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'NOT("0")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(cell), 'Formula #6 NOT("0") result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'NOT("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(cell), 'Formula #7 NOT("abc") result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'NOT(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #8 NOT(1/0) result mismatch'); +end; + +procedure TCalcLogicalFormulaTests.Test_OR; +var + cell: PCell; +begin + cell := FWorksheet.WriteFormula(0, 1, 'OR(1=1,2=2)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #1 OR(1=1,2=2) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'OR(1=2,2=2)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #2 OR(1=2,2=2) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'OR(1=1,2=1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #3 OR(1=1,2=1) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'OR(1=2,2=1)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #4 OR(1=2,2=1) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'OR(1/0,2=2)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #5 OR(1/0,2=2) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'OR(1,TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(true, FWorksheet.IsTrueValue(cell), 'Formula #6 OR(1,TRUE) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'OR(0,FALSE)'); + FWorksheet.CalcFormulas; + CheckEquals(false, FWorksheet.IsTrueValue(cell), 'Formula #7 OR(0,TRUE) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'OR("0",TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(cell), 'Formula #8 OR("0",TRUE) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'OR("abc",TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(cell), 'Formula #9 OR("abc",TRUE) result mismatch'); + + cell := FWorksheet.WriteFormula(0, 1, 'OR(1/0,1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(cell), 'Formula #10 OR(1/0,1/0) result mismatch'); +end; + + diff --git a/components/fpspreadsheet/unit-tests/common/testcases_calclookupformulas.inc b/components/fpspreadsheet/unit-tests/common/testcases_calclookupformulas.inc new file mode 100644 index 000000000..ca6cbf30c --- /dev/null +++ b/components/fpspreadsheet/unit-tests/common/testcases_calclookupformulas.inc @@ -0,0 +1,542 @@ +{ included by CalcFormulaTests.pas } + +procedure TCalcLookupFormulaTests.Test_ADDRESS; +begin + // Default values only + FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,1)'); + FWorksheet.CalcFormulas; + CheckEquals('$A$1', FWorksheet.ReadAsText(0, 1), 'Formula #1 ADDRESS(1,1) result mismatch'); + + // 3rd parameter --> absolute address + FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,1)'); + FWorksheet.CalcFormulas; + CheckEquals('$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #2 ADDRESS(1,2,1) result mismatch'); + + // 3rd parameter --> absolute row + FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,2)'); + FWorksheet.CalcFormulas; + CheckEquals('B$1', FWorksheet.ReadAsText(0, 1), 'Formula #3 ADDRESS(1,2,2) result mismatch'); + + // 3rd parameter --> absolute col + FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,3)'); + FWorksheet.CalcFormulas; + CheckEquals('$B1', FWorksheet.ReadAsText(0, 1), 'Formula 43 ADDRESS(1,2,3) result mismatch'); + + // 3rd parameter --> relative address + FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,4)'); + FWorksheet.CalcFormulas; + CheckEquals('B1', FWorksheet.ReadAsText(0, 1), 'Formula #5 ADDRESS(1,2,4) result mismatch'); + + // missing 3rd parameter --> absolute address + FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,)'); + FWorksheet.CalcFormulas; + CheckEquals('$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #6 ADDRESS(1,2,) result mismatch'); + + // Combined with ROW() and COLUMN() formulas + FWorksheet.WriteFormula(0, 1, '=ADDRESS(ROW(),COLUMN())'); + FWorksheet.CalcFormulas; + CheckEquals('$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #7 ADDRESS(ROW(), COLUMN()) result mismatch'); + + // A1 dialect + FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,1,TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals('$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #8 ADDRESS(1,2,1,TRUE) result mismatch'); + + // R1C1 dialect + FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,1,FALSE)'); + FWorksheet.CalcFormulas; + CheckEquals('R1C2', FWorksheet.ReadAsText(0, 1), 'Formula #9 ADDRESS(1,2,1,FALSE) result mismatch'); + + // Missing dialect argument (must use A1 then) + FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,1,)'); + FWorksheet.CalcFormulas; + CheckEquals('$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #10 ADDRESS(1,2,1,) result mismatch'); + + // Sheet name + FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,1,TRUE,"Sheet1")'); + FWorksheet.CalcFormulas; + CheckEquals('Sheet1!$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #11 ADDRESS(1,2,1,TRUE,"Sheet1") result mismatch'); + + // Quoted sheet name + FWorksheet.WriteFormula(0, 1, '=ADDRESS(1,2,1,TRUE,"Sheet 1")'); + FWorksheet.CalcFormulas; + CheckEquals('''Sheet 1''!$B$1', FWorksheet.ReadAsText(0, 1), 'Formula #12 ADDRESS(1,2,1,TRUE,"Sheet 1") result mismatch'); + + // Elements of address in cells + FWorksheet.WriteNumber(0, 0, 1); // Row (1) + FWorksheet.WriteNumber(1, 0, 2); // Column (2) + FWorksheet.WriteNumber(2, 0, 4); // Flags (relative) + FWorksheet.WriteBoolValue(3, 0, FALSE); // Dialect (R1C1) + FWorksheet.WriteText(4, 0, 'Sheet 1'); // Worksheet + FWorksheet.WriteFormula(0, 1, '=ADDRESS(A1,A2,A3,A4,A5)'); + FWorksheet.CalcFormulas; + CheckEquals('''Sheet 1''!R[1]C[2]', FWorksheet.ReadAsText(0, 1), 'Formula #13 ADDRESS(A1,A2,A3,A4,A5) result mismatch'); + + // dto., Sheetname cell empty + FWorksheet.WriteFormula(0, 1, '=ADDRESS(A1,A2,A3,A4,A10)'); + FWorksheet.CalcFormulas; + CheckEquals('R[1]C[2]', FWorksheet.ReadAsText(0, 1), 'Formula #13 ADDRESS(A1,A2,A3,A4,A10) (A10 blank) result mismatch'); + + // dto., Dialect cell empty (--> is assume to be 0 --> RC dialect) + FWorksheet.WriteFormula(0, 1, '=ADDRESS(A1,A2,A3,A9,A10)'); + FWorksheet.CalcFormulas; + CheckEquals('R[1]C[2]', FWorksheet.ReadAsText(0, 1), 'Formula #13 ADDRESS(A1,A2,A3,A9,A11) (A9,A10 blank) result mismatch'); +end; + +procedure TCalcLookupFormulaTests.Test_COLUMN; +begin + // Get column number of specified cell + FWorksheet.WriteFormula(0, 1, '=COLUMN(B2)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 COLUMN(B2) result mismatch'); + + // Get col of the formula cell --- NOT CORRECTLY IMPLEMENTED IN FPS + FWorksheet.WriteFormula(0, 1, '=COLUMN()'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 COLUMN() result mismatch'); // This would be the Excel result! + //CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #2 COLUMN() result mismatch'); + + // Error value as argument + FWorksheet.WriteFormula(0, 1, '=COLUMN(#REF!)'); + FWorksheet.CalcFormulas; + //CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 COLUMN() result mismatch'); + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #3 COLUMN(#REF!) result mismatch'); + + // Cell containing an error as argument + FWorksheet.WriteFormula(1, 1, '=1/0'); // cell B2 + FWorksheet.WriteFormula(0, 2, '=COLUMN(B2)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #4 COLUMN(B2) (B2 contains error) result mismatch'); +end; + +procedure TCalcLookupFormulaTests.Test_INDEX; +var + sh: TsWorksheet; +begin + // Sample adapted from https://www.ionos.de/digitalguide/online-marketing/verkaufen-im-internet/excel-index-funktion/ + sh := FWorksheet; + sh.WriteText(0, 0, 'Name'); sh.WriteText (0, 1, '1991'); sh.WriteText (0, 2, '1992'); + sh.WriteText(1, 0, 'Peter'); sh.WriteNumber(1, 1, 78); sh.WriteNumber(1, 2, 81); + sh.WriteText(2, 0, 'Frank'); sh.WriteNumber(2, 1, 55); sh.WriteNumber(2, 2, 66); + sh.WriteText(3, 0, 'Louise'); sh.WriteNumber(3, 1, 42); sh.WriteNumber(3, 2, 59); + sh.WriteText(4, 0, 'Valery'); sh.WriteNumber(4, 1, 12); sh.WriteNumber(4, 2, 33); + sh.Writetext(5, 0, 'Eva'); sh.WriteNumber(5, 1, 40); sh.WriteNumber(5, 2, 66); + + // Cell at third row and first column in range B2:C6 + FWorksheet.WriteFormula(10, 0, '=INDEX(B2:C6,3,1)'); + FWorksheet.CalcFormulas; + CheckEquals(42, FWorksheet.ReadAsNumber(10,0), 'Formula #1 INDEX(B2:F3,3,1) result mismatch'); + + // Sample similar to that in unit formulatests: + + FWorksheet.Clear; + FWorksheet.WriteText (0, 0, 'A'); // A1 + FWorksheet.WriteText (0, 1, 'B'); // B1 + FWorksheet.WriteText (0, 2, 'C'); // C1 + FWorksheet.WriteNumber(1, 0, 10); // A2 + FWorksheet.WriteNumber(1, 1, 20); // B2 + FWorksheet.WriteNumber(1, 2, 30); // C2 + FWorksheet.WriteNumber(2, 0, 11); // A3 + FWorksheet.WriteNumber(2, 1, 22); // B3 + FWorksheet.WriteNumber(2, 2, 33); // C4 + + FWorksheet.WriteFormula(0, 5, 'INDEX(A1:C3,1,1)'); + FWorksheet.CalcFormulas; + CheckEquals('A', FWorksheet.ReadAsText(0, 5), 'Formula #2 INDEX(A1:C3,1,1) result mismatch'); + + FWorksheet.WriteFormula(0, 5, 'INDEX(A1:C1,3)'); + FWorksheet.CalcFormulas; + CheckEquals('C', FWorksheet.ReadAsText(0, 5), 'Formula #3 INDEX(A1:C1,3) result mismatch'); + + FWorksheet.WriteFormula(0, 5, 'INDEX(A1:A3,2)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 5), 'Formula #4 INDEX(A1:A3,3) result mismatch'); + + FWorksheet.WriteFormula(0, 5, 'INDEX(A1:C2,1,10)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 5), 'Formula #5 INDEX(A1:C2,1,10) result mismatch'); + + FWorksheet.WriteFormula(0, 5, 'SUM(INDEX(A1:C3,0,2))'); // Sum of numbers in 2nd column of A1:C3 + FWorksheet.CalcFormulas; + CheckEquals(42, FWorksheet.ReadAsNumber(0, 5), 'Formula #6 SUM(INDEX(A1:C3,0,2)) result mismatch'); + + FWorksheet.WriteFormula(0, 5, 'SUM(INDEX(A1:C3,2,0))'); // Sum of numbers in 2nd row of A1:C3 + FWorksheet.CalcFormulas; + CheckEquals(60, FWorksheet.ReadAsNumber(0, 5), 'Formula #7 SUM(INDEX(A1:C3,2,0)) result mismatch'); + + // Now the same tests, but across sheets + FOtherWorksheet.WriteFormula(0, 5, 'INDEX(Sheet1!A1:C3,1,1)'); + FWorkbook.CalcFormulas; + CheckEquals('A', FOtherWorksheet.ReadAsText(0, 5), 'Formula #8 INDEX(Sheet1!A1:C3,1,1) result mismatch'); + + FOtherWorksheet.WriteFormula(0, 5, 'INDEX(Sheet1!A1:C1,3)'); + FWorkbook.CalcFormulas; + CheckEquals('C', FOtherWorksheet.ReadAsText(0, 5), 'Formula #9 INDEX(Sheet1!A1:C1,3) result mismatch'); + + FOtherWorksheet.WriteFormula(0, 5, 'INDEX(Sheet1!A1:A3,2)'); + FWorkbook.CalcFormulas; + CheckEquals(10, FOtherWorksheet.ReadAsNumber(0, 5), 'Formula #10 INDEX(Sheet1!A1:A3,3) result mismatch'); + + FOtherWorksheet.WriteFormula(0, 5, 'INDEX(Sheet1!A1:C2,1,10)'); + FWorkbook.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FOtherWorksheet.ReadAsText(0, 5), 'Formula #11 INDEX(Sheet1!A1:C2,1,10) result mismatch'); + + FOtherWorksheet.WriteFormula(0, 5, 'SUM(INDEX(Sheet1!A1:C3,0,2))'); // Sum of numbers in 2nd column of A1:C3 + FWorkbook.CalcFormulas; + CheckEquals(42, FOtherWorksheet.ReadAsNumber(0, 5), 'Formula #6 SUM(Sheet1!INDEX(A1:C3,0,2)) result mismatch'); + + FOtherWorksheet.WriteFormula(0, 5, 'SUM(INDEX(Sheet1!A1:C3,2,0))'); // Sum of numbers in 2nd row of A1:C3 + FWorkbook.CalcFormulas; + CheckEquals(60, FOtherWorksheet.ReadAsNumber(0, 5), 'Formula #7 SUM(Sheet1!INDEX(A1:C3,2,0)) result mismatch'); +end; + +procedure TCalcLookupFormulaTests.Test_INDIRECT; +begin + // *** Test data *** + FWorksheet.WriteNumber (0, 0, 10); // A1 + FWorksheet.WriteNumber (1, 0, 20); // A2 + FWorksheet.WriteNumber (2, 0, 30); // A3 + FWorksheet.WriteText (3, 0, 'A1'); // A4 + FWorksheet.WriteErrorValue(4, 0, errDivideByZero); // A5 + FWorksheet.WriteText (5, 0, 'A'); // A6 + FWorksheet.WriteNumber (6, 0, 1); // A7 + FWorksheet.WriteText (7, 0, 'Sheet2'); // A8 + FWorksheet.WriteText (8, 0, 'Sheet2!A1:A3'); // A9 + FWorksheet.WriteFormula(9, 0, '=A6&A7'); // A10 + FOtherWorksheet.WriteNumber(0, 0, 1000); // Sheet2!A1 + FOtherWorksheet.WriteNumber(1, 0, 2000); // Sheet2!A2 + FOtherWorksheet.WriteNumber(2, 0, 3000); // Sheet2!A3 + + // *** Single cell references *** + FWorksheet.WriteFormula(0, 1, '=INDIRECT("A1")'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 INDIRECT("A1") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=INDIRECT("A4")'); + FWorksheet.CalcFormulas; + CheckEquals('A1', FWorksheet.ReadAsText(0, 1), 'Formula #2 INDIRECT("A4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=INDIRECT(A4)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 INDIRECT(A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=INDIRECT("Sheet2!A1")'); + FWorksheet.CalcFormulas; + CheckEquals(1000, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 INDIRECT("Sheet2!A1") result mismatch'); + + // Constructing cell address from other cells + FWorksheet.WriteFormula(0, 1, '=INDIRECT(A6&A7)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 INDIRECT(A6&A7) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=INDIRECT(A10)'); // A10 = A6&A7 + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #6 INDIRECT(A10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=INDIRECT(A8&"!"&A6&A7)'); // --> "Sheet2!A1" + FWorksheet.CalcFormulas; + CheckEquals(1000, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 INDIRECT(A8&"!"&A6&A7) result mismatch'); + + // Constructing cell address from other cells and constant + FWorksheet.WriteFormula(0, 1, '=INDIRECT(A6&"1")'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 INDIRECT(A6&"1") result mismatch'); + + // Error in indirectly addressed cell + FWorksheet.WriteFormula(0, 1, '=INDIRECT(A5)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #9 INDIRECT(A5) result mismatch'); + + // Circular reference + FWorksheet.WriteFormula(0, 1, '=INDIRECT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #10 INDIRECT(A1) result mismatch'); + + + // *** Cell range references *** + + FWorksheet.WriteFormula(0, 1, '=SUM(INDIRECT("A1:A3"))'); + FWorksheet.CalcFormulas; + CheckEquals(60, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 SUM(INDIRECT("A1:A3")) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(INDIRECT("Sheet2!A1:A3"))'); + FWorksheet.CalcFormulas; + CheckEquals(6000, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 SUM(INDIRECT("Sheet2!A1:A3")) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(INDIRECT(A9))'); + FWorksheet.CalcFormulas; + CheckEquals(6000, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 SUM(INDIRECT(A9)) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(INDIRECT(A8&"!"&A4&":A3"))'); + FWorksheet.CalcFormulas; + CheckEquals(6000, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 SUM(INDIRECT(A8&"!"&A4&":A3")) result mismatch'); +end; + +procedure TCalcLookupFormulaTests.Test_MATCH; +begin + // *** Match_Type 0, unsorted data in search range, find first value + + // Search range to be checked: B1:B4 + FWorksheet.WriteNumber(0, 1, 10); + FWorksheet.WriteNumber(1, 1, 20); + FWorksheet.WriteNumber(2, 1, 30); + FWorksheet.WriteNumber(3, 1, 15); + FWorksheet.WriteNumber(4, 1, 20); + + // Search range in other sheet + FOtherWorksheet.WriteNumber(0, 1, 100); + FOtherWorksheet.WriteNumber(1, 1, 200); + FOtherWorksheet.WriteNumber(2, 1, 300); + FOtherWorksheet.WriteNumber(3, 1, 150); + FOtherWorksheet.WriteNumber(4, 1, 200); + + // Search for constant, contained in search range + FWorksheet.WriteFormula(0, 2, '=MATCH(10, B1:B5, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #1 MATCH(10,B1:B5,0) mismatch, value in range'); + + // dto., but in other sheet + FWorksheet.WriteFormula(0, 2, '=MATCH(100, Sheet2!B1:B5, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #2 MATCH(100,Sheet2!B1:B5,0) mismatch, value in range'); + + // Search for constant, contained several times in search range + FWorksheet.WriteFormula(0, 2, '=MATCH(20, B1:B5, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #3 MATCH(20,B1:B5,0) mismatch, value above range'); + + // dto., but in other sheet + FWorksheet.WriteFormula(0, 2, '=MATCH(200, Sheet2!B1:B5, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #4 MATCH(200,Sheet2!B1:B5,0) mismatch, value above range'); + + // Search for constant, below search range + FWorksheet.WriteFormula(0, 2, '=MATCH(0, B1:B5, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #5 MATCH(0,B1:B5,0) mismatch, value below range'); + + // dto., but in other sheet + FWorksheet.WriteFormula(0, 2, '=MATCH(0, Sheet2!B1:B5, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #6 MATCH(0,Sheet2!B1:B5,0) mismatch, value below range'); + + // Search for constant, above search range + FWorksheet.WriteFormula(0, 2, '=MATCH(90, B1:B5, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #7 MATCH(90,B1:B5,0) mismatch, value above range'); + + // dto., but in other sheet + FWorksheet.WriteFormula(0, 2, '=MATCH(900, Sheet2!B1:B5, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #8 MATCH(900,Sheet2!B1:B5,0) mismatch, value above range'); + + // Search for cell with value in range + FWorksheet.WriteNumber(0, 0, 20); + FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B5, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #9 MATCH(A1,B1:B5,0) mismatch, cell value in range'); + + // dto, but in other sheet + FWorksheet.WriteNumber(0, 0, 200); + FWorksheet.WriteFormula(0, 2, '=MATCH(A1, Sheet2!B1:B5, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #10 MATCH(A1,Sheet2!B1:B5,0) mismatch, cell value in range'); + + // Search for cell, but cell is empty + FWorksheet.WriteFormula(0, 2, '=MATCH(A99, B1:B5, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #11 MATCH(A99,B1:B5,0) mismatch, empty cell'); + + // dto., but in other sheet + FWorksheet.WriteFormula(0, 2, '=MATCH(A99, Sheet2!B1:B5, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #12 MATCH(A99,Sheet2!B1:B5,0) mismatch, empty cell'); + + // Search range is empty + FWorksheet.WriteFormula(0, 2, '=MATCH(28, D1:D3, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #13 MATCH mismatch, match_type -1, empty search range'); + + // dto., but in other sheet + FWorksheet.WriteFormula(0, 2, '=MATCH(28, Sheet2!D1:D3, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #14 MATCH mismatch, match_type -1, empty search range'); + + // *** Match_Type 1 (find largest value in range <= value), ascending values in search range + + // Search range to be checked: B1:B3 + FWorksheet.WriteNumber(0, 1, 10); + FWorksheet.WriteNumber(1, 1, 20); + FWorksheet.WriteNumber(2, 1, 30); + FWorksheet.WriteBlank(3, 1); + + // Search for constant, contained in search range + FWorksheet.WriteFormula(0, 2, '=MATCH(28, B1:B3, 1)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #8 MATCH mismatch, match_type 1, in range'); + + // Search for constant, below search range + FWorksheet.WriteFormula(0, 2, '=MATCH(8, B1:B3, 1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #9 MATCH mismatch, match_type 1, below range'); + + // Search for constant, above search range + FWorksheet.WriteFormula(0, 2, '=MATCH(123, B1:B3, 1)'); + FWorksheet.CalcFormulas; + CheckEquals(3, FWorksheet.ReadAsNumber(0, 2), 'Formula MATCH #10 mismatch, match_type 1, above range'); + + // Search for cell with value in range + FWorksheet.WriteNumber(0, 0, 28); + FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B3, 1)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula MATCH #11 mismatch, match_type 1, cell in range'); + FWorksheet.WriteBlank(0, 0); + + // Search for cell, but cell is empty + FWorksheet.WriteBlank(0, 0); + FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B3, 1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #12 MATCH mismatch, match_type 1, empty cell'); + + // Search range is empty + FWorksheet.WriteFormula(0, 2, '=MATCH(28, D1:D3, -1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula MATCH #13 mismatch, match_type -1, empty search range'); + + + // *** Match_Type -1 (find smallest value in range >= value), descending values in search range + + // Search range to be checked: B1:B3 + FWorksheet.WriteNumber(0, 1, 30); + FWorksheet.WriteNumber(1, 1, 20); + FWorksheet.WriteNumber(2, 1, 10); + + // Search for constant, contained in search range + FWorksheet.WriteFormula(0, 2, '=MATCH(28, B1:B3, -1)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #14 MATCH mismatch, match_type -1, in range'); + + // Search for constant, below search range + FWorksheet.WriteFormula(0, 2, '=MATCH(8, B1:B3, -1)'); + FWorksheet.CalcFormulas; + CheckEquals(3, FWorksheet.ReadAsNumber(0, 2), 'Formula #15 MATCH mismatch, match_type -1, below range'); + + // Search for constant, above search range + FWorksheet.WriteFormula(0, 2, '=MATCH(123, B1:B3, -1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #16 MATCH mismatch, match_type -1, above range'); + + // Search for cell with value in range + FWorksheet.WriteNumber(0, 0, 28); + FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B3, -1)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #17 MATCH mismatch, match_type -1, cell in range'); + FWorksheet.WriteBlank(0, 0); + + // Search for cell, but cell is empty + FWorksheet.WriteBlank(0, 0); + FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B3, -1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #18 MATCH mismatch, match_type -1, empty cell'); + + // Search range is empty + FWorksheet.WriteFormula(0, 2, '=MATCH(28, D1:D3, -1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #19 MATCH mismatch, match_type -1, empty search range'); + + + // **** Error propagation + + // Search for cell, but cell contains error + FWorksheet.WriteFormula(0, 0, '=1/0'); + FWorksheet.WriteNumber(1, 1, 20); + FWorksheet.WriteNumber(2, 1, 30); + FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B4, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #20 MATCH mismatch, match_type 0, error cell'); + + // Match_type parameter contains error + FWorksheet.WriteNumber(0, 1, 10); + FWorksheet.WriteFormula(0, 5, '=1/0'); // F1 + FWorksheet.WriteFormula(0, 2, '=MATCH(A1, B1:B3, F1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #21 MATCH mismatch, match_type 0, error in search range'); + + // Cell range contains error + FWorksheet.WriteNumber(0, 1, 10); + FWorksheet.WriteFormula(1, 1, '=1/0'); // B2 contains a #DIV/0! error now + FWorksheet.WriteNumber(2, 1, 30); + // Search for constant, contained in search range + FWorksheet.WriteFormula(0, 2, '=MATCH(20, B1:B3, 0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #22 MATCH mismatch, match_type 0, error in search range'); + // ArgError because search value is not found + + + // **** Partial text + + FWorksheet.WriteText(0, 0, 'abc'); + FWorksheet.WriteText(1, 0, 'axy'); + FWorksheet.WriteText(2, 0, 'xxy'); + FWorksheet.WriteText(3, 0, 'ayc'); + FWorksheet.WriteText(4, 0, 'äbc'); + + FWorksheet.WriteFormula(0, 2, '=MATCH("a*",A1:A4,0)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #23 MATCH mismatch, partial text "a*"'); + + FWorksheet.WriteFormula(0, 2, '=MATCH("z*",A1:A4,0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #24 MATCH mismatch, partial text "z*"'); + + FWorksheet.WriteFormula(0, 2, '=MATCH("*y",A1:A4,0)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 2), 'Formula #25 MATCH mismatch, partial text "*y"'); + + FWorksheet.WriteFormula(0, 2, '=MATCH("*z",A1:A4,0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #26 MATCH mismatch, partial text "*z"'); + + FWorksheet.WriteFormula(0, 2, '=MATCH("*z*",A1:A4,0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #27 MATCH mismatch, partial text "*z*"'); + + FWorksheet.WriteFormula(0, 2, '=MATCH("ay?",A1:A4,0)'); + FWorksheet.CalcFormulas; + CheckEquals(4, FWorksheet.ReadAsNumber(0, 2), 'Formula #28 MATCH mismatch, partial text "ay?'); + + FWorksheet.WriteFormula(0, 2, '=MATCH("a?",A1:A4,0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ARG_ERROR, FWorksheet.ReadAsText(0, 2), 'Formula #29 MATCH mismatch, partial text "a?'); + + FWorksheet.WriteFormula(0, 2, '=MATCH("Ä*",A1:A5,0)'); + FWorksheet.CalcFormulas; + CheckEquals(5, FWorksheet.ReadAsNumber(0, 2), 'Formula #30 MATCH mismatch, partial text "Ä*'); +end; + +procedure TCalcLookupFormulaTests.Test_ROW; +begin + // Get row of specified cell + FWorksheet.WriteFormula(0, 1, '=ROW(B2)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 ROW(B2) result mismatch'); + + // Get row of the formula cell --- NOT CORRECTLY IMPLEMENTED IN FPS + FWorksheet.WriteFormula(0, 1, '=ROW()'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 ROW() result mismatch'); // This would be the Excel result! + //CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #2 ROW() result mismatch'); + + // Error value as argument + FWorksheet.WriteFormula(0, 1, '=ROW(#REF!)'); + FWorksheet.CalcFormulas; + //CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 ROW() result mismatch'); + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #3 ROW(#REF!) result mismatch'); + + // Cell containing an error as argument + FWorksheet.WriteFormula(1, 1, '=1/0'); + FWorksheet.WriteFormula(0, 1, '=ROW(B2)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 ROW(B2) (B2 contains error) result mismatch'); +end; + diff --git a/components/fpspreadsheet/unit-tests/common/testcases_calcmathformulas.inc b/components/fpspreadsheet/unit-tests/common/testcases_calcmathformulas.inc new file mode 100644 index 000000000..fbe7b5da4 --- /dev/null +++ b/components/fpspreadsheet/unit-tests/common/testcases_calcmathformulas.inc @@ -0,0 +1,782 @@ +{ included by CalcFormulaTests.pas } + +procedure TCalcMathFormulaTests.Test_ABS; +begin + // Positive value + FWorksheet.WriteNumber(0, 0, +10); + FWorksheet.WriteFormula(0, 1, 'ABS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula ABS(10) result mismatch'); + + // Negative value + FWorksheet.WriteNumber(0, 0, -10); + FWorksheet.WriteFormula(0, 1, 'ABS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula ABS(-10) result mismatch'); + + // Error propagation + FWorksheet.WriteErrorValue(0, 0, errIllegalRef); + FWorksheet.WriteFormula(0, 1, 'ABS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula ABS(1/0) result mismatch'); + + // Empty argument + FWorksheet.WriteBlank(0, 0); + FWorksheet.WriteFormula(0, 1, 'ABS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula ABS([blank_cell]) result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_ACOS; +begin + FWorksheet.WriteFormula(0, 1, '=ACOS(0.5)'); + FWorksheet.CalcFormulas; + CheckEquals(pi/3, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #1 ACOS(0.5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ACOS(0)'); + FWorksheet.CalcFormulas; + CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #2 ACOS(0) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ACOS(1)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #3 ACOS(1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ACOS(-1)'); + FWorksheet.CalcFormulas; + CheckEquals(pi, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #4 ACOS(-1) result mismatch'); + + // Out-of-domain + FWorksheet.WriteFormula(0, 1, '=ACOS(2)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #5 ACOS(2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ACOS(-2)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #6 ACOS(-2) result mismatch'); + + // Boolean argument + FWorksheet.WriteFormula(0, 1, '=ACOS(FALSE)'); + FWorksheet.CalcFormulas; + CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #7 ACOS(FALSE) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ACOS(TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #8 ACOS(TRUE) result mismatch'); + + // Numeric string + FWorksheet.WriteFormula(0, 1, '=ACOS("1")'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #9 ACOS("1") result mismatch'); + + // Non-numeric string + FWorksheet.WriteFormula(0, 1, '=ACOS("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #10 ACOS("abc") result mismatch'); + + // Error argument + FWorksheet.WriteFormula(0, 1, '=ACOS(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #11 ACOS(1/0) result mismatch'); + + // Cell with boolean value + FWorksheet.WriteFormula(0, 0, '=(1=1)'); + FWorksheet.WriteFormula(0, 1, '=ACOS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #12 ACOS(A1) (A1: (1=1)) result mismatch'); + + // Cell with numeric string + FWorksheet.WriteText(0, 0, '1'); + FWorksheet.WriteFormula(0, 1, '=ACOS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #13 ACOS(A1) (A1: "1") result mismatch'); + + // Cell with non-numeric string + FWorksheet.WriteText(0, 0, 'abc'); + FWorksheet.WriteFormula(0, 1, '=ACOS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #14 ACOS(A1) (A1: "abc") result mismatch'); + + // Empty cell + FWorksheet.WriteBlank(0, 0); // Empty A1 + FWorksheet.WriteFormula(0, 1, '=ACOS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 'Formula #15 ACOS(A1) (A1: empty) result mismatch'); + + // Cell with error + FWorksheet.WriteErrorValue(0, 0, errIllegalRef); + FWorksheet.WriteFormula(0, 1, '=ACOS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #16 ACOS(A1) (A1: #REF!) result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_ASIN; +begin + FWorksheet.WriteFormula(0, 1, '=ASIN(0.5)'); + FWorksheet.CalcFormulas; + CheckEquals(pi/6, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #1 ASIN(0.5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ASIN(0)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #2 ASIN(0) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ASIN(1)'); + FWorksheet.CalcFormulas; + CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #3 ASIN(1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ASIN(-1)'); + FWorksheet.CalcFormulas; + CheckEquals(-pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #4 ASIN(-1) result mismatch'); + + // Out-of-domain + FWorksheet.WriteFormula(0, 1, '=ASIN(2)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #5 ASIN(2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ASIN(-2)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #6 ASIN(-2) result mismatch'); + + // Boolean argument + FWorksheet.WriteFormula(0, 1, '=ASIN(FALSE)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #7 ASIN(FALSE) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ASIN(TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #8 ASIN(TRUE) result mismatch'); + + // Numeric string + FWorksheet.WriteFormula(0, 1, '=ASIN("1")'); + FWorksheet.CalcFormulas; + CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #9 ASIN("1") result mismatch'); + + // Non-numeric string + FWorksheet.WriteFormula(0, 1, '=ASIN("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #10 ASIN("abc") result mismatch'); + + // Error argument + FWorksheet.WriteFormula(0, 1, '=ASIN(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #11 ASIN(1/0) result mismatch'); + + // Cell with boolean value + FWorksheet.WriteFormula(0, 0, '=(1=1)'); + FWorksheet.WriteFormula(0, 1, '=ASIN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #12 ASIN(A1) (A1: (1=1)) result mismatch'); + + // Cell with numeric string + FWorksheet.WriteText(0, 0, '1'); + FWorksheet.WriteFormula(0, 1, '=ASIN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #13 ASIN(A1) (A1: "1") result mismatch'); + + // Cell with non-numeric string + FWorksheet.WriteText(0, 0, 'abc'); + FWorksheet.WriteFormula(0, 1, '=ASIN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #14 ASIN(A1) (A1: "abc") result mismatch'); + + // Empty cell + FWorksheet.WriteBlank(0, 0); // Empty A1 + FWorksheet.WriteFormula(0, 1, '=ASIN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #15 ASIN(A1) (A1: empty) result mismatch'); + + // Cell with error + FWorksheet.WriteErrorValue(0, 0, errIllegalRef); + FWorksheet.WriteFormula(0, 1, '=ASIN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #16 ASIN(A1) (A1: #REF!) result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_ATAN; +begin + FWorksheet.WriteFormula(0, 1, '=ATAN(0)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #1 ATAN(0) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ATAN(1)'); + FWorksheet.CalcFormulas; + // Soll result from Wolfram Alpha + CheckEquals(0.78539816339744830961566084, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #2 ATAN(1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ATAN(-1)'); + FWorksheet.CalcFormulas; + // Soll result from Wolfram Alpha + CheckEquals(-0.78539816339744830961566084, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #3 ATAN(-1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ATAN(1E300)'); + FWorksheet.CalcFormulas; + CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #4 ATAN(1E300) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ATAN(-1E300)'); + FWorksheet.CalcFormulas; + CheckEquals(-pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #5 ATAN(-1E300) result mismatch'); + + // Boolean argument + FWorksheet.WriteFormula(0, 1, '=ATAN(FALSE)'); + FWorksheet.CalcFormulas; + CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #6 ATAN(FALSE) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ATAN(TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(0.78539816339744830961566084, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #7 ATAN(TRUE) result mismatch'); + + // Numeric string + FWorksheet.WriteFormula(0, 1, '=ATAN("1")'); + FWorksheet.CalcFormulas; + CheckEquals(0.78539816339744830961566084, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #8 ATAN("1") result mismatch'); + + // Non-numeric string + FWorksheet.WriteFormula(0, 1, '=ATAN("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #9 ATAN("abc") result mismatch'); + + // Error argument + FWorksheet.WriteFormula(0, 1, '=ATAN(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #10 ATAN(1/0) result mismatch'); + + // Cell with boolean value + FWorksheet.WriteFormula(0, 0, '=(1=1)'); + FWorksheet.WriteFormula(0, 1, '=ATAN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0.78539816339744830961566084, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #11 ATAN(A1) (A1: (1=1)) result mismatch'); + + // Cell with numeric string + FWorksheet.WriteText(0, 0, '1'); + FWorksheet.WriteFormula(0, 1, '=ATAN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0.78539816339744830961566084, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #12 ATAN(A1) (A1: "1") result mismatch'); + + // Cell with non-numeric string + FWorksheet.WriteText(0, 0, 'abc'); + FWorksheet.WriteFormula(0, 1, '=ATAN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #13 ATAN(A1) (A1: "abc") result mismatch'); + + // Empty cell + FWorksheet.WriteBlank(0, 0); // Empty A1 + FWorksheet.WriteFormula(0, 1, '=ATAN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 ATAN(A1) (A1: empty) result mismatch'); + + // Cell with error + FWorksheet.WriteErrorValue(0, 0, errIllegalRef); + FWorksheet.WriteFormula(0, 1, '=ATAN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #15 ATAN(A1) (A1: #REF!) result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_CEILING; +begin + // Examples from https://exceljet.net/functions/ceiling-function + FWorksheet.WriteFormula(0, 1, '=CEILING(10,3)'); + FWorksheet.CalcFormulas; + CheckEquals(12, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 CEILING(10,3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=CEILING(36,7)'); + FWorksheet.CalcFormulas; + CheckEquals(42, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 CEILING(36,7) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=CEILING(610,100)'); + FWorksheet.CalcFormulas; + CheckEquals(700, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 CEILING(610,100) result mismatch'); + + // Negative arguments + FWorksheet.WriteFormula(0, 1, '=CEILING(-5.4,-1)'); + FWorksheet.CalcFormulas; + CheckEquals(-5, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 CEILING(-5.4,-1) result mismatch'); + + // Zero significance + FWorksheet.WriteFormula(0, 1, '=CEILING(-5.4,0)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 CEILING(-5.4,0) result mismatch'); + + // Different signs of the arguments + FWorksheet.WriteFormula(0, 1, '=CEILING(-5.4,1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #6 CEILING(-5.4,1) result mismatch'); + + // Arguments as string + FWorksheet.WriteFormula(0, 1, '=CEILING("A",1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 CEILING("A",1) result mismatch'); + FWorksheet.WriteFormula(0, 1, '=CEILING(5.4,"A")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #8 CEILING(5.4,"A") result mismatch'); + + // Arguments as boolean + FWorksheet.WriteFormula(0, 1, '=CEILING(TRUE(),1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #9 CEILING(TRUE(),1) result mismatch'); + FWorksheet.WriteFormula(0, 1, '=CEILING(5.4, TRUE())'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #10 CEILING(5.4, TRUE()) result mismatch'); + + // Arguments with errors + FWorksheet.WriteFormula(0, 1, '=CEILING(1/0,1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #11 CEILING(1/0, 1) result mismatch'); + FWorksheet.WriteFormula(0, 1, '=CEILING(5.4, 1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #12 CEILING(5.4, 1/0) result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_EVEN; +begin + FWorksheet.WriteFormula(0, 1, '=EVEN(1.23)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 EVEN(1.23) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=EVEN(2.34)'); + FWorksheet.CalcFormulas; + CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 EVEN(2.34) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=EVEN(-1.23)'); + FWorksheet.CalcFormulas; + CheckEquals(-2, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 EVEN(-1.23) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=EVEN(-2.34)'); + FWorksheet.CalcFormulas; + CheckEquals(-4, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 EVEN(-2.34) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=EVEN(0.0)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 EVEN(0.0) result mismatch'); + + // String as argument + FWorksheet.WriteFormula(0, 1, '=EVEN("1")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 EVEN("1") result mismatch'); + + // Empty argument + FWorksheet.WriteFormula(0, 1, '=EVEN()'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 EVEND() result mismatch'); + + // Error in argument + FWorksheet.WriteFormula(0, 1, '=EVEN(#REF!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #8 EVEN(#REF!) result mismatch'); + + // Error in argument cell + FWorksheet.WriteErrorValue(0, 0, errIllegalRef); + FWorksheet.WriteFormula(0, 1, '=EVEN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #9 EVEN(A1) result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_FLOOR; +begin + FWorksheet.WriteFormula(0, 1, '=FLOOR(10,3)'); + FWorksheet.CalcFormulas; + CheckEquals(9, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 FLOOR(10,3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=FLOOR(36,7)'); + FWorksheet.CalcFormulas; + CheckEquals(35, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 FLOOR(36,7) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=FLOOR(610,100)'); + FWorksheet.CalcFormulas; + CheckEquals(600, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 FLOOR(610,100) result mismatch'); + + // Negative value, negative significance + FWorksheet.WriteFormula(0, 1, '=FLOOR(-5.4,-2)'); + FWorksheet.CalcFormulas; + CheckEquals(-4, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 FLOOR(-5.4,-2) result mismatch'); + + // Negative value, positive significance + FWorksheet.WriteFormula(0, 1, '=FLOOR(-5.4,2)'); + FWorksheet.CalcFormulas; + CheckEquals(-6, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 FLOOR(-5.4,2) result mismatch'); + + // Positive value, negative significance + FWorksheet.WriteFormula(0, 1, '=FLOOR(5.4,-2)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #6 FLOOR(5.4,-2) result mismatch'); + + // Zero significance + FWorksheet.WriteFormula(0, 1, '=FLOOR(-5.4,0)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 FLOOR(-5.4,0) result mismatch'); + + // Arguments as string + FWorksheet.WriteFormula(0, 1, '=FLOOR("A",1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #8 FLOOR("A",1) result mismatch'); + FWorksheet.WriteFormula(0, 1, '=FLOOR(5.4,"A")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #9 FLOOR(5.4,"A") result mismatch'); + + // Arguments as boolean + FWorksheet.WriteFormula(0, 1, '=FLOOR(TRUE(),1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #10 FLOOR(TRUE(),1) result mismatch'); + FWorksheet.WriteFormula(0, 1, '=FLOOR(5.4, TRUE())'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #11 FLOOR(5.4, TRUE()) result mismatch'); + + // Arguments with errors + FWorksheet.WriteFormula(0, 1, '=FLOOR(1/0,1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #12 FLOOR(1/0, 1) result mismatch'); + FWorksheet.WriteFormula(0, 1, '=FLOOR(5.4, 1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #13 FLOOR(5.4, 1/0) result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_LOG; +begin + // Correct formula + FWorksheet.WriteFormula(0, 1, '=LOG(10)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 LOG(10) result mismatch'); + + // Argument is zero + FWorksheet.WriteFormula(0, 1, '=LOG(0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #2 LOG(0) result mismatch'); + + // Negative argument + FWorksheet.WriteFormula(0, 1, '=LOG(-10)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #3 LOG(-10) result mismatch'); + + // Non-numeric argument + FWorksheet.WriteFormula(0, 1, '=LOG("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #4 LOG("abc") result mismatch'); + + // Error argument + FWorksheet.WriteFormula(0, 1, '=LOG(#REF!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #5 LOG(#REF!) result mismatch'); + + // Two argument cases + + // Correct formula + FWorksheet.WriteFormula(0, 1, '=LOG(8,2)'); + FWorksheet.CalcFormulas; + CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #6 LOG(8, 2) result mismatch'); + + // 2nd argument negative + FWorksheet.WriteFormula(0, 1, '=LOG(8,-2)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #7 LOG(8,-2) result mismatch'); + + // Non-numeric 2nd argument + FWorksheet.WriteFormula(0, 1, '=LOG(8,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #8 LOG(8,"abc") result mismatch'); + + // Missing 1st argument + FWorksheet.WriteFormula(0, 1, '=LOG(,2)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #9 LOG(,2) result mismatch'); + + // Missing 2nd argument + FWorksheet.WriteFormula(0, 1, '=LOG(10,)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #10 LOG(10,) result mismatch'); + + // Error in 2nd argument + FWorksheet.WriteFormula(0, 1, '=LOG(8,#REF!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #11 LOG(8,#REF!) result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_LOG10; +begin + // Correct formula + FWorksheet.WriteFormula(0, 1, '=LOG10(10)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 LOG10(10) result mismatch'); + + // Argument is zero + FWorksheet.WriteFormula(0, 1, '=LOG10(0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #2 LOG10(0) result mismatch'); + + // Negative argument + FWorksheet.WriteFormula(0, 1, '=LOG10(-10)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #3 LOG10(-10) result mismatch'); + + // Non-numeric argument + FWorksheet.WriteFormula(0, 1, '=LOG10("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #4 LOG10("abc") result mismatch'); + + // Error argument + FWorksheet.WriteFormula(0, 1, '=LOG10(#REF!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #5 LOG10(#REF!) result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_ODD; +begin + FWorksheet.WriteFormula(0, 1, '=ODD(0.5)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 ODD(0.5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ODD(1.5)'); + FWorksheet.CalcFormulas; + CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 ODD(1.5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ODD(-0.5)'); + FWorksheet.CalcFormulas; + CheckEquals(-1, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 ODD(-0.5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=ODD(0.0)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 ODD(0.0) result mismatch'); + + // String as argument + FWorksheet.WriteFormula(0, 1, '=ODD("1")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 ODD("1") result mismatch'); + + // Empty as argument + FWorksheet.WriteFormula(0, 1, '=ODD()'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 ODD() result mismatch'); + + // Error in argument + FWorksheet.WriteFormula(0, 1, '=ODD(#REF!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #7 ODD(#REF!) result mismatch'); + + // Error in argument cell + FWorksheet.WriteErrorValue(0, 0, errIllegalRef); + FWorksheet.WriteFormula(0, 1, '=ODD(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #8 ODD(A1) result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_POWER; +begin + FWorksheet.WriteFormula(0, 1, '=POWER(3,2)'); + FWorksheet.CalcFormulas; + CheckEquals(9, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 POWER(3,2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=POWER(2,-3)'); + FWorksheet.CalcFormulas; + CheckEquals(1/8, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 POWER(2,-3) result mismatch'); + + // x^0 + FWorksheet.WriteFormula(0, 1, '=POWER(2,0)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 POWER(2,0) result mismatch'); + + // 0^x + FWorksheet.WriteFormula(0, 1, '=POWER(0,2)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 POWER(0,2) result mismatch'); + + // 0^0 + FWorksheet.WriteFormula(0, 1, '=POWER(0,0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #5 POWER(0,0) result mismatch'); + + // Boolean argument + FWorksheet.WriteFormula(0, 1, '=POWER(TRUE,"2")'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #6 POWER(TRUE,"2") result mismatch'); + + // Numeric string arguments + FWorksheet.WriteFormula(0, 1, '=POWER("3",2)'); + FWorksheet.CalcFormulas; + CheckEquals(9, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 POWER("3",2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=POWER(3,"2")'); + FWorksheet.CalcFormulas; + CheckEquals(9, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 POWER(3,"2") result mismatch'); + + // Non-numeric string arguments + FWorksheet.WriteFormula(0, 1, '=POWER("abc",2)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #9 POWER("abc",2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=POWER(3,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #10 POWER(3,"abc") result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_RADIANS; +begin + FWorksheet.WriteFormula(0, 1, '=RADIANS(90)'); + FWorksheet.CalcFormulas; + CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #1 RADIANS(90) result mismatch'); + + // Boolean argument + FWorksheet.WriteFormula(0, 1, '=RADIANS(TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(pi*1/180, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #2 RADIANS(TRUE) result mismatch'); + + // Numeric string + FWorksheet.WriteFormula(0, 1, '=RADIANS("90")'); + FWorksheet.CalcFormulas; + CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #3 RADIANS("90") result mismatch'); + + // Non-numeric string + FWorksheet.WriteFormula(0, 1, '=RADIANS("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #4 RADIANS("abc") result mismatch'); + + // Error argument + FWorksheet.WriteFormula(0, 1, '=RADIANS(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #5 RADIANS(1/0) result mismatch'); + + // Cell with boolean value + FWorksheet.WriteFormula(0, 0, '=(1=1)'); + FWorksheet.WriteFormula(0, 1, '=RADIANS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(pi*1/180, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #6 RADIANS(A1) (A1: (1=1)) result mismatch'); + + // Cell with numeric string + FWorksheet.WriteText(0, 0, '90'); + FWorksheet.WriteFormula(0, 1, '=RADIANS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(pi/2, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #7 RADIANS(A1) (A1: "90") result mismatch'); + + // Cell with non-numeric string + FWorksheet.WriteText(0, 0, 'abc'); + FWorksheet.WriteFormula(0, 1, '=RADIANS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #8 RADIANS(A1) (A1: "abc") result mismatch'); + + // Empty cell + FWorksheet.WriteBlank(0, 0); // Empty A1 + FWorksheet.WriteFormula(0, 1, '=RADIANS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 RADIANS(A1) (A1: empty) result mismatch'); + + // Cell with error + FWorksheet.WriteErrorValue(0, 0, errIllegalRef); + FWorksheet.WriteFormula(0, 1, '=RADIANS(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #10 RADIANS(A1) (A1: #REF!) result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_ROUND; +begin + // Round positive value. + FWorksheet.WriteFormula(0, 1, '=ROUND(123.432, 1)'); + FWorksheet.CalcFormulas; + CheckEquals(123.4, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #1 ROUND(123.432,1) result mismatch'); + + // Round positive value. Check that Banker's rounding is not applied + FWorksheet.WriteFormula(0, 1, '=ROUND(123.456, 2)'); + FWorksheet.CalcFormulas; + CheckEquals(123.46, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #2 ROUND(123.3456,2) result mismatch'); + + // Round negative value. + FWorksheet.WriteFormula(0, 1, '=ROUND(-123.432, 1)'); + FWorksheet.CalcFormulas; + CheckEquals(-123.4, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #3 ROUND(-123.432,1) result mismatch'); + + // Round negative value. Check that Banker's rounding is not applied + FWorksheet.WriteFormula(0, 1, '=ROUND(-123.456, 2)'); + FWorksheet.CalcFormulas; + CheckEquals(-123.46, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #4 ROUND(-123.456,2) result mismatch'); + + // Negative number of decimals for positive value + FWorksheet.WriteFormula(0, 1, '=ROUND(123.456, -2)'); + FWorksheet.CalcFormulas; + CheckEquals(100, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 ROUND(123.3456,-2) result mismatch'); + + // Negative number of decimals for negative value + FWorksheet.WriteFormula(0, 1, '=ROUND(-123.456, -2)'); + FWorksheet.CalcFormulas; + CheckEquals(-100, FWorksheet.ReadAsNumber(0, 1), 'Formula #6 ROUND(123.3456,-2) result mismatch'); + + // Error in 1st argument + FWorksheet.WriteFormula(0, 1, '=Round(1/0, 2)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #7 ROUND(1/0,2) result mismatch'); + + // Error in 2nd argument + FWorksheet.WriteFormula(0, 1, '=Round(123.456, 1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 ROUND(123.456, 1/0) result mismatch'); +end; + +procedure TCalcMathFormulaTests.Test_SQRT; +begin + FWorksheet.WriteFormula(0, 1, '=SQRT(0.0)'); + FWorksheet.CalcFormulas; + CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #1 SQRT(0.0) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SQRT(1.0)'); + FWorksheet.CalcFormulas; + CheckEquals(1.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #2 SQRT(1.0) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SQRT(16.0)'); + FWorksheet.CalcFormulas; + CheckEquals(4.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #3 SQRT(16.0) result mismatch'); + + // Out-of-domain + FWorksheet.WriteFormula(0, 1, '=SQRT(-1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_OVERFLOW, FWorksheet.ReadAsText(0, 1), 'Formula #4 SQRT(-1) result mismatch'); + + // Boolean argument + FWorksheet.WriteFormula(0, 1, '=SQRT(FALSE)'); + FWorksheet.CalcFormulas; + CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #5 SQRT(FALSE) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SQRT(TRUE)'); + FWorksheet.CalcFormulas; + CheckEquals(1.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #6 SQRTS(TRUE) result mismatch'); + + // Numeric string + FWorksheet.WriteFormula(0, 1, '=SQRT("1")'); + FWorksheet.CalcFormulas; + CheckEquals(1.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #7 SQRT("1") result mismatch'); + + // Non-numeric string + FWorksheet.WriteFormula(0, 1, '=SQRT("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #8 SQRT("abc") result mismatch'); + + // Error argument + FWorksheet.WriteFormula(0, 1, '=SQRT(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #9 SQRT(1/0) result mismatch'); + + // Cell with boolean value + FWorksheet.WriteFormula(0, 0, '=(1=1)'); + FWorksheet.WriteFormula(0, 1, '=SQRT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(1.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #10 SQRT(A1) (A1: (1=1)) result mismatch'); + + // Cell with numeric string + FWorksheet.WriteText(0, 0, '1'); + FWorksheet.WriteFormula(0, 1, '=SQRT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(1.0, FWorksheet.ReadAsNumber(0, 1), 1e-8, 'Formula #11 SQRTS(A1) (A1: "1") result mismatch'); + + // Cell with non-numeric string + FWorksheet.WriteText(0, 0, 'abc'); + FWorksheet.WriteFormula(0, 1, '=SQRT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #12 SQRT(A1) (A1: "abc") result mismatch'); + + // Empty cell + FWorksheet.WriteBlank(0, 0); // Empty A1 + FWorksheet.WriteFormula(0, 1, '=SQRT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 SQRT(A1) (A1: empty) result mismatch'); + + // Cell with error + FWorksheet.WriteErrorValue(0, 0, errIllegalRef); + FWorksheet.WriteFormula(0, 1, '=SQRT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #14 SQRT(A1) (A1: #REF!) result mismatch'); +end; + + diff --git a/components/fpspreadsheet/unit-tests/common/testcases_calcstatsformulas.inc b/components/fpspreadsheet/unit-tests/common/testcases_calcstatsformulas.inc new file mode 100644 index 000000000..8faad7b06 --- /dev/null +++ b/components/fpspreadsheet/unit-tests/common/testcases_calcstatsformulas.inc @@ -0,0 +1,1487 @@ +{ included by CalcFormulaTests.pas } + +procedure TCalcStatsFormulaTests.Test_AVEDEV; +const + EPS = 1E-8; +begin + // Test data + FWorksheet.WriteNumber (0, 0, 1); + FWorksheet.WriteNumber (1, 0, -2); + FWorksheet.WriteNumber (2, 0, -3); + FWorksheet.WriteText (3, 0, '4'); + FWorksheet.WriteText (4, 0, 'abc'); + FWorksheet.WriteFormula(5, 0, '=1/0'); + + // Literal values + FWorksheet.WriteFormula(0, 1, '=AVEDEV(1)'); + FWorksheet.CalcFormulas; + CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 AVEDEV(1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV(1,-2)'); + FWorksheet.CalcFormulas; + CheckEquals(1.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #2 AVEDEV(1,-2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV("4")'); // although string considered to be numeric + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 AVEDEV("4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV(1,-2,-3,"4")'); + FWorksheet.CalcFormulas; + CheckEquals(2.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #4 AVEDEV(1,2,3,"4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 AVEDEV("abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV("")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 AVEDEV("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV(1,-2,-3,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 AVEDEV(1,-2,-3,"abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 AVEDEV(1/0) result mismatch'); + + // Cell references + FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 AVEDEV(A1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV(A10)'); // empty cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #8 AVEDEV(A10)(A10=empty) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals(1.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #9 AVEDEV(A1,A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1:A3)'); // "real" numeric values + FWorksheet.CalcFormulas; + CheckEquals(1.555555556, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #10 AVEDEV(A1:A3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1,A2:A3)'); // several ranges + FWorksheet.CalcFormulas; + CheckEquals(1.555555556, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #11 AVEDEV(A1,A2:A3) result mismatch'); + + // Cell references pointing to string cells + FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1:A4)'); // real and string numeric values + FWorksheet.CalcFormulas; + CheckEquals(2.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #12 AVEDEV(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1:A5)'); // real and string values --> ignore string + FWorksheet.CalcFormulas; + CheckEquals(2.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #13 AVEDEV(A1:A5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1:A4,A8:A10)'); // real and string values and blanks + FWorksheet.CalcFormulas; + CheckEquals(2.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #14 AVEDEV(A1:A4,A8:A10) result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1, 1/0, A2)'); // error in argument + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 AVEDEV(A1, 1/0, A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVEDEV(A1:A6)'); // error in cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 AVEDEV(A1:A6) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.Test_AVERAGE; +begin + // Test data + FWorksheet.WriteNumber (0, 0, 10); + FWorksheet.WriteNumber (1, 0, 20); + FWorksheet.WriteNumber (2, 0, 30); + FWorksheet.WriteText (3, 0, '40'); + FWorksheet.WriteText (4, 0, 'abc'); + FWorksheet.WriteFormula(5, 0, '=1/0'); + + // Literal values + FWorksheet.WriteFormula(0, 1, '=AVERAGE(10)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 AVERAGE(10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE(10,20)'); + FWorksheet.CalcFormulas; + CheckEquals(15, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 AVERAGE(10,20) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE("40")'); // although string considered to be numeric + FWorksheet.CalcFormulas; + CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 AVERAGE("40") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE(10,20,30,"40")'); + FWorksheet.CalcFormulas; + CheckEquals(25, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 AVERAGE(10,20,30,"40") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 AVERAGE("abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE("")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 AVERAGE("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE(10,20,30,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 AVERAGE(10,20,30,"abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 AVERAGE(1/0) result mismatch'); + + // Cell references + FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 AVERAGE(A1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE(A10)'); // empty cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 AVERAGE(A10)(A10=empty) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals(15, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 AVERAGE(A1,A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1:A3)'); // "real" numeric values + FWorksheet.CalcFormulas; + CheckEquals(20, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 AVERAGE(A1:A3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1,A2:A3)'); // several ranges + FWorksheet.CalcFormulas; + CheckEquals(20, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 AVERAGE(A1,A2:A3) result mismatch'); + + // Cell references pointing to string cells + FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1:A4)'); // real and string numeric values + FWorksheet.CalcFormulas; + CheckEquals(25, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 AVERAGE(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1:A5)'); // real and string values --> ignore string + FWorksheet.CalcFormulas; + CheckEquals(25, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 AVERAGE(A1:A5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1:A4,A8:A10)'); // real and string values and blanks + FWorksheet.CalcFormulas; + CheckEquals(25, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 AVERAGE(A1:A4,A8:A10) result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1, 1/0, A2)'); // error in argument + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 AVERAGE(A1, 1/0, A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=AVERAGE(A1:A6)'); // error in cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 AVERAGE(A:A6) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.Test_AVERAGEIF; +const + EPS = 1E-8; +begin + // Test data, value range A1:B9 + // A1:A9 - compare values // B1:B9 -- calculation values + FWorksheet.WriteText(0, 0, 'Abc'); FWorksheet.WriteNumber (0, 1, 100); + FWorksheet.WriteText(1, 0, 'Abc'); FWorksheet.WriteNumber (1, 1, 200); + FWorksheet.WriteText(2, 0, 'bc'); FWorksheet.WriteNumber (2, 1, 300); + FWorksheet.WriteText(3, 0, 'a'); FWorksheet.WriteNumber (3, 1, 400); + FWorksheet.WriteText(4, 0, 'bc'); FWorksheet.WriteText (4, 1, '500'); + FWorksheet.WriteText(5, 0, 'abc'); FWorksheet.WriteText (5, 1, 'no number'); + FWorksheet.WriteText(6, 0, ''); FWorksheet.WriteNumber (6, 1, 600); + FWorksheet.WriteDateTime(7, 0, EncodeDate(2025,2,1)); FWorksheet.WriteNumber (7, 1, 700); + FWorksheet.WriteText(8, 0, 'abc'); FWorksheet.WriteBoolValue (8, 1, TRUE); + FWorksheet.WriteText(9, 0, 'abc'); FWorksheet.WriteErrorValue(9, 1, errIllegalRef); + + // *** two-argument calls + + // Average value of all cells in the second column with are <=200 + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(B1:B8,"<=200")'); + FWorksheet.CalcFormulas; + CheckEquals(150, FWorksheet.ReadAsNumber(0, 2), 'Formula #1 AVERAGEIF(B1:B8,"<=200") result mismatch'); + + // Average value of all cells in the second column with are >=400 + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(B1:B8,">=400")'); + FWorksheet.CalcFormulas; + CheckEquals(550, FWorksheet.ReadAsNumber(0, 2), 'Formula #2 AVERAGEIF(B1:B8,">=400") result mismatch'); + + // Average value of all cells in the second column with are <0 + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(B1:B9,"<0")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #3 AVERAGEIF(B1:B9,"<0") result mismatch'); + + // *** three-argument calls + + // Average value of all cells in the second column for which the first column cell is 'abc' (case-insensitive)' + // ... numeric cells only (incl numeric text cell) + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A5,"abc",B1:B5)'); + FWorksheet.CalcFormulas; + CheckEquals(150, FWorksheet.ReadAsNumber(0, 2), 'Formula #4 AVERAGEIF(A1:A5,"abc",B1:B5) result mismatch'); + + // ... dto, but check case-insensitivity of search phrase + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A5,"ABC",B1:B5)'); + FWorksheet.CalcFormulas; + CheckEquals(150, FWorksheet.ReadAsNumber(0, 2), 'Formula #5 AVERAGEIF(A1:A5,"ABC",B1:B5) result mismatch'); + + // ... including non-numeric text cell + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A7,"abc",B1:B7)'); + FWorksheet.CalcFormulas; + CheckEquals(150, FWorksheet.ReadAsNumber(0, 2), 'Formula #6 AVERAGEIF(A1:A7,"abc",B1:B7) result mismatch'); + + // ... including boolean cell + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A9,"abc",B1:B9)'); + FWorksheet.CalcFormulas; + CheckEquals(150, FWorksheet.ReadAsNumber(0, 2), 'Formula #7 AVERAGEIF(A1:A9,"abc",B1:B9) result mismatch'); + + // ... including error cell + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A10,"abc",B1:B10)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 2), 'Formula #8 AVERAGEIF(A1:A10,"abc",B1:B10) result mismatch'); + + // ToDo: CompareStringsWithWildcards does not handle a mask such as "*b" like Excel + { + // Search for text cells by wildcards + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A8,"*bc",B1:B8)'); + FWorksheet.CalcFormulas; + CheckEquals(275, FWorksheet.ReadAsNumber(0, 2), 'Formula #9 AVERAGEIF(A1:A8,"*bc",B1:B8) result mismatch'); + } + + // Search for date cells (matching cell found) + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A8,DATE(2025,2,1),B1:B8)'); + FWorksheet.CalcFormulas; + CheckEquals(700, FWorksheet.ReadAsNumber(0, 2), 'Formula #9 AVERAGEIF(A1:A8,DATE(2025,2,1),B1:B8) result mismatch'); + + // Search for date cell (no matching cell found) + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A8,DATE(2000,2,1),B1:B8)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #9 AVERAGEIF(A1:A8,DATE(2000,2,1),B1:B8) result mismatch'); + + // Search for empty cells + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A8,"",B1:B8)'); + FWorksheet.CalcFormulas; + CheckEquals(600, FWorksheet.ReadAsNumber(0, 2), 'Formula #10 AVERAGEIF(A1:A8,"",B1:B8) result mismatch'); + + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A8,"=",B1:B8)'); + FWorksheet.CalcFormulas; + CheckEquals(600, FWorksheet.ReadAsNumber(0, 2), 'Formula #11 AVERAGEIF(A1:A8,"Abc",B1:B8) result mismatch'); + + // Search for non-empty cells + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A8,"<>",B1:B8)'); + FWorksheet.CalcFormulas; + CheckEquals(2200/6, FWorksheet.ReadAsNumber(0, 2), EPS, 'Formula #12 AVERAGEIF(A1:A8,"<>",B1:B8) result mismatch'); + + // Compare with reference cell A20 + FWorksheet.WriteText(19, 0, 'abc'); // A20 = "abc" + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A9,A20,B1:B9)'); + FWorksheet.CalcFormulas; + CheckEquals(150, FWorksheet.ReadAsNumber(0, 2), 'Formula #13 AVERAGEIF(A1:A9,A20,B1:B9) (A20="abc") result mismatch'); + + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A9,"<>"&A20,B1:B9)'); + FWorksheet.CalcFormulas; + CheckEquals(500, FWorksheet.ReadAsNumber(0, 2), 'Formula #13 AVERAGEIF(A1:A9,"<>"&A20,B1:B9) (A20="abc") result mismatch'); + + // Error in first argument + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(#DIV/0!,"<10")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #14 AVERAGEIF(#DIV/0,"<10") result mismatch'); + + // Error in second argument + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A9,#DIV/0!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #15 AVERAGEIF(A1:A9,#DIV/0) result mismatch'); + + // Error in third argument + FWorksheet.WriteFormula(0, 2, '=AVERAGEIF(A1:A9,"=",#DIV/0!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #16 AVERAGEIF(A1:A9,"=",#DIV/0) result mismatch'); +end; + + +procedure TCalcStatsFormulaTests.Test_COUNT; +begin + // Test data + FWorksheet.WriteNumber (0, 0, 10); + FWorksheet.WriteNumber (1, 0, 20); + FWorksheet.WriteNumber (2, 0, 30); + FWorksheet.WriteText (3, 0, '40'); + FWorksheet.WriteText (4, 0, 'abc'); + FWorksheet.WriteFormula(5, 0, '=1/0'); + + // Count literal values + FWorksheet.WriteFormula(0, 1, '=COUNT(10)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 COUNT(10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNT(20,10,"abc",40)'); + FWorksheet.CalcFormulas; + CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 COUNT(20,10,"abc",40) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNT("40")'); // although string considered to be numeric + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 COUNT("40") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNT("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 COUNT("abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNT("")'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 COUNT("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNT(1/0)'); // argument error does NOT propagate to formula result + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #6 COUNT(1/0) result mismatch'); + + // Count in cell references + FWorksheet.WriteFormula(0, 1, '=COUNT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 COUNT(A1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNT(A10)'); // empty cell + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 COUNT(A10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNT(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 COUNT(A1,A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNT(A1:A3)'); // "real" numeric values + FWorksheet.CalcFormulas; + CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 COUNT(A1:A3) result mismatch'); + + // Cell references pointing to string cells + FWorksheet.WriteFormula(0, 1, '=COUNT(A1:A4)'); // "real" and string numeric values + FWorksheet.CalcFormulas; + CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 COUNT(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNT(A1:A5)'); // "real" and string values + FWorksheet.CalcFormulas; + CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 COUNT(A1:A5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNT(A1:A5,A8:A10)'); // real and string values and blanks + FWorksheet.CalcFormulas; + CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 COUNT(A1:A5,A8:A10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNT(A1,A2:A5)'); // several ranges + FWorksheet.CalcFormulas; + CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 COUNT(A1,A2:A5) result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 1, '=COUNT(A1, 1/0, A2)'); // error in argument + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #15 COUNT(A1, 1/0, A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNT(A1:A6)'); // error in cell + FWorksheet.CalcFormulas; + CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #15 COUNT(A1:A6) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.Test_COUNTA; +begin + FWorksheet.WriteFormula(0, 1, '=COUNTA("")'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 COUNTA("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNTA(10)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 COUNTA(10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNTA(20,10,"abc",40)'); + FWorksheet.CalcFormulas; + CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 COUNTA(20,10,"abc",40) result mismatch'); + + FWorksheet.WriteNumber(0, 0, 20); + FWorksheet.WriteNumber(1, 0, 10); + FWorksheet.WriteText(2, 0, 'abc'); + FWorksheet.WriteNumber(3, 0, 40); + + FWorksheet.WriteFormula(4, 1, '=COUNTA(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(4, 1), 'Formula #4 COUNTA(A1) result mismatch'); + + FWorksheet.WriteFormula(4, 1, '=COUNTA(A10)'); // A10 is empty + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(4, 1), 'Formula #5 COUNTA(A10) result mismatch'); + + FWorksheet.WriteFormula(4, 1, '=COUNTA(A2,A3)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(4, 1), 'Formula #6 COUNTA(A2,A3) result mismatch'); + + FWorksheet.WriteFormula(4, 1, '=COUNTA(A1:A4)'); + FWorksheet.CalcFormulas; + CheckEquals(4, FWorksheet.ReadAsNumber(4, 1), 'Formula #7 COUNTA(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(4, 1, '=COUNTA(A1:A10)'); + FWorksheet.CalcFormulas; + CheckEquals(4, FWorksheet.ReadAsNumber(4, 1), 'Formula #8 COUNTA(A1:A10) result mismatch'); + + FWorksheet.WriteFormula(4, 1, '=COUNTA(A1,A2:A10)'); + FWorksheet.CalcFormulas; + CheckEquals(4, FWorksheet.ReadAsNumber(4, 1), 'Formula #9 COUNTA(A1,A2:A10) result mismatch'); + + FWorksheet.WriteFormula(4, 1, '=COUNTA(A1, 1/0, A3)'); + FWorksheet.CalcFormulas; + CheckEquals(3, FWorksheet.ReadAsNumber(4, 1), 'Formula #10 COUNTA(A1, 1/0, A3) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.Test_COUNTBLANK; +begin + // The next 2 tests are successful, but not accepted by Excel which only wants + // a "range" as argument in COUNTBLANK. + + FWorksheet.WriteFormula(0, 1, '=COUNTBLANK("")'); // empty string is not "blank" + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 COUNTBLANK("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=COUNTBLANK(10)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 COUNTBLANK(10) result mismatch'); + + // The following tests are conformal to Excel. + + FWorksheet.WriteNumber(0, 0, 20); + FWorksheet.WriteText(1, 0, 'abc'); + + FWorksheet.WriteFormula(4, 1, '=COUNTBLANK(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(4, 1), 'Formula #3 COUNTBLANK(A1) result mismatch'); + + FWorksheet.WriteFormula(4, 1, '=COUNTBLANK(A10)'); // A10 is empty + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(4, 1), 'Formula #4 COUNTBLANK(A10) result mismatch'); + + FWorksheet.WriteFormula(4, 1, '=COUNTBLANK(A1:A4)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(4, 1), 'Formula #5 COUNTBLANK(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(2, 0, '=1/0'); + FWorksheet.WriteFormula(4, 1, '=COUNTBLANK(A1:A4)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(4, 1), 'Formula #6 COUNTBLANK(A1:A4) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.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'); + + // Error in 1st argument + FWorksheet.WriteFormula(0, 2, '=COUNTIF(#REF!,1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 2), 'Formula #7 COUNTIF(#REF!,1) result mismatch'); + + // Error in both arguments + FWorksheet.WriteFormula(0, 2, '=COUNTIF(#REF!,#REF!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 2), 'Formula #8 COUNTIF(#REF!,#REF!) 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 #9 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 #10 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 #11 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 #12 COUNTIF(A1:B6,A15) (A15 = #NUM!) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.Test_MAX; +begin + // Test data + FWorksheet.WriteNumber (0, 0, 10); + FWorksheet.WriteNumber (1, 0, 20); + FWorksheet.WriteNumber (2, 0, 30); + FWorksheet.WriteText (3, 0, '40'); + FWorksheet.WriteText (4, 0, 'abc'); + FWorksheet.WriteFormula(5, 0, '=1/0'); + + // Literal values + FWorksheet.WriteFormula(0, 1, '=MAX(10)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 MAX(10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX(10,20)'); + FWorksheet.CalcFormulas; + CheckEquals(20, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 MAX(10,20) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX("40")'); // although string considered to be numeric + FWorksheet.CalcFormulas; + CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 MAX("40") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX(10,20,30,"40")'); + FWorksheet.CalcFormulas; + CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 MAX(10,20,30,"40") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 MAX("abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX("")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 MAX("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX(10,20,30,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 MAX(10,20,30,"abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 MAX(1/0) result mismatch'); + + // Cell references + FWorksheet.WriteFormula(0, 1, '=MAX(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 MAX(A1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX(A10)'); // empty cell + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 MAX(A10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals(20, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 MAX(A1,A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX(A1:A3)'); // "real" numeric values + FWorksheet.CalcFormulas; + CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 MAX(A1:A3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX(A1,A2:A3)'); // several ranges + FWorksheet.CalcFormulas; + CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 MAX(A1,A2:A3) result mismatch'); + + // Cell references pointing to string cells + FWorksheet.WriteFormula(0, 1, '=MAX(A1:A4)'); // real and string numeric values + FWorksheet.CalcFormulas; + CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 MAX(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX(A1:A5)'); // real and string values --> ignore string + FWorksheet.CalcFormulas; + CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 MAX(A1:A5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX(A1:A4,A8:A10)'); // real and string values and blanks + FWorksheet.CalcFormulas; + CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 MAX(A1:A4,A8:A10) result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 1, '=MAX(A1, 1/0, A2)'); // error in argument + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 MAX(A1, 1/0, A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX(A1:A6)'); // error in cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 MAX(A:A6) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.Test_MIN; +begin + // Test data + FWorksheet.WriteNumber (0, 0, 10); + FWorksheet.WriteNumber (1, 0, 20); + FWorksheet.WriteNumber (2, 0, 30); + FWorksheet.WriteText (3, 0, '-40'); + FWorksheet.WriteText (4, 0, 'abc'); + FWorksheet.WriteFormula(5, 0, '=1/0'); + + // Literal values + FWorksheet.WriteFormula(0, 1, '=MIN(10)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 MIN(10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN(10,20)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 MIN(10,20) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN("40")'); // although string considered to be numeric + FWorksheet.CalcFormulas; + CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 MIN("40") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN(10,20,30,"40")'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 MIN(10,20,30,"40") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 MIN("abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN("")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 MIN("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN(10,20,30,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 MIN(10,20,30,"abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MAX(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 MAX(1/0) result mismatch'); + + // Cell references + FWorksheet.WriteFormula(0, 1, '=MIN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 MIN(A1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN(A10)'); // empty cell + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 MIN(A10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 MIN(A1,A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN(A1:A3)'); // "real" numeric values + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 MIN(A1:A3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN(A1,A2:A3)'); // several ranges + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 MIN(A1,A2:A3) result mismatch'); + + // Cell references pointing to string cells + FWorksheet.WriteFormula(0, 1, '=MIN(A1:A4)'); // real and string numeric values + FWorksheet.CalcFormulas; + CheckEquals(-40, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 MIN(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN(A1:A5)'); // real and string values --> ignore string + FWorksheet.CalcFormulas; + CheckEquals(-40, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 MIN(A1:A5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN(A1:A4,A8:A10)'); // real and string values and blanks + FWorksheet.CalcFormulas; + CheckEquals(-40, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 MIN(A1:A4,A8:A10) result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 1, '=MIN(A1, 1/0, A2)'); // error in argument + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 MIN(A1, 1/0, A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=MIN(A1:A6)'); // error in cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 MIN(A:A6) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.Test_PRODUCT; +begin + // Test data + FWorksheet.WriteNumber (0, 0, 1); + FWorksheet.WriteNumber (1, 0, 2); + FWorksheet.WriteNumber (2, 0, 3); + FWorksheet.WriteText (3, 0, '4'); + FWorksheet.WriteText (4, 0, 'abc'); + FWorksheet.WriteFormula(5, 0, '=1/0'); + + // Literal values + 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)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 PRODUCT(1,2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT("4")'); // although string considered to be numeric + FWorksheet.CalcFormulas; + CheckEquals(4, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 PRODUCT("4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT(1,2,3,"4")'); + FWorksheet.CalcFormulas; + CheckEquals(24, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 PRODUCT(1,2,3,"4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 PRODUCT("abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT("")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 PRODUCT("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT(1,2,3,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 PRODUCT(1,2,3,"abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 PRODUCT(1/0) result mismatch'); + + // Count in cell references + FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 PRODUCT(A1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT(A10)'); // empty cell + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 PRODUCT(A10) (A10 = empty) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals(2, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 PRODUCT(A1,A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1:A3)'); // "real" numeric values + FWorksheet.CalcFormulas; + CheckEquals(6, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 PRODUCT(A1:A3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1,A2:A3)'); // several ranges + FWorksheet.CalcFormulas; + CheckEquals(6, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 PRODUCT(A1,A2:A3) result mismatch'); + + // Cell references pointing to string cells + FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1:A4)'); // real and string numeric values + FWorksheet.CalcFormulas; + CheckEquals(24, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 PRODUCT(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1:A5)'); // real and string values --> ignore string + FWorksheet.CalcFormulas; + CheckEquals(24, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 PRODUCT(A1:A5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1:A4,A8:A10)'); // real and string values and blanks + FWorksheet.CalcFormulas; + CheckEquals(24, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 PRODUCT(A1:A4,A8:A10) result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1, 1/0, A2)'); // error in argument + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 PRODUCT(A1, 1/0, A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=PRODUCT(A1:A6)'); // error in cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 PRODUCT(A:A6) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.Test_STDEV; +const + EPS = 1E-8; +begin + // Test data + FWorksheet.WriteNumber (0, 0, 1); + FWorksheet.WriteNumber (1, 0, -2); + FWorksheet.WriteNumber (2, 0, -3); + FWorksheet.WriteText (3, 0, '4'); + FWorksheet.WriteText (4, 0, 'abc'); + FWorksheet.WriteFormula(5, 0, '=1/0'); + + // Literal values + FWorksheet.WriteFormula(0, 1, '=STDEV(1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #1 STDEV(1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV(1,-2)'); + FWorksheet.CalcFormulas; + CheckEquals(2.121320344, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #2 STDEV(1,-2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV("4")'); // although string considered to be numeric + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #3 STDEV("4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV(1,-2,-3,"4")'); + FWorksheet.CalcFormulas; + CheckEquals(3.16227766, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #4 STDEV(1,2,3,"4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 STDEV("abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV("")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 STDEV("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV(1,-2,-3,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 STDEV(1,-2,-3,"abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 STDEV(1/0) result mismatch'); + + // Cell references + FWorksheet.WriteFormula(0, 1, '=STDEV(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #7 STDEV(A1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV(A10)'); // empty cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 STDEV(A10)(A10=empty) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals(2.121320344, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #9 STDEV(A1,A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV(A1:A3)'); // "real" numeric values + FWorksheet.CalcFormulas; + CheckEquals(2.081665999, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #10 STDEV(A1:A3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV(A1,A2:A3)'); // several ranges + FWorksheet.CalcFormulas; + CheckEquals(2.081665999, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #11 STDEV(A1,A2:A3) result mismatch'); + + // Cell references pointing to string cells + FWorksheet.WriteFormula(0, 1, '=STDEV(A1:A4)'); // real and string numeric values + FWorksheet.CalcFormulas; + CheckEquals(3.16227766, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #12 STDEV(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV(A1:A5)'); // real and string values --> ignore string + FWorksheet.CalcFormulas; + CheckEquals(3.16227766, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #13 STDEV(A1:A5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV(A1:A4,A8:A10)'); // real and string values and blanks + FWorksheet.CalcFormulas; + CheckEquals(3.16227766, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #14 STDEV(A1:A4,A8:A10) result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 1, '=STDEV(A1, 1/0, A2)'); // error in argument + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 STDEV(A1, 1/0, A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEV(A1:A6)'); // error in cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 STDEV(A:A6) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.Test_STDEVP; +const + EPS = 1E-8; +begin + // Test data + FWorksheet.WriteNumber (0, 0, 1); + FWorksheet.WriteNumber (1, 0, -2); + FWorksheet.WriteNumber (2, 0, -3); + FWorksheet.WriteText (3, 0, '4'); + FWorksheet.WriteText (4, 0, 'abc'); + FWorksheet.WriteFormula(5, 0, '=1/0'); + + // Literal values + FWorksheet.WriteFormula(0, 1, '=STDEVP(1)'); + FWorksheet.CalcFormulas; + CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 STDEVP(1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP(1,-2)'); + FWorksheet.CalcFormulas; + CheckEquals(1.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #2 STDEVP(1,-2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP("4")'); // although string considered to be numeric + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 STDEVP("4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP(1,-2,-3,"4")'); + FWorksheet.CalcFormulas; + CheckEquals(2.738612788, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #4 STDEVP(1,2,3,"4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 STDEVP("abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP("")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 STDEVP("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP(1,-2,-3,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 STDEVP(1,-2,-3,"abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 STDEVP(1/0) result mismatch'); + + // Cell references + FWorksheet.WriteFormula(0, 1, '=STDEVP(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 STDEVP(A1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP(A10)'); // empty cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 STDEVP(A10)(A10=empty) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals(1.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #9 STDEVP(A1,A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP(A1:A3)'); // "real" numeric values + FWorksheet.CalcFormulas; + CheckEquals(1.699673171, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #10 STDEVP(A1:A3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP(A1,A2:A3)'); // several ranges + FWorksheet.CalcFormulas; + CheckEquals(1.699673171, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #11 STDEVP(A1,A2:A3) result mismatch'); + + // Cell references pointing to string cells + FWorksheet.WriteFormula(0, 1, '=STDEVP(A1:A4)'); // real and string numeric values + FWorksheet.CalcFormulas; + CheckEquals(2.738612788, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #12 STDEVP(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP(A1:A5)'); // real and string values --> ignore string + FWorksheet.CalcFormulas; + CheckEquals(2.738612788, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #13 STDEVP(A1:A5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP(A1:A4,A8:A10)'); // real and string values and blanks + FWorksheet.CalcFormulas; + CheckEquals(2.738612788, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #14 STDEVP(A1:A4,A8:A10) result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 1, '=STDEVP(A1, 1/0, A2)'); // error in argument + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 STDEVP(A1, 1/0, A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=STDEVP(A1:A6)'); // error in cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 STDEVP(A:A6) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.Test_SUM; +begin + // Test data + FWorksheet.WriteNumber (0, 0, 10); + FWorksheet.WriteNumber (1, 0, 20); + FWorksheet.WriteNumber (2, 0, 30); + FWorksheet.WriteText (3, 0, '40'); + FWorksheet.WriteText (4, 0, 'abc'); + FWorksheet.WriteFormula(5, 0, '=1/0'); + + // Literal values + FWorksheet.WriteFormula(0, 1, '=SUM(10)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 SUM(10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(10,20)'); + FWorksheet.CalcFormulas; + CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 SUM(10,20) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM("40")'); // although string considered to be numeric + FWorksheet.CalcFormulas; + CheckEquals(40, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 SUM("40") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(10,20,30,"40")'); + FWorksheet.CalcFormulas; + CheckEquals(100, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 SUM(10,20,30,"40") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 SUM("abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM("")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 SUM("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(10,20,30,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 SUM(10,20,30,"abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 SUM(1/0) result mismatch'); + + // Count in cell references + FWorksheet.WriteFormula(0, 1, '=SUM(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 SUM(A1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(A10)'); // empty cell + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 SUM(A10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 SUM(A1,A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(A1:A3)'); // "real" numeric values + FWorksheet.CalcFormulas; + CheckEquals(60, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 SUM(A1:A3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(A1,A2:A3)'); // several ranges + FWorksheet.CalcFormulas; + CheckEquals(60, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 SUM(A1,A2:A3) result mismatch'); + + // Cell references pointing to string cells + FWorksheet.WriteFormula(0, 1, '=SUM(A1:A4)'); // real and string numeric values + FWorksheet.CalcFormulas; + CheckEquals(100, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 SUM(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(A1:A5)'); // real and string values --> ignore string + FWorksheet.CalcFormulas; + CheckEquals(100, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 SUM(A1:A5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(A1:A4,A8:A10)'); // real and string values and blanks + FWorksheet.CalcFormulas; + CheckEquals(100, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 SUM(A1:A4,A8:A10) result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 1, '=SUM(A1, 1/0, A2)'); // error in argument + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 SUM(A1, 1/0, A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUM(A1:A6)'); // error in cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 SUM(A:A6) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.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 in A10 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'); + + // *** Error in arguments + + // Error in first argument + FWorksheet.WriteFormula(0, 2, '=SUMIF(#DIV/0!,"<10")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #18 SUMIF(#DIV/0,"<10") result mismatch'); + + // Error in second argument + FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:A9,#DIV/0!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #19 SUMIF(A1:A9,#DIV/0) result mismatch'); + + // Error in third argument + FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:A9,"=",#DIV/0!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #20 SUMIF(A1:A9,"=",#DIV/0) result mismatch'); + + // Write compare cell to contain an error (A15) + FWorksheet.WriteFormula( 14, 0, '=1/0'); // A15 + + // Calculate sum of the elements in A1:B5 which are equal to cell A15 (containing #DIV/0!) + // but this error does not exist in any cell of A1:B5 + FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B5,A15)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 2), 'Formula #21 SUMIF(A1:B5,A15) (A15=#DIV/0!) result mismatch'); + + // Calculate sum of the elements in A1:B5 which are equal to cell A15 (containing #DIV/0!) + // Cell A1 does have this error, so we expect the result to be 1 (1 cell with #DIV/0! error) + FWorksheet.WriteFormula(0, 0, '=1/0'); + FWorksheet.WriteFormula(0, 2, '=SUMIF(A1:B5,A15)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 2), 'Formula #22 SUMIF(A1:B5,A15) (A1=A15=#DIV/0!) result mismatch'); + //CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 2), 'Formula #21 SUMIF(A1:B5,A15) (A15=#DIV/0!) result mismatch'); + +end; + +procedure TCalcStatsFormulaTests.Test_SUMSQ; +begin + // Test data + FWorksheet.WriteNumber (0, 0, 1); + FWorksheet.WriteNumber (1, 0, 2); + FWorksheet.WriteNumber (2, 0, 3); + FWorksheet.WriteText (3, 0, '4'); + FWorksheet.WriteText (4, 0, 'abc'); + FWorksheet.WriteFormula(5, 0, '=1/0'); + + // Literal values + FWorksheet.WriteFormula(0, 1, '=SUMSQ(1)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 SUMSQ(1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ(1,2)'); + FWorksheet.CalcFormulas; + CheckEquals(5, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 SUMSQ(1,2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ("4")'); // although string considered to be numeric + FWorksheet.CalcFormulas; + CheckEquals(16, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 SUMSQ("4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ(1,2,3,"4")'); + FWorksheet.CalcFormulas; + CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 SUMSQ(1,2,3,"4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 SUMSQ("abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ("")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 SUMSQ("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ(1,2,3,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 SUMSQ(1,2,3,"abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 SUMSQ(1/0) result mismatch'); + + // Count in cell references + FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(1, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 SUMSQ(A1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ(A10)'); // empty cell + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #8 SUMSQ(A10) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals(5, FWorksheet.ReadAsNumber(0, 1), 'Formula #9 SUMSQ(A1,A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1:A3)'); // "real" numeric values + FWorksheet.CalcFormulas; + CheckEquals(14, FWorksheet.ReadAsNumber(0, 1), 'Formula #10 SUMSQ(A1:A3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1,A2:A3)'); // several ranges + FWorksheet.CalcFormulas; + CheckEquals(14, FWorksheet.ReadAsNumber(0, 1), 'Formula #11 SUMSQ(A1,A2:A3) result mismatch'); + + // Cell references pointing to string cells + FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1:A4)'); // "real" and string numeric values + FWorksheet.CalcFormulas; + CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #12 SUMSQ(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1:A5)'); // "real" and string values --> ignore string + FWorksheet.CalcFormulas; + CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #13 SUMSQ(A1:A5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1:A4,A8:A10)'); // real and string values and blanks + FWorksheet.CalcFormulas; + CheckEquals(30, FWorksheet.ReadAsNumber(0, 1), 'Formula #14 SUMSQ(A1:A4,A8:A10) result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1:A5,1/0)'); // error in argument --> error in result + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 SUMSQ(A1, 1/0, A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=SUMSQ(A1:A6)'); // error in cell --> error in result + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 SUMSQ(A1:A6) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.Test_VAR; +const + EPS = 1E-8; +begin + // Test data + FWorksheet.WriteNumber (0, 0, 1); + FWorksheet.WriteNumber (1, 0, -2); + FWorksheet.WriteNumber (2, 0, -3); + FWorksheet.WriteText (3, 0, '4'); + FWorksheet.WriteText (4, 0, 'abc'); + FWorksheet.WriteFormula(5, 0, '=1/0'); + + // Literal values + FWorksheet.WriteFormula(0, 1, '=VAR(1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #1 VAR(1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR(1,-2)'); + FWorksheet.CalcFormulas; + CheckEquals(4.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #2 VAR(1,-2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR("4")'); // although string considered to be numeric + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #3 VAR("4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR(1,-2,-3,"4")'); + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #4 VAR(1,-2,-3,"4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 VAR("abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR("")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 VAR("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR(1,-2,-3,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 VAR(1,-2,-3,"abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 VAR(1/0) result mismatch'); + + // Cell references + FWorksheet.WriteFormula(0, 1, '=VAR(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #7 VAR(A1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR(A10)'); // empty cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 VAR(A10)(A10=empty) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals(4.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #9 VAR(A1,A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR(A1:A3)'); // "real" numeric values + FWorksheet.CalcFormulas; + CheckEquals(4.333333333, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #10 VAR(A1:A3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR(A1,A2:A3)'); // several ranges + FWorksheet.CalcFormulas; + CheckEquals(4.333333333, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #11 VAR(A1,A2:A3) result mismatch'); + + // Cell references pointing to string cells + FWorksheet.WriteFormula(0, 1, '=VAR(A1:A4)'); // real and string numeric values + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #12 VAR(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR(A1:A5)'); // real and string values --> ignore string + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #13 VAR(A1:A5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR(A1:A4,A8:A10)'); // real and string values and blanks + FWorksheet.CalcFormulas; + CheckEquals(10, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #14 VAR(A1:A4,A8:A10) result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 1, '=VAR(A1, 1/0, A2)'); // error in argument + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 VAR(A1, 1/0, A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VAR(A1:A6)'); // error in cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 VAR(A:A6) result mismatch'); +end; + +procedure TCalcStatsFormulaTests.Test_VARP; +const + EPS = 1E-8; +begin + // Test data + FWorksheet.WriteNumber (0, 0, 1); + FWorksheet.WriteNumber (1, 0, -2); + FWorksheet.WriteNumber (2, 0, -3); + FWorksheet.WriteText (3, 0, '4'); + FWorksheet.WriteText (4, 0, 'abc'); + FWorksheet.WriteFormula(5, 0, '=1/0'); + + // Literal values + FWorksheet.WriteFormula(0, 1, '=VARP(1)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #1 VAR(1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP(1,-2)'); + FWorksheet.CalcFormulas; + CheckEquals(2.25, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #2 VARP(1,-2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP("4")'); // although string considered to be numeric + FWorksheet.CalcFormulas; + CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #3 VARP("4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP(1,-2,-3,"4")'); + FWorksheet.CalcFormulas; + CheckEquals(7.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #4 VARP(1,-2,-3,"4") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #5 VARP("abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP("")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #6 VARP("") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP(1,-2,-3,"abc")'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_WRONG_TYPE, FWorksheet.ReadAsText(0, 1), 'Formula #7 VARP(1,-2,-3,"abc") result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP(1/0)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 VARP(1/0) result mismatch'); + + // Cell references + FWorksheet.WriteFormula(0, 1, '=VARP(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(0.0, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #7 VARP(A1) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP(A10)'); // empty cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #8 VARP(A10)(A10=empty) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals(2.25, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #9 VARP(A1,A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP(A1:A3)'); // "real" numeric values + FWorksheet.CalcFormulas; + CheckEquals(2.888888889, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #10 VARP(A1:A3) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP(A1,A2:A3)'); // several ranges + FWorksheet.CalcFormulas; + CheckEquals(2.888888889, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #11 VARP(A1,A2:A3) result mismatch'); + + // Cell references pointing to string cells + FWorksheet.WriteFormula(0, 1, '=VARP(A1:A4)'); // real and string numeric values + FWorksheet.CalcFormulas; + CheckEquals(7.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #12 VARP(A1:A4) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP(A1:A5)'); // real and string values --> ignore string + FWorksheet.CalcFormulas; + CheckEquals(7.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #13 VARP(A1:A5) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP(A1:A4,A8:A10)'); // real and string values and blanks + FWorksheet.CalcFormulas; + CheckEquals(7.5, FWorksheet.ReadAsNumber(0, 1), EPS, 'Formula #14 VARP(A1:A4,A8:A10) result mismatch'); + + // Error propagation + FWorksheet.WriteFormula(0, 1, '=VARP(A1, 1/0, A2)'); // error in argument + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #15 VARP(A1, 1/0, A2) result mismatch'); + + FWorksheet.WriteFormula(0, 1, '=VARP(A1:A6)'); // error in cell + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_DIVIDE_BY_ZERO, FWorksheet.ReadAsText(0, 1), 'Formula #16 VARP(A:A6) result mismatch'); +end; + + diff --git a/components/fpspreadsheet/unit-tests/common/testcases_calctextformulas.inc b/components/fpspreadsheet/unit-tests/common/testcases_calctextformulas.inc new file mode 100644 index 000000000..78d43d2fe --- /dev/null +++ b/components/fpspreadsheet/unit-tests/common/testcases_calctextformulas.inc @@ -0,0 +1,293 @@ +{ included by CalcFormulaTests.pas } + +// *** String formula tests + +procedure TCalcTextFormulaTests.Test_CONCATENATE; +begin + // Test data + FWorksheet.WriteText (0, 0, 'abc'); // A1 + FWorksheet.WriteText (1, 0, 'def'); // A2 + FWorksheet.WriteNumber (2, 0, 123); // A3 + FWorksheet.WriteBoolValue (3, 0, true); // A4 + FWorksheet.WriteErrorvalue(4, 0, errIllegalRef); // A5 + + // Concatenate 2 literal strings + FWorksheet.WriteFormula(0, 1, '=CONCATENATE("abc","def")'); + FWorksheet.CalcFormulas; + CheckEquals('abcdef', FWorksheet.ReadAsText(0, 1), 'Formula #1 CONCATENATE("abc","def") result mismatch'); + + // Concatenate 3 literal strings + FWorksheet.WriteFormula(0, 1, '=CONCATENATE("abc","def","ghi")'); + FWorksheet.CalcFormulas; + CheckEquals('abcdefghi', FWorksheet.ReadAsText(0, 1), 'Formula #2 CONCATENATE("abc","def","ghi") result mismatch'); + + // Concatenate 2 literal strings and number + FWorksheet.WriteFormula(0, 1, '=CONCATENATE("abc","def",123)'); + FWorksheet.CalcFormulas; + CheckEquals('abcdef123', FWorksheet.ReadAsText(0, 1), 'Formula #3 CONCATENATE("abc","def",123) result mismatch'); + + // Concatenate two numbers + FWorksheet.WriteFormula(0, 1, '=CONCATENATE(123,456)'); + FWorksheet.CalcFormulas; + CheckEquals('123456', FWorksheet.ReadAsText(0, 1), 'Formula #4 CONCATENATE(123,456) result mismatch'); + + { -- this test will not work in the file because Excel writes a localized "TRUE" to the cell + // Concatenate string and boolean + FWorksheet.WriteFormula(0, 1, '=CONCATENATE("abc",TRUE())'); + FWorksheet.CalcFormulas; + CheckEquals('abcTRUE', FWorksheet.ReadAsText(0, 1), 'Formula #5 CONCATENATE("abc",TRUE()) result mismatch'); + } + + // Concatenate 2 string cells + FWorksheet.WriteFormula(0, 1, '=CONCATENATE(A1,A2)'); + FWorksheet.CalcFormulas; + CheckEquals('abcdef', FWorksheet.ReadAsText(0, 1), 'Formula #5 CONCATENATE(A1,A2) result mismatch'); + + // Concatenate string and numeric cells + FWorksheet.WriteFormula(0, 1, '=CONCATENATE(A1,A3)'); + FWorksheet.CalcFormulas; + CheckEquals('abc123', FWorksheet.ReadAsText(0, 1), 'Formula #6 CONCATENATE(A1,A3) result mismatch'); + + // Concatenate string and error cells + FWorksheet.WriteFormula(0, 1, '=CONCATENATE(A1,A5)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #6 CONCATENATE(A1,A5) result mismatch'); +end; + +procedure TCalcTextFormulaTests.Test_EXACT; +var + cell: PCell; +begin + // Test cells + FWorksheet.WriteText(0, 0, 'abc'); // A1 + FWorksheet.WriteText(1, 0, 'ABC'); // A2 + FWorksheet.WriteText(2, 0, 'abcd'); // A3 + FWorksheet.WriteText(3, 0, 'äöü'); // A4 + FWorksheet.WriteText(4, 0, 'Äöü'); // A5 + FWorksheet.WriteErrorValue(5, 0, errDivideByZero); // A6 + FWorksheet.WriteNumber(6, 0, 123); // A7 + FWorksheet.WriteText(7, 0, '123'); // A8 + + // Same literal strings + cell := FWorksheet.WriteFormula(0, 1, '=EXACT("abc", "abc")'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #1 EXACT("abc","abc") result type mismatch:'); + CheckEquals(true, cell^.BoolValue, 'Formula #1 EXACT("abc", "abc") result mismatch.'); + + // Same strings but different case + cell := FWorksheet.WriteFormula(0, 1, '=EXACT("abc", "ABC")'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #2 EXACT("abc","ABC") result type mismatch:'); + CheckEquals(false, cell^.BoolValue, 'Formula #2 EXACT("abc", "ABC") result mismatch.'); + + // Lengths different + cell := FWorksheet.WriteFormula(0, 1, '=EXACT("abc", "abcd")'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #3 EXACT("abc","abcd") result type mismatch:'); + CheckEquals(false, cell^.BoolValue, 'Formula #3 EXACT("abc", "abcd") result mismatch.'); + + // Same unicode chars + cell := FWorksheet.WriteFormula(0, 1, '=EXACT("äöü", "äöü")'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #4 EXACT("äöü","äöü") result type mismatch:'); + CheckEquals(true, cell^.BoolValue, 'Formula #4 EXACT("äöü", "äöü") result mismatch.'); + + // Different unicode case + cell := FWorksheet.WriteFormula(0, 1, '=EXACT("äöü", "Äöü")'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #5 EXACT("äöü","Äöü") result type mismatch:'); + CheckEquals(false, cell^.BoolValue, 'Formula #5 EXACT("äöü", "Äöü") result mismatch.'); + + // Cells with same ASCII strings + cell := FWorksheet.WriteFormula(0, 1, '=EXACT(A1, A1)'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #6 EXACT(A1,A1) result type mismatch:'); + CheckEquals(true, cell^.BoolValue, 'Formula #6 EXACT(A1,A1) result mismatch.'); + + // Cells with same strings, but different case + cell := FWorksheet.WriteFormula(0, 1, '=EXACT(A1, A2)'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #7 EXACT(A1,A2) result type mismatch:'); + CheckEquals(false, cell^.BoolValue, 'Formula #7 EXACT(A1,A2) result mismatch.'); + + // Cells with almost same strings, but different lengths + cell := FWorksheet.WriteFormula(0, 1, '=EXACT(A1, A3)'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #8 EXACT(A1,A3) result type mismatch:'); + CheckEquals(false, cell^.BoolValue, 'Formula #8 EXACT(A1,A3) result mismatch.'); + + // Cells with ASCII and UTF8 + cell := FWorksheet.WriteFormula(0, 1, '=EXACT(A1, A4)'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #9 EXACT(A1,A4) result type mismatch:'); + CheckEquals(false, cell^.BoolValue, 'Formula #9 EXACT(A1,A4) result mismatch.'); + + // Cells with same Unicode strings + cell := FWorksheet.WriteFormula(0, 1, '=EXACT(A4, A4)'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #10 EXACT(A4,A4) result type mismatch:'); + CheckEquals(true, cell^.BoolValue, 'Formula #10 EXACT(A4,A4) result mismatch.'); + + // Cells with almost same Unicode strings, but different case + cell := FWorksheet.WriteFormula(0, 1, '=EXACT(A4, A5)'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #11 EXACT(A4,A5) result type mismatch:'); + CheckEquals(false, cell^.BoolValue, 'Formula #11 EXACT(A4,A5) result mismatch.'); + + // Error (#DIV/0!) in one cell + FWorksheet.WriteFormula(0, 1, '=EXACT(A6, A5)'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctError, 'Formula #12 EXACT(A6,A5) result type mismatch:'); + CheckEquals(true, cell^.ErrorValue = errDivideByZero, 'Formula #12 EXACT(A6,A5) result mismatch.'); + + // Compare numeric string with same number + FWorksheet.WriteFormula(0, 1, '=EXACT(12,"12")'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #13 EXACT(12,"12") result type mismatch:'); + CheckEquals(true, cell^.BoolValue, 'Formula #13 EXACT(12,"12") result mismatch.'); + + // dto with cells + FWorksheet.WriteFormula(0, 1, '=EXACT(A7,A8)'); + FWorksheet.CalcFormulas; + CheckEquals(true, cell^.ContentType = cctBool, 'Formula #14 EXACT(A7,A8) result type mismatch:'); + CheckEquals(true, cell^.BoolValue, 'Formula #14 EXACT(A7,A8) result mismatch.'); + +end; + +procedure TCalcTextFormulaTests.Test_LEN; +begin + FWorksheet.WriteText(0, 0, 'abc'); // A1 + FWorksheet.WriteText(1, 0, 'Äbγ'); // A2 + FWorksheet.WriteErrorValue(2, 0, errIllegalRef); // A3 + + // Literal ASCII string + FWorksheet.WriteFormula(0, 1, '=LEN("abc")'); + FWorksheet.CalcFormulas; + CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #1 LEN("abc") result mismatch'); + + // Literal Unicode string + FWorksheet.WriteFormula(0, 1, '=LEN("Äbγ")'); + FWorksheet.CalcFormulas; + CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #2 LEN("Äbc") result mismatch'); + + // Another Unicode string + FWorksheet.WriteFormula(0, 1, '=LEN("αβγδε")'); + FWorksheet.CalcFormulas; + CheckEquals(5, FWorksheet.ReadAsNumber(0, 1), 'Formula #3 LEN("αβγδε") result mismatch'); + + // Cell with ASCII string + FWorksheet.WriteFormula(0, 1, '=LEN(A1)'); + FWorksheet.CalcFormulas; + CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #4 LEN(A1) result mismatch'); + + // Cell with unicode string + FWorksheet.WriteFormula(0, 1, '=LEN(A2)'); + FWorksheet.CalcFormulas; + CheckEquals(3, FWorksheet.ReadAsNumber(0, 1), 'Formula #5 LEN(A2) result mismatch'); + + // Cell with error + FWorksheet.WriteFormula(0, 1, '=LEN(A3)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #6 LEN(A3) (#REF!) result mismatch'); + + // Empty cell + FWorksheet.WriteFormula(0, 1, '=LEN(A99)'); + FWorksheet.CalcFormulas; + CheckEquals(0, FWorksheet.ReadAsNumber(0, 1), 'Formula #7 LEN(A99) (empty cell) result mismatch'); +end; + +procedure TCalcTextFormulaTests.Test_LOWER; +begin + FWorksheet.WriteText(0, 0, 'abc'); // A1 + FWorksheet.WriteText(1, 0, 'Äbγδ'); // A2 + FWorksheet.WriteErrorValue(2, 0, errIllegalRef); // A3 + + // ASCII, already lower case + FWorksheet.WriteFormula(0, 1, '=LOWER("abc")'); + FWorksheet.CalcFormulas; + CheckEquals('abc', FWorksheet.ReadAsText(0, 1), 'Formula #1 LOWER("abc") result mismatch'); + + // ASCII, mixed upper/lower case + FWorksheet.WriteFormula(0, 1, '=LOWER("Abc")'); + FWorksheet.CalcFormulas; + CheckEquals('abc', FWorksheet.ReadAsText(0, 1), 'Formula #2 LOWER("Abc") result mismatch'); + + // Unicode, already lower case + FWorksheet.WriteFormula(0, 1, '=LOWER("äöü αβγ")'); + FWorksheet.CalcFormulas; + CheckEquals('äöü αβγ', FWorksheet.ReadAsText(0, 1), 'Formula #3 LOWER("äöü αβγ") result mismatch'); + + // Unicode, mixed upper/lower case + FWorksheet.WriteFormula(0, 1, '=LOWER("Äöü αβΓ")'); + FWorksheet.CalcFormulas; + CheckEquals('äöü αβγ', FWorksheet.ReadAsText(0, 1), 'Formula #4 LOWER("Äöü αβΓ") result mismatch'); + + // Mixed unicode, ASCII, number + FWorksheet.WriteFormula(0, 1, '=LOWER("Äöü αβΓ 123")'); + FWorksheet.CalcFormulas; + CheckEquals('äöü αβγ 123', FWorksheet.ReadAsText(0, 1), 'Formula #5 LOWER("Äöü αβΓ 123") result mismatch'); + + // Error in argument + FWorksheet.WriteFormula(0, 1, '=LOWER(#REF!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #6 LOWER(#REF!) result mismatch'); + + // Cell with error + FWorksheet.WriteFormula(0, 1, '=LOWER(A3)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #7 LOWER(A3) (#REF!) result mismatch'); + + // Empty cell + FWorksheet.WriteFormula(0, 1, '=LOWER(A99)'); + FWorksheet.CalcFormulas; + CheckEquals('', FWorksheet.ReadAsText(0, 1), 'Formula #8 LOWER(A9) (empty) result mismatch'); +end; + +procedure TCalcTextFormulaTests.Test_UPPER; +begin + FWorksheet.WriteText(0, 0, 'abc'); // A1 + FWorksheet.WriteText(1, 0, 'Äbγδ'); // A2 + FWorksheet.WriteErrorValue(2, 0, errIllegalRef); // A3 + + // ASCII, already upper case + FWorksheet.WriteFormula(0, 1, '=UPPER("ABC")'); + FWorksheet.CalcFormulas; + CheckEquals('ABC', FWorksheet.ReadAsText(0, 1), 'Formula #1 UPPER("ABC") result mismatch'); + + // ASCII, mixed upper/lower case + FWorksheet.WriteFormula(0, 1, '=UPPER("Abc")'); + FWorksheet.CalcFormulas; + CheckEquals('ABC', FWorksheet.ReadAsText(0, 1), 'Formula #2 UPPER("Abc") result mismatch'); + + // Unicode, already upper case + FWorksheet.WriteFormula(0, 1, '=UPPER("ÄÖÜ ΓΔΣ")'); + FWorksheet.CalcFormulas; + CheckEquals('ÄÖÜ ΓΔΣ', FWorksheet.ReadAsText(0, 1), 'Formula #3 UPPER("ÄÖÜ ΓΔΣ") result mismatch'); + + // Unicode, mixed upper/lower case + FWorksheet.WriteFormula(0, 1, '=UPPER("Äöü Γδσ")'); + FWorksheet.CalcFormulas; + CheckEquals('ÄÖÜ ΓΔΣ', FWorksheet.ReadAsText(0, 1), 'Formula #4 UPPER("Äöü Γδσ") result mismatch'); + + // Mixed unicode, ASCII, number + FWorksheet.WriteFormula(0, 1, '=UPPER("Äöü Γδσ 123")'); + FWorksheet.CalcFormulas; + CheckEquals('ÄÖÜ ΓΔΣ 123', FWorksheet.ReadAsText(0, 1), 'Formula #5 UPPER("Äöü Γδσ 123") result mismatch'); + + // Error in argument + FWorksheet.WriteFormula(0, 1, '=UPPER(#REF!)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #6 UPPER(#REF!) result mismatch'); + + // Cell with error + FWorksheet.WriteFormula(0, 1, '=UPPER(A3)'); + FWorksheet.CalcFormulas; + CheckEquals(STR_ERR_ILLEGAL_REF, FWorksheet.ReadAsText(0, 1), 'Formula #7 UPPER(A3) (#REF!) result mismatch'); + + // Empty cell + FWorksheet.WriteFormula(0, 1, '=UPPER(A99)'); + FWorksheet.CalcFormulas; + CheckEquals('', FWorksheet.ReadAsText(0, 1), 'Formula #8 UPPER(A9) (empty) result mismatch'); +end; + +