@topgrid/grid-export 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { Table } from '@tanstack/react-table';
2
- import { E as ExcelExportOptions, C as CSVExportOptions, P as PDFExportOptions, a as ClipboardOptions, b as PrintOptions, c as ExcelColumn, d as ExportRowsOptions } from './types-BCeqH-13.cjs';
3
- export { D as DownloadExcelOptions, e as EmptyBehavior, f as ExportScope } from './types-BCeqH-13.cjs';
2
+ import { E as ExcelExportOptions, C as CSVExportOptions, P as PDFExportOptions, a as ClipboardOptions, b as PrintOptions, c as ExcelColumn, d as ExportRowsOptions, e as ExcelSheet, M as MultiSheetOptions } from './types-yAFLGyyY.cjs';
3
+ export { D as DownloadExcelOptions, f as EmptyBehavior, g as ExportScope } from './types-yAFLGyyY.cjs';
4
4
 
5
5
  /**
6
6
  * TanStack Table 인스턴스를 기반으로 Excel(.xlsx) 파일을 생성·다운로드한다.
7
7
  *
8
8
  * @param table - TanStack v8 Table<TData> 인스턴스 (useReactTable 반환값)
9
- * @param options - Excel export 옵션 (fileName, sheetName, scope, emptyBehavior)
9
+ * @param options - Excel export 옵션 (fileName, sheetName, scope, emptyBehavior, columnFormats, columnWidths)
10
10
  * @returns void (동기 실행 — xlsx.writeFile 동기 API, D3)
11
11
  *
12
12
  * @remarks
@@ -14,6 +14,10 @@ export { D as DownloadExcelOptions, e as EmptyBehavior, f as ExportScope } from
14
14
  * xlsx.writeFile 이 동기 실행되어 브라우저 메인 스레드를 블로킹할 수 있습니다.
15
15
  * 대용량 사용 시 Web Worker 래핑 권장 (EC-05).
16
16
  *
17
+ * **셀 서식(MOD-GRID-25)**: `columnFormats` 는 네이티브 Excel number-format(`.z`)을 적용해
18
+ * 셀이 Excel 안에서 numeric·정렬가능하게 유지됩니다. 폰트/배경색은 community
19
+ * `xlsx@0.18.5` 가 write 시 미지원(round-trip 시 스트립)이라 제공하지 않습니다.
20
+ *
17
21
  * @example
18
22
  * // 기본 사용 (filtered 행)
19
23
  * exportToExcel(table, { fileName: '데이터.xlsx' });
@@ -26,6 +30,13 @@ export { D as DownloadExcelOptions, e as EmptyBehavior, f as ExportScope } from
26
30
  * scope: 'selected',
27
31
  * emptyBehavior: 'empty',
28
32
  * });
33
+ *
34
+ * @example
35
+ * // 네이티브 숫자서식 + 컬럼 폭
36
+ * exportToExcel(table, {
37
+ * columnFormats: { price: '#,##0.00', orderedAt: 'yyyy-mm-dd' },
38
+ * columnWidths: { name: 30 },
39
+ * });
29
40
  */
30
41
  declare function exportToExcel<TData>(table: Table<TData>, options?: ExcelExportOptions): void;
31
42
 
@@ -135,4 +146,69 @@ declare function printGrid<TData>(table: Table<TData>, options?: PrintOptions):
135
146
  */
136
147
  declare function exportRowsToExcel<TData extends Record<string, unknown>>(rows: TData[], columns: ExcelColumn[], options?: ExportRowsOptions): void;
137
148
 
