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