《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 嵌入式技術(shù) > 設(shè)計(jì)應(yīng)用 > 利用水晶報(bào)表動(dòng)態(tài)綁定數(shù)據(jù)源實(shí)現(xiàn)動(dòng)態(tài)交叉表的方法研究
利用水晶報(bào)表動(dòng)態(tài)綁定數(shù)據(jù)源實(shí)現(xiàn)動(dòng)態(tài)交叉表的方法研究
2015年微型機(jī)與應(yīng)用第10期
劉 輝1,常婉綸1,劉豫凡2
(1.西安理工大學(xué),陜西 西安 710082; 2.西北工業(yè)大學(xué) 機(jī)電學(xué)院 陜西 西安 710072)
摘要: 為減少數(shù)據(jù)冗余,根據(jù)規(guī)范化理論設(shè)計(jì)的數(shù)據(jù)庫不能直接輸出分類匯總的結(jié)果,需要進(jìn)行轉(zhuǎn)換生成交叉表,并利用水晶報(bào)表的Push模式實(shí)現(xiàn)對(duì)交叉表的顯示。在.NET和SQL Server環(huán)境下,探討了動(dòng)態(tài)交叉表的生成和利用水晶報(bào)表動(dòng)態(tài)綁定數(shù)據(jù)源顯示數(shù)據(jù)的方法,并給出了較為詳細(xì)的實(shí)現(xiàn)過程。
Abstract:
Key words :

  摘  要: 為減少數(shù)據(jù)冗余,根據(jù)規(guī)范化理論設(shè)計(jì)的數(shù)據(jù)庫不能直接輸出分類匯總的結(jié)果,需要進(jìn)行轉(zhuǎn)換生成交叉表,并利用水晶報(bào)表Push模式實(shí)現(xiàn)對(duì)交叉表的顯示。在.NET和SQL Server環(huán)境下,探討了動(dòng)態(tài)交叉表的生成和利用水晶報(bào)表動(dòng)態(tài)綁定數(shù)據(jù)源顯示數(shù)據(jù)的方法,并給出了較為詳細(xì)的實(shí)現(xiàn)過程。

  關(guān)鍵詞: 動(dòng)態(tài)交叉表;水晶報(bào)表;Push模式;動(dòng)態(tài)綁定

0 引言

  信息系統(tǒng)中都不能缺少報(bào)表,而交叉表是種常見的報(bào)表形式,它將源表中的數(shù)據(jù)分組匯總后,一組列在表的左側(cè),另一組列在表的上部,從而形成一種分類匯總表格[1]。動(dòng)態(tài)交叉表是按用戶呈現(xiàn)數(shù)據(jù)的要求,不僅對(duì)數(shù)據(jù)進(jìn)行分類,同時(shí)還要根據(jù)表中數(shù)據(jù)的情況動(dòng)態(tài)創(chuàng)建列,把數(shù)據(jù)行信息置換到表格列處并進(jìn)行匯總。

  水晶報(bào)表是一款商務(wù)智能軟件,主要用于設(shè)計(jì)產(chǎn)生報(bào)表,是業(yè)內(nèi)功能最強(qiáng)的報(bào)表系統(tǒng)[2],其出現(xiàn)的目的就是使計(jì)算機(jī)參與到辦公系統(tǒng)業(yè)務(wù)流程中。

1 問題的提出

  以我校學(xué)生成績(jī)管理系統(tǒng)為例,為消除存儲(chǔ)異常,減少數(shù)據(jù)冗余,保證數(shù)據(jù)的完整性,按規(guī)范化設(shè)計(jì)理論設(shè)計(jì)的數(shù)據(jù)庫含多張表,其中與成績(jī)有關(guān)的3個(gè)表的關(guān)系模式學(xué)生信息表S(學(xué)號(hào)、姓名、性別、班號(hào))、課程信息表C(課號(hào)、課名)、學(xué)生成績(jī)表SC(學(xué)號(hào)、課號(hào)、學(xué)期、成績(jī))之間的關(guān)系圖如圖1所示。學(xué)生成績(jī)表中的數(shù)據(jù)形式如圖2所示。實(shí)際工作中需要打印的學(xué)生成績(jī)表如圖3所示。

  由此可見,數(shù)據(jù)庫中存儲(chǔ)的數(shù)據(jù),在某些應(yīng)用中,需要生成動(dòng)態(tài)交叉表,因不同班級(jí)不同學(xué)期學(xué)生學(xué)習(xí)的課程不一樣,生成的動(dòng)態(tài)交叉表的列項(xiàng)的個(gè)數(shù)和名稱都是不固定的。經(jīng)驗(yàn)表明,水晶報(bào)表雖然功能強(qiáng)大且使用方便,但它要求設(shè)計(jì)表格時(shí)所使用的表名以及列名與使用時(shí)必須一致。本文研究了水晶報(bào)表的Pull模式和Push模式[3],提出了在數(shù)據(jù)庫端生成一個(gè)表格列項(xiàng)固定的動(dòng)態(tài)交叉表,利用Push模式動(dòng)態(tài)綁定數(shù)據(jù)源把數(shù)據(jù)推送給水晶報(bào)表引擎的方法。

