@omegagrid/grid-core 0.10.2 → 0.10.4

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.
Files changed (201) hide show
  1. package/dist/__generated/functions.d.ts +4 -0
  2. package/dist/__generated/functions.d.ts.map +1 -0
  3. package/dist/__generated/functions.js +45 -0
  4. package/dist/__generated/functions.js.map +1 -0
  5. package/dist/calculations/autofill.d.ts +7 -0
  6. package/dist/calculations/autofill.d.ts.map +1 -0
  7. package/dist/calculations/autofill.js +84 -0
  8. package/dist/calculations/autofill.js.map +1 -0
  9. package/dist/calculations/conditions.d.ts +4 -0
  10. package/dist/calculations/conditions.d.ts.map +1 -0
  11. package/dist/calculations/conditions.js +41 -0
  12. package/dist/calculations/conditions.js.map +1 -0
  13. package/dist/calculations/context.d.ts +53 -0
  14. package/dist/calculations/context.d.ts.map +1 -0
  15. package/dist/calculations/context.js +85 -0
  16. package/dist/calculations/context.js.map +1 -0
  17. package/dist/calculations/formula.d.ts +89 -0
  18. package/dist/calculations/formula.d.ts.map +1 -0
  19. package/dist/calculations/formula.js +443 -0
  20. package/dist/calculations/formula.js.map +1 -0
  21. package/dist/calculations/functions/dates.d.ts +13 -0
  22. package/dist/calculations/functions/dates.d.ts.map +1 -0
  23. package/dist/calculations/functions/dates.js +58 -0
  24. package/dist/calculations/functions/dates.js.map +1 -0
  25. package/dist/calculations/functions/index.d.ts +11 -0
  26. package/dist/calculations/functions/index.d.ts.map +1 -0
  27. package/dist/calculations/functions/index.js +21 -0
  28. package/dist/calculations/functions/index.js.map +1 -0
  29. package/dist/calculations/functions/logical.d.ts +11 -0
  30. package/dist/calculations/functions/logical.d.ts.map +1 -0
  31. package/dist/calculations/functions/logical.js +50 -0
  32. package/dist/calculations/functions/logical.js.map +1 -0
  33. package/dist/calculations/functions/lookup.d.ts +18 -0
  34. package/dist/calculations/functions/lookup.d.ts.map +1 -0
  35. package/dist/calculations/functions/lookup.js +169 -0
  36. package/dist/calculations/functions/lookup.js.map +1 -0
  37. package/dist/calculations/functions/math.d.ts +72 -0
  38. package/dist/calculations/functions/math.d.ts.map +1 -0
  39. package/dist/calculations/functions/math.js +182 -0
  40. package/dist/calculations/functions/math.js.map +1 -0
  41. package/dist/calculations/functions/special.d.ts +2 -0
  42. package/dist/calculations/functions/special.d.ts.map +1 -0
  43. package/dist/calculations/functions/special.js +51 -0
  44. package/dist/calculations/functions/special.js.map +1 -0
  45. package/dist/calculations/functions/statistical.d.ts +7 -0
  46. package/dist/calculations/functions/statistical.d.ts.map +1 -0
  47. package/dist/calculations/functions/statistical.js +47 -0
  48. package/dist/calculations/functions/statistical.js.map +1 -0
  49. package/dist/calculations/functions/text.d.ts +29 -0
  50. package/dist/calculations/functions/text.d.ts.map +1 -0
  51. package/dist/calculations/functions/text.js +58 -0
  52. package/dist/calculations/functions/text.js.map +1 -0
  53. package/dist/calculations/helpers.d.ts +13 -0
  54. package/dist/calculations/helpers.d.ts.map +1 -0
  55. package/dist/calculations/helpers.js +32 -0
  56. package/dist/calculations/helpers.js.map +1 -0
  57. package/dist/calculations/index.d.ts +7 -0
  58. package/dist/calculations/index.d.ts.map +1 -0
  59. package/dist/calculations/index.js +7 -0
  60. package/dist/calculations/index.js.map +1 -0
  61. package/dist/calculations/operators.d.ts +19 -0
  62. package/dist/calculations/operators.d.ts.map +1 -0
  63. package/dist/calculations/operators.js +58 -0
  64. package/dist/calculations/operators.js.map +1 -0
  65. package/dist/calculations/tokenization.d.ts +36 -0
  66. package/dist/calculations/tokenization.d.ts.map +1 -0
  67. package/dist/calculations/tokenization.js +203 -0
  68. package/dist/calculations/tokenization.js.map +1 -0
  69. package/dist/common/index.d.ts +2 -0
  70. package/dist/common/index.d.ts.map +1 -0
  71. package/dist/common/index.js +2 -0
  72. package/dist/common/index.js.map +1 -0
  73. package/dist/common/range.d.ts +66 -0
  74. package/dist/common/range.d.ts.map +1 -0
  75. package/dist/common/range.js +222 -0
  76. package/dist/common/range.js.map +1 -0
  77. package/dist/constants.d.ts +68 -0
  78. package/dist/constants.d.ts.map +1 -0
  79. package/dist/constants.js +127 -0
  80. package/dist/constants.js.map +1 -0
  81. package/dist/index.d.ts +8 -0
  82. package/dist/index.d.ts.map +1 -0
  83. package/dist/index.js +8 -0
  84. package/dist/index.js.map +1 -0
  85. package/dist/model/calculationModel.d.ts +30 -0
  86. package/dist/model/calculationModel.d.ts.map +1 -0
  87. package/dist/model/calculationModel.js +206 -0
  88. package/dist/model/calculationModel.js.map +1 -0
  89. package/dist/model/cellModel.d.ts +134 -0
  90. package/dist/model/cellModel.d.ts.map +1 -0
  91. package/dist/model/cellModel.js +371 -0
  92. package/dist/model/cellModel.js.map +1 -0
  93. package/dist/model/columnModel.d.ts +160 -0
  94. package/dist/model/columnModel.d.ts.map +1 -0
  95. package/dist/model/columnModel.js +159 -0
  96. package/dist/model/columnModel.js.map +1 -0
  97. package/dist/model/commentModel.d.ts +58 -0
  98. package/dist/model/commentModel.d.ts.map +1 -0
  99. package/dist/model/commentModel.js +81 -0
  100. package/dist/model/commentModel.js.map +1 -0
  101. package/dist/model/conditionalFormats.d.ts +104 -0
  102. package/dist/model/conditionalFormats.d.ts.map +1 -0
  103. package/dist/model/conditionalFormats.js +414 -0
  104. package/dist/model/conditionalFormats.js.map +1 -0
  105. package/dist/model/cssStyle.d.ts +20 -0
  106. package/dist/model/cssStyle.d.ts.map +1 -0
  107. package/dist/model/cssStyle.js +301 -0
  108. package/dist/model/cssStyle.js.map +1 -0
  109. package/dist/model/dependencies.d.ts +30 -0
  110. package/dist/model/dependencies.d.ts.map +1 -0
  111. package/dist/model/dependencies.js +139 -0
  112. package/dist/model/dependencies.js.map +1 -0
  113. package/dist/model/dependencyModel.d.ts +9 -0
  114. package/dist/model/dependencyModel.d.ts.map +1 -0
  115. package/dist/model/dependencyModel.js +9 -0
  116. package/dist/model/dependencyModel.js.map +1 -0
  117. package/dist/model/elementModel.d.ts +103 -0
  118. package/dist/model/elementModel.d.ts.map +1 -0
  119. package/dist/model/elementModel.js +181 -0
  120. package/dist/model/elementModel.js.map +1 -0
  121. package/dist/model/filterModel.d.ts +35 -0
  122. package/dist/model/filterModel.d.ts.map +1 -0
  123. package/dist/model/filterModel.js +153 -0
  124. package/dist/model/filterModel.js.map +1 -0
  125. package/dist/model/gridModel.d.ts +181 -0
  126. package/dist/model/gridModel.d.ts.map +1 -0
  127. package/dist/model/gridModel.js +797 -0
  128. package/dist/model/gridModel.js.map +1 -0
  129. package/dist/model/groupModel.d.ts +26 -0
  130. package/dist/model/groupModel.d.ts.map +1 -0
  131. package/dist/model/groupModel.js +112 -0
  132. package/dist/model/groupModel.js.map +1 -0
  133. package/dist/model/history.d.ts +24 -0
  134. package/dist/model/history.d.ts.map +1 -0
  135. package/dist/model/history.js +35 -0
  136. package/dist/model/history.js.map +1 -0
  137. package/dist/model/index.d.ts +23 -0
  138. package/dist/model/index.d.ts.map +1 -0
  139. package/dist/model/index.js +23 -0
  140. package/dist/model/index.js.map +1 -0
  141. package/dist/model/iterableRange.d.ts +49 -0
  142. package/dist/model/iterableRange.d.ts.map +1 -0
  143. package/dist/model/iterableRange.js +108 -0
  144. package/dist/model/iterableRange.js.map +1 -0
  145. package/dist/model/merges.d.ts +34 -0
  146. package/dist/model/merges.d.ts.map +1 -0
  147. package/dist/model/merges.js +123 -0
  148. package/dist/model/merges.js.map +1 -0
  149. package/dist/model/namingModel.d.ts +25 -0
  150. package/dist/model/namingModel.d.ts.map +1 -0
  151. package/dist/model/namingModel.js +77 -0
  152. package/dist/model/namingModel.js.map +1 -0
  153. package/dist/model/options.d.ts +257 -0
  154. package/dist/model/options.d.ts.map +1 -0
  155. package/dist/model/options.js +35 -0
  156. package/dist/model/options.js.map +1 -0
  157. package/dist/model/rowModel.d.ts +104 -0
  158. package/dist/model/rowModel.d.ts.map +1 -0
  159. package/dist/model/rowModel.js +155 -0
  160. package/dist/model/rowModel.js.map +1 -0
  161. package/dist/model/selectionModel.d.ts +19 -0
  162. package/dist/model/selectionModel.d.ts.map +1 -0
  163. package/dist/model/selectionModel.js +40 -0
  164. package/dist/model/selectionModel.js.map +1 -0
  165. package/dist/model/sortingModel.d.ts +46 -0
  166. package/dist/model/sortingModel.d.ts.map +1 -0
  167. package/dist/model/sortingModel.js +157 -0
  168. package/dist/model/sortingModel.js.map +1 -0
  169. package/dist/model/style.d.ts +90 -0
  170. package/dist/model/style.d.ts.map +1 -0
  171. package/dist/model/style.js +34 -0
  172. package/dist/model/style.js.map +1 -0
  173. package/dist/model/styleModel.d.ts +22 -0
  174. package/dist/model/styleModel.d.ts.map +1 -0
  175. package/dist/model/styleModel.js +91 -0
  176. package/dist/model/styleModel.js.map +1 -0
  177. package/dist/model/tableTheme.d.ts +46 -0
  178. package/dist/model/tableTheme.d.ts.map +1 -0
  179. package/dist/model/tableTheme.js +93 -0
  180. package/dist/model/tableTheme.js.map +1 -0
  181. package/dist/model/validations.d.ts +5 -0
  182. package/dist/model/validations.d.ts.map +1 -0
  183. package/dist/model/validations.js +24 -0
  184. package/dist/model/validations.js.map +1 -0
  185. package/dist/sparklines/index.d.ts +2 -0
  186. package/dist/sparklines/index.d.ts.map +1 -0
  187. package/dist/sparklines/index.js +2 -0
  188. package/dist/sparklines/index.js.map +1 -0
  189. package/dist/sparklines/sparklines.d.ts +59 -0
  190. package/dist/sparklines/sparklines.d.ts.map +1 -0
  191. package/dist/sparklines/sparklines.js +176 -0
  192. package/dist/sparklines/sparklines.js.map +1 -0
  193. package/dist/types.d.ts +103 -0
  194. package/dist/types.d.ts.map +1 -0
  195. package/dist/types.js +2 -0
  196. package/dist/types.js.map +1 -0
  197. package/dist/utils.d.ts +4 -0
  198. package/dist/utils.d.ts.map +1 -0
  199. package/dist/utils.js +11 -0
  200. package/dist/utils.js.map +1 -0
  201. package/package.json +3 -3
