summaryrefslogtreecommitdiff
path: root/lib/export.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/export.ts')
-rw-r--r--lib/export.ts111
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)