前端vue以模板方式导出word----依赖 docxtemplater

摘要:
您需要从页面的表中导出一个word文件,vue2.0将该文件放在静态目录中。3.导入插件并定义导出函数importdocxtemplterfrom'docxtemplater'importJSZipUtilsfrom'jszip-utils'Import{saveAs}from'file-saver'importJSZipfrom'jszip'exportWord:

原理:需要将页面中table导出一个word文件,在本地做好一个word模板,定义好变量,以这个模板文件为导出依赖,将后台获取的变量添加进去。

需求:将“伦理审查批件”导出为word

前端vue以模板方式导出word----依赖 docxtemplater第1张

导出word和pdf对实际工作的影响:

  上一篇博客实现了前端导出pdf,但是后来发现,当意见内容特别多的时候,pdf分页会有点问题:

  前端vue以模板方式导出word----依赖 docxtemplater第2张

  而word会自动处理这种情况:

  前端vue以模板方式导出word----依赖 docxtemplater第3张

  综上,如果确定导出文件的高度在一页内能搞定,那么用pdf会更简单点,需要多页的话还是用word更适合使用需求。

  导出pdf的原理是 html2canvas 对页面进行截图,再用 jspdf 将截图转为 pdf,所以这种做法一定会导致多页的时候出现上述问题,但是现在好像vue导出pdf大多数使用的都是这个方法,以后有时间再研究下其他的方法可以导出好看点的pdf。

操作步骤:

1、下载插件

  npm i docxtemplater jszip-utils file-saver jszip@2.6.1

  注意:jszip的版本是2.6.1,最新版的可能有问题,或者安装 pizzip 替代 jszip

2、定义word模板:vue3.0将该文件放在public目录下,vue2.0将该文件放在static目录下
前端vue以模板方式导出word----依赖 docxtemplater第4张

3、引入插件和定义导出函数

import docxtemplater from 'docxtemplater'
import JSZipUtils from 'jszip-utils'
import { saveAs } from 'file-saver'
import JSZip from 'jszip'
    exportWord: function() {
      let _this = this
      // 读取并获得模板文件的二进制内容
      JSZipUtils.getBinaryContent('approvalNo.docx', function(error, content) {
        if (error) throw error // 抛出异常
        let zip = new JSZip(content) // 创建一个JSZip实例,内容为模板的内容
        let doc = new docxtemplater().loadZip(zip) // 创建并加载docxtemplater实例对象
        doc.setData({ ..._this.approvalNoOrOpinionNoList }) // 设置模板变量的值
        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, 'aaa.docx')
      })
    }

  注意:引入路径和传入到模板中的参数

前端vue以模板方式导出word----依赖 docxtemplater第5张

4、定义按钮点击导出,实际导出效果:

前端vue以模板方式导出word----依赖 docxtemplater第6张

报错:

第一种:

Uncaught Error: Error: Can't find end of central directory : is this a zip file ? If it is, see http://stuk.github.io/jszip/documentation/howto/read_zip.html
    at XMLHttpRequest.xhr.onreadystatechange

前端vue以模板方式导出word----依赖 docxtemplater第7张

翻译:

未捕获的错误:错误:无法找到结束的中央目录:这是一个zip文件吗?如果是,请查看http://stuk.github.io/jszip/documentation/howto/read_zip.html

在XMLHttpRequest.xhr.onreadystatechange

解释:················意思是说你路径写错了

第二种:

Uncaught Error: InternalError: The filetype for this file could not be identified, is this file corrupted ?
    at XMLHttpRequest.xhr.onreadystatechange

前端vue以模板方式导出word----依赖 docxtemplater第8张

翻译:

无法识别此文件的文件类型,此文件是否已损坏?

在XMLHttpRequest.xhr.onreadystatechange

解释:················意思是说后缀名doc会有可能出问题,换成docx试试

页面完整代码:

