2023年 4月 25日 来源: 新华社微博 字号:默认 超大

最近的项目中,需要把vue中的部分内容导出为word形式,之前没有做过这方面的,特记录,由于是初学,所以整理了此模板,注意:这是一个模板,并不是相关字段的解析,每个字段都是做什么用的,我还不太清楚,以后会慢慢添加自己的理解。

看到的很好的一篇文章,讲的很详细:vue导出word - 知乎

1. 先在项目中安装所需要的依赖包,我安装了六个

npm install file-saver
npm install docxtemplater
npm install pizzip
npm install jszip-utils
npm install angular-expressions
npm install lodash

 2. 引入核心代码文件  exportBriefDataDocx.js

在组件中引用,我将文件写在根目录下的utils中:

import { ExportBriefDataDocx } from '../utils/exportBriefDataDocx'

文件 exportBriefDataDocx.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) => {
  console.log(tempDocxPath, data, fileName, 111)
  var expressions = require('angular-expressions')
  var assign = require('lodash/assign')
  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 scopeList = context.scopeList
        const num = context.num
        for (let i = 0, len = num + 1; i < len; i++) {
          obj = assign(obj, scopeList[i])
        }
        return expr(scope, obj)
      }
    }
  }
  JSZipUtils.getBinaryContent(tempDocxPath, (error, content) => {
    if (error) {
      console.log(error)
    }
    // 创建一个JSZip实例,内容为模板的内容
    // let zip = new JSZip(content); //用PizZip替代
    const zip = new PizZip(content)
    // 创建并加载 Docxtemplater 实例对象
    const doc = new Docxtemplater(zip, { 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({ error: e })
      // 当使用json记录时,此处抛出错误信息
      throw error
    }
    // 生成一个代表Docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
    const out = doc.getZip().generate({
      type: 'blob',
      mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
    })
    // 将目标文件对象保存为目标类型的文件,并命名
    saveAs(out, fileName)
  })
}

3. 然后设计需要导出的word模版,本地新建一个文档,后缀名为.docx。我是将这个文件保存在了根目录下的public中。

我到时候要传入模板中的数据是this.docxData,所以将所有的数据都保存在this.docxData中,例如:它有三个字段:数组tableData、数字year、数字month,如下:

tableData :

tableData: [{
            date: '2016-05-02',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1518 弄'
          }, {
            date: '2016-05-04',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1517 弄'
          }, {
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }, {
            date: '2016-05-03',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1516 弄'
          }]

 docxData :

this.docxData.tableData = this.tableData
this.docxData.year = 2022
this.docxData.month = 9

 这是模板文档中的内容:

vue导出word

文档注意事项:

1)模板文件必须是docx文件。doc文件不能通过修改后缀名变为docx,必须另存时选择docx类型,才能实现类型转变。
2)使用英文下的花括号;
3)花括号内的键名前后不要有空格,且它与程序中的data对象的键名必须保持一致 ;
4)表格中想要循环添加的数据,需要在开头添加{#键名},在结尾处添加{/键名},一般对应的就是需要循环的数组名称。
5)图片居中不要使用{%%image2}

6)做判断的话,以{#键名}开头,以{/}结尾

4. 触发导出事件

methods: {
    // 导出docx
    exportDocx() {
      console.log('导出');
      this.docxData.tableData = this.tableData
      this.docxData.year = 2022
      this.docxData.month = 9
      // ExportBriefDataDocx 是我导入的一个文件,里边写的是导出文本的核心代码
      ExportBriefDataDocx('模板文件', 要传入模板的数据, '文档名字.docx')
      // ExportBriefDataDocx('/text.docx', this.docxData, '文档导出.docx') // text.docx放在了根目录下的public文件夹下
    }
  }

效果图:

vue导出word

附上完整的组件部分的代码:

ExportDocx.vue:

<template>
  <div class="docx">
    <el-button @click="exportDocx">导出</el-button>
    <h2>{{2022}}年{{9}}月</h2>
    <el-table
        :data="tableData"
        border
        style="width: 100%">
      <el-table-column
          prop="date"
          label="日期"
          width="180">
      </el-table-column>
      <el-table-column
          prop="name"
          label="姓名"
          width="180">
      </el-table-column>
      <el-table-column
          prop="address"
          label="地址">
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
import { ExportBriefDataDocx } from '../utils/exportBriefDataDocx'
export default {
  name: "Docx",
  data() {
    return {
      tableData: [{
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄'
      }, {
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 弄'
      }, {
        date: '2016-05-01',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1519 弄'
      }, {
        date: '2016-05-03',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1516 弄'
      }],
      docxData:{}
    }
  },
  methods: {
    // 导出docx
    exportDocx() {
      console.log('导出');
      this.docxData.tableData = this.tableData
      this.docxData.year = 2022
      this.docxData.month = 9
      ExportBriefDataDocx('/text.docx', this.docxData, '文档导出.docx')
    }
  },
}
</script>
<style scoped>
</style>