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; width: 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"), width: 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                     width: 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

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

 效果图N张:

posted @ 2015-09-09 11:28  人生无赖  阅读(4020)  评论(0编辑  收藏  举报