@trebco/treb 28.11.1 → 28.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/treb-spreadsheet-light.mjs +11 -11
- package/dist/treb-spreadsheet.mjs +11 -11
- package/dist/treb.d.ts +27 -3
- package/package.json +1 -1
- package/treb-base-types/src/style.ts +3 -0
- package/treb-calculator/src/calculator.ts +235 -68
- package/treb-calculator/src/descriptors.ts +5 -0
- package/treb-calculator/src/expression-calculator.ts +9 -5
- package/treb-calculator/src/functions/base-functions.ts +410 -21
- package/treb-calculator/src/functions/text-functions.ts +45 -55
- package/treb-calculator/src/primitives.ts +11 -0
- package/treb-calculator/src/utilities.ts +55 -0
- package/treb-embed/markup/layout.html +15 -10
- package/treb-embed/markup/toolbar.html +5 -5
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +38 -2
- package/treb-embed/src/embedded-spreadsheet.ts +227 -29
- package/treb-embed/src/options.ts +5 -0
- package/treb-embed/style/dark-theme.scss +1 -0
- package/treb-embed/style/formula-bar.scss +20 -7
- package/treb-embed/style/theme-defaults.scss +20 -0
- package/treb-export/src/export-worker/export-worker.ts +1 -0
- package/treb-export/src/export2.ts +6 -1
- package/treb-export/src/import2.ts +76 -6
- package/treb-export/src/shared-strings2.ts +1 -1
- package/treb-export/src/workbook-style2.ts +89 -52
- package/treb-export/src/workbook2.ts +119 -1
- package/treb-grid/src/editors/editor.ts +7 -0
- package/treb-grid/src/editors/formula_bar.ts +23 -1
- package/treb-grid/src/render/tile_renderer.ts +46 -3
- package/treb-grid/src/types/annotation.ts +17 -3
- package/treb-grid/src/types/grid.ts +28 -9
- package/treb-grid/src/types/grid_base.ts +10 -105
- package/treb-grid/src/types/grid_options.ts +3 -2
- package/treb-grid/src/types/named_range.ts +8 -1
- package/treb-grid/src/types/serialize_options.ts +5 -0
- package/treb-parser/src/parser-types.ts +27 -4
- package/treb-parser/src/parser.ts +74 -36
package/dist/treb.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! API v28.
|
|
1
|
+
/*! API v28.15. Copyright 2018-2024 trebco, llc. All rights reserved. LGPL: https://treb.app/license */
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* add our tag to the map
|
|
@@ -756,6 +756,9 @@ export declare class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
756
756
|
/**
|
|
757
757
|
* Create a macro function.
|
|
758
758
|
*
|
|
759
|
+
* FIXME: this needs a control for argument separator, like other
|
|
760
|
+
* functions that use formulas (@see SetRange)
|
|
761
|
+
*
|
|
759
762
|
* @public
|
|
760
763
|
*/
|
|
761
764
|
DefineFunction(name: string, argument_names?: string | string[], function_def?: string): void;
|
|
@@ -1074,7 +1077,7 @@ export interface FreezePane {
|
|
|
1074
1077
|
rows: number;
|
|
1075
1078
|
columns: number;
|
|
1076
1079
|
}
|
|
1077
|
-
export type AnnotationType = 'treb-chart' | 'image' | 'external';
|
|
1080
|
+
export type AnnotationType = 'treb-chart' | 'image' | 'textbox' | 'external';
|
|
1078
1081
|
export declare type BorderConstants = "none" | "all" | "outside" | "top" | "bottom" | "left" | "right";
|
|
1079
1082
|
|
|
1080
1083
|
/**
|
|
@@ -1105,6 +1108,11 @@ export interface SerializeOptions {
|
|
|
1105
1108
|
|
|
1106
1109
|
/** share resources (images, for now) to prevent writing data URIs more than once */
|
|
1107
1110
|
share_resources?: boolean;
|
|
1111
|
+
|
|
1112
|
+
/**
|
|
1113
|
+
* if a function has an export() handler, call that
|
|
1114
|
+
*/
|
|
1115
|
+
export_functions?: boolean;
|
|
1108
1116
|
}
|
|
1109
1117
|
|
|
1110
1118
|
/**
|
|
@@ -1266,6 +1274,9 @@ export interface CellStyle {
|
|
|
1266
1274
|
/** border color */
|
|
1267
1275
|
border_bottom_fill?: Color;
|
|
1268
1276
|
|
|
1277
|
+
/** text indent */
|
|
1278
|
+
indent?: number;
|
|
1279
|
+
|
|
1269
1280
|
/**
|
|
1270
1281
|
* cell is locked for editing
|
|
1271
1282
|
*/
|
|
@@ -1797,7 +1808,7 @@ export interface SerializedGridSelection {
|
|
|
1797
1808
|
/** for cacheing addtional selections. optimally don't serialize */
|
|
1798
1809
|
rendered?: boolean;
|
|
1799
1810
|
}
|
|
1800
|
-
export type AnnotationData = AnnotationChartData | AnnotationImageData | AnnotationExternalData;
|
|
1811
|
+
export type AnnotationData = AnnotationChartData | AnnotationImageData | AnnotationExternalData | AnnotationTextBoxData;
|
|
1801
1812
|
export interface ImageSize {
|
|
1802
1813
|
width: number;
|
|
1803
1814
|
height: number;
|
|
@@ -1880,6 +1891,19 @@ export interface AnnotationImageData extends AnnotationDataBase {
|
|
|
1880
1891
|
export interface AnnotationChartData extends AnnotationDataBase {
|
|
1881
1892
|
type: 'treb-chart';
|
|
1882
1893
|
}
|
|
1894
|
+
export interface AnnotationTextBoxData extends AnnotationDataBase {
|
|
1895
|
+
type: 'textbox';
|
|
1896
|
+
data: {
|
|
1897
|
+
style?: CellStyle;
|
|
1898
|
+
paragraphs: {
|
|
1899
|
+
style?: CellStyle;
|
|
1900
|
+
content: {
|
|
1901
|
+
text: string;
|
|
1902
|
+
style?: CellStyle;
|
|
1903
|
+
}[];
|
|
1904
|
+
}[];
|
|
1905
|
+
};
|
|
1906
|
+
}
|
|
1883
1907
|
export interface AnnotationExternalData extends AnnotationDataBase {
|
|
1884
1908
|
type: 'external';
|
|
1885
1909
|
data: Record<string, string>;
|
package/package.json
CHANGED
|
@@ -23,7 +23,7 @@ import type { Cell, ICellAddress, ICellAddress2, UnionValue, EvaluateOptions,
|
|
|
23
23
|
ArrayUnion, IArea, CellDataWithAddress, CellValue} from 'treb-base-types';
|
|
24
24
|
import { Localization, Area, ValueType, IsCellAddress} from 'treb-base-types';
|
|
25
25
|
|
|
26
|
-
import type { ExpressionUnit, DependencyList, UnitRange, UnitAddress, UnitIdentifier } from 'treb-parser';
|
|
26
|
+
import type { ExpressionUnit, DependencyList, UnitRange, UnitAddress, UnitIdentifier, ParseResult } from 'treb-parser';
|
|
27
27
|
import { Parser,
|
|
28
28
|
DecimalMarkType, ArgumentSeparatorType, QuotedSheetNameRegex } from 'treb-parser';
|
|
29
29
|
|
|
@@ -57,6 +57,8 @@ import { StateLeafVertex } from './dag/state_leaf_vertex';
|
|
|
57
57
|
import { CalculationLeafVertex } from './dag/calculation_leaf_vertex';
|
|
58
58
|
import type { ConnectedElementType } from 'treb-grid';
|
|
59
59
|
|
|
60
|
+
import { ValueParser } from 'treb-format';
|
|
61
|
+
|
|
60
62
|
/**
|
|
61
63
|
* breaking this out so we can use it for export (TODO)
|
|
62
64
|
*
|
|
@@ -241,6 +243,160 @@ export class Calculator extends Graph {
|
|
|
241
243
|
}
|
|
242
244
|
|
|
243
245
|
// special functions... need reference to the graph (this)
|
|
246
|
+
// moving countif here so we can reference it in COUNTIFS...
|
|
247
|
+
|
|
248
|
+
const FlattenBooleans = (value: ArrayUnion) => {
|
|
249
|
+
const result: boolean[] = [];
|
|
250
|
+
for (const col of value.value) {
|
|
251
|
+
for (const entry of col) {
|
|
252
|
+
result.push(entry.type === ValueType.boolean && entry.value);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const CountIfInternal = (range: any, criteria: any): UnionValue => {
|
|
259
|
+
|
|
260
|
+
// do we really need parser/calculator for this? I think
|
|
261
|
+
// we've maybe gone overboard here, could we just use valueparser
|
|
262
|
+
// on the criteria and then calculate normally? I think we might...
|
|
263
|
+
// in any event there are no dynamic dependencies with this
|
|
264
|
+
// function.
|
|
265
|
+
|
|
266
|
+
const data = Utilities.FlattenUnboxed(range);
|
|
267
|
+
|
|
268
|
+
let parse_result: ParseResult|undefined;
|
|
269
|
+
let expression: ExpressionUnit|undefined;
|
|
270
|
+
|
|
271
|
+
// we'll handle operator and operand separately
|
|
272
|
+
|
|
273
|
+
let operator = '=';
|
|
274
|
+
|
|
275
|
+
// handle wildcards first. if we have a wildcard we use a
|
|
276
|
+
// matching function so we can centralize.
|
|
277
|
+
|
|
278
|
+
if (typeof criteria === 'string') {
|
|
279
|
+
|
|
280
|
+
// normalize first, pull out operator
|
|
281
|
+
|
|
282
|
+
criteria = criteria.trim();
|
|
283
|
+
const match = criteria.match(/^([=<>]+)/);
|
|
284
|
+
if (match) {
|
|
285
|
+
operator = match[1];
|
|
286
|
+
criteria = criteria.substring(operator.length);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const value_parser_result = ValueParser.TryParse(criteria);
|
|
290
|
+
if (value_parser_result?.type === ValueType.string) {
|
|
291
|
+
criteria = `"${value_parser_result.value}"`;
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
criteria = value_parser_result?.value?.toString() || '';
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// console.info({operator, criteria});
|
|
298
|
+
|
|
299
|
+
// check for wildcards (this will false-positive on escaped
|
|
300
|
+
// wildcards, which will not break but will waste cycles. we
|
|
301
|
+
// could check. TOOD/FIXME)
|
|
302
|
+
|
|
303
|
+
if (/[?*]/.test(criteria)) {
|
|
304
|
+
|
|
305
|
+
// NOTE: we're not specifying an argument separator when writing
|
|
306
|
+
// functions, because that might break numbers passed as strings.
|
|
307
|
+
// so we write the function based on the current separator.
|
|
308
|
+
|
|
309
|
+
const separator = this.parser.argument_separator;
|
|
310
|
+
|
|
311
|
+
if (operator === '=' || operator === '<>') {
|
|
312
|
+
|
|
313
|
+
parse_result = this.parser.Parse(`=WildcardMatch({}${separator} ${criteria}${separator} ${operator === '<>'})`);
|
|
314
|
+
expression = parse_result.expression;
|
|
315
|
+
|
|
316
|
+
if (parse_result.error || !expression) {
|
|
317
|
+
return ExpressionError();
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (expression?.type === 'call' && expression.args[0]?.type === 'array') {
|
|
321
|
+
expression.args[0].values = [data];
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
|
|
331
|
+
// if it's not a string, by definition it doesn't have an
|
|
332
|
+
// operator so use equality (default). it does not need
|
|
333
|
+
// escaping.
|
|
334
|
+
|
|
335
|
+
criteria = (criteria || 0).toString();
|
|
336
|
+
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (!parse_result) {
|
|
340
|
+
|
|
341
|
+
parse_result = this.parser.Parse('{}' + operator + criteria);
|
|
342
|
+
expression = parse_result.expression;
|
|
343
|
+
|
|
344
|
+
if (parse_result.error || !expression) {
|
|
345
|
+
return ExpressionError();
|
|
346
|
+
}
|
|
347
|
+
if (expression.type !== 'binary') {
|
|
348
|
+
console.warn('invalid expression [1]', expression);
|
|
349
|
+
return ExpressionError();
|
|
350
|
+
}
|
|
351
|
+
if (expression.left.type !== 'array') {
|
|
352
|
+
console.warn('invalid expression [1]', expression);
|
|
353
|
+
return ExpressionError();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// this is only going to work for binary left/right. it won't
|
|
357
|
+
// work if we change this to a function (wildcard match)
|
|
358
|
+
|
|
359
|
+
// this will not happen anymore, we can remove
|
|
360
|
+
|
|
361
|
+
if (expression.right.type === 'identifier') {
|
|
362
|
+
|
|
363
|
+
console.warn('will never happen');
|
|
364
|
+
|
|
365
|
+
expression.right = {
|
|
366
|
+
...expression.right,
|
|
367
|
+
type: 'literal',
|
|
368
|
+
value: expression.right.name,
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
expression.left.values = [data];
|
|
373
|
+
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (!expression) {
|
|
377
|
+
return ValueError();
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const result = this.CalculateExpression(expression);
|
|
381
|
+
return result;
|
|
382
|
+
|
|
383
|
+
/*
|
|
384
|
+
// console.info({expression, result});
|
|
385
|
+
|
|
386
|
+
if (result.type === ValueType.array) {
|
|
387
|
+
let count = 0;
|
|
388
|
+
for (const column of (result as ArrayUnion).value) {
|
|
389
|
+
for (const cell of column) {
|
|
390
|
+
if (cell.value) { count++; }
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return { type: ValueType.number, value: count };
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return result; // error?
|
|
397
|
+
*/
|
|
398
|
+
|
|
399
|
+
};
|
|
244
400
|
|
|
245
401
|
this.library.Register({
|
|
246
402
|
|
|
@@ -403,6 +559,57 @@ export class Calculator extends Graph {
|
|
|
403
559
|
},
|
|
404
560
|
},
|
|
405
561
|
|
|
562
|
+
/**
|
|
563
|
+
* anything I said about COUNTIF applies here, but worse.
|
|
564
|
+
* COUNTIFS is an AND operation across separate COUNTIFs.
|
|
565
|
+
* presumably they have to be the same shape.
|
|
566
|
+
*/
|
|
567
|
+
CountIfs: {
|
|
568
|
+
arguments: [
|
|
569
|
+
{ name: 'range1', },
|
|
570
|
+
{ name: 'criteria1', },
|
|
571
|
+
{ name: 'range2', },
|
|
572
|
+
{ name: 'criteria2', }
|
|
573
|
+
],
|
|
574
|
+
fn: (...args): UnionValue => {
|
|
575
|
+
|
|
576
|
+
let count = 0;
|
|
577
|
+
|
|
578
|
+
let result = CountIfInternal(args[0], args[1]);
|
|
579
|
+
if (result.type !== ValueType.array) {
|
|
580
|
+
return result; // error
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
const base = FlattenBooleans(result);
|
|
584
|
+
|
|
585
|
+
for (let i = 2; i < args.length; i += 2) {
|
|
586
|
+
if (args[i] && args[i + 1]) {
|
|
587
|
+
|
|
588
|
+
const result = CountIfInternal(args[i], args[i+1]);
|
|
589
|
+
if (result.type !== ValueType.array) {
|
|
590
|
+
return result;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
const step = FlattenBooleans(result);
|
|
594
|
+
for (const [index, value] of base.entries()) {
|
|
595
|
+
base[index] = value && step[index];
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
for (const element of base) {
|
|
602
|
+
if (element) { count++; }
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
return {
|
|
606
|
+
type: ValueType.number,
|
|
607
|
+
value: count,
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
},
|
|
611
|
+
},
|
|
612
|
+
|
|
406
613
|
/**
|
|
407
614
|
* this function is here so it has access to the parser.
|
|
408
615
|
* this is crazy expensive. is there a way to reduce cost?
|
|
@@ -425,59 +632,7 @@ export class Calculator extends Graph {
|
|
|
425
632
|
],
|
|
426
633
|
fn: (range, criteria): UnionValue => {
|
|
427
634
|
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
// console.info({range, data});
|
|
431
|
-
|
|
432
|
-
// console.info({range});
|
|
433
|
-
|
|
434
|
-
if (typeof criteria !== 'string') {
|
|
435
|
-
criteria = '=' + (criteria || 0).toString();
|
|
436
|
-
}
|
|
437
|
-
else {
|
|
438
|
-
criteria = criteria.trim();
|
|
439
|
-
if (!/^[=<>]/.test(criteria)) {
|
|
440
|
-
criteria = '=' + criteria;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// switching to an array. doesn't actually seem to be any
|
|
445
|
-
// faster... more appropriate, though.
|
|
446
|
-
|
|
447
|
-
const parse_result = this.parser.Parse('{}' + criteria);
|
|
448
|
-
const expression = parse_result.expression;
|
|
449
|
-
|
|
450
|
-
if (parse_result.error || !expression) {
|
|
451
|
-
return ExpressionError();
|
|
452
|
-
}
|
|
453
|
-
if (expression.type !== 'binary') {
|
|
454
|
-
// console.warn('invalid expression [1]', expression);
|
|
455
|
-
return ExpressionError();
|
|
456
|
-
}
|
|
457
|
-
if (expression.left.type !== 'array') {
|
|
458
|
-
// console.warn('invalid expression [1]', expression);
|
|
459
|
-
return ExpressionError();
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
expression.left.values = [data];
|
|
463
|
-
const result = this.CalculateExpression(expression);
|
|
464
|
-
|
|
465
|
-
// console.info({expression, result});
|
|
466
|
-
|
|
467
|
-
// this is no longer the case because we're getting
|
|
468
|
-
// a boxed result (union)
|
|
469
|
-
|
|
470
|
-
/*
|
|
471
|
-
if (Array.isArray(result)) {
|
|
472
|
-
let count = 0;
|
|
473
|
-
for (const column of result) {
|
|
474
|
-
for (const cell of column) {
|
|
475
|
-
if (cell.value) { count++; }
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
return { type: ValueType.number, value: count };
|
|
479
|
-
}
|
|
480
|
-
*/
|
|
635
|
+
const result = CountIfInternal(range, criteria);
|
|
481
636
|
|
|
482
637
|
if (result.type === ValueType.array) {
|
|
483
638
|
let count = 0;
|
|
@@ -489,7 +644,7 @@ export class Calculator extends Graph {
|
|
|
489
644
|
return { type: ValueType.number, value: count };
|
|
490
645
|
}
|
|
491
646
|
|
|
492
|
-
return result; // error
|
|
647
|
+
return result; // error
|
|
493
648
|
|
|
494
649
|
},
|
|
495
650
|
},
|
|
@@ -1150,12 +1305,16 @@ export class Calculator extends Graph {
|
|
|
1150
1305
|
// don't assume default, always set
|
|
1151
1306
|
|
|
1152
1307
|
if (Localization.decimal_separator === ',') {
|
|
1153
|
-
this.parser.
|
|
1154
|
-
|
|
1308
|
+
this.parser.SetLocaleSettings(DecimalMarkType.Comma);
|
|
1309
|
+
|
|
1310
|
+
// this.parser.decimal_mark = DecimalMarkType.Comma;
|
|
1311
|
+
// this.parser.argument_separator = ArgumentSeparatorType.Semicolon;
|
|
1155
1312
|
}
|
|
1156
1313
|
else {
|
|
1157
|
-
this.parser.
|
|
1158
|
-
|
|
1314
|
+
this.parser.SetLocaleSettings(DecimalMarkType.Period);
|
|
1315
|
+
|
|
1316
|
+
// this.parser.decimal_mark = DecimalMarkType.Period;
|
|
1317
|
+
// this.parser.argument_separator = ArgumentSeparatorType.Comma;
|
|
1159
1318
|
}
|
|
1160
1319
|
|
|
1161
1320
|
// this.expression_calculator.UpdateLocale();
|
|
@@ -1381,17 +1540,23 @@ export class Calculator extends Graph {
|
|
|
1381
1540
|
/** moved from embedded sheet */
|
|
1382
1541
|
public Evaluate(expression: string, active_sheet?: Sheet, options: EvaluateOptions = {}, raw_result = false) {
|
|
1383
1542
|
|
|
1384
|
-
const current = this.parser.argument_separator;
|
|
1385
|
-
const r1c1_state = this.parser.flags.r1c1;
|
|
1543
|
+
// const current = this.parser.argument_separator;
|
|
1544
|
+
// const r1c1_state = this.parser.flags.r1c1;
|
|
1545
|
+
|
|
1546
|
+
this.parser.Save();
|
|
1386
1547
|
|
|
1387
1548
|
if (options.argument_separator) {
|
|
1388
1549
|
if (options.argument_separator === ',') {
|
|
1389
|
-
this.parser.
|
|
1390
|
-
|
|
1550
|
+
this.parser.SetLocaleSettings(DecimalMarkType.Period);
|
|
1551
|
+
|
|
1552
|
+
// this.parser.argument_separator = ArgumentSeparatorType.Comma;
|
|
1553
|
+
// this.parser.decimal_mark = DecimalMarkType.Period;
|
|
1391
1554
|
}
|
|
1392
1555
|
else {
|
|
1393
|
-
this.parser.
|
|
1394
|
-
|
|
1556
|
+
this.parser.SetLocaleSettings(DecimalMarkType.Comma);
|
|
1557
|
+
|
|
1558
|
+
// this.parser.argument_separator = ArgumentSeparatorType.Semicolon;
|
|
1559
|
+
// this.parser.decimal_mark = DecimalMarkType.Comma;
|
|
1395
1560
|
}
|
|
1396
1561
|
}
|
|
1397
1562
|
|
|
@@ -1403,9 +1568,11 @@ export class Calculator extends Graph {
|
|
|
1403
1568
|
|
|
1404
1569
|
// reset
|
|
1405
1570
|
|
|
1406
|
-
this.parser.argument_separator = current;
|
|
1407
|
-
this.parser.decimal_mark = (current === ArgumentSeparatorType.Comma) ? DecimalMarkType.Period : DecimalMarkType.Comma;
|
|
1408
|
-
this.parser.flags.r1c1 = r1c1_state;
|
|
1571
|
+
// this.parser.argument_separator = current;
|
|
1572
|
+
// this.parser.decimal_mark = (current === ArgumentSeparatorType.Comma) ? DecimalMarkType.Period : DecimalMarkType.Comma;
|
|
1573
|
+
// this.parser.flags.r1c1 = r1c1_state;
|
|
1574
|
+
|
|
1575
|
+
this.parser.Restore();
|
|
1409
1576
|
|
|
1410
1577
|
// OK
|
|
1411
1578
|
|
|
@@ -806,15 +806,11 @@ export class ExpressionCalculator {
|
|
|
806
806
|
|
|
807
807
|
}
|
|
808
808
|
|
|
809
|
-
//protected ElementwiseBinaryExpression(fn: Primitives.PrimitiveBinaryExpression, left: UnionValue[][], right: UnionValue[][]): UnionValue[][] {
|
|
810
809
|
protected ElementwiseBinaryExpression(fn: Primitives.PrimitiveBinaryExpression, left: ArrayUnion, right: ArrayUnion): ArrayUnion {
|
|
811
810
|
|
|
812
811
|
const columns = Math.max(left.value.length, right.value.length);
|
|
813
812
|
const rows = Math.max(left.value[0].length, right.value[0].length);
|
|
814
813
|
|
|
815
|
-
// const columns = Math.max(left.length, right.length);
|
|
816
|
-
// const rows = Math.max(left[0].length, right[0].length);
|
|
817
|
-
|
|
818
814
|
const left_values = this.RecycleArray(left.value, columns, rows);
|
|
819
815
|
const right_values = this.RecycleArray(right.value, columns, rows);
|
|
820
816
|
|
|
@@ -822,8 +818,16 @@ export class ExpressionCalculator {
|
|
|
822
818
|
|
|
823
819
|
for (let c = 0; c < columns; c++) {
|
|
824
820
|
const col: UnionValue[] = [];
|
|
821
|
+
|
|
825
822
|
for (let r = 0; r < rows; r++ ) {
|
|
826
|
-
|
|
823
|
+
|
|
824
|
+
// handle undefineds. this is unfortunate. shouldn't the recycle
|
|
825
|
+
// function do that? ...CHECK/TODO/FIXME
|
|
826
|
+
|
|
827
|
+
col[r] = fn(
|
|
828
|
+
left_values[c][r] || { type: ValueType.undefined },
|
|
829
|
+
right_values[c][r] || { type: ValueType.undefined });
|
|
830
|
+
|
|
827
831
|
}
|
|
828
832
|
value.push(col);
|
|
829
833
|
}
|