목적 : 테이블 데이터를 엑셀로 Export
방법1) 프론트에서 처리 -> UI 상 보여지는 테이블 데이터를 그대로 엑셀 추출
방법2) 백엔드에서 처리 -> 프론트에서 가공되지 않은 원본 데이터를 추출
1. 프론트 처리
엑셀 처리를 위한 라이브러리 사용
https://www.npmjs.com/package/xlsx
import * as XLSX from "xlsx";
ExcelButton 컴포넌트의 onClick 함수
const worksheet = XLSX.utils.json_to_sheet(data);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
XLSX.writeFile(workbook, "OrderList.xlsx");
2. 백엔드에서 처리하여 excel 파일을 blob 형태로 리턴 -> excel 파일을 링크화하여 로컬에 다운
컴포넌트 호출 부분
import { getOrderListExcelFile } from "hooks/queries/order";
<ExportButton data={orderListData} excelExportFunction={getOrderListExcelFile} className="p-1 me-3 fs--1" />
API 요청 함수 부분
get 요청의 option에서 responseType : "blob" 로 지정해주어야 함
이 요청 함수를 <ExportButton> 컴포넌트의 excelExportFunction Prop으로 넘겨준다
// order list excel download
export const getOrderListExcelFile = async () => {
return axiosInstance
.get(`/order/download`, { responseType: "blob" })
.then((res) => res.data)
.catch((error) => error);
};
* 추가 Post 로 요청하기
// order list excel download
export const getOrderListExcelFile = async () => {
return axiosInstance
.post(`/order/download`, null, { responseType: "blob" })
.then((res) => res.data)
.catch((error) => error);
};
<ExportButton> 컴포넌트
방법1(프론트), 방법2(백) 동시 커버
API로 리턴받은 데이터와 원하는 추출 파일 형식(Excel) 을 'downloadFile' 함수로 전달
import React from "react";
import { Button } from "react-bootstrap";
import * as XLSX from "xlsx";
import classNames from "classnames";
import { toast } from "react-toastify";
import { downloadFile } from "helpers/download-file";
interface IExportButtonProps {
data: any;
excelExportFunction?: () => Promise<any>;
className: string;
}
const CONTENT_TYPE_EXCEL = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
export default function ExportButton({ data, excelExportFunction, className }: IExportButtonProps) {
const onClickExcel = async () => {
// 부모 컴포넌트에서 별도의 다운로드 API 함수(excelExportFunction)를 prop으로 내려보내줬을 경우
if (excelExportFunction) {
const res = await excelExportFunction();
// 에러 발생시 res.response.data에 담긴 blob을 parse해서 error message 출력
if (res.response && res.response.status !== 200) {
const blobToText = await res.response.data.text();
const errorResponse = JSON.parse(blobToText);
toast.error(errorResponse.message);
return;
}
downloadFile(res, CONTENT_TYPE_EXCEL);
} else {
// 부모 컴포넌트에서 다운로드 API를 내려보내지 않은 경우 프론트에서 처리
const worksheet = XLSX.utils.json_to_sheet(data);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
XLSX.writeFile(workbook, "OrderList.xlsx");
}
};
return (
<Button variant="falcon-default" className={classNames(className)} onClick={onClickExcel}>
Export
</Button>
);
}
blob 말아서 다운로드 링크로 만들고 로컬에 다운로드 하는 함수
리턴 받은 res 데이터(blob), 추출할 컨텐트 타입(Excel 파일 형태) 를 매개변수로 전달받고
<a>링크를 만들고, body 에 추가한 후 click하여 다운로드 후 삭제 처리
import dayjs from "dayjs";
const currentDate = dayjs(new Date()).format("YYYY-MM-DD");
export const downloadFile = (file, contentType) => {
const a = document.createElement("a");
const blob = new Blob([file], { type: contentType });
a.href = window.URL.createObjectURL(blob);
a.target = "_blank";
a.download = `downloaded_file_${currentDate}`;
a.style.display = "none";
document.body.appendChild(a);
a.click();
URL.revokeObjectURL(a.href);
document.body.removeChild(a);
};
'programming > React' 카테고리의 다른 글
useQuery enable (false) 비활성화 일때 isLoading = true 인 이슈 (0) | 2023.11.22 |
---|---|
useEffect 마운트 되었을때는 실행하지 않고, dependancies 가 실제로 변경된 경우에만 실행 시키기 (0) | 2023.11.15 |
무한 스크롤 구현기(React, Scrollevent, Throttle, Intersection Observer API) (0) | 2023.07.12 |
개발환경에서 CORS 에러 관련 프록시 설정 (0) | 2023.05.03 |
Recoil 새로고침 시 user 데이터 유지하기 (0) | 2023.05.03 |