vue实现把页面导出成word文件的方法
思路:先把页面上的元素转成图片,然后把图片放到word文件中进行导出.
1.先下载依赖
npm install docxtemplater pizzip --save npm install jszip-utils --save npm install jszip --save npm install file-saver --save npm install docxtemplater-image-module-free --save npm install angular-expressions --save npm install html2canvas --save
2.准备word模板
导出word文件需要在项目static文件中先放置一个模板,名称为demo.docx vue2放在static下面,vue3放在public下面
注意:
1)模板文件必须是docx文件。doc文件不能通过修改后缀名变为docx,必须另存时选择docx类型,才能实现类型转变。但是docx是可以通过修改后缀名改为doc文件的,因为office的升级基本都是向下兼容的。
2)使用英文下的花括号;
3)花括号内的键名前后不要有空格,且它与程序中的data对象的键名必须保持一致 ;
4)表格中想要循环添加的数据,需要在开头添加{#键名},在结尾处添加{/键名},例如下图的
{#table}和{/table};5)图片居中不要使用{%%image2}
3.封装js,创建一个js文件,其中代码如下:
import PizZip from 'pizzip' import docxtemplater from 'docxtemplater' import JSZipUtils from 'jszip-utils' import {saveAs} from 'file-saver' /** * 将base64格式的数据转为ArrayBuffer * @param {Object} dataURL base64格式的数据 */ 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; } /** * 导出word,支持图片 * @param {Object} tempDocxPath 模板文件路径 * @param {Object} wordData 导出数据 * @param {Object} fileName 导出文件名 * @param {Object} 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: true }; opts.getImage = (chartId) => { //console.log(chartId);//base64数据 //将base64的数据转为ArrayBuffer return base64DataURLToArrayBuffer(chartId); } opts.getSize = function(img, tagValue, tagName) { //自定义指定图像大小 if(imgSize.hasOwnProperty(tagName)){ return imgSize[tagName]; }else{ return [300, 300]; } } // 创建一个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); }); } /** * 将图片的url路径转为base64路径 * 可以用await等待Promise的异步返回 * @param {Object} imgUrl 图片路径 */ export function getBase64Sync(imgUrl) { return new Promise(function(resolve, reject) { // 一定要设置为let,不然图片不显示 let image = new Image(); //图片地址 image.src = imgUrl; // 解决跨域问题 image.setAttribute("crossOrigin", '*'); // 支持跨域图片 // 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; //转成base64 let dataurl = canvas.toDataURL("image/" + ext, quality); //返回 resolve(dataurl); }; }) }
4.vue文件使用
<template> <el-container class="a-section xxx"> <el-button type="success" @click="download">导出导出</el-button> <div class="canvasBox"> 测试文件内容展示 <el-progress :text-inside="true" :stroke-width="26" :percentage="70"></el-progress> <el-progress :text-inside="true" :stroke-width="24" :percentage="100" status="success"></el-progress> <el-progress :text-inside="true" :stroke-width="22" :percentage="80" status="warning"></el-progress> <el-progress :text-inside="true" :stroke-width="20" :percentage="50" status="exception"></el-progress> </div> </el-container> </template> <script> //刚刚创建的js文件 import { exportWord, getBase64Sync } from 'xxxx.js' import html2canvas from 'html2canvas'; export default { name: 'xxx', mounted() { }, methods: { async download() { // 找到需要导出的元素 var oTd = document.querySelector('.canvasBox'); //使用html2canvas生成base64的图片格式 html2canvas(oTd, { width: Math.floor(oTd.clientWidth), //宽 height: Math.floor(oTd.clientHeight), //高 scale: 2, //设置像素比 useCORS: true, allowTaint: false, }).then((canvas) => { document.body.appendChild(canvas); var img = document.createElement('img'); //获取图片路径 并且转base64格式 img.src = canvas.toDataURL('image/jpeg'); console.log(img.src, "路径"); var dataURL = img.src console.log(dataURL, 'base64格式'); img.setAttribute('id', 'canvasImg'); let data = { imglist: this.imglist, imgUrl: dataURL } let imgSize = { //控制导出的word图片大小 imgurl: [200, 200], }; //导出的文件名称 let docxName = "测试使用.docx"; exportWord("/static/demo.docx", data, docxName, imgSize); }) }, } } </script> <style> </style>
结果展示
以上就是vue实现把页面导出成word文件的方法的详细内容,更多关于vue把页面导出成word的资料请关注脚本之家其它相关文章!
最新评论