138
- export { CSVExportOptions, ClipboardOptions, ExcelColumn, ExcelExportOptions, ExportRowsOptions, PDFExportOptions, PrintOptions, copyToClipboard, exportRowsToExcel, exportToCSV, exportToExcel, exportToPdf, printGrid };
149
+ /**
150
+ * 여러 TanStack Table 을 **하나의 Excel 워크북**(여러 시트)으로 export·다운로드한다.
151
+ * (MOD-GRID-25 G-2 — AG Grid/DevExpress 다중 시트 export 격차 해소)
152
+ *
153
+ * 각 시트는 `exportToExcel`(단일 시트)과 동일한 빌더(`buildGridWorksheet`)를 재사용하므로
154
+ * 헤더 merge·scope·네이티브 숫자서식(`.z`)·컬럼 폭 동작이 단일 시트와 일관된다.
155
+ *
156
+ * @param sheets 시트 정의 배열 (`{ name, table, scope?, columnFormats?, columnWidths? }`)
157
+ * @param options 파일명 옵션
158
+ * @returns void (동기 — xlsx.writeFile)
159
+ *
160
+ * @example
161
+ * exportSheetsToExcel(
162
+ * [
163
+ * { name: '주문', table: ordersTable, columnFormats: { total: '#,##0' } },
164
+ * { name: '고객', table: customersTable, scope: 'selected' },
165
+ * ],
166
+ * { fileName: '월간보고.xlsx' },
167
+ * );
168
+ */
169
+ declare function exportSheetsToExcel(sheets: ExcelSheet[], options?: MultiSheetOptions): void;
170
+
171
+ /**
172
+ * @topgrid/grid-export — sheet ↔ .xlsx bridge (MOD-GRID-69).
173
+ *
174
+ * Import/export a spreadsheet **with formulas** to/from `.xlsx`. The pinned community `xlsx@0.18.5`
175
+ * round-trips cell formulas (`.f`) losslessly (probe-verified) — only cell *styles* (`.s`) are
176
+ * stripped on write (that is the separate "Excel cell styles" gap, out of scope; see MOD-25 LESS-004).
177
+ *
178
+ * The bridge is lib-agnostic of grid-pro-sheet: it operates on a plain `Record<cellRef, rawString>`
179
+ * where a raw string is either a formula (`"=A1+A2"`) or a literal (`"10"`, `"hi"`) — exactly the
180
+ * `createSheet` `setCell(ref, raw)` / `getRaw(ref)` contract. The consumer wires it to the engine.
181
+ */
182
+ /** A worksheet cell as understood by the xlsx lib (the subset this bridge reads/writes). */
183
+ interface XlsxCell {
184
+ /** Cell type: `'n'` number, `'s'` string, `'b'` boolean. */
185
+ t: 'n' | 's' | 'b';
186
+ /** Literal value (absent/ignored when `f` is the source of truth for display). */
187
+ v?: number | string | boolean;
188
+ /** Formula text WITHOUT the leading `=` (xlsx convention). */
189
+ f?: string;
190
+ }
191
+ /**
192
+ * Pure: a sheet raw input (`"=A1+A2"` | `"10"` | `"hi"`) → an xlsx cell object.
193
+ *
194
+ * A formula cell **must carry a cached value** (`v`) or the lib drops it on write (probe-verified),
195
+ * so `computed` (the engine's displayed value, from `getDisplay`) is written as the cache. Without
196
+ * it, a fallback `v: 0` keeps the formula (Excel recalculates on open). Value cells ignore `computed`.
197
+ */
198
+ declare function sheetRawToXlsxCell(raw: string, computed?: string | number): XlsxCell;
199
+ /** Pure: an xlsx cell → a sheet raw input. Formula cells become `"=…"`; value cells stringify. */
200
+ declare function xlsxCellToSheetRaw(cell: XlsxCell): string;
201
+ /**
202
+ * Build an `.xlsx` workbook from a sheet cell map and (in a browser/node) trigger a download / write.
203
+ * Formula cells are written as `.f` (preserved by the lib). Returns nothing — side-effecting write.
204
+ */
205
+ declare function exportSheetCellsToXlsx(cells: Record<string, string>, computed?: Record<string, string | number>, fileName?: string, sheetName?: string): void;
206
+ /** Build an `.xlsx` workbook as a Uint8Array buffer (node-testable; no file I/O). */
207
+ declare function exportSheetCellsToXlsxBuffer(cells: Record<string, string>, computed?: Record<string, string | number>, sheetName?: string): Uint8Array;
208
+ /**
209
+ * Parse an `.xlsx` (the first worksheet) into a sheet cell map. Formula cells become `"=…"` raws so
210
+ * the sheet engine re-evaluates them; value cells stringify. Feeds `createSheet` via `setCell`.
211
+ */
212
+ declare function importXlsxToSheetCells(data: ArrayBuffer | Uint8Array): Record<string, string>;
213
+
214
+ export { CSVExportOptions, ClipboardOptions, ExcelColumn, ExcelExportOptions, ExcelSheet, ExportRowsOptions, MultiSheetOptions, PDFExportOptions, PrintOptions, type XlsxCell, copyToClipboard, exportRowsToExcel, exportSheetCellsToXlsx, exportSheetCellsToXlsxBuffer, exportSheetsToExcel, exportToCSV, exportToExcel, exportToPdf, importXlsxToSheetCells, printGrid, sheetRawToXlsxCell, xlsxCellToSheetRaw };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { Table } from '@tanstack/react-table';
2
- import { E as ExcelExportOptions, C as CSVExportOptions, P as PDFExportOptions, a as ClipboardOptions, b as PrintOptions, c as ExcelColumn, d as ExportRowsOptions } from './types-BCeqH-13.js';
3
- export { D as DownloadExcelOptions, e as EmptyBehavior, f as ExportScope } from './types-BCeqH-13.js';
2
+ import { E as ExcelExportOptions, C as CSVExportOptions, P as PDFExportOptions, a as ClipboardOptions, b as PrintOptions, c as ExcelColumn, d as ExportRowsOptions, e as ExcelSheet, M as MultiSheetOptions } from './types-yAFLGyyY.js';
3
+ export { D as DownloadExcelOptions, f as EmptyBehavior, g as ExportScope } from './types-yAFLGyyY.js';
4
4
 
