likes
comments
collection
share

每日小记 —— 利用docxtemplater插件将页面表格导出word文档

作者站长头像
站长
· 阅读数 44

前言

周一早上刚来上班,"可爱"的产品经理就给我整个需求,让我一个上午把上星期做的表格(包含数据)在不借助后端的情况下,纯前端导出word,后来在网上一顿搜索找到了适配需求的插件-docxtemplater,首先声明一下:我这个项目是vue3,react的暂时没试过,下面简单介绍下使用方法。

安装插件

1、npm i docxtemplater
2、npm i docxtemplater-image-module-free(如果你需要的话,这是在文件中处理图片用的)
3、npm i pizzip
4、npm i file-saver(ts需要这样安装,npm i @types/file-saver)

封装组件

这里我把组件放在utils文件夹下,新增outword.js文件方便管理,下面是完整代码

import Docxtemplater from 'docxtemplater'
import PizZip from 'pizzip'
import JSZipUtils from 'jszip-utils'
import { saveAs } from 'file-saver'

export const ExportBriefDataDocx = (tempDocxPath, data, fileName, imgSize) => {
  console.log(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) {
    if (!input) return input
    return input.toLowerCase() // 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])
        }
        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)
  })
}

文档模板编写

这里有个比较坑的问题,就是你得把你生成的word文档做个模板出来,这里我是这样弄的

每日小记 —— 利用docxtemplater插件将页面表格导出word文档

我这里是个IOT的项目,具体的术语忽略,直接看重要的信息;

其中{shanMen},{duXieQi},{piaoXiang},{jianKangDu}这个四个数据我用{xxxx}这样的模板来表示,具体为啥这样来写,因为插件官网就是这么说的;

实际应用

主要工作都弄好了,下面就很简单了;

引入插件

import { ExportBriefDataDocx } from '@/utils/outword'

具体使用

// ExportBriefDataDocx('引用刚才我们写好的word文档', '你要展示的数据', '导出文件的名称')

注意!!!

还记得刚才我们写的模板中的内容么{shanMen},{duXieQi},{piaoXiang},{jianKangDu},所以传进去的数据格式,属性名称必须和模板中的名称相同。

所以这里的数据格式应该是:

const exportData = {
    shanMen: '否',
    duXieQi: '否',
    piaoXiang: '是',
    jianKangDu: '88',
}

// ExportBriefDataDocx('刚才写的模板的地址', '需要展示的数据', '导出报告的名称')

function exportReport() {
  ExportBriefDataDocx('/export-template/评估报告.docx', exportData, `评估报告.docx`)
}

结果

每日小记 —— 利用docxtemplater插件将页面表格导出word文档

我们可以看到数据已经上来了。

如果你想把数据做成动态,那就和后端做一下交互就好了。

后记

这里参考了一篇文章,还有docxtemplater官网,链接如下

docxtemplater官网:docxtemplater.com/

参考文档:blog.csdn.net/caizitjl/ar…

转载自:https://juejin.cn/post/7235898992293478461
评论
请登录