一、实现效果 

以填写并导出房屋出租审批表为例,首先填写表格相应内容后,点击" 导出 "按钮实现word文档的导出功能,界面如下所示:

最后导出word文档如下所示:

二、所需插件 

这里使用npm对以下所需依赖进行安装,并在后面封装的js文件(导出word文档主要实现方法)中引入 。

-- 安装 docxtemplater
npm install docxtemplater pizzip  --save
-- 安装 jszip-utils
npm install jszip-utils --save
-- 安装 jszip
npm install jszip --save
-- 安装 FileSaver
npm install file-saver --save
-- 引入处理图片的插件1
npm install docxtemplater-image-module-free --save
-- 引入处理图片的插件2
npm install angular-expressions --save

三、word文档模板 

在导出word之前,需要准备一个word模板文件(按自己所需最后导出的样式),放到该vue项目public文件夹下, 房屋出租审批表模板word样式如下所示:

需要填写的部分都被定义为变量或者json对象数组,具体格式如下:

1.  单一变量使用  {  }  包含,例如:

{ user } 、{ area }

2.  json数组格式,则包裹一个循环对象,例如:

原格式为:

"thinglist": [{ time :"2022-4-1",thing: "在家"},{ time :"2022-4-2",thing: "上班"},]

在模板文件中表示为:

