amp@java

amplifier's java blog

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  98 随笔 :: 0 文章 :: 228 评论 :: 0 Trackbacks

要把一个长表格打印出来,要做到正确分页,直接用HTML生成表格是不能满足要求的:
1、如果把整个表格放在一页,在打印时再自动分页,则有可能在某一表格行中间分页,而且只能有一个表格头,不能每页一个,因为你不知道会在哪里分页;
2、如果按照固定的行数分页,由于每行的高度不一样,就会造成有的页不能填满,有的却太满自动分页了。

原来考虑过一种方法:
利用Javascript动态生成表格,每次往表格的最后插入一行,然后检查表格高度,如果高度超过了一页的最大高度,则把这一行删除,新建一个表格,把这一行插入到新的表格里面,如此循环,直到全部行插入完毕。但是,利用table的height属性、style.height属性都得不到表格的实际高度(只有设置了height属性、style的height属性才能取得这两个值,但只是设置值,并不是实际值),于是就只能放弃了。

后来仔细查看了table的dom属性,才知道它还有clientHeight,offsetHeight等属性,这两个才是表格的真正高度,它们之间的区别可看这里:
http://developer.mozilla.org/cn/docs/DOM:element.clientHeight
http://developer.mozilla.org/en/docs/DOM:element.offsetHeight
更直观的可以看这里:
http://msdn.microsoft.com/library/default.asp?url=/workshop/author/om/measuring.asp


简单地说,clientHeight就是不包含border的高度,offsetHeight就是连border的高度。对于要打印的表格,border一般只有2px,所以用clientHeight和offsetHeight区别不大。

构建这个页面需要用到的:

table的insertRow(),deleteRow()方法,用来给表格增加、删除一行(tr);
tr的insertCell()方法,用来给一行加入一格(td);
td的innerText属性,用来给一格加入内容。

CSS分页要用到page-break-before:always(或page-break-after:aways)的样式,遇到使用了该样式的标签,就会在标签前面(或后面)强制分页,于是可以在两个表格之间加一个这样的分页。
为了显示而不打印,还要用到<style>标签的media属性,当设置
<style media="print">
.noprint {display:none}
</style>
时,用了noprint作为class的标签就只会显示而不打印出来。

对于IE,还可以使用WebBrowser控件,弹出“页面设置”窗口、“打印预览”窗口、直接打印等功能。对于其他浏览器,则只能调用window.print()函数了。

JSF生成的中文都是用&#unicode;来表示的,其中unicode是中文字符的UNICODE编码,通过innerText生成表格内容时,必须把这些东西转换成真正的中文,否则会直接把这些符号插入到表格中,惨不忍睹。javascript里有个String.fromCharCode()函数可以把Unicode编码转换成字符。另外,通过innerHTML加入内容也可把这些编码正常显示出来,但需要escape XML,以免把内容当作HTML标签渲染。




posted on 2006-11-07 10:11 amp@java 阅读(9063) 评论(8)  编辑  收藏 所属分类: JSF

评论

# re: Web表格打印页面的生成 2006-11-08 02:18 emu
1、如果把整个表格放在一页,在打印时再自动分页,则有可能在某一表格行中间分页,而且只能有一个表格头,不能每页一个,因为你不知道会在哪里分页;
2、如果按照固定的行数分页,由于每行的高度不一样,就会造成有的页不能填满,有的却太满自动分页了。

ie在打印的时候不但可以在每页自动添加,还可以自动添加表脚,当然还可以自动判断长度分页,实现这些都不需要半点脚本。请看这个例子(使用了内置打印控件来预览,如果被浏览器禁止了需要手工使用打印预览功能或者打印出来)

