一、最终效果&github
github先贴出来:可以看详细配置,demo也可以直接复制粘贴试一下:
https://github.com/natergj/excel4node
最终效果整这样:
话不多说,我们开始实战~开冲!
二、安装excel4node
npm i excel4node
三、引入
const xl = require("excel4node");
四、创建假数据
创建三条假数据
const fishlist = [
{
imgUrl: path.join(__dirname, '../public/imgs/1612275667938.jpg'),
name: "娃娃鱼",
weight: "0.1"
},
{
imgUrl: path.join(__dirname, '../public/imgs/1612275667938.jpg'),
name: "娃娃鱼",
weight: "0.1"
},
{
imgUrl: path.join(__dirname, '../public/imgs/1612275667938.jpg'),
name: "娃娃鱼",
weight: "0.1"
}
]
五、设置样式
设置每个格子中的内容水平和垂直都居中
const myStyle = {
alignment: {
horizontal: 'center',
vertical: 'center'
}
};
六、下载功能实现
1、添加表格
// 创建工作簿
const wb = new xl.Workbook();
// 创建style
const style = wb.createStyle(myStyle);
// 向工作簿添加一个表格
let ws = wb.addWorksheet('Sheet 1');
2、创建表头
ws.cell(1, 1).string('序号').style(style); // cell(1, 1)表示excel表格中的A1
ws.cell(1, 2).string('图片').style(style); // cell(1, 2)表示excel表格中的B1
ws.cell(1, 3).string('名称').style(style);
ws.cell(1, 4).string('重量/kg').style(style);
3、绘制表格
fishlist.forEach((item, i) => {
// 序号
ws.cell(3 + 4 * i, 1).number(i + 1).style(style);
// 图片
ws.addImage({
path: item.imgUrl,
type: 'picture',
position: {
type: 'twoCellAnchor', // 双锚点定位
from: {
col: 2, // 图片左上角的位置, 如果要设置一张3x3的图片,左上角设置为
colOff: 0, // col: 1, row: 1,右下角就为 col: 4, row: 4
row: 2 + 4 * i,
rowOff: 0,
},
to: {
col: 3, // 图片右下角的位置
colOff: 0,
row: 5 + 4 * i,
rowOff: 0,
},
},
});
// 名称
ws.cell(3 + 4 * i, 3).string(item.name).style(style);
// 重量
ws.cell(3 + 4 * i, 4).string(item.weight).style(style);
});
4、响应下载
通过这一步,前端请求该api,便可直接下载文件,无需在服务器中创建文件
// 设置请求头, 如果直接使用http中间件,
// 可以直接调用write方法,例wire(response)即可,原理请看下面
ctx.set('Content-Length', buffer.length);
ctx.set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
ctx.set('Content-Disposition', 'attachment; filename="' + encodeURIComponent(fileName) + '"; filename*=utf-8\'\'' + encodeURIComponent(fileName) + ';');
ctx.body = buffer;
七、完整代码
const xl = require("excel4node");
const fishlist = [
{
imgUrl: path.join(__dirname, '../public/imgs/1612275667938.jpg'),
name: "娃娃鱼",
weight: "0.1"
},
{
imgUrl: path.join(__dirname, '../public/imgs/1612275667938.jpg'),
name: "娃娃鱼",
weight: "0.1"
},
{
imgUrl: path.join(__dirname, '../public/imgs/1612275667938.jpg'),
name: "娃娃鱼",
weight: "0.1"
}
]
const myStyle = {
alignment: {
horizontal: 'center',
vertical: 'center'
}
};
const downloadExcel = async (ctx, next) => {
// 创建工作簿
const wb = new xl.Workbook();
const style = wb.createStyle(myStyle);
// 向工作簿添加一个表格
let ws = wb.addWorksheet('Sheet 1');
ws.cell(1, 1).string('序号').style(style);
ws.cell(1, 2).string('图片').style(style);
ws.cell(1, 3).string('名称').style(style);
ws.cell(1, 4).string('重量/kg').style(style);
fishlist.forEach((item, i) => {
ws.cell(3 + 4 * i, 1).number(i + 1).style(style);
ws.addImage({
path: item.imgUrl,
type: 'picture',
position: {
type: 'twoCellAnchor',
from: {
col: 2,
colOff: 0,
row: 2 + 4 * i,
rowOff: 0,
},
to: {
col: 3,
colOff: 0,
row: 5 + 4 * i,
rowOff: 0,
},
},
});
ws.cell(3 + 4 * i, 3).string(item.name).style(style);
ws.cell(3 + 4 * i, 4).string(item.weight).style(style);
});
const fileName = "fishlist.xlsx";
const buffer = await wb.writeToBuffer();
ctx.set('Content-Length', buffer.length);
ctx.set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
ctx.set('Content-Disposition', 'attachment; filename="' + encodeURIComponent(fileName) + '"; filename*=utf-8\'\'' + encodeURIComponent(fileName) + ';');
ctx.body = buffer;
};
module.exports = {
downloadExcel
}
八、(不想看可以跳过)write方法的部分源码
在excel4node的源码中可以看到,当write方法传入http.ServerResponse时,会自动生成请求头并返回
key: 'write',
value: function write(fileName, handler) {
var _this = this;
builder.writeToBuffer(this).then(function (buffer) {
switch (typeof handler === 'undefined' ? 'undefined' : _typeof(handler)) {
// handler passed as http response object.
case 'object':
if (handler instanceof http.ServerResponse) {
handler.writeHead(200, {
'Content-Length': buffer.length,
'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'Content-Disposition': 'attachment; filename="' + encodeURIComponent(fileName) + '"; filename*=utf-8\'\'' + encodeURIComponent(fileName) + ';'
});
handler.end(buffer);
} else {
throw new TypeError('Unknown object sent to write function.');
}
break;
});
handler.end(buffer);
} else {
throw new TypeError('Unknown object sent to write function.');
}
break;