5
5
  /**
6
6
  * TanStack Table 인스턴스를 기반으로 Excel(.xlsx) 파일을 생성·다운로드한다.
7
7
  *
8
8
  * @param table - TanStack v8 Table<TData> 인스턴스 (useReactTable 반환값)
9
- * @param options - Excel export 옵션 (fileName, sheetName, scope, emptyBehavior)
9
+ * @param options - Excel export 옵션 (fileName, sheetName, scope, emptyBehavior, columnFormats, columnWidths)
10
10
  * @returns void (동기 실행 — xlsx.writeFile 동기 API, D3)
11
11
  *
12
12
  * @remarks
@@ -14,6 +14,10 @@ export { D as DownloadExcelOptions, e as EmptyBehavior, f as ExportScope } from
14
14
  * xlsx.writeFile 이 동기 실행되어 브라우저 메인 스레드를 블로킹할 수 있습니다.
15
15
  * 대용량 사용 시 Web Worker 래핑 권장 (EC-05).
16
16
  *
17
+ * **셀 서식(MOD-GRID-25)**: `columnFormats` 는 네이티브 Excel number-format(`.z`)을 적용해
18
+ * 셀이 Excel 안에서 numeric·정렬가능하게 유지됩니다. 폰트/배경색은 community
19
+ * `xlsx@0.18.5` 가 write 시 미지원(round-trip 시 스트립)이라 제공하지 않습니다.
20
+ *
17
21
  * @example
18
22
  * // 기본 사용 (filtered 행)
19
23
  * exportToExcel(table, { fileName: '데이터.xlsx' });
@@ -26,6 +30,13 @@ export { D as DownloadExcelOptions, e as EmptyBehavior, f as ExportScope } from
26
30
  * scope: 'selected',
27
31
  * emptyBehavior: 'empty',
28
32
  * });
33
+ *
34
+ * @example
35
+ * // 네이티브 숫자서식 + 컬럼 폭
36
+ * exportToExcel(table, {
37
+ * columnFormats: { price: '#,##0.00', orderedAt: 'yyyy-mm-dd' },
38
+ * columnWidths: { name: 30 },
39
+ * });
29
40
  */
30
41
  declare function exportToExcel<TData>(table: Table<TData>, options?: ExcelExportOptions): void;
31
42
 
@@ -135,4 +146,69 @@ declare function printGrid<TData>(table: Table<TData>, options?: PrintOptions):
135
146
  */
136
147
  declare function exportRowsToExcel<TData extends Record<string, unknown>>(rows: TData[], columns: ExcelColumn[], options?: ExportRowsOptions): void;
137
148
 
