[SE] fixes processing input data in CountIfCache methods

This commit is contained in:
Aleksandr Nagaev
2026-01-20 10:44:50 +03:00
parent 65b2b1bd84
commit f2b7996279
3 changed files with 186 additions and 97 deletions

View File

@ -11430,7 +11430,7 @@ function parserFormula( formula, parent, _ws ) {
var matchingOperators = new RegExp("^(=|<>|<=|>=|<|>).*");
function matchingValue(oVal) {
function matchingValue(oVal, opt_callback) {
var res;
if (cElementType.string === oVal.type) {
var search, op;
@ -11443,7 +11443,9 @@ function parserFormula( formula, parent, _ws ) {
search = val;
op = null;
}
if (opt_callback) {
return {val: opt_callback(search), op: op};
}
var parseRes = AscCommon.g_oFormatParser.parse(search);
res = {val: parseRes ? new cNumber(parseRes.value) : new cString(search), op: op};
} else {

View File

@ -12167,6 +12167,7 @@ function (window, undefined) {
FormulaRangesCache.prototype.remove = function () {
};
function CountIfTypedCache() {
this.data = {};
}
@ -12285,6 +12286,21 @@ function (window, undefined) {
}
return i;
};
CountIfTypedCache.prototype.parseAnyNumber = function(value) {
let convertedToNumber = null;
if (AscCommon.g_oFormatParser.isLocaleNumber(value)) {
convertedToNumber = AscCommon.g_oFormatParser.parseLocaleNumber(value);
}
if (isNaN(convertedToNumber) || convertedToNumber === null) {
let convertedToNumber = AscCommon.g_oFormatParser.parse(value);
if (convertedToNumber) {
convertedToNumber = convertedToNumber.value;
return convertedToNumber;
}
return null;
}
return convertedToNumber;
};
CountIfTypedCache.prototype.forEachInTyped = function(range, type, matchingFunction, searchValue, convertToNumber) {
let count = 0;
const ws = range.getWS();
@ -12306,8 +12322,8 @@ function (window, undefined) {
const lastIndex = this.findHigherIndexInTyped(bbox.r2, typedIndexes);
if (convertToNumber) {
for (let j = firstIndex; j < lastIndex; j += 1) {
let value = AscCommon.g_oFormatParser.parseLocaleNumber(typedData[j]);
if (!isNaN(value)) {
let value = this.parseAnyNumber(typedData[j]);
if (value !== null) {
count += matchingFunction(value, searchValue);
}
}
@ -12420,6 +12436,78 @@ function (window, undefined) {
}
CountIfCache.prototype.constructor = CountIfCache;
CountIfCache.prototype.parseStringToCElement = function (val, cultureInfo) {
if (!cultureInfo) {
cultureInfo = AscCommon.g_oDefaultCultureInfo;
}
const cBoolLocal = AscCommon.cBoolLocal;
const cErrorLocal = AscCommon.cErrorLocal;
const cErrorOrigin = AscCommon.cErrorOrigin;
function checkCellValueTypeError(sUpText) {
switch (sUpText) {
case cErrorLocal["nil"]:
return cErrorOrigin["nil"];
case cErrorLocal["div"]:
return cErrorOrigin["div"];
case cErrorLocal["value"]:
return cErrorOrigin["value"];
case cErrorLocal["ref"]:
return cErrorOrigin["ref"];
case cErrorLocal["name"]:
case cErrorLocal["name"].replace('\\', ''):
return cErrorOrigin["name"];
case cErrorLocal["num"]:
return cErrorOrigin["num"];
case cErrorLocal["na"]:
return cErrorOrigin["na"];
case cErrorLocal["getdata"]:
return cErrorOrigin["getdata"];
case cErrorLocal["uf"]:
return cErrorOrigin["uf"];
case cErrorLocal["calc"]:
return cErrorOrigin["calc"];
case cErrorLocal["spill"]:
return cErrorOrigin["spill"];
case cErrorLocal["busy"]:
return cErrorOrigin["busy"];
}
return false;
}
if ("" === val) {
return new cString("");
}
if (AscCommon.g_oFormatParser.isLocaleNumber(val, cultureInfo)) {
const numberValue = AscCommon.g_oFormatParser.parseLocaleNumber(val, cultureInfo);
return new cNumber(numberValue);
}
const sUpText = val.toUpperCase();
if (cBoolLocal.t === sUpText || cBoolLocal.f === sUpText) {
return new cBool(cBoolLocal.t === sUpText);
}
if (sUpText === "TRUE" || sUpText === "FALSE") {
return new cBool(sUpText === "TRUE");
}
const errorValue = checkCellValueTypeError(sUpText);
if (errorValue) {
return new cError(errorValue);
}
const parseResult = AscCommon.g_oFormatParser.parse(val, cultureInfo);
if (null != parseResult) {
return new cNumber(parseResult.value);
}
return new cString(val);
};
CountIfCache.prototype.calculate = function (arg, _arg1) {
let arg0 = arg[0], arg1 = arg[1];
@ -12497,24 +12585,16 @@ function (window, undefined) {
CountIfCache.prototype._calculate = function (range, arg1) {
const ws = range.getWS();
let _count = 0;
let matchingInfo = AscCommonExcel.matchingValue(arg1);
let matchingInfo = AscCommonExcel.matchingValue(arg1, this.parseStringToCElement);
let type = matchingInfo.val.type;
let searchValue = matchingInfo.val;
if (type === cElementType.string) {
searchValue = searchValue.toString().toLowerCase();
} else if (type === cElementType.error) {
searchValue = searchValue.errorType;
} else {
searchValue = searchValue.value;
}
if (type === cElementType.error) {
searchValue = arg1.errorType;
}
if (type === cElementType.string) {
const checkErr = new cError(matchingInfo.val.value.toUpperCase());
if (checkErr.errorType !== -1) {
type = cElementType.error;
searchValue = checkErr.errorType;
}
}
if (searchValue === "") {
if (matchingInfo.op === "=" || matchingInfo.op === null) {
const bbox = range.getBBox0();
@ -12534,8 +12614,8 @@ function (window, undefined) {
const isWildcard = type === cElementType.string && (searchValue.indexOf('*') !== -1 || searchValue.indexOf('?') !== -1);
if ((matchingInfo.op === '=' || matchingInfo.op === null) && !isWildcard) {
if (type === cElementType.string) {
const convertedToNumber = AscCommon.g_oFormatParser.parseLocaleNumber(searchValue);
if (!isNaN(convertedToNumber)) {
const convertedToNumber = this.typedCache.parseAnyNumber(searchValue)
if (convertedToNumber !== null) {
searchValue = convertedToNumber;
type = cElementType.number;
}

View File

@ -9410,76 +9410,66 @@ $(function () {
ws.getRange2("CC8").setValue("");
AscCommonExcel.g_oCountIfCache.clean();
// Case #7: Area, Formula. Count TRUE values using TRUE() function
oParser = new parserFormula("COUNTIF(CC1:CC7, TRUE())", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 3);
// Case #8: Area, Boolean. Count TRUE values using boolean literal
oParser = new parserFormula("COUNTIF(CC1:CC7, TRUE)", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 3);
// Case #9: Area, Number. Count cells equal to 1
// Case #7: Area, Number. Count cells equal to 1
oParser = new parserFormula("COUNTIF(CC1:CC7, 1)", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 2);
// Case #10: Area, Number. Count cells equal to 0
// Case #8: Area, Number. Count cells equal to 0
oParser = new parserFormula("COUNTIF(CC1:CC7, 0)", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
// Case #11: Ref, String. Count text criteria in single cell (no match)
// Case #9: Ref, String. Count text criteria in single cell (no match)
ws.getRange2("CC8").setValue(">3");
oParser = new parserFormula("COUNTIF(CC8,\">3\")", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 0);
// Case #12: Ref, String. Count text criteria in single cell with equals prefix
// Case #10: Ref, String. Count text criteria in single cell with equals prefix
ws.getRange2("CC8").setValue(">3");
oParser = new parserFormula("COUNTIF(CC8,\"=>3\")", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
// Case #13: Area, String. Count error values using string representation
// Case #11: Area, String. Count error values using string representation
ws.getRange2("CC9").setValue("=NA()");
ws.getRange2("CC10").setValue("#N/A");
oParser = new parserFormula("COUNTIF(CC9:CC10,\"#N/A\")", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 2);
// Case #14: Area, Formula. Count error values using NA() function
// Case #12: Area, Formula. Count error values using NA() function
oParser = new parserFormula("COUNTIF(CC9:CC10, NA())", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 2);
// Case #15: Area, String. Count formula text (no match for function call)
// Case #13: Area, String. Count formula text (no match for function call)
oParser = new parserFormula("COUNTIF(CC9:CC10,\"=NA()\")", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 0);
// Case #16: Area, String. Count numbers greater than or equal to 1
// Case #14: Area, String. Count numbers greater than or equal to 1
oParser = new parserFormula("COUNTIF(CC1:CC8,\">=1\")", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 2);
// Case #17: Area, String. Count numbers equal to 1
// Case #15: Area, String. Count numbers equal to 1
oParser = new parserFormula("COUNTIF(CC1:CC8,\"=1\")", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 2);
// Case #18: Area, String. Count numbers less than 1
// Case #16: Area, String. Count numbers less than 1
oParser = new parserFormula("COUNTIF(CC1:CC8,\"<1\")", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
// Case #19: Area, String. Count numbers greater than 1
// Case #17: Area, String. Count numbers greater than 1
oParser = new parserFormula("COUNTIF(CC1:CC8,\">1\")", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 0);
// Case #20: Area, String. Count using dynamic criteria with cell reference
// Case #18: Area, String. Count using dynamic criteria with cell reference
oParser = new parserFormula("COUNTIF(CC1:CC8,\"=\"&CC8)", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
@ -9494,37 +9484,37 @@ $(function () {
ws.getRange2("A27").setValue("apples");
AscCommonExcel.g_oCountIfCache.clean();
// Case #21: Area, String. Count text ending with pattern using wildcard
// Case #19: Area, String. Count text ending with pattern using wildcard
oParser = new parserFormula('COUNTIF(A22:A27,"*es")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 4);
// Case #22: Area, String. Count text with exact length ending with pattern
// Case #20: Area, String. Count text with exact length ending with pattern
oParser = new parserFormula('COUNTIF(A22:A27,"?????es")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 2);
// Case #23: Area, String. Count all non-empty text cells using wildcard
// Case #21: Area, String. Count all non-empty text cells using wildcard
oParser = new parserFormula('COUNTIF(A22:A27,"*")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 4);
// Case #24: Area, String. Count cells not equal to literal asterisks
// Case #22: Area, String. Count cells not equal to literal asterisks
oParser = new parserFormula('COUNTIF(A22:A27,"<>"&"***")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 2);
// Case #25: Area, String. Count cells not equal to single asterisk
// Case #23: Area, String. Count cells not equal to single asterisk
oParser = new parserFormula('COUNTIF(A22:A27,"<>"&"*")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 2);
// Case #26: Area, String. Count cells not equal to single question mark
// Case #24: Area, String. Count cells not equal to single question mark
oParser = new parserFormula('COUNTIF(A22:A27,"<>"&"?")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 6);
// Case #27: Area, String. Count exact date string match
// Case #25: Area, String. Count exact date string match
ws.getRange2("A1").setValue("12/1");
ws.getRange2("A2").setValue("12/1");
AscCommonExcel.g_oCountIfCache.clean();
@ -9532,7 +9522,7 @@ $(function () {
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 2);
// Case #28: Area, String. Count date string with no match
// Case #26: Area, String. Count date string with no match
oParser = new parserFormula('COUNTIF(A1:A2,"12/1/1")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 0);
@ -9551,12 +9541,12 @@ $(function () {
ws.getRange2("B105").setValue("55");
AscCommonExcel.g_oCountIfCache.clean();
// Case #32: Formula, String. Count values greater than 80 in XLOOKUP result (Math). For bug 62491
// Case #27: Formula, String. Count values greater than 80 in XLOOKUP result (Math). For bug 62491
oParser = new parserFormula('COUNTIF(XLOOKUP(A100,A100:B100,A101:B105),">80")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 2);
// Case #33: Formula, String. Count values greater than 80 in XLOOKUP result (Physics)
// Case #28: Formula, String. Count values greater than 80 in XLOOKUP result (Physics)
oParser = new parserFormula('COUNTIF(XLOOKUP(B100,A100:B100,A101:B105),">80")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
@ -9577,12 +9567,6 @@ $(function () {
ws.getRange2("B104").setValue("23");
ws.getRange2("B105").setValue("55");
ws.getRange2("A201").setValue("123");
ws.getRange2("A204").setValue("#N/A");
ws.getRange2("B205").setValue("asd");
ws.getRange2("B206").setValue("123");
ws.getRange2("B207").setValue("ASD");
ws.getRange2("A300").setValue("a*c");
ws.getRange2("A301").setValue("aac");
ws.getRange2("A302").setValue("a123c");
@ -9685,56 +9669,49 @@ $(function () {
ws2.getRange2("A18").setValue("0.8"); // TestNameArea3D2
ws2.getRange2("B18").setValue("0.8"); // TestNameArea3D2
ws.getRange2("A200").setValue("");
ws.getRange2("A201").setValue("123");
ws.getRange2("A204").setValue("#N/A");
ws.getRange2("B205").setValue("asd");
ws.getRange2("B206").setValue("123");
ws.getRange2("B207").setValue("ASD");
ws.getRange2("A200").setValue("");
ws.getRange2("A202").setValue("");
ws.getRange2("A203").setValue("");
ws.getRange2("A204").setValue("#N/A");
ws.getRange2("A205").setValue("");
ws.getRange2("B200").setValue("");
ws.getRange2("B201").setValue(" ");
ws.getRange2("B202").setValue("");
ws.getRange2("B203").setValue("");
ws.getRange2("B204").setValue("");
ws.getRange2("B205").setValue("asd");
ws.getRange2("B206").setValue('123');
ws.getRange2("B207").setValue('ASD');
AscCommonExcel.g_oCountIfCache.clean();
// Case #40: Area, String. Empty cells check
// Case #29: Area, String. Empty cells check
oParser = new parserFormula('COUNTIF(A200:B205,"<>"&"*")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 10);
// Case #41: Area, String. Find empty cells check
// Case #30: Area, String. Find empty cells check
oParser = new parserFormula('COUNTIF(A200:B205,"")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 8);
// Case #42: Area, Ref. second arg as cell
// Case #31: Area, Ref. second arg as cell
oParser = new parserFormula('COUNTIF(A200:B205,B206)', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
// Case #43: Area, Ref. second arg as cell, case-sens test
// Case #32: Area, Ref. second arg as cell, case-sens test
oParser = new parserFormula('COUNTIF(A200:B205,B207)', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
// Case #44: Area, String. second arg as cell, case-sens test
// Case #33: Area, String. second arg as cell, case-sens test
oParser = new parserFormula('COUNTIF(A200:B205,"#n/A")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
ws.getRange2("A300").setValue("a*c");
ws.getRange2("A301").setValue("aac");
ws.getRange2("A302").setValue("a123c");
ws.getRange2("A303").setValue("a**c");
ws.getRange2("A304").setValue("");
ws.getRange2("A305").setValue("");
AscCommonExcel.g_oCountIfCache.clean();
// Case #45: Area, String. wildcard test with ~
// Case #34: Area, String. wildcard test with ~
oParser = new parserFormula('COUNTIF(A300:A305,"a~*c")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
@ -9747,7 +9724,7 @@ $(function () {
AscCommonExcel.g_oCountIfCache.clean();
const currentSheet = ws.getName();
// Case #46: Area3D, Ref3D. Ref3D and Ared3D test
// Case #35: Area3D, Ref3D. Ref3D and Ared3D test
oParser = new parserFormula('COUNTIF(' + currentSheet + '!A311:A314,' + currentSheet + '!A315)', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
@ -9759,7 +9736,7 @@ $(function () {
ws.getRange2("A310").setValue(">a");
AscCommonExcel.g_oCountIfCache.clean();
// Case #47: Area, Ref. diactric signs tests
// Case #36: Area, Ref. diactric signs tests
oParser = new parserFormula('COUNTIF(A306:A309,A310)', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 2);
@ -9771,12 +9748,12 @@ $(function () {
ws.getRange2("A320").setValue(">a");
AscCommonExcel.g_oCountIfCache.clean();
// Case #48: Area, Ref. Hieroglyphs test
// Case #37: Area, Ref. Hieroglyphs test
oParser = new parserFormula('COUNTIF(A316:A319,A320)', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
// Case #49: Area, Formula. Formula test
// Case #38: Area, Formula. Formula test
oParser = new parserFormula('COUNTIF(A311:A314,2+1)', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
@ -9787,7 +9764,7 @@ $(function () {
wb.editDefinesNames(null, defName3D);
wb.editDefinesNames(null, defNameArea3D);
// Case #50: Name3D, Name3D. DefName test
// Case #39: Name3D, Name3D. DefName test
oParser = new parserFormula('COUNTIF(COUNTIFTestNameArea3D,COUNTIFTestName3D)', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
@ -9796,7 +9773,7 @@ $(function () {
wb.delDefinesNames(defName3D);
wb.delDefinesNames(defNameArea3D);
// Case #51: Area, Area.
// Case #40: Area, Area.
oParser = new parserFormula('COUNTIF(A311:A314,A311:A314)', "C2", ws);
assert.ok(oParser.parse());
array = oParser.calculate();
@ -9804,7 +9781,7 @@ $(function () {
assert.strictEqual(array.getElementRowCol(1,0).getValue(), 1, "Result of COUNTIF(A311:A314,A311:A314)[1,0]");
assert.strictEqual(array.getElementRowCol(1,0).getValue(), 1, "Result of COUNTIF(A311:A314,A311:A314)[1,0]");
// Case #52: Area, Array.
// Case #41: Area, Array.
oParser = new parserFormula('COUNTIF(A311:A314,{1,2,3})', "C2", ws);
assert.ok(oParser.parse());
array = oParser.calculate();
@ -9812,6 +9789,52 @@ $(function () {
assert.strictEqual(array.getElementRowCol(0,1).getValue(), 1, "Result of COUNTIF(A311:A314,A311:A314)[0,1]");
assert.strictEqual(array.getElementRowCol(0,2).getValue(), 1, "Result of COUNTIF(A311:A314,A311:A314)[0,2]");
// Case #42: Area, String. Count TRUE values using string "TRUE"
oParser = new parserFormula('COUNTIF(CC1:CC7, "TRUE")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 3);
// Case #43: Area, String. Count FALSE values using string "FALSE"
oParser = new parserFormula('COUNTIF(CC1:CC7, "FALSE")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 0);
// Case #44: Area, String. Count TRUE values using string "tr"&"ue" (lowercase)
oParser = new parserFormula('COUNTIF(CC1:CC7, "tr"&"ue")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 3);
// Case #45: Area, String. Count FALSE values using string "false" (lowercase)
oParser = new parserFormula('COUNTIF(CC1:CC7, "false")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 0);
// Case #46: Prepare FALSE values for testing
ws.getRange2("CC13").setValue("0");
ws.getRange2("CC14").setValue("FALSE");
ws.getRange2("CC15").setValue("'false'");
AscCommonExcel.g_oCountIfCache.clean();
// Case #47: Area, Boolean. Count FALSE values using boolean literal
oParser = new parserFormula("COUNTIF(CC13:CC15, FALSE)", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
// Case #48: Area, Formula. Count FALSE values using FALSE() function
oParser = new parserFormula("COUNTIF(CC13:CC17, FALSE())", "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
// Case #49: Area, String. Count FALSE values using string "FALSE"
oParser = new parserFormula('COUNTIF(CC13:CC17, "FALSE")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
// Case #50: Area, String. Count FALSE values using string "fa"&"lse" (lowercase)
oParser = new parserFormula('COUNTIF(CC13:CC17, "fa"&"lse")', "C2", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 1);
// TODO Tables
// TODO 3D args handle
@ -9853,10 +9876,6 @@ $(function () {
// Bounded Cases:
// Case #1: Area, String. Count errors greater than #N/A
ws.getRange2("AB1").setValue("#N/A");
ws.getRange2("AB2").setValue("#DIV/0!");
ws.getRange2("AB3").setValue("#VALUE!");
ws.getRange2("AB4").setValue("5");
AscCommonExcel.g_oCountIfCache.clean();
oParser = new parserFormula('COUNTIF(AB1:AB4,">#N/A")', "AC1", ws);
assert.ok(oParser.parse());
@ -9878,30 +9897,18 @@ $(function () {
assert.strictEqual(oParser.calculate().getValue(), 2);
// Case #5: Area, String. Count values greater than error boundary
ws.getRange2("AD1").setValue("#N/A");
ws.getRange2("AD2").setValue("10");
ws.getRange2("AD3").setValue("20");
ws.getRange2("AD4").setValue("text");
AscCommonExcel.g_oCountIfCache.clean();
oParser = new parserFormula('COUNTIF(AD1:AD4,"<#N/A")', "AC6", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 0);
// Case #6: Area, String. Count specific error type in mixed range
ws.getRange2("AE1").setValue("#N/A");
ws.getRange2("AE2").setValue("#DIV/0!");
ws.getRange2("AE3").setValue("#N/A");
ws.getRange2("AE4").setValue("42");
AscCommonExcel.g_oCountIfCache.clean();
oParser = new parserFormula('COUNTIF(AE1:AE4,"=#N/A")', "AC7", ws);
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), 2);
// Case #7: Area, String. Count specific error type in mixed range
ws.getRange2("AF1").setValue("#VALUE!");
ws.getRange2("AF2").setValue("#DIV/0!");
ws.getRange2("AF3").setValue("#VALUE!");
ws.getRange2("AF4").setValue("42");
AscCommonExcel.g_oCountIfCache.clean();
oParser = new parserFormula('COUNTIF(AF1:AF4,"<#N/A")', "AC7", ws);
assert.ok(oParser.parse());