vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > VUE用docxtemplater导出word

VUE使用docxtemplater导出word文档实例(带图片)

作者:克劳迪尔

docxtemplate支持的功能很多,语法包含变量替换、条件判断、循环、列表循环、表格循环等,下面这篇文章主要给大家介绍了关于VUE使用docxtemplater导出word功能(带图片)的相关资料,需要的朋友可以参考下

一、docxtemplater

docxtemplater 是一种邮件合并工具,以编程方式使用并处理条件、循环,并且可以扩展以插入任何内容(表格、html、图像)。

npm 是安装 docxtemplater 最简单的方法

npm install docxtemplater pizzip --save​
// 安装 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模板文件(按自己所需最后导出的样式),放到public文件夹下

如下所示 

 (这里感觉用的语法比较全了,有其他语法可以交流一下)

注:

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

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

{name}、{user}

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

 原格式为: 

list:[
 {name:'lipipi'},
 {name:'heyaya'}
]

在模板文件中表示为: 

{#list}{name}{/} 

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

  在模板文件中表示为:

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

踩坑:图片这里我一直报错‘%imgUrl’,最后发现必须要换行写,而其他数组可以在一行写。

三、封装JS

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

/**
 * 导出word文档(带图片)
 * 
 */
import Docxtemplater from 'docxtemplater'
import PizZip from 'pizzip'
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 = Buffer.from(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;
}
export const ExportBriefDataDocx = (tempDocxPath, data, fileName, imgSize) => {
    console.log(111, tempDocxPath, data, fileName, imgSize)
    //这里要引入处理图片的插件
    var ImageModule = require('docxtemplater-image-module-free');
    var expressions = require('angular-expressions')
    var assign = require('lodash/assign')
    var last = require("lodash/last")
    expressions.filters.lower = function (input) {
        // This condition should be used to make sure that if your input is
        // undefined, your output will be undefined as well and will not
        // throw an error
        if (!input) return input
        // toLowerCase() 方法用于把字符串转换为小写。
        return input.toLowerCase()
    }
    function angularParser(tag) {
        tag = tag
            .replace(/^\.$/, 'this')
            .replace(/('|‘)/g, "'")
            .replace(/(“|”)/g, '"')
        const expr = expressions.compile(tag)
        return {
            get: function (scope, context) {
                let obj = {}
                const index = last(context.scopePathItem)
                const scopeList = context.scopeList
                const num = context.num
                for (let i = 0, len = num + 1; i < len; i++) {
                    obj = assign(obj, scopeList[i])
                }
                //word模板中使用 $index+1 创建递增序号
                obj = assign(obj, { $index: index })
                return expr(scope, obj)
            }
        }
    }
    JSZipUtils.getBinaryContent(tempDocxPath, (error, content) => {
        if (error) {
            console.log(error)
        }
        expressions.filters.size = function (input, width, height) {
            return {
                data: input,
                size: [width, height],
            };
        };
        let opts = {}
        opts = {
            //图像是否居中
            centered: true
        };
        opts.getImage = (chartId) => {
            //将base64的数据转为ArrayBuffer
            return base64DataURLToArrayBuffer(chartId);
        }
        opts.getSize = function (img, tagValue, tagName) {
            //自定义指定图像大小
            if (imgSize.hasOwnProperty(tagName)) {
                return imgSize[tagName];
            } else {
                return [200, 200];
            }
        }
        // 创建一个JSZip实例,内容为模板的内容        
        const zip = new PizZip(content)
        // 创建并加载 Docxtemplater 实例对象
        // 设置模板变量的值
		let doc = new Docxtemplater();
        doc.attachModule(new ImageModule(opts));
        doc.loadZip(zip);
        doc.setOptions({parser:angularParser});
        doc.setData(data)
        try {
            // 呈现文档,会将内部所有变量替换成值,
            doc.render()
        } catch (error) {
            const e = {
                message: error.message,
                name: error.name,
                stack: error.stack,
                properties: error.properties
            }
            console.log('err',{ error: e })
            // 当使用json记录时,此处抛出错误信息
            throw error
        }
        // 生成一个代表Docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
        const 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);
        };
    })
}

四、调用导出方法

<script>
import {exportWord,getBase64Sync} from '@/assets/js/outword.js'
export default {
  data () {
      return {		
        name:'lipipi',
        listname:'导出的模板'
		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 (){
            //多个图片遍历转base64
			for (let i in this.imglist) {
			    this.imglist[i].imgUrl = await getBase64Sync(this.imglist[i].imgUrl)
			}
			 let  data= {
				name:this.name
				imglist:this.imglist
			}
	        let imgSize = {
			//控制导出的word图片大小
	          imgurl:[200, 200],
	        };
	        exportWord("/我的模板.docx", data, `${this.listname}.docx`, imgSize);
	      }	
  }
}
</script>

总结

到此这篇关于VUE使用docxtemplater导出word文档的文章就介绍到这了,更多相关VUE用docxtemplater导出word内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文