1

项目需求:前端层面实现导出word功能
项目准备:

  • vue脚手架项目(vue-cli4)
  • 插件:docxtemplater pizzip jszip jszip-utils file-saver
1.安装依赖:
npm install  docxtemplater pizzip --save  // 处理docx模板
npm install  jszip-utils --save
npm install  jszip@2.6.1 --save   
npm install  file-saver --save  // 处理输出文件
  • 坑1:执行npm install jszip --save 会下载最新版本导致报错,必须指定版本号,亲测2.6.1版本可行
    image.png
2.创建word模板:public/test.docx
  • vuecli3/vuecli4在public文件下存放word模板test.docx;vuecli2在static文件下存放word模板test.docx;
    image.png
  • word模板示例:image.png
  • 坑2:如果直接在代码编辑器内通过新建文件的方式创建test.docx后面会报错,应该和文件编码格式有关,所以需要进入项目文件夹内右键新建docx文件,test.docx内编辑后编辑器内可以看到pulic文件下多了一个~$test.docx文件;出现这个文件夹基本就okay了
3.封装导出word组件:src/components/export2word.vue
<template>
  <div>
    <div class="word-box" @click="exportWord">word</div>
  </div>
</template>

<script>
import Docxtemplater from 'docxtemplater';
import JSZip from 'jszip';
import JSZipUtils from 'jszip-utils';
import { saveAs } from 'file-saver';

export default {
  name: 'Docx',
  props: {
    fileName: {
      type: String,   // 输出文件名
      default: ''
    },
    fileTemplete: {
      type: String,  // public下存放的word模板名称
      default: ''
    },
    exportData: {
      type: Object,  // 导出的word数据
      default: () => { }
    }
  },
  methods: {
    // 点击导出word
    exportWord() {
      
      // 读取并获得模板文件的二进制内容
      JSZipUtils.getBinaryContent(this.fileTemplete + '.docx', (error, content) => {
        // 抛出异常
        if (error) throw error;
        // 创建一个JSZip实例,内容为模板的内容
        let zip = new JSZip(content);
        // 创建并加载docxtemplater实例对象
        let doc = new Docxtemplater();
        doc.loadZip(zip);
        // 设置模板变量的值
        doc.setData({
          ...this.exportData
        });
        try {
          // 用模板变量的值替换所有模板变量
          doc.render();
        } catch (error) {
          // 抛出异常
          let e = {
            message: error.message,
            name: error.name,
            stack: error.stack,
            properties: error.properties
          };
          console.log(JSON.stringify({ error: e }));
          throw error;
        }
        // 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
        let out = doc.getZip().generate({
          type: 'blob',
          mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
        });
        // 将目标文件对象保存为目标类型的文件,并命名
        saveAs(out, this.fileName + '.docx');
      });
    },
  },
}
</script>
4.页面使用word组件:src/views/page.vue
<template>
  <div class="page">
    <Download
      class="download"
      :fileName="fileName"
      :fileTemplete="fileTemplete"
      :exportData="exportData"
    />
  </div>
</template>

<script>
import Download from '@/components/export2word.vue';

export default {
  data() {
    return {
      fileName: '2021年度销售业绩报告',
      fileTemplete: 'test',
      exportData: {
        "code": "value",
        "data": {
          "dataArr0": {
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
          },
          "dataArr1": {
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
          },
          "dataArr2": {
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
          },
          "dataArr3": {
            "obj1": {
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            },
            "obj2": {
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            },
            "obj3": {
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            },
             "key2": "value2",
             "key3": "value3",
          },
          "dataArr4": [
            {
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            },
            {
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            },
            {
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            },
            {
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            },
            {
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            }
          ],
          "dataArr5": {
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
            "key1": "value1",
          }
        }
      },
    }
  },
  components: {
    Download,
  },
}
</script>

<style>
.page {
  box-sizing: border-box;
  width: 100%;
  height: 100vh;
  user-select: none;
}
.page .download {
  border: 1px solid #000;
  padding: 5px 10px;
  height: 50px;
  margin-left: 100px;
  cursor: pointer;
}
</style>
5.填充word模板数据:
  • 填充数据根据渲染数据的结构而定,这里提供了数组和对象数据结构

    解析变量:{变量名}
    循环:
    {#数组名}
     {元素名1}{元素名2}....
    {/数组名}
    条件:
    {#条件}
     {变量}
    {/条件}
  • 坑3:注意使用JS对象点语法是访问不到变量的,对象格式数据访问{#父对象名}{子属性}{/父对象名}
  • 坑4:表格中loop必须在表格内开始 表格内结束
    image.png

结论

好好啃官网,就是看起来好烦,附上官网供你们继续烦:https://docxtemplater.com/doc...


guyu
9 声望0 粉丝

不要着急,不要着急,学习,学习一下