明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

ASP.NET中使用Crystal Report創(chuàng)建圖表

[摘要]在很多的應(yīng)用程序中,報(bào)表是不可缺少的,一張好的報(bào)表能直觀地讓人把握數(shù)據(jù)的情況,方便決策。在這篇文章中,我們將以一個(gè)三層結(jié)構(gòu)的asp.net程序?yàn)槔,介紹如何使用crystal report ,來(lái)制作一份報(bào)表,其中介紹了不少asp.net和水晶報(bào)表的技巧。  在這個(gè)例子中,我們?cè)O(shè)想的應(yīng)用要為一個(gè)銷售...

  在很多的應(yīng)用程序中,報(bào)表是不可缺少的,一張好的報(bào)表能直觀地讓人把握數(shù)據(jù)的情況,方便決策。在這篇文章中,我們將以一個(gè)三層結(jié)構(gòu)的asp.net程序?yàn)槔榻B如何使用crystal report ,來(lái)制作一份報(bào)表,其中介紹了不少asp.net和水晶報(bào)表的技巧。

  在這個(gè)例子中,我們?cè)O(shè)想的應(yīng)用要為一個(gè)銷售部門制作一份報(bào)表,管理者可以查看某段時(shí)間之內(nèi)的銷售情況,以列表或者折線圖的形式反映出銷售的趨勢(shì)。我們將使用SQL Server 2000做為數(shù)據(jù)庫(kù),使用VB.NET編寫中間層邏輯層,而前端的表示層使用C#。我們先來(lái)看下數(shù)據(jù)庫(kù)的結(jié)構(gòu)。

 
  其中,tbitem表中存放的是每張訂單中所訂購(gòu)的貨品,tbsales存放的是每張訂單,tblsalesperson是銷售員表,存放該出版社的每位銷售員。

  接下來(lái),使用SQL Server 2000來(lái)創(chuàng)建這些表。表的結(jié)構(gòu)如下所示:

CREATE TABLE [dbo].[tblItem] (
[ItemId] [int] NOT NULL ,
[Description] [varchar] (50) NOT NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[tblSalesPerson] (
[SalesPersonId] [int] NOT NULL ,
[UserName] [varchar] (50) NOT NULL ,
[Password] [varchar] (30) NOT NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[tblSales] (
[SaleId] [int] IDENTITY (1, 1) NOT NULL ,
[SalesPersonId] [int] NOT NULL ,
[ItemId] [int] NOT NULL ,
[SaleDate] [datetime] NOT NULL ,
[Amount] [int] NOT NULL
) ON [PRIMARY]

  并且用以下的代碼創(chuàng)建表之間的約束關(guān)系。

ALTER TABLE tblItem
ADD CONSTRAINT PK_ItemId
PRIMARY KEY (ItemId)
GO
ALTER TABLE tblSalesPerson
ADD CONSTRAINT PK_SalesPersonId
PRIMARY KEY (SalesPersonId)
GO
ALTER TABLE tblSales
ADD CONSTRAINT FK_ItemId
FOREIGN KEY (ItemId) REFERENCES tblItem(ItemId)
GO
ALTER TABLE tblSales
ADD CONSTRAINT FK_SalesPersonId
FOREIGN KEY (SalesPersonId) REFERENCES tblSalesPerson(SalesPersonId)
GO
 
  創(chuàng)建中間邏輯層

  在中間邏輯層組件中,我們?yōu)槊恳粡埍矶紕?chuàng)建兩個(gè)類。比如,對(duì)于tblItems表,創(chuàng)建item 和items類。Item類中記錄每件銷售的貨品的詳細(xì)情況,而items表則記錄所有銷售的貨品并且有增加貨品的方法。這樣,就存在下面的六個(gè)類:

  Item and Items
  SalesPerson and SalesPersons
  Sale and Sales

  接下來(lái),看一下每個(gè)類中的屬性:

  Item類

   包括如下屬性
    ItemId (貨品id編號(hào))
    Description (貨品的描述)
    Items

  有一個(gè)方法,將根據(jù)item的編號(hào)返回一個(gè)item對(duì)象

