요구사항
- 조회된 데이터를 엑셀로 다운로드
- 선택한 기간을 파일명에 포함
- 선택한 필터 정보를 파일명에 포함
- 헤더 스타일 적용
- 컬럼 너비 지정
- 숫자 데이터 가독성 향상
- 예) 충전금내역2026-05-01_2026-05-31충전금_열람.xlsx
ExcelJS 선택 이유
npm install exceljs
- 워크북 생성
- 시트 생성
- 셀 스타일 지정
- 컬럼 너비 지정
- 엑셀 파일 다운로드
- 기본 구조
등을 쉽게 처리 가능
Workbook과 Worksheet 생성
const wb = new ExcelJS.Workbook();
const ws = wb.addWorksheet("충전금 내역");
컬럼 정의
ws.columns = [
{ header: "일시", key: "date", width: 20 },
{ header: "내용", key: "content", width: 40 },
{ header: "포인트 변동", key: "point", width: 20 },
{ header: "잔여포인트", key: "balance", width: 20 },
];
- 일시 / 내용 / 포인트 변동 / 잔여 포인트
- 형태의 테이블이 생성됨
데이터 추가
rows.forEach((r) => {
ws.addRow({
date: formatDateTimeWithoutSeconds(r.date),
content: r.content ?? "-",
point: r.point ?? "-",
balance: (r.balance ?? 0).toLocaleString(),
});
});
헤더 스타일 적용
ws.getRow(1).eachCell((cell) => {
cell.fill = {
type: "pattern",
pattern: "solid",
fgColor: { argb: "FFEEEEEE" },
};
cell.font = {
bold: true,
};
cell.alignment = {
vertical: "middle",
horizontal: "center",
};
});
전체 셀 정렬 처리
ws.eachRow((row) => {
row.eachCell((cell) => {
cell.alignment = {
vertical: "middle",
horizontal: "left",
};
});
});
파일명에 검색 조건 반영하기
- 파일명 : 충전금내역2026-05-01_2026-05-31전체.xlsx 혹은 충전금내역2026-05-01_2026-05-31충전금_열람.xlsx
- 먼저 전체 선택 여부 판단
const isAllSelected =
allFilterIdxs.length > 0 &&
allFilterIdxs.every((idx) => selectedFilterIdxs.includes(idx));
const selectedLabels = filterOptions
.filter((f) => selectedFilterIdxs.includes(f.filterIdx))
.map((f) => f.label);
filterText = selectedLabels.join("_");
브라우저에서 다운로드 처리
- ExcelJs가 생성한 데이터를 Blob으로 변환한 뒤 다운로드 수행
const buffer = await wb.xlsx.writeBuffer();
const blob = new Blob([buffer], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
a.click();
URL.revokeObjectURL(url);