일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 스프링시큐리티
- 로그인 로직
- Ajax
- 회원가입로직
- register
- 밸류즈
- Styled Components
- Typesciprt
- 인증처리
- 밸류즈 홈페이지
- 마이페이지
- 로그인
- 파생상품평가
- 캘린더 라이브러리
- 빌드 및 배포
- 관리자페이지
- ui탬플릿
- MRC
- RCPS
- react
- Token
- 배포
- Update
- 공통메서드
- mypage
- userManagement
- 이미지 업로드
- stock option
- jsonwebtoken
- 달력 라이브러리
- Today
- Total
I T H
[MySchedule project] 18. exceljs를 사용한 엑셀 다운로드 구현 본문
엑셀을 다운로드 할수 있도록 해주는 라이브러리 exceljs는 db에 저장된 데이터들을 엑셀로 다운로드 받고싶거나 엑셀로 출력된 결과물을 원할때 사용할 수 있는 방법이다.
다운로드에 대한 기능은 백앤드인 node.js에서 진행했고, 원하는 데이터에 따라 다르게 다운로드 될수 있도록 조건 파라미터도 받도록 했다.
- 다운로드 구현할 페이지는 관리자의 사용자데이터 엑셀조회 화면에서 진행하도록 하겠다.
Backend
- node.js에서 exceljs를 설치 및 다운로드까지 로직을 한 후에, frontend에서 간단하게 요청 파라미터만 보내도록 구현하겠습니다.
[ exceljs 설치 ]
npm install exceljs
[ exceljs 불러오기 ]
const ExcelJS = require("exceljs");
[ src / index.js ]
- route 등록
app.use("/excelDownload", require("./routes/excelDownload"));
[ src / routes / excelDownload.js ]
1. exceljs 라이브러리를 불러오는 것까지 했다면 workbook을 생성하고 worksheet에 이름을 생성해준다.
2. worksheet의 컬럼의 구조를 만들어준다. 여기서 key에 해당하는 부분과 데이터를 넣는부분의 이름이 일치해야된다.
3. db에서 사용자 데이터를 조회한다. 이때 데이터가 많을 확률이 높으므로, 배열로 받는다.
4. 조회한 데이터를 양식에 맞게 엑셀에 저장해야 하는데, db에서 조회한 사용자 데이터 배열을 for문을 이용해서 하나씩 엑셀에 넣어준다.
5. 엑셀 데이터를 저장하는 코드와 다운로드 코드를 작성해준다.
const express = require("express");
const router = express.Router();
const ExcelJS = require("exceljs");
const User = require("../models/User");
//사용자 데이터 조회 후 엑셀로 다운로드
router.post("/excelUserDataSelect", async (req, res, next) => {
console.log("====== excelUserDataSelect");
console.log(req.body);
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet("My Sheet"); //이름지정
worksheet.columns = [
//엑셀 구조 만들기
{ header: "아이디", key: "userId", width: 20 },
{ header: "이름", key: "userName", width: 20 },
{ header: "이메일", key: "userEmail", width: 20 },
{ header: "폰번호", key: "userPhone", width: 20 },
{ header: "로그인타입", key: "loginType", width: 20 },
];
let userData = [];
let userId = req.body.userId;
let userName = req.body.userName;
try {
//db에 있는 데이터 조회하기 start
userData = await User.find({
userId: { $regex: userId },
userName: { $regex: userName },
});
//console.log(userData);
//조회해온 사용자 데이터 엑셀에 저장
for (let index in userData) {
//console.log(index);
console.log(userData[index]);
//엑셀 데이터 추가
let loginType = "";
if (userData[index].loginType === 0) {
loginType = "일반로그인";
} else {
loginType = "소셜로그인";
}
worksheet.addRow({
userId: userData[index].userId,
userName: userData[index].userName,
userEmail: userData[index].userEmail,
userPhone: userData[index].userPhone,
loginType: loginType,
});
}
//db에 있는 데이터 조회하기 end
//날짜형식으로 엑셀 파일 이름에 붙이기
const currentDate = new Date();
const currentDayFormat =
currentDate.getFullYear() +
"-" +
(currentDate.getMonth() + 1) +
"-" +
currentDate.getDate();
//엑셀 데이터 저장
res.header("Access-Control-Expose-Headers", "Content-Disposition");
res.setHeader(
"Content-Type",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
);
res.setHeader(
"Content-Disposition",
"attachment; filename=" + currentDayFormat + "excelfile.xlsx"
);
// 다운로드
await workbook.xlsx.write(res);
res.end();
/*
workbook.xlsx.write(res).then(function (data) {
res.end();
console.log("File write done........");
});
*/
} catch (error) {
console.error(error);
return;
}
});
module.exports = router;
Frontend
- 백앤드에서 엑셀 다운로드 구현을 했다면 프론트에서는 서버에서 받은 데이터를 "blob"을 통해 엑셀을 볼수있게 바꿔준다.
[ src / pages / Excel / index.tsx ]
1. 관리자가 이름 또는 아이디로 데이터를 엑셀로 다운로드 받을수 있도록 파라미터를 전달해준다. (선택사항)
2. 백앤드로부터 엑셀 데이터를 받았는데, 엑셀로 보이게 하려면 "blob"을 사용해야된다. responseType을 "blob"으로 지정하고, 서버에서 받은 데이터를 blob으로 변환 및 url을 생성한다.
3. 이제 링크를 만들고 click 이벤트를 발생시키면 엑셀이 다운로드 된다.
import React, { ChangeEvent, useState } from "react";
// import axiosInstance from "../../utils/axios";
import axios from "axios";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
const ExcelDownload = () => {
//사용자 데이터 조회용 state
const [userData, setUserData] = useState({
userId: "",
userName: "",
});
const link = document.createElement("a"); //blob 객체 URL을 설정할 링크
const [selectedDate, setSelectedDate] = useState<Date | null>(new Date());
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
e.preventDefault();
const { name, value } = e.target;
setUserData((prevState) => ({
...prevState,
[name]: value,
}));
};
//사용자 데이터 조회
const userDataSelect = async (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
e.preventDefault();
try {
const body = {
...userData,
};
axios({
url: "http://localhost:4003/excelDownload/excelUserDataSelect",
method: "POST",
data: body,
responseType: "blob", //이부분이 있어야 엑셀 파일로 받을수 있다.
}).then((response) => {
console.log(response);
// 서버에서 전달 받은 데이터를 blob으로 변환합니다.
const blob = new Blob([response.data]);
// blob을 사용해 객체 URL 생성
const fileObjectUrl = window.URL.createObjectURL(blob);
//blob 객체 URL을 설정할 링크
//const link = document.createElement("a");
link.href = fileObjectUrl;
link.style.display = "none";
// 다운로드 파일의 이름을 추출하는 메서드 호출
link.download = downloadFilename(response);
document.body.appendChild(link); //링크 body에 추가함
//click 이벤트를 발생시키고, 파일 다운로드를 실행함
link.click();
link.remove(); // 다운로드가 끝난 리소스(객체 URL)를 해제
window.URL.revokeObjectURL(fileObjectUrl);
});
} catch (error) {
console.log(error);
}
// 엑셀 다운로드 파일 이름을 추출하는 함수
const downloadFilename = (response: any) => {
const disposition = response.headers["content-disposition"];
const fileName = decodeURI(
disposition
.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)[1]
.replace(/['"]/g, "")
);
console.log(fileName);
return fileName;
};
};
return (
<section className="w-full my-10">
<p className="my-4 text-sm text-gray-800">
{" "}
- 다운로드 버튼을 클릭하시면 엑셀 파일 형식으로 데이터를 보실수
있습니다.{" "}
</p>
<div className="grid sm:grid-cols-2 gap-4">
{/* 사용자 데이터 엑셀로 조회 */}
<div className="py-4 border-[1px] rounded-md border-gray-200 text-center">
<div className="my-4">
<p className="text-lg font-semibold my-2">사용자 데이터 조회</p>
</div>
<div className="">
<label className="">이름: </label>
<input
onChange={handleChange}
id="userName"
name="userName"
value={userData.userName}
className="w-[200px] border-b-[1px] border-gray-500 placeholder-gray-400 text-gray-700 text-md font-medium mt-2 h-[35px] p-2 focus:focus:outline-none"
/>
</div>
<div className="">
<label className="">아이디: </label>
<input
onChange={handleChange}
id="userId"
name="userId"
value={userData.userId}
className="w-[200px] border-b-[1px] border-gray-500 placeholder-gray-400 text-gray-700 text-md font-medium mt-2 h-[35px] p-2 focus:focus:outline-none"
/>
</div>
<div className="my-2">
<button
onClick={userDataSelect}
className="w-5/12 my-2 bg-blue-700 text-gray-100 p-2 h-[40px] font-bold text-md py-2 px-2 rounded-md hover:ring hover:ring-blue-700"
>
download
</button>
</div>
</div>
</div>
</section>
);
};
export default ExcelDownload;
[ 결과화면 ]
- 관리자 페이지의 사용자데이터관리 - 엑셀
- 버튼 클릭시 조회된 데이터 엑셀로 다운로드
'React + Node.js' 카테고리의 다른 글
[MySchedule project] 20. 관리자 - 로그관리 페이지 구현 (1) | 2024.02.27 |
---|---|
[MySchedule project] 19. header (Navbar) 모바일 반응형 / 툴팁 / 토글 사용 (1) | 2024.02.27 |
[MySchedule project] 17. styled components 사용하기 / Footer (0) | 2024.02.20 |
[MySchedule project] 16. React-big-Calendar 사용하기 (2) (0) | 2024.02.20 |
[MySchedule project] 15. React-big-Calendar 사용하기 (1) (0) | 2024.02.20 |