728x90

NestJS에서 xlsx 라이브러리를 사용하여 엑셀 파일의 데이터를 읽을 때, 원하는 특정 시트에서 특정 행부터 데이터를 추출하는 것이 실무에서 매우 중요합니다. 이는 엑셀 파일의 상단에 제목, 설명, 헤더 정보 등 불필요한 행들이 포함되어 있기 때문입니다.
1. 📖 특정 시트(Worksheet) 선택
엑셀 파일 내에는 여러 시트가 있을 수 있습니다. XLSX.read로 워크북 객체를 생성한 후, 원하는 시트의 이름을 키(Key)로 사용하여 해당 시트 객체를 가져옵니다.
// buffer: 파일 업로드로 받은 엑셀 파일의 데이터 Buffer
const workbook = XLSX.read(buffer, { type: 'buffer' });
// 💡 1. 원하는 시트 이름 지정
const sheetName = '직원_목록';
const worksheet = workbook.Sheets[sheetName];
if (!worksheet) {
throw new Error(`워크시트 "${sheetName}"을(를) 찾을 수 없습니다.`);
}
728x90
2. ✂️ 특정 행부터 데이터 읽기 (Skip Rows)
xlsx 라이브러리의 XLSX.utils.sheet_to_json 함수를 사용할 때, range 옵션을 사용하여 데이터 파싱을 시작할 행을 지정할 수 있습니다.
2.1. range 옵션 이해
range 옵션은 파싱을 시작할 0-based 인덱스 또는 A1 표기법을 사용합니다.
- 0-based 인덱스: 엑셀의 첫 번째 행(Header)은 인덱스 0입니다.
- 시작 행 건너뛰기: 데이터가 엑셀의 3번째 행부터 시작한다면, 처음 두 행(인덱스 0, 1)을 건너뛰어야 합니다. 따라서 range: 2로 설정합니다.
2.2. 코드 적용 예시
만약 엑셀 파일의 구조가 다음과 같고, 실제 데이터는 3번째 행부터 시작한다면:
| 엑셀 행 (1-based) | 내용 | 역할 | 인덱스 (0-based) |
| 1 | 회사명 및 파일 정보 | 건너뛸 행 (헤더 이전) | 0 |
| 2 | 컬럼 헤더 (Name, Email) | 건너뛸 행 (헤더) | 1 |
| 3 | Jane Doe, jane@example.com | 실제 데이터 시작 | 2 |
// 💡 sheet_to_json 옵션 설정
const data = XLSX.utils.sheet_to_json(worksheet, {
// 1. 헤더 옵션: 데이터 배열로 반환 (첫 번째 행을 헤더 키로 사용하지 않음)
header: 1,
// 2. range 옵션: 엑셀의 3번째 행(인덱스 2)부터 읽기 시작
// (인덱스 0, 1은 건너뜀)
range: 2,
});
728x90
2.3. 결과 데이터 구조
header: 1 옵션과 range: 2 옵션을 사용하면, 반환되는 data 배열의 구조는 다음과 같습니다.
- data[0] = 엑셀의 3번째 행 데이터 (예: ['Jane Doe', 'jane@example.com', ...])
- data[1] = 엑셀의 4번째 행 데이터
3. ⌨️ 통합된 데이터 파싱 로직
최종적으로 서비스 계층에 통합된 코드는 다음과 같습니다.
import * as XLSX from 'xlsx';
// ... (UploadService 내부)
async processExcel(buffer: Buffer) {
const workbook = XLSX.read(buffer, { type: 'buffer' });
const sheetName = '직원_목록';
const worksheet = workbook.Sheets[sheetName];
if (!worksheet) {
throw new Error(`워크시트 "${sheetName}"을(를) 찾을 수 없습니다.`);
}
// 💡 엑셀의 3번째 행(인덱스 2)부터 모든 데이터를 배열로 읽어옵니다.
const rawData = XLSX.utils.sheet_to_json(worksheet, {
header: 1, // 배열 형태로 반환
range: 2, // 3번째 행부터 시작
});
// 이제 rawData를 DB 모델에 맞게 변환하고 저장 로직을 수행합니다.
const usersToCreate = rawData.map((row: any[]) => ({
name: row[0], // 엑셀 3행, A열 (인덱스 0)
email: row[1], // 엑셀 3행, B열 (인덱스 1)
// ...
}));
// return this.prisma.user.createMany({ data: usersToCreate });
}
728x90
'Nest.js를 배워보자 > 5. NestJS + MySQL 실전 예제 — Excel Import' 카테고리의 다른 글
| NestJS + Prisma: 대용량 처리 시 주의점 (0) | 2025.12.02 |
|---|---|
| NestJS + MySQL 실전 예제: Excel Import (0) | 2025.12.02 |