138
- export { CSVExportOptions, ClipboardOptions, ExcelColumn, ExcelExportOptions, ExportRowsOptions, PDFExportOptions, PrintOptions, copyToClipboard, exportRowsToExcel, exportToCSV, exportToExcel, exportToPdf, printGrid };
149
+ /**
150
+ * 여러 TanStack Table 을 **하나의 Excel 워크북**(여러 시트)으로 export·다운로드한다.
151
+ * (MOD-GRID-25 G-2 — AG Grid/DevExpress 다중 시트 export 격차 해소)
152
+ *
153
+ * 각 시트는 `exportToExcel`(단일 시트)과 동일한 빌더(`buildGridWorksheet`)를 재사용하므로
154
+ * 헤더 merge·scope·네이티브 숫자서식(`.z`)·컬럼 폭 동작이 단일 시트와 일관된다.
155
+ *
156
+ * @param sheets 시트 정의 배열 (`{ name, table, scope?, columnFormats?, columnWidths? }`)
157
+ * @param options 파일명 옵션
158
+ * @returns void (동기 — xlsx.writeFile)
159
+ *
160
+ * @example
161
+ * exportSheetsToExcel(
162
+ * [
163
+ * { name: '주문', table: ordersTable, columnFormats: { total: '#,##0' } },
164
+ * { name: '고객', table: customersTable, scope: 'selected' },
165
+ * ],
166
+ * { fileName: '월간보고.xlsx' },
167
+ * );
168
+ */
169
+ declare function exportSheetsToExcel(sheets: ExcelSheet[], options?: MultiSheetOptions): void;
170
+
171
+ /**
172
+ * @topgrid/grid-export — sheet ↔ .xlsx bridge (MOD-GRID-69).
173
+ *
174
+ * Import/export a spreadsheet **with formulas** to/from `.xlsx`. The pinned community `xlsx@0.18.5`
175
+ * round-trips cell formulas (`.f`) losslessly (probe-verified) — only cell *styles* (`.s`) are
176
+ * stripped on write (that is the separate "Excel cell styles" gap, out of scope; see MOD-25 LESS-004).
177
+ *
178
+ * The bridge is lib-agnostic of grid-pro-sheet: it operates on a plain `Record<cellRef, rawString>`
179
+ * where a raw string is either a formula (`"=A1+A2"`) or a literal (`"10"`, `"hi"`) — exactly the
180
+ * `createSheet` `setCell(ref, raw)` / `getRaw(ref)` contract. The consumer wires it to the engine.
181
+ */
182
+ /** A worksheet cell as understood by the xlsx lib (the subset this bridge reads/writes). */
183
+ interface XlsxCell {
184
+ /** Cell type: `'n'` number, `'s'` string, `'b'` boolean. */
185
+ t: 'n' | 's' | 'b';
186
+ /** Literal value (absent/ignored when `f` is the source of truth for display). */
187
+ v?: number | string | boolean;
188
+ /** Formula text WITHOUT the leading `=` (xlsx convention). */
189
+ f?: string;
190
+ }
191
+ /**
192
+ * Pure: a sheet raw input (`"=A1+A2"` | `"10"` | `"hi"`) → an xlsx cell object.
193
+ *
194
+ * A formula cell **must carry a cached value** (`v`) or the lib drops it on write (probe-verified),
195
+ * so `computed` (the engine's displayed value, from `getDisplay`) is written as the cache. Without
196
+ * it, a fallback `v: 0` keeps the formula (Excel recalculates on open). Value cells ignore `computed`.
197
+ */
198
+ declare function sheetRawToXlsxCell(raw: string, computed?: string | number): XlsxCell;
199
+ /** Pure: an xlsx cell → a sheet raw input. Formula cells become `"=…"`; value cells stringify. */
200
+ declare function xlsxCellToSheetRaw(cell: XlsxCell): string;
201
+ /**
202
+ * Build an `.xlsx` workbook from a sheet cell map and (in a browser/node) trigger a download / write.
203
+ * Formula cells are written as `.f` (preserved by the lib). Returns nothing — side-effecting write.
204
+ */
205
+ declare function exportSheetCellsToXlsx(cells: Record<string, string>, computed?: Record<string, string | number>, fileName?: string, sheetName?: string): void;
206
+ /** Build an `.xlsx` workbook as a Uint8Array buffer (node-testable; no file I/O). */
207
+ declare function exportSheetCellsToXlsxBuffer(cells: Record<string, string>, computed?: Record<string, string | number>, sheetName?: string): Uint8Array;
208
+ /**
209
+ * Parse an `.xlsx` (the first worksheet) into a sheet cell map. Formula cells become `"=…"` raws so
210
+ * the sheet engine re-evaluates them; value cells stringify. Feeds `createSheet` via `setCell`.
211
+ */
212
+ declare function importXlsxToSheetCells(data: ArrayBuffer | Uint8Array): Record<string, string>;
213
+
214
+ export { CSVExportOptions, ClipboardOptions, ExcelColumn, ExcelExportOptions, ExcelSheet, ExportRowsOptions, MultiSheetOptions, PDFExportOptions, PrintOptions, type XlsxCell, copyToClipboard, exportRowsToExcel, exportSheetCellsToXlsx, exportSheetCellsToXlsxBuffer, exportSheetsToExcel, exportToCSV, exportToExcel, exportToPdf, importXlsxToSheetCells, printGrid, sheetRawToXlsxCell, xlsxCellToSheetRaw };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import * as XLSX2 from 'xlsx';
1
+ import * as XLSX6 from 'xlsx';
2
2
 
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -35,8 +35,6 @@ function getRowsByScope(table, scope) {
35
35
  }