前端vue以模板方式导出word----依赖 docxtemplater第9张前端vue以模板方式导出word----依赖 docxtemplater第10张
<template>
  <div class="approvalNo-or-opinionNo-list">
    <el-button type="primary" size="small" @click="exportWord">点击下载</el-button>
    <div id="pdfDom">
      <table cellspacing="0">
        <caption>
          伦理审查批件
        </caption>
        <tr>
          <td class="key-name">批件号</td>
          <td colspan="3">{{ approvalNoOrOpinionNoList.approvalNo }}</td>
        </tr>
        <tr>
          <td class="key-name">项目名称</td>
          <td colspan="3">{{ approvalNoOrOpinionNoList.projectName }}</td>
        </tr>
        <tr>
          <td class="key-name">项目来源</td>
          <td colspan="3">{{ approvalNoOrOpinionNoList.sponsorName }}</td>
        </tr>
        <tr>
          <td class="key-name">研究单位</td>
          <td colspan="3">{{ approvalNoOrOpinionNoList.researchUnit }}</td>
        </tr>
        <tr>
          <td class="key-name">主要研究者</td>
          <td colspan="3">{{ approvalNoOrOpinionNoList.personName }}</td>
        </tr>
        <tr>
          <td class="key-name">审查类别</td>
          <td>{{ approvalNoOrOpinionNoList.taskStyle }}</td>
          <td class="key-name">审查方式</td>
          <td>{{ approvalNoOrOpinionNoList.taskType }}</td>
        </tr>
        <tr>
          <td class="key-name">审查日期</td>
          <td>{{ approvalNoOrOpinionNoList.auditDate }}</td>
          <td class="key-name">审查地点</td>
          <td>{{ approvalNoOrOpinionNoList.auditAddress }}</td>
        </tr>
        <tr>
          <td class="key-name">审查委员</td>
          <td colspan="3">{{ approvalNoOrOpinionNoList.auditCommittees }}</td>
        </tr>
        <tr>
          <td class="key-name">批准文件</td>
          <td colspan="3">见附件</td>
        </tr>
        <tr>
          <td colspan="4" class="options">
            {{ approvalNoOrOpinionNoList.auditRemark }}
          </td>
        </tr>
        <tr>
          <td class="key-name">年度/定期<br />跟踪审查频率</td>
          <td colspan="3">{{ approvalNoOrOpinionNoList.frequency }}</td>
        </tr>
        <tr>
          <td class="key-name">有效期</td>
          <td colspan="3">{{ approvalNoOrOpinionNoList.effectiveStartDate }} 至 {{ approvalNoOrOpinionNoList.effectiveEndDate }}</td>
        </tr>
        <tr>
          <td class="key-name">联系人与联系电话</td>
          <td colspan="3">{{ approvalNoOrOpinionNoList.sponsorContacts }} {{ approvalNoOrOpinionNoList.sponsorTel }}</td>
        </tr>
        <tr>
          <td class="key-name">伦理委员会</td>
          <td colspan="3">{{ approvalNoOrOpinionNoList.ethicsCommittee }}</td>
        </tr>
        <tr>
          <td class="key-name">主任签名</td>
          <td colspan="3">{{ approvalNoOrOpinionNoList.directorAutograph }}</td>
        </tr>
        <tr>
          <td class="key-name">日期</td>
          <td colspan="3">{{ approvalNoOrOpinionNoList.todayDate }}</td>
        </tr>
      </table>
    </div>
  </div>
