知识网经验知识百科全书!
登录

如何在Visual Studio中创建Grid 报表「如何在图片上添加文字」

191次浏览 | 2023-02-12 19:30:44 更新
来源 :一只小猪
最佳经验
本文由作者推荐

之前一直使用各种报表工具,如RDLC、DevExpress 套件的XtraReport报表,在之前一些文章中也有介绍,最近接触锐浪的Grid++报表,做了一些测试例子和辅助类来处理报表内容,觉得还是很不错的,特别是它的作者提供了很多报表的设计模板案例,功能还是非常强大的。试着用来做一些简单的报表,测试下功能,发现常规的二维表、套打、条形码..等我关注的功能都有,是一个比较强大的报表控件,本篇随笔主要介绍在Winform开发中使用Grid++报表设计报表模板,以及绑定数据的处理过程。

PS:给大家推荐这个WinForm应用界面开发组件——DevExpress WinForms,它能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任!

DevExpress WinForms Subscription官方最新版免费下载试用,历史版本下载,在线文档和帮助文件下载-慧都网

报表模板设计

这个报表系统,报表模板提供了很多案例,我们可以大概浏览下其功能。

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

它对应在相应的文件目录里面,我们可以逐一查看了解下,感觉提供这么多报表还是很赞的,我们可以参考着来用,非常好。

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

整个报表主要是基于现有数据进行一个报表的模板设计的,如果要预览效果,我们一般是需要绑定现有的数据,可以从各种数据库提供数据源,然后设计报表模板,进行实时的数据和格式查看及调整。

空白的报表模板大概如下所示,包含页眉页脚,以及明细表格的内容。

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

根据它的教程,模仿着简单的做了一个报表,也主要是设计报表格式的调整,和数据源的处理的关系,我们做一个两个报表就可以很快上手了。

为了动态的加入我们表格所需要的列,我们可以通过数据库里面的字段进行加入,首先提供数据源,指定我们具体的表即可(如果是自定义的信息,则可以手工添加字段)。

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

这个里面就是配置不同的数据库数据源了。

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

如SQLServer数据库的配置信息如下。

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

为了方便,我们可以利用案例的Access数据库,也就是Northwind.mdb来测试我们的报表,弄好这些我们指定对应的数据表数据即可。

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

这里面配置好数据库表信息后,我们就可以用它生成相关的字段和对应的列信息了。

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

修改列的表头,让它符合中文的表头列,如下所示。

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

我们在页脚出,加入了打印时间,页码的一些系统变量,具体操作就是添加一个综合文本,然后在内容里面插入指定的域内容即可,如下所示:

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

预览报表,我们就可以看到具体的报表格式显示了。

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

通过上面的操作,感觉生成一个报表还是很方便的,接着我有根据需要做了一个..的报表显示,方便打印资产标签。

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

绑定数据源显示的报表视图如下所示,看起来还是蛮好的。

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

数据绑定

一般我们绑定数据源,有的时候可以直接指定数据库连接,有时候可以绑定具体的数据列表,如DataTable或者Listu0026lt;Tu0026gt;这样的数据源,不同的方式报表控件的代码绑定不同。

直接绑定数据表的路径如下所示。

/// u0026lt;summaryu0026gt;/// 普通连接数据库的例子-打印预览/// u0026lt;/summaryu0026gt;private void btnNormalDatabase_Click(object sender, EventArgs e){Report = new GridppReport();string reportPath = Path.Combine(Application.StartupPath, "Reportstestgrid++.grf");string dbPath = Path.Combine(Application.StartupPath, "DataNorthWind.mdb");//从对应文件中载入报表模板数据Report.LoadFromFile(reportPath);//设置与数据源的连接串,因为在设计时指定的数据库路径是绝对路径。if (Report.DetailGrid != null){string connstr = Utility.GetDatabaseConnectionString(dbPath);Report.DetailGrid.Recordset.ConnectionString = connstr;}Report.PrintPreview(true);}

