网页WEB打印控件制作 开放源码可以调试
Posted szzzzn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网页WEB打印控件制作 开放源码可以调试相关的知识,希望对你有一定的参考价值。
在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)
也可以在www.sdpsoft.com直接下载
下面贴出源码:(在源码中有详细的注释说明)
1、PrintControl 打印插件类
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Printing;
using System.Xml;
using System.Security;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Text.RegularExpressions;
namespace E_Print
/// <summary>
/// 打印控件
/// 实现IObjectSafety接口
/// 网页上所有所使用到的GUID 通过Guid工具生成的唯一编码
/// 74D1ED1D-B1A7-4039-A060-6F544FBE99EC 编码以后不允许修改
/// </summary>
[Guid("74D1ED1D-B1A7-4039-A060-6F544FBE99EC"), ProgId("EReportPrint"), ComVisible(true)]
public partial class PrintControl : UserControl, IObjectSafety
#region 私有变量
#region 通用参数
/// <summary>
/// 缩放比例
/// </summary>
private float Zoom = 1;
/// <summary>
/// 网页高度 像素 px
/// </summary>
private float HtmlHeight = 0;
/// <summary>
/// 网页宽度 像素 px
/// </summary>
private float HtmlWidth = 0;
/// <summary>
/// 报表区域矩形
/// </summary>
private RectangleF TableRect = new RectangleF();
/// <summary>
/// 报表绘制实例
/// </summary>
private ReportDraw RptDraw = new ReportDraw();
#endregion
#region 页边距
/// <summary>
/// 左边距
/// 毫米 mm(一位小数)
/// </summary>
private float _marginLeft = 9.9f;
/// <summary>
/// 右边距
/// </summary>
private float _marginRight = 9.9f;
/// <summary>
/// 上边距
/// </summary>
private float _marginTop = 9.9f;
/// <summary>
/// 下边距
/// </summary>
private float _marginBottom = 9.9f;
#endregion
#region 版型方向
/// <summary>
/// 版型方向 Landscape: true 横向;false 纵向
/// </summary>
private bool _landscape = false;
#endregion
#region 纸型大小
/// <summary>
/// 纸张类型
/// </summary>
private string _paperName = "A4";
/// <summary>
/// 纸张宽度
/// </summary>
private int _paperWidth = 210; // 毫米
/// <summary>
/// 纸张高度
/// </summary>
private int _paperHeight = 297; // 毫米
#endregion
#region 打印参数
/// <summary>
/// 自适应纸张大小方法
/// null: 无
/// row: 横向
/// col: 纵向
/// </summary>
private string _zoomType = "null";
/// <summary>
/// 是否每页打印标题
/// </summary>
private bool _isTblTitleAllPage = false;
/// <summary>
/// 是否每页打印表头
/// </summary>
private bool _isTblHeadAllPage = false;
/// <summary>
/// 是否每页打印表尾
/// </summary>
private bool _isTblFootAllPage = false;
/// <summary>
/// 最后一页自动补行
/// </summary>
private bool _isAutoFillRow = false;
/// <summary>
/// 字符溢出是否换行缩小处理方式
/// </summary>
private bool _isOverFlow = false;
/// <summary>
/// 打印数据
/// </summary>
private string _dataXml = "";
#endregion
#region 页眉参数
/// <summary>
/// 页眉--绘制页眉
/// </summary>
private bool _headDraw = false;
/// <summary>
/// 页眉--高度 毫米
/// 默认 10 刚好
/// </summary>
private float _headHeight = 10.0f;
/// <summary>
/// 页眉--左侧文字
/// </summary>
private string _headLeft = "";
/// <summary>
/// 页眉--中间文字
/// </summary>
private string _headCenter = "";
/// <summary>
/// 页眉--右侧文字
/// </summary>
private string _headRight = "";
/// <summary>
/// 页眉--字体名称
/// </summary>
private string _headFontName = "宋体";
/// <summary>
/// 页眉--字体大小
/// </summary>
private string _headFontSize = "9pt";
/// <summary>
/// 页眉--字体颜色
/// </summary>
private string _headFontColor = "Black";
/// <summary>
/// 页眉--字体--粗体
/// </summary>
private bool _headFontBold = false;
/// <summary>
/// 页眉--字体--斜体
/// </summary>
private bool _headFontItalic = false;
/// <summary>
/// 页眉--字体--删除线
/// </summary>
private bool _headFontStrikeout = false;
/// <summary>
/// 页眉--字体--下划线
/// </summary>
private bool _headFontUnderline = false;
/// <summary>
/// 页眉--绘制分隔线
/// </summary>
private bool _headLineDraw = false;
/// <summary>
/// 页眉--分隔线宽度
/// </summary>
private float _headLineWidth = 1.0f;
/// <summary>
/// 页眉--分隔线线型
/// </summary>
private string _headLineDash = "solid";
/// <summary>
/// 页眉--分隔线颜色
/// </summary>
private string _headLineColor = "Black";
#endregion
#region 页脚参数
/// <summary>
/// 页脚--绘制页脚
/// </summary>
private bool _footDraw = false;
/// <summary>
/// 页脚--高度 毫米
/// </summary>
private float _footHeight = 10.0f;
/// <summary>
/// 页脚--左侧文字
/// </summary>
private string _footLeft = "";
/// <summary>
/// 页脚--中间文字
/// </summary>
private string _footCenter = "";
/// <summary>
/// 页脚--右侧文字
/// </summary>
private string _footRight = "";
/// <summary>
/// 页脚--字体名称
/// </summary>
private string _footFontName = "宋体";
/// <summary>
/// 页脚--字体大小
/// </summary>
private string _footFontSize = "9pt";
/// <summary>
/// 页脚--字体颜色
/// </summary>
private string _footFontColor = "Black";
/// <summary>
/// 页脚--字体--粗体
/// </summary>
private bool _footFontBold = false;
/// <summary>
/// 页脚--字体--斜体
/// </summary>
private bool _footFontItalic = false;
/// <summary>
/// 页脚--字体--删除线
/// </summary>
private bool _footFontStrikeout = false;
/// <summary>
/// 页脚--字体--下划线
/// </summary>
private bool _footFontUnderline = false;
/// <summary>
/// 页脚--绘制分隔线
/// </summary>
private bool _footLineDraw = false;
/// <summary>
/// 页脚--分隔线宽度
/// </summary>
private float _footLineWidth = 1.0f;
/// <summary>
/// 页脚--分隔线线型
/// </summary>
private string _footLineDash = "solid";
/// <summary>
/// 页脚--分隔线颜色
/// </summary>
private string _footLineColor = "Black";
#endregion
#endregion
#region 构造方法
/// <summary>
/// 打印控件构造函数
/// </summary>
public PrintControl()
InitializeComponent();
Init_PageSetting();
#endregion
#region 接口实现
private const string _IID_IDispatch = "00020400-0000-0000-C000-000000000046";
private const string _IID_IDispatchEx = "a6ef9860-c720-11d0-9337-00a0c90dcaa9";
private const string _IID_IPersistStorage = "0000010A-0000-0000-C000-000000000046";
private const string _IID_IPersistStream = "00000109-0000-0000-C000-000000000046";
private const string _IID_IPersistPropertyBag = "37D84F60-42CB-11CE-8135-00AA004BB851";
private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
private const int S_OK = 0;
private const int E_FAIL = unchecked((int)0x80004005);
private const int E_NOINTERFACE = unchecked((int)0x80004002);
private bool _fSafeForScripting = true;
private bool _fSafeForInitializing = true;
public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
int Rslt = E_FAIL;
string strGUID = riid.ToString("B");
pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
switch (strGUID)
case _IID_IDispatch:
case _IID_IDispatchEx:
Rslt = S_OK;
pdwEnabledOptions = 0;
if (_fSafeForScripting == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
Rslt = S_OK;
pdwEnabledOptions = 0;
if (_fSafeForInitializing == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
break;
default:
Rslt = E_NOINTERFACE;
break;
return Rslt;
public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
int Rslt = E_FAIL;
string strGUID = riid.ToString("B");
switch (strGUID)
case _IID_IDispatch:
case _IID_IDispatchEx:
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))
Rslt = S_OK;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))
Rslt = S_OK;
break;
default:
Rslt = E_NOINTERFACE;
break;
return Rslt;
#endregion
#region 属性方法
#region 页边距
/// <summary>
/// 获取--设置--左边距
/// 计量单位 毫米(mm)
/// </summary>
public float MARGINLEFT
get return _marginLeft;
set _marginLeft = value;
/// <summary>
/// 获取--设置--右边距
/// 计量单位 毫米(mm)
/// </summary>
public float MARGINRIGHT
get return _marginRight;
set _marginRight = value;
/// <summary>
/// 获取--设置--上边距
/// 计量单位 毫米(mm)
/// </summary>
public float MARGINTOP
get return _marginTop;
set _marginTop = value;
/// <summary>
/// 获取--设置--下边距
/// 计量单位 毫米(mm)
/// </summary>
public float MARGINBOTTOM
get return _marginBottom;
set _marginBottom = value;
#endregion
#region 版型方向
/// <summary>
/// 获取--设置--版型方向
/// Landscape: true 横向; false 纵向
/// </summary>
public bool LANDSCAPE
get return _landscape;
set _landscape = value;
#endregion
#region 纸张属性
/// <summary>
/// 获取--设置--纸张类型
/// </summary>
public string PAPERNAME
get return _paperName;
set _paperName = value;
/// <summary>
/// 获取--设置--纸张高度
/// 计量单位 毫米(mm)
/// </summary>
public int PAPERHEIGHT
get return _paperHeight;
set _paperHeight = value;
/// <summary>
/// 获取--设置--纸张宽度
/// 计量单位 毫米(mm)
/// </summary>
public int PAPERWIDTH
get return _paperWidth;
set _paperWidth = value;
#endregion
#region 页眉参数
/// <summary>
/// 获取--设置--页眉是否绘制
/// </summary>
public bool HEADDRAW
get return _headDraw;
set _headDraw = value;
/// <summary>
/// 获取--设置--页眉高度
/// 单位:毫米整数类型
/// </summary>
public float HEADHEIGHT
get return _headHeight;
set _headHeight = value;
/// <summary>
/// 获取--设置--页眉左侧文字
/// </summary>
public string HEADLEFT
get return _headLeft;
set _headLeft = value;
/// <summary>
/// 获取--设置--页眉中间文字
/// </summary>
public string HEADCENTER
get return _headCenter;
set _headCenter = value;
/// <summary>
/// 获取--设置--页眉右侧文字
/// </summary>
public string HEADRIGHT
get return _headRight;
set _headRight = value;
/// <summary>
/// 获取--设置--页眉字体名称
/// </summary>
public string HEADFONTNAME
get return _headFontName;
set _headFontName = value;
/// <summary>
/// 获取--设置--页眉字体大小
/// </summary>
public string HEADFONTSIZE
get return _headFontSize;
set _headFontSize = value;
/// <summary>
/// 获取--设置--页眉字体颜色
/// </summary>
public string HEADFONTCOLOR
get return _headFontColor;
set _headFontColor = value;
/// <summary>
/// 获取--设置--页眉字体--粗体
/// </summary>
public bool HEADFONTBOLD
get return _headFontBold;
set _headFontBold = value;
/// <summary>
/// 获取--设置--页眉字体--斜体
/// </summary>
public bool HEADFONTITALIC
get return _headFontItalic;
set _headFontItalic = value;
/// <summary>
/// 获取--设置--页眉字体--删除线
/// </summary>
public bool HEADFONTSTRIKEOUT
get return _headFontStrikeout;
set _headFontStrikeout = value;
/// <summary>
/// 获取--设置--页眉字体--下划线
/// </summary>
public bool HEADFONTUNDERLINE
get return _headFontUnderline;
set _headFontUnderline = value;
/// <summary>
/// 获取--设置--是否绘制分割线
/// </summary>
public bool HEADLINEDRAW
get return _headLineDraw;
set _headLineDraw = value;
/// <summary>
/// 获取--设置--页眉分隔线宽度
/// </summary>
public float HEADLINEWIDTH
get return _headLineWidth;
set _headLineWidth = value;
/// <summary>
/// 获取--设置--页眉分隔线线型
/// </summary>
public string HEADLINEDASH
get return _headLineDash;
set _headLineDash = value;
/// <summary>
/// 获取--设置--页眉分隔线颜色
/// </summary>
public string HEADLINECOLOR
get return _headLineColor;
set _headLineColor = value;
#endregion
#region 页脚参数
/// <summary>
/// 获取--设置--页脚是否绘制
/// </summary>
public bool FOOTDRAW
get return _footDraw;
set _footDraw = value;
/// <summary>
/// 获取--设置--页脚高度
/// 单位:毫米整数类型
/// </summary>
public float FOOTHEIGHT
get return _footHeight;
set _footHeight = value;
/// <summary>
/// 获取--设置--页脚左侧文字
/// </summary>
public string FOOTLEFT
get return _footLeft;
set _footLeft = value;
/// <summary>
/// 获取--设置--页脚中间文字
/// </summary>
public string FOOTCENTER
get return _footCenter;
set _footCenter = value;
/// <summary>
/// 获取--设置--页脚右侧文字
/// </summary>
public string FOOTRIGHT
get return _footRight;
set _footRight = value;
/// <summary>
/// 获取--设置--页脚字体名称
/// </summary>
public string FOOTFONTNAME
get return _footFontName;
set _footFontName = value;
/// <summary>
/// 获取--设置--页脚字体大小
/// </summary>
public string FOOTFONTSIZE
get return _footFontSize;
set _footFontSize = value;
/// <summary>
/// 获取--设置--页脚字体颜色
/// </summary>
public string FOOTFONTCOLOR
get return _footFontColor;
set _footFontColor = value;
/// <summary>
/// 获取--设置--页脚字体--粗体
/// </summary>
public bool FOOTFONTBOLD
get return _footFontBold;
set _footFontBold = value;
/// <summary>
/// 获取--设置--页脚字体--斜体
/// </summary>
public bool FOOTFONTITALIC
get return _footFontItalic;
set _footFontItalic = value;
/// <summary>
/// 获取--设置--页脚字体--删除线
/// </summary>
public bool FOOTFONTSTRIKEOUT
get return _footFontStrikeout;
set _footFontStrikeout = value;
/// <summary>
/// 获取--设置--页脚字体--下划线
/// </summary>
public bool FOOTFONTUNDERLINE
get return _footFontUnderline;
set _footFontUnderline = value;
/// <summary>
/// 获取--设置--是否绘制分割线
/// </summary>
public bool FOOTLINEDRAW
get return _footLineDraw;
set _footLineDraw = value;
/// <summary>
/// 获取--设置--页脚分隔线宽度
/// </summary>
public float FOOTLINEWIDTH
get return _footLineWidth;
set _footLineWidth = value;
/// <summary>
/// 获取--设置--页脚分隔线线型
/// </summary>
public string FOOTLINEDASH
get return _footLineDash;
set _footLineDash = value;
/// <summary>
/// 获取--设置--页脚分隔线颜色
/// </summary>
public string FOOTLINECOLOR
get return _footLineColor;
set _footLineColor = value;
#endregion
#region 打印参数
/// <summary>
/// 获取--设置--打印数据
/// 前台传入的XML格式的打印数据
/// </summary>
public string DATAXML
get return _dataXml;
set _dataXml = value;
/// <summary>
/// 获取--设置--是否每页打印标题
/// </summary>
public bool ISTBLTITLEALLPAGE
get return _isTblTitleAllPage;
set _isTblTitleAllPage = value;
/// <summary>
/// 获取--设置--是否每页打印表头
/// </summary>
public bool ISTBLHEADALLPAGE
get return _isTblHeadAllPage;
set _isTblHeadAllPage = value;
/// <summary>
/// 获取--设置--是否每页打印表尾
/// </summary>
public bool ISTBLFOOTALLPAGE
get return _isTblFootAllPage;
set _isTblFootAllPage = value;
/// <summary>
/// 获取--设置--末页自动补行
/// </summary>
public bool ISAUTOFILLROW
get return _isAutoFillRow;
set _isAutoFillRow = value;
/// <summary>
/// 获取--设置--缩放方向
/// 参数:以下三种;默认null
/// null: 无
/// row: 横向
/// col: 纵向
/// </summary>
public string ZOOMTYPE
get return _zoomType;
set _zoomType = value;
/// <summary>
/// 获取--设置--字符溢出是否缩小换行处理方式
/// </summary>
public bool ISOVERFLOW
get return _isOverFlow;
set _isOverFlow = value;
#endregion
#region 加载参数
/// <summary>
/// 加载打印参数
/// </summary>
public void INITPRINTPARAM()
Init_PageSetting();
#endregion
#endregion
#region 加载事件
/// <summary>
/// 初始化--页面设置参数
/// </summary>
private void Init_PageSetting()
this.E_PrintDocument.DefaultPageSettings.Margins.Left = (int)Math.Round(MARGINLEFT * 10); // 左边距
this.E_PrintDocument.DefaultPageSettings.Margins.Right = (int)Math.Round(MARGINRIGHT * 10); // 右边距
this.E_PrintDocument.DefaultPageSettings.Margins.Top = (int)Math.Round(MARGINTOP * 10); // 上边距
this.E_PrintDocument.DefaultPageSettings.Margins.Bottom = (int)Math.Round(MARGINBOTTOM * 10); // 下边距
this.E_PrintDocument.PrinterSettings.Copies = 1; // 打印份数
this.E_PrintDocument.DefaultPageSettings.Landscape = this.LANDSCAPE; // 版型方向
PaperSize size = GetPaperSize(PAPERNAME); // 纸张类型
if (size != null)
this.E_PrintDocument.DefaultPageSettings.PaperSize = size;
else
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));
/// <summary>
/// 获取--纸张类型
/// </summary>
/// <param name="paperName">纸张类型名称</param>
/// <returns></returns>
private PaperSize GetPaperSize(string paperName)
PaperSize paper = null;
foreach (PaperSize ps in this.E_PrintDocument.PrinterSettings.PaperSizes)
if (ps.PaperName.ToLower() == paperName.ToLower()) // 检查打印机是否有指定的纸张类型
paper = ps;
break;
return paper;
#endregion
#region 打印事件
/// <summary>
/// 直接打印
/// 此处加入了再次调用打印设置界面,因为用户可能需要选择那种打印机
/// </summary>
/// <returns></returns>
public string PRINT()
// 直接打印时,直接调用printDocument的Print()方法
// 因为用户可能在打印之前还要再更改打印设置所以需再次显示打印设置对话框
if (this.E_PrintDialog.ShowDialog() == DialogResult.OK)
try
this.Init_Printer();
this.E_PrintDocument.Print();
catch (Exception ex)
this.E_PrintDocument.PrintController.OnEndPrint(this.E_PrintDocument, new PrintEventArgs());
return ex.Message.ToString();
return "";
/// <summary>
/// 打印预览
/// 将打印的数据进行预览
/// </summary>
public string PREVIEW()
try
this.Init_Printer();
this.E_PrintPreviewDialog.ShowDialog();
catch (Exception ex)
return ex.Message.ToString();
return "";
/// <summary>
/// 页面设置
/// 设置打印的页面的纸张大小、纸型、页面边距
/// </summary>
public void PAGESTE()
// 页面设置对话框中使用的是公制长度计量单位 (厘米)
// 在.net中采用的是英制的计量单位 (英寸)
// 1英寸约等于2.54厘米,1厘米=10毫米
// 所以在下面中需要加入转换信息 将对话框中设置的页边距进行转换保存
// 设置传入的纸张信息
if (this.E_PageSetupDialog.ShowDialog() == DialogResult.OK) // 弹出页面设置对话框
if (System.Globalization.RegionInfo.CurrentRegion.IsMetric) // 转换页边距计量单位
this.E_PageSetupDialog.PageSettings.Margins = PrinterUnitConvert.Convert(this.E_PageSetupDialog.PageSettings.Margins, PrinterUnit.Display, PrinterUnit.TenthsOfAMillimeter);
this.E_PrintDocument.DefaultPageSettings = this.E_PageSetupDialog.PageSettings; // 更新页面设置参数值
// 更新参数
this.LANDSCAPE = this.E_PrintDocument.DefaultPageSettings.Landscape; // 版型方向
this.PAPERNAME = this.E_PrintDocument.DefaultPageSettings.PaperSize.PaperName; // 纸张类型
PaperSize tmPSize = this.E_PrintDocument.DefaultPageSettings.PaperSize; // 纸张尺寸
this.PAPERWIDTH = (int)Math.Round(tmPSize.Width * 25.4 / 100); // 纸张宽度
this.PAPERHEIGHT = (int)Math.Round(tmPSize.Height * 25.4 / 100); // 纸张高度
this.MARGINLEFT = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Left / 10f, 1); // 左边距
this.MARGINRIGHT = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Right / 10f, 1); // 右边距
this.MARGINTOP = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Top / 10f, 1); // 上边距
this.MARGINBOTTOM = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Bottom / 10f, 1); // 下边距
/// <summary>
/// 打印设置
/// 设置打印机的信息(选择打印机、设置打印份数等信息)
/// </summary>
public void PRINTSET()
this.E_PrintDialog.ShowDialog();
#endregion
#region 绘制对象
/// <summary>
/// 打印及打印前初始化数据
/// </summary>
private void Init_Printer()
HtmlHeight = 0; // 网页报表高度
HtmlWidth = 0; // 网页报表宽度
CalcTableRect(); // 计算区域矩形
RptDraw = new ReportDraw(); // 报表绘制实例
RptDraw.IsAllPrintTitle = this._isTblTitleAllPage; // 每页打印标题
RptDraw.IsAllPrintHead = this._isTblHeadAllPage; // 每页打印表头
RptDraw.IsAllPrintFoot = this._isTblFootAllPage; // 每页打印表尾
RptDraw.IsAutoFillRow = this._isAutoFillRow; // 末页自动补行
RptDraw.IsOverFlow = this._isOverFlow; // 字符溢出缩小
RptDraw.ReptRect = TableRect; // 赋值报表矩形
if (!ParseXML()) return; // 解析报表数据
CalcReportZoom(); // 计算缩小比例
CalcZoomAllSize(); // 按比计算尺寸
RptDraw.Zoom = this.Zoom; // 赋值缩小比例
RptDraw.CalcPaging(); // 计算打印分页
/// <summary>
/// PrintDocument 对象打印绘制事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void E_PrintDoc_PrintPage(object sender, PrintPageEventArgs e)
Graphics g = e.Graphics;
g.Clear(Color.White);
DrawHeader(g);
DrawFooter(g);
if (RptDraw.DrawReport(g))
e.HasMorePages = true;
else
e.HasMorePages = false;
/// <summary>
/// 绘制页眉
/// </summary>
/// <param name="g">绘图对象</param>
private void DrawHeader(Graphics g)
// 是否绘制
if (_headDraw)
// 页眉实例
PageHeader pgHeader = new PageHeader();
// 页眉矩形
RectangleF pgHeaderRect = new RectangleF(TableRect.X, // X 坐标
TableRect.Y - mmToPixel(_headHeight), // Y 坐标
TableRect.Width, // W 宽度
mmToPixel(_headHeight) // H 高度
);
// 页眉赋值
pgHeader.HeadRect = pgHeaderRect;
pgHeader.StrLeft = ReplacePageNum(_headLeft); // 左侧文本
pgHeader.StrCenter = ReplacePageNum(_headCenter); // 中间文本
pgHeader.StrRight = ReplacePageNum(_headRight); // 右侧文本
FontStyle fontStyle = FontStyle.Regular; // 字体样式
if (_headFontBold) fontStyle |= FontStyle.Bold;
if (_headFontItalic) fontStyle |= FontStyle.Italic;
if (_headFontStrikeout) fontStyle |= FontStyle.Strikeout;
if (_headFontUnderline) fontStyle |= FontStyle.Underline;
pgHeader.StrFont = new Font(_headFontName, (float)Convert.ToDouble(_headFontSize.ToLower().Replace("px", "").Replace("pt", "")), fontStyle, GraphicsUnit.Point);
pgHeader.StrColor = (Color)PrintTool.StrToColor(_headFontColor);
if (_headLineDraw) // 绘制分割线
pgHeader.LineDraw = _headLineDraw;
pgHeader.LineWidth = _headLineWidth;
pgHeader.LineColor = (Color)PrintTool.StrToColor(_headLineColor);
pgHeader.LineDash = PrintTool.GetDashStyle(_headLineDash);
// 页眉绘制
pgHeader.Draw(g);
/// <summary>
/// 绘制页脚
/// </summary>
/// <param name="g">绘图对象</param>
private void DrawFooter(Graphics g)
// 是否绘制
if (_footDraw)
// 页脚实例
PageFooter pgFooter = new PageFooter();
// 页脚矩形
RectangleF pgFooterRect = new RectangleF(TableRect.X, // X 坐标
TableRect.Y + TableRect.Height, // Y 坐标
TableRect.Width, // W 宽度
mmToPixel(_footHeight) // H 高度
);
// 页脚赋值
pgFooter.FootRect = pgFooterRect;
pgFooter.StrLeft = ReplacePageNum(_footLeft); // 左侧文本
pgFooter.StrCenter = ReplacePageNum(_footCenter); // 中间文本
pgFooter.StrRight = ReplacePageNum(_footRight); // 右侧文本
FontStyle fontStyle = FontStyle.Regular; // 字体样式
if (_footFontBold) fontStyle |= FontStyle.Bold;
if (_footFontItalic) fontStyle |= FontStyle.Italic;
if (_footFontStrikeout) fontStyle |= FontStyle.Strikeout;
if (_footFontUnderline) fontStyle |= FontStyle.Underline;
pgFooter.StrFont = new Font(_footFontName, (float)Convert.ToDouble(_footFontSize.ToLower().Replace("px", "").Replace("pt", "")), fontStyle, GraphicsUnit.Point);
pgFooter.StrColor = (Color)PrintTool.StrToColor(_footFontColor);
if (_footLineDraw) // 绘制分割线
pgFooter.LineDraw = _footLineDraw;
pgFooter.LineWidth = _footLineWidth;
pgFooter.LineColor = (Color)PrintTool.StrToColor(_footLineColor);
pgFooter.LineDash = PrintTool.GetDashStyle(_footLineDash);
// 页脚绘制
pgFooter.Draw(g);
#endregion
#region 辅助方法
/// <summary>
/// 毫米 TO 像素
/// </summary>
/// <param name="mmValue">毫米值</param>
/// <returns></returns>
public static float mmToPixel(float mmValue) //mmValue是毫米,1厘米=10毫米
return (mmValue / 25.4f * 100f);
/// <summary>
/// 替换 当前页码、总共页数两个变量
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private string ReplacePageNum(string str)
string retStr = "";
if (str == null || str.Trim() == "")
return retStr;
retStr = str;
int t = 0;
while (t >= 0)
t = retStr.IndexOf("[curpage]", StringComparison.OrdinalIgnoreCase);
if (t >= 0)
retStr = retStr.Substring(0, t) + RptDraw.CurPageNum.ToString() + retStr.Substring(t + "[curpage]".Length);
t = 0;
while (t >= 0)
t = retStr.IndexOf("[allpage]", StringComparison.OrdinalIgnoreCase);
if (t >= 0)
retStr = retStr.Substring(0, t) + RptDraw.AllPageNum.ToString() + retStr.Substring(t + "[allpage]".Length);
return retStr;
/// <summary>
/// 解析XML文件
/// </summary>
/// <returns>返回成功与否</returns>
private bool ParseXML()
if (this.DATAXML == null || this.DATAXML.Trim() == "") return false;
XmlDataDocument xmlDoc = new XmlDataDocument();
try
xmlDoc.LoadXml(this.DATAXML);
XmlNode rootNode = xmlDoc.DocumentElement;
if (rootNode.ChildNodes.Count == 0) return false;
if (rootNode.ChildNodes[0].Name.ToLower() != "table") return false;
XmlNode tableNode = rootNode.ChildNodes[0]; // 表格节点
HtmlHeight = float.Parse(tableNode.Attributes["height"].Value);
HtmlWidth = float.Parse(tableNode.Attributes["width"].Value);
int tmRowIndex = 0;
foreach (XmlNode trNode in tableNode.ChildNodes)
if (trNode.Name.ToLower() != "tr") continue;
// 解析表格行
Row tmRow = new Row();
tmRow.RowIndex = tmRowIndex;
tmRow.RowHeight = float.Parse(trNode.Attributes["height"].Value);
tmRow.RowType = trNode.Attributes["rowtype"].Value.ToLower();
// 解析单元格
foreach (XmlNode tdNode in trNode.ChildNodes)
Cell tmCell = new Cell();
#region 合并\\坐标\\矩形
tmCell.RowSpan = Convert.ToInt32(tdNode.Attributes["rowspan"].Value);
tmCell.ColSpan = Convert.ToInt32(tdNode.Attributes["colspan"].Value);
tmCell.RowIndex = Convert.ToInt32(tdNode.Attributes["r"].Value);
tmCell.ColIndex = Convert.ToInt32(tdNode.Attributes["c"].Value);
tmCell.RectX = float.Parse(tdNode.Attributes["x"].Value);
tmCell.RectY = float.Parse(tdNode.Attributes["y"].Value);
tmCell.RectW = float.Parse(tdNode.Attributes["w"].Value);
tmCell.RectH = float.Parse(tdNode.Attributes["h"].Value);
#endregion
#region 设置单元格字体
FontStyle tmStyle = new FontStyle();
tmStyle = FontStyle.Regular;
if (tdNode.Attributes["italic"].Value.ToString() == "1") tmStyle |= FontStyle.Italic;
if (tdNode.Attributes["bold"].Value.ToString() == "1") tmStyle |= FontStyle.Bold;
if (tdNode.Attributes["strikeout"].Value.ToString() == "1") tmStyle |= FontStyle.Strikeout;
if (tdNode.Attributes["underline"].Value.ToString() == "1") tmStyle |= FontStyle.Underline;
tmCell.CellFont = new Font(tdNode.Attributes["fontname"].Value, float.Parse(tdNode.Attributes["fontsize"].Value.Replace("pt", "").Replace("px", "")), tmStyle, GraphicsUnit.Point);
tmCell.FontColor = (Color)PrintTool.StrToColor(tdNode.Attributes["fontcolor"].Value);
tmCell.BackColor = (Color)PrintTool.StrToColor(tdNode.Attributes["backcolor"].Value);
StringFormat tmFormat = new StringFormat();
switch (tdNode.Attributes["align"].Value.ToLower()) // 水平对齐方式
case "center":
tmFormat.Alignment = StringAlignment.Center;
break;
case "right":
tmFormat.Alignment = StringAlignment.Far;
break;
default:
tmFormat.Alignment = StringAlignment.Near;
break;
switch (tdNode.Attributes["valign"].Value.ToLower()) // 垂直对齐方式
case "middle":
tmFormat.LineAlignment = StringAlignment.Center;
break;
case "bottom":
tmFormat.LineAlignment = StringAlignment.Far;
break;
default:
tmFormat.LineAlignment = StringAlignment.Near;
break;
tmCell.strFormat = tmFormat;
#endregion
#region 内嵌图片-属性
tmCell.IsImage = tdNode.Attributes["isimage"].Value.ToString() == "1" ? true : false;
if (tmCell.IsImage)
tmCell.ImageUrl = tdNode.Attributes["imageurl"].Value;
#endregion
#region 单元格边框属性
// 左边框线
string tmVal = tdNode.Attributes["leftwidth"].Value;
if (tmVal.IndexOf("px") >= 0)
tmCell.LeftBorder = new BorderLine(
float.Parse(tmVal.Replace("px", "")),
(Color)PrintTool.StrToColor(tdNode.Attributes["leftcolor"].Value),
PrintTool.GetDashStyle(tdNode.Attributes["leftdash"].Value)
);
// 上边框线
tmVal = tdNode.Attributes["topwidth"].Value;
if (tmVal.IndexOf("px") >= 0)
tmCell.TopBorder = new BorderLine(
float.Parse(tmVal.Replace("px", "")),
(Color)PrintTool.StrToColor(tdNode.Attributes["topcolor"].Value),
PrintTool.GetDashStyle(tdNode.Attributes["topdash"].Value)
);
// 右边框线
tmVal = tdNode.Attributes["rightwidth"].Value;
if (tmVal.IndexOf("px") >= 0)
tmCell.RightBorder = new BorderLine(
float.Parse(tmVal.Replace("px", "")),
(Color)PrintTool.StrToColor(tdNode.Attributes["rightcolor"].Value),
PrintTool.GetDashStyle(tdNode.Attributes["rightdash"].Value)
);
// 下边框线
tmVal = tdNode.Attributes["bottomwidth"].Value;
if (tmVal.IndexOf("px") >= 0)
tmCell.BottomBorder = new BorderLine(
float.Parse(tmVal.Replace("px", "")),
(Color)PrintTool.StrToColor(tdNode.Attributes["bottomcolor"].Value),
PrintTool.GetDashStyle(tdNode.Attributes["bottomdash"].Value)
);
#endregion
#region 单据格数据数值
tmCell.Value = tdNode.InnerText;
#endregion
// 加入对应的行内
tmRow.RowCells.Add(tmCell);
RptDraw.RowsList.Add(tmRow);
tmRowIndex++;
catch
return false;
finally
xmlDoc = null;
return true;
/// <summary>
/// 计算报表区域矩形
/// 真实的绘制报表的区域
/// </summary>
private void CalcTableRect()
// 重新初始化实例
TableRect = new RectangleF();
// 左顶点 X坐标
TableRect.X = mmToPixel(_marginLeft);
// 左顶点 Y坐标
TableRect.Y = mmToPixel(_marginTop);
if (_headDraw) // 需要绘制页眉
TableRect.Y += mmToPixel(_headHeight);
// 报表矩形宽度高度
if (this.LANDSCAPE) // 版型方向 横向
// 颠倒 宽高
TableRect.Width = mmToPixel((float)_paperHeight - _marginLeft - _marginRight);
TableRect.Height = mmToPixel((float)_paperWidth - _marginTop - _marginBottom);
else // 版型方向 纵向
TableRect.Width = mmToPixel((float)_paperWidth - _marginLeft - _marginRight);
TableRect.Height = mmToPixel((float)_paperHeight - _marginTop - _marginBottom);
// 报表矩形高度缩减
if (_headDraw) // 需要绘制页眉
TableRect.Height -= mmToPixel(_headHeight);
if (_footDraw) // 需要绘制页脚
TableRect.Height -= mmToPixel(_footHeight);
/// <summary>
/// 计算缩放比例
/// </summary>
private void CalcReportZoom()
if (this.ZOOMTYPE.ToLower() == "row")
if (Convert.ToInt32(TableRect.Width) >= HtmlWidth)
this.Zoom = 1;
else
this.Zoom = TableRect.Width / HtmlWidth;
else if (this.ZOOMTYPE.ToLower() == "col")
if (Convert.ToInt32(TableRect.Height) >= HtmlHeight)
this.Zoom = 1;
else
this.Zoom = TableRect.Height / HtmlHeight;
else
this.Zoom = 1;
/// <summary>
/// 转换所有的尺寸
/// 根据缩放比例
/// </summary>
private void CalcZoomAllSize()
if (this.Zoom != 1)
// 转换HTML 高度宽度
HtmlWidth = HtmlWidth * Zoom;
HtmlHeight = HtmlHeight * Zoom;
// 转换所有行号
foreach (Row zRow in this.RptDraw.RowsList)
// 行高缩小
zRow.RowHeight = zRow.RowHeight * Zoom;
// 转换所有单元格
foreach (Cell zCell in zRow.RowCells)
zCell.RectX = zCell.RectX * Zoom;
zCell.RectY = zCell.RectY * Zoom;
zCell.RectW = zCell.RectW * Zoom;
zCell.RectH = zCell.RectH * Zoom;
zCell.TopBorder.LineWidth = zCell.TopBorder.LineWidth * Zoom;
zCell.BottomBorder.LineWidth = zCell.BottomBorder.LineWidth * Zoom;
zCell.LeftBorder.LineWidth = zCell.LeftBorder.LineWidth * Zoom;
zCell.RightBorder.LineWidth = zCell.RightBorder.LineWidth * Zoom;
// 字体相应缩小
zCell.CellFont = new Font(zCell.CellFont.Name, zCell.CellFont.Size * Zoom, zCell.CellFont.Style, GraphicsUnit.Point);
#endregion
2、ReportDraw 打印绘制类
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
namespace E_Print
/// <summary>
/// 报表绘制
/// </summary>
public class ReportDraw
#region 私有成员
/// <summary>
/// 当前页码
/// </summary>
private int _curPageNum;
/// <summary>
/// 总共页数
/// </summary>
private int _allPageNum;
/// <summary>
/// 表格矩形
/// </summary>
private RectangleF _reptRect;
/// <summary>
/// 报表全部行集
/// </summary>
private List<Row> _rowsList;
/// <summary>
/// 分页页面数组
/// </summary>
private List<PagingItem> _pageList;
/// <summary>
/// 是否每页打印标题
/// </summary>
private bool _isAllPrintTitle;
/// <summary>
/// 是否每页打印表头
/// </summary>
private bool _isAllPrintHead;
/// <summary>
/// 是否每页打印表尾
/// </summary>
private bool _isAllPrintFoot;
/// <summary>
/// 是否末页自动补行
/// </summary>
private bool _isAutoFillRow;
/// <summary>
/// 缩小比例
/// </summary>
private float _zoom;
/// <summary>
/// 字符溢出处理方式
/// </summary>
private bool _isOverFlow;
/// <summary>
/// 每页打印的标题+表头的高度
/// </summary>
private float _headPix;
/// <summary>
/// 每页打印的表尾高度
/// </summary>
private float _footPix;
#endregion
#region 构造方法
/// <summary>
/// 构造函数
/// </summary>
public ReportDraw()
_curPageNum = 1;
_allPageNum = 1;
_reptRect = new RectangleF();
_rowsList = new List<Row>();
_pageList = new List<PagingItem>();
_isAllPrintTitle = false;
_isAllPrintHead = false;
_isAllPrintFoot = false;
_isAutoFillRow = false;
_zoom = 1;
_isOverFlow = false;
_headPix = 0;
_footPix = 0;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="printTitle">每页打印标题</param>
/// <param name="printHead">每页打印表头</param>
/// <param name="printFoot">每页打印表位</param>
/// <param name="fillRows">自动补全空行</param>
/// <param name="tableRect">报表尺寸矩形</param>
/// <param name="overFlow">字符溢出处理</param>
public ReportDraw(bool printTitle, bool printHead, bool printFoot, bool fillRows, RectangleF tableRect, bool overFlow)
_reptRect = tableRect;
_isAllPrintTitle = printTitle;
_isAllPrintHead = printHead;
_isAllPrintFoot = printFoot;
_isAutoFillRow = fillRows;
_isOverFlow = overFlow;
_curPageNum = 1;
_allPageNum = 1;
_zoom = 1;
_rowsList = new List<Row>();
_pageList = new List<PagingItem>();
_headPix = 0;
_footPix = 0;
#endregion
#region 属性方法
/// <summary>
/// 获取--设置--当前页码
/// </summary>
public int CurPageNum
get return _curPageNum;
set _curPageNum = value;
/// <summary>
/// 获取--设置--总共页数
/// </summary>
public int AllPageNum
get return _allPageNum;
set _allPageNum = value;
/// <summary>
/// 获取--设置--表格矩形
/// </summary>
public RectangleF ReptRect
get return _reptRect;
set _reptRect = value;
/// <summary>
/// 获取--设置--报表全部行集
/// </summary>
public List<Row> RowsList
get return _rowsList;
set _rowsList = value;
/// <summary>
/// 获取--设置--分页页面数组
/// </summary>
public List<PagingItem> PageList
get return _pageList;
set _pageList = value;
/// <summary>
/// 获取--设置--是否每页打印标题
/// </summary>
public bool IsAllPrintTitle
get return _isAllPrintTitle;
set _isAllPrintTitle = value;
/// <summary>
/// 获取--设置--是否每页打印表头
/// </summary>
public bool IsAllPrintHead
get return _isAllPrintHead;
set _isAllPrintHead = value;
/// <summary>
/// 获取--设置--是否每页打印表尾
/// </summary>
public bool IsAllPrintFoot
get return _isAllPrintFoot;
set _isAllPrintFoot = value;
/// <summary>
/// 获取--设置--末页是否自动补行
/// </summary>
public bool IsAutoFillRow
get return _isAutoFillRow;
set _isAutoFillRow = value;
/// <summary>
/// 获取--设置--缩小比例
/// </summary>
public float Zoom
get return _zoom;
set _zoom = value;
/// <summary>
/// 获取--设置--字符溢出处理方式
/// </summary>
public bool IsOverFlow
get return _isOverFlow;
set _isOverFlow = value;
/// <summary>
/// 获取--设置--每页打印的标题+表头高度
/// </summary>
public float HeadPix
get return _headPix;
set _headPix = value;
/// <summary>
/// 获取--设置--每页打印的表尾高度
/// </summary>
public float FootPix
get return _footPix;
set _footPix = value;
#endregion
#region 计算分页
/// <summary>
/// 计算分页
/// </summary>
public void CalcPaging()
// 分页实例
PagingCalc insCalc = new PagingCalc();
insCalc.TableRect = this.ReptRect;
insCalc.RowsList = this.RowsList;
insCalc.IsAllPrintTitle = this.IsAllPrintTitle;
insCalc.IsAllPrintHead = this.IsAllPrintHead;
insCalc.IsAllPrintFoot = this.IsAllPrintFoot;
// 分页计算
_pageList = insCalc.CalcPages();
this._allPageNum = _pageList.Count;
this._curPageNum = 1;
this._headPix = insCalc.MyHeadPix;
this._footPix = insCalc.MyFootPix;
#endregion
#region 绘制方法
/// <summary>
/// 绘制报表
/// </summary>
/// <param name="g"></param>
/// <returns>返回是否结束</returns>
public bool DrawReport(Graphics g)
bool isMorePage = false;
float offsetX = _reptRect.X; // X 偏移量
float offsetY = _reptRect.Y; // Y 偏移量
bool isCanFillRow = false; // 是否需要补行
bool isFillFlag = false; // 是否已经补过
int isFillRowNum = 0; // 需要补充几行
PagingItem nowPage = GetPageItem(CurPageNum); // 当前页
if (nowPage != null)
#region 判定高度不足是否自动补行
// 判定补行条件 报表设置了末页不足自动补行、同时 为最后一页
if (_isAutoFillRow == true && CurPageNum == AllPageNum)
// 判定页面高度 与 数据高度
float N_PageHeith = ReptRect.Height; // 当前页面高度
float N_DataHeith = GetThisPageDataRowsHeight(); // 当前数据高度
// 补行行高21
while ((N_DataHeith + (isFillRowNum + 1) * 21 * Zoom以上是关于网页WEB打印控件制作 开放源码可以调试的主要内容,如果未能解决你的问题,请参考以下文章