@bilig/excel-import 0.14.14

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 (198) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +165 -0
  3. package/dist/index.d.ts +31 -0
  4. package/dist/index.js +748 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/workbook-import-content-types.d.ts +10 -0
  7. package/dist/workbook-import-content-types.js +30 -0
  8. package/dist/workbook-import-content-types.js.map +1 -0
  9. package/dist/workbook-import-helpers.d.ts +21 -0
  10. package/dist/workbook-import-helpers.js +77 -0
  11. package/dist/workbook-import-helpers.js.map +1 -0
  12. package/dist/workbook-import-preview.d.ts +19 -0
  13. package/dist/workbook-import-preview.js +12 -0
  14. package/dist/workbook-import-preview.js.map +1 -0
  15. package/dist/xlsx-array-formulas.d.ts +6 -0
  16. package/dist/xlsx-array-formulas.js +186 -0
  17. package/dist/xlsx-array-formulas.js.map +1 -0
  18. package/dist/xlsx-axis-entries.d.ts +3 -0
  19. package/dist/xlsx-axis-entries.js +90 -0
  20. package/dist/xlsx-axis-entries.js.map +1 -0
  21. package/dist/xlsx-calculation-settings.d.ts +9 -0
  22. package/dist/xlsx-calculation-settings.js +198 -0
  23. package/dist/xlsx-calculation-settings.js.map +1 -0
  24. package/dist/xlsx-cell-insertion.d.ts +11 -0
  25. package/dist/xlsx-cell-insertion.js +164 -0
  26. package/dist/xlsx-cell-insertion.js.map +1 -0
  27. package/dist/xlsx-cell-metadata.d.ts +15 -0
  28. package/dist/xlsx-cell-metadata.js +380 -0
  29. package/dist/xlsx-cell-metadata.js.map +1 -0
  30. package/dist/xlsx-chart-artifacts.d.ts +7 -0
  31. package/dist/xlsx-chart-artifacts.js +327 -0
  32. package/dist/xlsx-chart-artifacts.js.map +1 -0
  33. package/dist/xlsx-charts.d.ts +4 -0
  34. package/dist/xlsx-charts.js +671 -0
  35. package/dist/xlsx-charts.js.map +1 -0
  36. package/dist/xlsx-comment-vml.d.ts +11 -0
  37. package/dist/xlsx-comment-vml.js +292 -0
  38. package/dist/xlsx-comment-vml.js.map +1 -0
  39. package/dist/xlsx-comments.d.ts +7 -0
  40. package/dist/xlsx-comments.js +120 -0
  41. package/dist/xlsx-comments.js.map +1 -0
  42. package/dist/xlsx-conditional-formats.d.ts +5 -0
  43. package/dist/xlsx-conditional-formats.js +513 -0
  44. package/dist/xlsx-conditional-formats.js.map +1 -0
  45. package/dist/xlsx-control-artifacts.d.ts +7 -0
  46. package/dist/xlsx-control-artifacts.js +404 -0
  47. package/dist/xlsx-control-artifacts.js.map +1 -0
  48. package/dist/xlsx-data-model-artifacts.d.ts +4 -0
  49. package/dist/xlsx-data-model-artifacts.js +240 -0
  50. package/dist/xlsx-data-model-artifacts.js.map +1 -0
  51. package/dist/xlsx-data-table-formulas.d.ts +4 -0
  52. package/dist/xlsx-data-table-formulas.js +138 -0
  53. package/dist/xlsx-data-table-formulas.js.map +1 -0
  54. package/dist/xlsx-defined-names.d.ts +7 -0
  55. package/dist/xlsx-defined-names.js +292 -0
  56. package/dist/xlsx-defined-names.js.map +1 -0
  57. package/dist/xlsx-dimensions.d.ts +4 -0
  58. package/dist/xlsx-dimensions.js +495 -0
  59. package/dist/xlsx-dimensions.js.map +1 -0
  60. package/dist/xlsx-drawing-artifacts.d.ts +7 -0
  61. package/dist/xlsx-drawing-artifacts.js +477 -0
  62. package/dist/xlsx-drawing-artifacts.js.map +1 -0
  63. package/dist/xlsx-escaped-text.d.ts +2 -0
  64. package/dist/xlsx-escaped-text.js +22 -0
  65. package/dist/xlsx-escaped-text.js.map +1 -0
  66. package/dist/xlsx-export-xml.d.ts +8 -0
  67. package/dist/xlsx-export-xml.js +99 -0
  68. package/dist/xlsx-export-xml.js.map +1 -0
  69. package/dist/xlsx-export.d.ts +2 -0
  70. package/dist/xlsx-export.js +800 -0
  71. package/dist/xlsx-export.js.map +1 -0
  72. package/dist/xlsx-external-link-artifacts.d.ts +4 -0
  73. package/dist/xlsx-external-link-artifacts.js +317 -0
  74. package/dist/xlsx-external-link-artifacts.js.map +1 -0
  75. package/dist/xlsx-external-references.d.ts +29 -0
  76. package/dist/xlsx-external-references.js +356 -0
  77. package/dist/xlsx-external-references.js.map +1 -0
  78. package/dist/xlsx-filters.d.ts +4 -0
  79. package/dist/xlsx-filters.js +273 -0
  80. package/dist/xlsx-filters.js.map +1 -0
  81. package/dist/xlsx-formula-translation.d.ts +10 -0
  82. package/dist/xlsx-formula-translation.js +391 -0
  83. package/dist/xlsx-formula-translation.js.map +1 -0
  84. package/dist/xlsx-formulas.d.ts +2 -0
  85. package/dist/xlsx-formulas.js +136 -0
  86. package/dist/xlsx-formulas.js.map +1 -0
  87. package/dist/xlsx-freeze-panes.d.ts +4 -0
  88. package/dist/xlsx-freeze-panes.js +206 -0
  89. package/dist/xlsx-freeze-panes.js.map +1 -0
  90. package/dist/xlsx-hyperlinks.d.ts +5 -0
  91. package/dist/xlsx-hyperlinks.js +64 -0
  92. package/dist/xlsx-hyperlinks.js.map +1 -0
  93. package/dist/xlsx-ignored-errors.d.ts +4 -0
  94. package/dist/xlsx-ignored-errors.js +106 -0
  95. package/dist/xlsx-ignored-errors.js.map +1 -0
  96. package/dist/xlsx-import-cell-styles.d.ts +8 -0
  97. package/dist/xlsx-import-cell-styles.js +255 -0
  98. package/dist/xlsx-import-cell-styles.js.map +1 -0
  99. package/dist/xlsx-import-sheet-metadata.d.ts +40 -0
  100. package/dist/xlsx-import-sheet-metadata.js +41 -0
  101. package/dist/xlsx-import-sheet-metadata.js.map +1 -0
  102. package/dist/xlsx-import-warnings.d.ts +8 -0
  103. package/dist/xlsx-import-warnings.js +44 -0
  104. package/dist/xlsx-import-warnings.js.map +1 -0
  105. package/dist/xlsx-import-workbook-metadata.d.ts +28 -0
  106. package/dist/xlsx-import-workbook-metadata.js +29 -0
  107. package/dist/xlsx-import-workbook-metadata.js.map +1 -0
  108. package/dist/xlsx-macros.d.ts +10 -0
  109. package/dist/xlsx-macros.js +63 -0
  110. package/dist/xlsx-macros.js.map +1 -0
  111. package/dist/xlsx-merge-entries.d.ts +3 -0
  112. package/dist/xlsx-merge-entries.js +17 -0
  113. package/dist/xlsx-merge-entries.js.map +1 -0
  114. package/dist/xlsx-number-formats.d.ts +7 -0
  115. package/dist/xlsx-number-formats.js +222 -0
  116. package/dist/xlsx-number-formats.js.map +1 -0
  117. package/dist/xlsx-pivot-artifacts.d.ts +29 -0
  118. package/dist/xlsx-pivot-artifacts.js +292 -0
  119. package/dist/xlsx-pivot-artifacts.js.map +1 -0
  120. package/dist/xlsx-pivots.d.ts +10 -0
  121. package/dist/xlsx-pivots.js +589 -0
  122. package/dist/xlsx-pivots.js.map +1 -0
  123. package/dist/xlsx-print-page-setup.d.ts +6 -0
  124. package/dist/xlsx-print-page-setup.js +224 -0
  125. package/dist/xlsx-print-page-setup.js.map +1 -0
  126. package/dist/xlsx-printer-settings.d.ts +4 -0
  127. package/dist/xlsx-printer-settings.js +279 -0
  128. package/dist/xlsx-printer-settings.js.map +1 -0
  129. package/dist/xlsx-protected-ranges.d.ts +4 -0
  130. package/dist/xlsx-protected-ranges.js +183 -0
  131. package/dist/xlsx-protected-ranges.js.map +1 -0
  132. package/dist/xlsx-rich-text-artifacts.d.ts +4 -0
  133. package/dist/xlsx-rich-text-artifacts.js +303 -0
  134. package/dist/xlsx-rich-text-artifacts.js.map +1 -0
  135. package/dist/xlsx-sheet-properties.d.ts +4 -0
  136. package/dist/xlsx-sheet-properties.js +89 -0
  137. package/dist/xlsx-sheet-properties.js.map +1 -0
  138. package/dist/xlsx-sheet-protection.d.ts +4 -0
  139. package/dist/xlsx-sheet-protection.js +153 -0
  140. package/dist/xlsx-sheet-protection.js.map +1 -0
  141. package/dist/xlsx-sheet-visibility.d.ts +4 -0
  142. package/dist/xlsx-sheet-visibility.js +53 -0
  143. package/dist/xlsx-sheet-visibility.js.map +1 -0
  144. package/dist/xlsx-slicer-connection-artifacts.d.ts +4 -0
  145. package/dist/xlsx-slicer-connection-artifacts.js +426 -0
  146. package/dist/xlsx-slicer-connection-artifacts.js.map +1 -0
  147. package/dist/xlsx-sorts.d.ts +5 -0
  148. package/dist/xlsx-sorts.js +216 -0
  149. package/dist/xlsx-sorts.js.map +1 -0
  150. package/dist/xlsx-sparklines.d.ts +4 -0
  151. package/dist/xlsx-sparklines.js +115 -0
  152. package/dist/xlsx-sparklines.js.map +1 -0
  153. package/dist/xlsx-style-only-blank-cells.d.ts +3 -0
  154. package/dist/xlsx-style-only-blank-cells.js +96 -0
  155. package/dist/xlsx-style-only-blank-cells.js.map +1 -0
  156. package/dist/xlsx-style-runs.d.ts +12 -0
  157. package/dist/xlsx-style-runs.js +35 -0
  158. package/dist/xlsx-style-runs.js.map +1 -0
  159. package/dist/xlsx-styles.d.ts +25 -0
  160. package/dist/xlsx-styles.js +857 -0
  161. package/dist/xlsx-styles.js.map +1 -0
  162. package/dist/xlsx-tab-colors.d.ts +4 -0
  163. package/dist/xlsx-tab-colors.js +166 -0
  164. package/dist/xlsx-tab-colors.js.map +1 -0
  165. package/dist/xlsx-tables.d.ts +4 -0
  166. package/dist/xlsx-tables.js +371 -0
  167. package/dist/xlsx-tables.js.map +1 -0
  168. package/dist/xlsx-theme-artifacts.d.ts +6 -0
  169. package/dist/xlsx-theme-artifacts.js +126 -0
  170. package/dist/xlsx-theme-artifacts.js.map +1 -0
  171. package/dist/xlsx-threaded-comment-artifacts.d.ts +8 -0
  172. package/dist/xlsx-threaded-comment-artifacts.js +329 -0
  173. package/dist/xlsx-threaded-comment-artifacts.js.map +1 -0
  174. package/dist/xlsx-validations.d.ts +4 -0
  175. package/dist/xlsx-validations.js +542 -0
  176. package/dist/xlsx-validations.js.map +1 -0
  177. package/dist/xlsx-view-state.d.ts +8 -0
  178. package/dist/xlsx-view-state.js +144 -0
  179. package/dist/xlsx-view-state.js.map +1 -0
  180. package/dist/xlsx-workbook-properties.d.ts +5 -0
  181. package/dist/xlsx-workbook-properties.js +388 -0
  182. package/dist/xlsx-workbook-properties.js.map +1 -0
  183. package/dist/xlsx-workbook-protection.d.ts +4 -0
  184. package/dist/xlsx-workbook-protection.js +147 -0
  185. package/dist/xlsx-workbook-protection.js.map +1 -0
  186. package/dist/xlsx-workbook-sheet-paths.d.ts +4 -0
  187. package/dist/xlsx-workbook-sheet-paths.js +96 -0
  188. package/dist/xlsx-workbook-sheet-paths.js.map +1 -0
  189. package/dist/xlsx-worksheet-cells.d.ts +16 -0
  190. package/dist/xlsx-worksheet-cells.js +104 -0
  191. package/dist/xlsx-worksheet-cells.js.map +1 -0
  192. package/dist/xlsx-worksheet-text-values.d.ts +2 -0
  193. package/dist/xlsx-worksheet-text-values.js +136 -0
  194. package/dist/xlsx-worksheet-text-values.js.map +1 -0
  195. package/dist/xlsx-zip.d.ts +6 -0
  196. package/dist/xlsx-zip.js +12 -0
  197. package/dist/xlsx-zip.js.map +1 -0
  198. package/package.json +56 -0
