开发工具与关键技术:Visual Studio 2015 打印水晶报表
作者:孙水兵
撰写时间:2019年6月17
一、 前期工作
第一步:安装软件—CRforVS_13_0_14
第二步:新建一个打印水晶报表的文件夹用来放置一些打印水晶报表的文件
第三步:添加数据集:在上面新建的文件夹上右键—>添加----->新建项,然后选择数据集,将名称改成自己需要的。点击添加。然后在该数据集中右键—>添加—>若要打印的数据都在一个数据表中并且数据库中存在该表,选择第一个(TableAdapter(T)),若要打印的数据不在一个数据表中,选择第二个(DataTable(D))。若选择的是第二个,则先将表名改了,然后在右键表中添加列(也可以使用快捷键Ctrl+L)。注意添加完列之后要查看每一列的属性中的DataType是否与数据库中的一致。若不一致,将其更改成与数据库中一致的数据类型,否则会报错。
第四步:画对应的水晶报表模板:在打印水晶报表的文件夹上右键—>添加----->新建项,然后选择Reporting,选择Crystal Reports(只有安装的打印水晶报表的软件才会显示出来)。将名称改成自己需要的。点击添加。点击添加后会弹出一个窗口,选择作为空白报表即可。然后在最左侧的字段资源管理器中选择数据库字段。然后在数据库字段上右键——>数据库专家,在ADO.NET数据集中选择刚刚新建的数据集,双击。然后打开数据库字段,可以查看到刚刚添加的数据集,然后打开刚添加的数据集,使用里面的字段来设计水晶报表。
设计完后的形式
在设计时可以右键—>插入,选择需要插入的对象,如这里的驾驶员信息与前面一个打印日期是文本对象,后面一个打印日期为特殊字段中的打印日期。也可以选中一些对象右键—>设置对象格式,设置相对应的对象的格式,如字体大小,文本居中等等。也可以同时选中多个进行设置。在设置页眉和详细资料时,将数据集中的相对应的字段拖到详细资料阴影处,这样页眉和详细资料都有该字段了。然后再进行一些样式的设置。
二、 代码
HTML代码
HTML代码只需一个点击按钮并且设置一个点击事件即可。
JS代码
JS代码与多条件查询有些类似,先获取查询条件的值,然后在判断。这样是为了若不需全部打印,只需要打印一部分做准备。然后就是一个询问提示框,然后是页面跳转到指定的路径以及一些拼接的条件。
function printDriverInfo() {
var searchDrive = $("#searchDrive").val();
var searchPassengerCar = $("#searchPassengerCar").val();
if (searchDrive == undefined || searchDrive == null) {
searchDrive = "";
}
if (searchPassengerCar == undefined || searchPassengerCar == null) {
searchPassengerCar = "";
}
layer.confirm("确定要打印当前表格中的数据吗?是请点击确定,否则请先筛选数据再进行打印!", { icon: 3, title: "提示" }, function (index) {
layer.close(index);
window.open("/BusinessManagement/DriverMessage/printDriverInfo?searchDrive=" + searchDrive + "?searchPassengerCar=" + searchPassengerCar);
})
}
控制器代码
将IEnumerable类型的集合转换为DataTable类型
先定义一个要返回的DataTable对象:dtReturn和保存列集合的属性信息数组:oProps。然后对传过来的参数进行安全检查。循环遍历集合,使用反射获取T类型的属性信息。判断数组oProps 是否为空。然后获取到当前实例的type,并将type的公共属性返回给数组oProps。然后foreach循环数组oProps,然后得到属性的类型。判断属性是否为泛型类型,如果是,获取泛型类型的参数并将将类型的属性名称与属性类型作为DataTable的列数据。然后新建一个用于添加到DataTable中的DataRow对象。Foreach循环数组oProps,然后为DataRow中的指定列赋值,然后返回DataTable对象。
public DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
{
//定义要返回的DataTable对象
DataTable dtReturn = new DataTable();
//保存列集合的属性信息数组
PropertyInfo[] oProps = null;
if (varlist == null)
return dtReturn;//安全性检查
//循环遍历集合,使用反射获取类型的属性信息
foreach (T rec in varlist)
{
//使用反射获取T类型的属性信息,返回一个PropertyInfo类型的集合
#region
if (oProps == null)
{
oProps = ((Type)rec.GetType()).GetProperties();
//循环PropertyInfo数组
foreach (PropertyInfo pi in oProps)
{
//得到属性的类型
Type colType = pi.PropertyType;
//如果属性为泛型类型
if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
//获取泛型类型的参数
colType = colType.GetGenericArguments()[0];
}
//将类型的属性名称与属性类型作为DataTable的列数据
dtReturn.Columns.Add(pi.Name, colType);
}
}
#endregion
//新建一个用于添加到DataTable中的DataRow对象
DataRow dr = dtReturn.NewRow();
//循环遍历属性集合
foreach (PropertyInfo pi in oProps)
{
//为DataRow中的指定列赋值
dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue(rec, null);
}
//将具有结果值的DataRow添加到DataTable集合中
dtReturn.Rows.Add(dr);
}
return dtReturn;//返回DataTable对象
}
打印水晶报表
在打印水晶报表的方法的最前面是查询或者多条件查询。再完成查询之后,将查询出来的结果转化为DataTable格式并用dtResult接收,然后实例化数据集。将dtResult放入数据集中名为DriverInfo的表格中(之前新建的数据集和表格)。然后实例化数据报表。获取打印文件的物理路径(即刚才报表模板的文件的路径)。然后将报表加载到报表模板中。然后设置报表的数据源,将报表化为文件流输出,并返回。
//将查询出来的结果转化为DataTable格式
DataTable dtResult = LINQToDataTable(SelectDriverAllInfo);
//实例化数据集
printReport.DriverData dbReport = new printReport.DriverData();
//将dbRedult放入数据集中名为"DriverInfo"的表格中
dbReport.Tables["DriverInfo"].Merge(dtResult);
//实例化数据报表
printReport.PrintDriver rp = new printReport.PrintDriver();
//获取文件物理路径
string strRpPath = Server.MapPath("~/") + "printReport\\printDriverReport.rpt";
//将报表加载到报表模板中
rp.Load(strRpPath);
//设置报表的数据源
rp.SetDataSource(dbReport);
//将报表转化为文件流输出
Stream dbStream = rp.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);
//返回
return File(dbStream, "application/pdf");