网页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;