diff options
Diffstat (limited to 'lib/menu-list/table/excel-export.ts')
| -rw-r--r-- | lib/menu-list/table/excel-export.ts | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/lib/menu-list/table/excel-export.ts b/lib/menu-list/table/excel-export.ts new file mode 100644 index 00000000..feba5310 --- /dev/null +++ b/lib/menu-list/table/excel-export.ts @@ -0,0 +1,107 @@ +// app/evcp/menu-list/utils/excel-export.ts + +import ExcelJS from 'exceljs'; + +interface MenuExportData { + menuPath: string; + menuTitle: string; + menuDescription?: string | null; + menuGroup?: string | null; + sectionTitle: string; + domain: string; + isActive: boolean; + manager1Name?: string | null; + manager1Email?: string | null; + manager2Name?: string | null; + manager2Email?: string | null; +} + +export async function exportMenusToExcel( + menus: MenuExportData[], + translate: (key: string) => string +) { + // 워크북 생성 + const workbook = new ExcelJS.Workbook(); + const worksheet = workbook.addWorksheet('메뉴 목록'); + + // 헤더 정의 + worksheet.columns = [ + { header: '메뉴 경로', key: 'menuPath', width: 40 }, + { header: '메뉴명', key: 'menuTitle', width: 30 }, + { header: '설명', key: 'menuDescription', width: 40 }, + { header: '그룹', key: 'menuGroup', width: 20 }, + { header: '섹션', key: 'sectionTitle', width: 20 }, + { header: '도메인', key: 'domain', width: 15 }, + { header: '상태', key: 'isActive', width: 10 }, + { header: '담당자1 이름', key: 'manager1Name', width: 20 }, + { header: '담당자1 이메일', key: 'manager1Email', width: 30 }, + { header: '담당자2 이름', key: 'manager2Name', width: 20 }, + { header: '담당자2 이메일', key: 'manager2Email', width: 30 }, + ]; + + // 헤더 스타일 설정 + worksheet.getRow(1).font = { bold: true }; + worksheet.getRow(1).fill = { + type: 'pattern', + pattern: 'solid', + fgColor: { argb: 'FFE0E0E0' } + }; + worksheet.getRow(1).alignment = { vertical: 'middle', horizontal: 'center' }; + + // 데이터 추가 (번역 적용) + menus.forEach((menu) => { + worksheet.addRow({ + menuPath: menu.menuPath, + menuTitle: translate(menu.menuTitle), + menuDescription: menu.menuDescription ? translate(menu.menuDescription) : '', + menuGroup: menu.menuGroup ? translate(menu.menuGroup) : '', + sectionTitle: translate(menu.sectionTitle), + domain: menu.domain.toUpperCase(), + isActive: menu.isActive ? '활성' : '비활성', + manager1Name: menu.manager1Name || '', + manager1Email: menu.manager1Email || '', + manager2Name: menu.manager2Name || '', + manager2Email: menu.manager2Email || '', + }); + }); + + // 모든 셀에 테두리 추가 + worksheet.eachRow((row, rowNumber) => { + row.eachCell((cell) => { + cell.border = { + top: { style: 'thin' }, + left: { style: 'thin' }, + bottom: { style: 'thin' }, + right: { style: 'thin' } + }; + // 데이터 행은 세로 가운데 정렬 + if (rowNumber > 1) { + cell.alignment = { vertical: 'middle', wrapText: true }; + } + }); + }); + + // 자동 필터 추가 + worksheet.autoFilter = { + from: 'A1', + to: `K${menus.length + 1}` + }; + + // 파일 다운로드 + const buffer = await workbook.xlsx.writeBuffer(); + const blob = new Blob([buffer], { + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + }); + + // 다운로드 링크 생성 + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + const fileName = `메뉴목록_${new Date().toISOString().slice(0, 10)}.xlsx`; + + link.href = url; + link.download = fileName; + link.click(); + + // 메모리 정리 + URL.revokeObjectURL(url); +}
\ No newline at end of file |
