datatable 导出无乱码中文pdf文件
原文地址:https://blog.csdn.net/qq_30076899/article/details/79731508
datatable 导出无乱码中文pdf文件
我一个前端程序员,最近老大要我出一个报表UI,并跟我说要支持pdf导出,因为这个报表数据回头要发给部门老大看,pdf显得正式点,然后,我就开始了各种找插件之旅。。。
开始尝试导出pdf文件
首先,介绍下我们的项目背景:UI使用datatable。当我去看datatable官网的时候,很高兴,有现成的导出插件:datatable导出插件,简直让我欣喜若狂呀,不过如果这么简单就把需求做好了,那我也就没有下文可写了。
datatable 毕竟是老外写的,所以并不支持中文,即:导出的中文都是乱码。作为中国人,是不是有点不可忍?(对于我来说,是的!!!)
打算放弃datatable extensoin
既然datatable现有插件不支持中文导出pdf,我首先想到的是放弃使用他的现有插件。百度一下,放眼望去出现比较多的词语就是tableExport。So,这应该是一款比较成熟的插件了吧,直接用应该没什么问题。
那就用下tableExport试试吧
使用tableExport
跑去tableExport官网荡一下,直接使用官网tableExport的 js文件,然鹅。。。中文还是有乱码。tableExport也是老外写的吧?
不过还好,咱们CSDN上有好几个热心的朋友都贴出来解决方案。
看了好几个博文的解决方案,解决办法就是需要引入中文字体vfs_fonts.js。
然鹅,我的悲剧就是:生成vfs_fonts.js失败(莫非是我用的mac最新版本?),更让我崩溃的是:在咱们CSDN上下载的近30M的vfs_fonts.js文件,竟然运行的时候报错,让我情何以堪?各种泪崩呀。
使用pdfmake.js
细心的我,发现:不管是tableExport 还是datatable
extension,他们都使用了pdfmake.js。vsf_fonts.js设置下自己想要的字体,pafmake.js就能导出相应的pdf无乱码文件。值得高兴的是,我也找到了一个中文的vsf_fonts.js,虽然是方正姚体,不过,能实现中文导出pdf无乱码,所以就不管三七二十一,用了再说。
代码实现很简单,js引入pdfmake.js和vfs_fonts.js就可以。HTML页面代码设置也很简单:就页面中放了一个下载的按钮而已
代码如下
-
-
<html lang="zh-CN">
-
<head>
-
<meta charset="utf-8">
-
<title>my first export PDF</title>
-
<script src="pdfmake.min.js"></script>
-
<script src="方正vfs_fonts.js"></script>
-
<script>
-
function down(data) {
-
var dd = {
-
content: [
-
data,
-
'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines'
-
],
-
defaultStyle: {
-
font: '方正姚体'
-
}
-
};
-
pdfMake.fonts = {
-
Roboto: {
-
normal: 'Roboto-Regular.ttf',
-
bold: 'Roboto-Medium.ttf',
-
italics: 'Roboto-Italic.ttf',
-
bolditalics: 'Roboto-Italic.ttf'
-
},
-
方正姚体: {
-
normal: 'FZYTK.TTF',
-
bold: 'FZYTK.TTF',
-
italics: 'FZYTK.TTF',
-
bolditalics: 'FZYTK.TTF',
-
}
-
};
-
pdfMake.createPdf(dd).download();
-
}
-
</script>
-
</head>
-
<body>
-
<button onclick="down('pdf文件显示中文')">下载</button>
-
</body>
-
</html>
深入pdfmake.js
OK, 到了这里,不难发现,当我们配置好了响应的vsf_fonts.js,然后使用pdfMake.fonts配置下响应的字体,那么导出的pdf就没有乱码了。实现了pdf中文导出无乱码,我的心情可以用雀跃来形容了。然后对pdfmake.js就迫不及待的想了解更多,于是找到了他们官网pdfmake官网 PS:正好我的办公网段刚开通了国外FQ,访问pdfmake官网完全没有压力,网速嘎嘎哒。。。
稍微浏览下pdfmake的docs,我惊呆了:pdfmake竟然功能如此强大,style、table、list、header、footer…各种排版样式,各种强大的功能都有,普通的table导出更不是问题了,即使领导要求pdf导出文件需要这个那个标红、这个那个显示背景颜色,这些通通不是事。
回到datatable extension
为什么回到datatable extension呢? 因为datatable extension已经把要导出的内容写好了,我们要导出pdf文件,直接把导出内容用createPdf()方法导出即可。
一起来读一读来看看datatable extension的源码:button.html5.js。
js有点基础的读起来应该问题不大,而这个button.html5.js也就一千多行代码,其中导出pdf文件相关的目测才300多行,不信你们看看:
有了之前咱们导出pdf中文无乱码的经验,那在button.html5.js先找到createPdf()这个方法,然后再该方法之前增加咱们相应的pdfMake.fonts
-
_pdfMake().fonts = {
-
Roboto: {
-
normal: 'Roboto-Regular.ttf',
-
bold: 'Roboto-Medium.ttf',
-
italics: 'Roboto-Italic.ttf',
-
bolditalics: 'Roboto-Italic.ttf'
-
},
-
方正姚体: {
-
normal: 'FZYTK.TTF',
-
bold: 'FZYTK.TTF',
-
italics: 'FZYTK.TTF',
-
bolditalics: 'FZYTK.TTF',
-
},
-
// 微软雅黑: {
-
// normal: '微软雅黑.ttf',
-
// bold: '微软雅黑.ttf',
-
// italics: '微软雅黑.ttf',
-
// bolditalics: '微软雅黑.ttf',
-
// }
-
};
-
-
var pdf = _pdfMake().createPdf( doc );
在代码中可以看到,我给微软雅黑字体预留了个位置,以后我的vsf_font.js有了微软雅黑之后就可以直接使用微软雅黑字体了。
从以上代码可以看到,createPdf该方法里边的doc就是生成pdf文件的配置了,咱们再花点精力往直前看看doc具体是什么
OK,如果你刚才在pdfmake官网有留意的话,不难发现,这就是标准的pdfmake导出文件的配置对象,并且使用的table布局导出。当然最后的defaultStyle中的font: ‘方正姚体’就是我配置好的文件导出的字体。
如果想再深入看看导出的内容,可以看看table>body的rows
从图片中可以看到,rows就是datable extension给我们生成的表格的所有内容,如果你不想逐行读代码,可以直接console.log(rows)看看里边的内容具体是什么,跟自己要导出的内容是否对的上(肯定是对的上的啦。。。)
导出结果展示
前端页面写一个简单的table,然后咱们来试试效果吧。
table是用datatable生成的,代码如下:
-
$('.datatable').DataTable({
-
'dom': 'Btirlp',
-
"sPaginationType": "full_numbers",
-
'buttons': [{
-
"extend": 'pdfHtml5',
-
'title': '候选人详细说明', //导出文件名字
-
'text': '导出table数据pdf文件', //定义导出excel按钮的文字
-
"aButtons": "true",
-
'download': 'open',//直接在窗口打开
-
// 'orientation': 'landscape',
-
// 'pageSize': 'LEGAL',
-
'messageTop': '副标题位置信息'
-
-
}],
-
// "searching": true
-
"bDestroy": true,
-
// "bServerSide": true,
-
// "sAjaxSource": "",
-
"data": [{ id: 1, name: '小明1', desc: '年龄45,至今未婚,有房有车' }, { id: 2, name: '小明2', desc: '年龄45,至今未婚,有房有车' }, { id: 3, name: '小明3', desc: '年龄45,至今未婚,有房有车' }, { id: 4, name: '小明4', desc: '年龄45,至今未婚,有房有车' }, { id: 5, name: '小明5', desc: '年龄45,至今未婚,有房有车' }, { id: 6, name: '小明6', desc: '年龄45,至今未婚,有房有车' }, { id: 7, name: '小明7', desc: '年龄45,至今未婚,有房有车' }, { id: 8, name: '小明8', desc: '年龄45,至今未婚,有房有车' }, { id: 9, name: '小明9', desc: '年龄45,至今未婚,有房有车' }, { id: 10, name: '小明10', desc: '年龄45,至今未婚,有房有车' }, { id: 11, name: '小明1', desc: '年龄45,至今未婚,有房有车' }, ],
-
"aoColumns": [{
-
"sTitle": "id",
-
// "sWidth": "10%",
-
"mDataProp": "id"
-
}, {
-
"sTitle": "名称",
-
// "sWidth": "10%",
-
"mDataProp": "name"
-
}, {
-
"sTitle": "描述",
-
// "sWidth": "15%",
-
"mDataProp": "desc"
-
}],
-
"oLanguage": {
-
"sProcessing": "处理中...",
-
"sLengthMenu": "显示 _MENU_ 项结果",
-
"sZeroRecords": "没有匹配结果",
-
"sInfo": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项",
-
"sInfoEmpty": "显示第 0 至 0 项结果,共 0 项",
-
"sInfoFiltered": "(由 _MAX_ 项结果过滤)",
-
"sInfoPostFix": "",
-
"sSearch": "搜索:",
-
"sUrl": "",
-
"sEmptyTable": "表中数据为空",
-
"sLoadingRecords": "载入中...",
-
"sInfoThousands": ",",
-
"oPaginate": {
-
"sFirst": "首页",
-
"sPrevious": "上页",
-
"sNext": "下页",
-
"sLast": "末页"
-
},
-
"oAria": {
-
"sSortAscending": ": 以升序排列此列",
-
"sSortDescending": ": 以降序排列此列"
-
}
-
},
-
"aoColumnDefs": []
-
});
其中buttons的配置参考datatable extension的文档去好好看看咯datatables.net/extensions/buttons/examples
导出pdf无中文乱码结果:
想要完整代码的,从下边链接进去下载吧
datatable、pdf中文无乱码导出
扩展使用
刚刚前面有提到,我们极有可能遇到:某个数据要标红显示的需求,那么我们来实现一下吧,让表格第五行的第二列标红.
要实现需求,本质上就是定位到我们需求的位置,然后对需求内容样式更改下即可。要定位到需求位置,就在rows里边去找吧。
生成rows的时候,遍历了一下data.body。OK,显然,我们在data.body遍历的时候去定位就可以了
代码如下
-
-
for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
-
if(i==4){
-
rows.push( $.map( data.body[i], function ( d, key ) {
-
if(key == 1){
-
return {
-
text: typeof d === 'string' ? d : d+'',
-
style: i % 2 ? 'tableBodyEven' : {fillColor: '#f3f3f3',color:'red'}
-
};
-
}else {
-
return {
-
text: typeof d === 'string' ? d : d+'',
-
style: i % 2 ? 'tableBodyEven' : 'tableBodyOdd'
-
};
-
-
}
-
} ) );
-
-
}else{
-
rows.push( $.map( data.body[i], function ( d ) {
-
return {
-
text: typeof d === 'string' ? d : d+'',
-
style: i % 2 ? 'tableBodyEven' : 'tableBodyOdd'
-
};
-
} ) );
-
-
}
-
}
再来看看导出效果:
完美收官
经过了以上从懵懵懂懂,到最后的应用游刃有余,我想说的不仅仅是一个pdf中文无乱码导出前端JS功能,更重要的是我们对技术追求的学习力。技术是一个无边的海阳,我们不可能掌握所有的技术。尤其是我们在工作的时候,更多的是需要什么,然后去学习什么。
包括目前现有的各种插件,当其中某一种部分不能满足我们需求的时候,不妨来读读源码,甚至可以尝试改改源码,轻而易举就能把需求漂亮完成咯
浙公网安备 33010602011771号