From ffb8e2e99e1d0c105b1c545ff7ab4d3149ec6c48 Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Mon, 1 Dec 2025 15:22:38 +0900 Subject: (김준회) 서버측 where, order by 절 지원을 위한 v2 임시작업 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/client-table-v2/import-utils.ts | 100 +++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 components/client-table-v2/import-utils.ts (limited to 'components/client-table-v2/import-utils.ts') diff --git a/components/client-table-v2/import-utils.ts b/components/client-table-v2/import-utils.ts new file mode 100644 index 00000000..bc7f4b44 --- /dev/null +++ b/components/client-table-v2/import-utils.ts @@ -0,0 +1,100 @@ +import ExcelJS from "exceljs" + +interface ImportExcelOptions { + file: File + /** + * Map Excel header names to data keys. + * Example: { "Name": "name", "Age": "age" } + */ + columnMapping?: Record + /** + * Row offset to start reading data (0-based). + * Default: 1 (assuming row 0 is header) + */ + dataStartRow?: number +} + +export interface ExcelImportResult { + data: T[] + errors: string[] +} + +/** + * Generic function to read an Excel file and convert it to an array of objects. + * Does NOT handle database insertion or validation logic. + */ +export async function importFromExcel({ + file, + columnMapping = {}, + dataStartRow = 1, +}: ImportExcelOptions): Promise> { + const workbook = new ExcelJS.Workbook() + const arrayBuffer = await file.arrayBuffer() + + try { + await workbook.xlsx.load(arrayBuffer) + } catch (error) { + return { data: [], errors: ["Failed to parse Excel file. Please ensure it is a valid .xlsx file."] } + } + + const worksheet = workbook.worksheets[0] // Read the first sheet + const data: T[] = [] + const errors: string[] = [] + + if (!worksheet) { + return { data: [], errors: ["No worksheet found in the Excel file."] } + } + + // 1. Read Header Row (assumed to be row 1 for mapping if no explicit mapping provided, + // or we can use it to validate mapping) + const headers: string[] = [] + const headerRow = worksheet.getRow(1) + headerRow.eachCell((cell, colNumber) => { + headers[colNumber] = String(cell.value).trim() + }) + + // 2. Iterate Data Rows + worksheet.eachRow((row, rowNumber) => { + if (rowNumber <= dataStartRow) return // Skip header/pre-header rows + + const rowData: any = {} + let hasData = false + + row.eachCell((cell, colNumber) => { + const headerText = headers[colNumber] + if (!headerText) return + + // Determine the key to use for this column + // Priority: Explicit mapping -> Header text as key + const key = columnMapping[headerText] || headerText + + let cellValue = cell.value + + // Handle ExcelJS object values (e.g. formula results, hyperlinks) + if (cellValue && typeof cellValue === 'object') { + if ('result' in cellValue) { + // Formula result + cellValue = (cellValue as any).result + } else if ('text' in cellValue) { + // Hyperlink text + cellValue = (cellValue as any).text + } else if ('richText' in cellValue) { + // Rich text + cellValue = (cellValue as any).richText.map((t: any) => t.text).join('') + } + } + + if (cellValue !== null && cellValue !== undefined && String(cellValue).trim() !== '') { + hasData = true + rowData[key] = cellValue + } + }) + + if (hasData) { + data.push(rowData as T) + } + }) + + return { data, errors } +} + -- cgit v1.2.3