2 生成動(dòng)態(tài)交叉表

  首先在數(shù)據(jù)庫服務(wù)器端完成列項(xiàng)名稱與個(gè)數(shù)固定的動(dòng)態(tài)交叉表的生成。設(shè)每學(xué)期最多有8門課,實(shí)現(xiàn)方法如下:

  (1)創(chuàng)建函數(shù)ufGetCourse,功能是篩選出某班對(duì)應(yīng)學(xué)期的課程,并按順序編號(hào)。運(yùn)行結(jié)果如圖4所示。

003.jpg

  create function ufGetCourse(@bno int,@tnum int)returns table

  as return

  (

  select col=count(*),tc1.cno,cname

  from(select distinct cno from s join sc on s.sno=sc.sno where bno=@bno and tnum=@tnum)as tc1

  join(select distinct cno from s join sc on s.sno=sc.sno where bno=@bno and tnum=@tnum)as tc2

  on tc1.cno>=tc2.cno

  join c on tc1.cno=c.cno

  group by tc1.cno,cname

 ?。?/p>

  (2)創(chuàng)建存儲(chǔ)過程upCreateJCB,功能是按學(xué)號(hào)對(duì)應(yīng),把順序編號(hào)為1的4號(hào)課程成績(jī)放在Cj1列中,把順序編號(hào)為2的5號(hào)課程成績(jī)放在Cj2列中,以此類推,最后計(jì)算每個(gè)學(xué)生的總評(píng)分。運(yùn)行結(jié)果如圖5所示。

004.jpg

  create proc upCreateJCB

  @bno int,@tnum int

  as

  declare @str varchar(100),@cstu varchar(100),@cno int,@sno char(10),@sname varchar(50),@sc int,@col int,@ZF int

  create table #t

 ?。?/p>

  sno char(10),sname varchar(50),ZF decimal(5,1),

  cj1 int,cj2 int,cj3 int,cj4 int,cj5 int,cj6 int,cj7 int,cj8 int

  )

  declare my_C cursor for select s.sno,sname,col,sc.cno,Score from S join SC on s.sno=sc.sno join(select*from dbo.ufGetCourse(@bno,@tnum))as c on sc.cno=c.cno where bno=@bno and tnum=@tnum order by sno

  open my_C

  fetch next from my_C into@sno,@sname,@col,@cno,@sc

  while @@fetch_status=0

  begin

  select@cstu=@sno,@ZF=0

  insert into#t(sno,sname)values(@sno,@sname)

  while@@fetch_status=0 and@cstu=@sno

  begin

  set@str=′update#t set cj′+cast(@col as varchar(2))+′=′′′+cast(@sc as varchar(3))+′′′′

  set@str=@str+′where sno=′+@sno

  exec(@str)

  set@ZF=@ZF+@sc

  fetch next from my_C into@sno,@sname,@col,@cno,@sc

  end

  --更新總評(píng)分

  update #t set ZF=@ZF where sno=@cstu

  end

  select*from#t

  drop table#t

  close my_C

  deallocate my_C

3 水晶報(bào)表動(dòng)態(tài)綁定數(shù)據(jù)源

  應(yīng)用程序的前臺(tái)界面在.NET平臺(tái)下進(jìn)行水晶報(bào)表設(shè)計(jì),采用Push模式在程序中動(dòng)態(tài)加載數(shù)據(jù)源和報(bào)表,用動(dòng)態(tài)傳參方式把表頭的cj1~cj8更換成對(duì)應(yīng)的中文課程名,方法如下:

  (1)建立解決方案。在解決方案資源管理器中添加“Crystal報(bào)表”模板。方法為:添加→新建項(xiàng)→Crystal報(bào)表→命名報(bào)表為MyCry.rpt→作為空白報(bào)表。

  (2)在字段資源管理器中通過“報(bào)表專家”完成報(bào)表設(shè)計(jì)。方法為:數(shù)據(jù)庫字段→數(shù)據(jù)庫專家→創(chuàng)建新鏈接→OLE DB(ADO)→Microsoft OLE DB Provider for SQL Server→填寫鏈接數(shù)據(jù)庫的信息→選擇對(duì)應(yīng)的數(shù)據(jù)庫→選擇存儲(chǔ)過程upCreateJCB→把涉及的字段拖拽到水晶報(bào)表細(xì)節(jié)欄中并填上表格線。

 ?。?)在字段資源管理器中添加參數(shù)字段:班級(jí)名classname、學(xué)期TermNo、Cj1~Cj8,并把這些參數(shù)字段拖拽到水晶報(bào)表的頁眉欄處。

  經(jīng)過上述過程設(shè)計(jì)的報(bào)表MyCry.rpt如圖6所示。