Public Function GetAllItems () As Collections.ArrayList

  SalesPerson

  該類有以下三個(gè)屬性:

   SalesPersonId (銷售員編號(hào))
   Name (姓名)
   Password (密碼)

  SalesPersons

  有一個(gè)方法,根據(jù)銷售員登陸時(shí)輸入的用戶名和密碼,在數(shù)據(jù)庫(kù)中,驗(yàn)證銷售員的登陸是否正確,如果正確,則返回零。

Public Function ValidateUser (strUserName as String, strPassword as String) As Integer

  Sale

  有如下5個(gè)屬性

  · SaleId
  · SalesPersonId
  · ItemId
  · SaleDate
  · Amount

  Sales

  有兩個(gè)方法,其中g(shù)etsales根據(jù)輸入的參數(shù)返回sales對(duì)象的集合

Public Function GetSales (Optional nSaleId As Integer = 0, Optional nSalesPersonId As Integer = 0,Optional nItemId As Integer = 0) As Collections.ArrayList

  還有一個(gè)addsales方法,用于增加一張訂單

Public Function AddSale (objSale As Sale)
  創(chuàng)建表現(xiàn)層頁(yè)面

  接下來(lái),開始創(chuàng)建表現(xiàn)層頁(yè)面。首先,要?jiǎng)?chuàng)建一個(gè)可以給銷售員登陸的頁(yè)面,如下圖所示。



  在銷售員成功登陸后,可以給銷售員輸入某樣貨品銷售的數(shù)量,如下圖:



  此外,為了給業(yè)務(wù)主管看到某個(gè)時(shí)期的銷售情況,創(chuàng)建如下頁(yè)面。



  其中,業(yè)務(wù)主管可以選擇查看某樣貨品在某個(gè)時(shí)期(選擇開始日期,結(jié)束日期)的銷售情況,以圖表方式顯示。

  這里特別值得一提的是,日歷控件的使用。在頁(yè)面中放置日歷控件后,設(shè)置如下代碼:

<input type="image" onclick="Page_ValidationActive=false;" src="http://www.okasp.com/techinfo/datepicker.gif" alt="Show Calender" runat="server" onserverclick="ShowCal1" id="ImgCal1" name="ImgCal1">

  這里設(shè)置page_validationactive參數(shù)為false,所以不需要重新提交頁(yè)面,并且,在onserverclick事件中,設(shè)置處理的代碼,如下所示:

public void ShowCal1(Object sender, System.Web.UI.ImageClickEventArgs e)
{ //顯示日歷控件
DtPicker1.Visible = true;
}

  當(dāng)用戶選擇了相關(guān)的日期后,在文本框中可以獲得相關(guān)的日期:

private void DtPicker1_SelectionChanged(object sender, System.EventArgs e)
{
txtStartDate.Text = DtPicker1.SelectedDate.ToShortDateString();
DtPicker1.Visible = false;
}

  在提交的頁(yè)面中,處理的代碼如下:

private void bSubmit_ServerClick(object sender, System.EventArgs e)
{
Response.Redirect("ViewReport.aspx?ItemId=" + cboItemType.SelectedItem.Value + "&StartDate=" + txtStartDate.Text + "&EndDate=" + txtEndDate.Text);}

  在提交頁(yè)面后,將跳轉(zhuǎn)到瀏覽報(bào)表的頁(yè)面viewreport.aspx,傳入相關(guān)的參數(shù),如貨品ID,開始和結(jié)束日期。
  用水晶報(bào)表創(chuàng)建報(bào)表

  首先,往窗體中添加水晶報(bào)表控件,之后,就可以用水晶報(bào)表的報(bào)表設(shè)計(jì)器設(shè)計(jì)一份報(bào)表了。新建一個(gè)水晶報(bào)表文件類型,命名為itemreport.rpt,接著使用報(bào)表設(shè)計(jì)專家,并選擇設(shè)計(jì)標(biāo)準(zhǔn)型的報(bào)表,點(diǎn)下一步,出現(xiàn)如下畫面:


  我們選擇使用ADO類型的數(shù)據(jù),在彈出的窗口中,設(shè)置好sql server的登陸名,登陸密碼,選擇好數(shù)據(jù)庫(kù)后,選擇在報(bào)表中使用tblsales表,如下圖:


  接著選Next,在要在報(bào)表中顯示的字段中,選擇SaleDate和Amount。之后,一直選NEXT,忽略其他相關(guān)設(shè)置,最后,在圖表類型中選擇折線圖,如下圖:


  最后點(diǎn)擊finish,可以看到如下的報(bào)表:


  再次選擇報(bào)表專家,在彈出的窗口中選擇數(shù)據(jù)頁(yè),在數(shù)據(jù)可用字段中選擇salesdate,并且可以在文本頁(yè)中,設(shè)置適當(dāng)?shù)膱?bào)表標(biāo)題。


  由于要根據(jù)輸入的日期,貨品參數(shù)來(lái)動(dòng)態(tài)顯示報(bào)表,因此我們要設(shè)置參數(shù)字段。在報(bào)表設(shè)計(jì)器中,在字段資源管理器中,選擇參數(shù)字段,鼠標(biāo)右擊選擇“新建”,新建如下三個(gè)參數(shù)字段。

