网页WEB打印控件制作
在WEB系统中,打印的确是比较烦人的问题,如果我们能制作一个属于自己的自定义的打印插件,那么我们在后续自定义打印的时候能随心所欲的控制打印,这样的效果对于程序员来说是非常开心的一件事件,本文将自己开发编写的C#制作的HTML打印插件分享出来,让有同样需求的朋友提供一个参考;此插件是基于Microsoft.NETFramework2.0开发的,缺点是每台客户端在安装插件时,必须要安装Microsoft.NETFramework2.0;本插件能实现页眉、页脚、表头、标题、表尾的分页打印;支持纸张类型、自动补充空行等功能;由于技术有限,肯定有很多不足的地方,请批评指正!
由于本打印插件是基于我们开发平台的报表基础来开发设计的,所以打印控件的原理:通过JS将页面表格数据生成固定格式的XML字符串(图片通过64base图片格式)传送给打印插件,有打印插件自主绘图生成打印页面。E_Print插件可以在WEB或WinForm中使用:
打印插件完整源码:E_Print.rar(包含插件源码、打包程序、winform调试DEMO)
下面贴出源码:(在源码中有详细的注释说明)
1、PrintControl打印插件类
usingSystem; usingSystem.Collections.Generic; usingSystem.ComponentModel; usingSystem.Drawing; usingSystem.Data; usingSystem.Text; usingSystem.Windows.Forms; usingSystem.Runtime.InteropServices; usingSystem.Drawing.Printing; usingSystem.Xml; usingSystem.Security; usingSystem.Drawing.DrawingD; usingSystem.Drawing.Text; usingSystem.Text.RegularExpressions; namespaceE_Print { ///<summary> ///打印控件 ///实现IObjectSafety接口 ///网页上所有所使用到的GUID通过Guid工具生成的唯一编码 ///DEDD-BA--A-FFBEEC编码以后不允许修改 ///</summary> [Guid("DEDD-BA--A-FFBEEC"),ProgId("EReportPrint"),ComVisible(true)] publicpartialclassPrintControl:UserControl,IObjectSafety { #region私有变量 #region通用参数 ///<summary> ///缩放比例 ///</summary> privatefloatZoom=; ///<summary> ///网页高度像素px ///</summary> privatefloatHtmlHeight=; ///<summary> ///网页宽度像素px ///</summary> privatefloatHtmlWidth=; ///<summary> ///报表区域矩形 ///</summary> privateRectangleFTableRect=newRectangleF(); ///<summary> ///报表绘制实例 ///</summary> privateReportDrawRptDraw=newReportDraw(); #endregion #region页边距 ///<summary> ///左边距 ///毫米mm(一位小数) ///</summary> privatefloat_marginLeft=.f; ///<summary> ///右边距 ///</summary> privatefloat_marginRight=.f; ///<summary> ///上边距 ///</summary> privatefloat_marginTop=.f; ///<summary> ///下边距 ///</summary> privatefloat_marginBottom=.f; #endregion #region版型方向 ///<summary> ///版型方向Landscape:true横向;false纵向 ///</summary> privatebool_landscape=false; #endregion #region纸型大小 ///<summary> ///纸张类型 ///</summary> privatestring_paperName="A"; ///<summary> ///纸张宽度 ///</summary> privateint_paperWidth=;//毫米 ///<summary> ///纸张高度 ///</summary> privateint_paperHeight=;//毫米 #endregion #region打印参数 ///<summary> ///自适应纸张大小方法 ///null:无 ///row:横向 ///col:纵向 ///</summary> privatestring_zoomType="null"; ///<summary> ///是否每页打印标题 ///</summary> privatebool_isTblTitleAllPage=false; ///<summary> ///是否每页打印表头 ///</summary> privatebool_isTblHeadAllPage=false; ///<summary> ///是否每页打印表尾 ///</summary> privatebool_isTblFootAllPage=false; ///<summary> ///最后一页自动补行 ///</summary> privatebool_isAutoFillRow=false; ///<summary> ///字符溢出是否换行缩小处理方式 ///</summary> privatebool_isOverFlow=false; ///<summary> ///打印数据 ///</summary> privatestring_dataXml=""; #endregion #region页眉参数 ///<summary> ///页眉--绘制页眉 ///</summary> privatebool_headDraw=false; ///<summary> ///页眉--高度毫米 ///默认刚好 ///</summary> privatefloat_headHeight=.f; ///<summary> ///页眉--左侧文字 ///</summary> privatestring_headLeft=""; ///<summary> ///页眉--中间文字 ///</summary> privatestring_headCenter=""; ///<summary> ///页眉--右侧文字 ///</summary> privatestring_headRight=""; ///<summary> ///页眉--字体名称 ///</summary> privatestring_headFontName="宋体"; ///<summary> ///页眉--字体大小 ///</summary> privatestring_headFontSize="pt"; ///<summary> ///页眉--字体颜色 ///</summary> privatestring_headFontColor="Black"; ///<summary> ///页眉--字体--粗体 ///</summary> privatebool_headFontBold=false; ///<summary> ///页眉--字体--斜体 ///</summary> privatebool_headFontItalic=false; ///<summary> ///页眉--字体--删除线 ///</summary> privatebool_headFontStrikeout=false; ///<summary> ///页眉--字体--下划线 ///</summary> privatebool_headFontUnderline=false; ///<summary> ///页眉--绘制分隔线 ///</summary> privatebool_headLineDraw=false; ///<summary> ///页眉--分隔线宽度 ///</summary> privatefloat_headLineWidth=.f; ///<summary> ///页眉--分隔线线型 ///</summary> privatestring_headLineDash="solid"; ///<summary> ///页眉--分隔线颜色 ///</summary> privatestring_headLineColor="Black"; #endregion #region页脚参数 ///<summary> ///页脚--绘制页脚 ///</summary> privatebool_footDraw=false; ///<summary> ///页脚--高度毫米 ///</summary> privatefloat_footHeight=.f; ///<summary> ///页脚--左侧文字 ///</summary> privatestring_footLeft=""; ///<summary> ///页脚--中间文字 ///</summary> privatestring_footCenter=""; ///<summary> ///页脚--右侧文字 ///</summary> privatestring_footRight=""; ///<summary> ///页脚--字体名称 ///</summary> privatestring_footFontName="宋体"; ///<summary> ///页脚--字体大小 ///</summary> privatestring_footFontSize="pt"; ///<summary> ///页脚--字体颜色 ///</summary> privatestring_footFontColor="Black"; ///<summary> ///页脚--字体--粗体 ///</summary> privatebool_footFontBold=false; ///<summary> ///页脚--字体--斜体 ///</summary> privatebool_footFontItalic=false; ///<summary> ///页脚--字体--删除线 ///</summary> privatebool_footFontStrikeout=false; ///<summary> ///页脚--字体--下划线 ///</summary> privatebool_footFontUnderline=false; ///<summary> ///页脚--绘制分隔线 ///</summary> privatebool_footLineDraw=false; ///<summary> ///页脚--分隔线宽度 ///</summary> privatefloat_footLineWidth=.f; ///<summary> ///页脚--分隔线线型 ///</summary> privatestring_footLineDash="solid"; ///<summary> ///页脚--分隔线颜色 ///</summary> privatestring_footLineColor="Black"; #endregion #endregion #region构造方法 ///<summary> ///打印控件构造函数 ///</summary> publicPrintControl() { InitializeComponent(); Init_PageSetting(); } #endregion #region接口实现 privateconststring_IID_IDispatch="{---C-}"; privateconststring_IID_IDispatchEx="{aef-c-d--acdcaa}"; privateconststring_IID_IPersistStorage="{A---C-}"; privateconststring_IID_IPersistStream="{---C-}"; privateconststring_IID_IPersistPropertyBag="{DF-CB-CE--AABB}"; privateconstintINTERFACESAFE_FOR_UNTRUSTED_CALLER=x; privateconstintINTERFACESAFE_FOR_UNTRUSTED_DATA=x; privateconstintS_OK=; privateconstintE_FAIL=unchecked((int)x); privateconstintE_NOINTERFACE=unchecked((int)x); privatebool_fSafeForScripting=true; privatebool_fSafeForInitializing=true; publicintGetInterfaceSafetyOptions(refGuidriid,refintpdwSupportedOptions,refintpdwEnabledOptions) { intRslt=E_FAIL; stringstrGUID=riid.ToString("B"); pdwSupportedOptions=INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA; switch(strGUID) { case_IID_IDispatch: case_IID_IDispatchEx: Rslt=S_OK; pdwEnabledOptions=; if(_fSafeForScripting==true) pdwEnabledOptions=INTERFACESAFE_FOR_UNTRUSTED_CALLER; break; case_IID_IPersistStorage: case_IID_IPersistStream: case_IID_IPersistPropertyBag: Rslt=S_OK; pdwEnabledOptions=; if(_fSafeForInitializing==true) pdwEnabledOptions=INTERFACESAFE_FOR_UNTRUSTED_DATA; break; default: Rslt=E_NOINTERFACE; break; } returnRslt; } publicintSetInterfaceSafetyOptions(refGuidriid,intdwOptionSetMask,intdwEnabledOptions) { intRslt=E_FAIL; stringstrGUID=riid.ToString("B"); switch(strGUID) { case_IID_IDispatch: case_IID_IDispatchEx: if(((dwEnabledOptions&dwOptionSetMask)==INTERFACESAFE_FOR_UNTRUSTED_CALLER)&&(_fSafeForScripting==true)) Rslt=S_OK; break; case_IID_IPersistStorage: case_IID_IPersistStream: case_IID_IPersistPropertyBag: if(((dwEnabledOptions&dwOptionSetMask)==INTERFACESAFE_FOR_UNTRUSTED_DATA)&&(_fSafeForInitializing==true)) Rslt=S_OK; break; default: Rslt=E_NOINTERFACE; break; } returnRslt; } #endregion #region属性方法 #region页边距 ///<summary> ///获取--设置--左边距 ///计量单位毫米(mm) ///</summary> publicfloatMARGINLEFT { get{return_marginLeft;} set{_marginLeft=value;} } ///<summary> ///获取--设置--右边距 ///计量单位毫米(mm) ///</summary> publicfloatMARGINRIGHT { get{return_marginRight;} set{_marginRight=value;} } ///<summary> ///获取--设置--上边距 ///计量单位毫米(mm) ///</summary> publicfloatMARGINTOP { get{return_marginTop;} set{_marginTop=value;} } ///<summary> ///获取--设置--下边距 ///计量单位毫米(mm) ///</summary> publicfloatMARGINBOTTOM { get{return_marginBottom;} set{_marginBottom=value;} } #endregion #region版型方向 ///<summary> ///获取--设置--版型方向 ///Landscape:true横向;false纵向 ///</summary> publicboolLANDSCAPE { get{return_landscape;} set{_landscape=value;} } #endregion #region纸张属性 ///<summary> ///获取--设置--纸张类型 ///</summary> publicstringPAPERNAME { get{return_paperName;} set{_paperName=value;} } ///<summary> ///获取--设置--纸张高度 ///计量单位毫米(mm) ///</summary> publicintPAPERHEIGHT { get{return_paperHeight;} set{_paperHeight=value;} } ///<summary> ///获取--设置--纸张宽度 ///计量单位毫米(mm) ///</summary> publicintPAPERWIDTH { get{return_paperWidth;} set{_paperWidth=value;} } #endregion #region页眉参数 ///<summary> ///获取--设置--页眉是否绘制 ///</summary> publicboolHEADDRAW { get{return_headDraw;} set{_headDraw=value;} } ///<summary> ///获取--设置--页眉高度 ///单位:毫米整数类型 ///</summary> publicfloatHEADHEIGHT { get{return_headHeight;} set{_headHeight=value;} } ///<summary> ///获取--设置--页眉左侧文字 ///</summary> publicstringHEADLEFT { get{return_headLeft;} set{_headLeft=value;} } ///<summary> ///获取--设置--页眉中间文字 ///</summary> publicstringHEADCENTER { get{return_headCenter;} set{_headCenter=value;} } ///<summary> ///获取--设置--页眉右侧文字 ///</summary> publicstringHEADRIGHT { get{return_headRight;} set{_headRight=value;} } ///<summary> ///获取--设置--页眉字体名称 ///</summary> publicstringHEADFONTNAME { get{return_headFontName;} set{_headFontName=value;} } ///<summary> ///获取--设置--页眉字体大小 ///</summary> publicstringHEADFONTSIZE { get{return_headFontSize;} set{_headFontSize=value;} } ///<summary> ///获取--设置--页眉字体颜色 ///</summary> publicstringHEADFONTCOLOR { get{return_headFontColor;} set{_headFontColor=value;} } ///<summary> ///获取--设置--页眉字体--粗体 ///</summary> publicboolHEADFONTBOLD { get{return_headFontBold;} set{_headFontBold=value;} } ///<summary> ///获取--设置--页眉字体--斜体 ///</summary> publicboolHEADFONTITALIC { get{return_headFontItalic;} set{_headFontItalic=value;} } ///<summary> ///获取--设置--页眉字体--删除线 ///</summary> publicboolHEADFONTSTRIKEOUT { get{return_headFontStrikeout;} set{_headFontStrikeout=value;} } ///<summary> ///获取--设置--页眉字体--下划线 ///</summary> publicboolHEADFONTUNDERLINE { get{return_headFontUnderline;} set{_headFontUnderline=value;} } ///<summary> ///获取--设置--是否绘制分割线 ///</summary> publicboolHEADLINEDRAW { get{return_headLineDraw;} set{_headLineDraw=value;} } ///<summary> ///获取--设置--页眉分隔线宽度 ///</summary> publicfloatHEADLINEWIDTH { get{return_headLineWidth;} set{_headLineWidth=value;} } ///<summary> ///获取--设置--页眉分隔线线型 ///</summary> publicstringHEADLINEDASH { get{return_headLineDash;} set{_headLineDash=value;} } ///<summary> ///获取--设置--页眉分隔线颜色 ///</summary> publicstringHEADLINECOLOR { get{return_headLineColor;} set{_headLineColor=value;} } #endregion #region页脚参数 ///<summary> ///获取--设置--页脚是否绘制 ///</summary> publicboolFOOTDRAW { get{return_footDraw;} set{_footDraw=value;} } ///<summary> ///获取--设置--页脚高度 ///单位:毫米整数类型 ///</summary> publicfloatFOOTHEIGHT { get{return_footHeight;} set{_footHeight=value;} } ///<summary> ///获取--设置--页脚左侧文字 ///</summary> publicstringFOOTLEFT { get{return_footLeft;} set{_footLeft=value;} } ///<summary> ///获取--设置--页脚中间文字 ///</summary> publicstringFOOTCENTER { get{return_footCenter;} set{_footCenter=value;} } ///<summary> ///获取--设置--页脚右侧文字 ///</summary> publicstringFOOTRIGHT { get{return_footRight;} set{_footRight=value;} } ///<summary> ///获取--设置--页脚字体名称 ///</summary> publicstringFOOTFONTNAME { get{return_footFontName;} set{_footFontName=value;} } ///<summary> ///获取--设置--页脚字体大小 ///</summary> publicstringFOOTFONTSIZE { get{return_footFontSize;} set{_footFontSize=value;} } ///<summary> ///获取--设置--页脚字体颜色 ///</summary> publicstringFOOTFONTCOLOR { get{return_footFontColor;} set{_footFontColor=value;} } ///<summary> ///获取--设置--页脚字体--粗体 ///</summary> publicboolFOOTFONTBOLD { get{return_footFontBold;} set{_footFontBold=value;} } ///<summary> ///获取--设置--页脚字体--斜体 ///</summary> publicboolFOOTFONTITALIC { get{return_footFontItalic;} set{_footFontItalic=value;} } ///<summary> ///获取--设置--页脚字体--删除线 ///</summary> publicboolFOOTFONTSTRIKEOUT { get{return_footFontStrikeout;} set{_footFontStrikeout=value;} } ///<summary> ///获取--设置--页脚字体--下划线 ///</summary> publicboolFOOTFONTUNDERLINE { get{return_footFontUnderline;} set{_footFontUnderline=value;} } ///<summary> ///获取--设置--是否绘制分割线 ///</summary> publicboolFOOTLINEDRAW { get{return_footLineDraw;} set{_footLineDraw=value;} } ///<summary> ///获取--设置--页脚分隔线宽度 ///</summary> publicfloatFOOTLINEWIDTH { get{return_footLineWidth;} set{_footLineWidth=value;} } ///<summary> ///获取--设置--页脚分隔线线型 ///</summary> publicstringFOOTLINEDASH { get{return_footLineDash;} set{_footLineDash=value;} } ///<summary> ///获取--设置--页脚分隔线颜色 ///</summary> publicstringFOOTLINECOLOR { get{return_footLineColor;} set{_footLineColor=value;} } #endregion #region打印参数 ///<summary> ///获取--设置--打印数据 ///前台传入的XML格式的打印数据 ///</summary> publicstringDATAXML { get{return_dataXml;} set{_dataXml=value;} } ///<summary> ///获取--设置--是否每页打印标题 ///</summary> publicboolISTBLTITLEALLPAGE { get{return_isTblTitleAllPage;} set{_isTblTitleAllPage=value;} } ///<summary> ///获取--设置--是否每页打印表头 ///</summary> publicboolISTBLHEADALLPAGE { get{return_isTblHeadAllPage;} set{_isTblHeadAllPage=value;} } ///<summary> ///获取--设置--是否每页打印表尾 ///</summary> publicboolISTBLFOOTALLPAGE { get{return_isTblFootAllPage;} set{_isTblFootAllPage=value;} } ///<summary> ///获取--设置--末页自动补行 ///</summary> publicboolISAUTOFILLROW { get{return_isAutoFillRow;} set{_isAutoFillRow=value;} } ///<summary> ///获取--设置--缩放方向 ///参数:以下三种;默认null ///null:无 ///row:横向 ///col:纵向 ///</summary> publicstringZOOMTYPE { get{return_zoomType;} set{_zoomType=value;} } ///<summary> ///获取--设置--字符溢出是否缩小换行处理方式 ///</summary> publicboolISOVERFLOW { get{return_isOverFlow;} set{_isOverFlow=value;} } #endregion #region加载参数 ///<summary> ///加载打印参数 ///</summary> publicvoidINITPRINTPARAM() { Init_PageSetting(); } #endregion #endregion #region加载事件 ///<summary> ///初始化--页面设置参数 ///</summary> privatevoidInit_PageSetting() { this.E_PrintDocument.DefaultPageSettings.Margins.Left=(int)Math.Round(MARGINLEFT*);//左边距 this.E_PrintDocument.DefaultPageSettings.Margins.Right=(int)Math.Round(MARGINRIGHT*);//右边距 this.E_PrintDocument.DefaultPageSettings.Margins.Top=(int)Math.Round(MARGINTOP*);//上边距 this.E_PrintDocument.DefaultPageSettings.Margins.Bottom=(int)Math.Round(MARGINBOTTOM*);//下边距 this.E_PrintDocument.PrinterSettings.Copies=;//打印份数 this.E_PrintDocument.DefaultPageSettings.Landscape=this.LANDSCAPE;//版型方向 PaperSizesize=GetPaperSize(PAPERNAME);//纸张类型 if(size!=null) this.E_PrintDocument.DefaultPageSettings.PaperSize=size; else this.E_PrintDocument.DefaultPageSettings.PaperSize=newPaperSize(this.PAPERNAME,(int)Math.Round(this.PAPERWIDTH/.*),(int)Math.Round(this.PAPERHEIGHT/.*)); } ///<summary> ///获取--纸张类型 ///</summary> ///<paramname="paperName">纸张类型名称</param> ///<returns></returns> privatePaperSizeGetPaperSize(stringpaperName) { PaperSizepaper=null; foreach(PaperSizepsinthis.E_PrintDocument.PrinterSettings.PaperSizes) { if(ps.PaperName.ToLower()==paperName.ToLower())//检查打印机是否有指定的纸张类型 { paper=ps; break; } } returnpaper; } #endregion #region打印事件 ///<summary> ///直接打印 ///此处加入了再次调用打印设置界面,因为用户可能需要选择那种打印机 ///</summary> ///<returns></returns> publicstringPRINT() { //直接打印时,直接调用printDocument的Print()方法 //因为用户可能在打印之前还要再更改打印设置所以需再次显示打印设置对话框 if(this.E_PrintDialog.ShowDialog()==DialogResult.OK) { try { this.Init_Printer(); this.E_PrintDocument.Print(); } catch(Exceptionex) { this.E_PrintDocument.PrintController.OnEndPrint(this.E_PrintDocument,newPrintEventArgs()); returnex.Message.ToString(); } } return""; } ///<summary> ///打印预览 ///将打印的数据进行预览 ///</summary> publicstringPREVIEW() { try { this.Init_Printer(); this.E_PrintPreviewDialog.ShowDialog(); } catch(Exceptionex) { returnex.Message.ToString(); } return""; } ///<summary> ///页面设置 ///设置打印的页面的纸张大小、纸型、页面边距 ///</summary> publicvoidPAGESTE() { //页面设置对话框中使用的是公制长度计量单位(厘米) //在.net中采用的是英制的计量单位(英寸) //英寸约等于.厘米,厘米=毫米 //所以在下面中需要加入转换信息将对话框中设置的页边距进行转换保存 //设置传入的纸张信息 if(this.E_PageSetupDialog.ShowDialog()==DialogResult.OK)//弹出页面设置对话框 { if(System.Globalization.RegionInfo.CurrentRegion.IsMetric)//转换页边距计量单位 this.E_PageSetupDialog.PageSettings.Margins=PrinterUnitConvert.Convert(this.E_PageSetupDialog.PageSettings.Margins,PrinterUnit.Display,PrinterUnit.TenthsOfAMillimeter); this.E_PrintDocument.DefaultPageSettings=this.E_PageSetupDialog.PageSettings;//更新页面设置参数值 //更新参数 this.LANDSCAPE=this.E_PrintDocument.DefaultPageSettings.Landscape;//版型方向 this.PAPERNAME=this.E_PrintDocument.DefaultPageSettings.PaperSize.PaperName;//纸张类型 PaperSizetmPSize=this.E_PrintDocument.DefaultPageSettings.PaperSize;//纸张尺寸 this.PAPERWIDTH=(int)Math.Round(tmPSize.Width*./);//纸张宽度 this.PAPERHEIGHT=(int)Math.Round(tmPSize.Height*./);//纸张高度 this.MARGINLEFT=(float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Left/f,);//左边距 this.MARGINRIGHT=(float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Right/f,);//右边距 this.MARGINTOP=(float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Top/f,);//上边距 this.MARGINBOTTOM=(float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Bottom/f,);//下边距 } } ///<summary> ///打印设置 ///设置打印机的信息(选择打印机、设置打印份数等信息) ///</summary> publicvoidPRINTSET() { this.E_PrintDialog.ShowDialog(); } #endregion #region绘制对象 ///<summary> ///打印及打印前初始化数据 ///</summary> privatevoidInit_Printer() { HtmlHeight=;//网页报表高度 HtmlWidth=;//网页报表宽度 CalcTableRect();//计算区域矩形 RptDraw=newReportDraw();//报表绘制实例 RptDraw.IsAllPrintTitle=this._isTblTitleAllPage;//每页打印标题 RptDraw.IsAllPrintHead=this._isTblHeadAllPage;//每页打印表头 RptDraw.IsAllPrintFoot=this._isTblFootAllPage;//每页打印表尾 RptDraw.IsAutoFillRow=this._isAutoFillRow;//末页自动补行 RptDraw.IsOverFlow=this._isOverFlow;//字符溢出缩小 RptDraw.ReptRect=TableRect;//赋值报表矩形 if(!ParseXML())return;//解析报表数据 CalcReportZoom();//计算缩小比例 CalcZoomAllSize();//按比计算尺寸 RptDraw.Zoom=this.Zoom;//赋值缩小比例 RptDraw.CalcPaging();//计算打印分页 } ///<summary> ///PrintDocument对象打印绘制事件 ///</summary> ///<paramname="sender"></param> ///<paramname="e"></param> privatevoidE_PrintDoc_PrintPage(objectsender,PrintPageEventArgse) { Graphicsg=e.Graphics; g.Clear(Color.White); DrawHeader(g); DrawFooter(g); if(RptDraw.DrawReport(g)) e.HasMorePages=true; else e.HasMorePages=false; } ///<summary> ///绘制页眉 ///</summary> ///<paramname="g">绘图对象</param> privatevoidDrawHeader(Graphicsg) { //是否绘制 if(_headDraw) { //页眉实例 PageHeaderpgHeader=newPageHeader(); //页眉矩形 RectangleFpgHeaderRect=newRectangleF(TableRect.X,//X坐标 TableRect.Y-mmToPixel(_headHeight),//Y坐标 TableRect.Width,//W宽度 mmToPixel(_headHeight)//H高度 ); //页眉赋值 pgHeader.HeadRect=pgHeaderRect; pgHeader.StrLeft=ReplacePageNum(_headLeft);//左侧文本 pgHeader.StrCenter=ReplacePageNum(_headCenter);//中间文本 pgHeader.StrRight=ReplacePageNum(_headRight);//右侧文本 FontStylefontStyle=FontStyle.Regular;//字体样式 if(_headFontBold)fontStyle|=FontStyle.Bold; if(_headFontItalic)fontStyle|=FontStyle.Italic; if(_headFontStrikeout)fontStyle|=FontStyle.Strikeout; if(_headFontUnderline)fontStyle|=FontStyle.Underline; pgHeader.StrFont=newFont(_headFontName,(float)Convert.ToDouble(_headFontSize.ToLower().Replace("px","").Replace("pt","")),fontStyle,GraphicsUnit.Point); pgHeader.StrColor=(Color)PrintTool.StrToColor(_headFontColor); if(_headLineDraw)//绘制分割线 { pgHeader.LineDraw=_headLineDraw; pgHeader.LineWidth=_headLineWidth; pgHeader.LineColor=(Color)PrintTool.StrToColor(_headLineColor); pgHeader.LineDash=PrintTool.GetDashStyle(_headLineDash); } //页眉绘制 pgHeader.Draw(g); } } ///<summary> ///绘制页脚 ///</summary> ///<paramname="g">绘图对象</param> privatevoidDrawFooter(Graphicsg) { //是否绘制 if(_footDraw) { //页脚实例 PageFooterpgFooter=newPageFooter(); //页脚矩形 RectangleFpgFooterRect=newRectangleF(TableRect.X,//X坐标 TableRect.Y+TableRect.Height,//Y坐标 TableRect.Width,//W宽度 mmToPixel(_footHeight)//H高度 ); //页脚赋值 pgFooter.FootRect=pgFooterRect; pgFooter.StrLeft=ReplacePageNum(_footLeft);//左侧文本 pgFooter.StrCenter=ReplacePageNum(_footCenter);//中间文本 pgFooter.StrRight=ReplacePageNum(_footRight);//右侧文本 FontStylefontStyle=FontStyle.Regular;//字体样式 if(_footFontBold)fontStyle|=FontStyle.Bold; if(_footFontItalic)fontStyle|=FontStyle.Italic; if(_footFontStrikeout)fontStyle|=FontStyle.Strikeout; if(_footFontUnderline)fontStyle|=FontStyle.Underline; pgFooter.StrFont=newFont(_footFontName,(float)Convert.ToDouble(_footFontSize.ToLower().Replace("px","").Replace("pt","")),fontStyle,GraphicsUnit.Point); pgFooter.StrColor=(Color)PrintTool.StrToColor(_footFontColor); if(_footLineDraw)//绘制分割线 { pgFooter.LineDraw=_footLineDraw; pgFooter.LineWidth=_footLineWidth; pgFooter.LineColor=(Color)PrintTool.StrToColor(_footLineColor); pgFooter.LineDash=PrintTool.GetDashStyle(_footLineDash); } //页脚绘制 pgFooter.Draw(g); } } #endregion #region辅助方法 ///<summary> ///毫米TO像素 ///</summary> ///<paramname="mmValue">毫米值</param> ///<returns></returns> publicstaticfloatmmToPixel(floatmmValue)//mmValue是毫米,厘米=毫米 { return(mmValue/.f*f); } ///<summary> ///替换当前页码、总共页数两个变量 ///</summary> ///<paramname="str"></param> ///<returns></returns> privatestringReplacePageNum(stringstr) { stringretStr=""; if(str==null||str.Trim()=="") returnretStr; retStr=str; intt=; while(t>=) { t=retStr.IndexOf("[curpage]",StringComparison.OrdinalIgnoreCase); if(t>=) { retStr=retStr.Substring(,t)+RptDraw.CurPageNum.ToString()+retStr.Substring(t+"[curpage]".Length); } } t=; while(t>=) { t=retStr.IndexOf("[allpage]",StringComparison.OrdinalIgnoreCase); if(t>=) { retStr=retStr.Substring(,t)+RptDraw.AllPageNum.ToString()+retStr.Substring(t+"[allpage]".Length); } } returnretStr; } ///<summary> ///解析XML文件 ///</summary> ///<returns>返回成功与否</returns> privateboolParseXML() { if(this.DATAXML==null||this.DATAXML.Trim()=="")returnfalse; XmlDataDocumentxmlDoc=newXmlDataDocument(); try { xmlDoc.LoadXml(this.DATAXML); XmlNoderootNode=xmlDoc.DocumentElement; if(rootNode.ChildNodes.Count==)returnfalse; if(rootNode.ChildNodes[].Name.ToLower()!="table")returnfalse; XmlNodetableNode=rootNode.ChildNodes[];//表格节点 HtmlHeight=float.Parse(tableNode.Attributes["height"].Value); HtmlWidth=float.Parse(tableNode.Attributes["width"].Value); inttmRowIndex=; foreach(XmlNodetrNodeintableNode.ChildNodes) { if(trNode.Name.ToLower()!="tr")continue; //解析表格行 RowtmRow=newRow(); tmRow.RowIndex=tmRowIndex; tmRow.RowHeight=float.Parse(trNode.Attributes["height"].Value); tmRow.RowType=trNode.Attributes["rowtype"].Value.ToLower(); //解析单元格 foreach(XmlNodetdNodeintrNode.ChildNodes) { CelltmCell=newCell(); #region合并\坐标\矩形 tmCell.RowSpan=Convert.ToInt(tdNode.Attributes["rowspan"].Value); tmCell.ColSpan=Convert.ToInt(tdNode.Attributes["colspan"].Value); tmCell.RowIndex=Convert.ToInt(tdNode.Attributes["r"].Value); tmCell.ColIndex=Convert.ToInt(tdNode.Attributes["c"].Value); tmCell.RectX=float.Parse(tdNode.Attributes["x"].Value); tmCell.RectY=float.Parse(tdNode.Attributes["y"].Value); tmCell.RectW=float.Parse(tdNode.Attributes["w"].Value); tmCell.RectH=float.Parse(tdNode.Attributes["h"].Value); #endregion #region设置单元格字体 FontStyletmStyle=newFontStyle(); tmStyle=FontStyle.Regular; if(tdNode.Attributes["italic"].Value.ToString()=="")tmStyle|=FontStyle.Italic; if(tdNode.Attributes["bold"].Value.ToString()=="")tmStyle|=FontStyle.Bold; if(tdNode.Attributes["strikeout"].Value.ToString()=="")tmStyle|=FontStyle.Strikeout; if(tdNode.Attributes["underline"].Value.ToString()=="")tmStyle|=FontStyle.Underline; tmCell.CellFont=newFont(tdNode.Attributes["fontname"].Value,float.Parse(tdNode.Attributes["fontsize"].Value.Replace("pt","").Replace("px","")),tmStyle,GraphicsUnit.Point); tmCell.FontColor=(Color)PrintTool.StrToColor(tdNode.Attributes["fontcolor"].Value); tmCell.BackColor=(Color)PrintTool.StrToColor(tdNode.Attributes["backcolor"].Value); StringFormattmFormat=newStringFormat(); switch(tdNode.Attributes["align"].Value.ToLower())//水平对齐方式 { case"center": tmFormat.Alignment=StringAlignment.Center; break; case"right": tmFormat.Alignment=StringAlignment.Far; break; default: tmFormat.Alignment=StringAlignment.Near; break; } switch(tdNode.Attributes["valign"].Value.ToLower())//垂直对齐方式 { case"middle": tmFormat.LineAlignment=StringAlignment.Center; break; case"bottom": tmFormat.LineAlignment=StringAlignment.Far; break; default: tmFormat.LineAlignment=StringAlignment.Near; break; } tmCell.strFormat=tmFormat; #endregion #region内嵌图片-属性 tmCell.IsImage=tdNode.Attributes["isimage"].Value.ToString()==""?true:false; if(tmCell.IsImage) tmCell.ImageUrl=tdNode.Attributes["imageurl"].Value; #endregion #region单元格边框属性 //左边框线 stringtmVal=tdNode.Attributes["leftwidth"].Value; if(tmVal.IndexOf("px")>=) { tmCell.LeftBorder=newBorderLine( float.Parse(tmVal.Replace("px","")), (Color)PrintTool.StrToColor(tdNode.Attributes["leftcolor"].Value), PrintTool.GetDashStyle(tdNode.Attributes["leftdash"].Value) ); } //上边框线 tmVal=tdNode.Attributes["topwidth"].Value; if(tmVal.IndexOf("px")>=) { tmCell.TopBorder=newBorderLine( float.Parse(tmVal.Replace("px","")), (Color)PrintTool.StrToColor(tdNode.Attributes["topcolor"].Value), PrintTool.GetDashStyle(tdNode.Attributes["topdash"].Value) ); } //右边框线 tmVal=tdNode.Attributes["rightwidth"].Value; if(tmVal.IndexOf("px")>=) { tmCell.RightBorder=newBorderLine( float.Parse(tmVal.Replace("px","")), (Color)PrintTool.StrToColor(tdNode.Attributes["rightcolor"].Value), PrintTool.GetDashStyle(tdNode.Attributes["rightdash"].Value) ); } //下边框线 tmVal=tdNode.Attributes["bottomwidth"].Value; if(tmVal.IndexOf("px")>=) { tmCell.BottomBorder=newBorderLine( float.Parse(tmVal.Replace("px","")), (Color)PrintTool.StrToColor(tdNode.Attributes["bottomcolor"].Value), PrintTool.GetDashStyle(tdNode.Attributes["bottomdash"].Value) ); } #endregion #region单据格数据数值 tmCell.Value=tdNode.InnerText; #endregion //加入对应的行内 tmRow.RowCells.Add(tmCell); } RptDraw.RowsList.Add(tmRow); tmRowIndex++; } } catch { returnfalse; } finally { xmlDoc=null; } returntrue; } ///<summary> ///计算报表区域矩形 ///真实的绘制报表的区域 ///</summary> privatevoidCalcTableRect() { //重新初始化实例 TableRect=newRectangleF(); //左顶点X坐标 TableRect.X=mmToPixel(_marginLeft); //左顶点Y坐标 TableRect.Y=mmToPixel(_marginTop); if(_headDraw)//需要绘制页眉 TableRect.Y+=mmToPixel(_headHeight); //报表矩形宽度高度 if(this.LANDSCAPE)//版型方向横向 { //颠倒宽高 TableRect.Width=mmToPixel((float)_paperHeight-_marginLeft-_marginRight); TableRect.Height=mmToPixel((float)_paperWidth-_marginTop-_marginBottom); } else//版型方向纵向 { TableRect.Width=mmToPixel((float)_paperWidth-_marginLeft-_marginRight); TableRect.Height=mmToPixel((float)_paperHeight-_marginTop-_marginBottom); } //报表矩形高度缩减 if(_headDraw)//需要绘制页眉 TableRect.Height-=mmToPixel(_headHeight); if(_footDraw)//需要绘制页脚 TableRect.Height-=mmToPixel(_footHeight); } ///<summary> ///计算缩放比例 ///</summary> privatevoidCalcReportZoom() { if(this.ZOOMTYPE.ToLower()=="row") { if(Convert.ToInt(TableRect.Width)>=HtmlWidth) this.Zoom=; else this.Zoom=TableRect.Width/HtmlWidth; } elseif(this.ZOOMTYPE.ToLower()=="col") { if(Convert.ToInt(TableRect.Height)>=HtmlHeight) this.Zoom=; else this.Zoom=TableRect.Height/HtmlHeight; } else { this.Zoom=; } } ///<summary> ///转换所有的尺寸 ///根据缩放比例 ///</summary> privatevoidCalcZoomAllSize() { if(this.Zoom!=) { //转换HTML高度宽度 HtmlWidth=HtmlWidth*Zoom; HtmlHeight=HtmlHeight*Zoom; //转换所有行号 foreach(RowzRowinthis.RptDraw.RowsList) { //行高缩小 zRow.RowHeight=zRow.RowHeight*Zoom; //转换所有单元格 foreach(CellzCellinzRow.RowCells) { zCell.RectX=zCell.RectX*Zoom; zCell.RectY=zCell.RectY*Zoom; zCell.RectW=zCell.RectW*Zoom; zCell.RectH=zCell.RectH*Zoom; zCell.TopBorder.LineWidth=zCell.TopBorder.LineWidth*Zoom; zCell.BottomBorder.LineWidth=zCell.BottomBorder.LineWidth*Zoom; zCell.LeftBorder.LineWidth=zCell.LeftBorder.LineWidth*Zoom; zCell.RightBorder.LineWidth=zCell.RightBorder.LineWidth*Zoom; //字体相应缩小 zCell.CellFont=newFont(zCell.CellFont.Name,zCell.CellFont.Size*Zoom,zCell.CellFont.Style,GraphicsUnit.Point); } } } } #endregion } }
2、ReportDraw打印绘制类
usingSystem; usingSystem.Collections.Generic; usingSystem.Drawing; usingSystem.Drawing.DrawingD; usingSystem.IO; namespaceE_Print { ///<summary> ///报表绘制 ///</summary> publicclassReportDraw { #region私有成员 ///<summary> ///当前页码 ///</summary> privateint_curPageNum; ///<summary> ///总共页数 ///</summary> privateint_allPageNum; ///<summary> ///表格矩形 ///</summary> privateRectangleF_reptRect; ///<summary> ///报表全部行集 ///</summary> privateList<Row>_rowsList; ///<summary> ///分页页面数组 ///</summary> privateList<PagingItem>_pageList; ///<summary> ///是否每页打印标题 ///</summary> privatebool_isAllPrintTitle; ///<summary> ///是否每页打印表头 ///</summary> privatebool_isAllPrintHead; ///<summary> ///是否每页打印表尾 ///</summary> privatebool_isAllPrintFoot; ///<summary> ///是否末页自动补行 ///</summary> privatebool_isAutoFillRow; ///<summary> ///缩小比例 ///</summary> privatefloat_zoom; ///<summary> ///字符溢出处理方式 ///</summary> privatebool_isOverFlow; ///<summary> ///每页打印的标题+表头的高度 ///</summary> privatefloat_headPix; ///<summary> ///每页打印的表尾高度 ///</summary> privatefloat_footPix; #endregion #region构造方法 ///<summary> ///构造函数 ///</summary> publicReportDraw() { _curPageNum=; _allPageNum=; _reptRect=newRectangleF(); _rowsList=newList<Row>(); _pageList=newList<PagingItem>(); _isAllPrintTitle=false; _isAllPrintHead=false; _isAllPrintFoot=false; _isAutoFillRow=false; _zoom=; _isOverFlow=false; _headPix=; _footPix=; } ///<summary> ///构造函数 ///</summary> ///<paramname="printTitle">每页打印标题</param> ///<paramname="printHead">每页打印表头</param> ///<paramname="printFoot">每页打印表位</param> ///<paramname="fillRows">自动补全空行</param> ///<paramname="tableRect">报表尺寸矩形</param> ///<paramname="overFlow">字符溢出处理</param> publicReportDraw(boolprintTitle,boolprintHead,boolprintFoot,boolfillRows,RectangleFtableRect,booloverFlow) { _reptRect=tableRect; _isAllPrintTitle=printTitle; _isAllPrintHead=printHead; _isAllPrintFoot=printFoot; _isAutoFillRow=fillRows; _isOverFlow=overFlow; _curPageNum=; _allPageNum=; _zoom=; _rowsList=newList<Row>(); _pageList=newList<PagingItem>(); _headPix=; _footPix=; } #endregion #region属性方法 ///<summary> ///获取--设置--当前页码 ///</summary> publicintCurPageNum { get{return_curPageNum;} set{_curPageNum=value;} } ///<summary> ///获取--设置--总共页数 ///</summary> publicintAllPageNum { get{return_allPageNum;} set{_allPageNum=value;} } ///<summary> ///获取--设置--表格矩形 ///</summary> publicRectangleFReptRect { get{return_reptRect;} set{_reptRect=value;} } ///<summary> ///获取--设置--报表全部行集 ///</summary> publicList<Row>RowsList { get{return_rowsList;} set{_rowsList=value;} } ///<summary> ///获取--设置--分页页面数组 ///</summary> publicList<PagingItem>PageList { get{return_pageList;} set{_pageList=value;} } ///<summary> ///获取--设置--是否每页打印标题 ///</summary> publicboolIsAllPrintTitle { get{return_isAllPrintTitle;} set{_isAllPrintTitle=value;} } ///<summary> ///获取--设置--是否每页打印表头 ///</summary> publicboolIsAllPrintHead { get{return_isAllPrintHead;} set{_isAllPrintHead=value;} } ///<summary> ///获取--设置--是否每页打印表尾 ///</summary> publicboolIsAllPrintFoot { get{return_isAllPrintFoot;} set{_isAllPrintFoot=value;} } ///<summary> ///获取--设置--末页是否自动补行 ///</summary> publicboolIsAutoFillRow { get{return_isAutoFillRow;} set{_isAutoFillRow=value;} } ///<summary> ///获取--设置--缩小比例 ///</summary> publicfloatZoom { get{return_zoom;} set{_zoom=value;} } ///<summary> ///获取--设置--字符溢出处理方式 ///</summary> publicboolIsOverFlow { get{return_isOverFlow;} set{_isOverFlow=value;} } ///<summary> ///获取--设置--每页打印的标题+表头高度 ///</summary> publicfloatHeadPix { get{return_headPix;} set{_headPix=value;} } ///<summary> ///获取--设置--每页打印的表尾高度 ///</summary> publicfloatFootPix { get{return_footPix;} set{_footPix=value;} } #endregion #region计算分页 ///<summary> ///计算分页 ///</summary> publicvoidCalcPaging() { //分页实例 PagingCalcinsCalc=newPagingCalc(); insCalc.TableRect=this.ReptRect; insCalc.RowsList=this.RowsList; insCalc.IsAllPrintTitle=this.IsAllPrintTitle; insCalc.IsAllPrintHead=this.IsAllPrintHead; insCalc.IsAllPrintFoot=this.IsAllPrintFoot; //分页计算 _pageList=insCalc.CalcPages(); this._allPageNum=_pageList.Count; this._curPageNum=; this._headPix=insCalc.MyHeadPix; this._footPix=insCalc.MyFootPix; } #endregion #region绘制方法 ///<summary> ///绘制报表 ///</summary> ///<paramname="g"></param> ///<returns>返回是否结束</returns> publicboolDrawReport(Graphicsg) { boolisMorePage=false; floatoffsetX=_reptRect.X;//X偏移量 floatoffsetY=_reptRect.Y;//Y偏移量 boolisCanFillRow=false;//是否需要补行 boolisFillFlag=false;//是否已经补过 intisFillRowNum=;//需要补充几行 PagingItemnowPage=GetPageItem(CurPageNum);//当前页 if(nowPage!=null) { #region判定高度不足是否自动补行 //判定补行条件报表设置了末页不足自动补行、同时为最后一页 if(_isAutoFillRow==true&&CurPageNum==AllPageNum) { //判定页面高度与数据高度 floatN_PageHeith=ReptRect.Height;//当前页面高度 floatN_DataHeith=GetThisPageDataRowsHeight();//当前数据高度 //补行行高 while((N_DataHeith+(isFillRowNum+)**Zoom)<N_PageHeith) { isFillRowNum++; } if(isFillRowNum>) isCanFillRow=true; } #endregion #region首先绘制上一页补充单元格 if(CurPageNum>) { PagingItemprePage=GetPageItem(CurPageNum-);//上一页 if(prePage!=null) { foreach(PagingMakeUptmMkinprePage.MakeupList) { //绘制补充单元格(上页中未绘制完成的单元格) DrawTD(g,tmMk.MakeupCell,offsetX,offsetY,true,tmMk.MakeupHeight,false); } } } #endregion #region其次绘制当前页面的单元格 //其次绘制当前页的单元格 for(intii=;ii<nowPage.IndexList.Count;ii++) { //先绘制TDCELL单元格 RowrowTR=GetRow(nowPage.IndexList[ii]); #region执行补行 if(isCanFillRow==true&&rowTR.RowType.ToLower().Trim()=="f")//需要补行行标志为F表尾前进行补充空行 { RowfillRow=newRow(); if(ii==) fillRow=rowTR; else fillRow=GetRow(nowPage.IndexList[ii-]); if(fillRow!=null)//绘制自动补充的空行单元格 { //开始补充空行 for(intfi=;fi<=isFillRowNum;fi++) { boolbcFlag=true; //绘制单元格 foreach(CellfillTdCellinfillRow.RowCells) { if(bcFlag) { //绘制边框线(合并单元格的情况才用到) if(fillTdCell.RectX>) { DrawLine(g,offsetX,offsetY,offsetX,offsetY+.F*Zoom);//最左边竖线 DrawLine(g,offsetX,offsetY+.F*Zoom,offsetX+fillTdCell.RectX,offsetY+.F*Zoom); } bcFlag=false; } DrawTD(g,fillTdCell,offsetX,offsetY,false,,true); } //再将偏移量+行号补充的行高全部为px offsetY+=*Zoom; } } isFillFlag=true; } #endregion #region正常绘制 foreach(CelltdinrowTR.RowCells) { DrawTD(g,td,offsetX,offsetY,false,,false); } //再将偏移量+行号 offsetY+=rowTR.RowHeight; #endregion } //判定是否补过;没有补充过,则在最后进行补充空行 if((isCanFillRow==true)&&(isFillFlag==false)&&(nowPage.IndexList.Count>)) { RowfillRow=GetRow(nowPage.IndexList[nowPage.IndexList.Count-]); if(fillRow!=null)//绘制自动补充的空行单元格 { //开始补充空行 for(intfi=;fi<=isFillRowNum;fi++) { boolnewFlag=true; foreach(CellfillTdCellinfillRow.RowCells) { if(newFlag) { //绘制边框线(合并单元格的情况才用到) if(fillTdCell.RectX>) { DrawLine(g,offsetX,offsetY,offsetX,offsetY+.F*Zoom);//最左边竖线 DrawLine(g,offsetX,offsetY+.F*Zoom,offsetX+fillTdCell.RectX,offsetY+.F*Zoom); } newFlag=false; } DrawTD(g,fillTdCell,offsetX,offsetY,false,,true); } offsetY+=*Zoom;//再将偏移量+行号补充的行高全部为px } } } #endregion if(CurPageNum<AllPageNum) { isMorePage=true;//还有下页 CurPageNum++;//页码增加 } } returnisMorePage; } ///<summary> ///绘制单元格 ///</summary> ///<paramname="g">绘图对象</param> ///<paramname="tdCell">单元格</param> ///<paramname="setX">X偏移量</param> ///<paramname="setY">Y坐标值</param> ///<paramname="isMakeup">是否补充单元格</param> ///<paramname="mkH">补充单元格高度</param> ///<paramname="fillCell">自动补行的单元格</param> privatevoidDrawTD(Graphicsg,CelltdCell,floatsetX,floatsetY,boolisMakeup,floatmkH,boolfillCell) { #region参数变量 Penpen; Brushbrush; //获取单元格绘制坐标矩形信息 floattdX=tdCell.RectX+setX; floattdY=setY; floattdW=tdCell.RectW; floattdH=; if(fillCell) { tdH=*Zoom;//自动补行的单元格的高度固定为px } else { if(isMakeup)//补充单元格 { tdH=mkH; tdY=tdY+HeadPix;//如果是补充单元格,则此单元格的Y坐标:如果每页打印标题或表头,则Y坐标需要下移HeadPix } else//实际单元格 { tdH=tdCell.RectH; } if(tdCell.RowSpan>)//判定单元格高度是否超过底线 { tdH=Calc_CellOverHeight(tdCell,tdY,tdH); } } #endregion #region绘制背景 //填充颜色 brush=newSolidBrush(tdCell.BackColor); g.FillRectangle(brush,tdX+.f*Zoom,tdY+.f*Zoom,tdW-.f*Zoom,tdH-.f*Zoom); #endregion #region绘制边框 //左边框线 if(tdCell.LeftBorder.LineWidth>) { pen=newPen(tdCell.LeftBorder.LineColor); pen.DashStyle=tdCell.LeftBorder.LineDash; pen.Width=tdCell.LeftBorder.LineWidth; g.DrawLine(pen,tdX,tdY,tdX,tdY+tdH); } //上边框线 if(tdCell.TopBorder.LineWidth>) { pen=newPen(tdCell.TopBorder.LineColor); pen.DashStyle=tdCell.TopBorder.LineDash; pen.Width=tdCell.TopBorder.LineWidth; g.DrawLine(pen,tdX,tdY,tdX+tdW,tdY); } //右边框线 if(tdCell.RightBorder.LineWidth>) { pen=newPen(tdCell.RightBorder.LineColor); pen.DashStyle=tdCell.RightBorder.LineDash; pen.Width=tdCell.RightBorder.LineWidth; g.DrawLine(pen,tdX+tdW,tdY,tdX+tdW,tdY+tdH); } //下边框线 if(tdCell.BottomBorder.LineWidth>) { pen=newPen(tdCell.BottomBorder.LineColor); pen.DashStyle=tdCell.BottomBorder.LineDash; pen.Width=tdCell.BottomBorder.LineWidth; g.DrawLine(pen,tdX,tdY+tdH,tdX+tdW,tdY+tdH); } #endregion #region绘制文字 if(!fillCell) { RectangleFrect=newRectangleF(tdX,tdY,tdW,tdH); if(tdCell.IsImage) { this.DrawImg(g,rect,tdCell.ImageUrl); } else { brush=newSolidBrush(tdCell.FontColor); this.DrawStr(g,rect,brush,tdCell.CellFont,tdCell.strFormat,tdCell.Value); } } #endregion } ///<summary> ///绘制字符串 ///溢出时,换行缩小字符 ///字体缩小到的最小值不得小于 ///</summary> ///<paramname="g">绘图对象</param> ///<paramname="strRect">文本区域</param> ///<paramname="strBrush">文本笔画</param> ///<paramname="strFont">文本字体</param> ///<paramname="strFormat">文本格式</param> ///<paramname="strValue">文本字符</param> ///<returns></returns> privatevoidDrawStr(Graphicsg,RectangleFstrRect,BrushstrBrush,FontstrFont,StringFormatstrFormat,stringstrValue) { //报表设置:字符溢出不做处理 if(!this.IsOverFlow) { g.DrawString(strValue,strFont,strBrush,strRect,strFormat); } else//需要处理 { //测量字体的宽度和高度会发现误差很大,如果一个一个的测量,误差就实在太大,所以这里就用简单的方式来进行处理 SizeFsf=g.MeasureString(strValue,strFont);//此种方式测量误差很大,如果 if(strRect.Width>sf.Width) { g.DrawString(strValue,strFont,strBrush,strRect,strFormat); } else { //计算换行后字符的全部高度是否满足 intmaxLines=;//计算当前字符当前字体最大打印的行数 maxLines=(int)Math.Ceiling((double)sf.Width/(double)strRect.Width); if(strRect.Height>=maxLines*sf.Height) { g.DrawString(strValue,strFont,strBrush,strRect,strFormat); } else { floattmScale=strRect.Height/(maxLines*sf.Height); FonttmNewFont=newFont(strFont.Name,strFont.Size*tmScale,strFont.Style,GraphicsUnit.Point); g.DrawString(strValue,tmNewFont,strBrush,strRect,strFormat); } } } } ///<summary> ///绘制图片 ///将Base图片流字符串转换成图片并进行绘制 ///</summary> ///<paramname="g"></param> ///<paramname="strRect"></param> ///<paramname="baseImg"></param> privatevoidDrawImg(Graphicsg,RectangleFstrRect,stringbaseImg) { if(baseImg.Trim()=="")return; stringimgStr=baseImg.Replace("data:image/gif;base,","").Trim(); if(imgStr=="")return; //生成图片 try { MemoryStreamstream=newMemoryStream(Convert.FromBaseString(imgStr)); BitmappicImg=newBitmap(stream); RectangleFimgRectF=newRectangleF(f,f,(float)picImg.Width,(float)picImg.Height);//原始图片矩形 RectangleFnewRectF=newRectangleF(strRect.X+f,strRect.Y+f,(float)strRect.Width-f,(float)strRect.Height-f);//绘制图片矩形 g.DrawImage(picImg,newRectF,imgRectF,GraphicsUnit.Pixel);//绘制缩放图片 stream.Close(); } catch { return; } } ///<summary> ///绘制线条 ///</summary> ///<paramname="g">绘图对象</param> ///<paramname="start_X">开始X</param> ///<paramname="start_Y">开始Y</param> ///<paramname="end_X">结束X</param> ///<paramname="end_Y">结束Y</param> privatevoidDrawLine(Graphicsg,floatstart_X,floatstart_Y,floatend_X,floatend_Y) { PenlinePen=newPen(Color.Black,.f); linePen.DashStyle=DashStyle.Solid; g.DrawLine(linePen,start_X,start_Y,end_X,end_Y); } privatefloatChangeUnit(floatvSize) { return(vSize*f/f*f/f); } ///<summary> ///获取行对象 ///</summary> ///<paramname="rowIndex"></param> ///<returns></returns> privateRowGetRow(introwIndex) { foreach(RowretRowin_rowsList) { if(retRow.RowIndex==rowIndex) returnretRow; } returnnull; } ///<summary> ///获取分页页面 ///</summary> ///<paramname="pNo">页码</param> ///<returns></returns> privatePagingItemGetPageItem(intpNo) { foreach(PagingItemretPIteminPageList) { if(retPItem.PageNum==pNo) returnretPItem; } returnnull; } ///<summary> ///计算绘制高度 ///判定并且计算单元格高度是否超过当前页面所有行高度的底线 ///</summary> ///<paramname="mCell">单元格</param> ///<paramname="mY">Y轴坐标值</param> ///<paramname="mH">H当前高度</param> ///<returns></returns> privatefloatCalc_CellOverHeight(CellmCell,floatmY,floatmH) { floatreturnHeight=;//返回高度 floattm_AllTrHeight=GetThisPageDataRowsHeight();//当前页面内所有数据行的高度 floattm_RealY=;//相对最大Y值 floattm_AbsY=;//实际最大Y值 floattm_OverPlus=;//单元格剩余高度 tm_RealY=mY+mH;//实际最大Y值 if(IsAllPrintFoot)//每页打印表尾 tm_AbsY=ReptRect.Y+(tm_AllTrHeight-FootPix);//需要减去表尾高度 else tm_AbsY=tm_AllTrHeight+ReptRect.Y; if(tm_RealY>tm_AbsY) { returnHeight=tm_AbsY-mY;//当前页面实际最大高度-单元格的当前Y坐标值=返回单元格在本页内需要绘制的高度 tm_OverPlus=mH-returnHeight;//当前高度-单元格当前页面需要绘制的高度=下页需要绘制的补充高度 //将当前单元格添加到后页需要补充绘制数组中去 PagingItemnPageItem=GetPageItem(CurPageNum); PagingMakeUpnMakeUp=newPagingMakeUp(); nMakeUp.MakeupCell=mCell; nMakeUp.MakeupHeight=tm_OverPlus; nPageItem.MakeupList.Add(nMakeUp); } else { returnHeight=mH; } returnreturnHeight; } ///<summary> ///获取本页内所有数据行的高度 ///</summary> ///<returns></returns> privatefloatGetThisPageDataRowsHeight() { floatretHeight=; PagingItemoThisPage=GetPageItem(CurPageNum);//当前页 foreach(intoRowIndexinoThisPage.IndexList) { RowoThisRow=GetRow(oRowIndex); retHeight+=oThisRow.RowHeight; } returnretHeight; } ///<summary> ///获取页内某一项所属行的高度 ///</summary> ///<paramname="itemPage">页面对象</param> ///<paramname="itemIndex">本页行数组中的某一项的序号</param> ///<returns></returns> privatefloatGetThisPageOneRowHeight(PagingItemitemPage,intitemIndex) { floatretHeight=; if(itemIndex<itemPage.IndexList.Count&&itemIndex>=) { RowoThisRow=GetRow(itemPage.IndexList[itemIndex]); retHeight=oThisRow.RowHeight; } returnretHeight; } #endregion } } 3、PagingCalc分页计算类 usingSystem; usingSystem.Collections.Generic; usingSystem.Text; usingSystem.Drawing; namespaceE_Print { ///<summary> ///分页计算 ///</summary> publicclassPagingCalc { #region私有变量 ///<summary> ///表格区域 ///</summary> privateRectangleF_tableRect; ///<summary> ///报表行集 ///</summary> privateList<Row>_rowsList; ///<summary> ///是否每页打印标题 ///</summary> privatebool_isAllPrintTitle; ///<summary> ///是否每页打印表头 ///</summary> privatebool_isAllPrintHead; ///<summary> ///是否每页打印表尾 ///</summary> privatebool_isAllPrintFoot; ///<summary> ///标题行集 ///</summary> privateList<Row>TitleList; ///<summary> ///表头前行集 ///</summary> privateList<Row>HForeList; ///<summary> ///表头行集 ///</summary> privateList<Row>HeadList; ///<summary> ///数据行集 ///</summary> privateList<Row>DataList; ///<summary> ///表尾行集 ///</summary> privateList<Row>FootList; ///<summary> ///每页打印标题+表头高度 ///</summary> privatefloat_myHeadPix; ///<summary> ///每页打印表尾高度 ///</summary> privatefloat_myFootPix; #endregion #region构造方法 ///<summary> ///构造函数 ///</summary> publicPagingCalc() { _tableRect=newRectangleF(); _rowsList=newList<Row>(); _isAllPrintTitle=false; _isAllPrintHead=false; _isAllPrintFoot=false; TitleList=newList<Row>(); HForeList=newList<Row>(); HeadList=newList<Row>(); DataList=newList<Row>(); FootList=newList<Row>(); _myHeadPix=; _myFootPix=; } #endregion #region属性方法 ///<summary> ///获取--设置--表格区域 ///</summary> publicRectangleFTableRect { get{return_tableRect;} set{_tableRect=value;} } ///<summary> ///获取--设置--表格行集 ///</summary> publicList<Row>RowsList { get{return_rowsList;} set{_rowsList=value;} } ///<summary> ///获取--设置--是否每页打印标题 ///</summary> publicboolIsAllPrintTitle { get{return_isAllPrintTitle;} set{_isAllPrintTitle=value;} } ///<summary> ///获取--设置--是否每页打印表头 ///</summary> publicboolIsAllPrintHead { get{return_isAllPrintHead;} set{_isAllPrintHead=value;} } ///<summary> ///获取--设置--是否每页打印表尾 ///</summary> publicboolIsAllPrintFoot { get{return_isAllPrintFoot;} set{_isAllPrintFoot=value;} } ///<summary> ///获取--设置--每页打印标题+表头高度 ///</summary> publicfloatMyHeadPix { get{return_myHeadPix;} set{_myHeadPix=value;} } ///<summary> ///获取--设置--每页打印表尾巴高度 ///</summary> publicfloatMyFootPix { get{return_myFootPix;} set{_myFootPix=value;} } #endregion #region计算方法 ///<summary> ///分页计算 ///</summary> ///<returns></returns> publicList<PagingItem>CalcPages() { List<PagingItem>retPages=newList<PagingItem>(); //无需分页 if(Get_TableAllHeight()<=TableRect.Height) { PagingItemtmItem=newPagingItem(); tmItem.PageNum=; for(inty=;y<RowsList.Count;y++) { tmItem.IndexList.Add(y); } retPages.Add(tmItem); } else//需要分页 { //有设置了每页打印标题、表头、表位其中的任意一个 if(Get_IsCusSet_THDF())//则执行每页相对分页 { Paging_Relative(,refretPages); //计算每页打印头尾高度 MyHeadPix=; if(IsAllPrintTitle) { MyHeadPix+=Get_TableTileHeight(); } if(IsAllPrintHead) { MyHeadPix+=Get_TableHeadHeight(); } if(IsAllPrintFoot) { MyFootPix=Get_TableFootHeight(); } } else//执行直接数据分页 { Paging_Direct(,refretPages); } } returnretPages; } ///<summary> ///直接分页 ///</summary> ///<paramname="startR">开始行号</param> ///<paramname="pages">页面数组</param> privatevoidPaging_Direct(intstartR,refList<PagingItem>pages) { floatp_Height=TableRect.Height; PagingItemp_Item=newPagingItem(); p_Item.PageNum=pages.Count+; for(intt=startR;t<RowsList.Count;t++) { //检查行内单元格是否不允许分页两种情况:条形码,图片 if(Paging_CheckCell(RowsList[t],p_Height)) { startR=t; pages.Add(p_Item); Paging_Direct(startR,refpages); break; } else { p_Height-=RowsList[t].RowHeight; if(p_Height<=) { startR=t; pages.Add(p_Item); Paging_Direct(startR,refpages); break; } else { p_Item.IndexList.Add(t); if(t==RowsList.Count-) { pages.Add(p_Item); } } } } } ///<summary> ///相对分页 ///</summary> ///<paramname="startR">开始序号</param> ///<paramname="pages">页面数组</param> privatevoidPaging_Relative(intstartR,refList<PagingItem>pages) { SplitReportArea();//拆分表行 floatp_Height=TableRect.Height;//页面总高 PagingItemp_Item=newPagingItem();//分页页面 p_Item.PageNum=pages.Count+;//分页页码 boolrunNext=false;//继续分页 #region每页打印标题 //每页打印标题 if(IsAllPrintTitle) { p_Height-=Get_TableTileHeight(); foreach(Rowp_RowinTitleList) p_Item.IndexList.Add(p_Row.RowIndex); } else { if(p_Item.PageNum==)//第一页特殊处理 { p_Height-=Get_TableTileHeight(); foreach(Rowp_RowinTitleList) p_Item.IndexList.Add(p_Row.RowIndex); } } #endregion #region每页打印表头 //每页打印表头 if(IsAllPrintHead) { if(p_Item.PageNum==)//第一页特殊处理 { //计算表头前的行高 p_Height-=Get_TableHForHeight(); foreach(Rowp_RowinHForeList) p_Item.IndexList.Add(p_Row.RowIndex); } //计算表头行的高度 p_Height-=Get_TableHeadHeight(); foreach(Rowp_RowinHeadList) p_Item.IndexList.Add(p_Row.RowIndex); } else { if(p_Item.PageNum==)//第一页特殊处理 { //计算表头前的行高 p_Height-=Get_TableHForHeight(); foreach(Rowp_RowinHForeList) p_Item.IndexList.Add(p_Row.RowIndex); //计算表头行的高度 p_Height-=Get_TableHeadHeight(); foreach(Rowp_RowinHeadList) p_Item.IndexList.Add(p_Row.RowIndex); } } #endregion #region每页数据区域 //每页数据划分 if(IsAllPrintFoot) { p_Height-=Get_TableFootHeight();//表格高度先减去表尾的高度 } for(intt=startR;t<DataList.Count;t++) { //检查行内单元格是否不允许分页两种情况:条形码,图片 if(Paging_CheckCell(DataList[t],p_Height))//此情况下,单元格不能分割,并且高度超过页面剩余高度,所以要启动新的一页 { startR=t; runNext=true; break; } else { p_Height-=DataList[t].RowHeight; if(p_Height<=) { startR=t; runNext=true; break; } else { p_Item.IndexList.Add(DataList[t].RowIndex); } } } #endregion #region每页打印表尾 //每页打印表尾 if(IsAllPrintFoot) { foreach(Rowp_RowinFootList) p_Item.IndexList.Add(p_Row.RowIndex); } #endregion #region添加分页页面 pages.Add(p_Item); if(runNext) { Paging_Relative(startR,refpages); } #endregion } ///<summary> ///检查行内单元格如果是图片 ///并且合并行数大于 ///</summary> ///<paramname="cRow"></param> ///<paramname="cHeight"></param> ///<returns></returns> privateboolPaging_CheckCell(RowcRow,floatcHeight) { foreach(CellcCellincRow.RowCells) { if(cCell.IsImage==true) { if(cCell.RectH>cHeight) returntrue; } } returnfalse; } #endregion #region辅助方法 ///<summary> ///获取--报表全部高度 ///</summary> ///<returns></returns> privatefloatGet_TableAllHeight() { floatretHight=; for(intk=;k<RowsList.Count;k++) { Rowt_Row=RowsList[k]; retHight+=t_Row.RowHeight; } returnretHight; } ///<summary> ///获取是否设置了标题、表头、表尾中的任意一个 ///</summary> ///<returns></returns> privateboolGet_IsCusSet_THDF() { stringtmType=""; foreach(RowcusRowinthis.RowsList) { tmType=cusRow.RowType.ToLower().Trim(); if(tmType=="t"||tmType=="h"||tmType=="f") returntrue; } returnfalse; } ///<summary> ///获取--报表标题高度 ///</summary> ///<returns></returns> privatefloatGet_TableTileHeight() { floatretHight=; for(intk=;k<TitleList.Count;k++) retHight+=TitleList[k].RowHeight; returnretHight; } ///<summary> ///获取--报表表头前高度 ///</summary> ///<returns></returns> privatefloatGet_TableHForHeight() { floatretHight=; for(intk=;k<HForeList.Count;k++) retHight+=HForeList[k].RowHeight; returnretHight;