36
36
  return table.getFilteredRowModel().rows;
37
37
  }
38
-
39
- // src/exportToExcel.ts
40
38
  function resolveHeaderText(headerValue) {
41
39
  if (typeof headerValue === "string") {
42
40
  return headerValue;
@@ -89,12 +87,56 @@ function buildHeaderRows(table) {
89
87
  }
90
88
  return { headerRows, merges };
91
89
  }
90
+ function buildGridWorksheet(params) {
91
+ const {
92
+ headerRows,
93
+ merges,
94
+ dataRows,
95
+ leafColumnIds,
96
+ columnFormats,
97
+ columnWidths
98
+ } = params;
99
+ const aoa = [...headerRows, ...dataRows];
100
+ const ws = XLSX6.utils.aoa_to_sheet(aoa);
101
+ if (merges.length > 0) {
102
+ ws["!merges"] = merges;
103
+ }
104
+ if (columnFormats) {
105
+ const headerOffset = headerRows.length;
106
+ for (let c = 0; c < leafColumnIds.length; c++) {
107
+ const fmt = columnFormats[leafColumnIds[c]];
108
+ if (!fmt) continue;
109
+ for (let r = 0; r < dataRows.length; r++) {
110
+ const addr = XLSX6.utils.encode_cell({ r: headerOffset + r, c });
111
+ const cell = ws[addr];
112
+ if (cell && cell.t === "n") {
113
+ cell.z = fmt;
114
+ }
115
+ }
116
+ }
117
+ }
118
+ if (columnWidths) {
119
+ const hasAny = leafColumnIds.some(
120
+ (id) => columnWidths[id] !== void 0
121
+ );
122
+ if (hasAny) {
123
+ ws["!cols"] = leafColumnIds.map(
124
+ (id) => columnWidths[id] !== void 0 ? { wch: columnWidths[id] } : {}
125
+ );
126
+ }
127
+ }
128
+ return ws;
129
+ }
130
+
131
+ // src/exportToExcel.ts
92
132
  function exportToExcel(table, options) {
93
133
  const {
94
134
  fileName = "export.xlsx",
95
135
  sheetName = "Sheet1",
96
136
  scope = "filtered",
97
- emptyBehavior = "skip"
137
+ emptyBehavior = "skip",
138
+ columnFormats,
139
+ columnWidths
98
140
  } = options ?? {};
99
141
  const rows = getRowsByScope(table, scope);
100
142
  if (rows.length === 0 && emptyBehavior === "skip") {
@@ -108,15 +150,19 @@ function exportToExcel(table, options) {
108
150
  return value !== void 0 && value !== null ? value : "";
109
151
  })
110
152
  );
111
- const aoa = [...headerRows, ...dataRows];
112
- const ws = XLSX2.utils.aoa_to_sheet(aoa);
113
- if (merges.length > 0) {
114
- ws["!merges"] = merges;
115
- }
116
- const wb = XLSX2.utils.book_new();
117
- XLSX2.utils.book_append_sheet(wb, ws, sheetName);
153
+ const leafColumnIds = table.getVisibleLeafColumns().map((c) => c.id);
154
+ const ws = buildGridWorksheet({
155
+ headerRows,
156
+ merges,
157
+ dataRows,
158
+ leafColumnIds,
159
+ columnFormats,
160
+ columnWidths
161
+ });
162
+ const wb = XLSX6.utils.book_new();
163
+ XLSX6.utils.book_append_sheet(wb, ws, sheetName);
118
164
  const finalFileName = fileName.endsWith(".xlsx") ? fileName : `${fileName}.xlsx`;
119
- XLSX2.writeFile(wb, finalFileName);
165
+ XLSX6.writeFile(wb, finalFileName);
120
166
  }