名稱: 類型:
ItemIdNumber
StartDateDate
EndDateDate
  
  最后,要設(shè)置相關(guān)的查詢公式,在除報(bào)表頁(yè)眉的區(qū)域,鼠標(biāo)右鍵點(diǎn)擊,在彈出菜單中選擇“報(bào)表 編輯選擇公式 記錄”,輸入如下的公式:


  在上面的公式編輯器中,分為左中右三部分,左邊的是報(bào)表的字段,中間的是相關(guān)的功能函數(shù),最右邊的是運(yùn)算符,雙擊其中選中的部分,則可以添加到下部的公式顯示區(qū)域中。最后,保存建立的公式。
  在程序中使用報(bào)表

  接下來(lái),我們可以在程序中用代碼處理和報(bào)表的連接過(guò)程。首先,在工程項(xiàng)目中,增加如下的兩個(gè)命名空間的引用(注意,在代碼中也必須用using引入它們):

CrystalDecisions.CrystalReports.Engine
CrystalDecisions.Shared
在viewreport.aspx的Page_load事件中,加入以下代碼

//接收傳遞的參數(shù)
nItemId = int.Parse(Request.QueryString.Get("ItemId"));
strStartDate = Request.QueryString.Get("StartDate");
strEndDate = Request.QueryString.Get("EndDate");
//聲明報(bào)表的數(shù)據(jù)對(duì)象
CrystalDecisions.CrystalReports.Engine.Database crDatabase; CrystalDecisions.CrystalReports.Engine.Table crTable;
TableLogOnInfo dbConn = new TableLogOnInfo();
// 創(chuàng)建報(bào)表對(duì)象opt
ReportDocument oRpt = new ReportDocument();
// 加載已經(jīng)做好的報(bào)表
oRpt.Load("F:\\aspnet\\WroxWeb\\ItemReport.rpt");
//連接數(shù)據(jù)庫(kù),獲得相關(guān)的登陸信息
crDatabase = oRpt.Database;
//定義一個(gè)arrtables對(duì)象數(shù)組
object[] arrTables = new object[1];
crDatabase.Tables.CopyTo(arrTables, 0);
crTable = (CrystalDecisions.CrystalReports.Engine.Table)arrTables[0]; dbConn = crTable.LogOnInfo;
//設(shè)置相關(guān)的登陸數(shù)據(jù)庫(kù)的信息
dbConn.ConnectionInfo.DatabaseName = "WroxSellers"; dbConn.ConnectionInfo.ServerName = "localhost";
dbConn.ConnectionInfo.UserID = "sa";
dbConn.ConnectionInfo.Password = "test";
//將登陸的信息應(yīng)用于crtable表對(duì)象
crTable.ApplyLogOnInfo(dbConn);
//將報(bào)表和報(bào)表瀏覽控件綁定
crViewer.ReportSource = oRpt;
//傳遞參數(shù)
setReportParameters();

  在上面的代碼中,首先接收了日期,貨品編號(hào)等參數(shù),并實(shí)例化了Database, Table和 TableLogOnInfo 三個(gè)類,它們是用來(lái)在運(yùn)行時(shí),建立報(bào)表和數(shù)據(jù)庫(kù)的連接必需的。再使用

