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页面代码设置也很简单:就页面中放了一个下载的按钮而已 
页面展示

代码如下

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>my first export PDF</title>
  6. <script src="pdfmake.min.js"></script>
  7. <script src="方正vfs_fonts.js"></script>
  8. <script>
  9. function down(data) {
  10. var dd = {
  11. content: [
  12. data,
  13. 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines'
  14. ],
  15. defaultStyle: {
  16. font: '方正姚体'
  17. }
  18. };
  19. pdfMake.fonts = {
  20. Roboto: {
  21. normal: 'Roboto-Regular.ttf',
  22. bold: 'Roboto-Medium.ttf',
  23. italics: 'Roboto-Italic.ttf',
  24. bolditalics: 'Roboto-Italic.ttf'
  25. },
  26. 方正姚体: {
  27. normal: 'FZYTK.TTF',
  28. bold: 'FZYTK.TTF',
  29. italics: 'FZYTK.TTF',
  30. bolditalics: 'FZYTK.TTF',
  31. }
  32. };
  33. pdfMake.createPdf(dd).download();
  34. }
  35. </script>
  36. </head>
  37. <body>
  38. <button onclick="down('pdf文件显示中文')">下载</button>
  39. </body>
  40. </html>
  •  

下载的PDF文件

深入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 
这里写图片描述

  1. _pdfMake().fonts = {
  2. Roboto: {
  3. normal: 'Roboto-Regular.ttf',
  4. bold: 'Roboto-Medium.ttf',
  5. italics: 'Roboto-Italic.ttf',
  6. bolditalics: 'Roboto-Italic.ttf'
  7. },
  8. 方正姚体: {
  9. normal: 'FZYTK.TTF',
  10. bold: 'FZYTK.TTF',
  11. italics: 'FZYTK.TTF',
  12. bolditalics: 'FZYTK.TTF',
  13. },
  14. // 微软雅黑: {
  15. // normal: '微软雅黑.ttf',
  16. // bold: '微软雅黑.ttf',
  17. // italics: '微软雅黑.ttf',
  18. // bolditalics: '微软雅黑.ttf',
  19. // }
  20. };
  21.  
  22. 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生成的,代码如下:

  1. $('.datatable').DataTable({
  2. 'dom': 'Btirlp',
  3. "sPaginationType": "full_numbers",
  4. 'buttons': [{
  5. "extend": 'pdfHtml5',
  6. 'title': '候选人详细说明', //导出文件名字
  7. 'text': '导出table数据pdf文件', //定义导出excel按钮的文字
  8. "aButtons": "true",
  9. 'download': 'open',//直接在窗口打开
  10. // 'orientation': 'landscape',
  11. // 'pageSize': 'LEGAL',
  12. 'messageTop': '副标题位置信息'
  13.  
  14. }],
  15. // "searching": true
  16. "bDestroy": true,
  17. // "bServerSide": true,
  18. // "sAjaxSource": "",
  19. "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,至今未婚,有房有车' }, ],
  20. "aoColumns": [{
  21. "sTitle": "id",
  22. // "sWidth": "10%",
  23. "mDataProp": "id"
  24. }, {
  25. "sTitle": "名称",
  26. // "sWidth": "10%",
  27. "mDataProp": "name"
  28. }, {
  29. "sTitle": "描述",
  30. // "sWidth": "15%",
  31. "mDataProp": "desc"
  32. }],
  33. "oLanguage": {
  34. "sProcessing": "处理中...",
  35. "sLengthMenu": "显示 _MENU_ 项结果",
  36. "sZeroRecords": "没有匹配结果",
  37. "sInfo": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项",
  38. "sInfoEmpty": "显示第 0 至 0 项结果,共 0 项",
  39. "sInfoFiltered": "(由 _MAX_ 项结果过滤)",
  40. "sInfoPostFix": "",
  41. "sSearch": "搜索:",
  42. "sUrl": "",
  43. "sEmptyTable": "表中数据为空",
  44. "sLoadingRecords": "载入中...",
  45. "sInfoThousands": ",",
  46. "oPaginate": {
  47. "sFirst": "首页",
  48. "sPrevious": "上页",
  49. "sNext": "下页",
  50. "sLast": "末页"
  51. },
  52. "oAria": {
  53. "sSortAscending": ": 以升序排列此列",
  54. "sSortDescending": ": 以降序排列此列"
  55. }
  56. },
  57. "aoColumnDefs": []
  58. });

其中buttons的配置参考datatable extension的文档去好好看看咯datatables.net/extensions/buttons/examples 
导出pdf无中文乱码结果: 
这里写图片描述

想要完整代码的,从下边链接进去下载吧 
datatable、pdf中文无乱码导出

扩展使用

  刚刚前面有提到,我们极有可能遇到:某个数据要标红显示的需求,那么我们来实现一下吧,让表格第五行的第二列标红. 
   要实现需求,本质上就是定位到我们需求的位置,然后对需求内容样式更改下即可。要定位到需求位置,就在rows里边去找吧。 
  生成rows的时候,遍历了一下data.body。OK,显然,我们在data.body遍历的时候去定位就可以了 
这里写图片描述
代码如下

  1.  
  2. for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
  3. if(i==4){
  4. rows.push( $.map( data.body[i], function ( d, key ) {
  5. if(key == 1){
  6. return {
  7. text: typeof d === 'string' ? d : d+'',
  8. style: i % 2 ? 'tableBodyEven' : {fillColor: '#f3f3f3',color:'red'}
  9. };
  10. }else {
  11. return {
  12. text: typeof d === 'string' ? d : d+'',
  13. style: i % 2 ? 'tableBodyEven' : 'tableBodyOdd'
  14. };
  15.  
  16. }
  17. } ) );
  18.  
  19. }else{
  20. rows.push( $.map( data.body[i], function ( d ) {
  21. return {
  22. text: typeof d === 'string' ? d : d+'',
  23. style: i % 2 ? 'tableBodyEven' : 'tableBodyOdd'
  24. };
  25. } ) );
  26.  
  27. }
  28. }

再来看看导出效果: 
这里写图片描述

完美收官

  经过了以上从懵懵懂懂,到最后的应用游刃有余,我想说的不仅仅是一个pdf中文无乱码导出前端JS功能,更重要的是我们对技术追求的学习力。技术是一个无边的海阳,我们不可能掌握所有的技术。尤其是我们在工作的时候,更多的是需要什么,然后去学习什么。 
包括目前现有的各种插件,当其中某一种部分不能满足我们需求的时候,不妨来读读源码,甚至可以尝试改改源码,轻而易举就能把需求漂亮完成咯

posted @ 2018-10-23 14:33  KJXY  阅读(873)  评论(0)    收藏  举报