而如果需要绑定和数据库无关的动态数据源,那么就需要通过控件的FetchRecord进行处理了,如下代码所示。

Report.FetchRecord += new _IGridppReportEvents_FetchRecordEventHandler(ReportFetchRecord);

通过这样我们增加每一个对应的列单元格信息,如下是随带案例所示:

//在C#中一次填入一条记录不能成功,只能使用一次将记录全部填充完的方式private void ReportFetchRecord(){//将全部记录一次填入Report.DetailGrid.Recordset.Append();FillRecord1();Report.DetailGrid.Recordset.Post();Report.DetailGrid.Recordset.Append();FillRecord2();Report.DetailGrid.Recordset.Post();Report.DetailGrid.Recordset.Append();FillRecord3();Report.DetailGrid.Recordset.Post();}private void FillRecord1(){C1Field.AsString = "A";I1Field.AsInteger = 1;F1Field.AsFloat = 1.01;}private void FillRecord2(){C1Field.AsString = "B";I1Field.AsInteger = 2;F1Field.AsFloat = 1.02;}private void FillRecord3(){C1Field.AsString = "C";I1Field.AsInteger = 3;F1Field.AsFloat = 1.03;}

这样处理肯定很麻烦,我们常规做法是弄一个辅助类,来处理DataTable和Listu0026lt;Tu0026gt;等这样类型数据的动态增加操作。

/// u0026lt;summaryu0026gt;/// 绑定实体类集合的例子-打印预览/// u0026lt;/summaryu0026gt;private void btnBindList_Click(object sender, EventArgs e){Report = new GridppReport();//从对应文件中载入报表模板数据string reportPath = Path.Combine(Application.StartupPath, "ReportstestList.grf");Report.LoadFromFile(reportPath);Report.FetchRecord += ReportList_FetchRecord;Report.PrintPreview(true);}/// u0026lt;summaryu0026gt;/// 绑定DataTable的例子-打印预览/// u0026lt;/summaryu0026gt;private void btnBindDatatable_Click(object sender, EventArgs e){Report = new GridppReport();//从对应文件中载入报表模板数据string reportPath = Path.Combine(Application.StartupPath, "ReportstestList.grf");Report.LoadFromFile(reportPath);Report.FetchRecord += ReportList_FetchRecord2;Report.PrintPreview(true);}private void ReportList_FetchRecord(){Listu0026lt;ProductInfou0026gt; list = BLLFactoryu0026lt;Productu0026gt;.Instance.GetAll();GridReportHelper.FillRecordToReportu0026lt;ProductInfou0026gt;(Report, list);}private void ReportList_FetchRecord2(){var dataTable = BLLFactoryu0026lt;Productu0026gt;.Instance.GetAllToDataTable();GridReportHelper.FillRecordToReport(Report, dataTable);}

其中辅助类 GridReportHelper 代码如下所示。

