본문 바로가기
2024 회사 프로젝트

엑셀 다운로드 기능 FE에서 해결하기

by Kimjoy 2025. 1. 11.

프로젝트 요구사항 중에 엑셀 다운로드 기능이 있었다!!

 

엑셀 다운로드 기능. 이렇게만 있고 상세기능에 대해서는 정의되어 있지 않았어서 다음과 같이 코딩을 했었다.

const ExcelDownload = () => {
  const ws = XLSX.utils.json_to_sheet(list.value);
  const wb = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(wb, ws, 'list');
  XLSX.writeFile(wb, 'list.xlsx');
};

 

그런데 나중에... 현재 페이지에서 다운로드, 전체 다운로드를 해달라는 PM의 요청이 있었고?

그럼 이건 BE가 해결해야할 것 같다! 로 의견이 통일이 되어서 나는 신경쓰지 않고 있었는데

이 엑셀 다운로드 기능이 배포될 즈음에 BE를 하시는 분이 굉장히 바빠졌다..

그래서 엑셀 다운로드 기능을 분석해 보라는 업무가 떨어졌고, 

기존의 기능이 어떻게 진행되고 있는지를 분석했다.

(기존의 기능이라는 말이 웃길 수 있지만.. 우리가 프로젝트를 진행하던 중 프로젝트가 팔려..? 버렸다..!

모두가 알만한 회사에서 이 프로그램?을 사용하고 있었는데 영업에 성공해서 프로젝트 진행 중 배포가 되어 버렸다..

그래서 회사에서 기존에 사용하던 프로그램과 포탈과 유사하게 기능을 만들면 된다고 했다..)

아무튼 분석이 되었고..!

처음에 BE에서 해야하는 줄 알고 파이썬으로 만드는 방법도 알아뒀었는데 이거는 버려져버림,,, 혹시 모르니 나중에 포스팅 해보겠습니다.

기존의 기능이 10개만 다운로드 되고, 엑셀 파일의 이름도 하나로 통일되고 있었고, 컬럼명이 화면과 같게 나오는 것을 확인했는데 그러다 보니 FE에서 처리하자!가 되어서 다시 나의 업무가 되었다!

 

기존의 내가 작성한 코드로는 컬럼명이 화면과 같게 나오지 않는다는 차이점이 있었고 이 부분을 해결해야했다.

그리고 모든 화면에 기존 코드가 있었기 때문에(나중에 BE가 해결할까봐.. 그냥 냅둠)

함수로 만들어서 모든 화면에서 호출하기로 했다

주요 정보는 삭제했지만, 딱 봐도 테이블의 컬럼명이 그대로 나오고 있어서 개선이 필요했다.

또, 너비 조정도 필요했다! 

 

그래서!! 

우선 공통함수로 만들기 위해 utill.ts파일로 만들었다!

테이블의 컬럼명을 BE에서 보내주는대로 표현하지 않고, 화면에 나오는 것처럼 바꿔주기 위해서 

데이터를 가공하는 함수를 하나 만들었다

// 엑셀 데이터 변환
export function transformDataForExcel(dataList: any[], columns: any[]) {
  return dataList.map((data) => {
    const transformedData = {};
    columns.forEach((col) => {
        transformedData[col.label] = data[col.field];
    });

    return transformedData;
  });
}

그리고 변환된 데이터를 이용해 엑셀 파일로 만드는 함수를 만들었다.

엑셀 파일로 만들 때 셀에 들어갈 데이터의 최대 길이로 너비를 조정할 수 있도록 계산하는 코드도 추가했다.

// 엑셀 다운로드 함수
export function makingExcel(dataList: any[], columns: any[]) {
  const ws = XLSX.utils.json_to_sheet(dataList);
  
  const maxLengths = columns.map((col) => {
    const colData = dataList.map((row) => row[col.field]?.toString() || '');

    //데이터 값 최대 길이 계산
    const maxLength = Math.max(
      ...colData.map((val) => val.length),
      col.label.length
    );
    return maxLength;
  });

  // 최대길이로 너비 조정
  ws['!cols'] = maxLengths.map((length) => ({ wch: length + 10 }));

  const wb = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(wb, ws, 'data');
  XLSX.writeFile(wb, 'data.xlsx');
}

 

그리고 엑셀 다운로드 버튼을 누를 때 makingExcel 함수에 list와 columns를 인자로 전달하여 엑셀 파일을 다운로드할 수 있도록 했다.

import { makingExcel } from '@/utils/excel';

/* 엑셀다운로드 */
const ExcelDownload = () => {
  makingExcel(list.value, columns);
};

 

이렇게 하면 

파일 이름은 data.xlsx이고, sheet의 이름은 data인 엑셀 파일이 만들어진다.

그리고 컬럼명도 화면에 나오는 것과 같은 이름으로 출력이 되고, 

셀의 너비도 데이터가 잘 보일 수 있도록 조정된 것을 볼 수 있다.

 

 

지워진 코드가 있어서 엑셀에 보여지는 데이터가 제대로 출력되고 있지 않지만,

나는 날짜 형식을 변환하거나 데이터의 값을 가공해야 한다면 transformDataForExcel 함수에서 할 수 있도록 했었는데,

코드리뷰를 하면서 이렇게 데이터를 가공해야한다면  store에서 값을 전달하기 전에 가공해서 view로 보내는 것이 좋다고 해 주셨다.(혹시 이 글을 보고 엑셀 다운로드 기능을 구현하시는 분이 계시다면 store에서 값을 가공해서 보내주세요!)