/** * 엑셀 내보내기 유틸리티 * xlsx 라이브러리를 사용하여 데이터를 엑셀 파일로 변환 */ import * as XLSX from "xlsx"; /** * 데이터를 엑셀 파일로 내보내기 * @param data 내보낼 데이터 배열 * @param fileName 파일명 (기본: "export.xlsx") * @param sheetName 시트명 (기본: "Sheet1") * @param includeHeaders 헤더 포함 여부 (기본: true) */ export async function exportToExcel( data: Record[], fileName: string = "export.xlsx", sheetName: string = "Sheet1", includeHeaders: boolean = true ): Promise { try { console.log("📥 엑셀 내보내기 시작:", { dataCount: data.length, fileName, sheetName, includeHeaders, }); if (data.length === 0) { throw new Error("내보낼 데이터가 없습니다."); } // 워크북 생성 const workbook = XLSX.utils.book_new(); // 데이터를 워크시트로 변환 const worksheet = XLSX.utils.json_to_sheet(data, { header: includeHeaders ? undefined : [], skipHeader: !includeHeaders, }); // 컬럼 너비 자동 조정 const columnWidths = autoSizeColumns(data); worksheet["!cols"] = columnWidths; // 워크시트를 워크북에 추가 XLSX.utils.book_append_sheet(workbook, worksheet, sheetName); // 파일 다운로드 XLSX.writeFile(workbook, fileName); console.log("✅ 엑셀 내보내기 완료:", fileName); } catch (error) { console.error("❌ 엑셀 내보내기 실패:", error); throw error; } } /** * 컬럼 너비 자동 조정 */ function autoSizeColumns(data: Record[]): Array<{ wch: number }> { if (data.length === 0) return []; const keys = Object.keys(data[0]); const columnWidths: Array<{ wch: number }> = []; keys.forEach((key) => { // 헤더 길이 let maxWidth = key.length; // 데이터 길이 확인 data.forEach((row) => { const value = row[key]; const valueLength = value ? String(value).length : 0; maxWidth = Math.max(maxWidth, valueLength); }); // 최소 10, 최대 50으로 제한 columnWidths.push({ wch: Math.min(Math.max(maxWidth, 10), 50) }); }); return columnWidths; } /** * 엑셀 파일을 읽어서 JSON 데이터로 변환 * @param file 읽을 파일 * @param sheetName 읽을 시트명 (기본: 첫 번째 시트) * @returns JSON 데이터 배열 */ export async function importFromExcel( file: File, sheetName?: string ): Promise[]> { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = (e) => { try { const data = e.target?.result; if (!data) { reject(new Error("파일을 읽을 수 없습니다.")); return; } // 워크북 읽기 const workbook = XLSX.read(data, { type: "binary" }); // 시트 선택 (지정된 시트 또는 첫 번째 시트) const targetSheetName = sheetName || workbook.SheetNames[0]; const worksheet = workbook.Sheets[targetSheetName]; if (!worksheet) { reject(new Error(`시트 "${targetSheetName}"를 찾을 수 없습니다.`)); return; } // JSON으로 변환 const jsonData = XLSX.utils.sheet_to_json(worksheet); console.log("✅ 엑셀 가져오기 완료:", { sheetName: targetSheetName, rowCount: jsonData.length, }); resolve(jsonData as Record[]); } catch (error) { console.error("❌ 엑셀 가져오기 실패:", error); reject(error); } }; reader.onerror = () => { reject(new Error("파일 읽기 중 오류가 발생했습니다.")); }; reader.readAsBinaryString(file); }); } /** * 엑셀 파일의 시트 목록 가져오기 */ export async function getExcelSheetNames(file: File): Promise { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = (e) => { try { const data = e.target?.result; if (!data) { reject(new Error("파일을 읽을 수 없습니다.")); return; } const workbook = XLSX.read(data, { type: "binary" }); resolve(workbook.SheetNames); } catch (error) { console.error("❌ 시트 목록 가져오기 실패:", error); reject(error); } }; reader.onerror = () => { reject(new Error("파일 읽기 중 오류가 발생했습니다.")); }; reader.readAsBinaryString(file); }); }