时间:2022-10-23 04:03:38
摘 要:水晶报表是一个功能强大的报表工具,现在已经被Microsoft Visual Studio 2005集成在一起,如何能动态地将多表以交叉表的方式实现是一种相当关键的技术难点,本文从完成“阳易教学分析系统V1.0-成绩交叉分析”模块来向读者做一个详细的介绍。
关键词:水晶报表 动态 交叉表
一、引言
几乎在所有的应用程序中报表都是程序员头疼的问题。在.Net环境下包含了功能强大的报表工具:水晶报表(Crystal Report)。
Crystal Reports通过数据库驱动程序与数据库连接。每个驱动程序都被编写为可处理特定数据库类型或数据库访问技术。为了向开发人员提供最灵活的数据访问方法,Crystal Reports 数据库驱动程序被设计为可同时提供数据访问的拉模型和推模型。
拉模型
在拉模型中,驱动程序将连接到数据库并根据需要将数据“拉”进来(见图1)。使用这种模型时,与数据库的连接和为了获取数据而执行的SQL命令都同时由Crystal Reports本身处理,不需要开发人员编写代码。如果在运行时无须编写任何特殊代码,则使用拉模型。
推模型
相反,推模型需要开发人员编写代码以连接到数据库,执行SQL命令以创建与报表中的字段匹配的记录集或数据集,并且将该对象传递给报表(见图2)。该方法使您可以将连接共享置入应用程序中,并在Crystal Reports收到数据之前先将数据筛选出来。
本文为了实现动态按条件生成报表的,因此主要采用推模型。
交叉表是一种非常常见的报表形式。一般的二维表只有列头,行就是数据,而交叉表(Cross Table)是行和列都有相应的行头和列头,中间的格子是交叉汇总项。原来的数据标题(字段)在两列上,但是现在想给其中一个列放到水平方向,形成行列交叉,交叉点求出统计结果,得出直接在表中不能看出的分析数据。交叉表查询显示来源于表中某个字段的总结值(合计、计算以及平均值等),并将它们分组放置在查询表中,一组列在数据表的左侧,一组列在数据表的上部。
本文将从完成“阳易教学分析系统V1.0-成绩交叉分析”模块来向读者做一个详细地介绍。
二、系统模块的设计
1. 数据库表的建立
系统已经有一个数据库:YangYiDB,包括三张表:课程、成绩、学生。各表之间的关系图见图3。
2.系统模块的实现
第一步、启动VS2005,新建一个架构文件。
a.在解决方案资源管理器中,右击项目名,指向“添加”,然后单击“添加新项”。
b.在“添加新项”对话框的“类别”区域,展开文件夹,然后选择“数据”。
c.在“模板”区域选择“数据集”。
d.修改默认名称 DataSetCross.xsd。
这就创建了一个新的架构文件(DataSetCross.xsd),以后将用它来生成强类型数据集。该架构文件将显示在数据集设计器中。
e.从“工具箱”中拖放一个DataTable,放入DataSetCross.xsd中,创建几个字段:名字、课程名、成绩(见图4)。
第二步、新建一个创建新报表。
a.指向“添加”,单击“添加新项”。
b.在“添加新项”对话框中,从“模板”区域选择Crystal Report,将报表命名为CrystalReport006,同时根据前面的数据集DataSetCross.xsd设计交叉表(如图5)。
第三步、新建窗体文件,命名为“Form012”。
a.拖放控件tableLayoutPanel1、groupBox2、checkBox3、checkBox2、checkBox1、button1、crystalReportViewer1、statusStrip1,布局和设置如图6所示。
第四步、代码实现。
a.在Form012类前面添加语句
using System.Data.OleDb;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared。
b.给Form012类添加类字段
tempDataView:
private DataView tempDataView; //
c.自定义私有方法myDataView(),实现连接数据库,读取前面所提的三张表的名字、课程名、成绩字段,返回一个内存中的数据视图,代码如下:
private DataView myDataView( )
{
DataSet tempDataSet = new DataSet( );
string connString = ″Provider=SQLOLEDB;Data Source=.;User ID=sa;Initial Catalog=Test″;
OleDbConnection myOleDbConnection = new OleDbConnection(connString);
string sqlString = ″select 名字,课程名,成绩 from 学生,课程,成绩 where 学生.学号=成绩.学号and课程.课程号=成绩.课程号″;
OleDbDataAdapter myOleDbDataAdapter = new OleDbDataAdapter(sqlString, myOleDbConnection);
myOleDbDataAdapter.Fill(tempDataSet, ″学生课程成绩″);
return tempDataSet.Tables[″学生课程成绩″].DefaultView;
}
d.在Form012_Load事件中添加tempDataView=myDataView();来调用上述方法。
e.双击“输出报表”按钮,在button1_Click事件中加入如下代码:
CrystalReport006 myCrystalReport006 = new CrystalReport006( );
DataSetCross myDataSetCross = new DataSetCross( );
//产生动态条件,存入字符ChooseStr中
string ChooseStr = ″″;
if (checkBox1.Checked) ChooseStr = ChooseStr + ″课程名=’″ + checkBox1.Text + ″’″;
if (checkBox2.Checked) ChooseStr = ChooseStr + ″ or ″ + ″课程名=’″ + checkBox2.Text + ″’″;
if (checkBox3.Checked) ChooseStr = ChooseStr + ″ or ″ + ″课程名=’″ + checkBox3.Text + ″’″;
if (ChooseStr == ″″)
{ MessageBox.Show(″请选择要显示的字段″); return; }
if (ChooseStr.Substring(0, 4) == ″ or ″)
ChooseStr = ChooseStr.Substring (4, ChooseStr.Length - 4);
//产生视图tempDataView,对应存入架构文件myDataSetCross中
tempDataView.RowFilter = ChooseStr;
foreach (DataRowView drw in tempDataView)
{
DataRow dr = myDataSetCross.Tables[″DataTableCross″].NewRow();
dr = drw[″名字″]; dr = drw[″课程名″]; dr = drw[″成绩″];
myDataSetCross.Tables[″DataTableCross″].Rows.Add(dr);
}
//刷新crystalReportViewer1,并将crystalReportViewer1显示出新的数据集结果
crystalReportViewer1.Refresh();
myCrystalReport006.SetDataSource(myDataSetCross.Tables[″DataTableCross″]);
crystalReportViewer1.ReportSource = myCrystalReport006;
第五步、程序运行,查看结果。
a.任意选择各种课程;
b.点击“输出报表”按钮;
c.重复a和b,可以看到有不同的交叉表输出。
结束语
用C#实现动态地水晶报表交叉表的实现方式,在许多项目中都将会用到,掌握其中的细节将会对软件开发者带来很大的帮助。
参考文献:
[1].NET环境下水晶报表使用总结