在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)
下面贴出源码:(在源码中有详细的注释说明)
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace E_Print
{
/// <summary>
/// 分页计算
/// </summary>
public class PagingCalc
{
#region 私有变量
/// <summary>
/// 表格区域
/// </summary>
private RectangleF _tableRect;
/// <summary>
/// 报表行集
/// </summary>
private List<Row> _rowsList;
/// <summary>
/// 是否每页打印标题
/// </summary>
private bool _isAllPrintTitle;
/// <summary>
/// 是否每页打印表头
/// </summary>
private bool _isAllPrintHead;
/// <summary>
/// 是否每页打印表尾
/// </summary>
private bool _isAllPrintFoot;
/// <summary>
/// 标题行集
/// </summary>
private List<Row> TitleList;
/// <summary>
/// 表头前行集
/// </summary>
private List<Row> HForeList;
/// <summary>
/// 表头行集
/// </summary>
private List<Row> HeadList;
/// <summary>
/// 数据行集
/// </summary>
private List<Row> DataList;
/// <summary>
/// 表尾行集
/// </summary>
private List<Row> FootList;
/// <summary>
/// 每页打印标题+表头高度
/// </summary>
private float _myHeadPix;
/// <summary>
/// 每页打印表尾高度
/// </summary>
private float _myFootPix;
#endregion
#region 构造方法
/// <summary>
/// 构造函数
/// </summary>
public PagingCalc()
{
_tableRect = new RectangleF();
_rowsList = new List<Row>();
_isAllPrintTitle = false;
_isAllPrintHead = false;
_isAllPrintFoot = false;
TitleList = new List<Row>();
HForeList = new List<Row>();
HeadList = new List<Row>();
DataList = new List<Row>();
FootList = new List<Row>();
_myHeadPix = 0;
_myFootPix = 0;
}
#endregion
#region 属性方法
/// <summary>
/// 获取--设置--表格区域
/// </summary>
public RectangleF TableRect
{
get { return _tableRect; }
set { _tableRect = value; }
}
/// <summary>
/// 获取--设置--表格行集
/// </summary>
public List<Row> RowsList
{
get { return _rowsList; }
set { _rowsList = 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 float MyHeadPix
{
get { return _myHeadPix; }
set { _myHeadPix = value; }
}
/// <summary>
/// 获取--设置--每页打印表尾巴高度
/// </summary>
public float MyFootPix
{
get { return _myFootPix; }
set { _myFootPix = value; }
}
#endregion
#region 计算方法
/// <summary>
/// 分页计算
/// </summary>
/// <returns></returns>
public List<PagingItem> CalcPages()
{
List<PagingItem> retPages = new List<PagingItem>();
// 无需分页
if (Get_TableAllHeight() <= TableRect.Height)
{
PagingItem tmItem0 = new PagingItem();
tmItem0.PageNum = 1;
for (int y = 0; y < RowsList.Count; y++)
{
tmItem0.IndexList.Add(y);
}
retPages.Add(tmItem0);
}
else // 需要分页
{
// 有设置了 每页打印标题、表头、表位 其中的任意一个
if (Get_IsCusSet_THDF()) // 则执行每页相对分页
{
Paging_Relative(0, ref retPages);
// 计算每页打印头尾高度
MyHeadPix = 0;
if (IsAllPrintTitle)
{
MyHeadPix += Get_TableTileHeight();
}
if (IsAllPrintHead)
{
MyHeadPix += Get_TableHeadHeight();
}
if (IsAllPrintFoot)
{
MyFootPix = Get_TableFootHeight();
}
}
else // 执行直接数据分页
{
Paging_Direct(0, ref retPages);
}
}
return retPages;
}
/// <summary>
/// 直接分页
/// </summary>
/// <param name="startR">开始行号</param>
/// <param name="pages">页面数组</param>
private void Paging_Direct(int startR, ref List<PagingItem> pages)
{
float p_Height = TableRect.Height;
PagingItem p_Item = new PagingItem();
p_Item.PageNum = pages.Count + 1;
for (int t = startR; t < RowsList.Count; t++)
{
// 检查行内单元格是否不允许分页两种情况:条形码,图片
if (Paging_CheckCell(RowsList[t], p_Height))
{
startR = t;
pages.Add(p_Item);
Paging_Direct(startR, ref pages);
break;
}
else
{
p_Height -= RowsList[t].RowHeight;
if (p_Height <= 0)
{
startR = t;
pages.Add(p_Item);
Paging_Direct(startR, ref pages);
break;
}
else
{
p_Item.IndexList.Add(t);
if (t == RowsList.Count - 1)
{
pages.Add(p_Item);
}
}
}
}
}
/// <summary>
/// 相对分页
/// </summary>
/// <param name="startR">开始序号</param>
/// <param name="pages">页面数组</param>
private void Paging_Relative(int startR, ref List<PagingItem> pages)
{
SplitReportArea(); // 拆分表行
float p_Height = TableRect.Height; // 页面总高
PagingItem p_Item = new PagingItem(); // 分页页面
p_Item.PageNum = pages.Count + 1; // 分页页码
bool runNext = false; // 继续分页
#region 每页打印标题
// 每页打印标题
if (IsAllPrintTitle)
{
p_Height -= Get_TableTileHeight();
foreach (Row p_Row in TitleList)
p_Item.IndexList.Add(p_Row.RowIndex);
}
else
{
if (p_Item.PageNum == 1) // 第一页特殊处理
{
p_Height -= Get_TableTileHeight();
foreach (Row p_Row in TitleList)
p_Item.IndexList.Add(p_Row.RowIndex);
}
}
#endregion
#region 每页打印表头
// 每页打印表头
if (IsAllPrintHead)
{
if (p_Item.PageNum == 1) // 第一页特殊处理
{
// 计算表头前的行高
p_Height -= Get_TableHForHeight();
foreach (Row p_Row in HForeList)
p_Item.IndexList.Add(p_Row.RowIndex);
}
// 计算表头行的高度
p_Height -= Get_TableHeadHeight();
foreach (Row p_Row in HeadList)
p_Item.IndexList.Add(p_Row.RowIndex);
}
else
{
if (p_Item.PageNum == 1) // 第一页特殊处理
{
// 计算表头前的行高
p_Height -= Get_TableHForHeight();
foreach (Row p_Row in HForeList)
p_Item.IndexList.Add(p_Row.RowIndex);
// 计算表头行的高度
p_Height -= Get_TableHeadHeight();
foreach (Row p_Row in HeadList)
p_Item.IndexList.Add(p_Row.RowIndex);
}
}
#endregion
#region 每页数据区域
// 每页数据划分
if (IsAllPrintFoot)
{
p_Height -= Get_TableFootHeight(); // 表格高度 先减去表尾的高度
}
for (int t = startR; t < DataList.Count; t++)
{
// 检查行内单元格是否不允许分页两种情况:条形码,图片
if (Paging_CheckCell(DataList[t], p_Height)) // 此情况下,单元格不能分割,并且高度超过页面剩余高度,所以要启动新的一页
{
startR = t;
runNext = true;
break;
}
else
{
p_Height -= DataList[t].RowHeight;
if (p_Height <= 0)
{
startR = t;
runNext = true;
break;
}
else
{
p_Item.IndexList.Add(DataList[t].RowIndex);
}
}
}
#endregion
#region 每页打印表尾
// 每页打印表尾
if (IsAllPrintFoot)
{
foreach (Row p_Row in FootList)
p_Item.IndexList.Add(p_Row.RowIndex);
}
#endregion
#region 添加分页页面
pages.Add(p_Item);
if (runNext)
{
Paging_Relative(startR, ref pages);
}
#endregion
}
/// <summary>
/// 检查行内单元格如果是图片
/// 并且合并行数大于1
/// </summary>
/// <param name="cRow"></param>
/// <param name="cHeight"></param>
/// <returns></returns>
private bool Paging_CheckCell(Row cRow, float cHeight)
{
foreach (Cell cCell in cRow.RowCells)
{
if (cCell.IsImage == true)
{
if (cCell.RectH > cHeight)
return true;
}
}
return false;
}
#endregion
#region 辅助方法
/// <summary>
/// 获取--报表全部高度
/// </summary>
/// <returns></returns>
private float Get_TableAllHeight()
{
float retHight = 0;
for (int k = 0; k < RowsList.Count; k++)
{
Row t_Row = RowsList[k];
retHight += t_Row.RowHeight;
}
return retHight;
}
/// <summary>
/// 获取是否设置了标题、表头、表尾 中的任意一个
/// </summary>
/// <returns></returns>
private bool Get_IsCusSet_THDF()
{
string tmType = "";
foreach (Row cusRow in this.RowsList)
{
tmType = cusRow.RowType.ToLower().Trim();
if (tmType == "t" || tmType == "h" || tmType == "f")
return true;
}
return false;
}
/// <summary>
/// 获取--报表标题高度
/// </summary>
/// <returns></returns>
private float Get_TableTileHeight()
{
float retHight = 0;
for (int k = 0; k < TitleList.Count; k++)
retHight += TitleList[k].RowHeight;
return retHight;
}
/// <summary>
/// 获取--报表表头前高度
/// </summary>
/// <returns></returns>
private float Get_TableHForHeight()
{
float retHight = 0;
for (int k = 0; k < HForeList.Count; k++)
retHight += HForeList[k].RowHeight;
return retHight;
}
/// <summary>
/// 获取--报表表头高度
/// </summary>
/// <returns></returns>
private float Get_TableHeadHeight()
{
float retHight = 0;
for (int k = 0; k < HeadList.Count; k++)
retHight += HeadList[k].RowHeight;
return retHight;
}
/// <summary>
/// 获取--报表表尾高度
/// </summary>
/// <returns></returns>
private float Get_TableFootHeight()
{
float retHight = 0;
for (int k = 0; k < FootList.Count; k++)
retHight += FootList[k].RowHeight;
return retHight;
}
/// <summary>
/// 拆分报表区域
/// </summary>
public void SplitReportArea()
{
TitleList = new List<Row>();
HForeList = new List<Row>();
HeadList = new List<Row>();
DataList = new List<Row>();
FootList = new List<Row>();
for (int m = 0; m < RowsList.Count; m++)
{
Row mmRow = RowsList[m];
switch (mmRow.RowType.ToLower())
{
case "t": // 标题
TitleList.Add(mmRow);
break;
case "h": // 表头
HeadList.Add(mmRow);
break;
case "f": // 表尾
FootList.Add(mmRow);
break;
case "d": // 数据
default:
DataList.Add(mmRow);
break;
}
}
// 设置表头前行集
if (TitleList.Count == 0 && HeadList.Count > 0)
{
List<Row> tmpList = new List<Row>();
for (int n = 0; n < DataList.Count; n++)
{
if (DataList[n].RowIndex < HeadList[0].RowIndex)
{
HForeList.Add(DataList[n]);
tmpList.Add(DataList[n]);
}
}
for (int n = 0; n < tmpList.Count; n++)
{
DataList.Remove(tmpList[n]);
}
tmpList.Clear();
}
// 重设表尾 不是每页打印表尾情况下,那么表位就去掉
if (!IsAllPrintFoot)
{
foreach (Row tRow in FootList)
DataList.Add(tRow);
FootList.Clear();
}
}
#endregion
}
}
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。