/// u0026lt;summaryu0026gt;/// Gird++报表的辅助类/// u0026lt;/summaryu0026gt;public class GridReportHelper{private struct MatchFieldPairType{public IGRField grField;public int MatchColumnIndex;}/// u0026lt;summaryu0026gt;/// 将 DataReader 的数据转储到 Grid++Report 的数据集中/// u0026lt;/summaryu0026gt;/// u0026lt;param name="Report"u0026gt;报表对象u0026lt;/paramu0026gt;/// u0026lt;param name="dr"u0026gt;DataReader对象u0026lt;/paramu0026gt;public static void FillRecordToReport(IGridppReport Report, IDataReader dr){MatchFieldPairType[] MatchFieldPairs = new MatchFieldPairType[Math.Min(Report.DetailGrid.Recordset.Fields.Count, dr.FieldCount)];//根据字段名称与列名称进行匹配,建立DataReader字段与Grid++Report记录集的字段之间的对应关系int MatchFieldCount = 0;for (int i = 0; i u0026lt; dr.FieldCount; ++i){foreach (IGRField fld in Report.DetailGrid.Recordset.Fields){if (string.Compare(fld.RunningDBField, dr.GetName(i), true) == 0){MatchFieldPairs[MatchFieldCount].grField = fld;MatchFieldPairs[MatchFieldCount].MatchColumnIndex = i;++MatchFieldCount;break;}}}// 将 DataReader 中的每一条记录转储到Grid++Report 的数据集中去while (dr.Read()){Report.DetailGrid.Recordset.Append();for (int i = 0; i u0026lt; MatchFieldCount; ++i){var columnIndex = MatchFieldPairs[i].MatchColumnIndex;if (!dr.IsDBNull(columnIndex)){MatchFieldPairs[i].grField.Value = dr.GetValue(columnIndex);}}Report.DetailGrid.Recordset.Post();}}/// u0026lt;summaryu0026gt;/// 将 DataTable 的数据转储到 Grid++Report 的数据集中/// u0026lt;/summaryu0026gt;/// u0026lt;param name="Report"u0026gt;报表对象u0026lt;/paramu0026gt;/// u0026lt;param name="dt"u0026gt;DataTable对象u0026lt;/paramu0026gt;public static void FillRecordToReport(IGridppReport Report, DataTable dt){MatchFieldPairType[] MatchFieldPairs = new MatchFieldPairType[Math.Min(Report.DetailGrid.Recordset.Fields.Count, dt.Columns.Count)];//根据字段名称与列名称进行匹配,建立DataReader字段与Grid++Report记录集的字段之间的对应关系int MatchFieldCount = 0;for (int i = 0; i u0026lt; dt.Columns.Count; ++i){foreach (IGRField fld in Report.DetailGrid.Recordset.Fields){if (string.Compare(fld.Name, dt.Columns[i].ColumnName, true) == 0){MatchFieldPairs[MatchFieldCount].grField = fld;MatchFieldPairs[MatchFieldCount].MatchColumnIndex = i;++MatchFieldCount;break;}}}// 将 DataTable 中的每一条记录转储到 Grid++Report 的数据集中去foreach (DataRow dr in dt.Rows){Report.DetailGrid.Recordset.Append();for (int i = 0; i u0026lt; MatchFieldCount; ++i){var columnIndex = MatchFieldPairs[i].MatchColumnIndex;if (!dr.IsNull(columnIndex)){MatchFieldPairs[i].grField.Value = dr[columnIndex];}}Report.DetailGrid.Recordset.Post();}}/// u0026lt;summaryu0026gt;/// List加载数据集/// u0026lt;/summaryu0026gt;/// u0026lt;typeparam name="T"u0026gt;u0026lt;/typeparamu0026gt;/// u0026lt;param name="Report"u0026gt;报表对象u0026lt;/paramu0026gt;/// u0026lt;param name="list"u0026gt;列表数据u0026lt;/paramu0026gt;public static void FillRecordToReportu0026lt;Tu0026gt;(IGridppReport Report, Listu0026lt;Tu0026gt; list){Type type = typeof(T); //反射类型MatchFieldPairType[] MatchFieldPairs = new MatchFieldPairType[Math.Min(Report.DetailGrid.Recordset.Fields.Count, type.GetProperties().Length)];//根据字段名称与列名称进行匹配,建立字段与Grid++Report记录集的字段之间的对应关系int MatchFieldCount = 0;int i = 0;MemberInfo[] members = type.GetMembers();foreach (MemberInfo memberInfo in members){foreach (IGRField fld in Report.DetailGrid.Recordset.Fields){if (string.Compare(fld.Name, memberInfo.Name, true) == 0){MatchFieldPairs[MatchFieldCount].grField = fld;MatchFieldPairs[MatchFieldCount].MatchColumnIndex = i;++MatchFieldCount;break;}}++i;}// 将 DataTable 中的每一条记录转储到 Grid++Report 的数据集中去foreach (T t in list){Report.DetailGrid.Recordset.Append();for (i = 0; i u0026lt; MatchFieldCount; ++i){object objValue = GetPropertyValue(t, MatchFieldPairs[i].grField.Name);if (objValue != null){MatchFieldPairs[i].grField.Value = objValue;}}Report.DetailGrid.Recordset.Post();}}/// u0026lt;summaryu0026gt;/// 获取对象实例的属性值/// u0026lt;/summaryu0026gt;/// u0026lt;param name="obj"u0026gt;对象实例u0026lt;/paramu0026gt;/// u0026lt;param name="name"u0026gt;属性名称u0026lt;/paramu0026gt;/// u0026lt;returnsu0026gt;u0026lt;/returnsu0026gt;public static object GetPropertyValue(object obj, string name){//这个无法获取基类//PropertyInfo fieldInfo = obj.GetType().GetProperty(name, bf);//return fieldInfo.GetValue(obj, null);//下面方法可以获取基类属性object result = null;foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(obj)){if (prop.Name == name){result = prop.GetValue(obj);}}return result;}}

