vue 根据word摸板导出word文档,并压缩为zip

yarn add [email protected]

yarn add [email protected]

yarn add [email protected]

yarn add [email protected]

yarn add [email protected]

yarn add [email protected]

 注意:这里的fileUrl必须是绝对路径,否则可能会报 is not zip的错误,请大家注意。

import ImageModule from 'docxtemplater-image-module-free'
import JSZipUtils from 'jszip-utils'
import Docxtemplater from 'docxtemplater'
import PizZip from 'pizzip'


export const exportDocx = (fileUrl, data) => {
  return new Promise((resolve) => {
    // 读取并获得模板文件的二进制内容
    
    JSZipUtils.getBinaryContent(fileUrl, (error, content) => {
      // 创建一个PizZip实例,内容为模板的内容
      if (error) {
        throw error // 错误处理
      }
      const imageOpts = {
        getImage: async function (tagValue, tagName) {
            // 这里尝试了很多次,需要将图片链接转为ArrayBuffer,字节数组的形式。
          const res = await URLToArrayBuffer(tagValue)
          return res
        },
        getSize: function (img, tagValue, tagName) {
          return [120, 180]
        },
      }

      const imageModule = new ImageModule(imageOpts)

      let zip = new PizZip(content)
      // 创建并加载docxtemplater实例对象
      let doc = new Docxtemplater()
      doc.attachModule(imageModule)
      doc.loadZip(zip)
      doc.setOptions({ paragraphLoop: true, linebreaks: false })
      doc.compile()
      // 设置模板变量的值

      doc.renderAsync({ ...data }).then(() => {
        // 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
        let out = doc.getZip().generate({
          type: 'blob',
          mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        })

        resolve({ out, data })

      })
    })
  })
}

这里将url地址转ArrayBuffer的方法有很多。我看网上很多都是先将转为base64然后转为ArrayBuffer。我没有按这种方式,我是发送了一次请求,响应类型为arraybuffer。

function URLToArrayBuffer(url) {
  return new Promise((resolve) => {
    const xhr = new XMLHttpRequest()
    xhr.open('GET', url, true)
    xhr.responseType = 'arraybuffer'

    xhr.onload = function () {
      if (xhr.status === 200) {
        resolve(xhr.response)
      }
    }

    xhr.send()
  })
}

然后就是批量导出word文档

我这里写一个demo
这是一个点击事件。

const arr = new Array(10);
const data = {}  // 渲染摸板需要的数据

const exportWord=()=>{
   const res = arr.map(async(item)=>{
        return await exportDocx('/word.docx',data);
    })
    // 这里会拿到10个 Promise对象,内容是是exportDocx 返回的Blob对象。
        const zip = new JSZip() //创建压缩对象

    res.forEach(async(ee,index)=>{
        const e = await ee
// 将文件存到zip中
        zip.file('word.docx',e.out, { base64: true,
          compression: 'DEFLATE', // STORE:默认不压缩 DEFLATE:需要压缩
          compressionOptions: {
            level: 9, // 压缩等级1~9    1压缩速度最快,9最优压缩方式
          },
        })
    })
    
// 等待res中的Promise状态都完成才执行。
    Promise.all(res).then(() => {
      console.log('zip', zip)
      zip
        .generateAsync({
          type: 'blob',
        })
        .then((content) => {
          FileSaver.saveAs(content, '详情.zip')
          this.load = false
        })
        .finally(() => {})
    })

}

word文档摸板如下: 比较特殊的就是在处理图片时。

{#url0}{%url0}{/url0} 这类似if条件语句。

#table需要table的格式为  table:[{url0:'123',url1:'123',...},{}]

vue 根据word摸板导出word文档,并压缩为zip_第1张图片

 大概就这些了,有什么问题私信哦

你可能感兴趣的:(vue.js,javascript,ecmascript)