oRpt.Load("F:\\aspnet\\WroxWeb\\ItemReport.rpt");

  來(lái)裝載已經(jīng)做好了的報(bào)表。

  在裝載完報(bào)表后,將數(shù)據(jù)庫(kù)中要使用的表復(fù)制到一個(gè)對(duì)象數(shù)組中去,并選擇對(duì)象數(shù)組中的第一個(gè)表元素,將其轉(zhuǎn)換為水晶報(bào)表的報(bào)表對(duì)象。接著,再設(shè)置LOGONINFO中的登陸數(shù)據(jù)庫(kù)的信息。最后,將報(bào)表源與報(bào)表瀏覽控件綁定。

  傳遞參數(shù)到水晶報(bào)表

  定義一個(gè)新的過(guò)程,setReportParameters(),代碼如下:

private void setReportParameters()
{
// all the parameter fields will be added to this collection
ParameterFields paramFields = new ParameterFields();
// the parameter fields to be sent to the report
ParameterField pfItemId = new ParameterField();
ParameterField pfStartDate = new ParameterField();
ParameterField pfEndDate = new ParameterField();
// 設(shè)置在報(bào)表中,將要接受的參數(shù)字段的名稱
pfItemId.ParameterFieldName = "ItemId";
pfStartDate.ParameterFieldName = "StartDate";
pfEndDate.ParameterFieldName = "EndDate";
ParameterDiscreteValue dcItemId = new ParameterDiscreteValue();
ParameterDiscreteValue dcStartDate = new ParameterDiscreteValue(); ParameterDiscreteValue dcEndDate = new ParameterDiscreteValue();

dcItemId.Value = nItemId;
dcStartDate.Value = DateTime.Parse(strStartDate);
dcEndDate.Value = DateTime.Parse(strEndDate);

pfItemId.CurrentValues.Add(dcItemId);
pfStartDate.CurrentValues.Add(dcStartDate); pfEndDate.CurrentValues.Add(dcEndDate);
paramFields.Add(pfItemId);
paramFields.Add(pfStartDate);
paramFields.Add(pfEndDate);

// 將參數(shù)集合綁定到報(bào)表瀏覽控件
crViewer.ParameterFieldInfo = paramFields;
}

  現(xiàn)在來(lái)解釋一下上面的代碼。在水晶報(bào)表中,瀏覽器控件有一個(gè)屬性parameterfieldsinfo,該屬性可以通過(guò)綁定parameterfields類型的集合,將相關(guān)的參數(shù)的實(shí)際數(shù)值傳遞到報(bào)表。Parameterfields類型集合通過(guò)add的方法,接收Parameterfield類型的對(duì)象。因此,我們先為itemid,startdate,enddate三個(gè)參數(shù)創(chuàng)建parameterfield類型的對(duì)象,并且設(shè)置它們對(duì)應(yīng)報(bào)表中接受參數(shù)的名稱:

ParameterFields paramFields = new ParameterFields();
ParameterField pfItemId = new ParameterField();
ParameterField pfStartDate = new ParameterField();
ParameterField pfEndDate = new ParameterField();
// 設(shè)置在報(bào)表中,將要接受的參數(shù)字段的名稱
pfItemId.ParameterFieldName = "ItemId";
pfStartDate.ParameterFieldName = "StartDate";
pfEndDate.ParameterFieldName = "EndDate";

  接著,可以為這些參數(shù)字段設(shè)置具體的值了,但由于parameterfield必須接受P arameterDiscreteValue類型的對(duì)象,所以,再創(chuàng)建相關(guān)的實(shí)例:

ParameterDiscreteValue dcItemId = new ParameterDiscreteValue();
ParameterDiscreteValue dcStartDate = new ParameterDiscreteValue();
ParameterDiscreteValue dcEndDate = new ParameterDiscreteValue();
dcItemId.Value = nItemId;
dcStartDate.Value = DateTime.Parse(strStartDate);
dcEndDate.Value = DateTime.Parse(strEndDate);

  最后,就可以在三個(gè)parameterfield的對(duì)象中的currentvalues中設(shè)置它們的值,并往paramFields集合中加進(jìn)這三個(gè)parameterfield對(duì)象。

  運(yùn)行的結(jié)果如下。


  本程序在VS.NET 2003,crystal report 9以上版本可以正確運(yùn)行。