vue导出word

news/2024/11/18 2:20:21/

先在项目中安装所需要的依赖包

npm install file-saver
npm install docxtemplater-image-module-free
npm install docxtemplater
npm install pizzip
npm install jszip-utils
//angular-expressions  如果需要自定义图片尺寸需要安装此依赖包

如图,一定要装完整
在这里插入图片描述
然后设计需要导出的word模版,本地新建一个word文档。
在这里插入图片描述

注意:

1)模板文件必须是docx文件。doc文件不能通过修改后缀名变为docx,必须另存时选择docx类型,才能实现类型转变。
2)使用英文下的花括号;
3)花括号内的键名前后不要有空格,且它与程序中的data对象的键名必须保持一致 ;
4)表格中想要循环添加的数据,需要在开头添加{#键名},在结尾处添加{/键名},一般对应的就是需要循环的数组名称。
5)图片居中不要使用{%%image2}
将编辑好的docx文档放在指定文件夹中(使用vue-cli2的放在static文件夹,vue-cli3的放在public文件夹)

新建js文件。export.js
在这里插入图片描述

如果不需要在word中插入图片getBase64Syncbase64DataURLToArrayBuffer方法可直接忽略不写,单纯word可以忽略代码里图像部分

export function getBase64Sync(imgUrl) {return new Promise(function (resolve, reject) {// 一定要设置为let,不然图片不显示let image = new Image();// 解决跨域问题image.crossOrigin = "anonymous";//图片地址image.src = imgUrl;// image.onload为异步加载image.onload = function () {let canvas = document.createElement("canvas");canvas.width = image.width;canvas.height = image.height;let context = canvas.getContext("2d");context.drawImage(image, 0, 0, image.width, image.height);//图片后缀名let ext = image.src.substring(image.src.lastIndexOf(".") + 1).toLowerCase();//图片质量let quality = 0.8;//转成base64let dataurl = canvas.toDataURL("image/" + ext, quality);//返回resolve(dataurl);};});
}//在实际使用过程中遇到了一点问题就是客户在短时间内大量下载文件,导致浏览器崩溃,
//测试后发现是下载的word文件内存过大,原始的word模版只有几十k,导出的图片也只有200k,但下载后的文件高大10M
//搜索文件后发现通过canvas转base64的方式会有可能引起图片内存过大或者过小
//于是修改后采用了下面的方法转base64
export function getBase(imgUrl) {return new Promise((resolve, reject) => {window.URL = window.URL || window.webkitURL;var xhr = new XMLHttpRequest();xhr.open("get", imgUrl, true);// 至关重要xhr.responseType = "blob";xhr.onload = function () {if (this.status == 200) {//得到一个blob对象var blob = this.response;console.log("blob", blob);// 至关重要let oFileReader = new FileReader();oFileReader.onloadend = function (e) {// 此处拿到的已经是 base64的图片了base64 = e.target.result;// return base64;resolve(base64);// console.log("方式一》》》》》》》》》", base64);};oFileReader.readAsDataURL(blob);} else {reject();}};xhr.send();});
}
//导入需要的依赖包
import PizZip from "pizzip";
import docxtemplater from "docxtemplater";
import JSZipUtils from "jszip-utils";
import { saveAs } from "file-saver";//将base64格式的数据转为ArrayBuffer
function base64DataURLToArrayBuffer(dataURL) {const base64Regex = /^data:image\/(png|jpg|jpeg|svg|svg\+xml);base64,/;if (!base64Regex.test(dataURL)) {return false;}const stringBase64 = dataURL.replace(base64Regex, "");let binaryString;if (typeof window !== "undefined") {binaryString = window.atob(stringBase64);} else {binaryString = new Buffer(stringBase64, "base64").toString("binary");}const len = binaryString.length;const bytes = new Uint8Array(len);for (let i = 0; i < len; i++) {const ascii = binaryString.charCodeAt(i);bytes[i] = ascii;}return bytes.buffer;
}/*** 参数明细*  tempDocxPath 模板文件路径* wordData 导出数据* fileName 导出文件名* imgSize 自定义图片尺寸*/
export const exportWord = (tempDocxPath, wordData, fileName, imgSize) => {//这里要引入处理图片的插件var ImageModule = require("docxtemplater-image-module-free");//   const expressions = require("angular-expressions");// 读取并获得模板文件的二进制内容JSZipUtils.getBinaryContent(tempDocxPath, function (error, content) {if (error) {throw error;}//设置图片尺寸大小// expressions.filters.size = function (input, width, height) {//   return {//     data: input,//     size: [width, height],//   };// };// function angularParser(tag) {//   const expr = expressions.compile(tag.replace(/’/g, "'"));//   return {//     get(scope) {//       return expr(scope);//     },//   };// }// 图片处理let opts = {};opts = {//图像是否居中centered: false,};opts.getImage = (chartId) => {//console.log(chartId);//base64数据//将base64的数据转为ArrayBufferreturn base64DataURLToArrayBuffer(chartId);};opts.getSize = function (img, tagValue, tagName) {//console.log(img);//ArrayBuffer数据//console.log(tagValue);//base64数据//console.log(tagName);//wordData对象的图像属性名//自定义指定图像大小if (imgSize.hasOwnProperty(tagName)) {return imgSize[tagName];} else {return [600, 350];}};// 创建一个PizZip实例,内容为模板的内容let zip = new PizZip(content);// 创建并加载docxtemplater实例对象let doc = new docxtemplater();doc.attachModule(new ImageModule(opts));doc.loadZip(zip);doc.setData(wordData);try {// 用模板变量的值替换所有模板变量doc.render();} catch (error) {// 抛出异常let e = {message: error.message,name: error.name,stack: error.stack,properties: error.properties,};console.log(JSON.stringify({error: e,}));throw error;}// 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)let out = doc.getZip().generate({type: "blob",mimeType:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",});// 将目标文件对象保存为目标类型的文件,并命名saveAs(out, fileName);});
};

在需要导出word的文件中引入刚才的js文件

import { exportWord, getBase64Sync } from "@/plugins/export.js";

使用方法

async exportWordTest() {//具体数据根据实际情况灵活变动let data = {num: '测试num',from:'测试来源'image: await getBase64Sync(url),};exportWord("test.docx", data, "测试.docx");
}

在这里插入图片描述
打开生成的word文档

在这里插入图片描述
完成。
遇见报错:Error: Can’t find end of central directory : is this a zip file ?
我的原因是我的word模板直接修改的后缀docx,需要另存为docx才可以。
文章借鉴:https://zhuanlan.zhihu.com/p/497941780


http://www.ppmy.cn/news/73320.html

相关文章

关于SD webui 部署运行的一些坑

[Bug 1]: RuntimeError: Couldnt install gfpgan 可以先尝试&#xff1a; pip install gfpgan 不过是在虚拟环境venv下的 E:\stable-diffusion-webui\venv\Scripts\python.exe -m pip install gfpgan 如果还是无法安装gfpgan的原因是网络问题&#xff0c;就算已经科学上网…

【SAP Abap】X-DOC:SE18/19 - SAP第四代增强概念理解

【SAP Abap】X-DOC&#xff1a;SE18/19 - SAP第四代增强概念理解 1、Tcode2、概念3、增强选项类型4、增强实现类型5、增强操作方式6、增强选项与增强实现关系7、增强实施建议 1、Tcode SE18&#xff1a;Business Add-Ins: Definitions&#xff08;增强点定义/查看&#xff09;…

深度解析Qt背景设计:从基础到高级,从Widget到Quick

深度解析Qt背景设计&#xff1a;从基础到高级&#xff0c;从Widget到Quick 一、Qt背景设计的基础知识&#xff08;Basic Knowledge of Qt Background Design&#xff09;1.1 Qt背景的基本概念&#xff08;Basic Concepts of Qt Background&#xff09;1.1.1 QWidget和QQuickIte…

网易游戏开发实习生一面面经

面试时长20min&#xff08;没有手撕代码&#xff09; 1、介绍一下自己 2、MonoBehaviour是干什么的 3、说一下Update和FixedUpdate、LateUpdate的区别 4、关于xlua你了解多少 5、你觉得xlua有什么优缺点的地方 6、对Unity插件有了解吗 7、说一下shared_ptr和weak_ptr&#xff1…

C++ map用法总结(整理)

1&#xff0c;map简介 map是STL的一个关联容器&#xff0c;它提供一对一的hash。 第一个可以称为关键字(key)&#xff0c;每个关键字只能在map中出现一次&#xff1b;第二个可能称为该关键字的值(value)&#xff1b; map以模板(泛型)方式实现&#xff0c;可以存储任意类型的…

2023五一数学建模B题完整思路

已更新五一数学建模ABC题思路&#xff0c;文章末尾获取&#xff01; B题思路&#xff1a; 问题1&#xff1a;附件1为该快递公司记录的2018年4月19日—2019年4月17日的站点城市之间(发货城市-收货城市)的快递运输数据&#xff0c;请从收货量、发货量、快递数量增长/减少趋势、…

厚积薄发|迭代为什么叫冲刺?

上士闻道&#xff0c;勤而行之&#xff1b;中士闻道&#xff0c;若存若亡&#xff1b;下士闻道&#xff0c;大笑之。不笑不足以为道。–《道德经》 软件工程从原始的作坊式工作方式&#xff0c;经过了哪些思考、哪些方案的试探&#xff0c;才在不断地尝试与改善后&#xff0c;走…

java接口与实现

文章目录 一、Java接口二、Java实现接口三、Java接口回调四、Java接口与多态五、Java接口参数六、Java接口与抽象类的比较七、Java接口的UML图总结 一、Java接口 接口是Java语言中一种重要的数据类型&#xff0c;通常使用关键字interface来定义一个接口。 接口的定义和类的定…