zoukankan      html  css  js  c++  java
  • Web打印连续的表格,自动根据行高分页

    拿到这个需求,我已经蛋碎了一地,经过N天的攻克,终于是把它搞定了,只是不知道会不会在某种情况下出现BUG。表示我心虚没有敢做太多的测试....

    ----------------------------------------------------------废话分割线-----------------------------------------------------------

    注:我们的系统是基于ligerui这个一堆bug的插件的。

    详细需求:

      1.任意一个表格,行高不均匀且不相等;

      2.数字、公式等,不能换行;

      3.A3、A4纸横向打印,用户可选;

      4.JavaScript实现

      5.每页都要有表头、总记录数、当前页和总页数

    整体思路:

      1.js无法获取打印机的信息,所以,要用户在我们系统中选择好纸张大小,然后打印的时候再选一次,个人认为这个要自动适配并不容易,反正我的是手动选的。

      2.数字、公式不能换行,如果表格横向特别长,就不能使用css:word-break进行强制换行,只能由它默认的去换行。

      3.js打印肯定是先新建个空白的页面,然后把东西展示出来,用Jquery.Print这个插件调用浏览器的所见即所得这种方式去打印。

      4.页面上有个隐藏的模版,规定表格、标题、汇总信息的样式,并给定Id,或者Class,以便后续Jquery取得时候比较方便(后面我贴源码出来)。

      5.先把整个表格都展示出来,给定它宽度(A3/A4纸的宽度)之后,它的每一行的高度就确定了。

      6.这时候去遍历这个表格,可以把每一行的高度都取出来,循环的累加它,当高度超过纸张高度时,就记录下来这个开始行数(startLine)和结束行数(endLine),然后Jquery创建一个表格,从步骤4的表格中,把它的表头取出来,Append到新创建的表格中,然后根据开始行数和结束行数,把这些tr取出来,也Append到新创建的表格中。

      7.从模板中取出来标题、汇总信息等的模版,然后把它替换成想要的内容之后,append到上面的表格的前后。

      8.打印设置纸张大小思路:给个打印设置的弹出层,上面有A3/A4两个单选按钮,选完,点击页面上的确定按钮,我把这个选中值存到cookie里面,打印的时候,从cookie里面取出来,然后去给定纸张的高度和宽度。

    以上就是整体的思路,下面贴代码(注:css其实也是蛮重要的,但是css前面不是我写的,后面我忘记改了哪些东西了,所以贴出来也没卵用)。

    1.打印所使用的HTML模板

     1    <!--打印设置页面开始-->
     2     <div id="print-setting" style="display: none;">
     3         <table cellpadding="0" cellspacing="0" style="margin:20px auto 0px auto;">
     4             <tbody>
     5             <tr>
     6                 <td align="right"  valign="top">纸张大小:</td>
     7                 <td align="left" >
     8                    <input type="radio" name="paper_size" value="A3">
     9                    <label for="radiolist1-0">A3</label>
    10                    <input type="radio" name="paper_size" value="A4">
    11                    <label for="radiolist1-0">A4</label>
    12                 </td>
    13             </tr>
    14         </tbody>
    15         </table>
    16     </div>
    17     <!--打印设置页面结束-->
    18     <!-- 页面打印功能开始 -->
    19     <div id="print-content" class="print-content" style="display: none;  1000pt;">
    20         <!--A3:700pt A4:1000pt-->
    21         <div class="header" id="header">
    22             <div>
    23                 <h2>
    24                     样本出库交接单</h2>
    25                 <%--<div id="action-buttons" class="noPrint" >
    26         <input onclick="grid_Print()" type="button" value="&nbsp;&nbsp;打印&nbsp;&nbsp;" class="btn" id="showPrintButton"/>
    27         </div>--%>
    28             </div>
    29             <!-- 页面顶部信息 -->
    30             <div class="headInfo" id="headerInfo">
    31                 <span class="floatRight">&nbsp;&nbsp;&nbsp;记录总数:50 </span>
    32             </div>
    33         </div>
    34         <!-- 页面记录信息 -->
    35         <table class="Printtable" id="tabContent" style="display: none;">
    36             <thead>
    37             </thead>
    38             <tbody>
    39             </tbody>
    40         </table>
    41         <!-- 页码信息 -->
    42         <div class="signatureArea" id="footerInfo">
    43             <span class="floatRight pageNum">1/1</span>
    44         </div>
    45     </div>
    46     <!-- 页面打印功能结束 -->
    打印模版

    2.jquery.printTable.js,这个是网上找的,我改了一些,它默认里面的总页数算法是有问题的,我做了调整,我还新增了列宽的指定等,具体我也记不清了,有兴趣的可以对比一下,我完了以附件的形式上传这个js插件。

      1 /**
      2  * jquery 表格打印插件
      3  *
      4  * 作者: LiuJunGuang
      5  * 日期:2013年6月4日
      6  * 分页样式(需要自定义):
      7  * @media print {
      8  *    .pageBreak { page-break-after:always; }
      9  * } 
     10  * 使用例子:
     11  *  $(function(){
     12  *        $("#tabContent").printTable({
     13  *         mode          : "rowNumber",
     14  *         header        : "#headerInfo",
     15  *         footer        : "#footerInfo",
     16  *         pageNumStyle  : "第#p页/共#P页",
     17  *         pageNumClass  : ".pageNum",
     18  *         pageSize      : 10
     19  *        });
     20  *   });
     21  *  注意事项:
     22  *      使用时注意表格中要使用 thead 和 tbody区分出标题头与表格内容,否则可能出现错误
     23  * 
     24  * 参数说明:
     25  *  options are passed as json (json example: { rowHeight : "rowHeight", header : ".tableHeader",})
     26  *
     27  *  {OPTIONS}        | [type]    | (default), values            | Explanation
     28  *  ---------------- | --------- | -----------------------------| -----------
     29  *  @mode            | [string]  | ("rowHeight"),rowNumber      | 分页模式,按行高分页或按行数分页
     30  *  @header          | [string]  | (".tableHeader")             | 页面开始处要添加的内同
     31  *  @footer          | [string]  | (".tableFooter")             | 页面结束要添加的内容
     32  *  @pageSize        | [number]  | (30)                         | 自动分页行数,按行高分页时改参数无效
     33  *  @breakClass      | [string]  | ("pageBreak")                | 分页插入符class,需要定义分页样式
     34  *  @pageNumStyle    | [string]  | "#p/#P"                      | 页码显示样式,#p当前页,#P总页数
     35  *  @pageNumClass    | [string]  | ".pageNumClass"              | 页码class样式,用于设值(使用text方法设置) 
     36  *  @startPage       | [number]  | (1)                          | 第一页起始页码
     37  *  @pageHeight      | [number]  | (297)                        | 页面高度,单位像素
     38  *  @topMargin       | [number]  | (15)                         | 上边距高度,单位像素
     39  *  @bottomMargin    | [number]  | (15)                         | 低边距高度,单位像素
     40  */
     41 (function($) {
     42     var modes = { rowHeight : "rowHeight", rowNumber : "rowNumber" };
     43     //默认参数
     44      var defaults = { 
     45              mode          : modes.rowHeight,
     46              header        : ".tableHeader",
     47              footer        : ".tableFooter",
     48              pageSize      : 30,
     49              breakClass    : "pageBreak",
     50              pageNumStyle  : "第#p页/共#Total#页",
     51              pageNumClass  : ".pageNumClass",
     52              startPage     : 1,
     53              pageHeight    : 720, //A4纸默认在win7下Web中的dpi是96,所以A4纸在win7下的大小换算成像素应该是794×1123,这里留空白
     54              topMargin     : 50,
     55              bottomMargin  : 50,
     56              width         : 1100, //留白100px
     57              totalNumClass : "floatRight",
     58              containsId :"#print-content"
     59          };
     60      var settings = {};//global settings
     61      var rowCount = 0;//行总数
     62      var pageCount = 0;//页总数
     63      var currentPage = 0;//当前页
     64      var $header = null;//表格头
     65      var $content = null;//表格内容
     66      var $footer = null;//表格尾
     67      var $table = null;
     68      var $tbodyTr = null;
     69      var totalPageCount = 0;//总页数
     70     $.fn.printTable = function( options ) {
     71         $.extend( settings, defaults, options );
     72         $table = $(this);
     73         $tbodyTr = $table.find("tbody tr");
     74         var $container = $(settings.containsId);
     75         totalPageCount = 0;
     76         //$(settings.totalNumClass).text($tbodyTr.length);
     77         //$table.width("720pt");
     78         switch ( settings.mode ){
     79             case modes.rowHeight :
     80                 rowHeightPage();//行高分页
     81                 $container.html($container.html().replace(/#Total/g,totalPageCount)) ;
     82                 break;
     83             case modes.rowNumber :
     84                 rowNumberPage();//行数分页
     85         }
     86     };
     87     //获取页总数
     88     $.fn.printTable.getStartPage = function(startPage) {
     89         return getPageStyle(startPage , pageCount);
     90     };
     91     //行高分页
     92 function rowHeightPage() {
     93         var contentHeight =     initHeightPage();
     94         getContentColne();
     95         beginPageByHeight(contentHeight);
     96         hidenContent();
     97     }
     98     
     99     
    100     //行数分页
    101     function rowNumberPage(){
    102         initNumberPage();
    103         getContentColne();
    104         beginPageByNumber();
    105         hidenContent();
    106     }
    107     
    108     //按行高分页
    109     function beginPageByHeight(contentHeight){
    110         var totalHeight = 0;
    111         var startLine = 0;
    112         $tbodyTr.each(function(i){
    113             var cHeight = $(this).outerHeight(true);
    114             $(this).height(cHeight);
    115             if ((totalHeight + cHeight) < contentHeight) {
    116                 totalHeight += cHeight;
    117                 if(i == $tbodyTr.length -1){
    118                     newPage(i + 1);
    119                 }
    120             }else{
    121                 newPage(i);
    122             }
    123 });
    124         
    125         function newPage(index){
    126             createPage(startLine,index);
    127             currentPage++;
    128             totalPageCount++;
    129             startLine = index;
    130             totalHeight = 0;
    131         }
    132     }
    133     
    134     //初始化高度分页信息
    135     function initHeightPage(contentHeight){
    136         var contentHeight =    initContentHeight();
    137         currentPage = 0 + settings.startPage;
    138         pageCount = Math.ceil($table.find("tbody").outerHeight(true)/contentHeight) + settings.startPage - 1;//初始化总页数
    139         rowCount = $tbodyTr.length; //初始化总记录数
    140         return contentHeight;
    141     }
    142     
    143     
    144     //初始化内容高度
    145     function initContentHeight(){
    146         var headerHeight = $(settings.header).outerHeight(true);
    147         var footerHeight = $(settings.footer).outerHeight(true);
    148         $table.find("thead td").each(function(i) {
    149             var cWidth = $(this).outerWidth(true);
    150             $(this).width((cWidth / 96 * 72) + "pt");
    151         });//给表头一个宽度,但是貌似打印的时候不顶卵用
    152         var theadHeight = $table.find("thead").outerHeight(true);
    153         var tableHeight =  settings.pageHeight - settings.topMargin - settings.bottomMargin ;
    154         var tbodyHeight =  tableHeight - theadHeight- headerHeight - footerHeight;
    155         return tbodyHeight;
    156     }
    157     //初始化分页基本信息
    158     function initNumberPage(){
    159         rowCount = $tbodyTr.length;//初始化总记录数
    160         pageCount =  Math.ceil(rowCount/settings.pageSize) + settings.startPage - 1;//初始化总页数
    161         currentPage = 0 + settings.startPage;
    162     }
    163     
    164     //开始分页
    165     function beginPageByNumber(){
    166         var startLine = 1;//开始行号
    167         var offsetLine = 0;//偏移行号
    168         for(var i = settings.startPage; i <= pageCount  ;i++ ){
    169             currentPage = i;
    170             startLine = settings.pageSize* (currentPage - settings.startPage);
    171             offsetLine = (startLine + settings.pageSize) > rowCount ? rowCount : startLine + settings.pageSize;
    172             createPage(startLine,offsetLine);
    173         };
    174     }
    175      //创建新的一页
    176     function createPage(startLine, offsetLine) {
    177         var $pageHeader = $header.clone();
    178         var $pageContent = $content.clone().append(getTrRecord(startLine, offsetLine));
    179         var $pageFooter = $footer.clone();
    180         $pageFooter.find(settings.pageNumClass).text(getPageStyle(currentPage , pageCount));//页码显示格式
    181         if(offsetLine == rowCount){
    182             $table.before($pageHeader).before($pageContent).before($pageFooter);
    183         }else{
    184             $table.before($pageHeader).before($pageContent).before($pageFooter).before(addPageBreak());
    185 }
    186     }
    187     
    188     //添加分页符
    189     function addPageBreak(){
    190         return "<div class='"+settings.breakClass+"'></div>";
    191     }
    192     
    193     //获取分页样式
    194     function getPageStyle(currentPage , pageCount){
    195         var numStr = settings.pageNumStyle;
    196          numStr = numStr.replace(/#p/g,currentPage);
    197          //numStr = numStr.replace(/#P/g,pageCount);
    198          return numStr;
    199     }
    200 
    201 
    202     //获取记录
    203     function getTrRecord(startLine,offsetLine){
    204         return $tbodyTr.clone().slice(startLine,offsetLine);
    205     }
    206     //获取内容
    207     function getContentColne(){
    208         $header = $(settings.header).clone().removeAttr("id");
    209         $content = $table.clone().find("tbody").remove().end().removeAttr("id");
    210         $footer = $(settings.footer).clone().removeAttr("id");
    211     }
    212     //隐藏原来的数据
    213     function hidenContent(){
    214         $(settings.header).hide();
    215         $table.hide();
    216         $(settings.footer).hide();
    217     }
    218 })(jQuery);    
    Jquery.printTable.js

    3.打印预览的实现js

      1  var win = null;
      2        // var winPrintSetting = null;
      3         //打印预览函数
      4         function grid_PrintView() {
      5             if (win) {
      6                 win.show();
      7                 return;
      8             }
      9             var grid = $(".listgrid:first").ligerGrid();
     10             //            var oldpageSize = grid.options.pageSize;
     11             //            grid.options.pageSize = grid.filteredData.Rows.length;
     12             //            grid.reload();
     13 
     14             $(".Printtable:gt(0)").remove();
     15             $(".header:gt(0)").remove();
     16             $(".headInfo:gt(0)").remove();
     17             $(".signatureArea:gt(0)").remove();
     18             $(".header  h2").text(TABData[0].标题);
     19             $(".headInfo .floatRight").text("记录总数:" + grid.currentData.Rows.length);
     20            $(".Printtable:last").find("thead").html("");
     21             $(".Printtable:last").find("tbody").html("");//清空第一个表格的thead和tbody
     22             $(".Printtable:last thead").append($(".l-grid2  .l-grid-header-inner  tbody")[0].innerHTML);
     23             $(".Printtable:last tbody").append($(".l-grid2  .l-grid-body-table tbody")[0].innerHTML);//重新把所有的数据给到这个表格
     24             $(".Printtable:last *").removeAttr("class");
     25             $(".Printtable:last *").removeAttr("style");//清理掉样式
     26             $(".header").show();
     27             $("#tabContent").show();
     28             win = $.ligerDialog.open(
     29         { height: 794, target: $("#print-content"),  1090, showMax: true, showToggle: true, showMin: true, isResize: true, modal: false, title: '打印预览   <input onclick="grid_Print()" type="button" value="&nbsp;&nbsp;打印&nbsp;&nbsp;" class="btn" id="showPrintButton">&nbsp;&nbsp; <input onclick="PrintSetting()" type="button" value="打印设置" class="btn" id="printSetting"/> ', slide: true });
     30             win.max();
     31             ChangePages();
     32         }
     33 //把一个连起来的表格拆分
     34         function ChangePages() {
     35             var height = 930;
     36             var paper_size = $.cookie('paper_size');
     37             if (paper_size == 'A4') {
     38                 height = 580;
     39                 $(".print-content").width("700pt");
     40             } else {
     41                 height = 930;
     42                 $(".print-content").width("1000pt");
     43             }
     44             $(".Printtable:last").printTable({
     45                 mode: "rowHeight",
     46                 header: "#header",
     47                 //footer: "#footerInfo",signatureArea
     48                 footer: "#footerInfo",
     49                 pageNumStyle: "第#p页/共#Total页",
     50                 pageNumClass: ".pageNum",
     51                 pageHeight: height, //A4:580 ,A3 930
     52                 startPage: 1,
     53                 totalNumClass: ".floatRight",
     54                 containsClass: "#print-content"
     55             });
     56         }
     57         //改变打印纸大小时
     58         function ChangePaper() {
     59           var grid = $(".listgrid:first").ligerGrid();
     60             $(".Printtable:gt(0)").remove();
     61             $(".header:gt(0)").remove();
     62             $(".signatureArea:not(:last)").remove();//清理当前已经分页分好的表格,把除了第一个表格外的所有表格都干掉
     63             $(".header  h2").text(TABData[0].标题);
     64             $(".headInfo .floatRight").text("记录总数:" + grid.currentData.Rows.length);
     65             $(".pageBreak").remove();
     66             $(".Printtable:first").find("thead").html("");
     67             $(".Printtable:first").find("tbody").html("");//清空第一个表格的thead和tbody
     68             $(".Printtable:first thead").append($(".l-grid2  .l-grid-header-inner  tbody")[0].innerHTML);
     69             $(".Printtable:first tbody").append($(".l-grid2  .l-grid-body-table tbody")[0].innerHTML);//重新把所有的数据给到这个表格
     70             $(".Printtable:first *").removeAttr("class");
     71             $(".Printtable:first *").removeAttr("style");//清理掉样式
     72             $(".header").show();
     73             $(".signatureArea").show();
     74             ChangePages();
     75         }
     76 
     77         var winPrintSetting = null;
     78         //纸张大小设置
     79         function PrintSetting() {
     80             var paper_size = $.cookie('paper_size');
     81             if (paper_size) {
     82                 $("input[name='paper_size'][value='" + paper_size + "']").attr("checked", true);
     83             } else {
     84                 $.cookie('paper_size', 'A3', { expires: 30 });
     85                 $("input[name='paper_size'][value='A3']").attr("checked", true);
     86             }
     87             win.min();
     88            
     89             if (winPrintSetting) {
     90                 winPrintSetting.show();
     91             } else {
     92                 winPrintSetting = $.ligerDialog.open({
     93                     target: $("#print-setting"),
     94                     height: 200,
     95                      300,
     96                     modal: true,
     97                     title: "打印设置",
     98                     allowClose: false,
     99                     isHidden:true,
    100                     buttons: [{ text: '确定', onclick: function (item, dialog) {
    101                         var paperSize = $("[name=paper_size]:checked").val();
    102                         $.cookie('paper_size', paperSize, { expires: 30 });
    103                             win.max();
    104                             win.active();
    105                             ChangePaper();
    106                             dialog.hide();
    107                     }
    108                     }, { text: '取消', onclick: function (item, dialog) {
    109                         win.max();
    110                         win.active();
    111                         dialog.hide();
    112                     }
    113                     }]
    114                 });
    115             }
    116            
    117         }
    打印预览的展示,调整纸张大小

    4.没了

    注意事项:改变纸张之后调整现有页面的宽度、高度的时候,记得把现有的DOM都给清掉,只留一个模版的table,然后重新来。指定宽度高度的时候,能用pt的就用pt,实在用不了的再用px,哪怕用个mm,cm都比px强,因为打印机最后认的是长度,而不是像素点,建议页面上所有的字体大小都用pt来指定。

    在谷歌浏览器中,使用默认页边距的情况下,A3、A4纸比较合适的尺寸:

    A3:1000pt *930px

    A4:700pt*580px

    这个因为宽度是你用jquery去指定的,所以能用pt去指定,但是你在分页时算高度时,用Jquery获取出来只能获取到像素,所以,这就是为什么要用奇葩的pt*px这种组合的原因。这样子反正我的是大部分没有什么问题,如果不行稍微微调一点就可以了

    这是我网上找的Jquery.printTable.js

    http://files.cnblogs.com/files/baiyunchen/jquery-printTable1.0.zip

     效果图N张:

  • 相关阅读:
    hdu 2.2.4 Wolf and Rabbit 解题心得
    概率(经典问题) 解题心得
    POJ2250:Compromise(LCS) 解题心得
    POJ 3903 Stock Exchange 解题心得
    2015 HUAS Summer Trainning #5~E
    2015 HUAS Summer Trainning #5~A
    015 HUAS Summer Contest#3~A
    2015 HUAS Summer Trainning #4~B
    2015 HUAS Summer Contest#3~E
    2015 HUAS Summer Contest#3~B
  • 原文地址:https://www.cnblogs.com/baiyunchen/p/4794134.html
Copyright © 2011-2022 走看看