005.jpg

 ?。?)在窗體上放一個(gè)CrystalReportViewer控件并命名為crv,用C#編程動(dòng)態(tài)加載數(shù)據(jù)源和報(bào)表。代碼如下:

  //程序開始處需對(duì)兩個(gè)名字空間進(jìn)行引用

  using CrystalDecisions.Shared;

  using CrystalDecisions.CrystalReports.Engine;

  //Load事件下執(zhí)行的代碼

  int num,bj=197,xq=1;//197為班級(jí)號(hào),1為第1學(xué)期

  SqlConnection con=new SqlConnection();

  con.ConnectionString="Data Source=.;Initial Catalog=Student_Score;Integrated Security=True";

  con.Open();

  string strSql="exec upCreateJCB"+bj.ToString()+","+xq.ToString();

  SqlDataAdapter da=new SqlDataAdapter(strSql,con);

  DataTable d1=new DataTable();

  da.Fill(d1);

  MyCry ocr=new MyCry();

  ocr.Load("MyCry");

  ocr.SetDataSource(d1);

  //向水晶報(bào)表中傳參數(shù)

  ParameterFields_ps=new ParameterFields();

  //TermNo參數(shù)

  ParameterField_p=new ParameterField();

  ParameterDiscreteValue_v=new ParameterDiscreteValue();

  _p.ParameterFieldName="TermNo";

  _v.Value=xq;

  _p.CurrentValues.Add(_v);

  _ps.Add(_p);

  //ClassName參數(shù)

  _p=new ParameterField();

  _v=new ParameterDiscreteValue();

  _p.ParameterFieldName="ClassName";

  _v.Value=bj;//此處可先從班級(jí)表中讀取班級(jí)名然后傳遞班級(jí)名,本例略

  _p.CurrentValues.Add(_v);

  _ps.Add(_p);

  //n個(gè)課程名稱參數(shù)

  strSql="select*from dbo.ufGetCourse("+bj.ToString()+","+xq.ToString()+")";

  SqlDataAdapter db=new SqlDataAdapter(strSql,con);

  DataTable d2=new DataTable();

  db.Fill(d2);

  for(num=1;num<=d2.Rows.Count;num++)

  {

  _p=new ParameterField();

  _v=new ParameterDiscreteValue();

  _p.ParameterFieldName="cj"+num.ToString();

  _v.Value=d2.Rows[num-1][2].ToString();

  _p.CurrentValues.Add(_v);

  _ps.Add(_p);

  }

  //報(bào)表中共有8列,不足8列時(shí)后面內(nèi)容填空

  for(;num<=8;num++)

  {

  _p=new ParameterField();

  _v=new ParameterDiscreteValue();

  _p.ParameterFieldName="cj"+num.ToString();

  _v.Value="";

  _p.CurrentValues.Add(_v);

  _ps.Add(_p);

  }

  crv.ParameterFieldInfo=_ps;

  crv.ReportSource=ocr;

4 結(jié)論

  本文提出了利用水晶報(bào)表顯示并打印動(dòng)態(tài)交叉表的一種方法,圖3就是本校學(xué)籍管理系統(tǒng)中用本方法打印的成績(jī)匯總表,由于來源于真實(shí)數(shù)據(jù),故姓名處進(jìn)行了處理。

參考文獻(xiàn)

  [1] 張賢斌,費(fèi)樹岷.管理信息系統(tǒng)中動(dòng)態(tài)交叉表的實(shí)現(xiàn)方式研究[J].計(jì)算機(jī)應(yīng)用工程技術(shù),2008,4(4):995-996.

  [2] 叢鳳俠,楊玉強(qiáng).通用水晶報(bào)表自動(dòng)生成技術(shù)研究[J].計(jì)算機(jī)技術(shù)與發(fā)展,2013,23(5):54-57.

  [3] 錢哨,李揮劍,李繼哲,等.C#WinForm實(shí)踐開發(fā)教程[M].北京:中國(guó)水利水電出版社,2010.


此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載。