网页WEB打印控件制作 – SDP开发平台 – 博客园

来源: 网页WEB打印控件制作 – SDP开发平台 – 博客园

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

由于本打印插件是基于我们开发平台的报表基础来开发设计的,所以打印控件的原理:通过JS将页面表格数据生成固定格式的XML字符串(图片通过 64base图片格式)传送给打印插件,有打印插件自主绘图生成打印页面。E_Print插件可以在WEB或WinForm中使用:

打印插件完整源码: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.Xml;
  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 _dataXml = "";
 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         /// 前台传入的XML格式的打印数据
 808         /// </summary>
 809         public string DATAXML
 810         {
 811             get { return _dataXml; }
 812             set { _dataXml = 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         #endregion
1017 
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 (!ParseXML()) return;                             // 解析报表数据
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             else
1056                 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         #endregion
1150 
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         /// 解析XML文件
1198         /// </summary>
1199         /// <returns>返回成功与否</returns>
1200         private bool ParseXML()
1201         {
1202             if (this.DATAXML == null || this.DATAXML.Trim() == "") return false;
1203             XmlDataDocument xmlDoc = new XmlDataDocument();
1204             try
1205             {
1206                 xmlDoc.LoadXml(this.DATAXML);
1207                 XmlNode rootNode = xmlDoc.DocumentElement;
1208                 if (rootNode.ChildNodes.Count == 0) return false;
1209                 if (rootNode.ChildNodes[0].Name.ToLower() != "table") return false;
1210 
1211                 XmlNode tableNode = rootNode.ChildNodes[0]; // 表格节点
1212                 HtmlHeight = float.Parse(tableNode.Attributes["height"].Value);
1213                 HtmlWidth = float.Parse(tableNode.Attributes["width"].Value);
1214 
1215                 int tmRowIndex = 0;
1216                 foreach (XmlNode trNode 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 (XmlNode tdNode 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                         #endregion
1243 
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                         #endregion
1284 
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                         #endregion
1291 
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                         #endregion
1340 
1341                         #region 单据格数据数值
1342 
1343                         tmCell.Value = tdNode.InnerText;
1344 
1345                         #endregion
1346 
1347                         // 加入对应的行内
1348                         tmRow.RowCells.Add(tmCell);
1349                     }
1350 
1351                     RptDraw.RowsList.Add(tmRow);
1352 
1353                     tmRowIndex++;
1354                 }
1355             }
1356             catch
1357             {
1358                 return false;
1359             }
1360             finally
1361             {
1362                 xmlDoc = 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                 else
1415                     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                 else
1422                     this.Zoom = TableRect.Height / HtmlHeight;
1423             }
1424             else
1425             {
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         #endregion
1470 
1471     }
1472 }
复制代码

 

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         #endregion
137 
138         #region 属性方法
139 
140         /// <summary>
141         /// 获取--设置--当前页码
142         /// </summary>
143         public int CurPageNum
144         {
145             get { return _curPageNum; }
146             set { _curPageNum = value; }
147         }
148 
149         /// <summary>
150         /// 获取--设置--总共页数
151         /// </summary>
152         public int AllPageNum
153         {
154             get { return _allPageNum; }
155             set { _allPageNum = value; }
156         }
157 
158         /// <summary>
159         /// 获取--设置--表格矩形
160         /// </summary>
161         public RectangleF ReptRect
162         {
163             get { return _reptRect; }
164             set { _reptRect = value; }
165         }
166 
167         /// <summary>
168         /// 获取--设置--报表全部行集
169         /// </summary>
170         public List<Row> RowsList
171         {
172             get { return _rowsList; }
173             set { _rowsList = value; }
174         }
175 
176         /// <summary>
177         /// 获取--设置--分页页面数组
178         /// </summary>
179         public List<PagingItem> PageList
180         {
181             get { return _pageList; }
182             set { _pageList = value; }
183         }
184 
185         /// <summary>
186         /// 获取--设置--是否每页打印标题
187         /// </summary>
188         public bool IsAllPrintTitle
189         {
190             get { return _isAllPrintTitle; }
191             set { _isAllPrintTitle = value; }
192         }
193 
194         /// <summary>
195         /// 获取--设置--是否每页打印表头
196         /// </summary>
197         public bool IsAllPrintHead
198         {
199             get { return _isAllPrintHead; }
200             set { _isAllPrintHead = value; }
201         }
202 
203         /// <summary>
204         /// 获取--设置--是否每页打印表尾
205         /// </summary>
206         public bool IsAllPrintFoot
207         {
208             get { return _isAllPrintFoot; }
209             set { _isAllPrintFoot = value; }
210         }
211 
212         /// <summary>
213         /// 获取--设置--末页是否自动补行
214         /// </summary>
215         public bool IsAutoFillRow
216         {
217             get { return _isAutoFillRow; }
218             set { _isAutoFillRow = value; }
219         }
220 
221         /// <summary>
222         /// 获取--设置--缩小比例
223         /// </summary>
224         public float Zoom
225         {
226             get { return _zoom; }
227             set { _zoom = value; }
228         }
229 
230         /// <summary>
231         /// 获取--设置--字符溢出处理方式
232         /// </summary>
233         public bool IsOverFlow
234         {
235             get { return _isOverFlow; }
236             set { _isOverFlow = value; }
237         }
238 
239         /// <summary>
240         /// 获取--设置--每页打印的标题+表头高度
241         /// </summary>
242         public float HeadPix
243         {
244             get { return _headPix; }
245             set { _headPix = value; }
246         }
247 
248         /// <summary>
249         /// 获取--设置--每页打印的表尾高度
250         /// </summary>
251         public float FootPix
252         {
253             get { return _footPix; }
254             set { _footPix = value; }
255         }
256 
257         #endregion
258 
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         #endregion
284 
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                     // 补行行高21
315                     while ((N_DataHeith + (isFillRowNum + 1) * 21 * Zoom) < N_PageHeith)
316                     {
317                         isFillRowNum++;
318                     }
319 
320                     if (isFillRowNum > 0)
321                         isCanFillRow = true;
322                 }
323 
324                 #endregion
325 
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                 #endregion
342 
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                         else
359                             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                                 // 再将偏移量+行号 补充的行高全部为21px
383                                 offsetY += 21 * Zoom;
384                             }
385                         }
386 
387                         isFillFlag = true;
388                     }
389 
390                     #endregion
391 
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                     #endregion
403                 }
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;  // 再将偏移量+行号 补充的行高全部为21px
431                         }
432                     }
433                 }
434 
435                 #endregion
436 
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;  // 自动补行的单元格的高度固定为21px
472             }
473             else
474             {
475                 if (isMakeup)            // 补充单元格
476                 {
477                     tdH = mkH;
478                     tdY = tdY + HeadPix; // 如果是补充单元格,则此单元格的Y坐标:如果每页打印标题或表头,则Y坐标 需要下移 HeadPix
479                 }
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             #endregion
491 
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             #endregion
499 
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             #endregion
539 
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                 else
550                 {
551                     brush = new SolidBrush(tdCell.FontColor);
552                     this.DrawStr(g, rect, brush, tdCell.CellFont, tdCell.strFormat, tdCell.Value);
553                 }
554             }
555 
556             #endregion
557         }
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                 else
587                 {
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                     else
596                     {
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             try
621             {
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             catch
631             {
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             else
706                 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             else
721             {
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         #endregion
764 
765     }
766 }
复制代码

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         #endregion
102 
103         #region 属性方法
104 
105         /// <summary>
106         /// 获取--设置--表格区域
107         /// </summary>
108         public RectangleF TableRect
109         {
110             get { return _tableRect; }
111             set { _tableRect = value; }
112         }
113 
114         /// <summary>
115         /// 获取--设置--表格行集
116         /// </summary>
117         public List<Row> RowsList
118         {
119             get { return _rowsList; }
120             set { _rowsList = value; }
121         }
122 
123         /// <summary>
124         /// 获取--设置--是否每页打印标题
125         /// </summary>
126         public bool IsAllPrintTitle
127         {
128             get { return _isAllPrintTitle; }
129             set { _isAllPrintTitle = value; }
130         }
131 
132         /// <summary>
133         /// 获取--设置--是否每页打印表头
134         /// </summary>
135         public bool IsAllPrintHead
136         {
137             get { return _isAllPrintHead; }
138             set { _isAllPrintHead = value; }
139         }
140 
141         /// <summary>
142         /// 获取--设置--是否每页打印表尾
143         /// </summary>
144         public bool IsAllPrintFoot
145         {
146             get { return _isAllPrintFoot; }
147             set { _isAllPrintFoot = value; }
148         }
149 
150         /// <summary>
151         /// 获取--设置--每页打印标题+表头高度
152         /// </summary>
153         public float MyHeadPix
154         {
155             get { return _myHeadPix; }
156             set { _myHeadPix = value; }
157         }
158 
159         /// <summary>
160         /// 获取--设置--每页打印表尾巴高度
161         /// </summary>
162         public float MyFootPix
163         {
164             get { return _myFootPix; }
165             set { _myFootPix = value; }
166         }
167 
168         #endregion
169 
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                 else
245                 {
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                     else
255                     {
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             else
289             {
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             #endregion
299 
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             else
319             {
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             #endregion
335 
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                 else
353                 {
354                     p_Height -= DataList[t].RowHeight;
355                     if (p_Height <= 0)
356                     {
357                         startR = t;
358                         runNext = true;
359                         break;
360                     }
361                     else
362                     {
363                         p_Item.IndexList.Add(DataList[t].RowIndex);
364                     }
365                 }
366             }
367 
368             #endregion
369 
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             #endregion
380 
381             #region 添加分页页面
382 
383             pages.Add(p_Item);
384             if (runNext)
385             {
386                 Paging_Relative(startR, ref pages);
387             }
388 
389             #endregion
390         }
391 
392         /// <summary>
393         /// 检查行内单元格如果是图片
394         /// 并且合并行数大于1
395         /// </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         #endregion
413 
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         #endregion
562     }
563 }
复制代码

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 PagingMakeUp
11     {
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 MakeupCell
35         {
36             get { return _makeupCell; }
37             set { _makeupCell = value; }
38         }
39 
40         /// <summary>
41         /// 获取--设置--补充高度
42         /// </summary>
43         public float MakeupHeight
44         {
45             get { return _makeupHeight; }
46             set { _makeupHeight = value; }
47         }
48 
49     }
50 }
复制代码

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 IObjectSafety
14     {
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 }
复制代码

6、预览效果

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

通过WEB前端js 生成打印的TABLE的 RptData.xml格式 数据,在WINForm中直接使用

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

分享到: 更多 (0)