本文主要参考了:
博主:芊赋予翔
https://blog.csdn.net/weixin_44956861/article/details/105029161
https://blog.csdn.net/weixin_44956861/article/details/101765177
两篇文章,十分感谢,也希望,这样实质有用能够解决问题的文章能够帮助到更多人。
先看看效果:
网页部分:
复杂的多级表格
导出结果:
方法内容主要分为一下几点:
1.(这里是我对docxtemplater的吐槽,不想看可以跳过1,直接去2.被折磨了好久,实在是忍不住,包容一下)不需要像其他方法如 docxtemplater 需要弄复杂的word模板,关于docxtemplater方法的主要使用方法相关链接如下:
vue导出Word文件(模板导出)
该方法使用依赖的主页
该方法的word模板的demo主页
还有这个方法不用考虑下载 docxtemplater-html-module 这个包了,当你
npm install --save docxtemplater-html-module
会显示
npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.com/docxtemplater-html-module - Not found
因为这个 docxtemplater-html-module 是付费下载的,就是要钱的 所以,这条路遇见了复杂的页面导出基本上是走不通,像上面这种表格。至少我研究了很久没有研究透怎么写它的word模板和相关的js函数。
2.说回mhtml-to-word这个方法的需要的第三方依赖不多,主要是:
npm install mhtml-to-word
npm install file-saver
3.使用方法也很简单:
import { exportWord } from 'mhtml-to-word'
import { saveAs } from 'file-saver'
4.当然你还需要将当前页面的html代码转换成字符串,主要靠三个函数:
函数一:
export function getModelHtml(mhtml,style){
return `
Content-Type: text/html; charset="utf-8"
<!DOCTYPE html>
<html>
<head>
<style>
${style}
</style>
</head>
<body>
${mhtml}
</body>
</html>
`
},
函数二:
export function getHtml(dom) {
let _dom = dom || document;
var canvass = _dom.querySelectorAll('canvas');
var imgRepalce = _dom.querySelectorAll('.imgRepalce');
let imageList = [];
//canvass echars图表转为图片
for(let k4 = 0; k4 < canvass.length; k4++) {
let imageURL = canvass[k4].toDataURL("image/png");
let img = document.createElement("img");
img.src = imageURL;
imageList.push(img.outerHTML);
}
//做分页
//style="page-break-after: always"
let pages = _dom.querySelectorAll('.result');
for(let k5 = 0; k5 < pages.length; k5++) {
pages[k5].setAttribute('style', 'page-break-after: always');
}
let result = _dom.outerHTML;
//result = result.replace(/<colgroup>(.*?)<\/colgroup>/gi, '')
//result = result.replace(/<canvas (.*?)><\/canvas>/gi, '')
for(let i = 0; i < imgRepalce.length; i++) {
result = result.replace(imgRepalce[i].outerHTML,
'<div class="imgRepalce">' + imageList[i] + '</div>')
}
result = result.replace(/<img (.*?)>/gi, '<img $1></img>')
result = result.replace(/<br>/gi, '<br></br>');
result = result.replace(/<hr>/gi, '<hr></hr>');
return "<body printmarginleft='72' printmarginright='72' printmargintop='56' printmarginbottom='56'>" + result + "</body>";
}
这里注意传参数,当前页面的话使用的参数为:
getHtml(this.$refs.print)
函数三:
export function getStyle(notPrint) {
var str = '<head><meta charset="utf-8"></meta>',
styles = document.querySelectorAll('style');
for(var i = 0; i < styles.length; i++) {
str += styles[i].outerHTML;
}
str += "<style>" + (notPrint ? notPrint : '.no-print') + "{display:none;}</style>";
str += "<style>.results{width:100%!important;} .result .title{width:100%;}</style>";
str += "<style>table{border-collapse: collapse;table-layout: fixed}</style>"
str += "<style>table thead tr{ background-color: #f3f4f9;}</style>"
str += "<style>table td,th{ font-size: 14px;padding: 1px 1px;border-width: 1px;border-style: solid;border-color: #d0d0d0;word-break: keep-all;white-space: nowrap;}</style>"
str += "<style>h5{font-color: #2fb89e;}</style>"
str += "</head>"
return str;
}
这三个函数缺一不可。
5.将所有的东西准备好了之后,就可以开始使用了:
exportWord(){
// 把当前 vue 所展示的页面对应的 html 转换成一个字符串,这里用到了上面的三个函数,所以,如果是写在外面的话要引用进来
let html = this.getModelHtml(getHtml(this.$refs.print),getStyle());
// 使用我们刚刚准备好的html模板并创建Blob对象
let blob = new Blob([html],{type:"application/msword;charset=utf-8"});
// 调用FileSaver.saveAs导出下载word
saveAs(blob, "导出word的名字.doc");
}
把这个函数的调用给一个按钮就行了。
最终效果:
就这么简单!!!