转 自网络
Web开发人员都会面临一个共同的难题,那就是打印。的确,相对于Windows桌面应用程序来讲,Web应用程序的打印有种种限制,技术人员在项目开发过程中经常会遇到用户这样或那样的需求. 做过桌面应用开发的人都会非常熟悉水晶报表、Active Report之类的报表控件,它们不仅有简单灵活的设计界面,更具有非常强大的报表功能,能满足各种报表的打印需求。而Web应用则因为其特殊的呈现方式,只能寻求其他的解决方案。现在我们来分析一下目前已经成形的Web打印方案:
现有的Web打印控制技术分成几种方案:
一.自定义控件完成打印
利用IE 自带的WebBrowser 控件实现打印
利用第三方控件实现打印
1、 自定义控件方式
自定义控件方式就是利用VB 或VC 等工具生成COM 组件,用定义好的打印格式来分析打印源文件从而实现打印。只有将生成的组件下载并注册到客户机上,才能实现在客户端的
打印。
难点主要是定义打印格式、如何来分析打印源文件。现有的比较好的方法是利用XML 技术来全面的解决问题,利用XML 可以非常容易地定义打印目标的文本、表格等内容的格式。
但对程序员的开发要求高,难度比较大。
2、利用WebBrowser 实现Web打印
WebBrowser是IE 内置的浏览器控件,无需用户下载。本文档所讨论的是有关IE6.0 版本 的WebBrowser 控件技术内容。与其相关的技术要求有:打印文档的生成、页面设置、打印操作的实现等几个环节。
(一)、打印文档的生成
1、客户端脚本方式
客户端脚本分为VBScript、JavaScript、JScript 几种脚本语言。在IE 下开发应用使用的语法为JScript 的语法,由于它和JavaScript 几乎没有什么区别,所以也可以称其为JavaScript(下面简写为JS)。一般情况下,主要使用JS 来实现DOM 文档的分析,DOM 为微软提 出的一种Web文档模型,主要用来实现Web脚本编程。
利用JS 可以分析源页面的内容,将欲打印的页面元素提取出来,实现打印。通过分析源文档的内容,可以生成打印目标文档。
优点:客户端独立完成打印目标文档的生成,减轻服务器负荷;
缺点:源文档的分析操作复杂,并且源文档中的打印内容要有约定;
2、服务器端程序方式
服务器端程序方式,主要是利用后台代码从数据库中读取打印源,生成打印目标文档。当的页面生成时,还应适当考虑使用CSS 来实现强制分页控制。
优点:可以生成内容非常的丰富的打印目标文档,目标文档的内容的可控性强。由于打印 内容是从数据库中获取的,所以生成操作相对简单;
缺点:服务器端负载比较大;
(二)、页面设置
页面设置主要是指设置打印文档的页边距、页眉、页脚、纸张等内容。页面设置将直接影响到打印文档版面的生成效果,所以它和打印文档的生成有着密切的关系。比如:表格的
行数、大小、位置、字体的大小等。
现有的技术是利用IE6.0 内置的打印模板方式来控制页面设置,其可以对打印目标文档产生非常大的影响。打印模板可以控制页边距、页眉、页脚、奇偶页等内容,并可以将用户的设置取得,还可以将设置发送到服务器端。
打印模板技术可以自定预览窗口和打印格式,最大限度地影响目标文档和打印效果。
(三)、打印操作的实现
此功能的实现主要是利用WebBrowser控件的函数接口来实现打印、打印预览(默认的)、
页面设置(默认的)。
<object ID='WebBrowser1' WIDTH=0 HEIGHT=0
CLASSID='CLSID:8856F961-340A-11D0-A96B-00C04FD705A2'>
//打印
WebBrowser1.ExecWB(6,1);
//打印设置
WebBrowser1.ExecWB(8,1);
//打印预览
WebBrowser1.ExecWB(7,1);
3、 一个实例项目采用的打印方案
服务器端程序方式、打印预览接口调用, 下面为例, 主要参考项目中的:
pageErrorPrint.aspx.vb 文件
主调用页
function PrintPage(iPageIndex,strQuery)
{
var strURL;
strURL = "PageErrorPrint.aspx?PageIndex=" + iPageIndex + "&QueryString=" +
strQuery;
winPrint=window.open(strURL,"","left=2000,top=2000,fullscreen=3");
}
打印页HTML 源中的预览控制
<SCRIPT language="javascript">
document.write("<object ID='WebBrowser' WIDTH=0 HEIGHT=0
CLASSID='CLSID:8856F961-340A-11D0-A96B-00C04FD705A2'></object>");
WebBrowser.ExecWB(7,1);
window.opener=null;
window.close();
</SCRIPT>
程序头
'首先声明表格容器
Protected WithEvents phContainer As System.Web.UI.WebControls.PlaceHolder
'每个表格中的记录数量
Private Const ItemPerTable As Integer = 20
关键的实现部分
'创建一个符合打印要求的表格
tabPagePrint = NewPrintTable()
'将表头添加到此表格中
Call AddTableTitle(tabPagePrint)
'初始化记录器
i = 0
iItemIndex = iStartPoint
For Each clsItem In clsAllData.ErrorCollection
If i > 0 And i Mod ItemPerTable = 0 Then
'添加表格控件到页面中
phContainer.Controls.Add(tabPagePrint)
'在页面中添加一个换行符
Call AddPageBreak()
'创建新一轮的表格
tabPagePrint = NewPrintTable()
Call AddTableTitle(tabPagePrint)
End If
'将记录添加到表格中
Call AddItemToTable(iItemIndex, tabPagePrint, clsItem)
iItemIndex = iItemIndex + 1
i = i + 1
Next
'添加表格控件到页面中
phContainer.Controls.Add(tabPagePrint)
支持函数
'功能:添加页的换行符
Private Sub AddPageBreak()
Dim ltBreak As LiteralControl
ltBreak = New LiteralControl("<p style='page-break-before:always'>")
phContainer.Controls.Add(ltBreak)
End Sub
二、利用IE自身打印
这种方式比较简单,也常用的打印方式,只需要将报表页面设计好,用户通过IE菜单中的打印功能完成打印。优点是简单,容易实现,缺点是不灵活,不能控制分页,不能控制好页眉和页脚。
三、将报表导出成Word,Excel或PDF形式打印
这种方式需要将页面导出成Office文档或pdf,最低的要求是客户端已经安装用以打开Word、Excel或Pdf文档的软件。这种方式可以通过水晶报表组件或其他一些第三方控件非常容易地实现。导出成Pdf形式后打印质量和效果都很好,导出成Word或Excel后用户可以自定义打印的内容和格式。
总之,现有的打印方案各有所长,在开发过程中应根据用户的需求作选择,利用IE打印简单,容易实现,在用户需求简单或打印内容较少的情况下采用此方案比较适宜。利用自定义控件打印可以实现完全自定义,但需要较高的技术要求和开发周期。利用导出的方式则可以满足用户需要一点自定义或打印内容有多页的需求。
先给一个简单实用的方式(可以打印多页,控制分页,隐藏非打印项目)
<!--语言无关 保存成 .HTML 看看-->
<html>
<head>
<meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
<title>看看</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<!--media=print 这个属性可以在打印时有效-->
<style media=print>
.Noprint{display:none;}
.PageNext{page-break-after: always;}
</style>
<style>
.tdp
{
border-bottom: 1 solid #000000;
border-left: 1 solid #000000;
border-right: 0 solid #ffffff;
border-top: 0 solid #ffffff;
}
.tabp
{
border-color: #000000 #000000 #000000 #000000;
border-style: solid;
border-top-width: 2px;
border-right-width: 2px;
border-bottom-width: 1px;
border-left-width: 1px;
}
.NOPRINT {
font-family: "宋体";
font-size: 9pt;
}
</style>
</head>
<body >
<center class="Noprint" >
<p>
<OBJECT id=WebBrowser classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height=0 width=0>
</OBJECT>
<input type=button value=打印 onclick=document.all.WebBrowser.ExecWB(6,1)>
<input type=button value=直接打印 onclick=document.all.WebBrowser.ExecWB(6,6)>
<input type=button value=页面设置 onclick=document.all.WebBrowser.ExecWB(8,1)>
</p>
<p> <input type=button value=打印预览 onclick=document.all.WebBrowser.ExecWB(7,1)>
<br/>
</p>
<hr align="center" width="90%" size="1" noshade>
</center>
<table width="90%" border="0" align="center" cellpadding="2" cellspacing="0" class="tabp">
<tr>
<td colspan="3" class="tdp">第1页</td>
</tr>
<tr>
<td width="29%" class="tdp"> </td>
<td width="28%" class="tdp"> </td>
<td width="43%" class="tdp"> </td>
</tr>
<tr>
<td colspan="3" class="tdp"> </td>
</tr>
<tr>
<td colspan="3" class="tdp"><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="50%" class="tdp"><p>这样的报表</p>
<p>对一般的要求就够了。</p></td>
<td> </td>
</tr>
</table></td>
</tr>
</table>
<hr align="center" width="90%" size="1" noshade class="NOPRINT" >
<!--分页-->
<div class="PageNext"></div>
<table width="90%" border="0" align="center" cellpadding="2" cellspacing="0" class="tabp">
<tr>
<td class="tdp">第2页</td>
</tr>
<tr>
<td class="tdp">看到分页了吧</td>
</tr>
<tr>
<td class="tdp"> </td>
</tr>
<tr>
<td class="tdp"> </td>
</tr>
<tr>
<td class="tdp"><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="50%" class="tdp"><p>这样的报表</p>
<p>对一般的要求就够了。</p></td>
<td> </td>
</tr>
</table></td>
</tr>
</table>
</body>
</html>
简单懂得 HTML CSS 即可。
下面样式只在打印时有用 <style media=print>
<style media=print>
.Noprint{display:none;}
.PageNext{page-break-after: always;}
</style>
WebBrowser 控件对象。只要是 win98 以上版本都有。
其实配合“分页样式表”,和 HTML表格 一般的打印都可以实现的。
如果想对 非Windows平台用户使用。
请去掉下面这些:
<center class="Noprint" >
<p>
<!--最主要是这个-->
<OBJECT id=WebBrowser classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height=0 width=0>
</OBJECT>
<input type=button value=打印 onclick=document.all.WebBrowser.ExecWB(6,1)>
<input type=button value=直接打印 onclick=document.all.WebBrowser.ExecWB(6,6)>
<input type=button value=页面设置 onclick=document.all.WebBrowser.ExecWB(8,1)>
</p>
<p> <input type=button value=打印预览 onclick=document.all.WebBrowser.ExecWB(7,1)>
<br/>
</p>
<hr align="center" width="90%" size="1" noshade>
</center>
分页是由 CSS中的 page-break-after的always属性实现的
always就是在对象后设置一个分页符。
//也许有些地方大家不太明白我解释一下其实很简单
<!--media=print只有在打印中 有效-->
<style media=print>
<!--display:none 隐藏加上,上面的 media=print 就是在打印时隐藏-->
.Noprint{display:none;}
<!--分页-->
.PageNext{page-break-after: always;}
</style>
<!--网页中分页-->
<div class="PageNext"></div>