aspnet之web打印.docx

上传人:b****3 文档编号:3518233 上传时间:2022-11-23 格式:DOCX 页数:7 大小:20.49KB
下载 相关 举报
aspnet之web打印.docx_第1页
第1页 / 共7页
aspnet之web打印.docx_第2页
第2页 / 共7页
aspnet之web打印.docx_第3页
第3页 / 共7页
aspnet之web打印.docx_第4页
第4页 / 共7页
aspnet之web打印.docx_第5页
第5页 / 共7页
点击查看更多>>
下载资源
资源描述

aspnet之web打印.docx

《aspnet之web打印.docx》由会员分享,可在线阅读,更多相关《aspnet之web打印.docx(7页珍藏版)》请在冰豆网上搜索。

aspnet之web打印.docx

aspnet之web打印

ASP.NET之Web打印

[日期:

2007-02-18]

来源:

blog 作者:

[字体:

大中小]

做过bs开发的同志应该都深有体会,在web程序中打印不再象应用程序中那样便于控制了,web程序天生的一些特性造成了这个缺点,如:

打印机在本地,而文件确可能在服务器上;格式如何控制和定制等等。

都给我们开发中带来了很多问题,虽说有水晶报表等控件来解决但总归是不方便。

当然有了问题就会有人来研究解决,这里我先对目前流行的几种方式做个简单介绍:

1、IE直接打印

        这个不用多说,直接调用window.print或者webrower控件的ExecWB方法来打印。

方便快捷,客户端无需任何设置即可。

利用一些办法也可以实现简单的定制,比如做一个模板htm文件,然后在js中动态创建一个隐藏帧来,用脚本来生成其中的数据,再把最后的结果文件写入到隐藏帧打印处理。

如果处理的好,实际上效果也是不错。

对于简单的打印需求应该是够了。

这里我举个实际中的例子来说明这种方式:

        开发中经常需要打印一些统计的结果给用户,比如说一个常见的功能是营业报表类的打印:

操作员先输入查询条件,然后提交得到查询的结果,点击打印后,按照定义好的格式打印报表。

        我们实现上大部分情况会把查询的结果绑定到DataGrid上来,然后打印DataGrid。

这种情况的打印一般来说格式比较固定简单,确定后基本不会再作更改。

所以可以采用IE直接打印,但若直接调用window.print来打印结果页面,页面上别的无关元素也会被打印出来,页头页尾的格式也不好控制,所以采用把需要打印的数据动态写入到隐藏帧中打印的方式来实现

        代码示例:

ASP.NET中打印指定的DataGrid内容

        其中借用来自微软的一段js代码,整个js代码如下:

//以下脚本实现:

打印指定的datagrid

varvGridContent;  //DataGrid的内容

varvHeaderInfo;  //打印的表头

varvTailerInfo;  //打印的表尾

/*

目的:

在页面写入隐藏帧并打印

参数:

vDataGrid 所要打印的DataGrid句柄

备注:

 代码中调用如下

 btPrint.Attributes.Add("onclick","returnPrintDataGrid(document.all('SheetList'))");

 

 SheetList为待打印的DataGrid的ID

*/

functionPrintDataGrid(vDataGrid)

{

 PickupHeaderInfo();

  

 document.body.insertAdjacentHTML("beforeEnd",

   "");

 

 vardoc=printHiddenFrame.document;

 doc.open();

 doc.write("");

 doc.write("");

 doc.write("");

 doc.close();

 

 CreateHtmlReport(printHiddenFrame.printMe,vDataGrid);

 returnfalse;

   

}

     

/*

目的:

在隐藏帧中写入DataGrid的内容,并重写DataGrid的格式

参数:

vHideFrame隐藏帧的句柄

vDataGrid 所要打印的DataGrid句柄

备注:

*/

functionCreateHtmlReport(vHideFrame,vDataGrid)

{

 vGridContent=vDataGrid.outerHTML;

 

 //输出报表头信息及抽取过来的表格

 vardoc=vHideFrame.document;

 doc.open();

 doc.write("");

 doc.write(vHeaderInfo);

 doc.write(vGridContent);

 doc.write("");

 doc.close();

 

 

 //重新设置表格样式

 vDataGrid.borderColor="#000000";

 vDataGrid.width="100%";

 vDataGrid.style.fontFamily="Verdana";

 vDataGrid.style.fontSize="12px";

 vDataGrid.style.borderRight="1pxsolid#000000";

 vDataGrid.style.borderTop="1pxsolid#000000";

 vDataGrid.style.borderLeft="1pxsolid#000000";

 vDataGrid.style.borderBottom="1pxsolid#000000";

 vDataGrid.style.borderCollapse="collapse";

 //重新设置表格头样式

 varTBody=vDataGrid.children(0);

 TBody.children(0).style.fontWeight="bold";

 TBody.children(0).bgColor="#E7E7E7";

 //替换原表格底部的页码信息

 varpageInfo="第"+((4-3)/1+1)+"页/共"+"1"+"页    ";

}

