diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-29 11:48:59 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-29 11:48:59 +0000 |
| commit | 10f90dc68dec42e9a64e081cc0dce6a484447290 (patch) | |
| tree | 5bc8bb30e03b09a602e7d414d943d0e7f24b1a0f /lib/export.ts | |
| parent | 792fb0c21136eededecf52b5b4aa1a252bdc4bfb (diff) | |
(대표님, 박서영, 최겸) document-list-only, gtc, vendorDocu, docu-list-rule
Diffstat (limited to 'lib/export.ts')
| -rw-r--r-- | lib/export.ts | 111 |
1 files changed, 104 insertions, 7 deletions
diff --git a/lib/export.ts b/lib/export.ts index d910ef6a..71fae264 100644 --- a/lib/export.ts +++ b/lib/export.ts @@ -2,7 +2,17 @@ import { type Table } from "@tanstack/react-table" import ExcelJS from "exceljs" /** - * `exportTableToExcel`: + * 컬럼 정의 인터페이스 + */ +export interface ExcelColumnDef { + id: string + header: string + accessor: string | ((row: any) => any) + group?: string +} + +/** + * `exportTableToExcel`: 기존 테이블 기반 내보내기 (페이지네이션된 데이터) * - filename: 다운로드할 엑셀 파일 이름(확장자 제외) * - onlySelected: 선택된 행만 내보낼지 여부 * - excludeColumns: 제외할 column id들의 배열 (e.g. ["select", "actions"]) @@ -89,12 +99,100 @@ export async function exportTableToExcel<TData>( sheetData = [headerRow, ...dataRows] } + // ExcelJS로 파일 생성 및 다운로드 + await createAndDownloadExcel(sheetData, columns.length, filename, useGroupHeader) +} + +/** + * `exportFullDataToExcel`: 전체 데이터를 Excel로 내보내기 + * - data: 전체 데이터 배열 + * - columns: 컬럼 정의 배열 + * - filename: 다운로드할 엑셀 파일 이름(확장자 제외) + * - useGroupHeader: 그룹화 헤더를 사용할지 여부 (기본 false) + */ +export async function exportFullDataToExcel<TData>( + data: TData[], + columns: ExcelColumnDef[], + { + filename = "export", + useGroupHeader = true, + }: { + filename?: string + useGroupHeader?: boolean + } = {} +): Promise<void> { + let sheetData: any[][] + + if (useGroupHeader) { + // ────────────── 2줄 헤더 (row1 = 그룹명, row2 = 컬럼헤더) ────────────── + const row1: string[] = [] + const row2: string[] = [] + + columns.forEach((col) => { + // group + row1.push(col.group ?? "") + // header + row2.push(col.header) + }) + + // 데이터 행 생성 + const dataRows = data.map((item) => + columns.map((col) => { + let val: any + if (typeof col.accessor === "function") { + val = col.accessor(item) + } else { + val = (item as any)[col.accessor] + } + + if (val == null) return "" + return typeof val === "object" ? JSON.stringify(val) : val + }) + ) + + // 최종 sheetData: [ [그룹들...], [헤더들...], ...데이터들 ] + sheetData = [row1, row2, ...dataRows] + } else { + // ────────────── 기존 1줄 헤더 ────────────── + const headerRow = columns.map((col) => col.header) + + // 데이터 행 생성 + const dataRows = data.map((item) => + columns.map((col) => { + let val: any + if (typeof col.accessor === "function") { + val = col.accessor(item) + } else { + val = (item as any)[col.accessor] + } + + if (val == null) return "" + return typeof val === "object" ? JSON.stringify(val) : val + }) + ) + + sheetData = [headerRow, ...dataRows] + } + + // ExcelJS로 파일 생성 및 다운로드 + await createAndDownloadExcel(sheetData, columns.length, filename, useGroupHeader) +} + +/** + * 공통 Excel 파일 생성 및 다운로드 함수 + */ +async function createAndDownloadExcel( + sheetData: any[][], + columnCount: number, + filename: string, + useGroupHeader: boolean +): Promise<void> { // ────────────── ExcelJS 워크북/시트 생성 ────────────── const workbook = new ExcelJS.Workbook() const worksheet = workbook.addWorksheet("Sheet1") - // (추가) 칼럼별 최대 길이 추적 - const maxColumnLengths = columns.map(() => 0) + // 칼럼별 최대 길이 추적 + const maxColumnLengths = Array(columnCount).fill(0) sheetData.forEach((row) => { row.forEach((cellValue, colIdx) => { const cellText = cellValue?.toString() ?? "" @@ -141,7 +239,6 @@ export async function exportTableToExcel<TData>( // ────────────── (핵심) 그룹 헤더 병합 로직 ────────────── if (useGroupHeader) { // row1 (인덱스 1) = 그룹명 행 - // row2 (인덱스 2) = 실제 컬럼 헤더 행 const groupRowIndex = 1 const groupRow = worksheet.getRow(groupRowIndex) @@ -149,7 +246,7 @@ export async function exportTableToExcel<TData>( let start = 1 // 시작 열 인덱스 (1-based) let prevValue = groupRow.getCell(start).value - for (let c = 2; c <= columns.length; c++) { + for (let c = 2; c <= columnCount; c++) { const cellVal = groupRow.getCell(c).value if (cellVal !== prevValue) { // 이전 그룹명이 빈 문자열이 아니면 병합 @@ -173,12 +270,12 @@ export async function exportTableToExcel<TData>( groupRowIndex, start, groupRowIndex, - columns.length + columnCount ) } } - // ────────────── (추가) 칼럼 너비 자동 조정 ────────────── + // ────────────── 칼럼 너비 자동 조정 ────────────── maxColumnLengths.forEach((len, idx) => { // 최소 너비 10, +2 여백 worksheet.getColumn(idx + 1).width = Math.max(len + 2, 10) |
