当前位置:Gxlcms > asp.net > 网页WEB打印控件制作

网页WEB打印控件制作

时间:2021-07-01 10:21:17 帮助过:18人阅读

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

2、ReportDraw 打印绘制类

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Drawing.DrawingD;
  5. using System.IO;
  6. namespace E_Print
  7. {
  8. /// <summary>
  9. /// 报表绘制
  10. /// </summary>
  11. public class ReportDraw
  12. {
  13. #region 私有成员
  14. /// <summary>
  15. /// 当前页码
  16. /// </summary>
  17. private int _curPageNum;
  18. /// <summary>
  19. /// 总共页数
  20. /// </summary>
  21. private int _allPageNum;
  22. /// <summary>
  23. /// 表格矩形
  24. /// </summary>
  25. private RectangleF _reptRect;
  26. /// <summary>
  27. /// 报表全部行集
  28. /// </summary>
  29. private List<Row> _rowsList;
  30. /// <summary>
  31. /// 分页页面数组
  32. /// </summary>
  33. private List<PagingItem> _pageList;
  34. /// <summary>
  35. /// 是否每页打印标题
  36. /// </summary>
  37. private bool _isAllPrintTitle;
  38. /// <summary>
  39. /// 是否每页打印表头
  40. /// </summary>
  41. private bool _isAllPrintHead;
  42. /// <summary>
  43. /// 是否每页打印表尾
  44. /// </summary>
  45. private bool _isAllPrintFoot;
  46. /// <summary>
  47. /// 是否末页自动补行
  48. /// </summary>
  49. private bool _isAutoFillRow;
  50. /// <summary>
  51. /// 缩小比例
  52. /// </summary>
  53. private float _zoom;
  54. /// <summary>
  55. /// 字符溢出处理方式
  56. /// </summary>
  57. private bool _isOverFlow;
  58. /// <summary>
  59. /// 每页打印的标题+表头的高度
  60. /// </summary>
  61. private float _headPix;
  62. /// <summary>
  63. /// 每页打印的表尾高度
  64. /// </summary>
  65. private float _footPix;
  66. #endregion
  67. #region 构造方法
  68. /// <summary>
  69. /// 构造函数
  70. /// </summary>
  71. public ReportDraw()
  72. {
  73. _curPageNum = ;
  74. _allPageNum = ;
  75. _reptRect = new RectangleF();
  76. _rowsList = new List<Row>();
  77. _pageList = new List<PagingItem>();
  78. _isAllPrintTitle = false;
  79. _isAllPrintHead = false;
  80. _isAllPrintFoot = false;
  81. _isAutoFillRow = false;
  82. _zoom = ;
  83. _isOverFlow = false;
  84. _headPix = ;
  85. _footPix = ;
  86. }
  87. /// <summary>
  88. /// 构造函数
  89. /// </summary>
  90. /// <param name="printTitle">每页打印标题</param>
  91. /// <param name="printHead">每页打印表头</param>
  92. /// <param name="printFoot">每页打印表位</param>
  93. /// <param name="fillRows">自动补全空行</param>
  94. /// <param name="tableRect">报表尺寸矩形</param>
  95. /// <param name="overFlow">字符溢出处理</param>
  96. public ReportDraw(bool printTitle, bool printHead, bool printFoot, bool fillRows, RectangleF tableRect, bool overFlow)
  97. {
  98. _reptRect = tableRect;
  99. _isAllPrintTitle = printTitle;
  100. _isAllPrintHead = printHead;
  101. _isAllPrintFoot = printFoot;
  102. _isAutoFillRow = fillRows;
  103. _isOverFlow = overFlow;
  104. _curPageNum = ;
  105. _allPageNum = ;
  106. _zoom = ;
  107. _rowsList = new List<Row>();
  108. _pageList = new List<PagingItem>();
  109. _headPix = ;
  110. _footPix = ;
  111. }
  112. #endregion
  113. #region 属性方法
  114. /// <summary>
  115. /// 获取--设置--当前页码
  116. /// </summary>
  117. public int CurPageNum
  118. {
  119. get { return _curPageNum; }
  120. set { _curPageNum = value; }
  121. }
  122. /// <summary>
  123. /// 获取--设置--总共页数
  124. /// </summary>
  125. public int AllPageNum
  126. {
  127. get { return _allPageNum; }
  128. set { _allPageNum = value; }
  129. }
  130. /// <summary>
  131. /// 获取--设置--表格矩形
  132. /// </summary>
  133. public RectangleF ReptRect
  134. {
  135. get { return _reptRect; }
  136. set { _reptRect = value; }
  137. }
  138. /// <summary>
  139. /// 获取--设置--报表全部行集
  140. /// </summary>
  141. public List<Row> RowsList
  142. {
  143. get { return _rowsList; }
  144. set { _rowsList = value; }
  145. }
  146. /// <summary>
  147. /// 获取--设置--分页页面数组
  148. /// </summary>
  149. public List<PagingItem> PageList
  150. {
  151. get { return _pageList; }
  152. set { _pageList = value; }
  153. }
  154. /// <summary>
  155. /// 获取--设置--是否每页打印标题
  156. /// </summary>
  157. public bool IsAllPrintTitle
  158. {
  159. get { return _isAllPrintTitle; }
  160. set { _isAllPrintTitle = value; }
  161. }
  162. /// <summary>
  163. /// 获取--设置--是否每页打印表头
  164. /// </summary>
  165. public bool IsAllPrintHead
  166. {
  167. get { return _isAllPrintHead; }
  168. set { _isAllPrintHead = value; }
  169. }
  170. /// <summary>
  171. /// 获取--设置--是否每页打印表尾
  172. /// </summary>
  173. public bool IsAllPrintFoot
  174. {
  175. get { return _isAllPrintFoot; }
  176. set { _isAllPrintFoot = value; }
  177. }
  178. /// <summary>
  179. /// 获取--设置--末页是否自动补行
  180. /// </summary>
  181. public bool IsAutoFillRow
  182. {
  183. get { return _isAutoFillRow; }
  184. set { _isAutoFillRow = value; }
  185. }
  186. /// <summary>
  187. /// 获取--设置--缩小比例
  188. /// </summary>
  189. public float Zoom
  190. {
  191. get { return _zoom; }
  192. set { _zoom = value; }
  193. }
  194. /// <summary>
  195. /// 获取--设置--字符溢出处理方式
  196. /// </summary>
  197. public bool IsOverFlow
  198. {
  199. get { return _isOverFlow; }
  200. set { _isOverFlow = value; }
  201. }
  202. /// <summary>
  203. /// 获取--设置--每页打印的标题+表头高度
  204. /// </summary>
  205. public float HeadPix
  206. {
  207. get { return _headPix; }
  208. set { _headPix = value; }
  209. }
  210. /// <summary>
  211. /// 获取--设置--每页打印的表尾高度
  212. /// </summary>
  213. public float FootPix
  214. {
  215. get { return _footPix; }
  216. set { _footPix = value; }
  217. }
  218. #endregion
  219. #region 计算分页
  220. /// <summary>
  221. /// 计算分页
  222. /// </summary>
  223. public void CalcPaging()
  224. {
  225. // 分页实例
  226. PagingCalc insCalc = new PagingCalc();
  227. insCalc.TableRect = this.ReptRect;
  228. insCalc.RowsList = this.RowsList;
  229. insCalc.IsAllPrintTitle = this.IsAllPrintTitle;
  230. insCalc.IsAllPrintHead = this.IsAllPrintHead;
  231. insCalc.IsAllPrintFoot = this.IsAllPrintFoot;
  232. // 分页计算
  233. _pageList = insCalc.CalcPages();
  234. this._allPageNum = _pageList.Count;
  235. this._curPageNum = ;
  236. this._headPix = insCalc.MyHeadPix;
  237. this._footPix = insCalc.MyFootPix;
  238. }
  239. #endregion
  240. #region 绘制方法
  241. /// <summary>
  242. /// 绘制报表
  243. /// </summary>
  244. /// <param name="g"></param>
  245. /// <returns>返回是否结束</returns>
  246. public bool DrawReport(Graphics g)
  247. {
  248. bool isMorePage = false;
  249. float offsetX = _reptRect.X; // X 偏移量
  250. float offsetY = _reptRect.Y; // Y 偏移量
  251. bool isCanFillRow = false; // 是否需要补行
  252. bool isFillFlag = false; // 是否已经补过
  253. int isFillRowNum = ; // 需要补充几行
  254. PagingItem nowPage = GetPageItem(CurPageNum); // 当前页
  255. if (nowPage != null)
  256. {
  257. #region 判定高度不足是否自动补行
  258. // 判定补行条件 报表设置了末页不足自动补行、同时 为最后一页
  259. if (_isAutoFillRow == true && CurPageNum == AllPageNum)
  260. {
  261. // 判定页面高度 与 数据高度
  262. float N_PageHeith = ReptRect.Height; // 当前页面高度
  263. float N_DataHeith = GetThisPageDataRowsHeight(); // 当前数据高度
  264. // 补行行高
  265. while ((N_DataHeith + (isFillRowNum + ) * * Zoom) < N_PageHeith)
  266. {
  267. isFillRowNum++;
  268. }
  269. if (isFillRowNum > )
  270. isCanFillRow = true;
  271. }
  272. #endregion
  273. #region 首先绘制上一页补充单元格
  274. if (CurPageNum > )
  275. {
  276. PagingItem prePage = GetPageItem(CurPageNum - ); // 上一页
  277. if (prePage != null)
  278. {
  279. foreach (PagingMakeUp tmMk in prePage.MakeupList)
  280. {
  281. // 绘制补充单元格(上页中未绘制完成的单元格)
  282. DrawTD(g, tmMk.MakeupCell, offsetX, offsetY, true, tmMk.MakeupHeight, false);
  283. }
  284. }
  285. }
  286. #endregion
  287. #region 其次绘制当前页面的单元格
  288. // 其次绘制当前页的单元格
  289. for (int ii = ; ii < nowPage.IndexList.Count; ii++)
  290. {
  291. // 先绘制 TD CELL 单元格
  292. Row rowTR = GetRow(nowPage.IndexList[ii]);
  293. #region 执行补行
  294. if (isCanFillRow == true && rowTR.RowType.ToLower().Trim() == "f") // 需要补行 行标志为F 表尾前进行补充空行
  295. {
  296. Row fillRow = new Row();
  297. if (ii == )
  298. fillRow = rowTR;
  299. else
  300. fillRow = GetRow(nowPage.IndexList[ii - ]);
  301. if (fillRow != null) // 绘制自动补充的空行单元格
  302. {
  303. // 开始补充空行
  304. for (int fi = ; fi <= isFillRowNum; fi++)
  305. {
  306. bool bcFlag = true;
  307. // 绘制单元格
  308. foreach (Cell fillTdCell in fillRow.RowCells)
  309. {
  310. if (bcFlag)
  311. {
  312. // 绘制边框线(合并单元格的情况才用到)
  313. if (fillTdCell.RectX > )
  314. {
  315. DrawLine(g, offsetX, offsetY, offsetX, offsetY + .F * Zoom); // 最左边竖线
  316. DrawLine(g, offsetX, offsetY + .F * Zoom, offsetX + fillTdCell.RectX, offsetY + .F * Zoom);
  317. }
  318. bcFlag = false;
  319. }
  320. DrawTD(g, fillTdCell, offsetX, offsetY, false, , true);
  321. }
  322. // 再将偏移量+行号 补充的行高全部为px
  323. offsetY += * Zoom;
  324. }
  325. }
  326. isFillFlag = true;
  327. }
  328. #endregion
  329. #region 正常绘制
  330. foreach (Cell td in rowTR.RowCells)
  331. {
  332. DrawTD(g, td, offsetX, offsetY, false, , false);
  333. }
  334. // 再将偏移量+行号
  335. offsetY += rowTR.RowHeight;
  336. #endregion
  337. }
  338. // 判定是否补过;没有补充过,则在最后进行补充空行
  339. if ((isCanFillRow == true) && (isFillFlag == false) && (nowPage.IndexList.Count > ))
  340. {
  341. Row fillRow = GetRow(nowPage.IndexList[nowPage.IndexList.Count - ]);
  342. if (fillRow != null) // 绘制自动补充的空行单元格
  343. {
  344. // 开始补充空行
  345. for (int fi = ; fi <= isFillRowNum; fi++)
  346. {
  347. bool newFlag = true;
  348. foreach (Cell fillTdCell in fillRow.RowCells)
  349. {
  350. if (newFlag)
  351. {
  352. // 绘制边框线(合并单元格的情况才用到)
  353. if (fillTdCell.RectX > )
  354. {
  355. DrawLine(g, offsetX, offsetY, offsetX, offsetY + .F * Zoom); // 最左边竖线
  356. DrawLine(g, offsetX, offsetY + .F * Zoom, offsetX + fillTdCell.RectX, offsetY + .F * Zoom);
  357. }
  358. newFlag = false;
  359. }
  360. DrawTD(g, fillTdCell, offsetX, offsetY, false, , true);
  361. }
  362. offsetY += * Zoom; // 再将偏移量+行号 补充的行高全部为px
  363. }
  364. }
  365. }
  366. #endregion
  367. if (CurPageNum < AllPageNum)
  368. {
  369. isMorePage = true; // 还有下页
  370. CurPageNum++; // 页码增加
  371. }
  372. }
  373. return isMorePage;
  374. }
  375. /// <summary>
  376. /// 绘制单元格
  377. /// </summary>
  378. /// <param name="g">绘图对象</param>
  379. /// <param name="tdCell">单元格</param>
  380. /// <param name="setX">X偏移量</param>
  381. /// <param name="setY">Y坐标值</param>
  382. /// <param name="isMakeup">是否补充单元格</param>
  383. /// <param name="mkH">补充单元格高度</param>
  384. /// <param name="fillCell">自动补行的单元格</param>
  385. private void DrawTD(Graphics g, Cell tdCell, float setX, float setY, bool isMakeup, float mkH, bool fillCell)
  386. {
  387. #region 参数变量
  388. Pen pen;
  389. Brush brush;
  390. // 获取单元格绘制坐标矩形信息
  391. float tdX = tdCell.RectX + setX;
  392. float tdY = setY;
  393. float tdW = tdCell.RectW;
  394. float tdH = ;
  395. if (fillCell)
  396. {
  397. tdH = * Zoom; // 自动补行的单元格的高度固定为px
  398. }
  399. else
  400. {
  401. if (isMakeup) // 补充单元格
  402. {
  403. tdH = mkH;
  404. tdY = tdY + HeadPix; // 如果是补充单元格,则此单元格的Y坐标:如果每页打印标题或表头,则Y坐标 需要下移 HeadPix
  405. }
  406. else // 实际单元格
  407. {
  408. tdH = tdCell.RectH;
  409. }
  410. if (tdCell.RowSpan > ) // 判定单元格高度是否超过底线
  411. {
  412. tdH = Calc_CellOverHeight(tdCell, tdY, tdH);
  413. }
  414. }
  415. #endregion
  416. #region 绘制背景
  417. // 填充颜色
  418. brush = new SolidBrush(tdCell.BackColor);
  419. g.FillRectangle(brush, tdX + .f * Zoom, tdY + .f * Zoom, tdW - .f * Zoom, tdH - .f * Zoom);
  420. #endregion
  421. #region 绘制边框
  422. // 左边框线
  423. if (tdCell.LeftBorder.LineWidth > )
  424. {
  425. pen = new Pen(tdCell.LeftBorder.LineColor);
  426. pen.DashStyle = tdCell.LeftBorder.LineDash;
  427. pen.Width = tdCell.LeftBorder.LineWidth;
  428. g.DrawLine(pen, tdX, tdY, tdX, tdY + tdH);
  429. }
  430. // 上边框线
  431. if (tdCell.TopBorder.LineWidth > )
  432. {
  433. pen = new Pen(tdCell.TopBorder.LineColor);
  434. pen.DashStyle = tdCell.TopBorder.LineDash;
  435. pen.Width = tdCell.TopBorder.LineWidth;
  436. g.DrawLine(pen, tdX, tdY, tdX + tdW, tdY);
  437. }
  438. // 右边框线
  439. if (tdCell.RightBorder.LineWidth > )
  440. {
  441. pen = new Pen(tdCell.RightBorder.LineColor);
  442. pen.DashStyle = tdCell.RightBorder.LineDash;
  443. pen.Width = tdCell.RightBorder.LineWidth;
  444. g.DrawLine(pen, tdX + tdW, tdY, tdX + tdW, tdY + tdH);
  445. }
  446. // 下边框线
  447. if (tdCell.BottomBorder.LineWidth > )
  448. {
  449. pen = new Pen(tdCell.BottomBorder.LineColor);
  450. pen.DashStyle = tdCell.BottomBorder.LineDash;
  451. pen.Width = tdCell.BottomBorder.LineWidth;
  452. g.DrawLine(pen, tdX, tdY + tdH, tdX + tdW, tdY + tdH);
  453. }
  454. #endregion
  455. #region 绘制文字
  456. if (!fillCell)
  457. {
  458. RectangleF rect = new RectangleF(tdX, tdY, tdW, tdH);
  459. if (tdCell.IsImage)
  460. {
  461. this.DrawImg(g, rect, tdCell.ImageUrl);
  462. }
  463. else
  464. {
  465. brush = new SolidBrush(tdCell.FontColor);
  466. this.DrawStr(g, rect, brush, tdCell.CellFont, tdCell.strFormat, tdCell.Value);
  467. }
  468. }
  469. #endregion
  470. }
  471. /// <summary>
  472. /// 绘制字符串
  473. /// 溢出时,换行缩小字符
  474. /// 字体缩小到的最小值不得小于
  475. /// </summary>
  476. /// <param name="g">绘图对象</param>
  477. /// <param name="strRect">文本区域</param>
  478. /// <param name="strBrush">文本笔画</param>
  479. /// <param name="strFont">文本字体</param>
  480. /// <param name="strFormat">文本格式</param>
  481. /// <param name="strValue">文本字符</param>
  482. /// <returns></returns>
  483. private void DrawStr(Graphics g, RectangleF strRect, Brush strBrush, Font strFont, StringFormat strFormat, string strValue)
  484. {
  485. // 报表设置:字符溢出不做处理
  486. if (!this.IsOverFlow)
  487. {
  488. g.DrawString(strValue, strFont, strBrush, strRect, strFormat);
  489. }
  490. else // 需要处理
  491. {
  492. // 测量字体的宽度和高度 会发现误差很大,如果一个一个的测量,误差就实在太大,所以这里就用简单的方式来进行处理
  493. SizeF sf = g.MeasureString(strValue, strFont); // 此种方式测量误差很大,如果
  494. if (strRect.Width > sf.Width)
  495. {
  496. g.DrawString(strValue, strFont, strBrush, strRect, strFormat);
  497. }
  498. else
  499. {
  500. // 计算换行后字符的全部高度是否满足
  501. int maxLines = ; // 计算当前字符当前字体最大打印的行数
  502. maxLines = (int)Math.Ceiling((double)sf.Width / (double)strRect.Width);
  503. if (strRect.Height >= maxLines * sf.Height)
  504. {
  505. g.DrawString(strValue, strFont, strBrush, strRect, strFormat);
  506. }
  507. else
  508. {
  509. float tmScale = strRect.Height / (maxLines * sf.Height);
  510. Font tmNewFont = new Font(strFont.Name, strFont.Size * tmScale, strFont.Style, GraphicsUnit.Point);
  511. g.DrawString(strValue, tmNewFont, strBrush, strRect, strFormat);
  512. }
  513. }
  514. }
  515. }
  516. /// <summary>
  517. /// 绘制图片
  518. /// 将Base图片流字符串转换成图片并进行绘制
  519. /// </summary>
  520. /// <param name="g"></param>
  521. /// <param name="strRect"></param>
  522. /// <param name="baseImg"></param>
  523. private void DrawImg(Graphics g, RectangleF strRect, string baseImg)
  524. {
  525. if (baseImg.Trim() == "") return;
  526. string imgStr = baseImg.Replace("data:image/gif;base,", "").Trim();
  527. if (imgStr == "") return;
  528. // 生成图片
  529. try
  530. {
  531. MemoryStream stream = new MemoryStream(Convert.FromBaseString(imgStr));
  532. Bitmap picImg = new Bitmap(stream);
  533. RectangleF imgRectF = new RectangleF(f, f, (float)picImg.Width, (float)picImg.Height); // 原始图片矩形
  534. RectangleF newRectF = new RectangleF(strRect.X + f, strRect.Y + f, (float)strRect.Width - f, (float)strRect.Height - f); // 绘制图片矩形
  535. g.DrawImage(picImg, newRectF, imgRectF, GraphicsUnit.Pixel); // 绘制缩放图片
  536. stream.Close();
  537. }
  538. catch
  539. {
  540. return;
  541. }
  542. }
  543. /// <summary>
  544. /// 绘制线条
  545. /// </summary>
  546. /// <param name="g">绘图对象</param>
  547. /// <param name="start_X">开始X</param>
  548. /// <param name="start_Y">开始Y</param>
  549. /// <param name="end_X">结束X</param>
  550. /// <param name="end_Y">结束Y</param>
  551. private void DrawLine(Graphics g, float start_X, float start_Y, float end_X, float end_Y)
  552. {
  553. Pen linePen = new Pen(Color.Black, .f);
  554. linePen.DashStyle = DashStyle.Solid;
  555. g.DrawLine(linePen, start_X, start_Y, end_X, end_Y);
  556. }
  557. private float ChangeUnit(float vSize)
  558. {
  559. return (vSize * f / f * f / f);
  560. }
  561. /// <summary>
  562. /// 获取行对象
  563. /// </summary>
  564. /// <param name="rowIndex"></param>
  565. /// <returns></returns>
  566. private Row GetRow(int rowIndex)
  567. {
  568. foreach (Row retRow in _rowsList)
  569. {
  570. if (retRow.RowIndex == rowIndex)
  571. return retRow;
  572. }
  573. return null;
  574. }
  575. /// <summary>
  576. /// 获取分页页面
  577. /// </summary>
  578. /// <param name="pNo">页码</param>
  579. /// <returns></returns>
  580. private PagingItem GetPageItem(int pNo)
  581. {
  582. foreach (PagingItem retPItem in PageList)
  583. {
  584. if (retPItem.PageNum == pNo)
  585. return retPItem;
  586. }
  587. return null;
  588. }
  589. /// <summary>
  590. /// 计算绘制高度
  591. /// 判定并且计算单元格高度是否超过当前页面所有行高度的底线
  592. /// </summary>
  593. /// <param name="mCell">单元格</param>
  594. /// <param name="mY">Y 轴坐标值</param>
  595. /// <param name="mH">H 当前高度</param>
  596. /// <returns></returns>
  597. private float Calc_CellOverHeight(Cell mCell, float mY, float mH)
  598. {
  599. float returnHeight = ; // 返回高度
  600. float tm_AllTrHeight = GetThisPageDataRowsHeight(); // 当前页面内所有数据行的高度
  601. float tm_RealY = ; // 相对最大Y值
  602. float tm_AbsY = ; // 实际最大Y值
  603. float tm_OverPlus = ; // 单元格剩余高度
  604. tm_RealY = mY + mH; // 实际最大Y值
  605. if (IsAllPrintFoot) // 每页打印表尾
  606. tm_AbsY = ReptRect.Y + (tm_AllTrHeight - FootPix); // 需要减去表尾高度
  607. else
  608. tm_AbsY = tm_AllTrHeight + ReptRect.Y;
  609. if (tm_RealY > tm_AbsY)
  610. {
  611. returnHeight = tm_AbsY - mY; // 当前页面实际最大高度-单元格的当前Y坐标值 = 返回单元格在本页内需要绘制的高度
  612. tm_OverPlus = mH - returnHeight; // 当前高度-单元格当前页面需要绘制的高度=下页需要绘制的补充高度
  613. // 将当前单元格添加到后页需要补充绘制数组中去
  614. PagingItem nPageItem = GetPageItem(CurPageNum);
  615. PagingMakeUp nMakeUp = new PagingMakeUp();
  616. nMakeUp.MakeupCell = mCell;
  617. nMakeUp.MakeupHeight = tm_OverPlus;
  618. nPageItem.MakeupList.Add(nMakeUp);
  619. }
  620. else
  621. {
  622. returnHeight = mH;
  623. }
  624. return returnHeight;
  625. }
  626. /// <summary>
  627. /// 获取本页内所有数据行的高度
  628. /// </summary>
  629. /// <returns></returns>
  630. private float GetThisPageDataRowsHeight()
  631. {
  632. float retHeight = ;
  633. PagingItem oThisPage = GetPageItem(CurPageNum); // 当前页
  634. foreach (int oRowIndex in oThisPage.IndexList)
  635. {
  636. Row oThisRow = GetRow(oRowIndex);
  637. retHeight += oThisRow.RowHeight;
  638. }
  639. return retHeight;
  640. }
  641. /// <summary>
  642. /// 获取页内某一项所属行的高度
  643. /// </summary>
  644. /// <param name="itemPage">页面对象</param>
  645. /// <param name="itemIndex">本页行数组中的某一项的序号</param>
  646. /// <returns></returns>
  647. private float GetThisPageOneRowHeight(PagingItem itemPage, int itemIndex)
  648. {
  649. float retHeight = ;
  650. if (itemIndex < itemPage.IndexList.Count && itemIndex >= )
  651. {
  652. Row oThisRow = GetRow(itemPage.IndexList[itemIndex]);
  653. retHeight = oThisRow.RowHeight;
  654. }
  655. return retHeight;
  656. }
  657. #endregion
  658. }
  659. }
  660. 3、PagingCalc 分页计算类
  661. using System;
  662. using System.Collections.Generic;
  663. using System.Text;
  664. using System.Drawing;
  665. namespace E_Print
  666. {
  667. /// <summary>
  668. /// 分页计算
  669. /// </summary>
  670. public class PagingCalc
  671. {
  672. #region 私有变量
  673. /// <summary>
  674. /// 表格区域
  675. /// </summary>
  676. private RectangleF _tableRect;
  677. /// <summary>
  678. /// 报表行集
  679. /// </summary>
  680. private List<Row> _rowsList;
  681. /// <summary>
  682. /// 是否每页打印标题
  683. /// </summary>
  684. private bool _isAllPrintTitle;
  685. /// <summary>
  686. /// 是否每页打印表头
  687. /// </summary>
  688. private bool _isAllPrintHead;
  689. /// <summary>
  690. /// 是否每页打印表尾
  691. /// </summary>
  692. private bool _isAllPrintFoot;
  693. /// <summary>
  694. /// 标题行集
  695. /// </summary>
  696. private List<Row> TitleList;
  697. /// <summary>
  698. /// 表头前行集
  699. /// </summary>
  700. private List<Row> HForeList;
  701. /// <summary>
  702. /// 表头行集
  703. /// </summary>
  704. private List<Row> HeadList;
  705. /// <summary>
  706. /// 数据行集
  707. /// </summary>
  708. private List<Row> DataList;
  709. /// <summary>
  710. /// 表尾行集
  711. /// </summary>
  712. private List<Row> FootList;
  713. /// <summary>
  714. /// 每页打印标题+表头高度
  715. /// </summary>
  716. private float _myHeadPix;
  717. /// <summary>
  718. /// 每页打印表尾高度
  719. /// </summary>
  720. private float _myFootPix;
  721. #endregion
  722. #region 构造方法
  723. /// <summary>
  724. /// 构造函数
  725. /// </summary>
  726. public PagingCalc()
  727. {
  728. _tableRect = new RectangleF();
  729. _rowsList = new List<Row>();
  730. _isAllPrintTitle = false;
  731. _isAllPrintHead = false;
  732. _isAllPrintFoot = false;
  733. TitleList = new List<Row>();
  734. HForeList = new List<Row>();
  735. HeadList = new List<Row>();
  736. DataList = new List<Row>();
  737. FootList = new List<Row>();
  738. _myHeadPix = ;
  739. _myFootPix = ;
  740. }
  741. #endregion
  742. #region 属性方法
  743. /// <summary>
  744. /// 获取--设置--表格区域
  745. /// </summary>
  746. public RectangleF TableRect
  747. {
  748. get { return _tableRect; }
  749. set { _tableRect = value; }
  750. }
  751. /// <summary>
  752. /// 获取--设置--表格行集
  753. /// </summary>
  754. public List<Row> RowsList
  755. {
  756. get { return _rowsList; }
  757. set { _rowsList = value; }
  758. }
  759. /// <summary>
  760. /// 获取--设置--是否每页打印标题
  761. /// </summary>
  762. public bool IsAllPrintTitle
  763. {
  764. get { return _isAllPrintTitle; }
  765. set { _isAllPrintTitle = value; }
  766. }
  767. /// <summary>
  768. /// 获取--设置--是否每页打印表头
  769. /// </summary>
  770. public bool IsAllPrintHead
  771. {
  772. get { return _isAllPrintHead; }
  773. set { _isAllPrintHead = value; }
  774. }
  775. /// <summary>
  776. /// 获取--设置--是否每页打印表尾
  777. /// </summary>
  778. public bool IsAllPrintFoot
  779. {
  780. get { return _isAllPrintFoot; }
  781. set { _isAllPrintFoot = value; }
  782. }
  783. /// <summary>
  784. /// 获取--设置--每页打印标题+表头高度
  785. /// </summary>
  786. public float MyHeadPix
  787. {
  788. get { return _myHeadPix; }
  789. set { _myHeadPix = value; }
  790. }
  791. /// <summary>
  792. /// 获取--设置--每页打印表尾巴高度
  793. /// </summary>
  794. public float MyFootPix
  795. {
  796. get { return _myFootPix; }
  797. set { _myFootPix = value; }
  798. }
  799. #endregion
  800. #region 计算方法
  801. /// <summary>
  802. /// 分页计算
  803. /// </summary>
  804. /// <returns></returns>
  805. public List<PagingItem> CalcPages()
  806. {
  807. List<PagingItem> retPages = new List<PagingItem>();
  808. // 无需分页
  809. if (Get_TableAllHeight() <= TableRect.Height)
  810. {
  811. PagingItem tmItem = new PagingItem();
  812. tmItem.PageNum = ;
  813. for (int y = ; y < RowsList.Count; y++)
  814. {
  815. tmItem.IndexList.Add(y);
  816. }
  817. retPages.Add(tmItem);
  818. }
  819. else // 需要分页
  820. {
  821. // 有设置了 每页打印标题、表头、表位 其中的任意一个
  822. if (Get_IsCusSet_THDF()) // 则执行每页相对分页
  823. {
  824. Paging_Relative(, ref retPages);
  825. // 计算每页打印头尾高度
  826. MyHeadPix = ;
  827. if (IsAllPrintTitle)
  828. {
  829. MyHeadPix += Get_TableTileHeight();
  830. }
  831. if (IsAllPrintHead)
  832. {
  833. MyHeadPix += Get_TableHeadHeight();
  834. }
  835. if (IsAllPrintFoot)
  836. {
  837. MyFootPix = Get_TableFootHeight();
  838. }
  839. }
  840. else // 执行直接数据分页
  841. {
  842. Paging_Direct(, ref retPages);
  843. }
  844. }
  845. return retPages;
  846. }
  847. /// <summary>
  848. /// 直接分页
  849. /// </summary>
  850. /// <param name="startR">开始行号</param>
  851. /// <param name="pages">页面数组</param>
  852. private void Paging_Direct(int startR, ref List<PagingItem> pages)
  853. {
  854. float p_Height = TableRect.Height;
  855. PagingItem p_Item = new PagingItem();
  856. p_Item.PageNum = pages.Count + ;
  857. for (int t = startR; t < RowsList.Count; t++)
  858. {
  859. // 检查行内单元格是否不允许分页两种情况:条形码,图片
  860. if (Paging_CheckCell(RowsList[t], p_Height))
  861. {
  862. startR = t;
  863. pages.Add(p_Item);
  864. Paging_Direct(startR, ref pages);
  865. break;
  866. }
  867. else
  868. {
  869. p_Height -= RowsList[t].RowHeight;
  870. if (p_Height <= )
  871. {
  872. startR = t;
  873. pages.Add(p_Item);
  874. Paging_Direct(startR, ref pages);
  875. break;
  876. }
  877. else
  878. {
  879. p_Item.IndexList.Add(t);
  880. if (t == RowsList.Count - )
  881. {
  882. pages.Add(p_Item);
  883. }
  884. }
  885. }
  886. }
  887. }
  888. /// <summary>
  889. /// 相对分页
  890. /// </summary>
  891. /// <param name="startR">开始序号</param>
  892. /// <param name="pages">页面数组</param>
  893. private void Paging_Relative(int startR, ref List<PagingItem> pages)
  894. {
  895. SplitReportArea(); // 拆分表行
  896. float p_Height = TableRect.Height; // 页面总高
  897. PagingItem p_Item = new PagingItem(); // 分页页面
  898. p_Item.PageNum = pages.Count + ; // 分页页码
  899. bool runNext = false; // 继续分页
  900. #region 每页打印标题
  901. // 每页打印标题
  902. if (IsAllPrintTitle)
  903. {
  904. p_Height -= Get_TableTileHeight();
  905. foreach (Row p_Row in TitleList)
  906. p_Item.IndexList.Add(p_Row.RowIndex);
  907. }
  908. else
  909. {
  910. if (p_Item.PageNum == ) // 第一页特殊处理
  911. {
  912. p_Height -= Get_TableTileHeight();
  913. foreach (Row p_Row in TitleList)
  914. p_Item.IndexList.Add(p_Row.RowIndex);
  915. }
  916. }
  917. #endregion
  918. #region 每页打印表头
  919. // 每页打印表头
  920. if (IsAllPrintHead)
  921. {
  922. if (p_Item.PageNum == ) // 第一页特殊处理
  923. {
  924. // 计算表头前的行高
  925. p_Height -= Get_TableHForHeight();
  926. foreach (Row p_Row in HForeList)
  927. p_Item.IndexList.Add(p_Row.RowIndex);
  928. }
  929. // 计算表头行的高度
  930. p_Height -= Get_TableHeadHeight();
  931. foreach (Row p_Row in HeadList)
  932. p_Item.IndexList.Add(p_Row.RowIndex);
  933. }
  934. else
  935. {
  936. if (p_Item.PageNum == ) // 第一页特殊处理
  937. {
  938. // 计算表头前的行高
  939. p_Height -= Get_TableHForHeight();
  940. foreach (Row p_Row in HForeList)
  941. p_Item.IndexList.Add(p_Row.RowIndex);
  942. // 计算表头行的高度
  943. p_Height -= Get_TableHeadHeight();
  944. foreach (Row p_Row in HeadList)
  945. p_Item.IndexList.Add(p_Row.RowIndex);
  946. }
  947. }
  948. #endregion
  949. #region 每页数据区域
  950. // 每页数据划分
  951. if (IsAllPrintFoot)
  952. {
  953. p_Height -= Get_TableFootHeight(); // 表格高度 先减去表尾的高度
  954. }
  955. for (int t = startR; t < DataList.Count; t++)
  956. {
  957. // 检查行内单元格是否不允许分页两种情况:条形码,图片
  958. if (Paging_CheckCell(DataList[t], p_Height)) // 此情况下,单元格不能分割,并且高度超过页面剩余高度,所以要启动新的一页
  959. {
  960. startR = t;
  961. runNext = true;
  962. break;
  963. }
  964. else
  965. {
  966. p_Height -= DataList[t].RowHeight;
  967. if (p_Height <= )
  968. {
  969. startR = t;
  970. runNext = true;
  971. break;
  972. }
  973. else
  974. {
  975. p_Item.IndexList.Add(DataList[t].RowIndex);
  976. }
  977. }
  978. }
  979. #endregion
  980. #region 每页打印表尾
  981. // 每页打印表尾
  982. if (IsAllPrintFoot)
  983. {
  984. foreach (Row p_Row in FootList)
  985. p_Item.IndexList.Add(p_Row.RowIndex);
  986. }
  987. #endregion
  988. #region 添加分页页面
  989. pages.Add(p_Item);
  990. if (runNext)
  991. {
  992. Paging_Relative(startR, ref pages);
  993. }
  994. #endregion
  995. }
  996. /// <summary>
  997. /// 检查行内单元格如果是图片
  998. /// 并且合并行数大于
  999. /// </summary>
  1000. /// <param name="cRow"></param>
  1001. /// <param name="cHeight"></param>
  1002. /// <returns></returns>
  1003. private bool Paging_CheckCell(Row cRow, float cHeight)
  1004. {
  1005. foreach (Cell cCell in cRow.RowCells)
  1006. {
  1007. if (cCell.IsImage == true)
  1008. {
  1009. if (cCell.RectH > cHeight)
  1010. return true;
  1011. }
  1012. }
  1013. return false;
  1014. }
  1015. #endregion
  1016. #region 辅助方法
  1017. /// <summary>
  1018. /// 获取--报表全部高度
  1019. /// </summary>
  1020. /// <returns></returns>
  1021. private float Get_TableAllHeight()
  1022. {
  1023. float retHight = ;
  1024. for (int k = ; k < RowsList.Count; k++)
  1025. {
  1026. Row t_Row = RowsList[k];
  1027. retHight += t_Row.RowHeight;
  1028. }
  1029. return retHight;
  1030. }
  1031. /// <summary>
  1032. /// 获取是否设置了标题、表头、表尾 中的任意一个
  1033. /// </summary>
  1034. /// <returns></returns>
  1035. private bool Get_IsCusSet_THDF()
  1036. {
  1037. string tmType = "";
  1038. foreach (Row cusRow in this.RowsList)
  1039. {
  1040. tmType = cusRow.RowType.ToLower().Trim();
  1041. if (tmType == "t" || tmType == "h" || tmType == "f")
  1042. return true;
  1043. }
  1044. return false;
  1045. }
  1046. /// <summary>
  1047. /// 获取--报表标题高度
  1048. /// </summary>
  1049. /// <returns></returns>
  1050. private float Get_TableTileHeight()
  1051. {
  1052. float retHight = ;
  1053. for (int k = ; k < TitleList.Count; k++)
  1054. retHight += TitleList[k].RowHeight;
  1055. return retHight;
  1056. }
  1057. /// <summary>
  1058. /// 获取--报表表头前高度
  1059. /// </summary>
  1060. /// <returns></returns>
  1061. private float Get_TableHForHeight()
  1062. {
  1063. float retHight = ;
  1064. for (int k = ; k < HForeList.Count; k++)
  1065. retHight += HForeList[k].RowHeight;
  1066. return retHight;
  1067. }
  1068. /// <summary>
  1069. /// 获取--报表表头高度
  1070. /// </summary>
  1071. /// <returns></returns>
  1072. private float Get_TableHeadHeight()
  1073. {
  1074. float retHight = ;
  1075. for (int k = ; k < HeadList.Count; k++)
  1076. retHight += HeadList[k].RowHeight;
  1077. return retHight;
  1078. }
  1079. /// <summary>
  1080. /// 获取--报表表尾高度
  1081. /// </summary>
  1082. /// <returns></returns>
  1083. private float Get_TableFootHeight()
  1084. {
  1085. float retHight = ;
  1086. for (int k = ; k < FootList.Count; k++)
  1087. retHight += FootList[k].RowHeight;
  1088. return retHight;
  1089. }
  1090. /// <summary>
  1091. /// 拆分报表区域
  1092. /// </summary>
  1093. public void SplitReportArea()
  1094. {
  1095. TitleList = new List<Row>();
  1096. HForeList = new List<Row>();
  1097. HeadList = new List<Row>();
  1098. DataList = new List<Row>();
  1099. FootList = new List<Row>();
  1100. for (int m = ; m < RowsList.Count; m++)
  1101. {
  1102. Row mmRow = RowsList[m];
  1103. switch (mmRow.RowType.ToLower())
  1104. {
  1105. case "t": // 标题
  1106. TitleList.Add(mmRow);
  1107. break;
  1108. case "h": // 表头
  1109. HeadList.Add(mmRow);
  1110. break;
  1111. case "f": // 表尾
  1112. FootList.Add(mmRow);
  1113. break;
  1114. case "d": // 数据
  1115. default:
  1116. DataList.Add(mmRow);
  1117. break;
  1118. }
  1119. }
  1120. // 设置表头前行集
  1121. if (TitleList.Count == && HeadList.Count > )
  1122. {
  1123. List<Row> tmpList = new List<Row>();
  1124. for (int n = ; n < DataList.Count; n++)
  1125. {
  1126. if (DataList[n].RowIndex < HeadList[].RowIndex)
  1127. {
  1128. HForeList.Add(DataList[n]);
  1129. tmpList.Add(DataList[n]);
  1130. }
  1131. }
  1132. for (int n = ; n < tmpList.Count; n++)
  1133. {
  1134. DataList.Remove(tmpList[n]);
  1135. }
  1136. tmpList.Clear();
  1137. }
  1138. // 重设表尾 不是每页打印表尾情况下,那么表位就去掉
  1139. if (!IsAllPrintFoot)
  1140. {
  1141. foreach (Row tRow in FootList)
  1142. DataList.Add(tRow);
  1143. FootList.Clear();
  1144. }
  1145. }
  1146. #endregion
  1147. }
  1148. }

4、PagingMakeUp 分页补充绘制类

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace E_Print
  5. {
  6. /// <summary>
  7. /// 下页需要补充绘制
  8. /// </summary>
  9. public class PagingMakeUp
  10. {
  11. /// <summary>
  12. /// 补充单元格
  13. /// </summary>
  14. private Cell _makeupCell;
  15. /// <summary>
  16. /// 补充高度
  17. /// </summary>
  18. private float _makeupHeight;
  19. /// <summary>
  20. /// 构造函数
  21. /// </summary>
  22. public PagingMakeUp()
  23. {
  24. _makeupCell = new Cell();
  25. _makeupHeight = ;
  26. }
  27. /// <summary>
  28. /// 获取--设置--补充单元格
  29. /// </summary>
  30. public Cell MakeupCell
  31. {
  32. get { return _makeupCell; }
  33. set { _makeupCell = value; }
  34. }
  35. /// <summ

人气教程排行