프로젝트를 진행하면서 엑셀 다운로드 작업 시 자주 사용하는 exceljs 대해 정리했다.
👉 선택 이유
npm trends를 보면 지난 1간 라이브러리 다운로드 횟수입니다. xlsx 다운로드 수가 더 많지만 ExcelJS를 선택한 이유는 다음과 같습니다.
exceljs | xlsx | |
스타일링과 서식 지정 | 세밀한 스타일링이 필요할 때 유리 ( 다양한 서식 기능, 차트, 이미지, 다양한 셀 유형을 지원 ) |
복잡한 서식이나 스타일링에는 제한 (기본적인 읽기, 쓰기 기능을 제공) |
호환성과 데이터 처리 | Excel 파일 => JSON 형식, JSON 데이터 => Excel로 변환하는 기능이 있음 ---- 세밀한 데이터 조작, 복잡한 데이터 처리 요구 사항 가능 |
대량의 데이터를 신속하게 처리할 수 있지만, 복잡한 데이터 변환이나 고급 조작에는 제약 |
파일 포맷 | xlsx, csv | xlsx, csv, html, json 등 |
*스트림 지원 | O ( 복잡한 스트림 처리 작업을 더 간편하게 할 수 있음 ) |
X ( *레거시 포맷을 지원하기 때문에 스트림 API가 복잡하거나 사용하기 어려움) |
* 스트림 읽기(Streaming Read) : 대량의 데이터를 처리할 때 메모리 사용을 최적화하고 성능을 개선하기 위해 사용되는 기법으로 데이터를 한 번에 모두 읽는 대신, 데이터의 일부분씩 순차적으로 읽어 처리합니다. 이 방법은 특히 대규모 파일을 다룰 때 유용합니다
*레거시 포맷 : 레거시 포맷 (예: xls)은 최신 포맷 (예: xlsx)과 구조가 다르기 때문에, 스트림 API를 사용하여 이러한 파일을 처리할 때 복잡성이 증가할 수 있습니다. 레거시 포맷의 경우, 데이터 구조와 파일 형식의 차이로 인해 스트리밍 읽기와 쓰기 작업이 더 복잡할 수 있습니다.
결론
exceljs는 복잡한 Excel 파일의 서식, 스타일링, 고급 기능을 지원하고, JSON과의 호환성으로 데이터 처리 및 조작이 유리하여, 프로젝트의 요구 사항에 적합하다고 판단되었습니다. xlsx는 성능 면에서는 우수하지만, 서식 및 스타일링의 제약과 복잡한 데이터 조작의 어려움으로 인해 exceljs를 선택하게 되었습니다.
사용법
exceljs npm
exceljs 설치
npm install exceljs
엑셀 파일 생성 및 다운로드
import ExcelJS from "exceljs"
export default function ExcelDownload() {
const data = [
{
userID: "12345678",
userName: "ABC",
userEmail: "abc@gmail.com",
createTime: "2023-11-26 10:11:00",
},
{
userID: "46578945",
userName: "DEF",
userEmail: "def@gmail.com",
createTime: "2023-11-26 12:51:10",
},
{
userID: "98745651",
userName: "가나",
userEmail: "가나@gmail.com",
createTime: "2023-11-26 22:30:00",
},
];
const [userDataLoading, setUserDataLoading] = useState(false);
const handleExcelDownload = async () => {
setUserDataLoading(true); // 로딩
const workbook = new ExcelJS.Workbook();
setUserDataLoading(false); // 로딩
const worksheet = workbook.addWorksheet("My Sheet");
worksheet.columns = [
{
header: "userID",
key: "userID",
width: 20,
style: { alignment: { horizontal: "left" } },
},
{
header: "닉네임",
key: "userName",
width: 20,
style: { alignment: { horizontal: "left" } },
},
{
header: "이메일",
key: "userEmail",
width: 30,
style: { alignment: { horizontal: "left" } },
},
{
header: "생성날짜",
key: "createTime",
width: 30,
style: { alignment: { horizontal: "left" } },
},
];
for (let i = 0, j = data.length; i < j; i++) {
worksheet.addRow({
userID: data[i].userID,
userName: data[i].userName,
userEmail: data[i].userEmail,
createTime: data[i].createTime.replace(/-/g, "."),
});
}
workbook.xlsx.writeBuffer().then((buffer) => {
const blob = new Blob([buffer], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
const excelDonwloadUrl = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = excelDonwloadUrl;
link.setAttribute("download", `엑셀내역_${formatDate(new Date())}.xlsx`);
document.body.appendChild(link);
link.click();
});
};
return (
<>
<section>
<button css={excelBtn} onClick={() => handleExcelDownload()}>
<Image
src={"/excelIcon.png"}
alt="excelIcon"
width={18}
height={18}
/>
<span>엑셀 다운로드</span>
</button>
</section>
{userDataLoading && (
<div css={excelDownloadLoading}>
<span>엑셀 다운로드중입니다.</span>
</div>
)}
</>
);
}
const excelBtn = css`
width: 200px;
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
background-color: #207245;
img {
filter: grayscale(1) brightness(3);
}
span {
color: #fff;
margin-left: 5px;
font-weight: 500;
}
`;
const excelDownloadLoading = css`
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 20;
background-color: rgba(0, 0, 0, 0.6);
span {
margin-top: -15px;
}
@media (max-width: 1023px) {
height: 100vh;
}
`;
다운로드 된 엑셀 파일
엑셀 파일 업로드
import ExcelJS from "exceljs"
export default function ExcelUpload() {
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const onFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files && event.target.files[0]) {
setSelectedFile(event.target.files[0]);
}
};
const onReadExcelClick = async () => {
//서버로 파일을 업로드할 때 사용
const formData = new FormData();
formData.append("file", selectedFile);
try {
const response = await fetchCreateListByExcel(url, token, formData)
} catch (error) {
console.log(error)
}
console.log(selectedFile);
// 엑셀 파일 읽기
if (selectedFile) {
const workbook = new ExcelJS.Workbook();
const fileBuffer = await selectedFile.arrayBuffer();
await workbook.xlsx.load(fileBuffer);
workbook.eachSheet((sheet) => {
sheet.eachRow((row, rowNumber) => {
console.log(`Row ${rowNumber}: ${row.values}`);
});
});
}
};
return (
<>
<section>
<div css={excelUploadBtn}>
<input
id="file-input"
type="file"
style={{ display: "none" }}
onChange={onFileChange}
/>
<label htmlFor="file-input" className="inputLabel">
{selectedFile ? (
<span style={{ color: "#BCBCBC" }}>{selectedFile.name}</span>
) : (
<span style={{ color: "#BCBCBC" }}>
등록할 파일을 첨부해주세요
</span>
)}
</label>
<button className="uploadBtn" onClick={() => onReadExcelClick()}>
엑셀 업로드
</button>
</div>
</section>
</>
);
}
const excelUploadBtn = css`
width: 500px;
padding: 10px;
.inputLabel {
padding: 10px 50px;
border: 1px solid #fff;
}
.uploadBtn {
background-color: #207245;
margin-left: 10px;
font-weight: 500;
padding: 13px;
color: #fff;
}
`;
업로드 된 엑셀 파일
- 미 업로드
- 업로드 시 파일 명 보임
- 엑셀 내용
'React' 카테고리의 다른 글
React에서 input 관리 (0) | 2024.08.24 |
---|---|
swr 기본 사용법 (0) | 2024.08.24 |
apexcharts (0) | 2024.08.24 |
React에서 Lottie 사용하기 (0) | 2024.08.24 |
React Datepicker (0) | 2024.08.23 |