121
167
 
122
168
  // src/exportToCSV.ts
@@ -229,7 +275,11 @@ function escapeTsvValue(value) {
229
275
  return value.replace(/[\t\r\n]/g, " ");
230
276
  }
231
277
  async function copyToClipboard(table, options) {
232
- const { scope = "filtered", emptyBehavior = "skip" } = options ?? {};
278
+ const {
279
+ scope = "filtered",
280
+ emptyBehavior = "skip",
281
+ includeHeader = true
282
+ } = options ?? {};
233
283
  const rows = getRowsByScope(table, scope);
234
284
  if (rows.length === 0 && emptyBehavior === "skip") {
235
285
  console.warn("[grid-export] copyToClipboard: \uB0B4\uBCF4\uB0BC \uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.");
@@ -248,7 +298,9 @@ async function copyToClipboard(table, options) {
248
298
  return escapeTsvValue(str);
249
299
  }).join(" ")
250
300
  );
251
- const tsvString = [headerRow, ...dataRows].join("\n");
301
+ const tsvString = (includeHeader ? [headerRow, ...dataRows] : dataRows).join(
302
+ "\n"
303
+ );
252
304
  if (typeof navigator !== "undefined" && navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
253
305
  await navigator.clipboard.writeText(tsvString);
254
306
  } else {
@@ -362,20 +414,106 @@ function exportRowsToExcel(rows, columns, options) {
362
414
  (row) => columns.map((col) => formatValue(row[col.key], col.format))
363
415
  );
364
416
  const aoa = rows.length === 0 ? [header] : [header, ...dataRows];
365
- const ws = XLSX2.utils.aoa_to_sheet(aoa);
417
+ const ws = XLSX6.utils.aoa_to_sheet(aoa);
366
418
  ws["!cols"] = columns.map((c) => ({ wch: c.width ?? 15 }));
367
- const headerRange = XLSX2.utils.decode_range(ws["!ref"] ?? "A1");
419
+ const headerRange = XLSX6.utils.decode_range(ws["!ref"] ?? "A1");
368
420
  for (let c = headerRange.s.c; c <= headerRange.e.c; c++) {
369
- const cellAddr = XLSX2.utils.encode_cell({ r: 0, c });
421
+ const cellAddr = XLSX6.utils.encode_cell({ r: 0, c });
370
422
  if (!ws[cellAddr]) continue;
371
423
  ws[cellAddr].s = { font: { bold: true }, fill: { fgColor: { rgb: "F3F4F6" } } };
372
424
  }
373
- const wb = XLSX2.utils.book_new();
374
- XLSX2.utils.book_append_sheet(wb, ws, sheetName);
425
+ const wb = XLSX6.utils.book_new();
426
+ XLSX6.utils.book_append_sheet(wb, ws, sheetName);
375
427
  const ext = fileName.endsWith(".xlsx") ? fileName : `${fileName}.xlsx`;
376
- XLSX2.writeFile(wb, ext);
428
+ XLSX6.writeFile(wb, ext);
429
+ }
430
+ function exportSheetsToExcel(sheets, options) {
431
+ const { fileName = "export.xlsx" } = options ?? {};
432
+ if (sheets.length === 0) {
433
+ console.warn("[grid-export] exportSheetsToExcel: \uC2DC\uD2B8\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.");
434
+ return;
435
+ }
436
+ const wb = XLSX6.utils.book_new();
437
+ for (const sheet of sheets) {
438
+ const { name, table, scope = "filtered", columnFormats, columnWidths } = sheet;
439
+ const rows = getRowsByScope(table, scope);
440
+ const { headerRows, merges } = buildHeaderRows(table);
441
+ const dataRows = rows.map(
442
+ (row) => row.getVisibleCells().map((cell) => {
443
+ const value = cell.getValue();
444
+ return value !== void 0 && value !== null ? value : "";
445
+ })
446
+ );
447
+ const leafColumnIds = table.getVisibleLeafColumns().map((c) => c.id);
448
+ const ws = buildGridWorksheet({
449
+ headerRows,
450
+ merges,
451
+ dataRows,
452
+ leafColumnIds,
453
+ columnFormats,
454
+ columnWidths
455
+ });
456
+ XLSX6.utils.book_append_sheet(wb, ws, name);
457
+ }
458
+ const finalFileName = fileName.endsWith(".xlsx") ? fileName : `${fileName}.xlsx`;
459
+ XLSX6.writeFile(wb, finalFileName);
460
+ }
461
+ function sheetRawToXlsxCell(raw, computed) {
462
+ if (raw.startsWith("=")) {
463
+ const f = raw.slice(1);
464
+ if (computed === void 0) return { t: "n", f, v: 0 };
465
+ const num = Number(computed);
466
+ return computed !== "" && !Number.isNaN(num) ? { t: "n", f, v: num } : { t: "s", f, v: String(computed) };
467
+ }
468
+ if (raw !== "" && !Number.isNaN(Number(raw))) {
469
+ return { t: "n", v: Number(raw) };
470
+ }
471
+ return { t: "s", v: raw };
472
+ }
473
+ function xlsxCellToSheetRaw(cell) {
474
+ if (cell.f !== void 0 && cell.f !== "") return `=${cell.f}`;
475
+ if (cell.v === void 0 || cell.v === null) return "";
476
+ return String(cell.v);
477
+ }
478
+ function exportSheetCellsToXlsx(cells, computed, fileName = "sheet.xlsx", sheetName = "Sheet1") {
479
+ const ws = buildWorksheet(cells, computed);
480
+ const wb = XLSX6.utils.book_new();
481
+ XLSX6.utils.book_append_sheet(wb, ws, sheetName);
482
+ XLSX6.writeFile(wb, fileName.endsWith(".xlsx") ? fileName : `${fileName}.xlsx`);
483
+ }
484
+ function exportSheetCellsToXlsxBuffer(cells, computed, sheetName = "Sheet1") {
485
+ const ws = buildWorksheet(cells, computed);
486
+ const wb = XLSX6.utils.book_new();
487
+ XLSX6.utils.book_append_sheet(wb, ws, sheetName);
488
+ return new Uint8Array(XLSX6.write(wb, { type: "array", bookType: "xlsx" }));
489
+ }
490
+ function importXlsxToSheetCells(data) {
491
+ const wb = XLSX6.read(data, { type: "array" });
492
+ const firstSheet = wb.SheetNames[0];
493
+ const out = {};
494
+ if (firstSheet === void 0) return out;
495
+ const ws = wb.Sheets[firstSheet];
496
+ if (ws === void 0) return out;
497
+ for (const ref of Object.keys(ws)) {
498
+ if (ref.startsWith("!")) continue;
499
+ out[ref] = xlsxCellToSheetRaw(ws[ref]);
500
+ }
501
+ return out;
502
+ }
503
+ function buildWorksheet(cells, computed) {
504
+ const ws = {};
505
+ let maxRow = 0;
506
+ let maxCol = 0;
507
+ for (const ref of Object.keys(cells)) {
508
+ const decoded = XLSX6.utils.decode_cell(ref);
509
+ if (decoded.r > maxRow) maxRow = decoded.r;
510
+ if (decoded.c > maxCol) maxCol = decoded.c;
511
+ ws[ref] = sheetRawToXlsxCell(cells[ref], computed?.[ref]);
512
+ }
513
+ ws["!ref"] = XLSX6.utils.encode_range({ s: { r: 0, c: 0 }, e: { r: maxRow, c: maxCol } });
514
+ return ws;
377
515
  }
378
516
 
379
- export { copyToClipboard, exportRowsToExcel, exportToCSV, exportToExcel, exportToPdf, printGrid };
517
+ export { copyToClipboard, exportRowsToExcel, exportSheetCellsToXlsx, exportSheetCellsToXlsxBuffer, exportSheetsToExcel, exportToCSV, exportToExcel, exportToPdf, importXlsxToSheetCells, printGrid, sheetRawToXlsxCell, xlsxCellToSheetRaw };
380
518
  //# sourceMappingURL=index.mjs.map
381
519
  //# sourceMappingURL=index.mjs.map