你的位置:首页 > ASP.net教程

[ASP.net教程]网页WEB打印控件制作


    在WEB系统中,打印的确是比较烦人的问题,如果我们能制作一个属于自己的自定义的打印插件,那么我们在后续自定义打印的时候能随心所欲的控制打印,这样的效果对于程序员来说是非常开心的一件事件,本文将自己开发编写的C# 制作的HTML打印插件分享出来,让有同样需求的朋友提供一个参考;此插件是基于Microsoft .NET Framework 2.0 开发的,缺点是每台客户端在安装插件时,必须要安装Microsoft .NET Framework 2.0 ;本插件能实现 页眉、页脚、表头、标题、表尾的分页打印;支持纸张类型、自动补充空行等功能;由于技术有限,肯定有很多不足的地方,请批评指正!

    由于本打印插件是基于我们开发平台的报表基础来开发设计的,所以打印控件的原理:通过JS将页面表格数据生成固定格式的

   打印插件完整源码:E_Print.rar   (包含插件源码、打包程序、winform调试DEMO)

   下面贴出源码:(在源码中有详细的注释说明)

1、PrintControl 打印插件类

 

  1 using System;  2 using System.Collections.Generic;  3 using System.ComponentModel;  4 using System.Drawing;  5 using System.Data;  6 using System.Text;  7 using System.Windows.Forms;  8 using System.Runtime.InteropServices;  9 using System.Drawing.Printing; 10 using System. 11 using System.Security; 12 using System.Drawing.Drawing2D; 13 using System.Drawing.Text; 14 using System.Text.RegularExpressions; 15  16 namespace E_Print 17 { 18   /// <summary> 19   /// 打印控件 20   /// 实现IObjectSafety接口 21   /// 网页上所有所使用到的GUID 通过Guid工具生成的唯一编码 22   /// 74D1ED1D-B1A7-4039-A060-6F544FBE99EC 编码以后不允许修改 23   /// </summary> 24   [Guid("74D1ED1D-B1A7-4039-A060-6F544FBE99EC"), ProgId("EReportPrint"), ComVisible(true)] 25   public partial class PrintControl : UserControl, IObjectSafety 26   { 27     #region 私有变量 28  29     #region 通用参数 30  31     /// <summary> 32     /// 缩放比例 33     /// </summary> 34     private float Zoom = 1; 35  36     /// <summary> 37     /// 网页高度 像素 px 38     /// </summary> 39     private float HtmlHeight = 0; 40  41     /// <summary> 42     /// 网页宽度 像素 px 43     /// </summary> 44     private float HtmlWidth = 0; 45  46     /// <summary> 47     /// 报表区域矩形 48     /// </summary> 49     private RectangleF TableRect = new RectangleF(); 50  51     /// <summary> 52     /// 报表绘制实例 53     /// </summary> 54     private ReportDraw RptDraw = new ReportDraw(); 55  56     #endregion 57  58     #region 页边距 59  60     /// <summary> 61     /// 左边距  62     /// 毫米 mm(一位小数) 63     /// </summary> 64     private float _marginLeft = 9.9f; 65  66     /// <summary> 67     /// 右边距 68     /// </summary> 69     private float _marginRight = 9.9f; 70  71     /// <summary> 72     /// 上边距 73     /// </summary> 74     private float _marginTop = 9.9f; 75  76     /// <summary> 77     /// 下边距 78     /// </summary> 79     private float _marginBottom = 9.9f; 80  81     #endregion 82  83     #region 版型方向 84  85     /// <summary> 86     /// 版型方向 Landscape: true 横向;false 纵向 87     /// </summary> 88     private bool _landscape = false; 89  90     #endregion 91  92     #region 纸型大小 93  94     /// <summary> 95     /// 纸张类型 96     /// </summary> 97     private string _paperName = "A4"; 98  99     /// <summary> 100     /// 纸张宽度 101     /// </summary> 102     private int _paperWidth = 210;  // 毫米 103  104     /// <summary> 105     /// 纸张高度 106     /// </summary> 107     private int _paperHeight = 297;  // 毫米 108  109     #endregion 110  111     #region 打印参数 112  113     /// <summary> 114     /// 自适应纸张大小方法  115     /// null: 无 116     /// row:  横向 117     /// col: 纵向 118     /// </summary> 119     private string _zoomType = "null"; 120  121     /// <summary> 122     /// 是否每页打印标题 123     /// </summary> 124     private bool _isTblTitleAllPage = false; 125  126     /// <summary> 127     /// 是否每页打印表头 128     /// </summary> 129     private bool _isTblHeadAllPage = false; 130  131     /// <summary> 132     /// 是否每页打印表尾 133     /// </summary> 134     private bool _isTblFootAllPage = false; 135  136     /// <summary> 137     /// 最后一页自动补行 138     /// </summary> 139     private bool _isAutoFillRow = false; 140  141     /// <summary> 142     /// 字符溢出是否换行缩小处理方式 143     /// </summary> 144     private bool _isOverFlow = false; 145  146     /// <summary> 147     /// 打印数据 148     /// </summary> 149     private string _data""; 150  151     #endregion 152  153     #region 页眉参数 154  155     /// <summary> 156     /// 页眉--绘制页眉 157     /// </summary> 158     private bool _headDraw = false; 159  160     /// <summary> 161     /// 页眉--高度 毫米 162     /// 默认 10 刚好 163     /// </summary> 164     private float _headHeight = 10.0f; 165  166     /// <summary> 167     /// 页眉--左侧文字 168     /// </summary> 169     private string _headLeft = ""; 170  171     /// <summary> 172     /// 页眉--中间文字 173     /// </summary> 174     private string _headCenter = ""; 175  176     /// <summary> 177     /// 页眉--右侧文字 178     /// </summary> 179     private string _headRight = ""; 180  181     /// <summary> 182     /// 页眉--字体名称 183     /// </summary> 184     private string _headFontName = "宋体"; 185  186     /// <summary> 187     /// 页眉--字体大小 188     /// </summary> 189     private string _headFontSize = "9pt"; 190  191     /// <summary> 192     /// 页眉--字体颜色 193     /// </summary> 194     private string _headFontColor = "Black"; 195  196     /// <summary> 197     /// 页眉--字体--粗体 198     /// </summary> 199     private bool _headFontBold = false; 200  201     /// <summary> 202     /// 页眉--字体--斜体 203     /// </summary> 204     private bool _headFontItalic = false; 205  206     /// <summary> 207     /// 页眉--字体--删除线 208     /// </summary> 209     private bool _headFontStrikeout = false; 210  211     /// <summary> 212     /// 页眉--字体--下划线 213     /// </summary> 214     private bool _headFontUnderline = false; 215  216     /// <summary> 217     /// 页眉--绘制分隔线 218     /// </summary> 219     private bool _headLineDraw = false; 220  221     /// <summary> 222     /// 页眉--分隔线宽度 223     /// </summary> 224     private float _headLineWidth = 1.0f; 225  226     /// <summary> 227     /// 页眉--分隔线线型 228     /// </summary> 229     private string _headLineDash = "solid"; 230  231     /// <summary> 232     /// 页眉--分隔线颜色 233     /// </summary> 234     private string _headLineColor = "Black"; 235  236     #endregion 237  238     #region 页脚参数 239  240     /// <summary> 241     /// 页脚--绘制页脚 242     /// </summary> 243     private bool _footDraw = false; 244  245     /// <summary> 246     /// 页脚--高度 毫米 247     /// </summary> 248     private float _footHeight = 10.0f; 249  250     /// <summary> 251     /// 页脚--左侧文字 252     /// </summary> 253     private string _footLeft = ""; 254  255     /// <summary> 256     /// 页脚--中间文字 257     /// </summary> 258     private string _footCenter = ""; 259  260     /// <summary> 261     /// 页脚--右侧文字 262     /// </summary> 263     private string _footRight = ""; 264  265     /// <summary> 266     /// 页脚--字体名称 267     /// </summary> 268     private string _footFontName = "宋体"; 269  270     /// <summary> 271     /// 页脚--字体大小 272     /// </summary> 273     private string _footFontSize = "9pt"; 274  275     /// <summary> 276     /// 页脚--字体颜色 277     /// </summary> 278     private string _footFontColor = "Black"; 279  280     /// <summary> 281     /// 页脚--字体--粗体 282     /// </summary> 283     private bool _footFontBold = false; 284  285     /// <summary> 286     /// 页脚--字体--斜体 287     /// </summary> 288     private bool _footFontItalic = false; 289  290     /// <summary> 291     /// 页脚--字体--删除线 292     /// </summary> 293     private bool _footFontStrikeout = false; 294  295     /// <summary> 296     /// 页脚--字体--下划线 297     /// </summary> 298     private bool _footFontUnderline = false; 299  300     /// <summary> 301     /// 页脚--绘制分隔线 302     /// </summary> 303     private bool _footLineDraw = false; 304  305     /// <summary> 306     /// 页脚--分隔线宽度 307     /// </summary> 308     private float _footLineWidth = 1.0f; 309  310     /// <summary> 311     /// 页脚--分隔线线型 312     /// </summary> 313     private string _footLineDash = "solid"; 314  315     /// <summary> 316     /// 页脚--分隔线颜色 317     /// </summary> 318     private string _footLineColor = "Black"; 319  320     #endregion 321  322     #endregion 323  324     #region 构造方法 325  326     /// <summary> 327     /// 打印控件构造函数 328     /// </summary> 329     public PrintControl() 330     { 331       InitializeComponent(); 332       Init_PageSetting(); 333     } 334  335     #endregion 336  337     #region 接口实现 338  339     private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}"; 340     private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}"; 341     private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}"; 342     private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}"; 343     private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}"; 344  345     private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001; 346     private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002; 347     private const int S_OK = 0; 348     private const int E_FAIL = unchecked((int)0x80004005); 349     private const int E_NOINTERFACE = unchecked((int)0x80004002); 350  351     private bool _fSafeForScripting = true; 352     private bool _fSafeForInitializing = true; 353  354     public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions) 355     { 356       int Rslt = E_FAIL; 357  358       string strGUID = riid.ToString("B"); 359       pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA; 360       switch (strGUID) 361       { 362         case _IID_IDispatch: 363         case _IID_IDispatchEx: 364           Rslt = S_OK; 365           pdwEnabledOptions = 0; 366           if (_fSafeForScripting == true) 367             pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER; 368           break; 369         case _IID_IPersistStorage: 370         case _IID_IPersistStream: 371         case _IID_IPersistPropertyBag: 372           Rslt = S_OK; 373           pdwEnabledOptions = 0; 374           if (_fSafeForInitializing == true) 375             pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA; 376           break; 377         default: 378           Rslt = E_NOINTERFACE; 379           break; 380       } 381  382       return Rslt; 383     } 384  385     public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions) 386     { 387       int Rslt = E_FAIL; 388       string strGUID = riid.ToString("B"); 389       switch (strGUID) 390       { 391         case _IID_IDispatch: 392         case _IID_IDispatchEx: 393           if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true)) 394             Rslt = S_OK; 395           break; 396         case _IID_IPersistStorage: 397         case _IID_IPersistStream: 398         case _IID_IPersistPropertyBag: 399           if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true)) 400             Rslt = S_OK; 401           break; 402         default: 403           Rslt = E_NOINTERFACE; 404           break; 405       } 406  407       return Rslt; 408     } 409  410     #endregion 411  412     #region 属性方法 413  414     #region 页边距 415  416     /// <summary> 417     /// 获取--设置--左边距 418     /// 计量单位 毫米(mm) 419     /// </summary> 420     public float MARGINLEFT 421     { 422       get { return _marginLeft; } 423       set { _marginLeft = value; } 424     } 425  426     /// <summary> 427     /// 获取--设置--右边距 428     /// 计量单位 毫米(mm) 429     /// </summary> 430     public float MARGINRIGHT 431     { 432       get { return _marginRight; } 433       set { _marginRight = value; } 434     } 435  436     /// <summary> 437     /// 获取--设置--上边距 438     /// 计量单位 毫米(mm)  439     /// </summary> 440     public float MARGINTOP 441     { 442       get { return _marginTop; } 443       set { _marginTop = value; } 444     } 445  446     /// <summary> 447     /// 获取--设置--下边距 448     /// 计量单位 毫米(mm)  449     /// </summary> 450     public float MARGINBOTTOM 451     { 452       get { return _marginBottom; } 453       set { _marginBottom = value; } 454     } 455  456     #endregion 457  458     #region 版型方向 459  460     /// <summary> 461     /// 获取--设置--版型方向 462     /// Landscape: true 横向; false 纵向 463     /// </summary> 464     public bool LANDSCAPE 465     { 466       get { return _landscape; } 467       set { _landscape = value; } 468     } 469  470     #endregion 471  472     #region 纸张属性 473  474     /// <summary> 475     /// 获取--设置--纸张类型 476     /// </summary> 477     public string PAPERNAME 478     { 479       get { return _paperName; } 480       set { _paperName = value; } 481     } 482  483     /// <summary> 484     /// 获取--设置--纸张高度 485     /// 计量单位 毫米(mm) 486     /// </summary> 487     public int PAPERHEIGHT 488     { 489       get { return _paperHeight; } 490       set { _paperHeight = value; } 491     } 492  493     /// <summary> 494     /// 获取--设置--纸张宽度 495     /// 计量单位 毫米(mm) 496     /// </summary> 497     public int PAPERWIDTH 498     { 499       get { return _paperWidth; } 500       set { _paperWidth = value; } 501     } 502  503     #endregion 504  505     #region 页眉参数 506  507     /// <summary> 508     /// 获取--设置--页眉是否绘制 509     /// </summary> 510     public bool HEADDRAW 511     { 512       get { return _headDraw; } 513       set { _headDraw = value; } 514     } 515  516     /// <summary> 517     /// 获取--设置--页眉高度 518     /// 单位:毫米整数类型 519     /// </summary> 520     public float HEADHEIGHT 521     { 522       get { return _headHeight; } 523       set { _headHeight = value; } 524     } 525  526     /// <summary> 527     /// 获取--设置--页眉左侧文字 528     /// </summary> 529     public string HEADLEFT 530     { 531       get { return _headLeft; } 532       set { _headLeft = value; } 533     } 534  535     /// <summary> 536     /// 获取--设置--页眉中间文字 537     /// </summary> 538     public string HEADCENTER 539     { 540       get { return _headCenter; } 541       set { _headCenter = value; } 542     } 543  544     /// <summary> 545     /// 获取--设置--页眉右侧文字 546     /// </summary> 547     public string HEADRIGHT 548     { 549       get { return _headRight; } 550       set { _headRight = value; } 551     } 552  553     /// <summary> 554     /// 获取--设置--页眉字体名称 555     /// </summary> 556     public string HEADFONTNAME 557     { 558       get { return _headFontName; } 559       set { _headFontName = value; } 560     } 561  562     /// <summary> 563     /// 获取--设置--页眉字体大小 564     /// </summary> 565     public string HEADFONTSIZE 566     { 567       get { return _headFontSize; } 568       set { _headFontSize = value; } 569     } 570  571     /// <summary> 572     /// 获取--设置--页眉字体颜色 573     /// </summary> 574     public string HEADFONTCOLOR 575     { 576       get { return _headFontColor; } 577       set { _headFontColor = value; } 578     } 579  580     /// <summary> 581     /// 获取--设置--页眉字体--粗体 582     /// </summary> 583     public bool HEADFONTBOLD 584     { 585       get { return _headFontBold; } 586       set { _headFontBold = value; } 587     } 588  589     /// <summary> 590     /// 获取--设置--页眉字体--斜体 591     /// </summary> 592     public bool HEADFONTITALIC 593     { 594       get { return _headFontItalic; } 595       set { _headFontItalic = value; } 596     } 597  598     /// <summary> 599     /// 获取--设置--页眉字体--删除线 600     /// </summary> 601     public bool HEADFONTSTRIKEOUT 602     { 603       get { return _headFontStrikeout; } 604       set { _headFontStrikeout = value; } 605     } 606  607     /// <summary> 608     /// 获取--设置--页眉字体--下划线 609     /// </summary> 610     public bool HEADFONTUNDERLINE 611     { 612       get { return _headFontUnderline; } 613       set { _headFontUnderline = value; } 614     } 615  616     /// <summary> 617     /// 获取--设置--是否绘制分割线 618     /// </summary> 619     public bool HEADLINEDRAW 620     { 621       get { return _headLineDraw; } 622       set { _headLineDraw = value; } 623     } 624  625     /// <summary> 626     /// 获取--设置--页眉分隔线宽度 627     /// </summary> 628     public float HEADLINEWIDTH 629     { 630       get { return _headLineWidth; } 631       set { _headLineWidth = value; } 632     } 633  634     /// <summary> 635     /// 获取--设置--页眉分隔线线型 636     /// </summary> 637     public string HEADLINEDASH 638     { 639       get { return _headLineDash; } 640       set { _headLineDash = value; } 641     } 642  643     /// <summary> 644     /// 获取--设置--页眉分隔线颜色 645     /// </summary> 646     public string HEADLINECOLOR 647     { 648       get { return _headLineColor; } 649       set { _headLineColor = value; } 650     } 651  652     #endregion 653  654     #region 页脚参数 655  656     /// <summary> 657     /// 获取--设置--页脚是否绘制 658     /// </summary> 659     public bool FOOTDRAW 660     { 661       get { return _footDraw; } 662       set { _footDraw = value; } 663     } 664  665     /// <summary> 666     /// 获取--设置--页脚高度 667     /// 单位:毫米整数类型 668     /// </summary> 669     public float FOOTHEIGHT 670     { 671       get { return _footHeight; } 672       set { _footHeight = value; } 673     } 674  675     /// <summary> 676     /// 获取--设置--页脚左侧文字 677     /// </summary> 678     public string FOOTLEFT 679     { 680       get { return _footLeft; } 681       set { _footLeft = value; } 682     } 683  684     /// <summary> 685     /// 获取--设置--页脚中间文字 686     /// </summary> 687     public string FOOTCENTER 688     { 689       get { return _footCenter; } 690       set { _footCenter = value; } 691     } 692  693     /// <summary> 694     /// 获取--设置--页脚右侧文字 695     /// </summary> 696     public string FOOTRIGHT 697     { 698       get { return _footRight; } 699       set { _footRight = value; } 700     } 701  702     /// <summary> 703     /// 获取--设置--页脚字体名称 704     /// </summary> 705     public string FOOTFONTNAME 706     { 707       get { return _footFontName; } 708       set { _footFontName = value; } 709     } 710  711     /// <summary> 712     /// 获取--设置--页脚字体大小 713     /// </summary> 714     public string FOOTFONTSIZE 715     { 716       get { return _footFontSize; } 717       set { _footFontSize = value; } 718     } 719  720     /// <summary> 721     /// 获取--设置--页脚字体颜色 722     /// </summary> 723     public string FOOTFONTCOLOR 724     { 725       get { return _footFontColor; } 726       set { _footFontColor = value; } 727     } 728  729     /// <summary> 730     /// 获取--设置--页脚字体--粗体 731     /// </summary> 732     public bool FOOTFONTBOLD 733     { 734       get { return _footFontBold; } 735       set { _footFontBold = value; } 736     } 737  738     /// <summary> 739     /// 获取--设置--页脚字体--斜体 740     /// </summary> 741     public bool FOOTFONTITALIC 742     { 743       get { return _footFontItalic; } 744       set { _footFontItalic = value; } 745     } 746  747     /// <summary> 748     /// 获取--设置--页脚字体--删除线 749     /// </summary> 750     public bool FOOTFONTSTRIKEOUT 751     { 752       get { return _footFontStrikeout; } 753       set { _footFontStrikeout = value; } 754     } 755  756     /// <summary> 757     /// 获取--设置--页脚字体--下划线 758     /// </summary> 759     public bool FOOTFONTUNDERLINE 760     { 761       get { return _footFontUnderline; } 762       set { _footFontUnderline = value; } 763     } 764  765     /// <summary> 766     /// 获取--设置--是否绘制分割线 767     /// </summary> 768     public bool FOOTLINEDRAW 769     { 770       get { return _footLineDraw; } 771       set { _footLineDraw = value; } 772     } 773  774     /// <summary> 775     /// 获取--设置--页脚分隔线宽度 776     /// </summary> 777     public float FOOTLINEWIDTH 778     { 779       get { return _footLineWidth; } 780       set { _footLineWidth = value; } 781     } 782  783     /// <summary> 784     /// 获取--设置--页脚分隔线线型 785     /// </summary> 786     public string FOOTLINEDASH 787     { 788       get { return _footLineDash; } 789       set { _footLineDash = value; } 790     } 791  792     /// <summary> 793     /// 获取--设置--页脚分隔线颜色 794     /// </summary> 795     public string FOOTLINECOLOR 796     { 797       get { return _footLineColor; } 798       set { _footLineColor = value; } 799     } 800  801     #endregion 802  803     #region 打印参数 804  805     /// <summary> 806     /// 获取--设置--打印数据 807     /// 前台传入的 808     /// </summary> 809     public string DATA 810     { 811       get { return _data 812       set { _data value; } 813     } 814  815     /// <summary> 816     /// 获取--设置--是否每页打印标题 817     /// </summary> 818     public bool ISTBLTITLEALLPAGE 819     { 820       get { return _isTblTitleAllPage; } 821       set { _isTblTitleAllPage = value; } 822     } 823  824     /// <summary> 825     /// 获取--设置--是否每页打印表头 826     /// </summary> 827     public bool ISTBLHEADALLPAGE 828     { 829       get { return _isTblHeadAllPage; } 830       set { _isTblHeadAllPage = value; } 831     } 832  833     /// <summary> 834     /// 获取--设置--是否每页打印表尾 835     /// </summary> 836     public bool ISTBLFOOTALLPAGE 837     { 838       get { return _isTblFootAllPage; } 839       set { _isTblFootAllPage = value; } 840     } 841  842     /// <summary> 843     /// 获取--设置--末页自动补行 844     /// </summary> 845     public bool ISAUTOFILLROW 846     { 847       get { return _isAutoFillRow; } 848       set { _isAutoFillRow = value; } 849     } 850  851     /// <summary> 852     /// 获取--设置--缩放方向 853     /// 参数:以下三种;默认null 854     /// null: 无 855     /// row:  横向 856     /// col: 纵向 857     /// </summary> 858     public string ZOOMTYPE 859     { 860       get { return _zoomType; } 861       set { _zoomType = value; } 862     } 863  864     /// <summary> 865     /// 获取--设置--字符溢出是否缩小换行处理方式 866     /// </summary> 867     public bool ISOVERFLOW 868     { 869       get { return _isOverFlow; } 870       set { _isOverFlow = value; } 871     } 872  873     #endregion 874  875     #region 加载参数 876  877     /// <summary> 878     /// 加载打印参数 879     /// </summary> 880     public void INITPRINTPARAM() 881     { 882       Init_PageSetting(); 883     } 884  885     #endregion 886  887     #endregion 888  889     #region 加载事件 890  891     /// <summary> 892     /// 初始化--页面设置参数 893     /// </summary> 894     private void Init_PageSetting() 895     { 896       this.E_PrintDocument.DefaultPageSettings.Margins.Left = (int)Math.Round(MARGINLEFT * 10);   // 左边距 897       this.E_PrintDocument.DefaultPageSettings.Margins.Right = (int)Math.Round(MARGINRIGHT * 10);  // 右边距 898       this.E_PrintDocument.DefaultPageSettings.Margins.Top = (int)Math.Round(MARGINTOP * 10);    // 上边距 899       this.E_PrintDocument.DefaultPageSettings.Margins.Bottom = (int)Math.Round(MARGINBOTTOM * 10); // 下边距 900  901       this.E_PrintDocument.PrinterSettings.Copies = 1;                        // 打印份数 902       this.E_PrintDocument.DefaultPageSettings.Landscape = this.LANDSCAPE;              // 版型方向    903       PaperSize size = GetPaperSize(PAPERNAME);                           // 纸张类型 904       if (size != null) 905         this.E_PrintDocument.DefaultPageSettings.PaperSize = size; 906       else 907         this.E_PrintDocument.DefaultPageSettings.PaperSize = new PaperSize(this.PAPERNAME, (int)Math.Round(this.PAPERWIDTH / 25.4 * 100), (int)Math.Round(this.PAPERHEIGHT / 25.4 * 100)); 908     } 909  910     /// <summary> 911     /// 获取--纸张类型 912     /// </summary> 913     /// <param name="paperName">纸张类型名称</param> 914     /// <returns></returns> 915     private PaperSize GetPaperSize(string paperName) 916     { 917       PaperSize paper = null; 918       foreach (PaperSize ps in this.E_PrintDocument.PrinterSettings.PaperSizes) 919       { 920         if (ps.PaperName.ToLower() == paperName.ToLower()) // 检查打印机是否有指定的纸张类型 921         { 922           paper = ps; 923           break; 924         } 925       } 926       return paper; 927     } 928  929     #endregion 930  931     #region 打印事件 932  933     /// <summary> 934     /// 直接打印 935     /// 此处加入了再次调用打印设置界面,因为用户可能需要选择那种打印机 936     /// </summary> 937     /// <returns></returns> 938     public string PRINT() 939     { 940       // 直接打印时,直接调用printDocument的Print()方法 941       // 因为用户可能在打印之前还要再更改打印设置所以需再次显示打印设置对话框 942       if (this.E_PrintDialog.ShowDialog() == DialogResult.OK) 943       { 944         try 945         { 946           this.Init_Printer(); 947           this.E_PrintDocument.Print(); 948         } 949         catch (Exception ex) 950         { 951           this.E_PrintDocument.PrintController.OnEndPrint(this.E_PrintDocument, new PrintEventArgs()); 952           return ex.Message.ToString(); 953         } 954       } 955       return ""; 956     } 957  958     /// <summary> 959     /// 打印预览 960     /// 将打印的数据进行预览 961     /// </summary> 962     public string PREVIEW() 963     { 964       try 965       { 966         this.Init_Printer(); 967         this.E_PrintPreviewDialog.ShowDialog(); 968       } 969       catch (Exception ex) 970       { 971         return ex.Message.ToString(); 972       } 973  974       return ""; 975     } 976  977     /// <summary> 978     /// 页面设置 979     /// 设置打印的页面的纸张大小、纸型、页面边距 980     /// </summary> 981     public void PAGESTE() 982     { 983       // 页面设置对话框中使用的是公制长度计量单位 (厘米) 984       // 在.net中采用的是英制的计量单位 (英寸) 985       // 1英寸约等于2.54厘米,1厘米=10毫米 986       // 所以在下面中需要加入转换信息 将对话框中设置的页边距进行转换保存 987       // 设置传入的纸张信息 988       if (this.E_PageSetupDialog.ShowDialog() == DialogResult.OK)             // 弹出页面设置对话框 989       { 990         if (System.Globalization.RegionInfo.CurrentRegion.IsMetric)           // 转换页边距计量单位 991           this.E_PageSetupDialog.PageSettings.Margins = PrinterUnitConvert.Convert(this.E_PageSetupDialog.PageSettings.Margins, PrinterUnit.Display, PrinterUnit.TenthsOfAMillimeter); 992         this.E_PrintDocument.DefaultPageSettings = this.E_PageSetupDialog.PageSettings; // 更新页面设置参数值 993  994         // 更新参数 995         this.LANDSCAPE = this.E_PrintDocument.DefaultPageSettings.Landscape;              // 版型方向  996         this.PAPERNAME = this.E_PrintDocument.DefaultPageSettings.PaperSize.PaperName;         // 纸张类型 997         PaperSize tmPSize = this.E_PrintDocument.DefaultPageSettings.PaperSize;            // 纸张尺寸 998         this.PAPERWIDTH = (int)Math.Round(tmPSize.Width * 25.4 / 100);                 // 纸张宽度 999         this.PAPERHEIGHT = (int)Math.Round(tmPSize.Height * 25.4 / 100);                // 纸张高度1000         this.MARGINLEFT = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Left / 10f, 1);   // 左边距1001         this.MARGINRIGHT = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Right / 10f, 1);  // 右边距1002         this.MARGINTOP = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Top / 10f, 1);    // 上边距1003         this.MARGINBOTTOM = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Bottom / 10f, 1); // 下边距1004       }1005     }1006 1007     /// <summary>1008     /// 打印设置1009     /// 设置打印机的信息(选择打印机、设置打印份数等信息)1010     /// </summary>1011     public void PRINTSET()1012     {1013       this.E_PrintDialog.ShowDialog();1014     }1015 1016     #endregion1017 1018     #region 绘制对象1019 1020     /// <summary>1021     /// 打印及打印前初始化数据1022     /// </summary>1023     private void Init_Printer()1024     {1025       HtmlHeight = 0;                   // 网页报表高度1026       HtmlWidth = 0;                    // 网页报表宽度1027       CalcTableRect();                   // 计算区域矩形1028       RptDraw = new ReportDraw();             // 报表绘制实例1029       RptDraw.IsAllPrintTitle = this._isTblTitleAllPage;  // 每页打印标题1030       RptDraw.IsAllPrintHead = this._isTblHeadAllPage;   // 每页打印表头1031       RptDraw.IsAllPrintFoot = this._isTblFootAllPage;   // 每页打印表尾1032       RptDraw.IsAutoFillRow = this._isAutoFillRow;     // 末页自动补行1033       RptDraw.IsOverFlow = this._isOverFlow;        // 字符溢出缩小1034       RptDraw.ReptRect = TableRect;            // 赋值报表矩形1035       if (!Parsereturn;               // 解析报表数据1036       CalcReportZoom();                  // 计算缩小比例1037       CalcZoomAllSize();                  // 按比计算尺寸1038       RptDraw.Zoom = this.Zoom;              // 赋值缩小比例     1039       RptDraw.CalcPaging();                // 计算打印分页1040     }1041 1042     /// <summary>1043     /// PrintDocument 对象打印绘制事件1044     /// </summary>1045     /// <param name="sender"></param>1046     /// <param name="e"></param>1047     private void E_PrintDoc_PrintPage(object sender, PrintPageEventArgs e)1048     {1049       Graphics g = e.Graphics;1050       g.Clear(Color.White);1051       DrawHeader(g);1052       DrawFooter(g);1053       if (RptDraw.DrawReport(g))1054         e.HasMorePages = true;1055       else1056         e.HasMorePages = false;1057 1058     }1059 1060     /// <summary>1061     /// 绘制页眉1062     /// </summary>1063     /// <param name="g">绘图对象</param>1064     private void DrawHeader(Graphics g)1065     {1066       // 是否绘制1067       if (_headDraw)1068       {1069         // 页眉实例1070         PageHeader pgHeader = new PageHeader();1071 1072         // 页眉矩形1073         RectangleF pgHeaderRect = new RectangleF(TableRect.X,             // X 坐标1074                             TableRect.Y - mmToPixel(_headHeight), // Y 坐标   1075                             TableRect.Width,           // W 宽度1076                             mmToPixel(_headHeight)        // H 高度1077                              );1078 1079         // 页眉赋值1080         pgHeader.HeadRect = pgHeaderRect;1081         pgHeader.StrLeft = ReplacePageNum(_headLeft);   // 左侧文本1082         pgHeader.StrCenter = ReplacePageNum(_headCenter); // 中间文本 1083         pgHeader.StrRight = ReplacePageNum(_headRight);  // 右侧文本1084         FontStyle fontStyle = FontStyle.Regular;     // 字体样式1085         if (_headFontBold) fontStyle |= FontStyle.Bold;1086         if (_headFontItalic) fontStyle |= FontStyle.Italic;1087         if (_headFontStrikeout) fontStyle |= FontStyle.Strikeout;1088         if (_headFontUnderline) fontStyle |= FontStyle.Underline;1089 1090         pgHeader.StrFont = new Font(_headFontName, (float)Convert.ToDouble(_headFontSize.ToLower().Replace("px", "").Replace("pt", "")), fontStyle, GraphicsUnit.Point);1091         pgHeader.StrColor = (Color)PrintTool.StrToColor(_headFontColor);1092         if (_headLineDraw)                // 绘制分割线1093         {1094           pgHeader.LineDraw = _headLineDraw;1095           pgHeader.LineWidth = _headLineWidth;1096           pgHeader.LineColor = (Color)PrintTool.StrToColor(_headLineColor);1097           pgHeader.LineDash = PrintTool.GetDashStyle(_headLineDash);1098         }1099 1100         // 页眉绘制1101         pgHeader.Draw(g);1102       }1103     }1104 1105     /// <summary>1106     /// 绘制页脚1107     /// </summary>1108     /// <param name="g">绘图对象</param>1109     private void DrawFooter(Graphics g)1110     {1111       // 是否绘制1112       if (_footDraw)1113       {1114         // 页脚实例1115         PageFooter pgFooter = new PageFooter();1116 1117         // 页脚矩形1118         RectangleF pgFooterRect = new RectangleF(TableRect.X,           // X 坐标1119                             TableRect.Y + TableRect.Height, // Y 坐标   1120                             TableRect.Width,        // W 宽度1121                             mmToPixel(_footHeight)      // H 高度1122                              );1123         // 页脚赋值1124         pgFooter.FootRect = pgFooterRect;1125         pgFooter.StrLeft = ReplacePageNum(_footLeft);   // 左侧文本1126         pgFooter.StrCenter = ReplacePageNum(_footCenter); // 中间文本 1127         pgFooter.StrRight = ReplacePageNum(_footRight);  // 右侧文本1128         FontStyle fontStyle = FontStyle.Regular;     // 字体样式1129         if (_footFontBold) fontStyle |= FontStyle.Bold;1130         if (_footFontItalic) fontStyle |= FontStyle.Italic;1131         if (_footFontStrikeout) fontStyle |= FontStyle.Strikeout;1132         if (_footFontUnderline) fontStyle |= FontStyle.Underline;1133 1134         pgFooter.StrFont = new Font(_footFontName, (float)Convert.ToDouble(_footFontSize.ToLower().Replace("px", "").Replace("pt", "")), fontStyle, GraphicsUnit.Point);1135         pgFooter.StrColor = (Color)PrintTool.StrToColor(_footFontColor);1136         if (_footLineDraw)                // 绘制分割线1137         {1138           pgFooter.LineDraw = _footLineDraw;1139           pgFooter.LineWidth = _footLineWidth;1140           pgFooter.LineColor = (Color)PrintTool.StrToColor(_footLineColor);1141           pgFooter.LineDash = PrintTool.GetDashStyle(_footLineDash);1142         }1143 1144         // 页脚绘制1145         pgFooter.Draw(g);1146       }1147     }1148 1149     #endregion1150 1151     #region 辅助方法1152 1153     /// <summary>1154     /// 毫米 TO 像素1155     /// </summary>1156     /// <param name="mmValue">毫米值</param>1157     /// <returns></returns>1158     public static float mmToPixel(float mmValue) //mmValue是毫米,1厘米=10毫米1159     {1160       return (mmValue / 25.4f * 100f);1161     }1162 1163     /// <summary>1164     /// 替换 当前页码、总共页数两个变量1165     /// </summary>1166     /// <param name="str"></param>1167     /// <returns></returns>1168     private string ReplacePageNum(string str)1169     {1170       string retStr = "";1171       if (str == null || str.Trim() == "")1172         return retStr;1173       retStr = str;1174       int t = 0;1175       while (t >= 0)1176       {1177         t = retStr.IndexOf("[curpage]", StringComparison.OrdinalIgnoreCase);1178         if (t >= 0)1179         {1180           retStr = retStr.Substring(0, t) + RptDraw.CurPageNum.ToString() + retStr.Substring(t + "[curpage]".Length);1181         }1182       }1183 1184       t = 0;1185       while (t >= 0)1186       {1187         t = retStr.IndexOf("[allpage]", StringComparison.OrdinalIgnoreCase);1188         if (t >= 0)1189         {1190           retStr = retStr.Substring(0, t) + RptDraw.AllPageNum.ToString() + retStr.Substring(t + "[allpage]".Length);1191         }1192       }1193       return retStr;1194     }1195 1196     /// <summary>1197     /// 解析1198     /// </summary>1199     /// <returns>返回成功与否</returns>1200     private bool Parse1201     {1202       if (this.DATAnull || this.DATA"") return false;1203       new 1204       try1205       {1206         this.DATA1207          1208         if (rootNode.ChildNodes.Count == 0) return false;1209         if (rootNode.ChildNodes[0].Name.ToLower() != "table") return false;1210 1211         0]; // 表格节点1212         HtmlHeight = float.Parse(tableNode.Attributes["height"].Value);1213         HtmlWidth = float.Parse(tableNode.Attributes["width"].Value);1214 1215         int tmRowIndex = 0;1216         foreach (in tableNode.ChildNodes)1217         {1218           if (trNode.Name.ToLower() != "tr") continue;1219 1220           // 解析表格行1221           Row tmRow = new Row();1222           tmRow.RowIndex = tmRowIndex;1223           tmRow.RowHeight = float.Parse(trNode.Attributes["height"].Value);1224           tmRow.RowType = trNode.Attributes["rowtype"].Value.ToLower();1225 1226           // 解析单元格1227           foreach (in trNode.ChildNodes)1228           {1229             Cell tmCell = new Cell();1230 1231             #region 合并\坐标\矩形1232 1233             tmCell.RowSpan = Convert.ToInt32(tdNode.Attributes["rowspan"].Value);1234             tmCell.ColSpan = Convert.ToInt32(tdNode.Attributes["colspan"].Value);1235             tmCell.RowIndex = Convert.ToInt32(tdNode.Attributes["r"].Value);1236             tmCell.ColIndex = Convert.ToInt32(tdNode.Attributes["c"].Value);1237             tmCell.RectX = float.Parse(tdNode.Attributes["x"].Value);1238             tmCell.RectY = float.Parse(tdNode.Attributes["y"].Value);1239             tmCell.RectW = float.Parse(tdNode.Attributes["w"].Value);1240             tmCell.RectH = float.Parse(tdNode.Attributes["h"].Value);1241 1242             #endregion1243 1244             #region 设置单元格字体1245 1246             FontStyle tmStyle = new FontStyle();1247             tmStyle = FontStyle.Regular;1248             if (tdNode.Attributes["italic"].Value.ToString() == "1") tmStyle |= FontStyle.Italic;1249             if (tdNode.Attributes["bold"].Value.ToString() == "1") tmStyle |= FontStyle.Bold;1250             if (tdNode.Attributes["strikeout"].Value.ToString() == "1") tmStyle |= FontStyle.Strikeout;1251             if (tdNode.Attributes["underline"].Value.ToString() == "1") tmStyle |= FontStyle.Underline;1252             tmCell.CellFont = new Font(tdNode.Attributes["fontname"].Value, float.Parse(tdNode.Attributes["fontsize"].Value.Replace("pt", "").Replace("px", "")), tmStyle, GraphicsUnit.Point);1253             tmCell.FontColor = (Color)PrintTool.StrToColor(tdNode.Attributes["fontcolor"].Value);1254             tmCell.BackColor = (Color)PrintTool.StrToColor(tdNode.Attributes["backcolor"].Value);1255 1256             StringFormat tmFormat = new StringFormat();1257             switch (tdNode.Attributes["align"].Value.ToLower())   // 水平对齐方式1258             {1259               case "center":1260                 tmFormat.Alignment = StringAlignment.Center;1261                 break;1262               case "right":1263                 tmFormat.Alignment = StringAlignment.Far;1264                 break;1265               default:1266                 tmFormat.Alignment = StringAlignment.Near;1267                 break;1268             }1269             switch (tdNode.Attributes["valign"].Value.ToLower())  // 垂直对齐方式1270             {1271               case "middle":1272                 tmFormat.LineAlignment = StringAlignment.Center;1273                 break;1274               case "bottom":1275                 tmFormat.LineAlignment = StringAlignment.Far;1276                 break;1277               default:1278                 tmFormat.LineAlignment = StringAlignment.Near;1279                 break;1280             }1281             tmCell.strFormat = tmFormat;1282 1283             #endregion1284 1285             #region 内嵌图片-属性1286 1287             tmCell.IsImage = tdNode.Attributes["isimage"].Value.ToString() == "1" ? true : false;1288             if (tmCell.IsImage)1289               tmCell.ImageUrl = tdNode.Attributes["imageurl"].Value;1290             #endregion1291 1292             #region 单元格边框属性1293 1294             // 左边框线1295             string tmVal = tdNode.Attributes["leftwidth"].Value;1296             if (tmVal.IndexOf("px") >= 0)1297             {1298               tmCell.LeftBorder = new BorderLine(1299                                 float.Parse(tmVal.Replace("px", "")),1300                                 (Color)PrintTool.StrToColor(tdNode.Attributes["leftcolor"].Value),1301                                 PrintTool.GetDashStyle(tdNode.Attributes["leftdash"].Value)1302                                 );1303             }1304 1305             // 上边框线1306             tmVal = tdNode.Attributes["topwidth"].Value;1307             if (tmVal.IndexOf("px") >= 0)1308             {1309               tmCell.TopBorder = new BorderLine(1310                                 float.Parse(tmVal.Replace("px", "")),1311                                 (Color)PrintTool.StrToColor(tdNode.Attributes["topcolor"].Value),1312                                 PrintTool.GetDashStyle(tdNode.Attributes["topdash"].Value)1313                                );1314 1315             }1316 1317             // 右边框线1318             tmVal = tdNode.Attributes["rightwidth"].Value;1319             if (tmVal.IndexOf("px") >= 0)1320             {1321               tmCell.RightBorder = new BorderLine(1322                                  float.Parse(tmVal.Replace("px", "")),1323                                  (Color)PrintTool.StrToColor(tdNode.Attributes["rightcolor"].Value),1324                                  PrintTool.GetDashStyle(tdNode.Attributes["rightdash"].Value)1325                                 );1326             }1327 1328             // 下边框线1329             tmVal = tdNode.Attributes["bottomwidth"].Value;1330             if (tmVal.IndexOf("px") >= 0)1331             {1332               tmCell.BottomBorder = new BorderLine(1333                                  float.Parse(tmVal.Replace("px", "")),1334                                  (Color)PrintTool.StrToColor(tdNode.Attributes["bottomcolor"].Value),1335                                  PrintTool.GetDashStyle(tdNode.Attributes["bottomdash"].Value)1336                                 );1337             }1338 1339             #endregion1340 1341             #region 单据格数据数值1342 1343             tmCell.Value = tdNode.InnerText;1344 1345             #endregion1346 1347             // 加入对应的行内1348             tmRow.RowCells.Add(tmCell);1349           }1350 1351           RptDraw.RowsList.Add(tmRow);1352 1353           tmRowIndex++;1354         }1355       }1356       catch1357       {1358         return false;1359       }1360       finally1361       {1362         null;1363       }1364 1365       return true;1366     }1367 1368     /// <summary>1369     /// 计算报表区域矩形1370     /// 真实的绘制报表的区域1371     /// </summary>1372     private void CalcTableRect()1373     {1374       // 重新初始化实例1375       TableRect = new RectangleF();1376 1377       // 左顶点 X坐标1378       TableRect.X = mmToPixel(_marginLeft);1379 1380       // 左顶点 Y坐标1381       TableRect.Y = mmToPixel(_marginTop);1382       if (_headDraw) // 需要绘制页眉1383         TableRect.Y += mmToPixel(_headHeight);1384 1385       // 报表矩形宽度高度1386       if (this.LANDSCAPE) // 版型方向 横向1387       {1388         // 颠倒 宽高1389         TableRect.Width = mmToPixel((float)_paperHeight - _marginLeft - _marginRight);1390         TableRect.Height = mmToPixel((float)_paperWidth - _marginTop - _marginBottom);1391       }1392       else // 版型方向 纵向1393       {1394         TableRect.Width = mmToPixel((float)_paperWidth - _marginLeft - _marginRight);1395         TableRect.Height = mmToPixel((float)_paperHeight - _marginTop - _marginBottom);1396       }1397 1398       // 报表矩形高度缩减1399       if (_headDraw) // 需要绘制页眉1400         TableRect.Height -= mmToPixel(_headHeight);1401       if (_footDraw) // 需要绘制页脚1402         TableRect.Height -= mmToPixel(_footHeight);1403     }1404 1405     /// <summary>1406     /// 计算缩放比例1407     /// </summary>1408     private void CalcReportZoom()1409     {1410       if (this.ZOOMTYPE.ToLower() == "row")1411       {1412         if (Convert.ToInt32(TableRect.Width) >= HtmlWidth)1413           this.Zoom = 1;1414         else1415           this.Zoom = TableRect.Width / HtmlWidth;1416       }1417       else if (this.ZOOMTYPE.ToLower() == "col")1418       {1419         if (Convert.ToInt32(TableRect.Height) >= HtmlHeight)1420           this.Zoom = 1;1421         else1422           this.Zoom = TableRect.Height / HtmlHeight;1423       }1424       else1425       {1426         this.Zoom = 1;1427       }1428     }1429 1430     /// <summary>1431     /// 转换所有的尺寸1432     /// 根据缩放比例1433     /// </summary>1434     private void CalcZoomAllSize()1435     {1436       if (this.Zoom != 1)1437       {1438         // 转换HTML 高度宽度1439         HtmlWidth = HtmlWidth * Zoom;1440         HtmlHeight = HtmlHeight * Zoom;1441 1442         // 转换所有行号1443         foreach (Row zRow in this.RptDraw.RowsList)1444         {1445           // 行高缩小1446           zRow.RowHeight = zRow.RowHeight * Zoom;1447 1448           // 转换所有单元格 1449           foreach (Cell zCell in zRow.RowCells)1450           {1451             zCell.RectX = zCell.RectX * Zoom;1452             zCell.RectY = zCell.RectY * Zoom;1453             zCell.RectW = zCell.RectW * Zoom;1454             zCell.RectH = zCell.RectH * Zoom;1455 1456             zCell.TopBorder.LineWidth = zCell.TopBorder.LineWidth * Zoom;1457             zCell.BottomBorder.LineWidth = zCell.BottomBorder.LineWidth * Zoom;1458             zCell.LeftBorder.LineWidth = zCell.LeftBorder.LineWidth * Zoom;1459             zCell.RightBorder.LineWidth = zCell.RightBorder.LineWidth * Zoom;1460 1461             // 字体相应缩小1462             zCell.CellFont = new Font(zCell.CellFont.Name, zCell.CellFont.Size * Zoom, zCell.CellFont.Style, GraphicsUnit.Point);1463 1464           }1465         }1466       }1467     }1468 1469     #endregion1470 1471   }1472 }

View Code

 

2、ReportDraw 打印绘制类

 1 using System; 2 using System.Collections.Generic; 3 using System.Drawing; 4 using System.Drawing.Drawing2D; 5 using System.IO; 6  7 namespace E_Print 8 { 9   /// <summary> 10   /// 报表绘制 11   /// </summary> 12   public class ReportDraw 13   { 14     #region 私有成员 15  16     /// <summary> 17     /// 当前页码 18     /// </summary> 19     private int _curPageNum; 20  21     /// <summary> 22     /// 总共页数 23     /// </summary> 24     private int _allPageNum; 25  26     /// <summary> 27     /// 表格矩形 28     /// </summary> 29     private RectangleF _reptRect; 30  31     /// <summary> 32     /// 报表全部行集 33     /// </summary> 34     private List<Row> _rowsList; 35  36     /// <summary> 37     /// 分页页面数组 38     /// </summary> 39     private List<PagingItem> _pageList; 40  41     /// <summary> 42     /// 是否每页打印标题 43     /// </summary> 44     private bool _isAllPrintTitle; 45  46     /// <summary> 47     /// 是否每页打印表头 48     /// </summary> 49     private bool _isAllPrintHead; 50  51     /// <summary> 52     /// 是否每页打印表尾 53     /// </summary> 54     private bool _isAllPrintFoot; 55  56     /// <summary> 57     /// 是否末页自动补行 58     /// </summary> 59     private bool _isAutoFillRow; 60  61     /// <summary> 62     /// 缩小比例 63     /// </summary> 64     private float _zoom; 65  66     /// <summary> 67     /// 字符溢出处理方式 68     /// </summary> 69     private bool _isOverFlow; 70  71     /// <summary> 72     /// 每页打印的标题+表头的高度 73     /// </summary> 74     private float _headPix; 75  76     /// <summary> 77     /// 每页打印的表尾高度 78     /// </summary> 79     private float _footPix; 80  81     #endregion 82  83     #region 构造方法 84  85     /// <summary> 86     /// 构造函数 87     /// </summary> 88     public ReportDraw() 89     { 90       _curPageNum = 1; 91       _allPageNum = 1; 92       _reptRect = new RectangleF(); 93       _rowsList = new List<Row>(); 94       _pageList = new List<PagingItem>(); 95  96       _isAllPrintTitle = false; 97       _isAllPrintHead = false; 98       _isAllPrintFoot = false; 99       _isAutoFillRow = false;100 101       _zoom = 1;102       _isOverFlow = false;103       _headPix = 0;104       _footPix = 0;105     }106 107     /// <summary>108     /// 构造函数109     /// </summary>110     /// <param name="printTitle">每页打印标题</param>111     /// <param name="printHead">每页打印表头</param>112     /// <param name="printFoot">每页打印表位</param>113     /// <param name="fillRows">自动补全空行</param>114     /// <param name="tableRect">报表尺寸矩形</param>115     /// <param name="overFlow">字符溢出处理</param>116     public ReportDraw(bool printTitle, bool printHead, bool printFoot, bool fillRows, RectangleF tableRect, bool overFlow)117     {118 119       _reptRect = tableRect;120       _isAllPrintTitle = printTitle;121       _isAllPrintHead = printHead;122       _isAllPrintFoot = printFoot;123       _isAutoFillRow = fillRows;124       _isOverFlow = overFlow;125 126       _curPageNum = 1;127       _allPageNum = 1;128       _zoom = 1;129       _rowsList = new List<Row>();130       _pageList = new List<PagingItem>();131 132       _headPix = 0;133       _footPix = 0;134     }135 136     #endregion137 138     #region 属性方法139 140     /// <summary>141     /// 获取--设置--当前页码142     /// </summary>143     public int CurPageNum144     {145       get { return _curPageNum; }146       set { _curPageNum = value; }147     }148 149     /// <summary>150     /// 获取--设置--总共页数151     /// </summary>152     public int AllPageNum153     {154       get { return _allPageNum; }155       set { _allPageNum = value; }156     }157 158     /// <summary>159     /// 获取--设置--表格矩形160     /// </summary>161     public RectangleF ReptRect162     {163       get { return _reptRect; }164       set { _reptRect = value; }165     }166 167     /// <summary>168     /// 获取--设置--报表全部行集169     /// </summary>170     public List<Row> RowsList171     {172       get { return _rowsList; }173       set { _rowsList = value; }174     }175 176     /// <summary>177     /// 获取--设置--分页页面数组178     /// </summary>179     public List<PagingItem> PageList180     {181       get { return _pageList; }182       set { _pageList = value; }183     }184 185     /// <summary>186     /// 获取--设置--是否每页打印标题187     /// </summary>188     public bool IsAllPrintTitle189     {190       get { return _isAllPrintTitle; }191       set { _isAllPrintTitle = value; }192     }193 194     /// <summary>195     /// 获取--设置--是否每页打印表头196     /// </summary>197     public bool IsAllPrintHead198     {199       get { return _isAllPrintHead; }200       set { _isAllPrintHead = value; }201     }202 203     /// <summary>204     /// 获取--设置--是否每页打印表尾205     /// </summary>206     public bool IsAllPrintFoot207     {208       get { return _isAllPrintFoot; }209       set { _isAllPrintFoot = value; }210     }211 212     /// <summary>213     /// 获取--设置--末页是否自动补行214     /// </summary>215     public bool IsAutoFillRow216     {217       get { return _isAutoFillRow; }218       set { _isAutoFillRow = value; }219     }220 221     /// <summary>222     /// 获取--设置--缩小比例223     /// </summary>224     public float Zoom225     {226       get { return _zoom; }227       set { _zoom = value; }228     }229 230     /// <summary>231     /// 获取--设置--字符溢出处理方式232     /// </summary>233     public bool IsOverFlow234     {235       get { return _isOverFlow; }236       set { _isOverFlow = value; }237     }238 239     /// <summary>240     /// 获取--设置--每页打印的标题+表头高度241     /// </summary>242     public float HeadPix243     {244       get { return _headPix; }245       set { _headPix = value; }246     }247 248     /// <summary>249     /// 获取--设置--每页打印的表尾高度250     /// </summary>251     public float FootPix252     {253       get { return _footPix; }254       set { _footPix = value; }255     }256 257     #endregion258 259     #region 计算分页260 261     /// <summary>262     /// 计算分页263     /// </summary>264     public void CalcPaging()265     {266       // 分页实例267       PagingCalc insCalc = new PagingCalc();268       insCalc.TableRect = this.ReptRect;269       insCalc.RowsList = this.RowsList;270       insCalc.IsAllPrintTitle = this.IsAllPrintTitle;271       insCalc.IsAllPrintHead = this.IsAllPrintHead;272       insCalc.IsAllPrintFoot = this.IsAllPrintFoot;273 274       // 分页计算275       _pageList = insCalc.CalcPages();276       this._allPageNum = _pageList.Count;277       this._curPageNum = 1;278 279       this._headPix = insCalc.MyHeadPix;280       this._footPix = insCalc.MyFootPix;281     }282 283     #endregion284 285     #region 绘制方法286 287     /// <summary>288     /// 绘制报表289     /// </summary>290     /// <param name="g"></param>291     /// <returns>返回是否结束</returns>292     public bool DrawReport(Graphics g)293     {294       bool isMorePage = false;295       float offsetX = _reptRect.X; // X 偏移量296       float offsetY = _reptRect.Y; // Y 偏移量297 298       bool isCanFillRow = false;  // 是否需要补行299       bool isFillFlag = false;   // 是否已经补过300       int isFillRowNum = 0;     // 需要补充几行301 302       PagingItem nowPage = GetPageItem(CurPageNum);       // 当前页303       if (nowPage != null)304       {305         #region 判定高度不足是否自动补行306 307         // 判定补行条件 报表设置了末页不足自动补行、同时 为最后一页308         if (_isAutoFillRow == true && CurPageNum == AllPageNum)309         {310           // 判定页面高度 与 数据高度311           float N_PageHeith = ReptRect.Height;          // 当前页面高度312           float N_DataHeith = GetThisPageDataRowsHeight();    // 当前数据高度313 314           // 补行行高21315           while ((N_DataHeith + (isFillRowNum + 1) * 21 * Zoom) < N_PageHeith)316           {317             isFillRowNum++;318           }319 320           if (isFillRowNum > 0)321             isCanFillRow = true;322         }323 324         #endregion325 326         #region 首先绘制上一页补充单元格327 328         if (CurPageNum > 1)329         {330           PagingItem prePage = GetPageItem(CurPageNum - 1); // 上一页331           if (prePage != null)332           {333             foreach (PagingMakeUp tmMk in prePage.MakeupList)334             {335               // 绘制补充单元格(上页中未绘制完成的单元格)336               DrawTD(g, tmMk.MakeupCell, offsetX, offsetY, true, tmMk.MakeupHeight, false);337             }338           }339         }340 341         #endregion342 343         #region 其次绘制当前页面的单元格344 345         // 其次绘制当前页的单元格346         for (int ii = 0; ii < nowPage.IndexList.Count; ii++)347         {348           // 先绘制 TD CELL 单元格349           Row rowTR = GetRow(nowPage.IndexList[ii]);350 351           #region 执行补行352 353           if (isCanFillRow == true && rowTR.RowType.ToLower().Trim() == "f") // 需要补行 行标志为F 表尾前进行补充空行354           {355             Row fillRow = new Row();356             if (ii == 0)357               fillRow = rowTR;358             else359               fillRow = GetRow(nowPage.IndexList[ii - 1]);360             if (fillRow != null) // 绘制自动补充的空行单元格361             {362               // 开始补充空行         363               for (int fi = 1; fi <= isFillRowNum; fi++)364               {365                 bool bcFlag = true;366                 // 绘制单元格367                 foreach (Cell fillTdCell in fillRow.RowCells)368                 {369                   if (bcFlag)370                   {371                     // 绘制边框线(合并单元格的情况才用到)372                     if (fillTdCell.RectX > 0)373                     {374                       DrawLine(g, offsetX, offsetY, offsetX, offsetY + 21.0F * Zoom); // 最左边竖线375                       DrawLine(g, offsetX, offsetY + 21.0F * Zoom, offsetX + fillTdCell.RectX, offsetY + 21.0F * Zoom);376                     }377                     bcFlag = false;378                   }379                   DrawTD(g, fillTdCell, offsetX, offsetY, false, 0, true);380                 }381 382                 // 再将偏移量+行号 补充的行高全部为21px383                 offsetY += 21 * Zoom;384               }385             }386 387             isFillFlag = true;388           }389 390           #endregion391 392           #region 正常绘制393 394           foreach (Cell td in rowTR.RowCells)395           {396             DrawTD(g, td, offsetX, offsetY, false, 0, false);397           }398 399           // 再将偏移量+行号400           offsetY += rowTR.RowHeight;401 402           #endregion403         }404 405         // 判定是否补过;没有补充过,则在最后进行补充空行406         if ((isCanFillRow == true) && (isFillFlag == false) && (nowPage.IndexList.Count > 0))407         {408           Row fillRow = GetRow(nowPage.IndexList[nowPage.IndexList.Count - 1]);409           if (fillRow != null) // 绘制自动补充的空行单元格410           {411            412             // 开始补充空行413             for (int fi = 1; fi <= isFillRowNum; fi++)414             {415               bool newFlag = true;416               foreach (Cell fillTdCell in fillRow.RowCells)417               {418                 if (newFlag)419                 {420                   // 绘制边框线(合并单元格的情况才用到)421                   if (fillTdCell.RectX > 0)422                   {423                     DrawLine(g, offsetX, offsetY, offsetX, offsetY + 21.0F * Zoom); // 最左边竖线424                     DrawLine(g, offsetX, offsetY + 21.0F * Zoom, offsetX + fillTdCell.RectX, offsetY + 21.0F * Zoom);425                   }426                   newFlag = false;427                 }428                 DrawTD(g, fillTdCell, offsetX, offsetY, false, 0, true);429               }430               offsetY += 21 * Zoom; // 再将偏移量+行号 补充的行高全部为21px431             }432           }433         }434 435         #endregion436 437         if (CurPageNum < AllPageNum)438         {439           isMorePage = true; // 还有下页440           CurPageNum++;    // 页码增加441         }442       }443       return isMorePage;444     }445 446     /// <summary>447     /// 绘制单元格448     /// </summary>449     /// <param name="g">绘图对象</param>450     /// <param name="tdCell">单元格</param>451     /// <param name="setX">X偏移量</param>452     /// <param name="setY">Y坐标值</param>453     /// <param name="isMakeup">是否补充单元格</param>454     /// <param name="mkH">补充单元格高度</param>455     /// <param name="fillCell">自动补行的单元格</param>456     private void DrawTD(Graphics g, Cell tdCell, float setX, float setY, bool isMakeup, float mkH, bool fillCell)457     {458       #region 参数变量459 460       Pen pen;461       Brush brush;462 463       // 获取单元格绘制坐标矩形信息464       float tdX = tdCell.RectX + setX;465       float tdY = setY;466       float tdW = tdCell.RectW;467       float tdH = 0;468 469       if (fillCell)470       {471         tdH = 21 * Zoom; // 自动补行的单元格的高度固定为21px472       }473       else474       {475         if (isMakeup)      // 补充单元格476         {477           tdH = mkH;478           tdY = tdY + HeadPix; // 如果是补充单元格,则此单元格的Y坐标:如果每页打印标题或表头,则Y坐标 需要下移 HeadPix479         }480         else           // 实际单元格481         {482           tdH = tdCell.RectH;483         }484         if (tdCell.RowSpan > 1) // 判定单元格高度是否超过底线485         {486           tdH = Calc_CellOverHeight(tdCell, tdY, tdH);487         }488       }489 490       #endregion491 492       #region 绘制背景493 494       // 填充颜色495       brush = new SolidBrush(tdCell.BackColor);496       g.FillRectangle(brush, tdX + 1.0f * Zoom, tdY + 1.0f * Zoom, tdW - 2.0f * Zoom, tdH - 2.0f * Zoom);497 498       #endregion499 500       #region 绘制边框501 502       // 左边框线503       if (tdCell.LeftBorder.LineWidth > 0)504       {505         pen = new Pen(tdCell.LeftBorder.LineColor);506         pen.DashStyle = tdCell.LeftBorder.LineDash;507         pen.Width = tdCell.LeftBorder.LineWidth;508         g.DrawLine(pen, tdX, tdY, tdX, tdY + tdH);509       }510 511       // 上边框线512       if (tdCell.TopBorder.LineWidth > 0)513       {514         pen = new Pen(tdCell.TopBorder.LineColor);515         pen.DashStyle = tdCell.TopBorder.LineDash;516         pen.Width = tdCell.TopBorder.LineWidth;517         g.DrawLine(pen, tdX, tdY, tdX + tdW, tdY);518       }519 520       // 右边框线521       if (tdCell.RightBorder.LineWidth > 0)522       {523         pen = new Pen(tdCell.RightBorder.LineColor);524         pen.DashStyle = tdCell.RightBorder.LineDash;525         pen.Width = tdCell.RightBorder.LineWidth;526         g.DrawLine(pen, tdX + tdW, tdY, tdX + tdW, tdY + tdH);527       }528 529       // 下边框线530       if (tdCell.BottomBorder.LineWidth > 0)531       {532         pen = new Pen(tdCell.BottomBorder.LineColor);533         pen.DashStyle = tdCell.BottomBorder.LineDash;534         pen.Width = tdCell.BottomBorder.LineWidth;535         g.DrawLine(pen, tdX, tdY + tdH, tdX + tdW, tdY + tdH);536       }537 538       #endregion539 540       #region 绘制文字541 542       if (!fillCell)543       {544         RectangleF rect = new RectangleF(tdX, tdY, tdW, tdH);545         if (tdCell.IsImage)546         {547           this.DrawImg(g, rect, tdCell.ImageUrl);548         }549         else550         {551           brush = new SolidBrush(tdCell.FontColor);552           this.DrawStr(g, rect, brush, tdCell.CellFont, tdCell.strFormat, tdCell.Value);553         }554       }555 556       #endregion557     }558 559     /// <summary>560     /// 绘制字符串561     /// 溢出时,换行缩小字符562     /// 字体缩小到的最小值不得小于563     /// </summary>564     /// <param name="g">绘图对象</param>565     /// <param name="strRect">文本区域</param>566     /// <param name="strBrush">文本笔画</param>567     /// <param name="strFont">文本字体</param>568     /// <param name="strFormat">文本格式</param>569     /// <param name="strValue">文本字符</param>570     /// <returns></returns>571     private void DrawStr(Graphics g, RectangleF strRect, Brush strBrush, Font strFont, StringFormat strFormat, string strValue)572     {573       // 报表设置:字符溢出不做处理574       if (!this.IsOverFlow)575       {576         g.DrawString(strValue, strFont, strBrush, strRect, strFormat);577       }578       else // 需要处理579       {580         // 测量字体的宽度和高度 会发现误差很大,如果一个一个的测量,误差就实在太大,所以这里就用简单的方式来进行处理581         SizeF sf = g.MeasureString(strValue, strFont);  // 此种方式测量误差很大,如果582         if (strRect.Width > sf.Width)583         {584           g.DrawString(strValue, strFont, strBrush, strRect, strFormat);585         }586         else587         {588           // 计算换行后字符的全部高度是否满足589           int maxLines = 0; // 计算当前字符当前字体最大打印的行数590           maxLines = (int)Math.Ceiling((double)sf.Width / (double)strRect.Width);591           if (strRect.Height >= maxLines * sf.Height)592           {593             g.DrawString(strValue, strFont, strBrush, strRect, strFormat);594           }595           else596           {597             float tmScale = strRect.Height / (maxLines * sf.Height);598             Font tmNewFont = new Font(strFont.Name, strFont.Size * tmScale, strFont.Style, GraphicsUnit.Point);599             g.DrawString(strValue, tmNewFont, strBrush, strRect, strFormat);600           }601         }602       }603 604     }605 606     /// <summary>607     /// 绘制图片608     /// 将Base64图片流字符串转换成图片并进行绘制609     /// </summary>610     /// <param name="g"></param>611     /// <param name="strRect"></param>612     /// <param name="base64Img"></param>613     private void DrawImg(Graphics g, RectangleF strRect, string base64Img)614     {615       if (base64Img.Trim() == "") return;616       string imgStr = base64Img.Replace("data:image/gif;base64,", "").Trim();617       if (imgStr == "") return;618 619       // 生成图片620       try621       {622         MemoryStream stream = new MemoryStream(Convert.FromBase64String(imgStr));623         Bitmap picImg = new Bitmap(stream);624 625         RectangleF imgRectF = new RectangleF(0f, 0f, (float)picImg.Width, (float)picImg.Height);        // 原始图片矩形626         RectangleF newRectF = new RectangleF(strRect.X + 1f, strRect.Y + 1f, (float)strRect.Width - 2f, (float)strRect.Height - 2f); // 绘制图片矩形627         g.DrawImage(picImg, newRectF, imgRectF, GraphicsUnit.Pixel);        // 绘制缩放图片628         stream.Close();629       }630       catch631       {632         return;633       }634     }635 636     /// <summary>637     /// 绘制线条638     /// </summary>639     /// <param name="g">绘图对象</param>640     /// <param name="start_X">开始X</param>641     /// <param name="start_Y">开始Y</param>642     /// <param name="end_X">结束X</param>643     /// <param name="end_Y">结束Y</param>644     private void DrawLine(Graphics g, float start_X, float start_Y, float end_X, float end_Y)645     {646       Pen linePen = new Pen(Color.Black, 1.0f);647       linePen.DashStyle = DashStyle.Solid;648       g.DrawLine(linePen, start_X, start_Y, end_X, end_Y);649     }650 651     private float ChangeUnit(float vSize)652     {653       return (vSize * 72f / 96f * 72f / 75f);654     }655 656     /// <summary>657     /// 获取行对象658     /// </summary>659     /// <param name="rowIndex"></param>660     /// <returns></returns>661     private Row GetRow(int rowIndex)662     {663       foreach (Row retRow in _rowsList)664       {665         if (retRow.RowIndex == rowIndex)666           return retRow;667       }668       return null;669     }670 671     /// <summary>672     /// 获取分页页面673     /// </summary>674     /// <param name="pNo">页码</param>675     /// <returns></returns>676     private PagingItem GetPageItem(int pNo)677     {678       foreach (PagingItem retPItem in PageList)679       {680         if (retPItem.PageNum == pNo)681           return retPItem;682       }683 684       return null;685     }686 687     /// <summary>688     /// 计算绘制高度689     /// 判定并且计算单元格高度是否超过当前页面所有行高度的底线690     /// </summary>691     /// <param name="mCell">单元格</param>692     /// <param name="mY">Y 轴坐标值</param>693     /// <param name="mH">H 当前高度</param>694     /// <returns></returns>695     private float Calc_CellOverHeight(Cell mCell, float mY, float mH)696     {697       float returnHeight = 0;                   // 返回高度698       float tm_AllTrHeight = GetThisPageDataRowsHeight();     // 当前页面内所有数据行的高度699       float tm_RealY = 0;                     // 相对最大Y值700       float tm_AbsY = 0;                      // 实际最大Y值701       float tm_OverPlus = 0;                    // 单元格剩余高度702       tm_RealY = mY + mH;                     // 实际最大Y值703       if (IsAllPrintFoot)                     // 每页打印表尾704         tm_AbsY = ReptRect.Y + (tm_AllTrHeight - FootPix);    // 需要减去表尾高度705       else706         tm_AbsY = tm_AllTrHeight + ReptRect.Y;707 708       if (tm_RealY > tm_AbsY)709       {710         returnHeight = tm_AbsY - mY;   // 当前页面实际最大高度-单元格的当前Y坐标值 = 返回单元格在本页内需要绘制的高度711         tm_OverPlus = mH - returnHeight; // 当前高度-单元格当前页面需要绘制的高度=下页需要绘制的补充高度712 713         // 将当前单元格添加到后页需要补充绘制数组中去714         PagingItem nPageItem = GetPageItem(CurPageNum);715         PagingMakeUp nMakeUp = new PagingMakeUp();716         nMakeUp.MakeupCell = mCell;717         nMakeUp.MakeupHeight = tm_OverPlus;718         nPageItem.MakeupList.Add(nMakeUp);719       }720       else721       {722         returnHeight = mH;723       }724 725       return returnHeight;726     }727 728     /// <summary>729     /// 获取本页内所有数据行的高度730     /// </summary>731     /// <returns></returns>732     private float GetThisPageDataRowsHeight()733     {734       float retHeight = 0;735       PagingItem oThisPage = GetPageItem(CurPageNum);   // 当前页736 737       foreach (int oRowIndex in oThisPage.IndexList)738       {739         Row oThisRow = GetRow(oRowIndex);740         retHeight += oThisRow.RowHeight;741       }742 743       return retHeight;744     }745 746     /// <summary>747     /// 获取页内某一项所属行的高度748     /// </summary>749     /// <param name="itemPage">页面对象</param>750     /// <param name="itemIndex">本页行数组中的某一项的序号</param>751     /// <returns></returns>752     private float GetThisPageOneRowHeight(PagingItem itemPage, int itemIndex)753     {754       float retHeight = 0;755       if (itemIndex < itemPage.IndexList.Count && itemIndex >= 0)756       {757         Row oThisRow = GetRow(itemPage.IndexList[itemIndex]);758         retHeight = oThisRow.RowHeight;759       }760       return retHeight;761     }762 763     #endregion764 765   }766 }

View Code

3、PagingCalc 分页计算类

 1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Drawing; 5  6 namespace E_Print 7 { 8   /// <summary> 9   /// 分页计算 10   /// </summary> 11   public class PagingCalc 12   { 13     #region 私有变量 14  15     /// <summary> 16     /// 表格区域 17     /// </summary> 18     private RectangleF _tableRect; 19  20     /// <summary> 21     /// 报表行集 22     /// </summary> 23     private List<Row> _rowsList; 24  25     /// <summary> 26     /// 是否每页打印标题 27     /// </summary> 28     private bool _isAllPrintTitle; 29  30     /// <summary> 31     /// 是否每页打印表头 32     /// </summary> 33     private bool _isAllPrintHead; 34  35     /// <summary> 36     /// 是否每页打印表尾 37     /// </summary> 38     private bool _isAllPrintFoot; 39  40     /// <summary> 41     /// 标题行集 42     /// </summary> 43     private List<Row> TitleList; 44  45     /// <summary> 46     /// 表头前行集 47     /// </summary> 48     private List<Row> HForeList; 49  50     /// <summary> 51     /// 表头行集 52     /// </summary> 53     private List<Row> HeadList; 54  55     /// <summary> 56     /// 数据行集 57     /// </summary> 58     private List<Row> DataList; 59  60     /// <summary> 61     /// 表尾行集 62     /// </summary> 63     private List<Row> FootList; 64  65     /// <summary> 66     /// 每页打印标题+表头高度 67     /// </summary> 68     private float _myHeadPix; 69  70     /// <summary> 71     /// 每页打印表尾高度 72     /// </summary> 73     private float _myFootPix; 74  75     #endregion 76  77     #region 构造方法 78  79     /// <summary> 80     /// 构造函数 81     /// </summary> 82     public PagingCalc() 83     { 84       _tableRect = new RectangleF(); 85       _rowsList = new List<Row>(); 86  87       _isAllPrintTitle = false; 88       _isAllPrintHead = false; 89       _isAllPrintFoot = false; 90  91       TitleList = new List<Row>(); 92       HForeList = new List<Row>(); 93       HeadList = new List<Row>(); 94       DataList = new List<Row>(); 95       FootList = new List<Row>(); 96  97       _myHeadPix = 0; 98       _myFootPix = 0; 99     }100 101     #endregion102 103     #region 属性方法104 105     /// <summary>106     /// 获取--设置--表格区域107     /// </summary>108     public RectangleF TableRect109     {110       get { return _tableRect; }111       set { _tableRect = value; }112     }113 114     /// <summary>115     /// 获取--设置--表格行集116     /// </summary>117     public List<Row> RowsList118     {119       get { return _rowsList; }120       set { _rowsList = value; }121     }122 123     /// <summary>124     /// 获取--设置--是否每页打印标题125     /// </summary>126     public bool IsAllPrintTitle127     {128       get { return _isAllPrintTitle; }129       set { _isAllPrintTitle = value; }130     }131 132     /// <summary>133     /// 获取--设置--是否每页打印表头134     /// </summary>135     public bool IsAllPrintHead136     {137       get { return _isAllPrintHead; }138       set { _isAllPrintHead = value; }139     }140 141     /// <summary>142     /// 获取--设置--是否每页打印表尾143     /// </summary>144     public bool IsAllPrintFoot145     {146       get { return _isAllPrintFoot; }147       set { _isAllPrintFoot = value; }148     }149 150     /// <summary>151     /// 获取--设置--每页打印标题+表头高度152     /// </summary>153     public float MyHeadPix154     {155       get { return _myHeadPix; }156       set { _myHeadPix = value; }157     }158 159     /// <summary>160     /// 获取--设置--每页打印表尾巴高度161     /// </summary>162     public float MyFootPix163     {164       get { return _myFootPix; }165       set { _myFootPix = value; }166     }167 168     #endregion169 170     #region 计算方法171 172     /// <summary>173     /// 分页计算174     /// </summary>175     /// <returns></returns>176     public List<PagingItem> CalcPages()177     {178       List<PagingItem> retPages = new List<PagingItem>();179 180       // 无需分页181       if (Get_TableAllHeight() <= TableRect.Height)182       {183         PagingItem tmItem0 = new PagingItem();184         tmItem0.PageNum = 1;185         for (int y = 0; y < RowsList.Count; y++)186         {187           tmItem0.IndexList.Add(y);188         }189         retPages.Add(tmItem0);190       }191       else // 需要分页192       {193         // 有设置了 每页打印标题、表头、表位 其中的任意一个194         if (Get_IsCusSet_THDF()) // 则执行每页相对分页195         {196           Paging_Relative(0, ref retPages);197 198           // 计算每页打印头尾高度199           MyHeadPix = 0;200           if (IsAllPrintTitle)201           {202             MyHeadPix += Get_TableTileHeight();203           }204 205           if (IsAllPrintHead)206           {207             MyHeadPix += Get_TableHeadHeight();208           }209 210           if (IsAllPrintFoot)211           {212             MyFootPix = Get_TableFootHeight();213           }214         }215         else // 执行直接数据分页216         {217           Paging_Direct(0, ref retPages);218         }219       }220 221       return retPages;222     }223 224     /// <summary>225     /// 直接分页226     /// </summary>227     /// <param name="startR">开始行号</param>228     /// <param name="pages">页面数组</param>229     private void Paging_Direct(int startR, ref List<PagingItem> pages)230     {231       float p_Height = TableRect.Height;232       PagingItem p_Item = new PagingItem();233       p_Item.PageNum = pages.Count + 1;234       for (int t = startR; t < RowsList.Count; t++)235       {236         // 检查行内单元格是否不允许分页两种情况:条形码,图片237         if (Paging_CheckCell(RowsList[t], p_Height))238         {239           startR = t;240           pages.Add(p_Item);241           Paging_Direct(startR, ref pages);242           break;243         }244         else245         {246           p_Height -= RowsList[t].RowHeight;247           if (p_Height <= 0)248           {249             startR = t;250             pages.Add(p_Item);251             Paging_Direct(startR, ref pages);252             break;253           }254           else255           {256             p_Item.IndexList.Add(t);257             if (t == RowsList.Count - 1)258             {259               pages.Add(p_Item);260             }261           }262         }263       }264     }265 266     /// <summary>267     /// 相对分页268     /// </summary>269     /// <param name="startR">开始序号</param>270     /// <param name="pages">页面数组</param>271     private void Paging_Relative(int startR, ref List<PagingItem> pages)272     {273       SplitReportArea();           // 拆分表行274       float p_Height = TableRect.Height;   // 页面总高275       PagingItem p_Item = new PagingItem(); // 分页页面276       p_Item.PageNum = pages.Count + 1;   // 分页页码277       bool runNext = false;         // 继续分页278 279       #region 每页打印标题280 281       // 每页打印标题282       if (IsAllPrintTitle)283       {284         p_Height -= Get_TableTileHeight();285         foreach (Row p_Row in TitleList)286           p_Item.IndexList.Add(p_Row.RowIndex);287       }288       else289       {290         if (p_Item.PageNum == 1) // 第一页特殊处理291         {292           p_Height -= Get_TableTileHeight();293           foreach (Row p_Row in TitleList)294             p_Item.IndexList.Add(p_Row.RowIndex);295         }296       }297 298       #endregion299 300       #region 每页打印表头301 302       // 每页打印表头303       if (IsAllPrintHead)304       {305         if (p_Item.PageNum == 1) // 第一页特殊处理306         {307           // 计算表头前的行高308           p_Height -= Get_TableHForHeight();309           foreach (Row p_Row in HForeList)310             p_Item.IndexList.Add(p_Row.RowIndex);311         }312 313         // 计算表头行的高度314         p_Height -= Get_TableHeadHeight();315         foreach (Row p_Row in HeadList)316           p_Item.IndexList.Add(p_Row.RowIndex);317       }318       else319       {320         if (p_Item.PageNum == 1) // 第一页特殊处理321         {322           // 计算表头前的行高323           p_Height -= Get_TableHForHeight();324           foreach (Row p_Row in HForeList)325             p_Item.IndexList.Add(p_Row.RowIndex);326 327           // 计算表头行的高度328           p_Height -= Get_TableHeadHeight();329           foreach (Row p_Row in HeadList)330             p_Item.IndexList.Add(p_Row.RowIndex);331         }332       }333 334       #endregion335 336       #region 每页数据区域337 338       // 每页数据划分339       if (IsAllPrintFoot)340       {341         p_Height -= Get_TableFootHeight();       // 表格高度 先减去表尾的高度342       }343       for (int t = startR; t < DataList.Count; t++)344       {345         // 检查行内单元格是否不允许分页两种情况:条形码,图片346         if (Paging_CheckCell(DataList[t], p_Height)) // 此情况下,单元格不能分割,并且高度超过页面剩余高度,所以要启动新的一页347         {348           startR = t;349           runNext = true;350           break;351         }352         else353         {354           p_Height -= DataList[t].RowHeight;355           if (p_Height <= 0)356           {357             startR = t;358             runNext = true;359             break;360           }361           else362           {363             p_Item.IndexList.Add(DataList[t].RowIndex);364           }365         }366       }367 368       #endregion369 370       #region 每页打印表尾371 372       // 每页打印表尾373       if (IsAllPrintFoot)374       {375         foreach (Row p_Row in FootList)376           p_Item.IndexList.Add(p_Row.RowIndex);377       }378 379       #endregion380 381       #region 添加分页页面382 383       pages.Add(p_Item);384       if (runNext)385       {386         Paging_Relative(startR, ref pages);387       }388 389       #endregion390     }391 392     /// <summary>393     /// 检查行内单元格如果是图片394     /// 并且合并行数大于1395     /// </summary>396     /// <param name="cRow"></param>397     /// <param name="cHeight"></param>398     /// <returns></returns>399     private bool Paging_CheckCell(Row cRow, float cHeight)400     {401       foreach (Cell cCell in cRow.RowCells)402       {403         if (cCell.IsImage == true)404         {405           if (cCell.RectH > cHeight)406             return true;407         }408       }409       return false;410     }411 412     #endregion413 414     #region 辅助方法415 416     /// <summary>417     /// 获取--报表全部高度418     /// </summary>419     /// <returns></returns>420     private float Get_TableAllHeight()421     {422       float retHight = 0;423       for (int k = 0; k < RowsList.Count; k++)424       {425         Row t_Row = RowsList[k];426         retHight += t_Row.RowHeight;427       }428       return retHight;429     }430 431     /// <summary>432     /// 获取是否设置了标题、表头、表尾 中的任意一个433     /// </summary>434     /// <returns></returns>435     private bool Get_IsCusSet_THDF()436     {437       string tmType = "";438       foreach (Row cusRow in this.RowsList)439       {440         tmType = cusRow.RowType.ToLower().Trim();441         if (tmType == "t" || tmType == "h" || tmType == "f")442           return true;443       }444 445       return false;446     }447 448     /// <summary>449     /// 获取--报表标题高度450     /// </summary>451     /// <returns></returns>452     private float Get_TableTileHeight()453     {454       float retHight = 0;455       for (int k = 0; k < TitleList.Count; k++)456         retHight += TitleList[k].RowHeight;457 458       return retHight;459     }460 461     /// <summary>462     /// 获取--报表表头前高度463     /// </summary>464     /// <returns></returns>465     private float Get_TableHForHeight()466     {467       float retHight = 0;468       for (int k = 0; k < HForeList.Count; k++)469         retHight += HForeList[k].RowHeight;470 471       return retHight;472     }473 474     /// <summary>475     /// 获取--报表表头高度476     /// </summary>477     /// <returns></returns>478     private float Get_TableHeadHeight()479     {480       float retHight = 0;481       for (int k = 0; k < HeadList.Count; k++)482         retHight += HeadList[k].RowHeight;483       return retHight;484     }485 486     /// <summary>487     /// 获取--报表表尾高度488     /// </summary>489     /// <returns></returns>490     private float Get_TableFootHeight()491     {492       float retHight = 0;493       for (int k = 0; k < FootList.Count; k++)494         retHight += FootList[k].RowHeight;495       return retHight;496     }497 498     /// <summary>499     /// 拆分报表区域500     /// </summary>501     public void SplitReportArea()502     {503       TitleList = new List<Row>();504       HForeList = new List<Row>();505       HeadList = new List<Row>();506       DataList = new List<Row>();507       FootList = new List<Row>();508 509       for (int m = 0; m < RowsList.Count; m++)510       {511         Row mmRow = RowsList[m];512         switch (mmRow.RowType.ToLower())513         {514           case "t": // 标题515             TitleList.Add(mmRow);516             break;517           case "h": // 表头518             HeadList.Add(mmRow);519             break;520           case "f": // 表尾521             FootList.Add(mmRow);522             break;523           case "d": // 数据524           default:525             DataList.Add(mmRow);526             break;527         }528       }529 530 531       // 设置表头前行集532       if (TitleList.Count == 0 && HeadList.Count > 0)533       {534         List<Row> tmpList = new List<Row>();535         for (int n = 0; n < DataList.Count; n++)536         {537           if (DataList[n].RowIndex < HeadList[0].RowIndex)538           {539             HForeList.Add(DataList[n]);540             tmpList.Add(DataList[n]);541           }542         }543 544         for (int n = 0; n < tmpList.Count; n++)545         {546           DataList.Remove(tmpList[n]);547         }548 549         tmpList.Clear();550       }551 552       // 重设表尾 不是每页打印表尾情况下,那么表位就去掉553       if (!IsAllPrintFoot)554       {555         foreach (Row tRow in FootList)556           DataList.Add(tRow);557         FootList.Clear();558       }559     }560 561     #endregion562   }563 }

View Code

4、PagingMakeUp 分页补充绘制类

 1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4  5 namespace E_Print 6 { 7   /// <summary> 8   /// 下页需要补充绘制 9   /// </summary>10   public class PagingMakeUp11   {12     /// <summary>13     /// 补充单元格14     /// </summary>15     private Cell _makeupCell;16 17     /// <summary>18     /// 补充高度19     /// </summary>20     private float _makeupHeight;21 22     /// <summary>23     /// 构造函数24     /// </summary>25     public PagingMakeUp()26     {27       _makeupCell = new Cell();28       _makeupHeight = 0;29     }30 31     /// <summary>32     /// 获取--设置--补充单元格33     /// </summary>34     public Cell MakeupCell35     {36       get { return _makeupCell; }37       set { _makeupCell = value; }38     }39 40     /// <summary>41     /// 获取--设置--补充高度42     /// </summary>43     public float MakeupHeight44     {45       get { return _makeupHeight; }46       set { _makeupHeight = value; }47     }48 49   }50 }

View Code

5、IObjectSafety 抽象接口类

 1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Runtime.InteropServices; 5  6 namespace E_Print 7 { 8   /// <summary> 9   /// 接口抽象基类10   /// </summary>11   [ComImport, GuidAttribute("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]12   [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]13   public interface IObjectSafety14   {15     [PreserveSig]16     int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);17 18     [PreserveSig()]19     int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);20   }21 }

View Code

6、预览效果

7、我们可以通过源码中的 EPrintTest.exe 打印Winform 实例 ,来执行示范,

     通过WEB前端js 生成打印的TABLE的 RptData.

     如果在网页中,通过JS 直接传给打印控件就OK