Mã phía máy chủ
> pnpm add -w exceljs
async downloadExcel(ctx) {
const category = ctx.request.body.categoryId || 'user';
const workbook = new ExcelJs.Workbook();
workbook.creator = 'ABC';
workbook.lastModifiedBy = 'ABC';
workbook.created = new Date();
workbook.modified = new Date();
workbook.lastPrinted = new Date();
const sheet = workbook.addWorksheet('Dữ liệu', { properties: { tabColor: { argb: 'FFC0CB' } } });
sheet.columns = this._getColumnDefinitions(category);
const filePath = `./${category}.xlsx`;
try {
await workbook.xlsx.writeFile(filePath);
} catch (err) {
return this.sendResponse(ctx, null, { message: 'Tạo mẫu thất bại' });
}
ctx.set(`Content-Disposition`, `attachment; filename=${category}.xlsx`);
ctx.set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
ctx.body = fs.createReadStream(filePath);
}
_getColumnDefinitions(category) {
switch (category) {
case 'user':
return [
{
header: 'Mã số',
key: 'userId',
width: 15
},
{
header: 'Email cá nhân',
key: 'emailAddr',
width: 35
},
{
header: 'Số điện thoại',
key: 'phoneNum',
width: 15
},
{
header: 'Tên',
key: 'firstName',
width: 15
},
{
header: 'Họ',
key: 'lastName',
width: 15
},
{
header: 'Tuổi',
key: 'age',
width: 10
},
{
header: 'Địa chỉ',
key: 'address',
width: 40
},
{
header: 'Trường học',
key: 'schoolName',
width: 25
},
{
header: 'Lớp',
key: 'classLevel',
width: 10
},
{
header: 'Cấp độ',
key: 'level',
width: 10
},
{
header: 'Điểm thưởng',
key: 'points',
width: 10
},
{
header: 'Ảnh đại diện',
key: 'avatarUrl',
width: 20
},
{
header: 'Chức danh',
key: 'title',
width: 20
},
];
default:
return [];
}
}
Mã phía máy khách
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Ứng dụng thử nghiệm</title>
</head>
<body>
<script src="./node_modules/axios/dist/axios.min.js"></script>
<script>
axios.get('api/excel-download', { responseType: 'arraybuffer' })
.then((response) => {
const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'danh_sach.xlsx';
document.body.appendChild(link);
link.click();
window.URL.revokeObjectURL(url);
})
.catch((error) => {
console.error(error);
});
</script>
</body>
</html>
Các vấn đề phát sinh
- Sai định dạng khi tải về, cần kiểm tra `type` là `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`.
- Đọc file không đúng cách có thể dẫn đến việc không mở được file. Sử dụng `axios` với `responseType: 'arraybuffer'` để đảm bảo đọc chính xác.
- Các hộp chọn không hỗ trợ kiểu key-value trực tiếp, nên nếu muốn xác thực giá trị phải thêm các bộ kiểm tra riêng lẻ trong vòng lặp.