一、所需依赖
npm install docxtemplater pizzip --save
-- 安装 jszip-utils
npm install jszip-utils --save
-- 安装 jszip
npm install jszip --save
-- 安装 FileSaver
npm install file-saver --save
-- 安装处理图片的插件
npm install docxtemplater-image-module-free --save
二、准备一个word模板,放在vue项目的public下
如需展示图片,在模板中这样写即可:{#item_li}{%imgUrl}{/item_li}
三、代码部分
downloadWithTemplate(path, data, fileName) {
// 这里要引入处理图片的插件
var ImageModule = require('docxtemplater-image-module-free')
// 读取并获得模板文件的二进制内容
JSZipUtils.getBinaryContent(path, (error, content) => {
if (error) throw error
// 图片处理
var opts = {}
opts = {
// 图像是否居中
centered: false
}
// opts.centered = true // 图片居中,在word模板中定义方式为{%%image}
// opts.fileType = 'docx'
opts.getImage = chartId => {
// 将base64的数据转为ArrayBuffer
return this.base64DataURLToArrayBuffer(chartId)
}
opts.getSize = function() {
return [600, 300]
}
const imageModule = new ImageModule(opts)
// 创建一个PizZip实例,内容为模板的内容
const zip = new PizZip(content)
// 创建并加载docxtemplater实例对象
const doc = new Docxtemplater()
doc.attachModule(imageModule)
doc.loadZip(zip)
doc.setData({
...data
})
try {
// 用模板变量的值替换所有模板变量
doc.render()
} catch (error) {
const e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties
}
this.$message.error('文件格式有误!')
throw error
}
// 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
const out = doc.getZip().generate({
type: 'blob',
mimeType:
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
})
// 将目标文件对象保存为目标类型的文件,并命名
saveAs(out, fileName + '.docx')
})
},
/**
* 将base64格式的数据转为ArrayBuffer
* @param {Object} dataURL base64格式的数据
*/
base64DataURLToArrayBuffer(dataURL) {
const base64Regex = /^data:image\/(png|jpg|svg|svg\+xml);base64,/
if (!base64Regex.test(dataURL)) {
return false
}
const stringBase64 = dataURL.replace(base64Regex, '')
let binaryString
if (typeof window !== 'undefined') {
binaryString = window.atob(stringBase64)
} else {
binaryString = new Buffer(stringBase64, 'base64').toString('binary')
}
const len = binaryString.length
const bytes = new Uint8Array(len)
for (let i = 0; i < len; i++) {
const ascii = binaryString.charCodeAt(i)
bytes[i] = ascii
}
return bytes.buffer
},
getBase64Sync(imgUrl) {
return new Promise(function(resolve, reject) {
// 一定要设置,不然图片不显示
const image = new Image()
// 解决跨域问题
image.setAttribute('crossOrigin', '*') // 解决跨域
image.crossOrigin = 'Anonymous'
// 图片地址
image.src = imgUrl
// image.onload为异步加载
image.onload = function() {
const canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
const context = canvas.getContext('2d')
context.drawImage(image, 0, 0, image.width, image.height)
// 图片后缀名
const ext = image.src.substring(image.src.lastIndexOf('.') + 1).toLowerCase()
// 图片质量
const quality = 0.8
// 转成base64
const dataurl = canvas.toDataURL('image/' + ext, quality)
// 返回
resolve(dataurl)
}
})
}
导出按钮
<el-button type="warning" icon="el-icon-download" @click="export">Export Report</el-button>
data: {
name: 'test',
item_li: [
{ index: 1, title: 'item1', status: '<w:p><w:r><w:rPr><w:b/><w:sz w:val="21"/><w:color w:val=\"ef4646\"/></w:rPr><w:t>status1</w:t></w:r></w:p>' },
{ index: 2, title: 'item2', status: '<w:p><w:r><w:rPr><w:b/><w:sz w:val="21"/><w:color w:val=\"57a957\"/></w:rPr><w:t>status2</w:t></w:r></w:p>' },
{ index: 3, title: 'item3', status: '<w:p><w:r><w:rPr><w:b/><w:sz w:val="21"/><w:color w:val=\"FFF1CD\"/></w:rPr><w:t>status3</w:t></w:r></w:p>' }
]
},
nowdate: '',
mounted() {
this.nowdate = this.dateFormat()
// this.getData()
},
export() {
const newdata = {
...this.data,
nowdate: this.nowdate
}
const filename = this.data.name + '_' + this.nowdate + '_report'
this.downloadWithTemplate('data.docx', newdata, filename)
}
// 当前日期格式化
dateFormat() {
var date = new Date()
var year = date.getFullYear()
var month = date.getMonth() + 1 < 10
? '0' + (date.getMonth() + 1) : date.getMonth() + 1
var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
// var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
// var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
// var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
return year + '-' + month + '-' + day
}