</template>
<script>
import docxtemplater from 'docxtemplater'
import JSZipUtils from 'jszip-utils'
import { saveAs } from 'file-saver'
import JSZip from 'jszip'
export default {
  data() {
    return {}
  },
  props: {
    approvalNoOrOpinionNoList: {
      type: Object,
      default: {}
    }
  },
  methods: {
    exportWord: function() {
      let _this = this
      // 读取并获得模板文件的二进制内容
      JSZipUtils.getBinaryContent('approvalNo.docx', function(error, content) {
        if (error) throw error // 抛出异常
        let zip = new JSZip(content) // 创建一个JSZip实例,内容为模板的内容
        let doc = new docxtemplater().loadZip(zip) // 创建并加载docxtemplater实例对象
        doc.setData({ ..._this.approvalNoOrOpinionNoList }) // 设置模板变量的值
        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, 'aaa.docx')
      })
    }
  }
}
</script>
<style lang="scss">
.approvalNo-or-opinionNo-list {
  height: 350px;
  overflow-y: auto;
  padding-bottom: 20px;
  border-bottom: 1px solid #ccc;
  > #pdfDom {
    table {
      text-align: center;
      border-bottom: 1px solid #ccc;
       93%;
      margin: 0 auto;
      font-family: '楷体', '楷体_GB2312';
      caption {
        font-size: 16px;
        text-align: center;
        line-height: 46px;
        color: #333;
        font-weight: bold;
      }
      td {
         25%;
        height: 32px;
        color: #666;
        border-left: 1px solid #ccc;
        border-top: 1px solid #ccc;
        padding: 0 6px;
      }
      td:last-child {
        border-right: 1px solid #ccc;
      }
      .key-name {
        color: #333;
        font-weight: 600;
      }
      .options {
        padding: 10px;
        text-align: justify;
        text-indent: 2em;
      }
    }
  }
}
</style>
View Code
前端vue以数据流方式导出word----借助 jquery

免责声明:文章转载自《前端vue以模板方式导出word----依赖 docxtemplater》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇goto的用法WIN APIVFP获取第三方窗体的控件信息(句柄,窗口ID,进程ID,类名,标题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

实现Windows和Linux之间的文件共享

一、windows 向linux共享文件(这里都是以win10和ubuntu为例) 首先,打开网络共享中心。如图1 图1 打开更改高级共享设置(图2) 图 2 选择启用网络发现以及启用文件和打印机共享,然后点击保存更改。 接着,选择你要共享的文件夹,右键选择属性,然后选择共享,选择高级共享,选择权限,分别如图3,图4,图5所示: 图 3 图 4...

eAccelerator 配置参数详解

eAccelerator配置参数如下: [eaccelerator]extension=eaccelerator.soeaccelerator.shm_size="64"eaccelerator.cache_dir="/tmp/eaccelerator"eaccelerator.enable="1"eaccelerator.optimizer="1"eacc...

清除页面广告?身为前端,自己做一款简易的chrome扩展吧

大家肯定有这样的经历,浏览网页的时候,左右两端广告,诸如“屠龙宝刀,点击就送”,以及最近火的不行的林子聪37传奇霸业什么“霸业面具,霸业吊坠”的魔性广告总是充斥我们的眼球。 当然有现成的扩展程序或者插件(两者概念稍有不同)可以清除页面广告,但是既然身为一名程序猿,尤其是FEDer,为什么不尝试一下自己写一个清除广告的扩展程序呢。其实,编写一个浏览器扩展程序...

mac 版本navicate 如何安装破解版

https://www.jianshu.com/p/f42785e55b6b  博客地址 部分童鞋安装后没有rpk文件,我也不知道怎么解决实在不行,请下载破解版链接:https://pan.baidu.com/s/1oyatsIdn-_oD4JW3_RTqpg  密码:4cbi 教程原链接 如有版权问题,请联系我立即删除 Mac版 Navicat Pr...

安装系统时出现 Windows无法打开所需的文件 C:Sourcesinstall.wim 的解决办法

  使用U盘安装Win10的时候,出现 Windows无法打开所需的文件 C:Sourcesinstall.wim,错误代码:0x8007000D,这是由于启动盘里 install.wim 文件不正确造成的。 新Win10 镜像文件一般都大于4G,镜像中Sources文件夹下面的 install.wim 单个文件就超过了4G, 它是安装系统的主程序文件,制...

golang 热更新技巧 负载均衡才是正道啊

golang plugin热更新尝试 - 呵大官人的鱼塘 - 开源中国 https://my.oschina.net/scgywx/blog/1796358 golang plugin热更新尝试  发布于 04/16 17:47 当我们在使用php开发的时候,基本不需要关心热更新这件事的,因为PHP本身已经帮我处理好了,只需要提交代码,PHP重新解释一遍...