纯小白一步步填坑去学vue怎么导出Word

因为公司做的是阅卷系统,最近要开发一个新功能,老板说的是可以导出一本像书似的可打印的PDF,因为成绩报表里面都是学生成绩的分析图也就是echarts还有各种表格,无法确定其长度,多以导出PDF最终到了成功导出但我的echarts都被拦腰切断这步不了了之,实在是做不出来,最后考虑到老师下载后还要编辑,采取了导出Word的形式,不多废话,一步步开始。

导入安装包

第一步当然是下载导入包啦,需要下载如下的几个安装包:

	// 下载
	npm install docxtemplater pizzip  --save
	npm install jszip-utils --save 
	npm install jszip --save
	npm install file-saver --save
	//在需要导出Word的vue文件导入
	import JSZipUtils from 'jszip-utils'import docxtemplater from 'docxtemplater'import { saveAs } from 'file-saver'import PizZip from 'pizzip'

创建模板

在本地创建一个docx也就是Word文档,放入我们的项目中,我用的是脚手架2,所以放在static下,百度说用3的话需要放在public下,然后我们编写需要的Word底层的模板。其实语法在docxtemplater 官网写的非常的清楚还明白(其实我第一次去官网看,都不知道去哪儿看语法规则,害)这里是官网的地址可以参考(https://docxtemplater.readthedocs.io/en/latest/)去例子那里看就非常清楚。下面我简单介绍几个常用的注意的:
Word截图
vue-data截图

这张图是我简单写的一个例子,因为命名过多,我就胡乱用拼音代替了,哈哈
要想成功输出数据,需要有数组包裹 {#字段名}开始 {/字段名}结束,但凡数据是存在数组中的 就必须用数组名称给包裹起来,否则就会输出undefined,图片的话我用的是base64格式,输出需要用{%字段名}这样写{%%字段名}这样是使图片居中。因为我的数据中存在大量的echarts图表,图片的问题稍后说,回到文本内容上,要是有表格输出的话,我们需要在Word中自己建立表格,然后拿出数据去渲染。大家可以对比我的Word还有我的data数据就能明白。

echart图片处理

echart
因为我的报表中几乎都是echarts,所以输出到Word中是以图片形式的,我们先用echarts自带的功能getDataURL()会直接得到base64的图片格式,这是代码:

var that = this;
var img = new Image();
img.src = myline.getDataURL({
    pixelRatio: 2,// 导出的图片分辨率比例,默认为 1。
    backgroundColor: '#fff'// 导出的图片背景色,默认使用 option 里的 backgroundColor
});
that.wordData.fenduanList.fdUrl= img.src;
//wordData是包裹全部要输出的在Word文档中的最外层的数组名称

给图片赋值的时候一定要记住是=img.src,这里我最开始做的时候以为=img就OK了 但怎么也导不出来 最后才想通要的是地址而不是个图片。
除了echarts自带的方法,我最开始导出PDF时还接触到一个 叫做html2Canvas的插件,这个主要是把vue前端页面转化为base64格式的图片,即所见即所得,因为我的项目存在大量的echart图表而且很多都是我循环出来的,所以用上面的办法没有找到办法循环得到base64图片,所以采用这种插件,如下是代码:

import html2Canvas from 'html2canvas';//下载并导入包
getCanvas(){
	//this.$refs.ss 就是标记我图片的大框div区域
    for(let j = 0 ; j <this.$refs.ss.length;j++){
         html2Canvas(this.$refs.ss[j],{
             allowTaint: false,//允许 canvas 污染
             useCORS: true, //允许图片跨域
         }).then((canvas)=>{
              this.sydArr.push(canvas.toDataURL('image/png', 1.0));
              //这里得到的就是一个循环出来的base64图片数组
         }); 
     }
 },

这里是打印出来的循环数组的样式
在这里插入图片描述
然后最后一步就是导出Word了

导出Word

上代码:

		//这里是官网写的应该是处理图片的代码,照着写就行,没动过
       base64DataURLToArrayBuffer(dataURL) {
            const base64Regex = /^data:image\/(png|jpg|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
        exportWord() {
        	//这里要引入处理图片的插件,下载docxtemplater后,引入的就在其中了
            var ImageModule = require('docxtemplater-image-module-free');
            var that = this;
            //这里是我的Word路径,在static文件下
            JSZipUtils.getBinaryContent("../../static/word.docx", function (error, content) {
                if (error) {
                    throw error
                };
                let opts = {}
                opts.centered = true;  
                opts.fileType = "docx";
                opts.getImage = (tag)=> {
                    return that.base64DataURLToArrayBuffer(tag);
                }
                opts.getSize = ()=>{
                    return [600, 400]//这里可更改输出的图片宽和高
                }
                let zip = new PizZip(content);
                let doc = new docxtemplater();
                doc.attachModule(new ImageModule(opts));
                doc.loadZip(zip);
                doc.setData({
                    ...that.wordData//我的最外层包裹一切要导出的数据名称
                });
                try {
                    doc.render()
                } catch (error) {
                    var e = {
                        message: error.message,
                        name: error.name,
                        stack: error.stack,
                        properties: error.properties,
                    }
                    console.log(JSON.stringify({
                        error: e
                    }));
                    throw error;
                }
                var out = doc.getZip().generate({
                    type: "blob",
                    mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                })
                    saveAs(out, "成绩报表.docx")
            })
        },

然后就没有然后了,成功导出,这是我的样例:
导出Word
封面,页码,页眉页脚,目录的话也可以自己直接在Word模板中填好,导出时就会自动生成了,但目录的功能虽然可实现,但不能动态的刷新成新目录,目前只能导出后用户自己更新目录,这点让我很困扰,如果有解决的办法,欢迎告知。奥,对了如果总报如下的错误,就去看看自己的Word模板上的标签名包没包住,尽量的对齐书写标签名称。
在这里插入图片描述

这是我的第一篇博客,很是激动,来自一个毕业一年,工作一年但觉得自己就是废物的不能说胖仙女程序猿,哈哈哈。

Logo

前往低代码交流专区

更多推荐