vue使用docxtemplater导出word

vue使用docxtemplater导出word

// Func:导出word文档,包括图片和文字
// 使用:
// 		安装JSZipUtils,Docxtemplater,PizZip,file-saver,docxtemplater-image-module-free
// 		引用该组件,import DocRender from "DocRender.vue"
// 		注册 components:{ DocRender }
// 		在Template中使用 <DocRender ref="DocRender"/>\
// 		在scripts中调用exports函数生成word文档
// 		示例,参数依次为,图片最大高度,模板文件路径(示例放在public文件夹下),图片,文字,输出文件名
// 			this.$refs.export(
// 				100,
// 				100,
// 				`./i.docx`,
// 				{
// 					image:
// 						"https://t8.baidu.com/it/u=3571592872,3353494284&fm=79&app=86&size=h300&n=0&g=4n&f=jpeg?sec=1604021710&t=9c909dc8afcad27ac6a080e699025d7b"
// 				},
// 				{},
// 				"检查"
// 			);
// 		},


<template>
</template>

<script>
import JSZipUtils from "jszip-utils/dist/jszip-utils.js";
import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import { saveAs } from "file-saver";
import ImageModule from "docxtemplater-image-module-free";

function loadFile(url, callback) {
	JSZipUtils.getBinaryContent(url, callback);
}

export default {
	name: "DocRender",
	data() {
		return {
			imageSize: {},
			imageMaxHeight: 0,
			imageMaxWidth: 0,
			templateLocaton: "",
			content: {},
			outputname: "output.docx"
		};
	},

	methods: {
		export(
			imageMaxHeight,
			imageMaxWidth,
			templateLocaton,
			imageArray,
			wordArray,
			outputname
		) {
			this.content = Object.assign(imageArray, wordArray);
			this.imageMaxHeight = imageMaxHeight;
			this.imageMaxWidth = imageMaxWidth;
			this.templateLocaton = templateLocaton;
			this.outputname = outputname;
			this.initializeImageSize(imageArray);
			console.log(this.imageSize);
			console.log(this.content);
			this.renderDoc();
		},

		initializeImageSize(array) {
			let that = this;
			Object.keys(array).forEach(async key => {
				await this.getImageOriginalSize(array[key]).then(res => {
					that.imageSize[key] = [res];
				});
			});
		},
		getImageOriginalSize(url) {
			var that = this;
			return new Promise(function(resolve, reject) {
				var image = new Image();
				image.src = url;
				image.onload = function() {
					resolve({ width: image.width, height: image.height });
				};
				// image.onerror = function(e) {
				// 	//console.log("img, tagValue, tagName : ", img, tagValue, tagName);
				// 	console.log("An error occured while loading ");
				// 	reject(e);
				// };
			}).then(sizeObj => {
				const maxWidth = that.imageMaxWidth;
				const maxHeight = that.imageMaxHeight;
				const aspectRatio = sizeObj.width / sizeObj.height;
				const widthRatio = sizeObj.width / maxWidth;
				const heightRatio = sizeObj.height / maxHeight;
				if (widthRatio < 1 && heightRatio < 1) {
					// Do not scale up images that are smaller than maxWidth,maxHeight
					return [sizeObj.width, sizeObj.height];
				}
				let finalWidth, finalHeight;
				if (widthRatio > heightRatio) {
					// Width will be equal to maxWidth because width is the most
					// "limiting"
					finalWidth = maxWidth;
					finalHeight = sizeObj.height / widthRatio;
				} else {
					// Height will be equal to maxHeight because height is the most
					// "limiting"
					finalHeight = maxHeight;
					finalWidth = sizeObj.width / heightRatio;
				}
				//console.log([Math.round(finalWidth), Math.round(finalHeight)]);
				return [Math.round(finalWidth), Math.round(finalHeight)];
			});
		},

		replaceErrors(key, value) {
			if (value instanceof Error) {
				return Object.getOwnPropertyNames(value).reduce(function(error, key) {
					error[key] = value[key];
					return error;
				}, {});
			}
			return value;
		},
		renderDoc() {
			var that = this;
			console.log(that.templateLocaton);
			loadFile(that.templateLocaton, (error, content) => {
				if (error) {
					throw error;
				}
				var opts = {};
				opts.centered = false;
				opts.fileType = "docx"; //Or pptx
				opts.getImage = function(tagValue, tagName) {
					//console.log(tagValue, tagName);
					return new Promise(function(resolve, reject) {
						JSZipUtils.getBinaryContent(tagValue, function(error, content) {
							if (error) {
								return reject(error);
							}
							return resolve(content);
						});
					});
				};

				opts.getSize = (img, tagValue, tagName) => {
					//console.log(tagValue, tagName);
					// img is the value that was returned by getImage
					// This is to limit the width and height of the resulting image
					console.log(that.imageSize[tagName][0]);
					return that.imageSize[tagName][0];
				};

				var imageModule = new ImageModule(opts);
				var zip = new PizZip(content);
				const doc = new Docxtemplater()
					.loadZip(zip)
					.attachModule(imageModule)
					.compile();
				doc.resolveData(that.content).then(() => {
					try {
						// render the document (replace all occurences of {first_name} by John, {last_name} by Doe, ...)
						doc.render();
					} catch (error) {
						// The error thrown here contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors).

						console.log(JSON.stringify({ error: error }, that.replaceErrors));

						if (error.properties && error.properties.errors instanceof Array) {
							const errorMessages = error.properties.errors
								.map(function(error) {
									return error.properties.explanation;
								})
								.join("\n");
							console.log("errorMessages", errorMessages);
							// errorMessages is a humanly readable message looking like this :
							// 'The tag beginning with "foobar" is unopened'
						}
						throw error;
					}
					var out = doc.getZip().generate({
						type: "blob",
						mimeType:
							"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
					}); //Output the document using Data-URI
					saveAs(out, that.outputname);
				});
			});
		}
	}
};
</script>


<style scoped>
</style>

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值