name:
src/Formulas/Info.ts
-rw-r--r--
11688
1import {
2 ArgsChecker
3} from "../Utilities/ArgsChecker";
4import {
5 NAError, NullError, DivZeroError, ValueError, RefError, NameError, NumError, NULL_ERROR, DIV_ZERO_ERROR, VALUE_ERROR,
6 REF_ERROR, NAME_ERROR, NUM_ERROR, NA_ERROR
7} from "../Errors";
8import {
9 TypeConverter
10} from "../Utilities/TypeConverter";
11import {
12 Cell
13} from "../Cell";
14import {Filter} from "../Utilities/Filter";
15
16
17/**
18 * Returns the "value not available" error, "#N/A".
19 * @constructor
20 */
21let NA = function () {
22 ArgsChecker.checkLength(arguments, 0, "NA");
23 throw new NAError("NA Error thrown.");
24};
25
26
27/**
28 * Returns true if a value is text.
29 * @param value - value or reference to check.
30 * @returns {boolean}.
31 * @constructor
32 */
33let ISTEXT = function (value) {
34 ArgsChecker.checkLength(arguments, 1, "ISTEXT");
35 return typeof TypeConverter.firstValue(value) === "string";
36};
37
38
39/**
40 * Returns true if a value is not text.
41 * @param value - value or reference to check.
42 * @returns {boolean}.
43 * @constructor
44 */
45let ISNONTEXT = function (value) {
46 ArgsChecker.checkLength(arguments, 1, "ISNONTEXT");
47 return typeof TypeConverter.firstValue(value) !== "string";
48};
49
50
51/**
52 * Returns true if value is a boolean (FALSE, or TRUE). Numerical and text values return false.
53 * @param value - value or reference to check.
54 * @returns {boolean}
55 * @constructor
56 */
57let ISLOGICAL = function (value) {
58 ArgsChecker.checkLength(arguments, 1, "ISLOGICAL");
59 return typeof TypeConverter.firstValue(value) === "boolean";
60};
61
62
63/**
64 * Returns true if value or reference is a number.
65 * @param value - value or reference to check.
66 * @returns {boolean}
67 * @constructor
68 */
69let ISNUMBER = function (value) {
70 ArgsChecker.checkLength(arguments, 1, "ISNUMBER");
71 return typeof TypeConverter.firstValue(value) === "number";
72};
73
74
75/**
76 * Returns true if input is a valid email. Valid domains are Original top-level domains and Country code top-level
77 * domains.
78 * @param value - Value to check whether it is an email or not.
79 * @returns {boolean}
80 * @constructor
81 */
82let ISEMAIL = function (value) {
83 ArgsChecker.checkLength(arguments, 1, "ISEMAIL");
84 if (typeof value !== "string") {
85 return false;
86 }
87 const EMAIL_REGEX = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|com|org|net|gov|mil|edu|int|biz|info|mobi|name|aero|jobs|museum|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bl|bm|bn|bo|bq|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mf|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)\b/;
88 return EMAIL_REGEX.test(TypeConverter.firstValueAsString(value));
89};
90
91
92/**
93 * Returns true if the input is a valid URL.
94 * @param value - Value to check
95 * @returns {boolean}
96 * @constructor
97 */
98let ISURL = function (value) {
99 ArgsChecker.checkLength(arguments, 1, "ISURL");
100 value = TypeConverter.firstValueAsString(value);
101 let matches = value.match(/(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/);
102 if (/[^a-z0-9\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=\.\-\_\~\%]/i.test(value)) {
103 return false;
104 }
105 if (/%[^0-9a-f]/i.test(value)) {
106 return false;
107 }
108 if (/%[0-9a-f](:?[^0-9a-f]|$)/i.test(value)) {
109 return false;
110 }
111 let authority = matches[2];
112 let path = matches[3];
113 if (!(path.length >= 0)) {
114 return false;
115 }
116 if (authority && authority.length) {
117 if (!(path.length === 0 || /^\//.test(path))) {
118 return false;
119 }
120 } else {
121 if (/^\/\//.test(path)) {
122 return false;
123 }
124 }
125 return true;
126};
127
128/**
129 * Returns the value as a number.
130 * @param value - value to return.
131 * @returns {number}
132 * @constructor
133 */
134let N = function (value) {
135 ArgsChecker.checkLength(arguments, 1, "N");
136 return TypeConverter.firstValueAsNumber(value);
137};
138
139
140/**
141 * Tests if the content of one or several cells is a reference. Verifies the type of references in a cell or a range of
142 * cells. If an error occurs, the function returns a logical or numerical value.
143 * @param value - The value to be tested, to determine whether it is a reference.
144 * @returns {boolean}
145 * @constructor
146 */
147let ISREF = function (value) {
148 ArgsChecker.checkLength(arguments, 1, "ISREF");
149 return TypeConverter.firstValue(value) instanceof Cell;
150};
151
152
153/**
154 * Returns the number corresponding to an error value occurring in a different cell. With the aid of this number, an
155 * error message text can be generated. If an error occurs, the function returns a logical or numerical value.
156 * @param value - Contains either the address/reference of the cell in which the error occurs, or the error directly.
157 * Eg: `=ERRORTYPE(NA())`
158 * @constructor
159 */
160let ERRORTYPE = function (value) {
161 ArgsChecker.checkLength(arguments, 1, "ERRORTYPE");
162 try {
163 value = TypeConverter.firstValue(value);
164 } catch (e) {
165 value = e;
166 }
167 if (value instanceof Cell) {
168 if (value.hasError()) {
169 value = value.getError();
170 } else {
171 throw new NAError("Function ERROR.TYPE parameter 1 value is not an error.");
172 }
173 }
174 if (value instanceof Error) {
175 switch (value.name) {
176 case NULL_ERROR:
177 return 1;
178 case DIV_ZERO_ERROR:
179 return 2;
180 case VALUE_ERROR:
181 return 3;
182 case REF_ERROR:
183 return 4;
184 case NAME_ERROR:
185 return 5;
186 case NUM_ERROR:
187 return 6;
188 case NA_ERROR:
189 return 7;
190 default:
191 return 8;
192 }
193 } else {
194 throw new NAError("Function ERROR.TYPE parameter 1 value is not an error.");
195 }
196};
197
198
199/**
200 * Returns TRUE if the reference to a cell is blank. This function is used to determine if the content of a cell is
201 * empty. A cell with a formula inside is not empty. If an error occurs, the function returns a logical or numerical
202 * value.
203 * @param value - The content to be tested.
204 * @returns {boolean}
205 * @constructor
206 */
207let ISBLANK = function (value) {
208 ArgsChecker.checkLength(arguments, 1, "ISBLANK");
209 if (value instanceof Cell) {
210 return value.isBlank();
211 }
212 return value === undefined;
213};
214
215
216/**
217 * Returns TRUE if the value refers to any error value except #N/A. You can use this function to control error values
218 * in certain cells. If an error occurs, the function returns a logical or numerical value.
219 * @param value - Any value or expression in which a test is performed to determine whether an error value not equal to
220 * #N/A is present.
221 * @returns {boolean}
222 * @constructor
223 */
224let ISERR = function (value) {
225 ArgsChecker.checkLength(arguments, 1, "ISERR");
226 try {
227 value = TypeConverter.firstValue(value);
228 } catch (e) {
229 return true;
230 }
231 if (value instanceof Cell) {
232 if (value.hasError()) {
233 return value.getError().name !== NA_ERROR;
234 }
235 return false;
236 }
237 if (value instanceof Error) {
238 return value.name !== NA_ERROR;
239 }
240 return false;
241};
242
243/**
244 * Tests if the cells contain general error values. ISERROR recognizes the #N/A error value. If an error occurs, the
245 * function returns a logical or numerical value.
246 * @param value - is any value where a test is performed to determine whether it is an error value.
247 * @returns {boolean}
248 * @constructor
249 */
250let ISERROR = function (value) {
251 ArgsChecker.checkLength(arguments, 1, "ISERROR");
252 try {
253 value = TypeConverter.firstValue(value);
254 } catch (e) {
255 return true;
256 }
257 if (value instanceof Cell) {
258 return value.hasError();
259 }
260 return (value instanceof Error);
261};
262
263
264/**
265 * Returns TRUE if a cell contains the #N/A (value not available) error value. If an error occurs, the function returns
266 * a logical or numerical value.
267 * @param value - The value or expression to be tested.
268 * @returns {boolean}
269 * @constructor
270 */
271let ISNA = function (value) {
272 ArgsChecker.checkLength(arguments, 1, "ISNA");
273 try {
274 value = TypeConverter.firstValue(value);
275 } catch (e) {
276 return false;
277 }
278 if (value instanceof Cell) {
279 if (value.hasError()) {
280 return value.getError().name === NA_ERROR;
281 }
282 }
283 if (value instanceof Error) {
284 return value.name === NA_ERROR;
285 }
286 return false;
287};
288
289
290/**
291 * Returns the first argument if no error value is present, otherwise returns the second argument if provided, or a
292 * blank if the second argument is absent. Blank value is `null`.
293 * @param value - Value to check for error.
294 * @param valueIfError - [OPTIONAL] - Value to return if no error is present in the first argument.
295 * @returns {any}
296 * @constructor
297 */
298let IFERROR = function (value, valueIfError?) {
299 valueIfError = valueIfError || null;
300 ArgsChecker.checkLengthWithin(arguments, 1, 2, "IFERROR");
301 if (value instanceof Cell) {
302 if (value.hasError()) {
303 return valueIfError;
304 }
305 return value;
306 }
307 if (ISERROR(value)) {
308 return valueIfError;
309 }
310 return value;
311};
312
313
314/**
315 * Returns a number corresponding to the type of data passed into the function. 1 = number, 2 = text, 4 = boolean,
316 * 16 = error, 64 = array/range, 128 = any other type of cell.
317 * @param value - Value for which the type will be determined.
318 * @returns {number}
319 * @constructor
320 */
321let TYPE = function (value) {
322 ArgsChecker.checkLengthWithin(arguments, 1, 2, "TYPE");
323 if (value instanceof Cell) {
324 if (value.hasError()) {
325 return 16;
326 }
327 value = value.getValue();
328 }
329 if (value === null) {
330 return 1;
331 }
332 if (typeof value === "number") {
333 return 1;
334 }
335 if (typeof value === "string") {
336 return 2;
337 }
338 if (typeof value === "boolean") {
339 return 4;
340 }
341 if (value instanceof Error) {
342 return 16;
343 }
344 if (value instanceof Array) {
345 return 64;
346 }
347 return 128;
348};
349
350
351/**
352 * Returns the column number of a specified cell, starting with column 1 for A.
353 * @param cell - Cell, defaults to the cell calling this formula, when used in the context of a spreadsheet.
354 * @constructor
355 */
356let COLUMN = function (cell) {
357 ArgsChecker.checkLength(arguments, 1, "COLUMN");
358 if (!(cell instanceof Cell)) {
359 throw new NAError("Argument must be a range or reference.");
360 }
361 return cell.getColumn() + 1;
362};
363
364
365/**
366 * Returns the row number of a specified cell, starting with row 1 for A1.
367 * @param cell - Cell, defaults to the cell calling this formula, when used in the context of a spreadsheet.
368 * @constructor
369 */
370let ROW = function (cell) {
371 ArgsChecker.checkLength(arguments, 1, "ROW");
372 if (!(cell instanceof Cell)) {
373 throw new NAError("Argument must be a range or reference.");
374 }
375 return cell.getRow() + 1;
376};
377
378
379/**
380 * Returns TRUE if a cell is a formula cell. Must be given a reference.
381 * @param value - To check.
382 * @returns {boolean}
383 * @constructor
384 */
385let ISFORMULA = function (value) {
386 ArgsChecker.checkLength(arguments, 1, "ISFORMULA");
387 if (value instanceof Array) {
388 if (value.length === 0) {
389 throw new RefError("Reference does not exist.");
390 }
391 }
392 if (!(value instanceof Cell)) {
393 throw new NAError("Argument must be a range");
394 }
395 return value.hasFormula();
396};
397
398
399export {
400 NA,
401 ISTEXT,
402 ISLOGICAL,
403 ISNUMBER,
404 ISNONTEXT,
405 ISEMAIL,
406 ISURL,
407 N,
408 ISREF,
409 ERRORTYPE,
410 ISBLANK,
411 ISERR,
412 ISERROR,
413 ISNA,
414 IFERROR,
415 TYPE,
416 COLUMN,
417 ROW,
418 ISFORMULA
419}