只涉及前端,将html页面导出成word文档

用docxtemplater插件,前端实现html导出word文档(可导出文字、表格、图片)

下面我用的是vue框架,用其他框架同理,只要这个插件能兼容就行

官方文档https://docxtemplater.com/

参考地址https://www.cnblogs.com/zmh-980509/p/15480113.html

一、下载插件并引入

// 下载名字与导入名字相同,照着npm/yarn
import JSZipUtils from 'jszip-utils';
import PizZip from 'pizzip';
import docxtemplater from 'docxtemplater'; //导出word文档的插件
import { saveAs } from 'file-saver';
import ImageModule from 'docxtemplater-image-module-free'; //导出图片才需要这个插件

二、设置模板

        需要在public路径下设置一个word的标准模板文件(也可以在其它路径,后面导入正确即可),内容例如:

        需要导出的变量格式如下,其中,字体样式,如字体大小加粗等可以直接在word表中设置;图片宽高需在js里设置:

普通变量 {params}

循环 {#List} {params} {/List}

图片 {%imgUrl}

三、主要内容

        主要用到的方法,注意要点基本都在备注里面。

exportWord() {
      JSZipUtils.getBinaryContent('/docTemp/xxxxx.docx', (error, content) => {
        //'/docTemp/xxxxx.docx'为模板的地址
        const zip = new PizZip(content);
        let doc = new docxtemplater();
        doc.loadZip(zip);
        //处理图片 开始
        const opts = {};
        // opts.centered = true; // 图片居中
        opts.fileType = 'docx';
        opts.getImage = chartId => {
          return this.base64DataURLToArrayBuffer(chartId);
        };
        opts.getSize = function(byteLength, url, name) {
          // 可根据name不同分别设置图片的宽高
          //if (name == 'lastPanoUrl' || name == 'panoUrl') {
          //  return [280, 180];
          //} else if (name == 'posUrl') {
          //  return [300, 230];
          //} else {
          //  return [180, 110];
          //}
          return [200, 120];
        };
        let imageModule = new ImageModule(opts);
        doc.attachModule(imageModule);
        //处理图片 结束
      });
      //自定义导入表中的变量
      let baseInfo = {
        params: 'xxxx',
        List: [{}, {}, {}],
        imgUrl: '' //图片需为base64地址
      };
      doc.setData(baseInfo); //baseInfo为导入表中的变量,键值都可以自己定义
      try {
        doc.render();
      } catch (error) {
        const e = {
          message: error.message,
          name: error.name,
          stack: error.stack,
          properties: error.properties
        };
        throw error;
      }
      const out = doc.getZip().generate({
        type: 'blob',
        mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
      });
      saveAs(out, '无居民海岛无人机巡查简报.docx'); //导出的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;
    }

注意:图片地址需转换成base64

UrlToBase64(url, callback) {
      let image = new Image();
      //解决跨域问题
      image.setAttribute('crossOrigin', 'anonymous');
      image.src = url;
      image.onload = () => {
        var canvas = document.createElement('canvas');
        canvas.width = image.width;
        canvas.height = image.height;
        var context = canvas.getContext('2d');
        context.drawImage(image, 0, 0, image.width, image.height);
        var quality = 0.8;
        var dataURL = canvas.toDataURL('image/png', quality);
        callback && callback(dataURL); //回调函数的参数就是base64类型字符串
      };
    },

        最后,有图片的话导出比较久(因为用canvas原宽高转base64,所以导出的图片比较大),如果想优化word导出,应该还是要前后端一起配合。

有错误欢迎指正,最后更新2023.1.11

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值