@@ -0,0 +1,671 @@
1
+ import { strFromU8, strToU8, unzipSync, zipSync } from 'fflate';
2
+ import { XMLParser } from 'fast-xml-parser';
3
+ import * as XLSX from 'xlsx';
4
+ import { readXlsxZipEntries } from './xlsx-zip.js';
5
+ const xmlParser = new XMLParser({
6
+ ignoreAttributes: false,
7
+ attributeNamePrefix: '',
8
+ parseAttributeValue: false,
9
+ removeNSPrefix: true,
10
+ });
11
+ const relationshipNamespace = 'http://schemas.openxmlformats.org/package/2006/relationships';
12
+ const worksheetDrawingRelationshipType = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing';
13
+ const chartRelationshipType = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart';
14
+ const drawingContentType = 'application/vnd.openxmlformats-officedocument.drawing+xml';
15
+ const chartContentType = 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml';
16
+ function isRecord(value) {
17
+ return typeof value === 'object' && value !== null;
18
+ }
19
+ function asArray(value) {
20
+ if (value === undefined || value === null) {
21
+ return [];
22
+ }
23
+ return Array.isArray(value) ? value : [value];
24
+ }
25
+ function recordChild(value, key) {
26
+ if (!isRecord(value)) {
27
+ return null;
28
+ }
29
+ const child = value[key];
30
+ return isRecord(child) ? child : null;
31
+ }
32
+ function stringChild(value, key) {
33
+ if (!isRecord(value)) {
34
+ return null;
35
+ }
36
+ const child = value[key];
37
+ return typeof child === 'string' ? child : null;
38
+ }
39
+ function escapeXml(value) {
40
+ return value.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&apos;');
41
+ }
42
+ function normalizeZipPath(path) {
43
+ return path.replace(/^\/+/, '');
44
+ }
45
+ function getZipText(zip, path) {
46
+ const file = zip[normalizeZipPath(path)];
47
+ return file ? strFromU8(file) : null;
48
+ }
49
+ function setZipText(zip, path, text) {
50
+ zip[normalizeZipPath(path)] = strToU8(text);
51
+ }
52
+ function nextPartIndex(zip, prefix, suffix) {
53
+ let next = 1;
54
+ for (const path of Object.keys(zip)) {
55
+ if (!path.startsWith(prefix) || !path.endsWith(suffix)) {
56
+ continue;
57
+ }
58
+ const raw = path.slice(prefix.length, -suffix.length);
59
+ const value = Number(raw);
60
+ if (Number.isInteger(value) && value >= next) {
61
+ next = value + 1;
62
+ }
63
+ }
64
+ return next;
65
+ }
66
+ function absoluteAddress(address) {
67
+ const decoded = XLSX.utils.decode_cell(address);
68
+ return `$${XLSX.utils.encode_col(decoded.c)}$${decoded.r + 1}`;
69
+ }
70
+ function quoteSheetName(sheetName) {
71
+ return `'${sheetName.replaceAll("'", "''")}'`;
72
+ }
73
+ function formulaForRange(sheetName, range) {
74
+ const start = absoluteAddress(range.startAddress);
75
+ const end = absoluteAddress(range.endAddress);
76
+ return start === end ? `${quoteSheetName(sheetName)}!${start}` : `${quoteSheetName(sheetName)}!${start}:${end}`;
77
+ }
78
+ function rangeFromIndexes(sheetName, startRow, startCol, endRow, endCol) {
79
+ return {
80
+ sheetName,
81
+ startAddress: XLSX.utils.encode_cell({ r: startRow, c: startCol }),
82
+ endAddress: XLSX.utils.encode_cell({ r: endRow, c: endCol }),
83
+ };
84
+ }
85
+ function chartTypeElement(chartType) {
86
+ switch (chartType) {
87
+ case 'bar':
88
+ case 'column':
89
+ return 'barChart';
90
+ case 'area':
91
+ return 'areaChart';
92
+ case 'pie':
93
+ return 'pieChart';
94
+ case 'scatter':
95
+ return 'scatterChart';
96
+ case 'line':
97
+ default:
98
+ return 'lineChart';
99
+ }
100
+ }
101
+ function legendPositionValue(position) {
102
+ switch (position) {
103
+ case 'top':
104
+ return 't';
105
+ case 'right':
106
+ return 'r';
107
+ case 'bottom':
108
+ return 'b';
109
+ case 'left':
110
+ return 'l';
111
+ case 'hidden':
112
+ return null;
113
+ case undefined:
114
+ return null;
115
+ default:
116
+ return 'r';
117
+ }
118
+ }
119
+ function parseLegendPosition(value) {
120
+ switch (value) {
121
+ case 't':
122
+ return 'top';
123
+ case 'r':
124
+ return 'right';
125
+ case 'b':
126
+ return 'bottom';
127
+ case 'l':
128
+ return 'left';
129
+ default:
130
+ return undefined;
131
+ }
132
+ }
133
+ function buildChartSeries(chart, exportSourceSheetName) {
134
+ const source = XLSX.utils.decode_range(`${chart.source.startAddress}:${chart.source.endAddress}`);
135
+ const orientation = chart.seriesOrientation ?? 'columns';
136
+ const firstRowAsHeaders = chart.firstRowAsHeaders === true;
137
+ const firstColumnAsLabels = chart.firstColumnAsLabels === true;
138
+ const series = [];
139
+ if (orientation === 'rows') {
140
+ const dataStartRow = source.s.r + (firstRowAsHeaders ? 1 : 0);
141
+ const dataStartCol = source.s.c + (firstColumnAsLabels ? 1 : 0);
142
+ const category = firstRowAsHeaders && dataStartCol <= source.e.c
143
+ ? rangeFromIndexes(exportSourceSheetName, source.s.r, dataStartCol, source.s.r, source.e.c)
144
+ : undefined;
145
+ for (let row = dataStartRow; row <= source.e.r; row += 1) {
146
+ series.push({
147
+ ...(firstColumnAsLabels ? { name: rangeFromIndexes(exportSourceSheetName, row, source.s.c, row, source.s.c) } : {}),
148
+ ...(category ? { category } : {}),
149
+ value: rangeFromIndexes(exportSourceSheetName, row, dataStartCol, row, source.e.c),
150
+ });
151
+ }
152
+ return series.length > 0 ? series : [{ value: { ...chart.source, sheetName: exportSourceSheetName } }];
153
+ }
154
+ const dataStartRow = source.s.r + (firstRowAsHeaders ? 1 : 0);
155
+ const dataStartCol = source.s.c + (firstColumnAsLabels ? 1 : 0);
156
+ const category = firstColumnAsLabels && dataStartRow <= source.e.r
157
+ ? rangeFromIndexes(exportSourceSheetName, dataStartRow, source.s.c, source.e.r, source.s.c)
158
+ : undefined;
159
+ for (let col = dataStartCol; col <= source.e.c; col += 1) {
160
+ series.push({
161
+ ...(firstRowAsHeaders ? { name: rangeFromIndexes(exportSourceSheetName, source.s.r, col, source.s.r, col) } : {}),
162
+ ...(category ? { category } : {}),
163
+ value: rangeFromIndexes(exportSourceSheetName, dataStartRow, col, source.e.r, col),
164
+ });
165
+ }
166
+ return series.length > 0 ? series : [{ value: { ...chart.source, sheetName: exportSourceSheetName } }];
167
+ }
168
+ function chartRefXml(kind, formula) {
169
+ if (kind === 'name') {
170
+ return `<c:tx><c:strRef><c:f>${escapeXml(formula)}</c:f></c:strRef></c:tx>`;
171
+ }
172
+ const refTag = kind === 'cat' ? 'strRef' : 'numRef';
173
+ return `<c:${kind}><c:${refTag}><c:f>${escapeXml(formula)}</c:f></c:${refTag}></c:${kind}>`;
174
+ }
175
+ function buildSeriesXml(chart, exportSourceSheetName) {
176
+ return buildChartSeries(chart, exportSourceSheetName)
177
+ .map((series, index) => {
178
+ const name = series.name ? chartRefXml('name', formulaForRange(exportSourceSheetName, series.name)) : '';
179
+ if (chart.chartType === 'scatter') {
180
+ const xValue = series.category ?? series.value;
181
+ if (!xValue || !series.value) {
182
+ return '';
183
+ }
184
+ return [
185
+ `<c:ser><c:idx val="${String(index)}"/><c:order val="${String(index)}"/>`,
186
+ name,
187
+ chartRefXml('xVal', formulaForRange(exportSourceSheetName, xValue)),
188
+ series.value ? chartRefXml('yVal', formulaForRange(exportSourceSheetName, series.value)) : '',
189
+ '</c:ser>',
190
+ ].join('');
191
+ }
192
+ return [
193
+ `<c:ser><c:idx val="${String(index)}"/><c:order val="${String(index)}"/>`,
194
+ name,
195
+ series.category ? chartRefXml('cat', formulaForRange(exportSourceSheetName, series.category)) : '',
196
+ series.value ? chartRefXml('val', formulaForRange(exportSourceSheetName, series.value)) : '',
197
+ '</c:ser>',
198
+ ].join('');
199
+ })
200
+ .join('');
201
+ }
202
+ function buildChartTitleXml(title) {
203
+ if (!title || title.trim().length === 0) {
204
+ return '';
205
+ }
206
+ return `<c:title><c:tx><c:rich><a:bodyPr/><a:lstStyle/><a:p><a:r><a:t>${escapeXml(title.trim())}</a:t></a:r></a:p></c:rich></c:tx></c:title>`;
207
+ }
208
+ function buildLegendXml(position) {
209
+ const value = legendPositionValue(position);
210
+ return value ? `<c:legend><c:legendPos val="${value}"/><c:layout/></c:legend>` : '';
211
+ }
212
+ function buildPlotAreaXml(chart, exportSourceSheetName) {
213
+ const typeElement = chartTypeElement(chart.chartType);
214
+ const barDirection = chart.chartType === 'bar' || chart.chartType === 'column' ? `<c:barDir val="${chart.chartType === 'bar' ? 'bar' : 'col'}"/>` : '';
215
+ const grouping = chart.chartType === 'bar' || chart.chartType === 'column' || chart.chartType === 'line' || chart.chartType === 'area'
216
+ ? '<c:grouping val="standard"/>'
217
+ : '';
218
+ const axisIds = chart.chartType === 'pie' ? '' : '<c:axId val="123456"/><c:axId val="123457"/>';
219
+ const axes = chart.chartType === 'pie'
220
+ ? ''
221
+ : [
222
+ '<c:catAx><c:axId val="123456"/><c:scaling><c:orientation val="minMax"/></c:scaling><c:axPos val="b"/>',
223
+ '<c:crossAx val="123457"/><c:tickLblPos val="nextTo"/></c:catAx>',
224
+ '<c:valAx><c:axId val="123457"/><c:scaling><c:orientation val="minMax"/></c:scaling><c:axPos val="l"/>',
225
+ '<c:crossAx val="123456"/><c:tickLblPos val="nextTo"/></c:valAx>',
226
+ ].join('');
227
+ return [
228
+ '<c:plotArea><c:layout/>',
229
+ `<c:${typeElement}>`,
230
+ barDirection,
231
+ grouping,
232
+ '<c:varyColors val="0"/>',
233
+ buildSeriesXml(chart, exportSourceSheetName),
234
+ axisIds,
235
+ `</c:${typeElement}>`,
236
+ axes,
237
+ '</c:plotArea>',
238
+ ].join('');
239
+ }
240
+ function buildChartXml(chart, exportSourceSheetName) {
241
+ return [
242
+ '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
243
+ '<c:chartSpace xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" ',
244
+ 'xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" ',
245
+ 'xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">',
246
+ '<c:chart>',
247
+ buildChartTitleXml(chart.title),
248
+ buildPlotAreaXml(chart, exportSourceSheetName),
249
+ buildLegendXml(chart.legendPosition),
250
+ '<c:plotVisOnly val="1"/>',
251
+ '</c:chart>',
252
+ '</c:chartSpace>',
253
+ ].join('');
254
+ }
255
+ function buildDrawingAnchorXml(chart, relationshipId, anchorId) {
256
+ const decoded = XLSX.utils.decode_cell(chart.address);
257
+ const endCol = decoded.c + Math.max(1, chart.cols);
258
+ const endRow = decoded.r + Math.max(1, chart.rows);
259
+ return [
260
+ '<xdr:twoCellAnchor editAs="twoCell">',
261
+ `<xdr:from><xdr:col>${String(decoded.c)}</xdr:col><xdr:colOff>0</xdr:colOff><xdr:row>${String(decoded.r)}</xdr:row><xdr:rowOff>0</xdr:rowOff></xdr:from>`,
262
+ `<xdr:to><xdr:col>${String(endCol)}</xdr:col><xdr:colOff>0</xdr:colOff><xdr:row>${String(endRow)}</xdr:row><xdr:rowOff>0</xdr:rowOff></xdr:to>`,
263
+ '<xdr:graphicFrame macro="">',
264
+ `<xdr:nvGraphicFramePr><xdr:cNvPr id="${String(anchorId)}" name="${escapeXml(chart.id)}"/><xdr:cNvGraphicFramePr/></xdr:nvGraphicFramePr>`,
265
+ '<xdr:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/></xdr:xfrm>',
266
+ '<a:graphic><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/chart">',
267
+ `<c:chart xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:id="${relationshipId}"/>`,
268
+ '</a:graphicData></a:graphic>',
269
+ '</xdr:graphicFrame><xdr:clientData/></xdr:twoCellAnchor>',
270
+ ].join('');
271
+ }
272
+ function buildDrawingXml(anchors) {
273
+ return [
274
+ '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
275
+ '<xdr:wsDr xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" ',
276
+ 'xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">',
277
+ ...anchors,
278
+ '</xdr:wsDr>',
279
+ ].join('');
280
+ }
281
+ function buildRelationshipsXml(relationships) {
282
+ return [
283
+ '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
284
+ `<Relationships xmlns="${relationshipNamespace}">`,
285
+ ...relationships.map((relationship) => `<Relationship Id="${escapeXml(relationship.id)}" Type="${escapeXml(relationship.type)}" Target="${escapeXml(relationship.target)}"/>`),
286
+ '</Relationships>',
287
+ ].join('');
288
+ }
289
+ function parseRelationships(xml) {
290
+ if (!xml) {
291
+ return [];
292
+ }
293
+ const parsed = xmlParser.parse(xml);
294
+ return asArray(recordChild(parsed, 'Relationships')?.['Relationship']).flatMap((entry) => {
295
+ if (!isRecord(entry) || typeof entry['Id'] !== 'string' || typeof entry['Target'] !== 'string' || typeof entry['Type'] !== 'string') {
296
+ return [];
297
+ }
298
+ return [{ id: entry['Id'], target: entry['Target'], type: entry['Type'] }];
299
+ });
300
+ }
301
+ function nextRelationshipId(relationships) {
302
+ let next = 1;
303
+ for (const relationship of relationships) {
304
+ const match = /^rId(\d+)$/u.exec(relationship.id);
305
+ if (match) {
306
+ next = Math.max(next, Number(match[1]) + 1);
307
+ }
308
+ }
309
+ return `rId${String(next)}`;
310
+ }
311
+ function ensureWorksheetRelationshipNamespace(sheetXml) {
312
+ if (/xmlns:r=/u.test(sheetXml)) {
313
+ return sheetXml;
314
+ }
315
+ return sheetXml.replace(/<worksheet\b([^>]*)>/u, `<worksheet$1 xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">`);
316
+ }
317
+ function addWorksheetDrawing(sheetXml, relationshipId) {
318
+ const withNamespace = ensureWorksheetRelationshipNamespace(sheetXml);
319
+ if (/<drawing\b/u.test(withNamespace)) {
320
+ return withNamespace.replace(/<drawing\b[^>]*\/>/u, `<drawing r:id="${relationshipId}"/>`);
321
+ }
322
+ return withNamespace.replace('</worksheet>', `<drawing r:id="${relationshipId}"/></worksheet>`);
323
+ }
324
+ function addContentTypeOverride(contentTypesXml, partName, contentType) {
325
+ if (contentTypesXml.includes(`PartName="${partName}"`)) {
326
+ return contentTypesXml;
327
+ }
328
+ return contentTypesXml.replace('</Types>', `<Override PartName="${partName}" ContentType="${contentType}"/></Types>`);
329
+ }
330
+ function resolveTargetPath(basePartPath, target) {
331
+ const parts = basePartPath.split('/');
332
+ parts.pop();
333
+ for (const segment of target.split('/')) {
334
+ if (segment === '..') {
335
+ parts.pop();
336
+ }
337
+ else if (segment !== '.' && segment.length > 0) {
338
+ parts.push(segment);
339
+ }
340
+ }
341
+ return parts.join('/');
342
+ }
343
+ export function addExportChartsToXlsxBytes(bytes, snapshot, exportSheetNamesByOriginalName) {
344
+ const charts = snapshot.workbook.metadata?.charts ?? [];
345
+ if (charts.length === 0) {
346
+ return bytes;
347
+ }
348
+ const zip = unzipSync(bytes);
349
+ let nextDrawingIndex = nextPartIndex(zip, 'xl/drawings/drawing', '.xml');
350
+ let nextChartIndex = nextPartIndex(zip, 'xl/charts/chart', '.xml');
351
+ let contentTypesXml = getZipText(zip, '[Content_Types].xml') ?? '';
352
+ snapshot.sheets
353
+ .toSorted((left, right) => left.order - right.order)
354
+ .forEach((sheet, sheetIndex) => {
355
+ const sheetCharts = charts.filter((chart) => chart.sheetName === sheet.name);
356
+ if (sheetCharts.length === 0) {
357
+ return;
358
+ }
359
+ const sheetPath = `xl/worksheets/sheet${String(sheetIndex + 1)}.xml`;
360
+ const sheetXml = getZipText(zip, sheetPath);
361
+ if (!sheetXml) {
362
+ return;
363
+ }
364
+ const drawingIndex = nextDrawingIndex;
365
+ nextDrawingIndex += 1;
366
+ const drawingPath = `xl/drawings/drawing${String(drawingIndex)}.xml`;
367
+ const drawingRelsPath = `xl/drawings/_rels/drawing${String(drawingIndex)}.xml.rels`;
368
+ const anchors = [];
369
+ const drawingRelationships = [];
370
+ sheetCharts.forEach((chart, chartIndex) => {
371
+ const chartPartIndex = nextChartIndex;
372
+ nextChartIndex += 1;
373
+ const chartPath = `xl/charts/chart${String(chartPartIndex)}.xml`;
374
+ const relationshipId = `rId${String(chartIndex + 1)}`;
375
+ const exportSourceSheetName = exportSheetNamesByOriginalName.get(chart.source.sheetName) ?? chart.source.sheetName;
376
+ setZipText(zip, chartPath, buildChartXml(chart, exportSourceSheetName));
377
+ anchors.push(buildDrawingAnchorXml(chart, relationshipId, chartIndex + 2));
378
+ drawingRelationships.push({
379
+ id: relationshipId,
380
+ type: chartRelationshipType,
381
+ target: `../charts/chart${String(chartPartIndex)}.xml`,
382
+ });
383
+ contentTypesXml = addContentTypeOverride(contentTypesXml, `/${chartPath}`, chartContentType);
384
+ });
385
+ setZipText(zip, drawingPath, buildDrawingXml(anchors));
386
+ setZipText(zip, drawingRelsPath, buildRelationshipsXml(drawingRelationships));
387
+ contentTypesXml = addContentTypeOverride(contentTypesXml, `/${drawingPath}`, drawingContentType);
388
+ const sheetRelsPath = `xl/worksheets/_rels/sheet${String(sheetIndex + 1)}.xml.rels`;
389
+ const sheetRelationships = parseRelationships(getZipText(zip, sheetRelsPath));
390
+ const drawingRelationshipId = nextRelationshipId(sheetRelationships);
391
+ sheetRelationships.push({
392
+ id: drawingRelationshipId,
393
+ type: worksheetDrawingRelationshipType,
394
+ target: `../drawings/drawing${String(drawingIndex)}.xml`,
395
+ });
396
+ setZipText(zip, sheetRelsPath, buildRelationshipsXml(sheetRelationships));
397
+ setZipText(zip, sheetPath, addWorksheetDrawing(sheetXml, drawingRelationshipId));
398
+ });
399
+ if (contentTypesXml.length > 0) {
400
+ setZipText(zip, '[Content_Types].xml', contentTypesXml);
401
+ }
402
+ return zipSync(zip);
403
+ }
404
+ function parseSheetRangeFormula(formula) {
405
+ const match = /^(?:'((?:[^']|'')+)'|([^'!]+))!\$([A-Z]+)\$(\d+)(?::\$([A-Z]+)\$(\d+))?$/u.exec(formula.trim());
406
+ if (!match) {
407
+ return null;
408
+ }
409
+ const sheetName = (match[1] ?? match[2] ?? '').replaceAll("''", "'");
410
+ const startAddress = `${match[3]}${match[4]}`;
411
+ const endAddress = `${match[5] ?? match[3]}${match[6] ?? match[4]}`;
412
+ return { sheetName, startAddress, endAddress };
413
+ }
414
+ function readReferenceFormula(value) {
415
+ if (!isRecord(value)) {
416
+ return null;
417
+ }
418
+ const numRef = recordChild(value, 'numRef');
419
+ const strRef = recordChild(value, 'strRef');
420
+ return parseSheetRangeFormula(stringChild(numRef, 'f') ?? stringChild(strRef, 'f') ?? '');
421
+ }
422
+ function readSeriesRefs(series) {
423
+ if (!isRecord(series)) {
424
+ return null;
425
+ }
426
+ const name = readReferenceFormula(recordChild(series, 'tx'));
427
+ const category = readReferenceFormula(recordChild(series, 'cat')) ?? readReferenceFormula(recordChild(series, 'xVal'));
428
+ const value = readReferenceFormula(recordChild(series, 'val')) ?? readReferenceFormula(recordChild(series, 'yVal'));
429
+ return value ? { ...(name ? { name } : {}), ...(category ? { category } : {}), value } : null;
430
+ }
431
+ function unionRanges(ranges) {
432
+ const [first] = ranges;
433
+ if (!first) {
434
+ return null;
435
+ }
436
+ let start = XLSX.utils.decode_cell(first.startAddress);
437
+ let end = XLSX.utils.decode_cell(first.endAddress);
438
+ for (const range of ranges.slice(1)) {
439
+ if (range.sheetName !== first.sheetName) {
440
+ continue;
441
+ }
442
+ const nextStart = XLSX.utils.decode_cell(range.startAddress);
443
+ const nextEnd = XLSX.utils.decode_cell(range.endAddress);
444
+ start = { r: Math.min(start.r, nextStart.r), c: Math.min(start.c, nextStart.c) };
445
+ end = { r: Math.max(end.r, nextEnd.r), c: Math.max(end.c, nextEnd.c) };
446
+ }
447
+ return {
448
+ sheetName: first.sheetName,
449
+ startAddress: XLSX.utils.encode_cell(start),
450
+ endAddress: XLSX.utils.encode_cell(end),
451
+ };
452
+ }
453
+ function inferSeriesOrientation(series) {
454
+ const valueRanges = series.flatMap((entry) => (entry.value ? [entry.value] : []));
455
+ if (valueRanges.length === 0) {
456
+ return undefined;
457
+ }
458
+ const decoded = valueRanges.map((range) => ({
459
+ start: XLSX.utils.decode_cell(range.startAddress),
460
+ end: XLSX.utils.decode_cell(range.endAddress),
461
+ }));
462
+ const columns = decoded.every((range) => range.start.c === range.end.c);
463
+ const rows = decoded.every((range) => range.start.r === range.end.r);
464
+ if (columns) {
465
+ return 'columns';
466
+ }
467
+ if (rows) {
468
+ return 'rows';
469
+ }
470
+ return undefined;
471
+ }
472
+ function rangeWithinSource(source, range) {
473
+ const sourceStart = XLSX.utils.decode_cell(source.startAddress);
474
+ const sourceEnd = XLSX.utils.decode_cell(source.endAddress);
475
+ const rangeStart = XLSX.utils.decode_cell(range.startAddress);
476
+ const rangeEnd = XLSX.utils.decode_cell(range.endAddress);
477
+ return (range.sheetName === source.sheetName &&
478
+ rangeStart.r >= sourceStart.r &&
479
+ rangeEnd.r <= sourceEnd.r &&
480
+ rangeStart.c >= sourceStart.c &&
481
+ rangeEnd.c <= sourceEnd.c);
482
+ }
483
+ function isTopRowHeaderRange(source, range) {
484
+ if (!rangeWithinSource(source, range)) {
485
+ return false;
486
+ }
487
+ const sourceStart = XLSX.utils.decode_cell(source.startAddress);
488
+ const sourceEnd = XLSX.utils.decode_cell(source.endAddress);
489
+ const rangeStart = XLSX.utils.decode_cell(range.startAddress);
490
+ const rangeEnd = XLSX.utils.decode_cell(range.endAddress);
491
+ return sourceStart.r < sourceEnd.r && rangeStart.r === sourceStart.r && rangeEnd.r === sourceStart.r;
492
+ }
493
+ function isFirstColumnLabelRange(source, range) {
494
+ if (!rangeWithinSource(source, range)) {
495
+ return false;
496
+ }
497
+ const sourceStart = XLSX.utils.decode_cell(source.startAddress);
498
+ const sourceEnd = XLSX.utils.decode_cell(source.endAddress);
499
+ const rangeStart = XLSX.utils.decode_cell(range.startAddress);
500
+ const rangeEnd = XLSX.utils.decode_cell(range.endAddress);
501
+ return sourceStart.c < sourceEnd.c && rangeStart.c === sourceStart.c && rangeEnd.c === sourceStart.c;
502
+ }
503
+ function rangeEquals(left, right) {
504
+ return (left !== undefined &&
505
+ right !== undefined &&
506
+ left.sheetName === right.sheetName &&
507
+ left.startAddress === right.startAddress &&
508
+ left.endAddress === right.endAddress);
509
+ }
510
+ function nonValueSeriesRange(range, series) {
511
+ return range && !rangeEquals(range, series.value) ? [range] : [];
512
+ }
513
+ function inferFirstRowAsHeaders(source, series, orientation) {
514
+ const candidates = series.flatMap((entry) => {
515
+ if (orientation === 'rows') {
516
+ return nonValueSeriesRange(entry.category, entry);
517
+ }
518
+ if (orientation === 'columns') {
519
+ return nonValueSeriesRange(entry.name, entry);
520
+ }
521
+ return [...nonValueSeriesRange(entry.name, entry), ...nonValueSeriesRange(entry.category, entry)];
522
+ });
523
+ return candidates.some((range) => isTopRowHeaderRange(source, range)) ? true : undefined;
524
+ }
525
+ function inferFirstColumnAsLabels(source, series, orientation) {
526
+ const candidates = series.flatMap((entry) => {
527
+ if (orientation === 'rows') {
528
+ return nonValueSeriesRange(entry.name, entry);
529
+ }
530
+ if (orientation === 'columns') {
531
+ return nonValueSeriesRange(entry.category, entry);
532
+ }
533
+ return [...nonValueSeriesRange(entry.name, entry), ...nonValueSeriesRange(entry.category, entry)];
534
+ });
535
+ return candidates.some((range) => isFirstColumnLabelRange(source, range)) ? true : undefined;
536
+ }
537
+ function textValues(value) {
538
+ if (typeof value === 'string') {
539
+ return [value];
540
+ }
541
+ if (!isRecord(value)) {
542
+ return [];
543
+ }
544
+ return Object.entries(value).flatMap(([key, child]) => (key === 't' ? textValues(child) : textValues(child)));
545
+ }
546
+ function readChartTitle(chart) {
547
+ const values = textValues(recordChild(chart, 'title'));
548
+ const title = values.join('').trim();
549
+ return title.length > 0 ? title : undefined;
550
+ }
551
+ function chartRecord(plotArea) {
552
+ const lineChart = recordChild(plotArea, 'lineChart');
553
+ if (lineChart) {
554
+ return { type: 'line', record: lineChart };
555
+ }
556
+ const areaChart = recordChild(plotArea, 'areaChart');
557
+ if (areaChart) {
558
+ return { type: 'area', record: areaChart };
559
+ }
560
+ const pieChart = recordChild(plotArea, 'pieChart');
561
+ if (pieChart) {
562
+ return { type: 'pie', record: pieChart };
563
+ }
564
+ const scatterChart = recordChild(plotArea, 'scatterChart');
565
+ if (scatterChart) {
566
+ return { type: 'scatter', record: scatterChart };
567
+ }
568
+ const barChart = recordChild(plotArea, 'barChart');
569
+ if (barChart) {
570
+ return { type: recordChild(barChart, 'barDir')?.['val'] === 'bar' ? 'bar' : 'column', record: barChart };
571
+ }
572
+ return null;
573
+ }
574
+ function parseChartXml(chartXml) {
575
+ const parsed = xmlParser.parse(chartXml);
576
+ const chart = recordChild(recordChild(parsed, 'chartSpace'), 'chart');
577
+ const plotArea = recordChild(chart, 'plotArea');
578
+ if (!chart || !plotArea) {
579
+ return null;
580
+ }
581
+ const typedChart = chartRecord(plotArea);
582
+ if (!typedChart) {
583
+ return null;
584
+ }
585
+ const series = asArray(typedChart.record['ser']).flatMap((entry) => {
586
+ const refs = readSeriesRefs(entry);
587
+ return refs ? [refs] : [];
588
+ });
589
+ const source = unionRanges(series.flatMap((entry) => [entry.name, entry.category, entry.value].filter((range) => Boolean(range))));
590
+ if (!source) {
591
+ return null;
592
+ }
593
+ const seriesOrientation = inferSeriesOrientation(series);
594
+ const title = readChartTitle(chart);
595
+ const legendPosition = parseLegendPosition(recordChild(recordChild(chart, 'legend'), 'legendPos')?.['val']);
596
+ return {
597
+ chartType: typedChart.type,
598
+ source,
599
+ ...(seriesOrientation !== undefined ? { seriesOrientation } : {}),
600
+ ...(inferFirstRowAsHeaders(source, series, seriesOrientation) ? { firstRowAsHeaders: true } : {}),
601
+ ...(inferFirstColumnAsLabels(source, series, seriesOrientation) ? { firstColumnAsLabels: true } : {}),
602
+ ...(title !== undefined ? { title } : {}),
603
+ ...(legendPosition !== undefined ? { legendPosition } : {}),
604
+ };
605
+ }
606
+ function readDrawingRelationshipId(anchor) {
607
+ const chart = recordChild(recordChild(recordChild(recordChild(anchor, 'graphicFrame'), 'graphic'), 'graphicData'), 'chart');
608
+ return typeof chart?.['id'] === 'string' ? chart['id'] : null;
609
+ }
610
+ function readAnchorChartId(anchor, fallback) {
611
+ return stringChild(recordChild(recordChild(anchor, 'graphicFrame'), 'nvGraphicFramePr')?.['cNvPr'], 'name') ?? fallback;
612
+ }
613
+ function readAnchorNumber(anchor, key, field) {
614
+ const raw = recordChild(anchor, key)?.[field];
615
+ const number = typeof raw === 'number' ? raw : typeof raw === 'string' ? Number(raw) : Number.NaN;
616
+ return Number.isFinite(number) ? number : null;
617
+ }
618
+ export function readImportedWorkbookCharts(source, sheetNames) {
619
+ const zip = readXlsxZipEntries(source);
620
+ const charts = [];
621
+ sheetNames.forEach((sheetName, sheetIndex) => {
622
+ const sheetPath = `xl/worksheets/sheet${String(sheetIndex + 1)}.xml`;
623
+ const sheetXml = getZipText(zip, sheetPath);
624
+ const drawingRelationshipId = /<drawing\b[^>]*\br:id="([^"]+)"/u.exec(sheetXml ?? '')?.[1];
625
+ if (!drawingRelationshipId) {
626
+ return;
627
+ }
628
+ const sheetRelationships = parseRelationships(getZipText(zip, `xl/worksheets/_rels/sheet${String(sheetIndex + 1)}.xml.rels`));
629
+ const drawingRelationship = sheetRelationships.find((relationship) => relationship.id === drawingRelationshipId && relationship.type === worksheetDrawingRelationshipType);
630
+ if (!drawingRelationship) {
631
+ return;
632
+ }
633
+ const drawingPath = resolveTargetPath(sheetPath, drawingRelationship.target);
634
+ const drawingXml = getZipText(zip, drawingPath);
635
+ if (!drawingXml) {
636
+ return;
637
+ }
638
+ const drawingRelationships = parseRelationships(getZipText(zip, `${drawingPath.slice(0, drawingPath.lastIndexOf('/'))}/_rels/${drawingPath.slice(drawingPath.lastIndexOf('/') + 1)}.rels`));
639
+ const parsedDrawing = xmlParser.parse(drawingXml);
640
+ const anchors = asArray(recordChild(parsedDrawing, 'wsDr')?.['twoCellAnchor']);
641
+ anchors.forEach((anchor, anchorIndex) => {
642
+ const chartRelationshipId = readDrawingRelationshipId(anchor);
643
+ const fromCol = readAnchorNumber(anchor, 'from', 'col');
644
+ const fromRow = readAnchorNumber(anchor, 'from', 'row');
645
+ const toCol = readAnchorNumber(anchor, 'to', 'col');
646
+ const toRow = readAnchorNumber(anchor, 'to', 'row');
647
+ if (!chartRelationshipId || fromCol === null || fromRow === null || toCol === null || toRow === null) {
648
+ return;
649
+ }
650
+ const chartRelationship = drawingRelationships.find((relationship) => relationship.id === chartRelationshipId && relationship.type === chartRelationshipType);
651
+ if (!chartRelationship) {
652
+ return;
653
+ }
654
+ const chartPath = resolveTargetPath(drawingPath, chartRelationship.target);
655
+ const chartMetadata = parseChartXml(getZipText(zip, chartPath) ?? '');
656
+ if (!chartMetadata) {
657
+ return;
658
+ }
659
+ charts.push({
660
+ id: readAnchorChartId(anchor, `xlsx-chart:${sheetName}:${String(anchorIndex + 1)}`),
661
+ sheetName,
662
+ address: XLSX.utils.encode_cell({ r: fromRow, c: fromCol }),
663
+ rows: Math.max(1, toRow - fromRow),
664
+ cols: Math.max(1, toCol - fromCol),
665
+ ...chartMetadata,
666
+ });
667
+ });
668
+ });
669
+ return charts.length > 0 ? charts.toSorted((left, right) => left.id.localeCompare(right.id)) : undefined;
670
+ }
671
+ //# sourceMappingURL=xlsx-charts.js.map