nodejs 根据excel表格和word模板,生成对应的多份word模板
一、效果
二、 需求
根据表格中的开票名称的金额,生成对应的单位对账函,然后发给各单位的负责人进行审核。由于word模板样式一致,故可用模板填充数据,进行企业对账函的一次性生成
三、前端vue技术
前端采用vue、avue、elementUI 技术
1、前端主要代码
<template><div style="padding: 20px"><div style="display: flex"><div style="margin-right: 20px"><el-upload:show-file-list="false"action="action":on-change="handleChange"><el-button type="primary">上传销售金额Excel</el-button></el-upload></div><div style="margin-right: 20px"><el-date-pickerv-model="daterange"type="daterange"range-separator="至"start-placeholder="开始日期"format="yyyy年MM月dd日"value-format="yyyy年MM月dd日"end-placeholder="结束日期"></el-date-picker></div><el-button type="primary" @click="createWordFiles">生成对账函</el-button></div><avue-crud :data="data" :option="option" ref="crud"></avue-crud></div>
</template>
<script>
import { createWordFilesApi } from "../api/api";
export default {data() {return {data: [],daterange: [],title: "",option: {index: true,menu: false,addBtn: false,page: false,column: [{label: "单位",prop: "company",},{label: "金额",prop: "totalPrice",},{label: "开票名称",prop: "ticketName",},],},};},methods: {handleChange(file, fileLis) {this.$export.xlsx(file.raw).then((data) => {console.log("data", data);this.title = data.header[0];let re = data.results;let result = [];for (let i = 1; i < re.length; i++) {let item = re[i];result.push({company: item[this.title],totalPrice: item.__EMPTY,ticketName: item.__EMPTY_1 ? item.__EMPTY_1 : "",});}this.data = result;});},createWordFiles() {let params = {title: this.title,data: JSON.stringify(this.data),startDate: this.daterange[0],endDate: this.daterange[1],};createWordFilesApi(params).then((res) => {console.log('res: ', res);let data =res.data.data;let a = document.createElement('a');a.style.display='none';a.href="http://localhost/upload"+data.fileUrl;a.download = data.fileName;document.body.append(a);a.click();console.log("我单击了a标签")document.body.removeChild(a)// this.$message({// type: "success",// message: "生成成功!",// });}).catch((res)=>{console.log('fail-res: ', res);});},},
};
</script>
<style>
</style>
四、nodejs 技术
express +nodejs
1、生成文件并压缩文件夹
var fs = require("fs");
var util = require("../public/util");const PizZip = require("pizzip");
const Docxtemplater = require("docxtemplater");
const path = require("path");const archiver = require("archiver");const compressing = require("compressing");var fstream = require("fstream");
var zlib = require("zlib");
var tar = require("tar");let info = {createWordFilesApi: async function (req, res) {let result = req.body;let floderName = result.title + "-" + util.getNowFormatDate();let floder = "./企业对账函/" + floderName;let path = floder + "/";//生成文件夹目录fs.mkdirSync(path);// 加载docx模板 注意:只能用docx后缀名,如果为doc后缀名,需手动另存为docxconst content = fs.readFileSync("./word.docx", "binary");//生成docx文档let fileData = JSON.parse(result.data);for (let i = 0; i < fileData.length; i++) {let item = fileData[i];//注意:let zip = new PizZip(content); 需每次实例化,不然渲染出来所有的文件都为第一条数据let zip = new PizZip(content);let doc = new Docxtemplater(zip);//设置参数doc.setData({ticketName: item.ticketName ? item.ticketName : item.company,totalPrice: item.totalPrice,uppercaseTotalPrice: util.transCnMoney(item.totalPrice),startDate: result.startDate,endDate: result.endDate,});// 渲染doc.render();// 导出数据const buf = doc.getZip().generate({ type: "nodebuffer" });fs.writeFileSync(path + item.company + ".docx", buf);}let downLoadFile = floder + "-对账函.tgz";//压缩文件 因为需下载生成的压缩文件,故采用gzip压缩,试了其他两种压缩方式,均未能正常下载tar.c({gzip: true,file: downLoadFile,},[floder]).then(() => {let data = {};data.code = "200";data.data = {fileName: floderName + "-对账函.zip",fileUrl: "/" + downLoadFile.split("./")[1],};data.message = "生成文件夹成功";res.send(data);});// const output = fs.createWriteStream(downLoadFile);// // const archive = archiver("zip", {// // zlib: { level: 9 }, // Sets the compression level.// // });// const archive = archiver("tar", {// gzip:true,// gzipOptions:{// level: 9// }// });// archive.pipe(output);// archive.directory(path, false);// archive.finalize();//await compressing.tgz.compressDir(floder, downLoadFile)// let data = {};// data.code = "200";// data.data = {// fileName: floderName + "-对账函.zip",// fileUrl: "/" + downLoadFile.split("./")[1],// };// data.message = "生成文件夹成功";// res.send(data);},
};module.exports = info;
2、下载文件
const path = require('path')
let express = require('express')
let fs = require('fs')
var mime = require('mime');
let router = express.Router()router.get('/*', (req,res) => {var filePath = "./"+req.params["0"];// var filePath = "./企业对账函/2022年1月份销售-20220211083510-对账函.zip";
// console.log('filePath: ', filePath);
// console.log('download');
// var f=filePath;
// //var f = req.params[0];
// f = path.resolve(f);
// console.log('Download file: %s', f);
// res.download(f);var file = fs.readFileSync(filePath, 'binary');
console.log('file: ', file.length);var file=filePath;var f = fs.createReadStream(file);var filename = path.basename(file);console.log('filename: ', filename);var mimetype = mime.getType(file);console.log('mimetype: ', mimetype);// res.setHeader('Content-Disposition', 'attachment; filename=' + filename);// res.setHeader('Content-Type', mimetype); //application/zip// var filestream = fs.createReadStream(file);// filestream.pipe(res)// res.writeHead(200, {// 'Content-Type': 'application/force-download',// 'Content-Disposition': 'attachment; filename=price_letter.zip'// });res.writeHead(200, {'Content-Type': "application/octet-stream",'Content-Disposition': 'attachment; filename=price_letter.gzip',//'Content-Length':352*1024,'Content-Encoding':'gzip ',//'Content-Encoding':'deflate',//gzip'Transfer-Encoding':'chunked'});f.pipe(res);
})module.exports = router
五、所遇问题
1、
所遇问题的node版本为14.X.X,升级为16.X.X 解决了此问题
2、下载文件损坏
需了解:1、Content-Encoding值
gzip 表明实体采用GNU zip编码
compress 表明实体采用Unix的文件压缩程序
deflate 表明实体是用zlib的格式压缩的
identity 表明没有对实体进行编码。当没有Content-Encoding header时, 就默认为这种情况
gzip, compress, 以及deflate编码都是无损压缩算法,用于减少传输报文的大小,不会导致信息损失。 其中gzip通常效率最高, 使用最为广泛。
2、Content-Length
Content-Length用于描述HTTP消息实体的传输长度the transfer-length of the message-body。在HTTP协议中,消息实体长度和消息实体的传输长度是有区别,比如说gzip压缩下,消息实体长度是压缩前的长度,消息实体的传输长度是gzip压缩后的长度
3、Transfer-Encoding: chunked
注意:压缩时需要采用gzip压缩,才不会出现问题
Transfer-Encoding: chunked 表示输出的内容长度不能确定,普通的静态页面、图片之类的基本上都用不到这个。
但动态页面就有可能会用到,但我也注意到大部分asp,php,asp.net动态页面输出的时候大部分还是使用Content-Length,没有使用Transfer-Encoding: chunked。
不过如果结合:Content-Encoding: gzip 使用的时候,Transfer-Encoding: chunked还是比较有用的。
记得以前实现:Content-Encoding: gzip 输出时,先把整个压缩后的数据写到一个很大的字节数组里(如 ByteArrayOutputStream),然后得到数组大小 -> Content-Length。
如果结合Transfer-Encoding: chunked使用,就不必申请一个很大的字节数组了,可以一块一块的输出,更科学,占用资源更少。
这在http协议中也是个常见的字段,用于http传送过程的分块技术,原因是http服务器响应的报文长度经常是不可预测的,使用Content-length的实体搜捕并不是总是管用。
参考链接:nodejs提取excel中的信息填充到word文件,批量生成合同
node docx模板引擎
Nodejs做后端,实现文件压缩下载的几种方案(archiver、compressing、linux的zip命令)
NodeJS下载文件实例
transfer-encoding:chunked的含义
HTTP协议中Content-Length的详细解读
nodejs 根据excel表格和word模板,生成对应的多份word模板相关推荐
- 【PHP】PHP使用PHPExcel生成Excel表格文件(附带随机生成英文名函数)
[PHP]PHP使用PHPExcel生成Excel表格文件(附带随机生成英文名函数) 前言 由于业务需要,我们需要从业务中汇总数据,并生成Excel文件. 思路是这样的 PHP要导出Excel表格文件 ...
- excel怎样修改表格时间和计算机一制,Excel表格中如何自动生成记录数据的日期和时间...
前几天有人问我:Excel表格在录入信息时如何在日期单元格自动生成日期时间? 在录入表格的时候,我们经常需要录入时间,比要填写出入库时间,为了减少录入的工作量,可以把日期设置为自动生成. 例如我们在B ...
- 如何从Excel表格导入数据批量生成二维码
目前二维码应用渐趋广泛,二维码具有储存量大.保密性高.追踪性高.抗损性强.备援性大.成本便宜等特性,这些特性特别适用于表单.安全保密.追踪.证照.存货盘点.资料备援等方面.那么我们怎么用条码打印软件从 ...
- 【csv文件转xml文件】Excel表格数据快速批量生成xml格式文件
使用背景: 使用场景举例:数据集标签处理 有时候我们需要将固定格式的Excel表格文件(csv文件)转换为xml文件使用,例如我们在目标检测实验当中我们需要制作数据集Pascal VOC格式的标签文件 ...
- Excel表格中如何快速生成下拉菜单
Excel表格中如何快速生成下拉菜单 目录 Excel表格中如何快速生成下拉菜单 1.例如下表先手动输入前几组的"等级"类别"优良中差" 2.同时按住 alt ...
- python excel模板 生成excel表格_python使用xlwt生成Excel表格
在工作中,遇到了使用python生成Excel表格的需求,经过资料的查找与对比,决定使用第三方库xlwt来生成Excel表格,现做如下总结: 简单例子: import xlwt wb = xlwt.W ...
- node-js——将excel表格转换成json文件
文章目录 将excel表格转换成json文件 步骤 一.引用nodejs的xlsx模块,读取表格的数据 二.引入fs模块,创建文件并写入 三.写一个bat脚本,双击自动执行nodejs文件 示例文件下 ...
- python按某列拆分excel表格_Python实现将excel表格按某列拆分为多个sheet(模板格式不变)...
#将一个excel表格,按照某列分为不同的sheet,并且将id作为sheet表格的名称 from openpyxl import load_workbook #加载需要拆分的总表个 wb = loa ...
- 如何从Excel表格导入数据批量生成二维码 1
目前二维码应用渐趋广泛,二维码具有储存量大.保密性高.追踪性高.抗损性强.备援性大.成本便宜等特性,这些特性特别适用于表单.安全保密.追踪.证照.存货盘点.资料备援等方面.那么我们怎么用条码打印软件从 ...
最新文章
- SQL数据库的数据体系结构
- 网工路由基础(4)EIGRP协议
- tensorflow教程 学习笔记 之 Eager execution 急切执行
- linux常用命令(1)帮助命令man使用
- Object类和String类
- Web应用安全————Shiro 解决会话固定漏洞
- 测试人员眼中的问题解决策略
- SAE学习-使用SAE的Storage服务存储图片
- 文件自动备份和同步bypy和syncthing
- php移动文件的函数 move_uploaded_file()和copy
- Jsp/servlet面试题
- 云数据中心容灾备份方案
- 转:飞思卡尔单片机RAM与flash相关问题
- java commons math_Apache Commons Math
- SketchUp2020下载SketchUp2020下载安装SketchUp草图大师2020下载安装详细教程
- 手算KMP算法nextval数组
- python单位根检验平稳性怎么看是否平稳_PYthon ADF 单位根检验 如何查看结果
- Guge搜索引擎汇总
- 你知道啥是无监督聚类吗?
- 奥塔哥大学计算机科学怎样,奥塔哥大学自然科学学院挂科率高吗?
热门文章
- 深入理解 tornado 之 底层 ioloop 实现(一)
- 运行PHP程序时提示“Notice: Undefined index”的解决办法
- 网络电视盒子的选择经验
- 创业者必看(马云语录)
- intel n100核显性能 intel n100评测 n100相当于什么水平
- auto-extending data file /ibdata1 is of a different size 17152 pages (rounded down to MB)
- 喜报|九州云获评“浙江省高新技术企业研究开发中心”
- 运营商SDWAN组网对比之---思科Cisco-SDWAN高珊珊的博客
- 全新VR全景可视化制作小程序系统源码+公众号功能模块1.0.28
- AAA服务器搭建与实验案例