{#thinglist}{time}-{thing}
{/thinglist}

如果对象是图片地址时,需要在对象前加上% ,例如:

原格式为:

imglist:[{ imgUrl: "  "},{ imgUrl: "  "},
]

在模板文件中表示为:

{#imglist}{%imgUrl}
{/imglist}

四、封装js 文件

这部分主要是实现word文档导出含图片的主要实现方法,包括将图片的url路径转为base64路径、base64转二进制、以及导出图片的处理,可以直接复制粘贴在页面引入使用,具体代码如下:

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的数据转为ArrayBufferreturn 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;//转成base64let dataurl = canvas.toDataURL("image/" + ext, quality);//返回resolve(dataurl);};})
}

五、实现导出word文档

1.  首先是前端部分,这里使用ElementPlus进行前端页面实现,代码如下:

<template><div class="page-css"><el-card class="box-card" shadow="never"><div class="search-data"><el-button type="success" @click="editVisible=true">填写审批表</el-button></div> </el-card><el-dialog v-model="editVisible" title="房屋出租审批表" width="50%" custom-class="role-mask"><div><div class="tablename"><h2>房屋出租审批表</h2></div><table class="tb" border="1"><tr><td height="60">承租人</td><td colspan="2"  width="180"><input class="inputone" v-model="user"/></td><td colspan="2" width="125">房屋面积</td><td colspan="2" width="175"><input class="inputtwo" v-model="area" />平方米</td></tr><tr><td height="60">年租金</td><td colspan="2" ><input class="inputtwo" v-model="annualrent" />元/年</td><td colspan="2" >出租用途</td><td colspan="2" ><input class="inputone" v-model="purpose"/></td></tr><tr><td height="300">房屋平面示意图</td><td  colspan="6"><div v-for="(item,index) in imglist"><img style="width: 60%;" :src="item.imgUrl"/></div></td></tr></table></div><template #footer><span class="dialog-footer"><el-button type="info" @click="editVisible=false">取消</el-button><el-button type="primary" @click="exportWordFile" >导出</el-button></span></template></el-dialog> </div>
</template>

实现过程遇到一个问题:使用el-dialog弹出框时,想固定其在页面居中、距离页面顶部以及底部的固定距离,但是里面的表格内容却超出其显示范围,该如何实现喃?css设置如下:

/* 弹出框居中显示 */
/deep/.el-dialog {left: 50%;top: 50%;transform: translate(-50%, -50%);margin: 0px !important;
}
/* 弹出框超出部分滑动 */
/deep/.el-dialog__body {height: 75vh;overflow: hidden;overflow-y: auto;
}

包括更改el-dialog弹出框头部以及底部区域样式,css设置如下:

/deep/.el-dialog__header {width: 100%;background-color:#f8f8f8 ;
}
/deep/ .el-dialog__footer {width: 100%;border-top: 1px #ebebeb solid ;
}

2.然后在页面内引入封装js里的exportWord以及getBase64Sync方法,data部分定义的是双向绑定填写的内容以及图片地址,考虑到图片可能不知一张,需要循环对其处理转为base64路径,代码如下:

// 引入将图片的url路径转为base64路径的方法
for (let i in this.imglist) {this.imglist[i].imgUrl = await getBase64Sync(this.imglist[i].imgUrl)
}

完整代码如下所示:

<script>
import {exportWord,getBase64Sync} from '@/assets/js/outword.js'
export default {data () {return {editVisible:false,user:'',area:'',annualrent:'',purpose:'',imglist:[{imgUrl: "https://img2.baidu.com/it/u=2709954499,581919391&fm=253&fmt=auto&app=138&f=JPEG?w=468&h=518"},{imgUrl: "https://img0.baidu.com/it/u=1462004956,1440895436&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=353"}]}   },methods:{async exportWordFile (){for (let i in this.imglist) {this.imglist[i].imgUrl = await getBase64Sync(this.imglist[i].imgUrl)}let  data= {user:this.user,area:this.area,annualrent:this.annualrent,purpose:this.purpose,imglist:this.imglist}let imgSize = {//控制导出的word图片大小imgurl:[200, 200],};exportWord("/房屋出租审批表.docx", data, "房屋出租审批表.docx", imgSize);}   }
}
</script>

vue实现导出word文档(含多张图片)相关推荐

  1. 使用freemarker导出word文档包含多张图片

    使用freemarker导出word文档包含多张图片 最近项目中有个需求就是导出word文档并且文档中需要有多张图片,我当时一脸懵逼啊,之前没有搞过这个啊,但是不要灰心,肯定会有很多人搞过的,百度一下 ...

  2. vue页面导出Word文档(含图片)

    引用插件 安装 npm i docxtemplater@3.17.6 npm i pizzip npm i jszip-utils@0.1.0 npm i jszip@2.6.1 npm i file ...

  3. vue简易导出word文档——docxtemplater使用介绍

    好久不见,上班时间 时间紧急,把领导要写的文档写好复制了一份发给大家(斜眼笑). 一.下载依赖 npm install docxtemplater pizzip --save // 处理docx模板 ...

  4. vue动态导出word文档

    首先 要npm这四个依赖包 jszip jszip-utils docxtemplater file-saver 个人建议用cnpm , npm总是会出现莫名其妙的问题 hellowword.vue ...

  5. vue 生产word_nodejs(officegen)+vue(axios)在客户端导出word文档

    前言 我的项目中有一个需求:点击按钮生成可编辑的word文档订单详情的信息 我使用的前端框架是Vue.js.后台使用的是node.js node.js生成和导出word文档我参考的是下面这两篇文章,写 ...

  6. vue 导出word文档(包括图片)

    vue 导出word文档(包括图片) 1.打开终端,安装依赖 -- 安装 docxtemplater npm install docxtemplater pizzip --save-- 安装 jszi ...

  7. vue前端html页面导出word文件,Vue-纯前端导出word文档

    在项目中,我们可以借助后端返回文件流实现文件下载.如果前端有数据,也可以借助前端框架进行下载.本文将介绍如何在前端纯js实现word文档导出. 1. 组件介绍 要实现前端纯js导出word文档,我们需 ...

  8. 「Vue To Words」 - 教你在Vue项目中导出Word文档(包含表格合并,图片修改大小)

    前言:最近在项目中遇到了,vue页面需要导出word文档,今日就进行记录一下,如有不对的地方,还请见谅 ^^ 简单说一下需求:需要导出的页面是表格页面,因为包含表格的嵌套和合并,其实最主要的就是导出页 ...

  9. Java 导出Word文档(含图片)doc格式 (保姆级)

    1.maven仓库 <!-- freemarker jar --><dependency><groupId>org.freemarker</groupId&g ...

最新文章

  1. python是一种面向对象的高级语言_爬了世纪佳缘后发现了一个秘密,世纪佳缘找对象靠谱吗?...
  2. Mat 类型转 QImage 类型
  3. 手把手教你安装OpenStack——Ocata安装指南(上)
  4. 一代偶像终将老去,总有AI正在年轻
  5. Spring MVC文件上传
  6. Maven -- group、artifact、package
  7. 最优化课程(part1)
  8. 如何正确地生成一个随机数
  9. 人类视觉计算理论经典著作,豆瓣评分9.7,中文版惊鸿面世!
  10. 深度学习数据集制作_一篇文章搞定人工智能之深度学习创建训练数据集的方法
  11. NAS DIY的设计和实施过程-5-Openfiler篇
  12. 【CV学习笔记】色彩空间
  13. 自动化测试-selenium初始化Driver参考
  14. FreeMarker模板制作
  15. c语言省略号电脑键盘怎么打,省略号的快捷键怎么打【图解】
  16. 【集合论】集合概念与关系 ( 集合表示 | 数集合 | 集合关系 | 包含 | 相等 | 集合关系性质 )
  17. 商品进销差价_商品进销差价如何计算及账务处理怎么做?
  18. 2021年会议平板十大品牌榜中榜,十大会议平板品牌销量排行榜
  19. android aidl混淆代码,Android代码混淆
  20. windows 10 ISO 纯净版 官方来源

热门文章

  1. css3 border img 边框图片
  2. PVT(Pyramid Vision Transformer)学习记录
  3. 咸鱼翻身beta冲刺博客集
  4. erwin教程 mysql_ERWin中生成Oracle数据库
  5. 双绞线的分类—按电气特性分
  6. Scrapy框架实战(五):通用爬虫 CrawlSpider
  7. linux下mysql大小写区分问题
  8. 智慧的地球助力新一代数据中心建设
  9. 东华oj-进阶题第13题
  10. weka_ 聚类分析实例演练