ERP-node/frontend/lib/utils/excelExport.ts

173 lines
4.5 KiB
TypeScript
Raw Permalink Normal View History

/**
*
* xlsx
*/
import * as XLSX from "xlsx";
/**
*
* @param data
* @param fileName (: "export.xlsx")
* @param sheetName (: "Sheet1")
* @param includeHeaders (기본: true)
*/
export async function exportToExcel(
data: Record<string, any>[],
fileName: string = "export.xlsx",
sheetName: string = "Sheet1",
includeHeaders: boolean = true
): Promise<void> {
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<string, any>[]): 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<Record<string, any>[]> {
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<string, any>[]);
} catch (error) {
console.error("❌ 엑셀 가져오기 실패:", error);
reject(error);
}
};
reader.onerror = () => {
reject(new Error("파일 읽기 중 오류가 발생했습니다."));
};
reader.readAsBinaryString(file);
});
}
/**
*
*/
export async function getExcelSheetNames(file: File): Promise<string[]> {
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);
});
}