@shbernal/ts-xlsx 3.0.0 → 3.2.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/README.md +34 -24
- package/dist/bytes.d.ts +10 -2
- package/dist/bytes.js +22 -0
- package/dist/core/address.d.ts +96 -2
- package/dist/core/address.js +87 -33
- package/dist/core/array-formula-ranges.d.ts +33 -0
- package/dist/core/array-formula-ranges.js +62 -0
- package/dist/core/autofilter.d.ts +4 -3
- package/dist/core/autofilter.js +31 -30
- package/dist/core/axis-handle.d.ts +2 -0
- package/dist/core/axis-handle.js +5 -2
- package/dist/core/cell.d.ts +4 -3
- package/dist/core/cell.js +4 -6
- package/dist/core/clone.d.ts +29 -0
- package/dist/core/clone.js +24 -0
- package/dist/core/color-resolution.js +4 -6
- package/dist/core/column.d.ts +1 -0
- package/dist/core/column.js +6 -2
- package/dist/core/comment-thread.d.ts +7 -3
- package/dist/core/comment-thread.js +2 -1
- package/dist/core/conditional-formatting-overlay.d.ts +11 -1
- package/dist/core/conditional-formatting-overlay.js +30 -3
- package/dist/core/conditional-formatting.d.ts +107 -11
- package/dist/core/conditional-formatting.js +76 -19
- package/dist/core/containers.d.ts +12 -0
- package/dist/core/containers.js +5 -0
- package/dist/core/data-validation-overlay.d.ts +7 -1
- package/dist/core/data-validation-overlay.js +19 -4
- package/dist/core/data-validation.d.ts +22 -0
- package/dist/core/data-validation.js +30 -4
- package/dist/core/date-format.d.ts +20 -0
- package/dist/core/date-format.js +170 -0
- package/dist/core/date.d.ts +43 -8
- package/dist/core/date.js +19 -3
- package/dist/core/formula-references.d.ts +26 -0
- package/dist/core/formula-references.js +173 -0
- package/dist/core/formula-scan.d.ts +2 -0
- package/dist/core/formula-scan.js +58 -0
- package/dist/core/formula.d.ts +76 -17
- package/dist/core/formula.js +87 -80
- package/dist/core/function-values.d.ts +4 -0
- package/dist/core/function-values.js +58 -0
- package/dist/core/future-functions.d.ts +3 -0
- package/dist/core/{modern-functions.js → future-functions.js} +119 -88
- package/dist/core/grid-edits.d.ts +30 -3
- package/dist/core/grid-edits.js +248 -81
- package/dist/core/grid-shift.d.ts +58 -9
- package/dist/core/grid-shift.js +26 -4
- package/dist/core/hyperlink.d.ts +39 -0
- package/dist/core/hyperlink.js +88 -0
- package/dist/core/image.d.ts +49 -14
- package/dist/core/image.js +16 -5
- package/dist/core/internal.d.ts +10 -2
- package/dist/core/limits.d.ts +25 -0
- package/dist/core/limits.js +4 -0
- package/dist/core/merge.d.ts +18 -4
- package/dist/core/merge.js +33 -20
- package/dist/core/page-setup.d.ts +26 -11
- package/dist/core/pivot-table.d.ts +49 -10
- package/dist/core/pivot-table.js +112 -60
- package/dist/core/protection.d.ts +66 -4
- package/dist/core/protection.js +6 -11
- package/dist/core/range.js +34 -30
- package/dist/core/row-input.js +2 -2
- package/dist/core/row.d.ts +1 -0
- package/dist/core/row.js +6 -2
- package/dist/core/structured-reference.d.ts +7 -0
- package/dist/core/structured-reference.js +7 -0
- package/dist/core/style.d.ts +85 -70
- package/dist/core/style.js +92 -28
- package/dist/core/table-style.d.ts +1 -1
- package/dist/core/table-style.js +4 -4
- package/dist/core/table.d.ts +64 -16
- package/dist/core/table.js +87 -40
- package/dist/core/theme.d.ts +2 -0
- package/dist/core/theme.js +9 -5
- package/dist/core/value.d.ts +60 -28
- package/dist/core/value.js +48 -43
- package/dist/core/workbook-media.d.ts +34 -0
- package/dist/core/workbook-media.js +44 -0
- package/dist/core/workbook-styles.d.ts +83 -1
- package/dist/core/workbook-styles.js +4 -0
- package/dist/core/workbook-theme.js +5 -3
- package/dist/core/workbook-vba.js +3 -2
- package/dist/core/workbook.d.ts +41 -3
- package/dist/core/workbook.js +46 -41
- package/dist/core/worksheet-comments.d.ts +2 -1
- package/dist/core/worksheet-comments.js +20 -13
- package/dist/core/worksheet-merges.d.ts +49 -0
- package/dist/core/worksheet-merges.js +65 -0
- package/dist/core/worksheet-model.d.ts +10 -2
- package/dist/core/worksheet-model.js +28 -9
- package/dist/core/worksheet-pictures.d.ts +3 -3
- package/dist/core/worksheet-pictures.js +7 -6
- package/dist/core/worksheet.d.ts +165 -27
- package/dist/core/worksheet.js +206 -89
- package/dist/customui/ribbon.js +2 -1
- package/dist/entries/core.d.ts +21 -14
- package/dist/entries/core.js +14 -7
- package/dist/entries/errors.d.ts +1 -0
- package/dist/entries/errors.js +1 -0
- package/dist/entries/xlsx.d.ts +1 -1
- package/dist/errors.d.ts +64 -0
- package/dist/errors.js +22 -0
- package/dist/hex.d.ts +8 -0
- package/dist/hex.js +3 -0
- package/dist/io/cell-metadata/metadata.d.ts +42 -0
- package/dist/io/cell-metadata/metadata.js +35 -0
- package/dist/io/cell-metadata/rich-values.d.ts +11 -0
- package/dist/io/cell-metadata/rich-values.js +80 -0
- package/dist/io/csv/delimiter.d.ts +21 -0
- package/dist/io/csv/delimiter.js +18 -0
- package/dist/io/csv/errors.d.ts +14 -0
- package/dist/io/csv/errors.js +5 -0
- package/dist/io/csv/read.d.ts +6 -1
- package/dist/io/csv/read.js +51 -22
- package/dist/io/csv/write.d.ts +19 -5
- package/dist/io/csv/write.js +24 -44
- package/dist/io/opc/inflate.js +14 -0
- package/dist/io/opc/namespaces.d.ts +16 -0
- package/dist/io/opc/namespaces.js +4 -0
- package/dist/io/opc/part-paths.d.ts +9 -0
- package/dist/io/opc/part-paths.js +5 -5
- package/dist/io/opc/read-opc.d.ts +58 -14
- package/dist/io/opc/read-opc.js +49 -21
- package/dist/io/opc/read-options.d.ts +5 -1
- package/dist/io/opc/sniff-format.d.ts +3 -3
- package/dist/io/opc/sniff-format.js +2 -2
- package/dist/io/opc/strict-relationships.d.ts +2 -0
- package/dist/io/opc/strict-relationships.js +12 -0
- package/dist/io/read-policy/column-budget.d.ts +26 -0
- package/dist/io/read-policy/column-budget.js +18 -0
- package/dist/io/read-policy/read-repair.d.ts +74 -0
- package/dist/io/read-policy/read-repair.js +119 -0
- package/dist/io/style/cell-style-resolution.d.ts +25 -0
- package/dist/io/style/cell-style-resolution.js +30 -0
- package/dist/io/style/xf-style.d.ts +23 -1
- package/dist/io/style/xf-style.js +8 -0
- package/dist/io/xlsb/formula.d.ts +2 -2
- package/dist/io/xlsb/formula.js +52 -35
- package/dist/io/xlsb/primitives.js +8 -14
- package/dist/io/xlsb/ptg-functions.d.ts +19 -10
- package/dist/io/xlsb/ptg-functions.js +495 -596
- package/dist/io/xlsb/read-metadata.d.ts +7 -0
- package/dist/io/xlsb/read-metadata.js +69 -0
- package/dist/io/xlsb/read-styles.js +45 -81
- package/dist/io/xlsb/read-worksheet.d.ts +26 -1
- package/dist/io/xlsb/read-worksheet.js +148 -106
- package/dist/io/xlsb/read.d.ts +6 -3
- package/dist/io/xlsb/read.js +70 -31
- package/dist/io/xlsb/record-stream.d.ts +30 -0
- package/dist/io/xlsb/record-stream.js +20 -0
- package/dist/io/xlsb/record-types.d.ts +14 -5
- package/dist/io/xlsb/record-types.js +14 -5
- package/dist/io/xlsb/sheet-protection.d.ts +20 -0
- package/dist/io/xlsb/sheet-protection.js +60 -0
- package/dist/io/xlsx/cell-accumulator.d.ts +24 -9
- package/dist/io/xlsx/cell-accumulator.js +74 -21
- package/dist/io/xlsx/cell-metadata.d.ts +39 -0
- package/dist/io/xlsx/cell-metadata.js +162 -0
- package/dist/io/xlsx/cell-value.d.ts +19 -5
- package/dist/io/xlsx/cell-value.js +45 -30
- package/dist/io/xlsx/color-xml.js +3 -2
- package/dist/io/xlsx/column-span.d.ts +11 -0
- package/dist/io/xlsx/column-span.js +9 -0
- package/dist/io/xlsx/comments.d.ts +9 -30
- package/dist/io/xlsx/comments.js +25 -83
- package/dist/io/xlsx/conditional-formatting.d.ts +43 -23
- package/dist/io/xlsx/conditional-formatting.js +437 -138
- package/dist/io/xlsx/data-validation.d.ts +12 -7
- package/dist/io/xlsx/data-validation.js +67 -53
- package/dist/io/xlsx/edit-vba.d.ts +7 -2
- package/dist/io/xlsx/edit-vba.js +52 -52
- package/dist/io/xlsx/font-xml.d.ts +7 -0
- package/dist/io/xlsx/font-xml.js +104 -0
- package/dist/io/xlsx/hyperlinks.d.ts +19 -21
- package/dist/io/xlsx/hyperlinks.js +12 -32
- package/dist/io/xlsx/images.d.ts +49 -16
- package/dist/io/xlsx/images.js +149 -50
- package/dist/io/xlsx/namespaces.d.ts +24 -0
- package/dist/io/xlsx/namespaces.js +11 -0
- package/dist/io/xlsx/package-plan.d.ts +60 -15
- package/dist/io/xlsx/package-plan.js +83 -18
- package/dist/io/xlsx/part-names.d.ts +6 -8
- package/dist/io/xlsx/part-names.js +3 -7
- package/dist/io/xlsx/pivot.d.ts +5 -5
- package/dist/io/xlsx/pivot.js +26 -24
- package/dist/io/xlsx/preserved-splices.d.ts +6 -0
- package/dist/io/xlsx/preserved-splices.js +74 -0
- package/dist/io/xlsx/read-comments.d.ts +29 -0
- package/dist/io/xlsx/read-comments.js +75 -0
- package/dist/io/xlsx/read-parts.d.ts +59 -0
- package/dist/io/xlsx/read-parts.js +259 -0
- package/dist/io/xlsx/read-pivot.js +11 -4
- package/dist/io/xlsx/{rich-runs.d.ts → read-rich-runs.d.ts} +8 -5
- package/dist/io/xlsx/{rich-runs.js → read-rich-runs.js} +24 -4
- package/dist/io/xlsx/read-rows.d.ts +35 -11
- package/dist/io/xlsx/read-rows.js +73 -49
- package/dist/io/xlsx/read-shared-strings.js +3 -2
- package/dist/io/xlsx/read-styles.d.ts +0 -30
- package/dist/io/xlsx/read-styles.js +45 -105
- package/dist/io/xlsx/read-workbook-xml.d.ts +42 -0
- package/dist/io/xlsx/read-workbook-xml.js +175 -0
- package/dist/io/xlsx/read-worksheet.d.ts +9 -3
- package/dist/io/xlsx/read-worksheet.js +70 -177
- package/dist/io/xlsx/read.d.ts +3 -14
- package/dist/io/xlsx/read.js +74 -411
- package/dist/io/xlsx/relationships.d.ts +3 -0
- package/dist/io/xlsx/relationships.js +4 -0
- package/dist/io/xlsx/rich-text.js +1 -1
- package/dist/io/xlsx/row-position.d.ts +20 -0
- package/dist/io/xlsx/row-position.js +11 -0
- package/dist/io/xlsx/row-xml.d.ts +139 -0
- package/dist/io/xlsx/row-xml.js +222 -0
- package/dist/io/xlsx/shared-formulas.js +2 -2
- package/dist/io/xlsx/sheet-properties.d.ts +10 -1
- package/dist/io/xlsx/sheet-properties.js +182 -20
- package/dist/io/xlsx/strict-parts.d.ts +7 -0
- package/dist/io/xlsx/strict-parts.js +171 -0
- package/dist/io/xlsx/style-elements.d.ts +41 -0
- package/dist/io/xlsx/style-elements.js +136 -0
- package/dist/io/xlsx/styles.d.ts +17 -3
- package/dist/io/xlsx/styles.js +13 -209
- package/dist/io/xlsx/tables.d.ts +10 -2
- package/dist/io/xlsx/tables.js +55 -52
- package/dist/io/xlsx/theme-xml.d.ts +32 -4
- package/dist/io/xlsx/theme-xml.js +106 -71
- package/dist/io/xlsx/threaded-comments.d.ts +14 -11
- package/dist/io/xlsx/threaded-comments.js +16 -8
- package/dist/io/xlsx/workbook-xml.d.ts +45 -6
- package/dist/io/xlsx/workbook-xml.js +62 -54
- package/dist/io/xlsx/worksheet-xml.d.ts +26 -70
- package/dist/io/xlsx/worksheet-xml.js +69 -282
- package/dist/io/xlsx/write-stream.d.ts +90 -19
- package/dist/io/xlsx/write-stream.js +80 -25
- package/dist/io/xlsx/write.d.ts +12 -6
- package/dist/io/xlsx/write.js +226 -123
- package/dist/rel-type.d.ts +25 -0
- package/dist/rel-type.js +9 -0
- package/dist/token-set.d.ts +13 -0
- package/dist/token-set.js +4 -1
- package/dist/vba/bytes.d.ts +16 -5
- package/dist/vba/bytes.js +27 -6
- package/dist/vba/cfb-format.d.ts +55 -0
- package/dist/vba/cfb-format.js +35 -0
- package/dist/vba/cfb-writer.d.ts +8 -0
- package/dist/vba/cfb-writer.js +40 -40
- package/dist/vba/cfb.d.ts +21 -4
- package/dist/vba/cfb.js +124 -90
- package/dist/vba/codepage.js +2 -1
- package/dist/vba/dir-records.d.ts +6 -0
- package/dist/vba/dir-records.js +10 -2
- package/dist/vba/errors.d.ts +11 -4
- package/dist/vba/index.d.ts +0 -2
- package/dist/vba/index.js +0 -2
- package/dist/vba/ms-ovba.d.ts +6 -2
- package/dist/vba/ms-ovba.js +66 -22
- package/dist/vba/project-editor.js +129 -119
- package/dist/vba/project.d.ts +15 -1
- package/dist/vba/project.js +38 -13
- package/dist/vba/vba-encoding.d.ts +4 -10
- package/dist/vba/vba-encoding.js +3 -17
- package/dist/xml/xml-attrs.d.ts +37 -0
- package/dist/xml/xml-attrs.js +30 -0
- package/dist/xml/xml-chars.d.ts +40 -0
- package/dist/xml/xml-chars.js +12 -0
- package/dist/xml/xml-namespaces.d.ts +31 -0
- package/dist/xml/xml-namespaces.js +50 -0
- package/dist/xml/xml-read.d.ts +101 -11
- package/dist/xml/xml-read.js +150 -18
- package/dist/xml/xml-scan.d.ts +25 -34
- package/dist/xml/xml-scan.js +69 -46
- package/dist/xml/xml.d.ts +59 -26
- package/dist/xml/xml.js +45 -23
- package/package.json +15 -9
- package/skills/ts-xlsx-upstream/SKILL.md +21 -13
- package/dist/core/modern-functions.d.ts +0 -1
|
@@ -1,92 +1,201 @@
|
|
|
1
|
-
import { isCfValueObjectType, isConditionalFormattingOperator, isConditionalFormattingType, isIconSetType,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { isCfIconSetType, isCfTimePeriod, isCfValueObjectType, isConditionalFormattingOperator, isConditionalFormattingType, isDataBarAxisPosition, isDataBarDirection, isIconSetType, ruleNeedsExtension, } from '../../core/conditional-formatting.js';
|
|
2
|
+
import { mangleFormula, stripFormulaEquals, unmangleFunctions } from '../../core/formula.js';
|
|
3
|
+
import { decodeSqrefRects } from '../../core/merge.js';
|
|
4
|
+
import { InternalError } from '../../errors.js';
|
|
5
|
+
import { coerceNumericLiteral, enumToken, numInteger } from '../../xml/xml-attrs.js';
|
|
6
|
+
import { elementRange, TextCapture, } from '../../xml/xml-read.js';
|
|
7
|
+
import { boolStrict, boolTristate, localName } from '../../xml/xml-scan.js';
|
|
8
|
+
import { boolAttr, checkedToken, escapeAttr, escapeText, intAttr, numberText, textAttr, } from '../../xml/xml.js';
|
|
9
|
+
import { admitting } from '../read-policy/read-repair.js';
|
|
5
10
|
import { colorAttrs, parseColor } from './color-xml.js';
|
|
6
|
-
import { CF_EXT_URI, DATABAR_LINK_EXT_URI, XM_NS } from './namespaces.js';
|
|
11
|
+
import { CF_EXT_URI, DATABAR_LINK_EXT_URI, isExtensionElement, isMainNamespaceElement, XM_NS, } from './namespaces.js';
|
|
7
12
|
import { x14Ext } from './x14-ext.js';
|
|
8
13
|
const DEFAULT_DATABAR_CFVO = [{ type: 'min' }, { type: 'max' }];
|
|
9
14
|
const DEFAULT_DATABAR_COLOR = { argb: 'FF638EC6' };
|
|
15
|
+
const CLASSIC_ANCHOR = {
|
|
16
|
+
autoMin: 'min',
|
|
17
|
+
autoMax: 'max',
|
|
18
|
+
};
|
|
10
19
|
function needsDataBarExt(rule) {
|
|
11
20
|
return (rule.gradient !== undefined ||
|
|
21
|
+
rule.border !== undefined ||
|
|
22
|
+
rule.borderColor !== undefined ||
|
|
23
|
+
rule.direction !== undefined ||
|
|
12
24
|
rule.negativeFillColor !== undefined ||
|
|
13
|
-
rule.
|
|
25
|
+
rule.negativeBorderColor !== undefined ||
|
|
26
|
+
rule.negativeBarColorSameAsPositive !== undefined ||
|
|
27
|
+
rule.negativeBarBorderColorSameAsPositive !== undefined ||
|
|
28
|
+
rule.axisPosition !== undefined ||
|
|
29
|
+
rule.axisColor !== undefined ||
|
|
30
|
+
(rule.cfvo ?? []).some((anchor) => CLASSIC_ANCHOR[anchor.type] !== undefined));
|
|
14
31
|
}
|
|
15
|
-
function
|
|
32
|
+
function inExtension(cf, rule) {
|
|
33
|
+
return cf.extended === true || ruleNeedsExtension(rule);
|
|
34
|
+
}
|
|
35
|
+
function extensionGuid(index) {
|
|
16
36
|
return `{00000000-0000-0000-0000-${String(index + 1).padStart(12, '0')}}`;
|
|
17
37
|
}
|
|
18
|
-
function
|
|
19
|
-
const
|
|
20
|
-
|
|
38
|
+
export function planConditionalFormatting(formattings) {
|
|
39
|
+
const priorities = new Map();
|
|
40
|
+
const extensionIds = new Map();
|
|
41
|
+
let next = 1;
|
|
21
42
|
for (const cf of formattings) {
|
|
22
43
|
for (const rule of cf.rules) {
|
|
23
|
-
|
|
24
|
-
|
|
44
|
+
const priority = rule.priority ?? next;
|
|
45
|
+
intAttr('priority', priority);
|
|
46
|
+
next = Math.max(next, priority) + 1;
|
|
47
|
+
priorities.set(rule, priority);
|
|
48
|
+
if (inExtension(cf, rule) || (rule.type === 'dataBar' && needsDataBarExt(rule))) {
|
|
49
|
+
extensionIds.set(rule, extensionGuid(extensionIds.size));
|
|
50
|
+
}
|
|
25
51
|
}
|
|
26
52
|
}
|
|
27
|
-
return
|
|
53
|
+
return { priorities, extensionIds };
|
|
54
|
+
}
|
|
55
|
+
function priorityOf(plan, rule) {
|
|
56
|
+
const priority = plan.priorities.get(rule);
|
|
57
|
+
if (priority === undefined) {
|
|
58
|
+
throw new InternalError('a conditional format rule reached a serialiser unplanned');
|
|
59
|
+
}
|
|
60
|
+
return priority;
|
|
28
61
|
}
|
|
29
62
|
const SCALE_KINDS = ['dataBar', 'colorScale', 'iconSet'];
|
|
30
63
|
const SCALE_TYPES = new Set(SCALE_KINDS);
|
|
31
|
-
export function conditionalFormattingsXml(formattings, styles) {
|
|
32
|
-
|
|
33
|
-
return '';
|
|
34
|
-
const priority = { next: 1 };
|
|
35
|
-
const extLinks = dataBarExtLinks(formattings);
|
|
36
|
-
return formattings.map((cf) => blockXml(cf, styles, priority, extLinks)).join('');
|
|
64
|
+
export function conditionalFormattingsXml(formattings, styles, plan, formulaNames) {
|
|
65
|
+
return formattings.map((cf) => blockXml(cf, styles, plan, formulaNames)).join('');
|
|
37
66
|
}
|
|
38
|
-
export function conditionalFormattingsExtXml(formattings) {
|
|
39
|
-
const extLinks = dataBarExtLinks(formattings);
|
|
67
|
+
export function conditionalFormattingsExtXml(formattings, styles, plan, formulaNames) {
|
|
40
68
|
const items = [];
|
|
41
69
|
for (const cf of formattings) {
|
|
70
|
+
const whole = cf.rules.filter((rule) => inExtension(cf, rule));
|
|
71
|
+
if (whole.length > 0) {
|
|
72
|
+
const rules = whole.map((rule) => extensionRuleXml(rule, styles, plan, formulaNames));
|
|
73
|
+
items.push(extensionBlockXml(cf.ref, rules.join('')));
|
|
74
|
+
}
|
|
42
75
|
for (const rule of cf.rules) {
|
|
43
|
-
const guid =
|
|
44
|
-
if (guid
|
|
45
|
-
|
|
76
|
+
const guid = plan.extensionIds.get(rule);
|
|
77
|
+
if (guid === undefined || inExtension(cf, rule))
|
|
78
|
+
continue;
|
|
79
|
+
items.push(extensionBlockXml(cf.ref, `<x14:cfRule type="dataBar" id="${guid}">${x14DataBarXml(rule, formulaNames, false)}</x14:cfRule>`));
|
|
46
80
|
}
|
|
47
81
|
}
|
|
48
82
|
if (items.length === 0)
|
|
49
83
|
return '';
|
|
50
84
|
return x14Ext(CF_EXT_URI, `<x14:conditionalFormattings>${items.join('')}</x14:conditionalFormattings>`);
|
|
51
85
|
}
|
|
52
|
-
function
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
86
|
+
function extensionBlockXml(ref, rules) {
|
|
87
|
+
return (`<x14:conditionalFormatting xmlns:xm="${XM_NS}">${rules}` +
|
|
88
|
+
`<xm:sqref>${escapeText(ref)}</xm:sqref></x14:conditionalFormatting>`);
|
|
89
|
+
}
|
|
90
|
+
function extensionRuleXml(rule, styles, plan, formulaNames) {
|
|
91
|
+
const attrs = [typeAttr(rule), `priority="${priorityOf(plan, rule)}"`, ...ruleFlagAttrs(rule)];
|
|
92
|
+
const id = plan.extensionIds.get(rule);
|
|
93
|
+
if (id !== undefined)
|
|
94
|
+
attrs.push(`id="${id}"`);
|
|
95
|
+
const body = (SCALE_TYPES.has(rule.type)
|
|
96
|
+
? extensionScaleXml(rule, formulaNames)
|
|
97
|
+
: operandsXml(rule.formulae, 'xm:f', formulaNames)) + inlineDxfXml(rule, styles);
|
|
98
|
+
return body === ''
|
|
99
|
+
? `<x14:cfRule ${attrs.join(' ')}/>`
|
|
100
|
+
: `<x14:cfRule ${attrs.join(' ')}>${body}</x14:cfRule>`;
|
|
101
|
+
}
|
|
102
|
+
function inlineDxfXml(rule, styles) {
|
|
103
|
+
const id = resolveDxfId(rule, styles);
|
|
104
|
+
const fragment = id === undefined ? undefined : styles.differentialStyleFragment(id);
|
|
105
|
+
const range = fragment === undefined ? undefined : elementRange(fragment, ['dxf']);
|
|
106
|
+
if (fragment === undefined || range === undefined)
|
|
107
|
+
return '';
|
|
108
|
+
return `<x14:dxf>${fragment.slice(range.contentStart, range.contentEnd)}</x14:dxf>`;
|
|
109
|
+
}
|
|
110
|
+
function extensionScaleXml(rule, formulaNames) {
|
|
111
|
+
if (rule.type === 'dataBar')
|
|
112
|
+
return x14DataBarXml(rule, formulaNames, true);
|
|
113
|
+
const cfvoXml = cfvoWriter('x14', formulaNames);
|
|
114
|
+
if (rule.type === 'colorScale') {
|
|
115
|
+
const anchors = (rule.cfvo ?? []).map(cfvoXml).join('');
|
|
116
|
+
const colors = (rule.colors ?? []).map((c) => `<x14:color ${colorAttrs(c)}/>`).join('');
|
|
117
|
+
return `<x14:colorScale>${anchors}${colors}</x14:colorScale>`;
|
|
118
|
+
}
|
|
119
|
+
return iconSetXml(rule, cfvoXml, 'x14');
|
|
120
|
+
}
|
|
121
|
+
function x14DataBarXml(rule, formulaNames, whole) {
|
|
122
|
+
const attrs = intAttr('minLength', rule.minLength, 0) +
|
|
123
|
+
intAttr('maxLength', rule.maxLength, 0) +
|
|
124
|
+
(whole && rule.showValue === false ? ' showValue="0"' : '') +
|
|
125
|
+
boolAttr('border', rule.border) +
|
|
126
|
+
boolAttr('gradient', rule.gradient) +
|
|
127
|
+
tokenAttr('direction', rule.direction, isDataBarDirection, 'data bar direction') +
|
|
128
|
+
boolAttr('negativeBarColorSameAsPositive', rule.negativeBarColorSameAsPositive) +
|
|
129
|
+
boolAttr('negativeBarBorderColorSameAsPositive', rule.negativeBarBorderColorSameAsPositive) +
|
|
130
|
+
tokenAttr('axisPosition', rule.axisPosition, isDataBarAxisPosition, 'data bar axis position');
|
|
131
|
+
const children = dataBarAnchors(rule).map(cfvoWriter('x14', formulaNames)).join('') +
|
|
132
|
+
(whole ? x14ColorXml('fillColor', rule.color ?? DEFAULT_DATABAR_COLOR) : '') +
|
|
133
|
+
x14ColorXml('borderColor', rule.borderColor) +
|
|
134
|
+
x14ColorXml('negativeFillColor', rule.negativeFillColor) +
|
|
135
|
+
x14ColorXml('negativeBorderColor', rule.negativeBorderColor) +
|
|
136
|
+
x14ColorXml('axisColor', rule.axisColor);
|
|
137
|
+
return `<x14:dataBar${attrs}>${children}</x14:dataBar>`;
|
|
138
|
+
}
|
|
139
|
+
function x14ColorXml(name, color) {
|
|
140
|
+
return color === undefined ? '' : `<x14:${name} ${colorAttrs(color)}/>`;
|
|
141
|
+
}
|
|
142
|
+
function tokenAttr(name, value, isValid, kind) {
|
|
143
|
+
return value === undefined ? '' : ` ${name}="${checkedToken(value, isValid, kind)}"`;
|
|
144
|
+
}
|
|
145
|
+
function dataBarAnchors(rule) {
|
|
146
|
+
return rule.cfvo && rule.cfvo.length > 0 ? rule.cfvo : DEFAULT_DATABAR_CFVO;
|
|
147
|
+
}
|
|
148
|
+
function cfvoWriter(form, formulaNames) {
|
|
149
|
+
return (cfvo) => {
|
|
150
|
+
const checked = checkedToken(cfvo.type, isCfValueObjectType, 'conditional format value type');
|
|
151
|
+
const type = form === 'classic' ? (CLASSIC_ANCHOR[cfvo.type] ?? checked) : checked;
|
|
152
|
+
const tag = form === 'classic' ? 'cfvo' : 'x14:cfvo';
|
|
153
|
+
const gte = cfvo.gte === false ? ' gte="0"' : '';
|
|
154
|
+
if (cfvo.value === undefined)
|
|
155
|
+
return `<${tag} type="${type}"${gte}/>`;
|
|
156
|
+
const value = typeof cfvo.value === 'number'
|
|
157
|
+
? numberText(cfvo.value)
|
|
158
|
+
: type === 'formula'
|
|
159
|
+
? mangleFormula(cfvo.value, formulaNames)
|
|
160
|
+
: cfvo.value;
|
|
161
|
+
return form === 'classic'
|
|
162
|
+
? `<${tag} type="${type}"${textAttr('val', value)}${gte}/>`
|
|
163
|
+
: `<${tag} type="${type}"${gte}><xm:f>${escapeText(value)}</xm:f></${tag}>`;
|
|
164
|
+
};
|
|
70
165
|
}
|
|
71
166
|
function cfRuleExtLinkXml(guid) {
|
|
72
167
|
return `<extLst>${x14Ext(DATABAR_LINK_EXT_URI, `<x14:id>${guid}</x14:id>`)}</extLst>`;
|
|
73
168
|
}
|
|
74
|
-
function blockXml(cf, styles,
|
|
75
|
-
const rules = cf.rules
|
|
169
|
+
function blockXml(cf, styles, plan, formulaNames) {
|
|
170
|
+
const rules = cf.rules
|
|
171
|
+
.filter((rule) => !inExtension(cf, rule))
|
|
172
|
+
.map((rule) => ruleXml(rule, styles, plan, formulaNames))
|
|
173
|
+
.join('');
|
|
76
174
|
if (rules === '')
|
|
77
175
|
return '';
|
|
78
176
|
return `<conditionalFormatting sqref="${escapeAttr(cf.ref)}">${rules}</conditionalFormatting>`;
|
|
79
177
|
}
|
|
80
|
-
function ruleXml(rule, styles,
|
|
81
|
-
const
|
|
82
|
-
priority.next = Math.max(priority.next, p) + 1;
|
|
83
|
-
const attrs = [
|
|
84
|
-
`type="${checkedToken(rule.type, isConditionalFormattingType, 'conditional formatting type')}"`,
|
|
85
|
-
];
|
|
178
|
+
function ruleXml(rule, styles, plan, formulaNames) {
|
|
179
|
+
const attrs = [typeAttr(rule)];
|
|
86
180
|
const dxfId = resolveDxfId(rule, styles);
|
|
87
181
|
if (dxfId !== undefined)
|
|
88
182
|
attrs.push(`dxfId="${dxfId}"`);
|
|
89
|
-
attrs.push(`priority="${
|
|
183
|
+
attrs.push(`priority="${priorityOf(plan, rule)}"`, ...ruleFlagAttrs(rule));
|
|
184
|
+
const extGuid = plan.extensionIds.get(rule);
|
|
185
|
+
let body = SCALE_TYPES.has(rule.type)
|
|
186
|
+
? scaleXml(rule, formulaNames, extGuid !== undefined)
|
|
187
|
+
: operandsXml(rule.formulae, 'formula', formulaNames);
|
|
188
|
+
if (extGuid !== undefined)
|
|
189
|
+
body += cfRuleExtLinkXml(extGuid);
|
|
190
|
+
return body === ''
|
|
191
|
+
? `<cfRule ${attrs.join(' ')}/>`
|
|
192
|
+
: `<cfRule ${attrs.join(' ')}>${body}</cfRule>`;
|
|
193
|
+
}
|
|
194
|
+
function typeAttr(rule) {
|
|
195
|
+
return `type="${checkedToken(rule.type, isConditionalFormattingType, 'conditional formatting type')}"`;
|
|
196
|
+
}
|
|
197
|
+
function ruleFlagAttrs(rule) {
|
|
198
|
+
const attrs = [];
|
|
90
199
|
if (rule.stopIfTrue)
|
|
91
200
|
attrs.push('stopIfTrue="1"');
|
|
92
201
|
if (rule.aboveAverage === false)
|
|
@@ -106,16 +215,10 @@ function ruleXml(rule, styles, priority, extLinks) {
|
|
|
106
215
|
attrs.push(`timePeriod="${checkedToken(rule.timePeriod, isCfTimePeriod, 'time period')}"`);
|
|
107
216
|
}
|
|
108
217
|
if (rule.rank !== undefined)
|
|
109
|
-
attrs.push(
|
|
218
|
+
attrs.push(intAttr('rank', rule.rank, 0).trim());
|
|
110
219
|
if (rule.stdDev !== undefined)
|
|
111
|
-
attrs.push(
|
|
112
|
-
|
|
113
|
-
const extGuid = extLinks.get(rule);
|
|
114
|
-
if (extGuid !== undefined)
|
|
115
|
-
body += cfRuleExtLinkXml(extGuid);
|
|
116
|
-
return body === ''
|
|
117
|
-
? `<cfRule ${attrs.join(' ')}/>`
|
|
118
|
-
: `<cfRule ${attrs.join(' ')}>${body}</cfRule>`;
|
|
220
|
+
attrs.push(intAttr('stdDev', rule.stdDev).trim());
|
|
221
|
+
return attrs;
|
|
119
222
|
}
|
|
120
223
|
function resolveDxfId(rule, styles) {
|
|
121
224
|
if (SCALE_TYPES.has(rule.type))
|
|
@@ -127,72 +230,221 @@ function resolveDxfId(rule, styles) {
|
|
|
127
230
|
return styles.differentialStyleId(rule.style);
|
|
128
231
|
return undefined;
|
|
129
232
|
}
|
|
130
|
-
function
|
|
233
|
+
function operandsXml(formulae, tag, formulaNames) {
|
|
131
234
|
if (formulae === undefined)
|
|
132
235
|
return '';
|
|
133
|
-
return formulae
|
|
236
|
+
return formulae
|
|
237
|
+
.map((f) => `<${tag}>${escapeText(mangleFormula(stripFormulaEquals(f), formulaNames))}</${tag}>`)
|
|
238
|
+
.join('');
|
|
134
239
|
}
|
|
135
|
-
function scaleXml(rule) {
|
|
240
|
+
function scaleXml(rule, formulaNames, linked) {
|
|
241
|
+
const cfvoXml = cfvoWriter('classic', formulaNames);
|
|
136
242
|
if (rule.type === 'dataBar')
|
|
137
|
-
return dataBarXml(rule);
|
|
243
|
+
return dataBarXml(rule, cfvoXml, linked);
|
|
138
244
|
if (rule.type === 'colorScale')
|
|
139
|
-
return colorScaleXml(rule);
|
|
140
|
-
return iconSetXml(rule);
|
|
245
|
+
return colorScaleXml(rule, cfvoXml);
|
|
246
|
+
return iconSetXml(rule, cfvoXml, 'classic');
|
|
141
247
|
}
|
|
142
|
-
function dataBarXml(rule) {
|
|
143
|
-
const cfvo = rule.cfvo && rule.cfvo.length > 0 ? rule.cfvo : DEFAULT_DATABAR_CFVO;
|
|
248
|
+
function dataBarXml(rule, cfvoXml, linked) {
|
|
144
249
|
const color = rule.color ?? DEFAULT_DATABAR_COLOR;
|
|
145
|
-
const anchors =
|
|
146
|
-
|
|
250
|
+
const anchors = dataBarAnchors(rule).map(cfvoXml).join('');
|
|
251
|
+
const lengths = linked
|
|
252
|
+
? ''
|
|
253
|
+
: intAttr('minLength', rule.minLength, 0) + intAttr('maxLength', rule.maxLength, 0);
|
|
254
|
+
const showValue = rule.showValue === false ? ' showValue="0"' : '';
|
|
255
|
+
return `<dataBar${lengths}${showValue}>${anchors}<color ${colorAttrs(color)}/></dataBar>`;
|
|
147
256
|
}
|
|
148
|
-
function colorScaleXml(rule) {
|
|
257
|
+
function colorScaleXml(rule, cfvoXml) {
|
|
149
258
|
const anchors = (rule.cfvo ?? []).map(cfvoXml).join('');
|
|
150
259
|
const colors = (rule.colors ?? []).map((c) => `<color ${colorAttrs(c)}/>`).join('');
|
|
151
260
|
return `<colorScale>${anchors}${colors}</colorScale>`;
|
|
152
261
|
}
|
|
153
|
-
function iconSetXml(rule) {
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
262
|
+
function iconSetXml(rule, cfvoXml, form) {
|
|
263
|
+
const tag = form === 'classic' ? 'iconSet' : 'x14:iconSet';
|
|
264
|
+
const icons = form === 'x14' ? (rule.icons ?? []) : [];
|
|
265
|
+
const attrs = tokenAttr('iconSet', rule.iconSet, isIconSetType, 'icon set') +
|
|
266
|
+
(rule.showValue === false ? ' showValue="0"' : '') +
|
|
267
|
+
(rule.reverse ? ' reverse="1"' : '') +
|
|
268
|
+
(icons.length > 0 ? ' custom="1"' : '');
|
|
157
269
|
const anchors = (rule.cfvo ?? []).map(cfvoXml).join('');
|
|
158
|
-
return
|
|
270
|
+
return `<${tag}${attrs}>${anchors}${icons.map(cfIconXml).join('')}</${tag}>`;
|
|
159
271
|
}
|
|
160
|
-
function
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
272
|
+
function cfIconXml(icon) {
|
|
273
|
+
const iconSet = checkedToken(icon.iconSet, isCfIconSetType, 'custom icon set');
|
|
274
|
+
return `<x14:cfIcon iconSet="${iconSet}"${intAttr('iconId', icon.iconId, 0)}/>`;
|
|
275
|
+
}
|
|
276
|
+
class DxfCapture {
|
|
277
|
+
#xml = '<dxf>';
|
|
278
|
+
#depth = 0;
|
|
279
|
+
#skippingFrom;
|
|
280
|
+
open(name, attrs, selfClosing, scope) {
|
|
281
|
+
const local = localName(name);
|
|
282
|
+
if (this.#skippingFrom === undefined) {
|
|
283
|
+
if (isMainNamespaceElement(scope, name) && local !== 'extLst') {
|
|
284
|
+
const attributes = Object.entries(attrs)
|
|
285
|
+
.filter(([key]) => key !== 'xmlns' && !key.includes(':'))
|
|
286
|
+
.map(([key, value]) => ` ${key}="${escapeAttr(value)}"`)
|
|
287
|
+
.join('');
|
|
288
|
+
this.#xml += `<${local}${attributes}${selfClosing ? '/>' : '>'}`;
|
|
289
|
+
}
|
|
290
|
+
else if (!selfClosing) {
|
|
291
|
+
this.#skippingFrom = this.#depth;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (!selfClosing)
|
|
295
|
+
this.#depth += 1;
|
|
296
|
+
}
|
|
297
|
+
close(name) {
|
|
298
|
+
if (this.#depth === 0) {
|
|
299
|
+
this.#xml += '</dxf>';
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
this.#depth -= 1;
|
|
303
|
+
if (this.#skippingFrom === undefined)
|
|
304
|
+
this.#xml += `</${localName(name)}>`;
|
|
305
|
+
else if (this.#skippingFrom === this.#depth)
|
|
306
|
+
this.#skippingFrom = undefined;
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
get fragment() {
|
|
310
|
+
return this.#xml;
|
|
311
|
+
}
|
|
164
312
|
}
|
|
165
|
-
export function conditionalFormattingPass() {
|
|
313
|
+
export function conditionalFormattingPass(definedNames, adoptDifferentialStyle) {
|
|
166
314
|
const blocks = [];
|
|
167
315
|
let block;
|
|
168
316
|
let draft;
|
|
169
317
|
let scale;
|
|
170
318
|
const formulaCapture = new TextCapture('formula');
|
|
171
319
|
const linked = [];
|
|
320
|
+
const linkedIds = new Set();
|
|
172
321
|
const extById = new Map();
|
|
173
|
-
let x14Ext;
|
|
174
|
-
let x14ExtId;
|
|
175
322
|
const x14IdCapture = new TextCapture('id');
|
|
323
|
+
let extRules;
|
|
324
|
+
let extRule;
|
|
325
|
+
let extCfvo;
|
|
326
|
+
let extSqref = '';
|
|
327
|
+
const extCapture = new TextCapture(['f', 'sqref']);
|
|
328
|
+
let dxf;
|
|
329
|
+
const closeExtensionRule = () => {
|
|
330
|
+
if (extRule === undefined)
|
|
331
|
+
return;
|
|
332
|
+
const { draft: ruleDraft, id } = extRule;
|
|
333
|
+
extRule = undefined;
|
|
334
|
+
extCfvo = undefined;
|
|
335
|
+
if (id !== undefined && linkedIds.has(id)) {
|
|
336
|
+
extById.set(id, { bar: ruleDraft.bar, cfvo: ruleDraft.cfvo });
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
if (ruleDraft.dxf !== undefined)
|
|
340
|
+
ruleDraft.dxfId = String(adoptDifferentialStyle(ruleDraft.dxf));
|
|
341
|
+
const rule = finalizeRule(ruleDraft);
|
|
342
|
+
if (rule !== undefined)
|
|
343
|
+
extRules?.push(rule);
|
|
344
|
+
};
|
|
345
|
+
const openExtension = (ln, attrs, selfClosing) => {
|
|
346
|
+
if (ln === 'id' && draft !== undefined) {
|
|
347
|
+
x14IdCapture.open(ln, selfClosing);
|
|
348
|
+
}
|
|
349
|
+
else if (ln === 'conditionalFormatting') {
|
|
350
|
+
extRules = [];
|
|
351
|
+
extSqref = '';
|
|
352
|
+
}
|
|
353
|
+
else if (ln === 'cfRule') {
|
|
354
|
+
extRule = { draft: newDraft(attrs), id: attrs.id };
|
|
355
|
+
if (selfClosing)
|
|
356
|
+
closeExtensionRule();
|
|
357
|
+
}
|
|
358
|
+
else if (extRule === undefined) {
|
|
359
|
+
if (extRules !== undefined && ln === 'sqref')
|
|
360
|
+
extCapture.open(ln, selfClosing);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
readExtensionRuleChild(extRule.draft, ln, attrs, selfClosing);
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
const readExtensionRuleChild = (rule, ln, attrs, selfClosing) => {
|
|
367
|
+
switch (ln) {
|
|
368
|
+
case 'dataBar':
|
|
369
|
+
readDataBarAttrs(rule, attrs);
|
|
370
|
+
break;
|
|
371
|
+
case 'iconSet':
|
|
372
|
+
readIconSetAttrs(rule, attrs);
|
|
373
|
+
break;
|
|
374
|
+
case 'cfvo':
|
|
375
|
+
extCfvo = parseCfvo(attrs, definedNames);
|
|
376
|
+
rule.cfvo.push(extCfvo);
|
|
377
|
+
if (selfClosing)
|
|
378
|
+
extCfvo = undefined;
|
|
379
|
+
break;
|
|
380
|
+
case 'f':
|
|
381
|
+
extCapture.open(ln, selfClosing);
|
|
382
|
+
break;
|
|
383
|
+
case 'color':
|
|
384
|
+
rule.colors.push(parseColor(attrs));
|
|
385
|
+
break;
|
|
386
|
+
case 'fillColor':
|
|
387
|
+
rule.color = parseColor(attrs);
|
|
388
|
+
break;
|
|
389
|
+
case 'borderColor':
|
|
390
|
+
case 'negativeFillColor':
|
|
391
|
+
case 'negativeBorderColor':
|
|
392
|
+
case 'axisColor':
|
|
393
|
+
rule.bar[ln] = parseColor(attrs);
|
|
394
|
+
break;
|
|
395
|
+
case 'cfIcon': {
|
|
396
|
+
const icon = parseCfIcon(attrs);
|
|
397
|
+
if (icon === undefined)
|
|
398
|
+
rule.icons = undefined;
|
|
399
|
+
else
|
|
400
|
+
rule.icons?.push(icon);
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
case 'dxf':
|
|
404
|
+
if (selfClosing)
|
|
405
|
+
rule.dxf = '<dxf/>';
|
|
406
|
+
else
|
|
407
|
+
dxf = new DxfCapture();
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
const closeExtension = (ln) => {
|
|
412
|
+
const id = x14IdCapture.close(ln);
|
|
413
|
+
if (id !== undefined) {
|
|
414
|
+
if (draft !== undefined)
|
|
415
|
+
draft.x14Id = id;
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
const text = extCapture.close(ln);
|
|
419
|
+
if (text !== undefined) {
|
|
420
|
+
if (ln === 'sqref')
|
|
421
|
+
extSqref = text;
|
|
422
|
+
else if (extCfvo !== undefined)
|
|
423
|
+
extCfvo.value = anchorValue(extCfvo.type, text, definedNames);
|
|
424
|
+
else
|
|
425
|
+
extRule?.draft.formulae.push(coerceNumericLiteral(unmangleFunctions(text, definedNames)));
|
|
426
|
+
}
|
|
427
|
+
else if (ln === 'cfvo') {
|
|
428
|
+
extCfvo = undefined;
|
|
429
|
+
}
|
|
430
|
+
else if (ln === 'cfRule') {
|
|
431
|
+
closeExtensionRule();
|
|
432
|
+
}
|
|
433
|
+
else if (ln === 'conditionalFormatting' && extRules !== undefined) {
|
|
434
|
+
if (extRules.length > 0)
|
|
435
|
+
blocks.push({ ref: extSqref, rules: extRules, extended: true });
|
|
436
|
+
extRules = undefined;
|
|
437
|
+
}
|
|
438
|
+
};
|
|
176
439
|
const handlers = {
|
|
177
|
-
onOpen(name, attrs, selfClosing) {
|
|
440
|
+
onOpen(name, attrs, selfClosing, scope) {
|
|
441
|
+
if (dxf !== undefined) {
|
|
442
|
+
dxf.open(name, attrs, selfClosing, scope);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
178
445
|
const ln = localName(name);
|
|
179
|
-
if (name
|
|
180
|
-
|
|
181
|
-
x14IdCapture.open(ln, selfClosing);
|
|
182
|
-
}
|
|
183
|
-
else if (ln === 'cfRule') {
|
|
184
|
-
x14Ext = attrs.type === 'dataBar' && attrs.id !== undefined ? emptyExt() : undefined;
|
|
185
|
-
x14ExtId = attrs.id;
|
|
186
|
-
}
|
|
187
|
-
else if (x14Ext !== undefined && ln === 'dataBar') {
|
|
188
|
-
x14Ext.gradient = boolPresent(attrs.gradient);
|
|
189
|
-
}
|
|
190
|
-
else if (x14Ext !== undefined && ln === 'negativeFillColor') {
|
|
191
|
-
x14Ext.negativeFillColor = parseColor(attrs);
|
|
192
|
-
}
|
|
193
|
-
else if (x14Ext !== undefined && ln === 'axisColor') {
|
|
194
|
-
x14Ext.axisColor = parseColor(attrs);
|
|
195
|
-
}
|
|
446
|
+
if (isExtensionElement(scope, name)) {
|
|
447
|
+
openExtension(ln, attrs, selfClosing);
|
|
196
448
|
return;
|
|
197
449
|
}
|
|
198
450
|
if (ln === 'conditionalFormatting') {
|
|
@@ -213,10 +465,12 @@ export function conditionalFormattingPass() {
|
|
|
213
465
|
(ln === 'dataBar' || ln === 'colorScale' || ln === 'iconSet')) {
|
|
214
466
|
scale = ln;
|
|
215
467
|
if (ln === 'iconSet')
|
|
216
|
-
draft
|
|
468
|
+
readIconSetAttrs(draft, attrs);
|
|
469
|
+
else if (ln === 'dataBar')
|
|
470
|
+
readDataBarAttrs(draft, attrs);
|
|
217
471
|
}
|
|
218
472
|
else if (draft !== undefined && ln === 'cfvo') {
|
|
219
|
-
draft.cfvo.push(parseCfvo(attrs));
|
|
473
|
+
draft.cfvo.push(parseCfvo(attrs, definedNames));
|
|
220
474
|
}
|
|
221
475
|
else if (draft !== undefined && ln === 'color') {
|
|
222
476
|
const color = parseColor(attrs);
|
|
@@ -232,26 +486,27 @@ export function conditionalFormattingPass() {
|
|
|
232
486
|
onText(chunk) {
|
|
233
487
|
formulaCapture.text(chunk);
|
|
234
488
|
x14IdCapture.text(chunk);
|
|
489
|
+
extCapture.text(chunk);
|
|
235
490
|
},
|
|
236
|
-
onClose(name) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
draft.x14Id = id;
|
|
243
|
-
}
|
|
244
|
-
else if (ln === 'cfRule' && x14Ext !== undefined && x14ExtId !== undefined) {
|
|
245
|
-
extById.set(x14ExtId, x14Ext);
|
|
246
|
-
x14Ext = undefined;
|
|
247
|
-
x14ExtId = undefined;
|
|
491
|
+
onClose(name, scope) {
|
|
492
|
+
if (dxf !== undefined) {
|
|
493
|
+
if (dxf.close(name)) {
|
|
494
|
+
if (extRule !== undefined)
|
|
495
|
+
extRule.draft.dxf = dxf.fragment;
|
|
496
|
+
dxf = undefined;
|
|
248
497
|
}
|
|
249
498
|
return;
|
|
250
499
|
}
|
|
500
|
+
const ln = localName(name);
|
|
501
|
+
if (isExtensionElement(scope, name)) {
|
|
502
|
+
closeExtension(ln);
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
251
505
|
const formula = formulaCapture.close(ln);
|
|
252
506
|
if (formula !== undefined) {
|
|
253
|
-
if (draft !== undefined)
|
|
254
|
-
draft.formulae.push(coerceNumericLiteral(formula));
|
|
507
|
+
if (draft !== undefined) {
|
|
508
|
+
draft.formulae.push(coerceNumericLiteral(unmangleFunctions(formula, definedNames)));
|
|
509
|
+
}
|
|
255
510
|
}
|
|
256
511
|
else if (ln === 'dataBar' || ln === 'colorScale' || ln === 'iconSet') {
|
|
257
512
|
scale = undefined;
|
|
@@ -261,8 +516,10 @@ export function conditionalFormattingPass() {
|
|
|
261
516
|
if (rule !== undefined) {
|
|
262
517
|
if (block !== undefined)
|
|
263
518
|
block.rules.push(rule);
|
|
264
|
-
if (draft.x14Id !== undefined)
|
|
519
|
+
if (draft.x14Id !== undefined) {
|
|
265
520
|
linked.push({ rule, id: draft.x14Id });
|
|
521
|
+
linkedIds.add(draft.x14Id);
|
|
522
|
+
}
|
|
266
523
|
}
|
|
267
524
|
draft = undefined;
|
|
268
525
|
}
|
|
@@ -277,47 +534,77 @@ export function conditionalFormattingPass() {
|
|
|
277
534
|
const ext = extById.get(id);
|
|
278
535
|
if (ext === undefined)
|
|
279
536
|
continue;
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
rule.negativeFillColor = ext.negativeFillColor;
|
|
284
|
-
if (ext.axisColor !== undefined)
|
|
285
|
-
rule.axisColor = ext.axisColor;
|
|
537
|
+
Object.assign(rule, ext.bar);
|
|
538
|
+
if (ext.cfvo.length > 0)
|
|
539
|
+
rule.cfvo = [...ext.cfvo];
|
|
286
540
|
}
|
|
287
541
|
return blocks;
|
|
288
542
|
};
|
|
289
543
|
return { handlers, result };
|
|
290
544
|
}
|
|
291
|
-
function
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
545
|
+
export function applyConditionalFormattings(sheet, blocks) {
|
|
546
|
+
for (const block of blocks) {
|
|
547
|
+
if (decodeSqrefRects(block.ref).length === 0)
|
|
548
|
+
continue;
|
|
549
|
+
admitting(() => {
|
|
550
|
+
sheet.addConditionalFormatting(block);
|
|
551
|
+
});
|
|
552
|
+
}
|
|
297
553
|
}
|
|
298
554
|
function newDraft(attrs) {
|
|
299
555
|
return {
|
|
300
556
|
type: enumToken(attrs.type, isConditionalFormattingType),
|
|
301
|
-
priority:
|
|
557
|
+
priority: numInteger(attrs.priority),
|
|
302
558
|
stopIfTrue: boolStrict(attrs.stopIfTrue),
|
|
303
559
|
operator: enumToken(attrs.operator, isConditionalFormattingOperator),
|
|
304
560
|
text: attrs.text,
|
|
305
561
|
timePeriod: enumToken(attrs.timePeriod, isCfTimePeriod),
|
|
306
|
-
rank:
|
|
307
|
-
stdDev:
|
|
562
|
+
rank: numInteger(attrs.rank, 0),
|
|
563
|
+
stdDev: numInteger(attrs.stdDev),
|
|
308
564
|
percent: boolStrict(attrs.percent),
|
|
309
565
|
bottom: boolStrict(attrs.bottom),
|
|
310
|
-
aboveAverage:
|
|
566
|
+
aboveAverage: boolTristate(attrs.aboveAverage),
|
|
311
567
|
equalAverage: boolStrict(attrs.equalAverage),
|
|
312
568
|
dxfId: parseIndexAttr(attrs.dxfId),
|
|
313
569
|
iconSet: undefined,
|
|
570
|
+
icons: [],
|
|
571
|
+
reverse: false,
|
|
572
|
+
showValue: undefined,
|
|
314
573
|
formulae: [],
|
|
315
574
|
cfvo: [],
|
|
316
575
|
colors: [],
|
|
317
576
|
color: undefined,
|
|
577
|
+
bar: {},
|
|
318
578
|
x14Id: undefined,
|
|
579
|
+
dxf: undefined,
|
|
319
580
|
};
|
|
320
581
|
}
|
|
582
|
+
function readIconSetAttrs(draft, attrs) {
|
|
583
|
+
draft.iconSet = enumToken(attrs.iconSet, isIconSetType);
|
|
584
|
+
draft.showValue = boolTristate(attrs.showValue);
|
|
585
|
+
draft.reverse = boolStrict(attrs.reverse);
|
|
586
|
+
}
|
|
587
|
+
function readDataBarAttrs(draft, attrs) {
|
|
588
|
+
const { bar } = draft;
|
|
589
|
+
draft.showValue = boolTristate(attrs.showValue);
|
|
590
|
+
setDefined(bar, 'minLength', numInteger(attrs.minLength, 0));
|
|
591
|
+
setDefined(bar, 'maxLength', numInteger(attrs.maxLength, 0));
|
|
592
|
+
setDefined(bar, 'border', boolTristate(attrs.border));
|
|
593
|
+
setDefined(bar, 'gradient', boolTristate(attrs.gradient));
|
|
594
|
+
setDefined(bar, 'direction', enumToken(attrs.direction, isDataBarDirection));
|
|
595
|
+
setDefined(bar, 'negativeBarColorSameAsPositive', boolTristate(attrs.negativeBarColorSameAsPositive));
|
|
596
|
+
setDefined(bar, 'negativeBarBorderColorSameAsPositive', boolTristate(attrs.negativeBarBorderColorSameAsPositive));
|
|
597
|
+
setDefined(bar, 'axisPosition', enumToken(attrs.axisPosition, isDataBarAxisPosition));
|
|
598
|
+
}
|
|
599
|
+
function setDefined(bar, key, value) {
|
|
600
|
+
if (value !== undefined)
|
|
601
|
+
bar[key] = value;
|
|
602
|
+
}
|
|
603
|
+
function parseCfIcon(attrs) {
|
|
604
|
+
const iconSet = enumToken(attrs.iconSet, isCfIconSetType);
|
|
605
|
+
const iconId = numInteger(attrs.iconId, 0);
|
|
606
|
+
return iconSet === undefined || iconId === undefined ? undefined : { iconSet, iconId };
|
|
607
|
+
}
|
|
321
608
|
function dxfIndex(value) {
|
|
322
609
|
return numInteger(value, 0);
|
|
323
610
|
}
|
|
@@ -354,6 +641,12 @@ function finalizeRule(draft) {
|
|
|
354
641
|
rule.dxfId = draft.dxfId;
|
|
355
642
|
if (draft.iconSet !== undefined)
|
|
356
643
|
rule.iconSet = draft.iconSet;
|
|
644
|
+
if (draft.icons !== undefined && draft.icons.length > 0)
|
|
645
|
+
rule.icons = draft.icons;
|
|
646
|
+
if (draft.reverse)
|
|
647
|
+
rule.reverse = true;
|
|
648
|
+
if (draft.showValue === false)
|
|
649
|
+
rule.showValue = false;
|
|
357
650
|
if (draft.formulae.length > 0)
|
|
358
651
|
rule.formulae = draft.formulae;
|
|
359
652
|
if (draft.cfvo.length > 0)
|
|
@@ -362,14 +655,20 @@ function finalizeRule(draft) {
|
|
|
362
655
|
rule.colors = draft.colors;
|
|
363
656
|
if (draft.color !== undefined)
|
|
364
657
|
rule.color = draft.color;
|
|
658
|
+
if (draft.type === 'dataBar')
|
|
659
|
+
Object.assign(rule, draft.bar);
|
|
365
660
|
return rule;
|
|
366
661
|
}
|
|
367
|
-
function parseCfvo(attrs) {
|
|
662
|
+
function parseCfvo(attrs, definedNames) {
|
|
368
663
|
const raw = attrs.type;
|
|
369
664
|
const type = raw !== undefined && isCfValueObjectType(raw) ? raw : 'num';
|
|
370
665
|
const cfvo = { type };
|
|
371
|
-
if (attrs.val !== undefined)
|
|
372
|
-
cfvo.value = type
|
|
373
|
-
|
|
666
|
+
if (attrs.val !== undefined)
|
|
667
|
+
cfvo.value = anchorValue(type, attrs.val, definedNames);
|
|
668
|
+
if (boolTristate(attrs.gte) === false)
|
|
669
|
+
cfvo.gte = false;
|
|
374
670
|
return cfvo;
|
|
375
671
|
}
|
|
672
|
+
function anchorValue(type, text, definedNames) {
|
|
673
|
+
return type === 'formula' ? unmangleFunctions(text, definedNames) : coerceNumericLiteral(text);
|
|
674
|
+
}
|