Web打印连续的表格,自动根据行高分页

时间:2023-03-09 16:24:52
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模板

    <!--打印设置页面开始-->
<div id="print-setting" style="display: none;">
<table cellpadding="0" cellspacing="0" style="margin:20px auto 0px auto;">
<tbody>
<tr>
<td align="right" valign="top">纸张大小:</td>
<td align="left" >
<input type="radio" name="paper_size" value="A3">
<label for="radiolist1-0">A3</label>
<input type="radio" name="paper_size" value="A4">
<label for="radiolist1-0">A4</label>
</td>
</tr>
</tbody>
</table>
</div>
<!--打印设置页面结束-->
<!-- 页面打印功能开始 -->
<div id="print-content" class="print-content" style="display: none; width: 1000pt;">
<!--A3:700pt A4:1000pt-->
<div class="header" id="header">
<div>
<h2>
样本出库交接单</h2>
<%--<div id="action-buttons" class="noPrint" >
<input onclick="grid_Print()" type="button" value="&nbsp;&nbsp;打印&nbsp;&nbsp;" class="btn" id="showPrintButton"/>
</div>--%>
</div>
<!-- 页面顶部信息 -->
<div class="headInfo" id="headerInfo">
<span class="floatRight">&nbsp;&nbsp;&nbsp;记录总数:50 </span>
</div>
</div>
<!-- 页面记录信息 -->
<table class="Printtable" id="tabContent" style="display: none;">
<thead>
</thead>
<tbody>
</tbody>
</table>
<!-- 页码信息 -->
<div class="signatureArea" id="footerInfo">
<span class="floatRight pageNum">1/1</span>
</div>
</div>
<!-- 页面打印功能结束 -->

