ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JS纯前端导出PDF及分页和使用window.print()保存PDF

2021-09-06 18:32:43  阅读:322  来源: 互联网

标签:newWb JS window brhtml pdf var PDF rowNum firstNum


	最近由于项目要求需要将导出PDF类文件,其中涉及到固定表头,翻页,样式调整等问题
一开始选择了网上较多讲解的使用html2canvas.js和jspdf.js先转图片再转PDF的方法。
 var xsxf = document.getElementById("export_content");
 html2canvas(
     xsxf,
     //document.getElementById("export_content"),
     {
         dpi: 172,//导出pdf清晰度
         //proxy: "string",
         onrendered: function (canvas) {
             var contentWidth = canvas.width;
             var contentHeight = canvas.height;
             //一页pdf显示html页面生成的canvas高度;
             var pageHeight = 840;
             //var pageHeight = contentWidth / 575 * 840;
             //未生成pdf的html页面高度
             var leftHeight = contentHeight;
             //pdf页面偏移
             var position = 0;
             //html页面生成的canvas在pdf中图片的宽高(a4纸的尺寸[595.28,841.89])
             var imgWidth = 595.28;
             var imgHeight = 592.28 / contentWidth * contentHeight;
    
             var pageData;
             var pdf = new jsPDF('', 'pt', 'a4');
             //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
             //当内容未超过pdf一页显示的范围,无需分页
            if (leftHeight < pageHeight) {
                 pageData = canvas.toDataURL('image/jpeg', 1.0);
                 pdf.addImage(pageData, 'JPEG', 10, 5, imgWidth - 20, imgHeight - 10);
                
             } else {
                 while (leftHeight > 0) {
                     pageData = canvas.toDataURL('image/jpeg', 1.0);
                     pdf.addImage(pageData, 'JPEG', 10, position + 5, imgWidth - 20, imgHeight - 10)
                     leftHeight -= pageHeight;
                     position -= 841.89;
                     //避免添加空白页
                     if (leftHeight > 0) {
                         pdf.addPage();
                     }
                 }
             }
             pdf.save(filename);
         },
         //背景设为白色(默认为黑色)
         background: "#fff"
     });

但很快发现当表格数据量大时出现翻页问题,所以试着先将表头固定数据取出,表体数据进行分割拼接表头

 //大于一页分页表头固定
        function reFullHtml(wb, filename, _tableHead, rowNum, pageHeight) {
            var tableH = document.querySelector('#table_content').scrollHeight + 70;
            var miH = (pageHeight - tableH);       //详细
            var trL = $('#mini-grid-table1 > tbody>tr').length;
            var max = parseInt(miH / 34);
            var firstNum = rowNum - 2 + max;

            var page = Math.ceil(trL / max);
            var brhtml = "</table></br></br></br></br></br>";
            //PL表尾
            if (rowNum == 12 && firstNum > (trL + rowNum - 5)) {
                firstNum = trL + rowNum - 6;
                page = Math.ceil(trL / (max - 5));
                brhtml = brhtml + "</br></br></br></br></br></br></br></br></br>";
            }
            //CI表尾(特殊德国小家电)
            if (rowNum == 14 && firstNum > (trL + rowNum - 1)) {
                firstNum = trL + rowNum - 2;
                page = Math.ceil(trL / (max - 1));
                brhtml = brhtml + "</br></br>";
            }
            //判断一页内行数高度+表头高是否大于页高
            if ((firstNum - rowNum) * 34 + 75 > miH) {
                firstNum -= 1;
                brhtml = '</table></br></br></br></br></br></br></br>';
            }
            var beforNum = firstNum;
            var newWb = wb;
            var pNum = firstNum - rowNum - 2;
            var syNum = pageHeight - (pNum + 1) * 34 - tableH;
            var nbrHtml = "</table>"
            for (var c = 0; c < Math.ceil(syNum / 20); c++) {
                nbrHtml += "</br>"
            }
            for (var i = 0; i < page - 1; i++) {
                if ((firstNum - beforNum) * 34 + 75 > miH) {
                    firstNum -= 1;
                    brhtml = '</table></br></br></br></br></br></br></br>';
                }
                beforNum = firstNum;
                var reg = "<tr><td style='text-align: center; border-bottom: 1px solid #000000;  border-right: 1px solid #000000; font-size: 10px; font-family: 微软雅黑; word-wrap:break-word; height:33px;' t='[a-z]' id='sjs-A" + firstNum + "'>.*";
                var res = newWb.match(reg);
                if (res != null) {
                    if (res.length > 0) {
                        var newHead = newWb.replace(res[0], brhtml);
                        newWb = newHead + _tableHead + res[0];
                    }
                }
                firstNum += pNum;
                brhtml = nbrHtml;
            }
            if (firstNum < (trL + rowNum)) {
                if (rowNum == 12) {
                    firstNum = trL + rowNum - 6;
                    brhtml = "</table></br></br></br></br></br></br></br></br></br></br></br></br></br>";
                }
                else if (rowNum == 14) {
                    firstNum = trL + rowNum - 2;
                    brhtml = "</table></br></br></br></br></br></br>";
                }
                var reg1 = "<tr><td style='text-align: center; border-bottom: 1px solid #000000;  border-right: 1px solid #000000; font-size: 10px; font-family: 微软雅黑; word-wrap:break-word; height:33px;' t='[a-z]' id='sjs-A" + firstNum + "'>.*";
                var res1 = newWb.match(reg1);
                if (res1 != null) {
                    if (res1.length > 0) {
                        var newHead = newWb.replace(res1[0], brhtml);
                        newWb = newHead + _tableHead + res1[0];
                    }
                }
            }
            var xsxf = document.getElementById("export_content");
            xsxf.innerHTML = "</br>" +  newWb;
            rowNum = 1;
            if (newWb != "") {
                //var pageWidth = document.querySelector("#mini-grid-table1").scrollWidth;

                for (var p = 0; p < document.querySelectorAll("#sjs-A1").length; p++) {
                    document.querySelectorAll("#sjs-A1")[p].width = (pageWidth - 20) + "px";

                    document.querySelectorAll("#sjs-A5")[p].width = (pageWidth - 20) / 2 + "px";
                    document.querySelectorAll("#sjs-E5")[p].width = (pageWidth - 20) / 2 + "px";

                }
                downPDF(newWb, filename, _tableHead, rowNum);
            }

        }

