VUE使用docxtemplater導出word文檔實例(帶圖片)
一、docxtemplater
docxtemplater 是一種郵件合并工具,以編程方式使用并處理條件、循環(huán),并且可以擴展以插入任何內(nèi)容(表格、html、圖像)。
npm 是安裝 docxtemplater 最簡單的方法
npm install docxtemplater pizzip --save?
// 安裝 docxtemplater npm install docxtemplater pizzip --save // 安裝 jszip-utils npm install jszip-utils --save // 安裝 jszip npm install jszip --save // 安裝 FileSaver npm install file-saver --save // 引入處理圖片的插件1 npm install docxtemplater-image-module-free --save // 引入處理圖片的插件2 npm install angular-expressions --save
二、在導出word前,需要準備一個word模板文件(按自己所需最后導出的樣式),放到public文件夾下
如下所示

(這里感覺用的語法比較全了,有其他語法可以交流一下)
注:
需要填寫的部分都被定義為變量或者json對象數(shù)組,具體格式如下:
1. 單一變量使用 { } 包含,例如:
{name}、{user}2. json數(shù)組格式,則包裹一個循環(huán)對象,例如:
原格式為:
list:[
{name:'lipipi'},
{name:'heyaya'}
]在模板文件中表示為:
{#list}{name}{/}
如果對象是圖片地址時,需要在對象前加上% ,例如:
在模板文件中表示為:
{#imglist}
{%imgUrl}
{/imglist}
踩坑:圖片這里我一直報錯‘%imgUrl’,最后發(fā)現(xiàn)必須要換行寫,而其他數(shù)組可以在一行寫。
三、封裝JS
這部分主要是實現(xiàn)word文檔導出含圖片的主要實現(xiàn)方法,包括將圖片的url路徑轉(zhuǎn)為base64路徑、base64轉(zhuǎn)二進制、以及導出圖片的處理,可以直接復制粘貼在頁面引入使用,具體代碼如下:
/**
* 導出word文檔(帶圖片)
*
*/
import Docxtemplater from 'docxtemplater'
import PizZip from 'pizzip'
import JSZipUtils from 'jszip-utils'
import { saveAs } from 'file-saver'
/**
* 將base64格式的數(shù)據(jù)轉(zhuǎn)為ArrayBuffer
* @param {Object} dataURL base64格式的數(shù)據(jù)
*/
function base64DataURLToArrayBuffer(dataURL) {
const base64Regex = /^data:image\/(png|jpg|jpeg|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 = Buffer.from(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;
}
export const ExportBriefDataDocx = (tempDocxPath, data, fileName, imgSize) => {
console.log(111, tempDocxPath, data, fileName, imgSize)
//這里要引入處理圖片的插件
var ImageModule = require('docxtemplater-image-module-free');
var expressions = require('angular-expressions')
var assign = require('lodash/assign')
var last = require("lodash/last")
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() 方法用于把字符串轉(zhuǎn)換為小寫。
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 index = last(context.scopePathItem)
const scopeList = context.scopeList
const num = context.num
for (let i = 0, len = num + 1; i < len; i++) {
obj = assign(obj, scopeList[i])
}
//word模板中使用 $index+1 創(chuàng)建遞增序號
obj = assign(obj, { $index: index })
return expr(scope, obj)
}
}
}
JSZipUtils.getBinaryContent(tempDocxPath, (error, content) => {
if (error) {
console.log(error)
}
expressions.filters.size = function (input, width, height) {
return {
data: input,
size: [width, height],
};
};
let opts = {}
opts = {
//圖像是否居中
centered: true
};
opts.getImage = (chartId) => {
//將base64的數(shù)據(jù)轉(zhuǎn)為ArrayBuffer
return base64DataURLToArrayBuffer(chartId);
}
opts.getSize = function (img, tagValue, tagName) {
//自定義指定圖像大小
if (imgSize.hasOwnProperty(tagName)) {
return imgSize[tagName];
} else {
return [200, 200];
}
}
// 創(chuàng)建一個JSZip實例,內(nèi)容為模板的內(nèi)容
const zip = new PizZip(content)
// 創(chuàng)建并加載 Docxtemplater 實例對象
// 設置模板變量的值
let doc = new Docxtemplater();
doc.attachModule(new ImageModule(opts));
doc.loadZip(zip);
doc.setOptions({parser:angularParser});
doc.setData(data)
try {
// 呈現(xiàn)文檔,會將內(nèi)部所有變量替換成值,
doc.render()
} catch (error) {
const e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties
}
console.log('err',{ error: e })
// 當使用json記錄時,此處拋出錯誤信息
throw error
}
// 生成一個代表Docxtemplater對象的zip文件(不是一個真實的文件,而是在內(nèi)存中的表示)
const out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
})
// 將目標文件對象保存為目標類型的文件,并命名
saveAs(out, fileName)
})
}
/**
* 將圖片的url路徑轉(zhuǎn)為base64路徑
* 可以用await等待Promise的異步返回
* @param {Object} imgUrl 圖片路徑
*/
export function getBase64Sync(imgUrl) {
return new Promise(function (resolve, reject) {
// 一定要設置為let,不然圖片不顯示
let image = new Image();
//圖片地址
image.src = imgUrl;
// 解決跨域問題
image.setAttribute("crossOrigin", '*'); // 支持跨域圖片
// image.onload為異步加載
image.onload = function () {
let canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
let context = canvas.getContext("2d");
context.drawImage(image, 0, 0, image.width, image.height);
//圖片后綴名
let ext = image.src.substring(image.src.lastIndexOf(".") + 1).toLowerCase();
//圖片質(zhì)量
let quality = 0.8;
//轉(zhuǎn)成base64
let dataurl = canvas.toDataURL("image/" + ext, quality);
//返回
resolve(dataurl);
};
})
}四、調(diào)用導出方法
<script>
import {exportWord,getBase64Sync} from '@/assets/js/outword.js'
export default {
data () {
return {
name:'lipipi',
listname:'導出的模板'
imglist:[
{
imgUrl: "https://img2.baidu.com/it/u=2709954499,581919391&fm=253&fmt=auto&app=138&f=JPEG?w=468&h=518"
},
{
imgUrl: "https://img0.baidu.com/it/u=1462004956,1440895436&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=353"
}
]
}
},
methods:{
async exportWordFile (){
//多個圖片遍歷轉(zhuǎn)base64
for (let i in this.imglist) {
this.imglist[i].imgUrl = await getBase64Sync(this.imglist[i].imgUrl)
}
let data= {
name:this.name
imglist:this.imglist
}
let imgSize = {
//控制導出的word圖片大小
imgurl:[200, 200],
};
exportWord("/我的模板.docx", data, `${this.listname}.docx`, imgSize);
}
}
}
</script>總結(jié)
到此這篇關(guān)于VUE使用docxtemplater導出word文檔的文章就介紹到這了,更多相關(guān)VUE用docxtemplater導出word內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
uniapp使用scroll-view下拉刷新無法取消的坑及解決
這篇文章主要介紹了uniapp使用scroll-view下拉刷新無法取消的坑及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05
vue?element-ui如何在el-tabs組件最右側(cè)添加按鈕
這篇文章主要介紹了vue?element-ui如何在el-tabs組件最右側(cè)添加按鈕問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
如何在Vue中使localStorage具有響應式(思想實驗)
這篇文章主要介紹了如何在Vue中使localStorage具有響應式,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07