@@ -0,0 +1,797 @@
1
+ import { tree } from "@omegagrid/core";
2
+ import { log } from "@omegagrid/core";
3
+ import { CalculationModel } from "./calculationModel";
4
+ import { CellRange } from "../common/range";
5
+ import { ConditionalFormats } from "./conditionalFormats";
6
+ import { Sparklines } from "../sparklines/sparklines";
7
+ import { ColumnModel } from "./columnModel";
8
+ import { CommentModel } from "./commentModel";
9
+ import { IterableAxisRange, IterableRange } from "./iterableRange";
10
+ import { NamingModel } from "./namingModel";
11
+ import { initOptions } from "./options";
12
+ import { RowModel } from "./rowModel";
13
+ import { StyleModel } from "./styleModel";
14
+ import { applyCellTheme, applyRowTheme, applyTheme } from "./tableTheme";
15
+ import { SortingModel } from "./sortingModel";
16
+ import { Merges } from "./merges";
17
+ import { FilterModel } from "./filterModel";
18
+ const DEFAULT_SOURCE_KEYS = [
19
+ 'index', 'name', 'rows', 'columns', 'cells', 'options', 'sparklines',
20
+ 'rules', 'comments', 'styles', 'names', 'props', 'tab', 'theme'
21
+ ];
22
+ export class GridModel {
23
+ get mergedHeaders() { return this._mergedHeaders; }
24
+ get hasFilter() { return this._filter; }
25
+ get hasRowTree() { return this._maxRowLevel > 0; }
26
+ get hasRowTreeEnabled() { return this.hasRowTree && this.options.rowTree.enabled; }
27
+ get maxRowLevel() { return this._maxRowLevel; }
28
+ get hasColumnTree() { return this._maxColumnLevel > 0; }
29
+ get hasColumnTreeEnabled() { return this.hasColumnTree && this.options.columnTree.enabled; }
30
+ get maxColumnLevel() { return this._maxColumnLevel; }
31
+ get headerCount() { return this._headerCount; }
32
+ get columnHeaderCount() { return this.headerCount + (this.hasColumnTreeEnabled ? 1 : 0) + (this.hasFilter ? 1 : 0); }
33
+ get properties() { return this._properties; }
34
+ set properties(v) { this._properties = v; }
35
+ get theme() { return this._theme; }
36
+ set theme(v) { this._theme = v; }
37
+ constructor(source, options, logger) {
38
+ this.otherModels = {};
39
+ this.autofitColumns = new Set();
40
+ this.autofitRows = new Set();
41
+ this.merges = new Merges(this);
42
+ this.styles = new StyleModel(this);
43
+ this.comments = new CommentModel(this);
44
+ this.calculations = new CalculationModel(this);
45
+ this.names = new NamingModel(this);
46
+ this.sorting = new SortingModel(this);
47
+ this.filter = new FilterModel(this);
48
+ this.sparklines = new Sparklines(this);
49
+ this.conditionalFormats = new ConditionalFormats(this);
50
+ this._filter = false;
51
+ this._maxRowLevel = 0;
52
+ this._maxColumnLevel = 0;
53
+ this._headerCount = 0;
54
+ this._levelBasedRowTree = true;
55
+ this._levelBasedColTree = true;
56
+ this.clearRows = () => {
57
+ this.rowRoot.clearChildren();
58
+ this.rows = [];
59
+ return this.rows;
60
+ };
61
+ this.clearColumns = () => this.columns = [];
62
+ this.logger = logger;
63
+ this.options = options ?? initOptions(source.options);
64
+ this.populate(source);
65
+ }
66
+ getConnectedModel(name) {
67
+ return this.group ? this.group.get(name) : null;
68
+ }
69
+ getModelByRange(range) {
70
+ return range.sheet ? this.getConnectedModel(range.sheet) : this;
71
+ }
72
+ getCellByA1(a1) {
73
+ return this.getCellByRange(CellRange.fromA1(a1));
74
+ }
75
+ getCellByRange(r) {
76
+ return this.getCellByCoords(r.r1, r.c1);
77
+ }
78
+ getCellByCoords(r, c) {
79
+ return this.rows[r]?.cell(c);
80
+ }
81
+ cell(coord1, coord2) {
82
+ if (!isNaN(coord1))
83
+ return this.getCellByCoords(coord1, coord2 || 0);
84
+ if (coord1 instanceof CellRange)
85
+ return this.getCellByRange(coord1);
86
+ if (typeof coord1 === 'string')
87
+ return this.getCellByA1(coord1);
88
+ return null;
89
+ }
90
+ createRows(source, root = new RowModel(this, { l: -1 }), indexOffset = 0) {
91
+ let hasRowLevelBasedTree = false;
92
+ let hasRowParentBasedTree = false;
93
+ this.autofitRows.clear();
94
+ const rows = source.map((rowSource, r) => {
95
+ if (!rowSource)
96
+ rowSource = {};
97
+ if (!isNaN(rowSource.l))
98
+ hasRowLevelBasedTree = true;
99
+ if (rowSource.p != null)
100
+ hasRowParentBasedTree = true;
101
+ if (rowSource.h == 'auto')
102
+ this.autofitRows.add(r);
103
+ const rowModel = new RowModel(this, rowSource);
104
+ rowModel.origIndex = r + indexOffset;
105
+ if (rowModel.name)
106
+ this.names.set(rowModel.name, CellRange.fullRow(r));
107
+ return rowModel;
108
+ });
109
+ let maxRowLevel = -1;
110
+ if (hasRowLevelBasedTree)
111
+ maxRowLevel = tree.buildLevelBasedTree(rows, root, {
112
+ reverse: this.options.rowTree.reversed
113
+ });
114
+ else if (hasRowParentBasedTree)
115
+ maxRowLevel = tree.buildParentBasedTree(rows, root);
116
+ else
117
+ root.children = rows;
118
+ if (!hasRowParentBasedTree)
119
+ hasRowLevelBasedTree = true; // default to level based tree
120
+ return [root, rows, maxRowLevel, hasRowLevelBasedTree];
121
+ }
122
+ insertRowData(parent, offset, source) {
123
+ const res = this.createRows(source, new RowModel(this, { l: parent.level }), offset);
124
+ this._maxRowLevel = Math.max(this._maxRowLevel, res[2]);
125
+ parent.insertChildren(res[0].children, offset);
126
+ this.indexRowsByTree();
127
+ if (this.theme) {
128
+ const newRows = res[1];
129
+ applyRowTheme(this.theme, this, newRows);
130
+ applyCellTheme(this.theme, this, new CellRange(0, newRows[0].index, Infinity, newRows[newRows.length - 1].index));
131
+ }
132
+ }
133
+ applyTheme(theme, invalidateCellStyles) {
134
+ if (invalidateCellStyles) {
135
+ for (const cell of this.getInitializedCellIterator()) {
136
+ cell.invalidateStyle();
137
+ }
138
+ }
139
+ applyTheme(theme, this);
140
+ }
141
+ populate(source) {
142
+ this.index = source.index;
143
+ this.name = source.name ?? this.name;
144
+ this.tab = source.tab;
145
+ let hasColLevelBasedTree = false;
146
+ let hasColParentBasedTree = false;
147
+ if (!source.columns)
148
+ source.columns = new Array(this.options.columns).fill({});
149
+ if (!source.rows)
150
+ source.rows = new Array(this.options.rows).fill({});
151
+ // styles
152
+ if (source.styles)
153
+ this.styles.populate(source.styles);
154
+ // columns
155
+ this.autofitColumns.clear();
156
+ this.columns = source.columns.map((columnSource, c) => {
157
+ if (!columnSource)
158
+ columnSource = {};
159
+ if (columnSource.l > 0)
160
+ hasColLevelBasedTree = true;
161
+ if (columnSource.p != null)
162
+ hasColParentBasedTree = true;
163
+ if (columnSource.w == 'auto')
164
+ this.autofitColumns.add(c);
165
+ const colModel = new ColumnModel(this, columnSource);
166
+ this._filter = colModel.hasFilter || this._filter;
167
+ if (colModel.name)
168
+ this.names.set(colModel.name, CellRange.fullColumn(c));
169
+ return colModel;
170
+ });
171
+ this._levelBasedColTree = hasColLevelBasedTree;
172
+ this._maxColumnLevel = -1;
173
+ this.colRoot = new ColumnModel(this, { l: -1 });
174
+ if (hasColLevelBasedTree)
175
+ this._maxColumnLevel = tree.buildLevelBasedTree(this.columns, this.colRoot, {
176
+ reverse: this.options.columnTree.reversed
177
+ });
178
+ else if (hasColParentBasedTree)
179
+ this._maxColumnLevel = tree.buildParentBasedTree(this.columns, this.colRoot);
180
+ else
181
+ this.colRoot.children = this.columns;
182
+ if (!hasColParentBasedTree)
183
+ this._levelBasedColTree = true; // default to level based tree
184
+ this.indexColumns();
185
+ this.indexVisibleColumns();
186
+ // rows
187
+ [this.rowRoot, this.rows, this._maxRowLevel, this._levelBasedRowTree] = this.createRows(source.rows);
188
+ this.indexRows();
189
+ this.indexVisibleRows();
190
+ if (this.options.pageSize && this.options.pageSize <= this.rows.length)
191
+ this.rowRoot.count = Infinity;
192
+ // cells
193
+ this.merges.clear();
194
+ source.comments = source.comments || [];
195
+ source.cells?.forEach((cellSource, i) => {
196
+ const cell = this.rows[cellSource.r] ? this.rows[cellSource.r].cell(cellSource.c, cellSource) : null;
197
+ if (!cell) {
198
+ this.logger?.error(`invalid cell definition (index ${i}): ${JSON.stringify(cellSource)}`);
199
+ }
200
+ else if (cellSource.cs > 1 || cellSource.rs > 1) {
201
+ this.merges.add({ r: cell.r, c: cell.c, rs: cellSource.rs || 1, cs: cellSource.cs || 1 });
202
+ }
203
+ if (cell && cellSource.comment) {
204
+ source.comments.push(Object.assign(cellSource.comment, { c: cellSource.c, r: cellSource.r }));
205
+ }
206
+ });
207
+ // sparklines
208
+ if (source.sparklines) {
209
+ try {
210
+ this.sparklines.populate(source.sparklines);
211
+ }
212
+ catch (error) {
213
+ log.getLogger().error(`Sparkline init error: ${error}`);
214
+ }
215
+ }
216
+ // names
217
+ if (source.names) {
218
+ try {
219
+ this.names.populate(source.names);
220
+ }
221
+ catch (error) {
222
+ log.getLogger().error(`Named range init error: ${error}`);
223
+ }
224
+ }
225
+ // conditional formats
226
+ if (source.rules) {
227
+ try {
228
+ this.conditionalFormats.populate(source.rules);
229
+ }
230
+ catch (error) {
231
+ log.getLogger().error(`Conditional formats init error: ${error}`);
232
+ }
233
+ }
234
+ // theme
235
+ if (source.theme) {
236
+ try {
237
+ this.applyTheme(source.theme);
238
+ this._theme = source.theme;
239
+ }
240
+ catch (error) {
241
+ log.getLogger().error(`Theme init error: ${error}`);
242
+ }
243
+ }
244
+ // comments
245
+ if (source.comments) {
246
+ try {
247
+ this.comments.populate(source.comments);
248
+ }
249
+ catch (error) {
250
+ log.getLogger().error(`Comment init error: ${error}`);
251
+ }
252
+ }
253
+ // custom properties
254
+ this._properties = source.props;
255
+ // additional properties
256
+ this.otherSourceData = {};
257
+ const defaultKeys = new Set(DEFAULT_SOURCE_KEYS);
258
+ const keys = Object.keys(source).filter(k => !defaultKeys.has(k));
259
+ keys.forEach(k => this.otherSourceData[k] = source[k]);
260
+ // default sort
261
+ if (this.options.sorting?.defaultSettings) {
262
+ this.sorting.settings = this.options.sorting.defaultSettings;
263
+ }
264
+ // default filter
265
+ if (this.options.filters?.defaultSettings) {
266
+ this.filter.settings = this.options.filters.defaultSettings;
267
+ }
268
+ this.calcHeaderHeights();
269
+ }
270
+ getSourceData() {
271
+ const data = {
272
+ index: this.index,
273
+ name: this.name,
274
+ tab: this.tab,
275
+ columns: this.columns.map(col => col.getSourceData()),
276
+ rows: this.rows.map(row => row.getSourceData()),
277
+ styles: this.styles.getSourceData(),
278
+ rules: this.conditionalFormats.getSourceData(),
279
+ sparklines: this.sparklines.getSourceData(),
280
+ names: this.names.getSourceData(),
281
+ options: this.options,
282
+ };
283
+ if (this._properties)
284
+ data.props = this._properties;
285
+ const cells = [];
286
+ let cellData;
287
+ for (let r = 0; r < this.rows.length; r++) {
288
+ for (let c = 0; c < this.columns.length; c++) {
289
+ cellData = this.rows[r].cell(c).getSourceData();
290
+ if (Object.keys(cellData).length > 0) {
291
+ cellData.r = r;
292
+ cellData.c = c;
293
+ cells.push(cellData);
294
+ }
295
+ }
296
+ }
297
+ if (cells.length > 0)
298
+ data.cells = cells;
299
+ const styles = [];
300
+ this.styles.clean();
301
+ this.styles.map.forEach(style => styles.push(style));
302
+ if (styles.length > 0)
303
+ data.styles = styles;
304
+ const otherModelKeys = new Set([
305
+ ...Object.keys(this.otherModels ?? {}),
306
+ ...Object.keys(this.otherSourceData ?? {})
307
+ ]);
308
+ otherModelKeys.forEach(k => data[k] = this.otherModels[k]
309
+ ? Array.from(this.otherModels[k]).map(m => m.getSourceData())
310
+ : this.otherSourceData[k]);
311
+ return data;
312
+ }
313
+ calcHeaderHeights() {
314
+ this._headerCount = 0;
315
+ this._headerHeights = [];
316
+ this.columns.forEach((column) => {
317
+ this._headerCount = column.header ? column.header.length : this._headerCount;
318
+ if (this._headerHeights.length < this._headerCount) {
319
+ this._headerHeights.push(...Array(this._headerCount - this._headerHeights.length).fill(0));
320
+ }
321
+ column.header?.forEach((h, r) => {
322
+ if (r >= this._headerHeights.length) {
323
+ this._headerHeights.push(0);
324
+ }
325
+ this._headerHeights[r] = Math.max(this._headerHeights[r], h.height ?? 0);
326
+ });
327
+ });
328
+ }
329
+ indexRows() {
330
+ this.visibleRows = [];
331
+ this.rows.forEach((row, r) => {
332
+ row.index = r;
333
+ if (!row.isLoaded)
334
+ row.collapsed = true;
335
+ if (!row.hidden && row.filterState != tree.FilterState.Filtered) {
336
+ row.visibleIndex = this.visibleRows.length;
337
+ this.visibleRows.push(row);
338
+ }
339
+ });
340
+ }
341
+ indexVisibleRows() {
342
+ this.visibleRows = [];
343
+ let r = 0;
344
+ if (this._levelBasedRowTree) {
345
+ this.rowRoot.walkVisible((node) => {
346
+ node.visibleIndex = r++;
347
+ this.visibleRows.push(node);
348
+ });
349
+ // reverse order of row index
350
+ if (this.options.rowTree.reversed) {
351
+ const reversedVisibleRows = new Array(this.visibleRows.length);
352
+ this.visibleRows.forEach((row, i) => {
353
+ r = this.visibleRows.length - i - 1;
354
+ row.visibleIndex = r;
355
+ reversedVisibleRows[r] = row;
356
+ });
357
+ this.visibleRows = reversedVisibleRows;
358
+ }
359
+ }
360
+ else {
361
+ // in parent based node rows do not have to respect tree order
362
+ this.rowRoot.walkVisible((node) => this.visibleRows[node.index] = node);
363
+ this.visibleRows = this.visibleRows.filter(row => {
364
+ if (row) {
365
+ row.visibleIndex = r++;
366
+ return true;
367
+ }
368
+ return false;
369
+ });
370
+ }
371
+ }
372
+ indexRowsByTree() {
373
+ this.rows = [];
374
+ let r = 0;
375
+ this.rowRoot.walk((row) => {
376
+ row.index = r++;
377
+ this.rows.push(row);
378
+ });
379
+ if (this.options.rowTree.reversed)
380
+ this.rows.reverse();
381
+ this.indexVisibleRows();
382
+ }
383
+ indexColumns() {
384
+ this.visibleColumns = [];
385
+ this.columns.forEach((column, c) => {
386
+ column.index = c;
387
+ if (!column.hidden)
388
+ this.visibleColumns.push(column);
389
+ });
390
+ }
391
+ indexVisibleColumns() {
392
+ this.visibleColumns = [];
393
+ this.visibleColumnIndex = {};
394
+ let c = 0;
395
+ this.colRoot.walkVisible((node) => {
396
+ node.visibleIndex = c;
397
+ this.visibleColumnIndex[node.index] = c++;
398
+ this.visibleColumns.push(node);
399
+ });
400
+ // reverse order of column index
401
+ if (this.options.columnTree.reversed) {
402
+ this.visibleColumnIndex = {};
403
+ const reversedVisibleColumns = new Array(this.visibleColumns.length);
404
+ this.visibleColumns.forEach((column, i) => {
405
+ c = this.visibleColumns.length - i - 1;
406
+ column.visibleIndex = c;
407
+ this.visibleColumnIndex[column.index] = c;
408
+ reversedVisibleColumns[c] = column;
409
+ });
410
+ this.visibleColumns = reversedVisibleColumns;
411
+ }
412
+ this.indexHeaders();
413
+ }
414
+ indexHeaders() {
415
+ this._mergedHeaders = [];
416
+ this._headerCount = 0;
417
+ this.colRoot.walkVisible((column) => {
418
+ this._headerCount = Math.max(column.header ? column.header.length : 0, this._headerCount);
419
+ column.mergedHeaders.forEach(h => this._mergedHeaders.push({
420
+ h: h,
421
+ c: column.index,
422
+ r: h.r,
423
+ cs: column.calculateRealColspan(h.cs ?? 1),
424
+ rs: h.rs ?? 1
425
+ }));
426
+ });
427
+ // hidden header cells
428
+ this._mergedHeaders.forEach(h => {
429
+ if (h.h.hidden)
430
+ return;
431
+ for (let c = h.c; c < h.c + h.cs; c++) {
432
+ for (let r = h.r; r < h.r + h.rs; r++) {
433
+ if ((r > h.r || c > h.c) && this.columns[c] && this.columns[c].header[r]) {
434
+ this.columns[c].header[r].hidden = true;
435
+ }
436
+ }
437
+ }
438
+ });
439
+ this.calcHeaderHeights();
440
+ }
441
+ removeHeader(r) {
442
+ this.columns.forEach(column => {
443
+ if (r < column.header.length)
444
+ column.header.splice(r, 1);
445
+ });
446
+ this.indexHeaders();
447
+ }
448
+ clear() {
449
+ this.clearRows();
450
+ this.clearColumns();
451
+ this.resetViewport();
452
+ }
453
+ resetViewport() {
454
+ this._viewport = null;
455
+ return this;
456
+ }
457
+ getViewport(offset, viewportSize, freeze) {
458
+ const viewportRows = [];
459
+ const viewportColumns = [];
460
+ let row;
461
+ let remainingHeight = viewportSize.h;
462
+ let r = 0;
463
+ // top rows
464
+ for (r = 0; r < freeze.t; r++) {
465
+ row = this.visibleRows[r];
466
+ remainingHeight -= row.height;
467
+ viewportRows.push(row);
468
+ }
469
+ // bottom rows
470
+ for (r = this.visibleRows.length - freeze.b; r < this.visibleRows.length; r++) {
471
+ row = this.visibleRows[r];
472
+ remainingHeight -= row.height;
473
+ }
474
+ // center rows
475
+ r = freeze.t + offset.r;
476
+ while (remainingHeight > 0 && r < this.visibleRows.length) {
477
+ row = this.visibleRows[r++];
478
+ remainingHeight -= row.height;
479
+ viewportRows.push(row);
480
+ }
481
+ // bottom rows again
482
+ for (r = this.visibleRows.length - freeze.b; r < this.visibleRows.length; r++) {
483
+ viewportRows.push(this.visibleRows[r]);
484
+ }
485
+ let column;
486
+ let remainingWidth = viewportSize.w;
487
+ let c = 0;
488
+ // left columns
489
+ for (c = 0; c < freeze.l; c++) {
490
+ column = this.visibleColumns[c];
491
+ remainingWidth -= column.width;
492
+ viewportColumns.push(column);
493
+ }
494
+ // right columns
495
+ for (c = this.visibleColumns.length - freeze.r; c < this.visibleColumns.length; c++) {
496
+ column = this.visibleColumns[c];
497
+ remainingWidth -= column.width;
498
+ }
499
+ // center columns
500
+ c = freeze.l + offset.c;
501
+ while (remainingWidth > 0 && c < this.visibleColumns.length) {
502
+ column = this.visibleColumns[c++];
503
+ remainingWidth -= column.width;
504
+ viewportColumns.push(column);
505
+ }
506
+ // right columns again
507
+ for (c = this.visibleColumns.length - freeze.r; c < this.visibleColumns.length; c++) {
508
+ viewportColumns.push(this.visibleColumns[c]);
509
+ }
510
+ return (this._viewport = { rows: viewportRows, columns: viewportColumns });
511
+ }
512
+ calculateViewport() {
513
+ return this._viewport ? this.calculations.calculateViewport(this._viewport) : [];
514
+ }
515
+ getValuesInRange(range, formattedValues = false) {
516
+ range = range.intersect(this.gridRange);
517
+ if (!range)
518
+ return [];
519
+ const { columns, rows } = range.size;
520
+ const values = new Array(rows);
521
+ let i = 0, j = 0;
522
+ let row;
523
+ for (let r = range.r1; r <= range.r2; r++) {
524
+ values[i] = new Array(columns);
525
+ j = 0;
526
+ row = this.rows[r];
527
+ for (let c = range.c1; c <= range.c2; c++) {
528
+ values[i][j++] = formattedValues ? row.cell(c).formattedValue : row.cell(c).value;
529
+ }
530
+ ++i;
531
+ }
532
+ return values;
533
+ }
534
+ setRowExpandLevel(level) {
535
+ this.rows.forEach(row => {
536
+ row.collapsed = (!row.isLoaded && !row.isPartialyLoaded) || row.level >= level;
537
+ if (row.level <= level)
538
+ row.hidden = false; // remove hidden flag for visible rows
539
+ });
540
+ this.indexVisibleRows();
541
+ }
542
+ setColumnExpandLevel(level) {
543
+ this.columns.forEach(column => column.collapsed = column.level >= level);
544
+ this.indexVisibleColumns();
545
+ }
546
+ getViewportRange() {
547
+ return this._viewport ? new CellRange(this._viewport.columns[0].index, this._viewport.rows[0].index, this._viewport.columns[this._viewport.columns.length - 1].index, this._viewport.rows[this._viewport.rows.length - 1].index) : null;
548
+ }
549
+ get gridRange() {
550
+ return new CellRange(0, 0, this.columns.length - 1, this.rows.length - 1);
551
+ }
552
+ getRangeIterator(range, withinViewport = false) {
553
+ return new IterableRange(this, withinViewport && this._viewport
554
+ ? range.intersect(this.getViewportRange())
555
+ : range.intersect(this.gridRange));
556
+ }
557
+ getInitializedCellIterator() {
558
+ return new IterableRange(this, this.gridRange, true);
559
+ }
560
+ getRowIterator(range, withinViewport = false) {
561
+ range = withinViewport && this._viewport
562
+ ? range.intersect(this.getViewportRange())
563
+ : range.intersect(this.gridRange);
564
+ return new IterableAxisRange(this, range, 'rows');
565
+ }
566
+ getColumnIterator(range, withinViewport = false) {
567
+ range = withinViewport && this._viewport
568
+ ? range.intersect(this.getViewportRange())
569
+ : range.intersect(this.gridRange);
570
+ return new IterableAxisRange(this, range, 'columns');
571
+ }
572
+ getCellArray(range) {
573
+ const cells = [];
574
+ for (const cell of this.getRangeIterator(range)) {
575
+ cells.push(cell);
576
+ }
577
+ return cells;
578
+ }
579
+ transformRangeToMatrix(range, transform) {
580
+ let row, cell, rowValues;
581
+ range = range.intersect(this.gridRange);
582
+ const cells = [];
583
+ for (let r = range.r1; r <= range.r2; r++) {
584
+ row = this.rows[r];
585
+ if (!row)
586
+ continue;
587
+ rowValues = [];
588
+ for (let c = range.c1; c <= range.c2; c++) {
589
+ cell = row.cell(c);
590
+ if (cell)
591
+ rowValues.push(transform(cell));
592
+ }
593
+ cells.push(rowValues);
594
+ }
595
+ return cells;
596
+ }
597
+ getCellMatrix(range) {
598
+ return this.getModelByRange(range)?.transformRangeToMatrix(range, c => c);
599
+ }
600
+ getValueMatrix(range) {
601
+ return this.getModelByRange(range)?.transformRangeToMatrix(range, c => c.value);
602
+ }
603
+ shift(options) {
604
+ options.sheet = this.name;
605
+ this.merges.shift(options);
606
+ this.calculations.shift(options);
607
+ this.names.shift(options);
608
+ this.comments.shift(options);
609
+ this.sparklines.shift(options);
610
+ }
611
+ clearCalculations(all = false) {
612
+ if (all && this.group)
613
+ this.group.models.forEach(m => m.calculations.refresh());
614
+ else
615
+ this.calculations.refresh();
616
+ }
617
+ refreshSparklines() {
618
+ this.sparklines.updateRangeMaps();
619
+ for (const cell of this.getInitializedCellIterator()) {
620
+ cell.invalidateStyle();
621
+ }
622
+ }
623
+ clearCalculatedStyles() {
624
+ this.conditionalFormats.refresh();
625
+ const cells = [];
626
+ for (const cell of this.getInitializedCellIterator()) {
627
+ cells.push(cell);
628
+ cell.invalidateStyle();
629
+ }
630
+ }
631
+ insertColumns(index, count, after = false) {
632
+ const parent = this.columns[Math.min(this.columns.length - 1, index)].parent;
633
+ if (after)
634
+ ++index;
635
+ this.shift({ index: index, offset: count, direction: 'right' });
636
+ for (let r = 0; r < this.rows.length; r++)
637
+ this.rows[r].insertColumns(index, count, false);
638
+ const newColumns = (new Array(count)).fill(null).map(() => new ColumnModel(this));
639
+ this.columns.splice(index, 0, ...newColumns);
640
+ if (this.maxColumnLevel > 0)
641
+ parent.insertChildren(newColumns, index - (parent.index || -1) - 1);
642
+ this.indexColumns();
643
+ this.clearCalculations(true);
644
+ return newColumns;
645
+ }
646
+ deleteColumns(index, count) {
647
+ const parent = this.columns[index].parent;
648
+ this.shift({ index: index, offset: count, direction: 'left' });
649
+ const deletedCells = [];
650
+ for (let r = 0; r < this.rows.length; r++)
651
+ deletedCells.push(this.rows[r].deleteColumns(index, count, false));
652
+ // const deletedColumns: [ColumnModel, CellModel[]][] = this.columns.splice(index, count)
653
+ // .map((column, i) => [column, deletedCells[i]]);
654
+ const deletedColumns = this.columns.splice(index, count);
655
+ parent?.deleteChildren(deletedColumns);
656
+ this.indexColumns();
657
+ this.clearCalculations(true);
658
+ return deletedColumns;
659
+ }
660
+ insertRows(index, rows, after = false) {
661
+ const parentIndex = Math.min(this.rows.length - 1, index);
662
+ const parent = parentIndex < 0 ? this.rowRoot : this.rows[parentIndex].parent;
663
+ if (after)
664
+ ++index;
665
+ const count = isNaN(rows) ? rows.length : rows;
666
+ this.shift({ index: index, offset: count, direction: 'down' });
667
+ const newRows = isNaN(rows) ? rows : (new Array(count)).fill(null).map(() => new RowModel(this));
668
+ this.rows.splice(index, 0, ...newRows);
669
+ if (this.maxRowLevel > 0)
670
+ parent.insertChildren(newRows, index - (parent.index || -1) - 1);
671
+ this.indexRows();
672
+ if (this.theme) {
673
+ applyRowTheme(this.theme, this, newRows);
674
+ applyCellTheme(this.theme, this, new CellRange(0, newRows[0].index, Infinity, newRows[newRows.length - 1].index));
675
+ }
676
+ this.clearCalculations(true);
677
+ return newRows;
678
+ }
679
+ deleteRows(index, count) {
680
+ const parent = this.rows[index].parent;
681
+ this.shift({ index: index, offset: count, direction: 'up' });
682
+ const deletedRows = this.rows.splice(index, count);
683
+ parent?.deleteChildren(deletedRows);
684
+ this.indexRows();
685
+ this.clearCalculations(true);
686
+ return deletedRows;
687
+ }
688
+ moveRows(index, count, targetIndex) {
689
+ const movingRows = this.rows.splice(index, count);
690
+ this.rows.splice(targetIndex, 0, ...movingRows);
691
+ this.shift({ index: index, offset: targetIndex - index, direction: 'down', maxIndex: index + count - 1 });
692
+ this.indexRows();
693
+ this.clearCalculations(true);
694
+ return movingRows;
695
+ }
696
+ moveColumns(index, count, targetIndex) {
697
+ const movingColumns = this.columns.splice(index, count);
698
+ this.columns.splice(targetIndex, 0, ...movingColumns);
699
+ this.shift({ index: index, offset: targetIndex - index, direction: 'right', maxIndex: index + count - 1 });
700
+ this.indexColumns();
701
+ this.clearCalculations(true);
702
+ return movingColumns;
703
+ }
704
+ spillValues(opt) {
705
+ const { cell, values, displayValues, propertyCell } = opt;
706
+ const cells = [];
707
+ const oldValues = [];
708
+ const empty = values.length === 0 || values[0].length === 0;
709
+ let row, spillCell;
710
+ const range = empty ? null : new CellRange(cell.c, cell.r, cell.c + values[0].length - 1, cell.r + values.length - 1);
711
+ if (cell.spillRange) {
712
+ // clear values from previous evaluations not contained in the new spill range
713
+ this.getRangeIterator(cell.spillRange, true).forEach(c => {
714
+ if (cell != c && !range?.contains(c.range))
715
+ c.clearSpilledValue();
716
+ });
717
+ }
718
+ cell.spillRange = range;
719
+ if (empty)
720
+ return { cells, oldValues, range: null };
721
+ for (let r = range.r1; r <= range.r2; r++) {
722
+ row = this.rows[r];
723
+ if (!row)
724
+ continue;
725
+ const r2 = r - range.r1;
726
+ for (let c = range.c1; c <= range.c2; c++) {
727
+ const c2 = c - range.c1;
728
+ spillCell = row.cell(c);
729
+ if (spillCell.editable) {
730
+ oldValues.push(spillCell.value2);
731
+ spillCell.spillValue(values[r2][c2], cell);
732
+ if (propertyCell) {
733
+ spillCell.format = propertyCell.format;
734
+ spillCell.type = propertyCell.type;
735
+ }
736
+ if (displayValues && displayValues[r2][c2] != null)
737
+ spillCell.displayValue = displayValues[r2][c2];
738
+ cells.push(spillCell);
739
+ }
740
+ }
741
+ }
742
+ return { cells, oldValues, range };
743
+ }
744
+ getCellByName(name, contextRange, searchGroup = true) {
745
+ const cell = this.names.getCellByName(name, contextRange);
746
+ if (cell)
747
+ return cell;
748
+ else if (this.group && searchGroup)
749
+ return this.group.getCellByName(name, contextRange);
750
+ return null;
751
+ }
752
+ getRangeByName(name, searchGroup = true) {
753
+ const range = this.names.getRangeByName(name);
754
+ if (range)
755
+ return range;
756
+ else if (this.group && searchGroup)
757
+ return this.group.getRangeByName(name);
758
+ return null;
759
+ }
760
+ getValueMatrixByName(name, searchGroup = true) {
761
+ const matrix = this.names.getRangeByName(name);
762
+ if (matrix)
763
+ return this.getValueMatrix(matrix);
764
+ else if (this.group && searchGroup)
765
+ return this.group.getValueMatrixByName(name);
766
+ return null;
767
+ }
768
+ rebuildRowTree() {
769
+ const buildFunction = this._levelBasedRowTree ? tree.buildLevelBasedTree : tree.buildParentBasedTree;
770
+ this._maxRowLevel = buildFunction(this.rows, this.rowRoot, {
771
+ reverse: this.options.rowTree.reversed
772
+ });
773
+ this.indexRowsByTree();
774
+ }
775
+ rebuildColumnTree() {
776
+ const buildFunction = this._levelBasedColTree ? tree.buildLevelBasedTree : tree.buildParentBasedTree;
777
+ this._maxColumnLevel = buildFunction(this.columns, this.colRoot, {
778
+ reverse: this.options.columnTree.reversed
779
+ });
780
+ this.indexColumns();
781
+ }
782
+ calculateCellOffset(cell) {
783
+ let x = 0, y = 0;
784
+ for (let c = 0; c < cell.c1; c++) {
785
+ if (!this.columns[c])
786
+ break;
787
+ x += this.columns[c].width;
788
+ }
789
+ for (let r = 0; r < cell.r1; r++) {
790
+ if (!this.rows[r])
791
+ break;
792
+ y += this.rows[r].height;
793
+ }
794
+ return { x, y };
795
+ }
796
+ }
797
+ //# sourceMappingURL=gridModel.js.map