分页解决完毕后,业务部门使用后反馈PDF过于模糊和数据无法复制,无奈寻找其他方法。
最后确定使用window.print()原生打印方法来保存。
其中碰到几个坑:
1、当表格宽度大于A4纸时,表格列宽会被挤压变现导致之前设置的列宽无效从而使分页出现问题
2、分页容纳行数算法和使用wp打印显示行数不一致,固尝试多次后固定行数
解决方案:
1、分页属性:style=‘page-break-after:always’ 分页属性 table 加上后会自动分页
2、设置表格宽度,其中表格宽最大设置到1000,大于1000时会变形

table {
  width:750px;
}

3、特殊列设置固定宽(列文字多的),其他使用百分比

function downPDF(wb, filename, _tableHead, rowNum, dataNum) {
	var xsxf = document.getElementById("export_content");
	  html2canvas(
	      xsxf,
	      //document.getElementById("export_content"),
	      {
	          //dpi: 172,//导出pdf清晰度
	          dpi: 144,
	          //proxy: "string",
	          onrendered: function (canvas) {
	              var contentWidth = canvas.width;
	              var contentHeight = canvas.height;
	              //一页pdf显示html页面生成的canvas高度;
	              var pageHeight = 840;
	              //var pageHeight = contentWidth / 575 * 840;
	              //未生成pdf的html页面高度
	              var leftHeight = contentHeight;
	              //pdf页面偏移
	              var position = 0;
	              //html页面生成的canvas在pdf中图片的宽高(a4纸的尺寸[595.28,841.89])
	              var imgWidth = 595.28;
	              var imgHeight = 592.28 / contentWidth * contentHeight;
	              var pageData;
	              var pdf = new jsPDF('', 'pt', 'a4');
	              if (leftHeight > pageHeight) {
	                  if (rowNum != 1) {
	                      reFullHtml(wb, filename, _tableHead, rowNum, dataNum);
	                      return;
	                  }
	              }
	              //20210826 hsj 原转PDF转图片失真严重,直接调用window打印方法保存
	              //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
	              //当内容未超过pdf一页显示的范围,无需分页
	              //if (leftHeight < pageHeight) {
	              //    pageData = canvas.toDataURL('image/jpeg', 1.0);
	              //    pdf.addImage(pageData, 'JPEG', 10, 5, imgWidth - 20, imgHeight - 10);
	                 
	              //} else {
	              //    while (leftHeight > 0) {
	              //        pageData = canvas.toDataURL('image/jpeg', 1.0);
	              //        pdf.addImage(pageData, 'JPEG', 10, position + 5, imgWidth - 20, imgHeight - 10)
	              //        leftHeight -= pageHeight;
	              //        position -= 841.89;
	              //        //避免添加空白页
	              //        if (leftHeight > 0) {
	              //            pdf.addPage();
	              //        }
	              //    }
	              //}
	              //pdf.save(filename);
	              window.print();
	          },
	          //背景设为白色(默认为黑色)
	          background: "#fff"
	      });
}
  //大于一页分页表头固定
        function reFullHtml(wb, filename, _tableHead, rowNum, dataNum) {
            var trL = $('#mini-grid-table1 > tbody>tr').length;
            var max = 20;
            if (dataNum>10) {
                max = 27;
            }
            else if (dataNum == 10){
                max = 25;
            }
            else if (dataNum >7) {
                max = 22;
            }
            var firstNum = rowNum + 2 + max;
            var page = Math.ceil(trL / max);
            var brhtml = "</table>";
            var newWb = wb;
            for (var i = 0; i < page - 1; i++) {
                var reg = "<tr><td style='text-align: center; border-bottom: 1px solid #000000;  border-right: 1px solid #000000; font-size: 10px; font-family: 微软雅黑; word-wrap:break-word; height:33px;' t='[a-z]' id='sjs-A" + firstNum + "'>.*";
                var res = newWb.match(reg);
                if (res != null) {
                    if (res.length > 0) {
                        var newHead = newWb.replace(res[0], brhtml);
                        //style='page-break-after:always' 分页属性
                        newWb = newHead + "</div><div style='page-break-after:always'>" + _tableHead + res[0];
                    }
                }
                else {
                    if (rowNum == 12) {
                        firstNum = trL + rowNum - 5;
                        brhtml = "</table>";
                    }
                    else if (rowNum == 14) {
                        firstNum = trL + rowNum - 1;
                        brhtml = "</table>";
                    }
                    var reg1 = "<tr><td style='text-align: center; border-bottom: 1px solid #000000;  border-right: 1px solid #000000; font-size: 10px; font-family: 微软雅黑; word-wrap:break-word; height:33px;' t='[a-z]' id='sjs-A" + firstNum + "'>.*";
                    var res1 = newWb.match(reg1);
                    if (res1 != null) {
                        if (res1.length > 0) {
                            var newHead = newWb.replace(res1[0], brhtml);
                            newWb = newHead + "</div><div style='page-break-after:always'>" + _tableHead + res1[0];
                        }
                    }
                }
                firstNum += max;
            }
            if (firstNum < (trL + rowNum)) {
                if (rowNum == 12) {
                    firstNum = trL + rowNum - 5;
                    brhtml = "</table>";
                }
                else if (rowNum == 14) {
                    firstNum = trL + rowNum - 2;
                    brhtml = "</table>";
                }
                var reg1 = "<tr><td style='text-align: center; border-bottom: 1px solid #000000;  border-right: 1px solid #000000; font-size: 10px; font-family: 微软雅黑; word-wrap:break-word; height:33px;' t='[a-z]' id='sjs-A" + firstNum + "'>.*";
                var res1 = newWb.match(reg1);
                if (res1 != null) {
                    if (res1.length > 0) {
                        var newHead = newWb.replace(res1[0], brhtml);
                        newWb = newHead + "</div><div style='page-break-after:always'>" + _tableHead + res1[0];
                    }
                }
            }
            var xsxf = document.getElementById("export_content");
            xsxf.innerHTML = "<div style='page-break-after:always'>" + newWb + "</div>";
            rowNum = 1;
            if (newWb != "") {
                if (dataNum >= 10) {
                    for (var n = 0; n < document.querySelectorAll("table").length; n++) {
                        document.querySelectorAll("table")[n].style.width = '900px';
                        document.querySelectorAll("table")[n].style.width = '900px';
                    }
                }
                for (var p = 0; p < document.querySelectorAll("#sjs-A1").length; p++) {
                    document.querySelectorAll("#sjs-A1")[p].width = (pageWidth - 20) + "px";
                    document.querySelectorAll("#sjs-A5")[p].width = (pageWidth - 20) / 2 + "px";
                    document.querySelectorAll("#sjs-E5")[p].width = (pageWidth - 20) / 2 + "px";
                    
                }
                downPDF(newWb, filename, _tableHead, rowNum);
            }
           
        }

效果
在这里插入图片描述
在这里插入图片描述
总结:总体来说还是使用最开始导出PDF的思路,先在html中解决分页问题后导出,不过放弃转成图片方式而直接使用原生方法。整体解决了分页问题和不清晰无法复制等问题。

标签:newWb,JS,window,brhtml,pdf,var,PDF,rowNum,firstNum
来源: https://blog.csdn.net/qq_38648411/article/details/120140980

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有