//创建表头表尾

functionPickupHeaderInfo()

{

 try

 {

  //提取报表标题字体大小

  varReportTitleWithSizeInfo=""+"无费用用户统计"+""

  varreportDate="";

  varreportWriter="";

  varnowdate=newDate();

  reportDate="统计时间

"+nowdate.toLocaleString()+"
";

  reportDate+="营业厅

测试而已
";  

 

  //生成报表头信息

  vHeaderInfo="";

  vHeaderInfo+="无费用用户统计"+

   "

#000000;font-family:

Verdana;font-size:

12px;cursor:

default'>";

  vHeaderInfo+="
"+ReportTitleWithSizeInfo+"

";

  vHeaderInfo+="

"+reportDate;

  vHeaderInfo+=reportWriter+"

";

 }

 catch(e)

 {

  alert("提取报表公共信息失败,打印操作被取消!

");

  self.close();

 }

}

//下面的脚本来自msdn

//ThecodebyCaptain

    //Mead&Company,

//fakeprint()forIE4.x

if(!

printIsNativeSupport())

 window.print=printFrame;

//mainstuff

functionprintFrame(frame,onfinish){

 if(!

frame)frame=window;

 if(frame.document.readyState!

=="complete"&&

      !

confirm("Thedocumenttoprintisnotdownloadedyet!

Continuewithprinting?

"))

 {

   if(onfinish)onfinish();

   return;

 }

 if(printIsNativeSupport()){

   /*focushandlingforthisscopeisIE5Betaworkaround,

      shouldbegonewithIE5RTM.

   */

   varfocused=document.activeElement;

   frame.focus();

   frame.self.print();

   if(onfinish)onfinish();

   if(focused&&!

focused.disabled)focused.focus();

   return;

 }

 vareventScope=printGetEventScope(frame);

 varfocused=document.activeElement;

 window.printHelper=function(){

   execScript("onerrorresumenext:

printWB.ExecWB6,1","VBScript");

   printFireEvent(frame,eventScope,"onafterprint");

   printWB.outerHTML="";

   if(onfinish)onfinish();

   if(focused&&!

focused.disabled)focused.focus();

   window.printHelper=null;

 }

 document.body.insertAdjacentHTML("beforeEnd",

   "

   classid=\"clsid:

8856F961-340A-11D0-A96B-00C04FD705A2\">");

 printFireEvent(frame,eventScope,"onbeforeprint");

 frame.focus();

 window.printHelper=printHelper;

 setTimeout("window.printHelper()",0);

}

//helpers

functionprintIsNativeSupport(){

 varagent=window.navigator.userAgent;

 vari=agent.indexOf("MSIE")+5;

 returnparseInt(agent.substr(i))>=5&&agent.indexOf("5.0b1")<0;

}

functionprintFireEvent(frame,obj,name){

 varhandler=obj[name];

 switch(typeof(handler)){

   case"string":

frame.execScript(handler);break;

   case"function":

handler();

 }

}

functionprintGetEventScope(frame){

 varframeset=frame.document.all.tags("FRAMESET");

 if(frameset.length)returnframeset[0];

 returnframe.document.body;

}

functiononprintHiddenFrame(){

 functiononfinish(){

   printHiddenFrame.outerHTML="";

   if(window.onprintcomplete)window.onprintcomplete();

 }

 printFrame(printHiddenFrame.printMe,onfinish);

}

        

        程序中在Page_Load里面加上:

btPrint.Attributes.Add("onclick","returnPrintDataGrid(document.all('SheetList'))");

        注:

SheetList为需要打印的DataGridID,在查询后,btPrint为页面上打印按钮的ID

       

        可以将上述脚本代码写在一个js文件中,然后再aspx文件中引用,如  ,上述代码的原理比较简单,我不在多说。

上述代码可以实现直接打印页面上指定控件的内容,当然最多还是打印table的内容,如果需要先预览后打印。

需要作一个空的html文件,然后动态写入需要打印的内容:

        varpreDlg=window.open("PrintList.htm");

        CreateHtmlReport(preDlg,true);

        

2、ActiveX控件

        自己开发控件。

这种方式很多商用软件采用这种方式,写成控件后已经无所谓是在web中使用还是应用程序中使用了。

打印方式非常灵活,基本上程序能做到的web也能做得到。

但客户端需要安装组件,部署不是很方便。

3、.NET组件

        

        卢彦写过一篇很好的文章《利用XML实现通用WEB报表打印》,相信大家都看过了。

思路新颖,实现简单,确实不失为一种通用WEB打印解决办法,尤其利用XML来描述打印文件的方法给以后的格式的拓展留下很好的接口,非常容易扩充。

这种打印方式对于格式变化大,数据量小的应用来说非常合适。

这种思路也给了ASP.NET上打印的一种新的思路:

自定义一些组件来实现灵活的打印功能。

当然缺点也是显而易见:

1、需要客户端安装NETframework1.0组件。

2、XML的解析上,如果文件较大速度上不是很理想。

3、页面首次加载时会有明显的延时。

当然最大的问题在于客户端需要安装组件,因为大部分采用BS架构的系统,客户端配置都不会太高,9x的操作系统居多,如果采用这种方式必将给工程的实施造成很多麻烦,所以最好能有一种方式:

既能利用xml这种好的方式来描述打印文件,而且客户端也无需安装任何组件。

        在研究了卢大侠的代码后,俺有了一个想法:

事实上代码里别的功能我们并不关心,最重要的关键在于xml的解析部分和打印的部分。

先来看看XmlDocument的命名空间System.Xml,并非winform特有,webform也可以使用,再看看PrintDocument的命名空间System.Drawing.Printing,查询了MSDN后发现这个命名空间下的类库webform中依然可以使用。

好了,我们最关心的两点WebForm中都可以使用,我们可以把这个打印控件写成一个类库,然后在ASP.NET中直接调用而客户端无需再安装任何组件了。

        但随后问题出来了:

卢彦的.NET组件是在页面请求的首次下载到客户端执行的,所以组件中可以直接使用各种本地资源,如打印机,网络等,但我们的打印控件写成类库由ASP.NET程序调用时,实际上组件是在服务端上运行,它访问服务端的资源不会有问题,但我们更希望:

运行在服务端的组件可以访问客户端的资源,如访问客户端的打印机打印指定内容,当然打印的内容可能是在服务端生成的。

        这又引出一个新的问题:

ASP.NET如何不受限制的访问各种资源。

由于安全原因,ASP.NET程序默认以ASPNET本地用户帐户运行。

由于该帐户不具有任何网络凭据,因此在网络看来,它是Windows匿名帐户(NTAUTHORITY\ANONYMOUSLOGON),不具有访问本地资源的权限,所以必须采用模拟用户的方式让APS.NET程序以别的帐户形式运行。

        思路已经整理清楚,简单说一些实现的步骤:

A、编写打印组件

        参考卢彦的代码,去除无关部分,只保留xml解析部分和打印部分,PrintControl类中增加三个成员数据:

        publicstring FileName="";            //需要打印的文件名称

        publicstringPrinterName="";        //打印机名称

        publicstringClientIP="";                //客户端IP地址

        增加一个成员函数:

        publicvoidPrintPage()

  {

   try

   {

    doc.Load(FileName);

    //settheprintername

      this.printDocument1.PrinterSettings.PrinterName=ClientIP+PrinterName;

    //addprintpageeventhandler

    this.printDocument1.PrintPage+=newPrintPageEventHandler(this.pd_PrintPage);

    //printthepage

    //stringtm=User.Identity.Name;

    this.printDocument1.Print();

    error_msg="打印成功";

   }

   catch(Exceptionex)

   {

    error_msg=ex.Message;

   }

  }

        

        注意:

客户端的打印机必须是共享

        别的xml解析部分不用动,编译成类库后,在ASP.NET引用RemotePrint.dll,并在需要打印功能的页面放上一个打印按钮,代码中引用RemotePrint命名空间,编写Click事件如下:

    

       PrintControlprint=newPrintControl();

       print.PrintPath =Request.PhysicalApplicationPath;

       print.ClientIP=Request.ServerVariables["REMOTE_ADDR"]     

       print.PrinterName="printer";

       print.PrintPage();

        ASP.NET项目中Web.Config开启用户模拟:

        

        上述解决办法必须基于一个前提,服务端和客户端是运行在同一个网段内,不过仔细想想,有上述打印需求的BS系统一般都运行在企业的内网上,所以基本上满足要求

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1