C# 实用工具类:FastReport 打印封装(完整可复用)

在 C# 桌面开发(尤其是 WinForm、DevExpress 项目)中,报表打印是高频需求,而 FastReport 作为轻量、灵活的报表工具,深受开发者青睐。但重复编写报表加载、数据源注册、打印机配置等代码,不仅繁琐还易出错。本文将解析一套完整的 FastReport 打印工具类(基于你提供的代码优化完善),封装了打印核心逻辑、打印机校验、模板校验等功能,可直接复制到项目中复用,大幅提升开发效率,新手也能快速上手!
## 一、前言:为什么要封装 FastReport 工具类?
FastReport 本身提供了完整的报表操作 API,但在实际项目中,我们会遇到这些痛点:
– 重复编写报表加载、数据源注册代码,冗余且维护成本高;
– 打印机选择、模板路径校验、异常处理分散在各个业务逻辑中,代码混乱;
– 不同报表(如住院费用清单、普通报表)的打印逻辑差异小,可统一封装复用;
– 缺乏统一的异常捕获和提示,用户体验不佳。
基于此,我们封装了 `Fast_Report` 工具类,将报表打印的核心逻辑(模板加载、数据源注册、打印机配置、异常处理)统一封装,对外提供简洁的调用接口,无需重复编码,直接传入参数即可实现打印功能。
## 二、环境准备
在使用该工具类前,需先完成 FastReport 的环境配置,确保项目能正常引用相关组件:
1. 项目框架:.NET Framework(适配 WinForm/DevExpress 项目,本文代码兼容 .NET Framework 4.0+);
2. 安装 FastReport 组件:通过 NuGet 安装 `FastReport` 核心包(搜索 FastReport,安装对应版本);
3. 引用依赖:确保项目中引用 `FastReport.dll`、`FastReport.Data.dll`,若使用 DevExpress 控件,需额外引用对应兼容包;
4. 模板准备:在项目根目录创建 `Report` 文件夹,存放 FastReport 模板文件(.frx 格式),模板中需提前设计好报表布局、数据绑定字段。
## 三、完整 FastReport 工具类代码(可直接复制复用)
以下是完整的 `Fast_Report` 工具类代码,包含 2 个打印方法(主方法+备用方法)、1 个打印机校验方法,注释详细,可根据自身项目需求微调(如提示信息、模板路径):
“`csharp
using System;
using System.Data;
using System.IO;
using System.Reflection;
using System.Drawing.Printing;
using FastReport;
using FastReport.Data;
using DevExpress.XtraEditors; // 若未使用DevExpress,可替换为System.Windows.Forms.MessageBox
namespace YourNamespace // 替换为你的项目命名空间
{
/// <summary>
/// FastReport 打印工具类
/// 封装报表加载、数据源注册、打印机配置、异常处理等核心逻辑
/// 可直接复用,支持多报表类型、指定打印机打印
/// </summary>
public class Fast_Report
{
/// <summary>
/// 错误信息(用于返回打印异常详情)
/// </summary>
static string MessageError = string.Empty;
/// <summary>
/// 核心打印方法(推荐使用)
/// </summary>
/// <param name=”PrinterName”>指定打印机名称(可为空,为空则使用默认打印机)</param>
/// <param name=”type”>报表类型(用于区分不同报表的数据源绑定逻辑)</param>
/// <param name=”ReportNmae”>报表模板名称(无需加.frx后缀)</param>
/// <param name=”dset”>数据源(DataSet,支持多表)</param>
/// <returns>打印结果(空字符串表示成功,非空表示错误信息)</returns>
public static string FastReport_Print(string PrinterName, int type, string ReportNmae, DataSet dset)
{
// 初始化错误信息
MessageError = string.Empty;
try
{
// 1. 实例化FastReport报表对象
FastReport.Report report = new FastReport.Report();
// 2. 获取报表模板路径(项目根目录/Report/模板名.frx)
// 优先获取当前程序运行目录(兼容不同部署场景)
string path = Environment.CurrentDirectory;
// 拼接模板完整路径(Report文件夹需提前创建,存放.frx模板)
string reportFile = Path.Combine(Path.Combine(path, “Report”), ReportNmae + “.frx”);
// 3. 校验模板文件是否存在
if (!File.Exists(reportFile))
{
string errorMsg = “很抱歉,未找到对应的打印模板,请联系系统管理员!\r\n\r\n” + reportFile;
XtraMessageBox.Show(errorMsg); // 若未用DevExpress,替换为MessageBox.Show(errorMsg)
return errorMsg;
}
// 4. 加载报表模板
report.Load(reportFile);
// 5. 注册数据源(将DataSet注册到报表中,供模板绑定)
report.RegisterData(dset);
// 6. 根据报表类型,绑定数据源到报表的DataBand(可根据实际报表调整)
// 此处适配两种报表类型,可根据自身项目扩展更多类型
switch (type)
{
case 1:// 示例:住院病人费用分类汇总清单
// 找到报表中的DataBand(需与模板中的DataBand名称一致,此处为”band”)
FastReport.DataBand band = report.FindObject(“band”) as FastReport.DataBand;
// 获取数据源(与DataSet中的表名对应)
FastReport.Data.DataSourceBase dataSource = report.GetDataSource(dset.Tables[0].TableName);
// 将数据源绑定到DataBand
band.DataSource = dataSource;
break;
case 2:// 示例:其他报表(可自定义报表类型)
FastReport.DataBand band1 = report.FindObject(“band”) as FastReport.DataBand;
FastReport.Data.DataSourceBase dataSource1 = report.GetDataSource(dset.Tables[0].TableName);
band1.DataSource = dataSource1;
break;
}
// 7. 打印配置:不显示打印对话框,直接打印(可根据需求调整)
report.PrintSettings.ShowDialog = false;
// 8. 校验并设置指定打印机(若打印机存在,使用指定打印机;否则使用默认打印机)
if (Fast_Report.DYJBOOL(PrinterName))
{
report.PrintSettings.Printer = PrinterName;
}
// 9. 准备报表(解析模板和数据源)
report.Prepare();
// 10. 显示打印预览(false表示不模态显示,可根据需求改为true)
report.ShowPrepared(false);
// 若需直接打印(不显示预览),注释上一行,启用下一行
// report.Print();
}
catch (Exception aa)
{
// 捕获异常,记录错误信息并提示
MessageError = aa.ToString();
XtraMessageBox.Show(MessageError);
}
// 返回错误信息(空字符串表示打印成功)
return MessageError;
}
#region 备用打印方法(未使用,可根据需求启用)
/// <summary>
/// 备用打印方法(单表数据源,简化版)
/// </summary>
/// <param name=”ReportNmae”>报表模板名称(无需加.frx后缀)</param>
/// <param name=”dset”>数据源(DataTable,单表)</param>
/// <param name=”name”>可选参数(可用于扩展,如打印机名称)</param>
public static void FastReport_Print(string ReportNmae, DataTable dset, string name = null)
{
// 使用using自动释放报表资源,避免内存泄露
using (FastReport.Report report = new FastReport.Report())
{
// 拼接模板路径(使用Application.StartupPath,适用于WinForm项目)
string reportFile = Path.Combine(Path.Combine(Application.StartupPath, “Report”), ReportNmae + “.frx”);
// 校验模板文件
if (!File.Exists(reportFile))
{
MessageBox.Show(“很抱歉,未找到对应的打印模板,请联系系统管理员!”);
return;
}
// 加载模板、注册单表数据源
report.Load(reportFile);
report.RegisterData(dset, dset.TableName);// 单表数据源注册,指定表名
// 打印配置:不显示打印对话框
report.PrintSettings.ShowDialog = false;
// 准备并显示预览
report.Prepare();
report.ShowPrepared();
// 直接打印(不显示预览)
// report.Print();
}
}
/// <summary>
/// 打印机校验方法:判断指定打印机是否已安装
/// </summary>
/// <param name=”PrinterName”>打印机名称</param>
/// <returns>true:打印机存在;false:打印机不存在</returns>
public static bool DYJBOOL(string PrinterName)
{
try
{
bool isFind = false;
// 实例化打印文档,用于获取系统已安装打印机
System.Drawing.Printing.PrintDocument printDoc = new System.Drawing.Printing.PrintDocument();
// 遍历系统中所有已安装的打印机
foreach (string pName in PrinterSettings.InstalledPrinters)
{
// 忽略大小写、空格,精准匹配打印机名称
if (PrinterName.Trim().ToUpper() == pName.Trim().ToUpper())
{
printDoc.PrinterSettings.PrinterName = PrinterName;
isFind = true;
break;
}
}
// 若未找到指定打印机,可启用提示(根据需求调整)
// if (isFind == false)
// {
// XtraMessageBox.Show(“未找到名为\'” + PrinterName.Trim().ToUpper() + “\’的打印机!”, “提醒”, MessageBoxButtons.OK, MessageBoxIcon.Warning);
// }
return isFind;
}
catch (Exception ex)
{
// 异常情况下,返回false(默认使用系统默认打印机)
return false;
}
}
}
}
“`
## 四、工具类核心解析(关键知识点)
该工具类封装了 FastReport 打印的全流程,核心逻辑和关键细节如下,帮助你理解并灵活调整:
### 1. 模板路径获取(兼容多场景)
工具类中使用 `Environment.CurrentDirectory` 获取程序运行目录,拼接 `Report` 文件夹路径,确保模板能被正确加载:
“`csharp
string path = Environment.CurrentDirectory;
string reportFile = Path.Combine(Path.Combine(path, “Report”), ReportNmae + “.frx”);
“`
补充:若项目部署后模板路径异常,可替换为 `Application.StartupPath`(适用于 WinForm 项目),即备用方法中的路径获取方式。
### 2. 数据源注册与绑定
支持 `DataSet`(多表)和 `DataTable`(单表)两种数据源,注册后需绑定到报表的 `DataBand`(报表模板中的数据带):
– 多表数据源:`report.RegisterData(dset);`,再通过 `report.GetDataSource(表名)` 获取指定表,绑定到 DataBand;
– 单表数据源:`report.RegisterData(dset, dset.TableName);`,直接注册并指定表名,简化操作。
关键注意:模板中的`DataBand` 名称(如工具类中的 “band”),必须与代码中`report.FindObject(“band”)` 的名称一致,否则绑定失败。
### 3. 打印机配置与校验
工具类中的 `DYJBOOL` 方法,用于校验指定打印机是否已安装,避免打印失败:
– 遍历系统已安装打印机:`PrinterSettings.InstalledPrinters`;
– 忽略大小写和空格匹配,提升兼容性;
– 若打印机不存在,返回 false,工具类会自动使用系统默认打印机。
### 4. 异常处理与返回值
核心打印方法 `FastReport_Print` 用 try-catch 捕获所有异常,错误信息存入 `MessageError`,并返回给调用者:
– 打印成功:返回空字符串;
– 打印失败(模板缺失、异常):返回具体错误信息,同时弹出提示框,提升用户体验。
### 5. 两种打印模式(灵活选择)
– 预览打印:`report.ShowPrepared(false);`,显示打印预览界面,用户可确认后再打印;
– 直接打印:注释预览代码,启用 `report.Print();`,不显示预览,直接发送到打印机。
## 五、工具类调用示例(实战演示)
以下是两种常见场景的调用示例,直接复制到业务代码中,替换参数即可使用:
### 示例1:调用核心方法(多表数据源,指定打印机)
“`csharp
// 1. 准备数据源(DataSet,可包含多个表)
DataSet ds = new DataSet();
// 假设已从数据库查询数据,填充到DataTable并加入DataSet
DataTable dt1 = GetDataFromDB(“SELECT * FROM 住院费用表”); // 自定义方法,获取数据
ds.Tables.Add(dt1);
// 2. 调用FastReport工具类打印
string printerName = “HP LaserJet Pro MFP M426fdw”; // 你的打印机名称
int reportType = 1; // 报表类型(对应工具类中的switch case)
string reportName = “住院费用分类汇总清单”; // 报表模板名称(无需加.frx)
string result = Fast_Report.FastReport_Print(printerName, reportType, reportName, ds);
// 3. 校验打印结果
if (string.IsNullOrEmpty(result))
{
XtraMessageBox.Show(“打印操作已发起,正在预览!”);
}
else
{
XtraMessageBox.Show(“打印失败:” + result);
}
“`
### 示例2:调用备用方法(单表数据源,默认打印机)
“`csharp
// 1. 准备单表数据源
DataTable dt = GetDataFromDB(“SELECT * FROM 普通报表数据”);
// 2. 调用备用打印方法(不指定打印机,使用默认打印机)
Fast_Report.FastReport_Print(“普通报表模板”, dt);
// 说明:备用方法无返回值,异常会直接弹出提示框
“`
## 六、避坑提醒(新手必看)
– 模板路径问题:必须在项目根目录创建 `Report` 文件夹,且模板名称与代码中传入的 `ReportNmae` 一致(区分大小写),否则会提示“未找到模板”;
– DataBand 名称匹配:模板中的 DataBand 名称(如 “band”)必须与代码中 `report.FindObject(“band”)` 的名称完全一致,否则数据源绑定失败,报表无数据;
– 打印机名称匹配:传入的 `PrinterName` 需与系统中打印机名称一致(可在“设备和打印机”中查看),工具类虽忽略大小写,但建议精准输入;
– 资源释放:备用方法中使用 `using` 包裹报表对象,可自动释放资源,核心方法若需优化,也可添加 `using`;
– DevExpress 依赖:若项目未使用 DevExpress,需将 `XtraMessageBox` 替换为 `System.Windows.Forms.MessageBox`,避免编译报错。
## 七、总结
本文提供的 FastReport 工具类,封装了报表打印的核心逻辑,解决了重复编码、逻辑分散、异常处理不统一等痛点,可直接复制到 C# 桌面项目中复用。无论是多表报表、单表报表,还是指定打印机打印、预览打印,都能通过简单调用实现。
工具类可根据自身项目需求灵活扩展:如增加更多报表类型(switch case 扩展)、调整模板路径、优化提示信息、添加打印参数(如打印份数)等。掌握这个工具类,能大幅节省报表打印功能的开发时间,提升代码可维护性。
如果在使用过程中遇到模板绑定失败、打印机不生效、异常报错等问题,欢迎在评论区留言交流,一一为你解答!
夜雨聆风