打印模版

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

 /**
* jquery 表格打印插件
*
* 作者: LiuJunGuang
* 日期:2013年6月4日
* 分页样式(需要自定义):
* @media print {
* .pageBreak { page-break-after:always; }
* }
* 使用例子:
* $(function(){
* $("#tabContent").printTable({
* mode : "rowNumber",
* header : "#headerInfo",
* footer : "#footerInfo",
* pageNumStyle : "第#p页/共#P页",
* pageNumClass : ".pageNum",
* pageSize : 10
* });
* });
* 注意事项:
* 使用时注意表格中要使用 thead 和 tbody区分出标题头与表格内容,否则可能出现错误
*
* 参数说明:
* options are passed as json (json example: { rowHeight : "rowHeight", header : ".tableHeader",})
*
* {OPTIONS} | [type] | (default), values | Explanation
* ---------------- | --------- | -----------------------------| -----------
* @mode | [string] | ("rowHeight"),rowNumber | 分页模式,按行高分页或按行数分页
* @header | [string] | (".tableHeader") | 页面开始处要添加的内同
* @footer | [string] | (".tableFooter") | 页面结束要添加的内容
* @pageSize | [number] | (30) | 自动分页行数,按行高分页时改参数无效
* @breakClass | [string] | ("pageBreak") | 分页插入符class,需要定义分页样式
* @pageNumStyle | [string] | "#p/#P" | 页码显示样式,#p当前页,#P总页数
* @pageNumClass | [string] | ".pageNumClass" | 页码class样式,用于设值(使用text方法设置)
* @startPage | [number] | (1) | 第一页起始页码
* @pageHeight | [number] | (297) | 页面高度,单位像素
* @topMargin | [number] | (15) | 上边距高度,单位像素
* @bottomMargin | [number] | (15) | 低边距高度,单位像素
*/
(function($) {
var modes = { rowHeight : "rowHeight", rowNumber : "rowNumber" };
//默认参数
var defaults = {
mode : modes.rowHeight,
header : ".tableHeader",
footer : ".tableFooter",
pageSize : 30,
breakClass : "pageBreak",
pageNumStyle : "第#p页/共#Total#页",
pageNumClass : ".pageNumClass",
startPage : 1,
pageHeight : 720, //A4纸默认在win7下Web中的dpi是96,所以A4纸在win7下的大小换算成像素应该是794×1123,这里留空白
topMargin : 50,
bottomMargin : 50,
width : 1100, //留白100px
totalNumClass : "floatRight",
containsId :"#print-content"
};
var settings = {};//global settings
var rowCount = 0;//行总数
var pageCount = 0;//页总数
var currentPage = 0;//当前页
var $header = null;//表格头
var $content = null;//表格内容
var $footer = null;//表格尾
var $table = null;
var $tbodyTr = null;
var totalPageCount = 0;//总页数
$.fn.printTable = function( options ) {
$.extend( settings, defaults, options );
$table = $(this);
$tbodyTr = $table.find("tbody tr");
var $container = $(settings.containsId);
totalPageCount = 0;
//$(settings.totalNumClass).text($tbodyTr.length);
//$table.width("720pt");
switch ( settings.mode ){
case modes.rowHeight :
rowHeightPage();//行高分页
$container.html($container.html().replace(/#Total/g,totalPageCount)) ;
break;
case modes.rowNumber :
rowNumberPage();//行数分页
}
};
//获取页总数
$.fn.printTable.getStartPage = function(startPage) {
return getPageStyle(startPage , pageCount);
};
//行高分页
function rowHeightPage() {
var contentHeight = initHeightPage();
getContentColne();
beginPageByHeight(contentHeight);
hidenContent();
} //行数分页
function rowNumberPage(){
initNumberPage();
getContentColne();
beginPageByNumber();
hidenContent();
} //按行高分页
function beginPageByHeight(contentHeight){
var totalHeight = 0;
var startLine = 0;
$tbodyTr.each(function(i){
var cHeight = $(this).outerHeight(true);
$(this).height(cHeight);
if ((totalHeight + cHeight) < contentHeight) {
totalHeight += cHeight;
if(i == $tbodyTr.length -1){
newPage(i + 1);
}
}else{
newPage(i);
}
}); function newPage(index){
createPage(startLine,index);
currentPage++;
totalPageCount++;
startLine = index;
totalHeight = 0;
}
} //初始化高度分页信息
function initHeightPage(contentHeight){
var contentHeight = initContentHeight();
currentPage = 0 + settings.startPage;
pageCount = Math.ceil($table.find("tbody").outerHeight(true)/contentHeight) + settings.startPage - 1;//初始化总页数
rowCount = $tbodyTr.length; //初始化总记录数
return contentHeight;
} //初始化内容高度
function initContentHeight(){
var headerHeight = $(settings.header).outerHeight(true);
var footerHeight = $(settings.footer).outerHeight(true);
$table.find("thead td").each(function(i) {
var cWidth = $(this).outerWidth(true);
$(this).width((cWidth / 96 * 72) + "pt");
});//给表头一个宽度,但是貌似打印的时候不顶卵用
var theadHeight = $table.find("thead").outerHeight(true);
var tableHeight = settings.pageHeight - settings.topMargin - settings.bottomMargin ;
var tbodyHeight = tableHeight - theadHeight- headerHeight - footerHeight;
return tbodyHeight;
}
//初始化分页基本信息
function initNumberPage(){
rowCount = $tbodyTr.length;//初始化总记录数
pageCount = Math.ceil(rowCount/settings.pageSize) + settings.startPage - 1;//初始化总页数
currentPage = 0 + settings.startPage;
} //开始分页
function beginPageByNumber(){
var startLine = 1;//开始行号
var offsetLine = 0;//偏移行号
for(var i = settings.startPage; i <= pageCount ;i++ ){
currentPage = i;
startLine = settings.pageSize* (currentPage - settings.startPage);
offsetLine = (startLine + settings.pageSize) > rowCount ? rowCount : startLine + settings.pageSize;
createPage(startLine,offsetLine);
};
}
//创建新的一页
function createPage(startLine, offsetLine) {
var $pageHeader = $header.clone();
var $pageContent = $content.clone().append(getTrRecord(startLine, offsetLine));
var $pageFooter = $footer.clone();
$pageFooter.find(settings.pageNumClass).text(getPageStyle(currentPage , pageCount));//页码显示格式
if(offsetLine == rowCount){
$table.before($pageHeader).before($pageContent).before($pageFooter);
}else{
$table.before($pageHeader).before($pageContent).before($pageFooter).before(addPageBreak());
}
} //添加分页符
function addPageBreak(){
return "<div class='"+settings.breakClass+"'></div>";
} //获取分页样式
function getPageStyle(currentPage , pageCount){
var numStr = settings.pageNumStyle;
numStr = numStr.replace(/#p/g,currentPage);
//numStr = numStr.replace(/#P/g,pageCount);
return numStr;
} //获取记录
function getTrRecord(startLine,offsetLine){
return $tbodyTr.clone().slice(startLine,offsetLine);
}
//获取内容
function getContentColne(){
$header = $(settings.header).clone().removeAttr("id");
$content = $table.clone().find("tbody").remove().end().removeAttr("id");
$footer = $(settings.footer).clone().removeAttr("id");
}
//隐藏原来的数据
function hidenContent(){
$(settings.header).hide();
$table.hide();
$(settings.footer).hide();
}
})(jQuery);

Jquery.printTable.js

3.打印预览的实现js

  var win = null;
// var winPrintSetting = null;
//打印预览函数
function grid_PrintView() {
if (win) {
win.show();
return;
}
var grid = $(".listgrid:first").ligerGrid();
// var oldpageSize = grid.options.pageSize;
// grid.options.pageSize = grid.filteredData.Rows.length;
// grid.reload(); $(".Printtable:gt(0)").remove();
$(".header:gt(0)").remove();
$(".headInfo:gt(0)").remove();
$(".signatureArea:gt(0)").remove();
$(".header h2").text(TABData[0].标题);
$(".headInfo .floatRight").text("记录总数:" + grid.currentData.Rows.length);
$(".Printtable:last").find("thead").html("");
$(".Printtable:last").find("tbody").html("");//清空第一个表格的thead和tbody
$(".Printtable:last thead").append($(".l-grid2 .l-grid-header-inner tbody")[0].innerHTML);
$(".Printtable:last tbody").append($(".l-grid2 .l-grid-body-table tbody")[0].innerHTML);//重新把所有的数据给到这个表格
$(".Printtable:last *").removeAttr("class");
$(".Printtable:last *").removeAttr("style");//清理掉样式
$(".header").show();
$("#tabContent").show();
win = $.ligerDialog.open(
{ 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 });
win.max();
ChangePages();
}
//把一个连起来的表格拆分
function ChangePages() {
var height = 930;
var paper_size = $.cookie('paper_size');
if (paper_size == 'A4') {
height = 580;
$(".print-content").width("700pt");
} else {
height = 930;
$(".print-content").width("1000pt");
}
$(".Printtable:last").printTable({
mode: "rowHeight",
header: "#header",
//footer: "#footerInfo",signatureArea
footer: "#footerInfo",
pageNumStyle: "第#p页/共#Total页",
pageNumClass: ".pageNum",
pageHeight: height, //A4:580 ,A3 930
startPage: 1,
totalNumClass: ".floatRight",
containsClass: "#print-content"
});
}
//改变打印纸大小时
function ChangePaper() {
var grid = $(".listgrid:first").ligerGrid();
$(".Printtable:gt(0)").remove();
$(".header:gt(0)").remove();
$(".signatureArea:not(:last)").remove();//清理当前已经分页分好的表格,把除了第一个表格外的所有表格都干掉
$(".header h2").text(TABData[0].标题);
$(".headInfo .floatRight").text("记录总数:" + grid.currentData.Rows.length);
$(".pageBreak").remove();
$(".Printtable:first").find("thead").html("");
$(".Printtable:first").find("tbody").html("");//清空第一个表格的thead和tbody
$(".Printtable:first thead").append($(".l-grid2 .l-grid-header-inner tbody")[0].innerHTML);
$(".Printtable:first tbody").append($(".l-grid2 .l-grid-body-table tbody")[0].innerHTML);//重新把所有的数据给到这个表格
$(".Printtable:first *").removeAttr("class");
$(".Printtable:first *").removeAttr("style");//清理掉样式
$(".header").show();
$(".signatureArea").show();
ChangePages();
} var winPrintSetting = null;
//纸张大小设置
function PrintSetting() {
var paper_size = $.cookie('paper_size');
if (paper_size) {
$("input[name='paper_size'][value='" + paper_size + "']").attr("checked", true);
} else {
$.cookie('paper_size', 'A3', { expires: 30 });
$("input[name='paper_size'][value='A3']").attr("checked", true);
}
win.min(); if (winPrintSetting) {
winPrintSetting.show();
} else {
winPrintSetting = $.ligerDialog.open({
target: $("#print-setting"),
height: 200,
width: 300,
modal: true,
title: "打印设置",
allowClose: false,
isHidden:true,
buttons: [{ text: '确定', onclick: function (item, dialog) {
var paperSize = $("[name=paper_size]:checked").val();
$.cookie('paper_size', paperSize, { expires: 30 });
win.max();
win.active();
ChangePaper();
dialog.hide();
}
}, { text: '取消', onclick: function (item, dialog) {
win.max();
win.active();
dialog.hide();
}
}]
});
} }

打印预览的展示,调整纸张大小

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张:

Web打印连续的表格,自动根据行高分页

Web打印连续的表格,自动根据行高分页

Web打印连续的表格,自动根据行高分页