<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
function pageSetup(){try{WB.ExecWB(8,1)}catch(e){alert("您的浏览器不支持此功能")}}
function preview(){try{WB.ExecWB(7,1)}catch(e){alert("您的浏览器不支持此功能")}}
</SCRIPT>
<style>
td,th{border-bottom:1px solid black;width:70px}
thead{display:table-header-group}
tfoot{display:table-footer-group}
</style>
</HEAD>
<BODY>
<OBJECT classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height=0 id=WB width=0 VIEWASTEXT></OBJECT>
<TABLE cellspacing=0 align=center>
<thead><th> 姓 名 </th><th> 地 址 </th><th> 籍 贯 </th><th>毕业学校</th><th> 年 龄 </th><th> 性 别 </th><th> 婚 否 </th></thead>
<tbody align=center>
<SCRIPT LANGUAGE="JavaScript">
<!--
var n=100;
for(var i=0;i<n;i++){
document.write("<tr>");
for(var j=0;j<7;j++)
document.write("<td>"+Math.round(Math.random()*10000)+
(Math.random()>.05?"":"<br>"+Math.round(Math.random()*10000))+
(Math.random()>.02?"":"<br>"+Math.round(Math.random()*10000))+
(Math.random()>.01?"":"<br>"+Math.round(Math.random()*10000))+
"</td>");
document.write("</tr>");
}
//-->
</SCRIPT>
</tbody>
<tfoot><th colspan=7 align=center style="width:100%">这 是 一 个 测 试</th></tfoot>
</TABLE>
</BODY>
<SCRIPT LANGUAGE="JavaScript">
preview();
</SCRIPT>
</HTML>

例子中特意使用脚本构造了随机高度的行。  回复  更多评论
  

# re: Web表格打印页面的生成 2006-11-08 02:25 emu
这个例子在firefox下面使用的时候页脚有显示不完整的现象。不知道是否firefox的打印预览功能的bug。为tbody添加上display: table-row-group样式后有一些改观但是没有完全解决。  回复  更多评论
  

# re: Web表格打印页面的生成 2006-11-08 22:04 amp@java
谢谢,我现在才知道还有display:table-header-group这个样式。

不过不用脚本生成表格的话还是有可能会把行拦腰截断,上面那个不截断,是因为行高比较小,我稍稍改了一下每行的内容,就出现了:

<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
function pageSetup(){try{WB.ExecWB(8,1)}catch(e){alert("您的浏览器不支持此功能")}}
function preview(){try{WB.ExecWB(7,1)}catch(e){alert("您的浏览器不支持此功能")}}
</SCRIPT>
<style>
td, th{border-bottom:1px solid black;width:70px}
thead{display:table-header-group}
tfoot{display:table-footer-group}
</style>
</HEAD>
<BODY>
<OBJECT classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height=0 id=WB width=0 VIEWASTEXT></OBJECT>
<TABLE cellspacing=0 align=center border=1>
<thead><th> 姓 名 </th><th> 地 址 </th><th> 籍 贯 </th><th>毕业学校</th><th> 年 龄 </th><th> 性 别 </th><th> 婚 否

</th></thead>
<tbody align=center>
<SCRIPT LANGUAGE="JavaScript">
<!--
var n=100;
for(var i=0;i<n;i++){
document.write("<tr>");
for(var j=0;j<7;j++)
document.write("<td>有可能在某一表格行中间分页在某一表格行中间分页</td>");
document.write("</tr>");
}
//-->

</SCRIPT>
</tbody>
<tfoot><th colspan=7 align=center style="width:100%">这 是 一 个 测 试</th></tfoot>
</TABLE>
</BODY>
<SCRIPT LANGUAGE="JavaScript">
preview();
</SCRIPT>
</HTML>  回复  更多评论
  

# re: Web表格打印页面的生成 2006-11-09 01:27 emu
实际应用当中,就要考虑行高是否真的这么自由,分行是否真的这么不可接受了了。比如说,行高超过了一页怎么办,不得不分行的时候是否还需要保持每页的表头表脚,不用样式而用脚本的话,表头表脚要如何正确的呈现?

