前端根据数据生成word文档()

##项目背景#

因公司需要生成word文档,后端导出需要收费下载依赖,so由前端负责生成。

#项目依赖#

"jszip-utils": "^0.1.0",

"pizzip": "^3.1.4",

"file-saver": "^2.0.5",

"angular-expressions": "^1.2.1",

"docxtemplater": "^3.36.1",

#方法封装#

在utils文件夹下面新建createWord.js


import Docxtemplater from 'docxtemplater'
import JSZipUtils from 'jszip-utils'
import PizZip from 'pizzip'
import {saveAs} from 'file-saver'
import expressions from 'angular-expressions'
import merge from "lodash/merge"


/**
 * dataURL:base64图片
 * */
export function 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
}

/**
 * setData:word模板对应的数据
 * wordTitle:生成的word标题
 * wordPath:word模板对应的路径
 * point:Vue
 * isUrlArr:是否针对生成的图片特殊化处理
 * */
export function downloadprice(setData, wordTitle, wordPath, point,isUrlArr) {
  let _this = point;

  let ImageModule = require('docxtemplater-image-module-free')
  //1
  var last = require("lodash/last");
  var assign = require("lodash/assign");
  var docxtemplater = require('docxtemplater');
  JSZipUtils.getBinaryContent(wordPath, function (error, content) {
    if (error) {
      _this.$msgError('下载word失败,请稍候重试。。。');
      throw error;
    }
    let opts = {}
    opts.centered = false
    opts.fileType = 'docx'
    opts.getImage = function (chartId) {
      return base64DataURLToArrayBuffer(chartId)
    }
    opts.getSize = function (value, item, url) {
      if (isUrlArr && typeof isUrlArr === 'object') {
        for (const [key, size] of Object.entries(isUrlArr)) {
          if (url === key) {
            return size;
          }
        }
      }
      return [350, 350];
    };
    //角度筛选器
    var  angularParser= function(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]);
          }
          obj = assign(obj, {objIndex  : index });
          return expr(scope, obj);
        },
      };
    }
    let zip = new PizZip(content);
    // 创建并加载docxtemplater实例对象
    var doc = new docxtemplater()
      .loadZip(zip)
      .setOptions({parser:angularParser})
      .attachModule(new ImageModule(opts))
      .compile();

    doc.resolveData({...setData}).then(function () {
      doc.render();
      var out = doc.getZip().generate({
        type: "blob",
        mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      });
      //输出文档
      _this.$msgSuccess('下载成功');
      saveAs(out, wordTitle+".docx");
    })
  });
}

 注意:此项目是vue2项目,所以导出得文件路径是在public目录下面

#方法使用#

1:我使用得是延迟4s调用此方法

2:方法使用

copyValue就是你包裹的所有数据对象

这几个img都要转为base64格式

举例:availabilityUrl: [{availabilityUrl: ''}]

 createDownload() {
      this.copyValue = cloneDeep(this.reportObj)
      this.copyValue.securityIncidentImg = this.securityChartsUrl
      this.copyValue.vulnerabilityRiskImg = this.vulnerabilityRiskChartsUrl
      this.copyValue.riskAssetsChartsImg = this.riskAssetsChartsUrl
      this.copyValue.assertsContentImg = this.assertsContentUrl
      this.copyValue.assetsBarImg = this.assetsBarUrl
      this.copyValue.availabilityImg = this.availabilityUrl
      downloadprice(
        {...this.copyValue},
        this.copyValue.wordTitle,
        '/wordEyeVersionTwo.docx',
        this,
        {
          securityIncidentUrl: [630, 400],
          vulnerabilityRiskUrl: [630, 400],
          riskAssetsChartsUrl: [630, 400],
          assertsContentUrl: [630, 500],
          assetsBarUrl: [630, 400],
          availabilityUrl: [630, 400]
        }
      )
    },

3:word模板

最后左右的样式都可以在word上修改,包括颜色、字体大小、间距等等

#写在结尾#

word由前端生成资料很少,部分要实现的效果可能要借助word本身自带的功能,例如,我每一个标题下面会有一个空格,这种是因为我做判断长度的时候这个会占用一行,解决办法就是word的把这个文字隐藏掉就好了,但是这种对后期维护很不友好!还是要看产品怎么决定。最后:祝君上岸!!!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值