사붐이개발일기

[JS/Svelte] Excel파일 다운로드 기능 구현하기 - Excel.js 본문

Front/JavaScript

[JS/Svelte] Excel파일 다운로드 기능 구현하기 - Excel.js

sabeom 2024. 8. 14. 16:56

서론

회사 프로젝트에서 정산현황의 기간 별 데이터를 엑셀 파일로 만들어 내려받게 해달라는 요구사항이 들어왔다. 엑셀파일 변환은 처음이라 여기저기 구글링하다 xlsx 라이브러리 보단 excel.js 가 좀 더 간단한것같아서 후자로 라이브러리를 선택했다. 

나중에 더 찾아보니 xlsx 라이브러리는 css가 유료라고 한다. 

 

 

 

사용하기

1. exceljs 라이브러리 설치

npm install exceljs;

 

2. exceljs 객체 가져오기

import ExcelJS from 'exceljs';

 

3. workbook 객체 생성

엑셀파일은 여러개의 sheet를 포함한다. workbook은 worksheet를 담는 그릇이다.

const workbook = new ExcelJS.Workbook();

 

4. worksheet 객체 생성

worksheet는 엑셀파일에서 sheet에 해당한다.

const worksheet = workbook.addWorksheet('정산데이터');

 

5. worksheet 컬럼명 등록

worksheet 첫번째 줄에 컬럼명을 추가한다.

header : 컬럼명

key : 데이터 key 값

style : 데이터 포맷 or style 설정

worksheet.columns = [
      {header: '순번', key: 'rowNum', style: {numFmt: '0'}},
      ...
      {header: '승인일자', key: 'appDt'},
      {header: '승인시간', key: 'appTm'},
      {header: '취소일자', key: 'ccDt'},
      {header: '취소시간', key: 'ccTm'},
      {header: '금액', key: 'amt'},
      {header: '과세', key: 'taxAmt'},
      {header: '비과세', key: 'taxFreeAmt'},
      {header: '일반수수료', key: 'generalFee'},
      {header: '일반부가세', key: 'generalVat'},
      {header: '입금금액', key: 'depositAmt'},
      {header: '정산일자', key: 'settlmntDt'}
    ];

 

6. worksheet 데이터 추가

worksheet 2번째줄 부터 데이터를 추가한다.

const data = {'rowNum' = 1, 'appDt' = '20240814', 'appTm' = '164011', ... }
worksheet.insertRows(2, data);

 

7. workbook 객체를 Blob 객체로 변환하여 다운받기

const fileName = '파일명.xlsx';

workbook.xlsx.writeBuffer()
    .then((data) => {
      const blob = new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
      const url = window.URL.createObjectURL(blob);
      const anchor = document.createElement('a');
      anchor.href = url;
      anchor.download = fileName;
      anchor.click();
      window.URL.revokeObjectURL(url);
    })
    .catch((error) => {
        console.error('Error creating Excel file:', error);
	});

 

 

 

이슈사항

서버에서 VO 값을 String으로 뿌려주니 excel로 변환했을때도 값들이 String으로 들어가 정렬이 안되는 문제가 있었다.
number로 변경하려면 클라이언트에서 json을 int로 변경해주거나 서버에서 int로 보내주면된다. 나는 서버에서 int로 변경했다.

 


#  24-08-21

기존데이터를 가공해야할 일이 생겼다. 컬럼꾸미기, 정렬, 데이터 형식 변경 등 수정 요청

 

엑셀 컬럼 설정

worksheet.columns = [
      {header: '순번', key: 'rowNum', style: {numFmt: '0', alignment: {horizontal: 'center'}}},
      ...
      {header: '결제자명', key: 'mpayMbrName', style: {alignment: {horizontal: 'center'}}},
      {header: '결제상태', key: 'padjStatDesc', style: {alignment: {horizontal: 'center'}}},
      {header: '승인일자', key: 'appDtDesc', width: 15, style: {alignment: {horizontal: 'center'}}},
      {header: '승인시간', key: 'appTmDesc', width: 15, style: {alignment: {horizontal: 'center'}}},
      {header: '취소일자', key: 'ccDtDesc', width: 15, style: {alignment: {horizontal: 'center'}}},
      {header: '취소시간', key: 'ccTmDesc', width: 15, style: {alignment: {horizontal: 'center'}}},
      {header: '금액', key: 'amt', style: {numFmt: '#,##0', alignment: {horizontal: 'center'}}},
      {header: '과세', key: 'taxAmt', style: {numFmt: '#,##0', alignment: {horizontal: 'center'}}},
      {header: '비과세', key: 'taxFreeAmt', style: {numFmt: '#,##0', alignment: {horizontal: 'center'}}},
      {header: '일반수수료', key: 'generalFee', width: 10, style: {numFmt: '#,##0', alignment: {horizontal: 'center'}}},
      {header: '일반부가세', key: 'generalVat', width: 10, style: {numFmt: '#,##0', alignment: {horizontal: 'center'}}},
      {header: '입금금액', key: 'depositAmt', style: {numFmt: '#,##0', alignment: {horizontal: 'center'}}},
      {header: '정산일자', key: 'settlmntDtDesc', width: 15, style: {alignment: {horizontal: 'center'}}}
    ];

 

엑셀 데이터 변경

// 기존 JSON 데이터 + 가공데이터 추가
const data = excelData.map(item => {
  return {
    ...item,
    appDtDesc: changeDateForExcel(item.appDt),
    appTmDesc: changeTimeForExcel(item.appTm),
    ccDtDesc: changeDateForExcel(item.ccDt),
    ccTmDesc: changeTimeForExcel(item.ccTm),
    settlmntDtDesc: changeDateForExcel(item.settlmntDt)
  };
});

 

컬럼 꾸미기

// 컬럼 배경색 설정
const headerFill = {
  type: 'pattern',
  pattern: 'solid',
  fgColor: {argb: '6666ff'},
}
// 컬럼 폰트 설정
const headerFont = {bold: true, color: {argb: 'ffffff'}}

// 모든 컬럼에 적용
for (let i = 1; i <= worksheet.columnCount; i++) {
  const headerEachCell = worksheet.getCell(`${String.fromCharCode(i + 64)}1`);
  headerEachCell.fill = headerFill;
  headerEachCell.font = headerFont;
  headerEachCell.alignment = { horizontal: 'center' };
}

 

 

 

 


Reperence

1. ExcelJS 사용법

https://blckchainetc.tistory.com/entry/Nodejs-Exceljs-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%B4%9D%EC%A0%95%EB%A6%AC-How-to-use-Exceljs-%ED%85%8C%EC%9D%B4%EB%B8%94-%EB%A7%8C%EB%93%A4%EA%B8%B0-insertRows-columns-value-%EB%93%B1

2. ExcelJS 다운로드

https://developer-talk.tistory.com/328