spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← All files
name: src/Utilities/CriteriaFunctionFactory.ts
-rw-r--r--
3435
 1/**
 2 * Converts wild-card style expressions (in which * matches zero or more characters, and ? matches exactly one character)
 3 * to regular expressions. * and ? can be escaped by prefixing with ~.
 4 * For future reference, something like this might be better
 5 * http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex.
 6 * @param c input
 7 * @returns {RegExp} resulting regex
 8 */
 9function wildCardRegex(c: string) {
10  let a = c.split("~?");
11  for (let i = 0; i < a.length; i++) {
12    a[i] = a[i].split("?").join(".{1}");
13  }
14  let b = a.join("\\\?");
15  let d = b.split("~*");
16  for (let i = 0; i < d.length; i++) {
17    d[i] = d[i].split("*").join(".*");
18  }
19  return new RegExp("^"+d.join(".*")+"$", "g");
20}
21
22
23
24
25/**
26 * Creates a criteria function to evaluate elements in a range in an *IF function.
27 */
28class CriteriaFunctionFactory {
29  /**
30   * If the criteria is a number, use strict equality checking.
31   * If the criteria is a string, check to see if it is a comparator.
32   * If the criteria is a string, and it is not a comparator, check for regex.
33   * If the criteria is a string and has not matched the above, finally use strict equality checking as a fallback.
34   * If the criteria has not been set, default to false-returning criteria function.
35   * @param criteria
36   * @returns {(x:any)=>boolean}
37   */
38  static createCriteriaFunction(criteria: string) : Function {
39    // Default criteria does nothing
40    let criteriaEvaluation = function (x) : boolean {
41      return false;
42    };
43
44    if (typeof criteria === "number" || typeof criteria === "boolean") {
45      criteriaEvaluation = function (x) : boolean {
46        return x === criteria;
47      };
48    } else if (typeof criteria === "string") {
49      let comparisonMatches = criteria.match(/^\s*(<=|>=|=|<>|>|<)\s*(-)?\s*(\$)?\s*([0-9]+([,.][0-9]+)?)\s*$/);
50      if (comparisonMatches !== null && comparisonMatches.length >= 6 && comparisonMatches[4] !== undefined) {
51        criteriaEvaluation = function (x) : boolean {
52          return eval(x + comparisonMatches[1] + (comparisonMatches[2] === undefined ? "" : "-") +  comparisonMatches[4]);
53        };
54        if (comparisonMatches[1] === "=") {
55          criteriaEvaluation = function (x) : boolean {
56            return eval(x + "===" + (comparisonMatches[2] === undefined ? "" : "-") +  comparisonMatches[4]);
57          };
58        }
59        if (comparisonMatches[1] === "<>") {
60          criteriaEvaluation = function (x) : boolean {
61            return eval(x + "!==" + (comparisonMatches[2] === undefined ? "" : "-") +  comparisonMatches[4]);
62          };
63        }
64      } else if (criteria.match(/\*|\~\*|\?|\~\?/) !== null) {
65        // Regular string
66        let matches = criteria.match(/\*|\~\*|\?|\~\?/);
67        if (matches !== null) {
68          criteriaEvaluation = function (x) : boolean {
69            try {
70              // http://stackoverflow.com/questions/26246601/wildcard-string-comparison-in-javascript
71              return wildCardRegex(criteria).test(x);
72            } catch (e) {
73              return false;
74            }
75          };
76        } else {
77          criteriaEvaluation = function (x) : boolean {
78            return x === criteria;
79          };
80        }
81      } else {
82        criteriaEvaluation = function (x) : boolean {
83          return x === criteria;
84        };
85      }
86    }
87    return criteriaEvaluation;
88  }
89}
90
91export {
92  CriteriaFunctionFactory
93}