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

代码如下

<!DOCTYPE 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>  
  •  

下载的PDF文件

深入pdfmake.js

  OK, 到了这里,不难发现,当我们配置好了响应的vsf_fonts.js,然后使用pdfMake.fonts配置下响应的字体,那么导出的pdf就没有乱码了。实现了pdf中文导出无乱码,我的心情可以用雀跃来形容了。然后对pdfmake.js就迫不及待的想了解更多,于是找到了他们官网pdfmake官网 PS:正好我的办公网段刚开通了国外翻墙,访问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功能,更重要的是我们对技术追求的学习力。技术是一个无边的海阳,我们不可能掌握所有的技术。尤其是我们在工作的时候,更多的是需要什么,然后去学习什么。 
包括目前现有的各种插件,当其中某一种部分不能满足我们需求的时候,不妨来读读源码,甚至可以尝试改改源码,轻而易举就能把需求漂亮完成咯

猜你喜欢

转载自blog.csdn.net/qq_38316721/article/details/81455186