asp.net|建立|水晶報表|圖表
在很多的應用程式中,報表是不可缺少的,一張好的報表能直觀地讓人把握資料的情況,方便決策。在這篇文章中,我們將以一個三層結構的asp.net程式為例,介紹如何使用crystal report ,來製作一份報表,其中介紹了不少asp.net和水晶報表的技巧。
在這個例子中,我們設想的應用要為一個銷售部門製作一份報表,管理者可以查看某段時間之內的銷售情況,以列表或者折線圖的形式反映出銷售的趨勢。我們將使用SQL Server 2000做為資料庫,使用VB.NET編寫中介層邏輯層,而前端的展示層使用C#。我們先來看下資料庫的結構。
其中,tbitem表中存放的是每張訂單中所訂購的貨品,tbsales存放的是每張訂單,tblsalesperson是銷售人員表,存放該出版社的每位銷售人員。
接下來,使用SQL Server 2000來建立這些表。表的結構如下所示:
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] |
並且用以下的代碼建立表之間的約束關係。
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 |
建立中間邏輯層
在中間邏輯層組件中,我們為每一張表都建立兩個類。比如,對於tblItems表,建立item 和items類。Item類中記錄每件銷售的貨品的詳細情況,而items表則記錄所有銷售的貨品並且有增加貨品的方法。這樣,就存在下面的六個類:
Item and Items
SalesPerson and SalesPersons
Sale and Sales
接下來,看一下每個類中的屬性:
Item類
包括如下屬性
ItemId (貨品id編號)
Description (貨品的描述)
Items
有一個方法,將根據item的編號返回一個item對象
Public Function GetAllItems () As Collections.ArrayList |
SalesPerson
該類有以下三個屬性:
SalesPersonId (銷售人員編號)
Name (姓名)
Password (密碼)
SalesPersons
有一個方法,根據銷售人員登陸時輸入的使用者名稱和密碼,在資料庫中,驗證銷售人員的登陸是否正確,如果正確,則返回零。
Public Function ValidateUser (strUserName as String, strPassword as String) As Integer |
Sale
有如下5個屬性
· SaleId
· SalesPersonId
· ItemId
· SaleDate
· Amount
Sales
有兩個方法,其中getsales根據輸入的參數返回sales對象的集合
Public Function GetSales (Optional nSaleId As Integer = 0, Optional nSalesPersonId As Integer = 0,Optional nItemId As Integer = 0) As Collections.ArrayList |
還有一個addsales方法,用於增加一張訂單
Public Function AddSale (objSale As Sale) |
建立表現層頁面
接下來,開始建立表現層頁面。首先,要建立一個可以給銷售人員登陸的頁面,如下圖所示。
在銷售人員成功登陸後,可以給銷售人員輸入某樣貨品銷售的數量,如下圖:
此外,為了給業務主管看到某個時期的銷售情況,建立如下頁面。
其中,業務主管可以選擇查看某樣貨品在某個時期(選擇開始日期,結束日期)的銷售情況,以圖表方式顯示。
這裡特別值得一提的是,日曆控制項的使用。在頁面中放置日曆控制項後,設定如下代碼:
<input type="image" src="http://www.pushad.com/Info/datepicker.gif" alt="Show Calender" runat="server" onserverclick="ShowCal1" id="ImgCal1" name="ImgCal1"> |
這裡設定page_validationactive參數為false,所以不需要重新提交頁面,並且,在onserverclick事件中,設定處理的代碼,如下所示:
public void ShowCal1(Object sender, System.Web.UI.ImageClickEventArgs e) { //顯示日曆控制項 DtPicker1.Visible = true; } |
當使用者選擇了相關的日期後,在文字框中可以獲得相關的日期:
private void DtPicker1_SelectionChanged(object sender, System.EventArgs e) { txtStartDate.Text = DtPicker1.SelectedDate.ToShortDateString(); DtPicker1.Visible = false; } |
在提交的頁面中,處理的代碼如下:
private void bSubmit_ServerClick(object sender, System.EventArgs e) { Response.Redirect("ViewReport.aspx?ItemId=" + cboItemType.SelectedItem.Value + "&StartDate=" + txtStartDate.Text + "&EndDate=" + txtEndDate.Text);} |
在提交頁面後,將跳轉到瀏覽報表的頁面viewreport.aspx,傳入相關的參數,如貨品ID,開始和結束日期。
用水晶報表建立報表
首先,往表單中添加水晶報表控制項,之後,就可以用水晶報表的報表設計師設計一份報表了。建立一個水晶報表檔案類型,命名為itemreport.rpt,接著使用報表設計專家,並選擇設計標準型的報表,點下一步,出現如下畫面:
我們選擇使用ADO類型的資料,在彈出的視窗中,設定好sql server的登陸名,登陸密碼,選擇好資料庫後,選擇在報表中使用tblsales表,如下圖:
接著選Next,在要在報表中顯示的欄位中,選擇SaleDate和Amount。之後,一直選NEXT,忽略其他相關設定,最後,在圖表類型中選擇折線圖,如下圖:
最後點擊finish,可以看到如下的報表:
再次選擇報表專家,在彈出的視窗中選擇資料頁,在資料可用欄位中選擇salesdate,並且可以在文本頁中,設定適當的報表標題。
由於要根據輸入的日期,貨品參數來動態顯示報表,因此我們要設定參數欄位。在報表設計師中,在欄位總管中,選擇參數欄位,滑鼠右擊選擇“建立”,建立如下三個參數欄位。
名稱: |
類型: |
ItemId |
Number |
StartDate |
Date |
EndDate |
Date |
最後,要設定相關的查詢公式,在除報表首的地區,滑鼠右鍵點擊,在快顯功能表中選擇“報表|編輯選擇公式|記錄”,輸入如下的公式:
在上面的方程式編輯器中,分為左中右三部分,左邊的是報表的欄位,中間的是相關的功能函數,最右邊的是運算子,雙擊其中選中的部分,則可以添加到下部的公式顯示地區中。最後,儲存建立的公式。
在程式中使用報表
接下來,我們可以在程式中用代碼處理和報表的串連過程。首先,在工程項目中,增加如下的兩個命名空間的引用(注意,在代碼中也必須用using引入它們):
CrystalDecisions.CrystalReports.Engine CrystalDecisions.Shared 在viewreport.aspx的Page_load事件中,加入以下代碼
//接收傳遞的參數 nItemId = int.Parse(Request.QueryString.Get("ItemId")); strStartDate = Request.QueryString.Get("StartDate"); strEndDate = Request.QueryString.Get("EndDate"); //聲明報表的資料對象 CrystalDecisions.CrystalReports.Engine.Database crDatabase; CrystalDecisions.CrystalReports.Engine.Table crTable; TableLogOnInfo dbConn = new TableLogOnInfo(); // 建立報表對象opt ReportDocument oRpt = new ReportDocument(); // 載入已經做好的報表 oRpt.Load("F:\\aspnet\\WroxWeb\\ItemReport.rpt"); //串連資料庫,獲得相關的登陸資訊 crDatabase = oRpt.Database; //定義一個arrtables對象數組 object[] arrTables = new object[1]; crDatabase.Tables.CopyTo(arrTables, 0); crTable = (CrystalDecisions.CrystalReports.Engine.Table)arrTables[0]; dbConn = crTable.LogOnInfo; //設定相關的登陸資料庫的資訊 dbConn.ConnectionInfo.DatabaseName = "WroxSellers"; dbConn.ConnectionInfo.ServerName = "localhost"; dbConn.ConnectionInfo.UserID = "sa"; dbConn.ConnectionInfo.Password = "test"; //將登陸的資訊應用於crtable表對象 crTable.ApplyLogOnInfo(dbConn); //將報表和報表瀏覽控制項綁定 crViewer.ReportSource = oRpt; //傳遞參數 setReportParameters(); |
在上面的代碼中,首先接收了日期,貨品編號等參數,並執行個體化了Database, Table和 TableLogOnInfo 三個類,它們是用來在運行時,建立報表和資料庫的串連必需的。再使用
oRpt.Load("F:\\aspnet\\WroxWeb\\ItemReport.rpt"); |
來裝載已經做好了的報表。
在裝載完報表後,將資料庫中要使用的表複製到一個對象數組中去,並選擇對象數組中的第一個表元素,將其轉換為水晶報表的報表對象。接著,再設定LOGONINFO中的登陸資料庫的資訊。最後,將報表源與報表瀏覽控制項綁定。
傳遞參數到水晶報表
定義一個新的過程,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(); // 設定在報表中,將要接受的參數欄位的名稱 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);
// 將參數集合綁定到報表瀏覽控制項 crViewer.ParameterFieldInfo = paramFields; } |
現在來解釋一下上面的代碼。在水晶報表中,瀏覽器控制項有一個屬性parameterfieldsinfo,該屬性可以通過綁定parameterfields類型的集合,將相關的參數的實際數值傳遞到報表。Parameterfields類型集合通過add的方法,接收Parameterfield類型的對象。因此,我們先為itemid,startdate,enddate三個參數建立parameterfield類型的對象,並且設定它們對應報表中接受參數的名稱:
ParameterFields paramFields = new ParameterFields(); ParameterField pfItemId = new ParameterField(); ParameterField pfStartDate = new ParameterField(); ParameterField pfEndDate = new ParameterField(); // 設定在報表中,將要接受的參數欄位的名稱 pfItemId.ParameterFieldName = "ItemId"; pfStartDate.ParameterFieldName = "StartDate"; pfEndDate.ParameterFieldName = "EndDate"; |
接著,可以為這些參數欄位設定具體的值了,但由於parameterfield必須接受P arameterDiscreteValue類型的對象,所以,再建立相關的執行個體:
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); |
最後,就可以在三個parameterfield的對象中的currentvalues中設定它們的值,並往paramFields集合中加進這三個parameterfield對象。
啟動並執行結果如下。
本程式在VS.NET 2003,crystal report 9以上版本可以正確運行。