<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
function pageSetup(){try{WB.ExecWB(8,1)}catch(e){alert("您的浏览器不支持此功能")}}
function preview(){try{WB.ExecWB(7,1)}catch(e){alert("您的浏览器不支持此功能")}}
</SCRIPT>
<style>
td, th{border-bottom:1px solid black;width:70px}
thead{display:table-header-group}
tfoot{display:table-footer-group}
</style>
</HEAD>
<BODY>
<OBJECT classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height=0 id=WB width=0 VIEWASTEXT></OBJECT>
<TABLE cellspacing=0 align=center border=1>
<thead><th> 姓 名 </th><th> 地 址 </th><th> 籍 贯 </th><th>毕业学校</th><th> 年 龄 </th><th> 性 别 </th><th> 婚 否 </th></thead>
<tbody align=center>
<SCRIPT LANGUAGE="JavaScript">
document.write("<tr>");
for(var j=0;j<7;j++)
document.write("<td>"+(new Array(10).join("有可能在某一表格行中间分页在某一表格行中间分页"))+"</td>");
document.write("</tr>");
</SCRIPT>
</tbody>
<tfoot><th colspan=7 align=center style="width:100%">这 是 一 个 测 试</th></tfoot>
</TABLE>
</BODY>
<SCRIPT LANGUAGE="JavaScript">
preview();
</SCRIPT>
</HTML>   回复  更多评论
  

# re: Web表格打印页面的生成 2006-11-09 09:32 amp@java
行高超过一页的情况是极少的,但一般3-4行文字的高度是经常有的,这样的高度就足以造成一行分两页,我的应用中就遇到过,打印出来有点奇怪。使用脚本生成表格之后,每页一个完整的表格,而且基本能满一页,看起来舒服点。

脚本可以生成任意HTML,当判断表格高度满一页的时候,就利用 page-break-before:always 样式生成一个分页符,再新建一个表格,这个表格就在下一页了,可以通过脚本往里面加入新的内容,表格的表头和表脚都可以用脚本生成。另外,用innerHTML就可以在某标签范围内加入任意HTML语句,所以还可以生成其他的内容。  回复  更多评论
  

# re: Web表格打印页面的生成 2008-01-08 12:09 as
怎么知道打印页面的高度啊?  回复  更多评论
  

# re: Web表格打印页面的生成[未登录] 2008-01-13 00:29 amp@java
@as
一般都是A4纸,所以就按照A4纸的高度来定  回复  更多评论
  

# re: Web表格打印页面的生成 2008-01-24 14:25 msung
amp@java 你好,我遇到这个问题很久,由于数据太多,一个td里的东西在一个页面下根本放不下,就会分开俩页打,这就造成tr分成俩页,特别难看,下面是我的代码。你有什么好方法。能避免这准分页。