绑定数据的报表效果如下所示 :

如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

导出报表为PDF也是比较常规的操作,这个报表控件也可以实现PDF等格式文件的导出,如下所示。

private void btnExportPdf_Click(object sender, EventArgs e){Listu0026lt;ProductInfou0026gt; list = BLLFactoryu0026lt;Productu0026gt;.Instance.GetAll();//从对应文件中载入报表模板数据string reportPath = Path.Combine(Application.StartupPath, "ReportstestList.grf");GridExportHelper helper = new GridExportHelper(reportPath);string fileName = "d:my.pdf";var succeeded = helper.ExportPdf(list, fileName);if(succeeded){Process.Start(fileName);}}
如何在Visual Studio中创建Grid  报表「如何在图片上添加文字」

以上就是利用这个报表控件做的一些功能测试和辅助类封装,方便使用。

本文转载自:博客园 - 伍华聪

本文到此结束,希望对大家有所帮助。

标签:
收到0个赞
win7磁盘清理(win7磁盘清理会误删东西吗)

win7磁盘清理(win7磁盘清理会误删东西吗)

关于win7磁盘清理,这个很多人还不知道,
摩托罗拉me501(摩托罗拉me501有呼吸灯吗)

摩托罗拉me501(摩托罗拉me501有呼吸灯吗)

大家好,linda来为大家解答摩托罗拉me50
h3c路由器(h3c路由器手机设置)

h3c路由器(h3c路由器手机设置)

大家好,一只小美来为大家解答h3c路由器
华为手表pro(华为手表pro和gt哪个好)

华为手表pro(华为手表pro和gt哪个好)

大家好,linda来为大家解答华为手表pro以
aca烤箱使用说明书(aca烤箱使用说明)

aca烤箱使用说明书(aca烤箱使用说明)

大家好,一只小美来为大家解答aca烤箱使
支付宝邮箱注册教程(个人邮箱号怎么查)

支付宝邮箱注册教程(个人邮箱号怎么查)

大家好,linda来为大家解答支付宝邮箱注
三星白色翻盖手机型号(三星翻盖经典白色)

三星白色翻盖手机型号(三星翻盖经典白色)

关于三星白色翻盖手机型号,这个很多人
oppoa93s和oppoa93有什么区别(oppoa93和oppoa93s哪个更好)

oppoa93s和oppoa93有什么区别(oppoa93和oppoa93s哪个更好)

大家好,一只小美来为大家解答oppoa93s和
摩托罗拉c261手机自带游戏(摩托罗拉c261手机自带游戏)

摩托罗拉c261手机自带游戏(摩托罗拉c261手机自带游戏)

关于摩托罗拉c261手机自带游戏,这个很多
关于我们 | 版权声明 | 免责声明 | 联系我们
免责声明:知识网所有文字、图片、视频、音频等资料均来自互联网,不代表本站赞同其观点,内容仅代表作者本人意见,若因此产生任何纠纷作者本人负责,本站亦不为其版权负责! 如有问题,请联系我们
CopyRight©1999-2024 www.44jj.com All Right Reserved 豫ICP备16009659号