<#assign ww=JspTaglibs["/WEB-INF/webwork.tld"] />
<html>
<style type="text/css">
<!--
a { font-family: "宋体"; font-size: 10pt; text-decoration: none; }
a:link { font: 12pt "宋体"; color: #336699; text-decoration: none; }
a:active { font: 12pt "宋体"; color: #336699; text-decoration: none; }
a:visited { font: 12pt "宋体"; color: #336699; text-decoration: none; }
a:hover { font: 12pt "宋体"; color: #FF4333; text-decoration: none; }
td { font-size:12pt }
.td_css {
BORDER-RIGHT: #000000 1px solid;
BORDER-BOTTOM: #000000 1px solid;
}

.table_css{
BORDER-top: #000000 1px solid;
BORDER-left: #000000 1px solid
}
.prin{
font: 15pt "宋体"; color: #FFFFF; text-decoration: none;
}
.pageEnd {page-break-before:always}
-->
</style>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>计划信息打印</title>
<meta content="no-cache">
<script language='javascript' src='../../scripts/checkform.js' ></script>
<script language="javascript" src="../../scripts/Calendar.js"></script>
<script language="javascript" src="../include/Common.js"></script>
<script type="text/javascript">

function fReturn(){
history.go(-1);
}
function select(key){
// alert(document.getElementById('PM').style.display);
findObj(key).style.display='';

}

//直接打印
function doPrint() {
//alert(findObj('antable').clientHeight);
//alert(document.all.table.rows(0).cells(0).offsetHeight) //这个也是查询指定对象的高度。
bdhtml=window.document.body.innerHTML;
sprnstr="<!--startprint-->";
eprnstr="<!--endprint-->";
prnhtml=bdhtml.substr(bdhtml.indexOf(sprnstr)+17);
prnhtml=prnhtml.substring(0,prnhtml.indexOf(eprnstr));
window.document.body.innerHTML=prnhtml;
var table1=document.all.tags("table") //找出所有table
//alert(table1);
var tabnumber=table1.length; //table的个数
//alert(tabnumber);
for(var i=0;i<=tabnumber;i++){ //循环遍历table
//alert(table1[i].id); //输出table的id
//下面是找出table的id为table的table,并且查出table的高度,如果他的高度高于899,就给它里面的id为‘one’的对象的高度赋值为850
//并且给id为pp的对象插入pageEnd的样式,然后跳出循环。
if(table1[i].id=="table"){
//var frameheight=table1[i].rows(0).cells(0).offsetHeight
var frameheight = findObj('table').clientHeight;
if(frameheight>899){
document.getElementById('one').height='850'
//alert(document.getElementById('one').height);
//alert(document.getElementById('PP').className);
document.getElementById('PP').className='pageEnd'; //插入pageEnd样式,用于俩个table的分页。
document.getElementById('two').height='850'
//alert(document.getElementById('PP').className);
}
continue;
}
if(table1[i].id=="antable"){
var frameheight = findObj('antable').clientHeight;
if(frameheight>899){
document.getElementById('three').height='850'
document.getElementById('QQ').className='pageEnd';
document.getElementById('four').height='850'
}
break;
}
}
window.print();
}

</script>

</head>
<body>
<div>
<input type="button" name="Submit" value="返回" class="button" onClick="fReturn()">
<input type="button" name="button" value="打印" class="button" onClick="doPrint()">

</div>
<!--startprint-->
<table id="table" width="95%" align="center" border="0" cellspacing="1" cellpadding="1" >
<tr>
<td colspan="4" align="center"><font size="5" face="黑体_GB2312">${(plan.month)?default('')}月份工作月报</font></td>
</tr>
<tr>
<td colspan="4" align="center" height="20"></td>
</tr>
<tr>
<td bgcolor="#FFFFFF" width="12%">部门:</td>
<td bgcolor="#FFFFFF" width="30%">&nbsp;&nbsp;${(plan.department)?default('')}</td>
<td bgcolor="#FFFFFF" width="20%" align="right">日期:</td>
<td bgcolor="#FFFFFF" width="30%" align="left">&nbsp;${(plan.mitTime)?default('')}</td>
</tr>
<tr><td colspan="4">
<table id="one" width="100%" cellpadding="1" cellspacing="0" class="table_css" bgcolor="#000000">
<tr>
<td bgcolor="#FFFFFF" class=td_css align=center width="12%" height="30">填报人&nbsp;</td>
<td bgcolor="#FFFFFF" class=td_css align=center width="30%">&nbsp;${(plan.realName)?default('')}</td>
<td bgcolor="#FFFFFF" class=td_css align=center width="20%">签发人&nbsp;</td>
<td bgcolor="#FFFFFF" class=td_css align=center width="30%">&nbsp;${(plan.checkUserid)?default('')}</td>
</tr>
<tr>
<td height="300" align="center" bgcolor=#FFFFFF class=td_css>上月计划</td>
<td align='left' valign='top' colspan='6' bgcolor=#FFFFFF class=td_css>${(plan.summarize)?default('')}&nbsp;</td>
</tr>
</table>
</td></tr>
<tr id="pp"><td colspan="4">
<table id="two" width="100%" cellpadding="1" cellspacing="0" class="table_css" bgcolor="#000000">
<tr>
<td width="13%" height="300" align="center" bgcolor=#FFFFFF class=td_css>本月计划</td>
<td align='left' valign='top' colspan='6' bgcolor=#FFFFFF class=td_css>${(plan.program)?default('')}&nbsp;</td>
</tr>
</table>
</td></tr>
</table>
</div>
<!--endprint-->
</body>
</html>
  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: