關於編寫報表,職場中的人相信都會有所感慨,一份整潔、優美的報表會為你在上司面前增色不少,甚至加薪 ——大家都喜歡加薪,對吧?在本文中,將向大家介紹怎樣利用MS Reporting Services 2005來建立一份報表,並用一個C#小程式來產生它。
本文假定讀者已對Visual Studio 2005 IDE有了初步的瞭解,並能用C#編寫代碼,懂不懂MS Reporting Services都對理解本文沒有關係,當然了,之前寫過類似的報表,將有助於你更快地上手。好了,捲起袖子,準備開始吧!
請看圖1,這份報表有多複雜?猜猜它需要多少時間完成?就複雜而言,它只是一份簡單的、從NorthWind->Products (SQL Server 2000)中提取出來的報表;就時間而言,相信不會花你一整個小時吧。
圖1
下面,我們開始建立報表,首先要編寫一個產生報表的C#小程式。
第一步:建立一個Windows應用程式
選擇檔案菜單,建立-工程,從工程類型中選擇C#,從右方對話方塊中選擇Windows應用程式;在名稱欄中,最好用一個表明程式用途的名字;在位置欄中,寫明你想要儲存的目錄。完成之後,工程中會有一個Form1,我們就從對它的表單設計器開始講解。
像下面這樣修改Form1的屬性,當然也可以依個人喜好修改其他的屬性:
Form1.Text = "MS Reporting Services 101 with Smart Client"
Form1.Size = 750, 300
第二步:為表單(Form)添加報表檢視器(Report Viewer)
什麼是報表檢視器,就像看DVD碟時需要一部DVD播放機一樣,我們需要一個報表檢視器來預覽報表。
對初寫報表的人來說,報表檢視器可以說是賦予了報表生命,它不僅可預覽輸出,還可協助將報表資訊產生各種格式(PDF或Excel等等),列印出來更不在話下。
[span] 請按如下步驟在Form1上放置好報表檢視器控制項:
依次找到工具箱(ToolBox)-資料(Data)-報表檢視器(ReportViewer),並把它拖到Form1上。這會建立一個名為reportViewer1新的執行個體。
通過設定reportViewer1.Dock = Fill,報表檢視器將會填充表單的整個地區,以顯示報表。
在完成第一步與第二步之後,工程看起來應該2所示:
圖2
第三步:為工程添加資料集(DataSet)
資料集是伴隨報表檢視器而來的,它儲存並提供從資料來源而來的未經處理資料,我們便可對這些未經處理資料進行處理或在C#程式中輸出。
請依照如下步驟添加資料集:
從解決方案資源總管中選擇添加-新項目-資料集,將其名稱DataSet1修改dsProduct,並單擊添加按鈕完成。
添加一個資料表到新建立的資料集中。資料表實質上是用來載入報表資料的,在設計報表時,將會用到DataSet/DataTable中的相關資訊。
以下為添加資料表到資料集(dsProduct)中:
從解決方案資源總管中雙擊dsProduct,將會開啟設計檢視,按右鍵並選擇添加-資料表。接著,單擊表頭修改名稱為dtProductList,3:
圖3
接下來開始為資料表(dtProductList)添加列,此時的設計檢視應該4所示。按右鍵dtProductList並選擇添加——列(Column)。
圖4
重複以上步驟添加以下列:
ProductName (String)
QuantityPerUnit (String)
UnitPrice (Double)
UnitsInStock (Double)
UnitValue (Double):一個基於UnitsInStock * UnitPrice的計算域
在添加列時,預設為String資料類型,添加完之後請轉到屬性視窗,修改相應的列為Double類型。
請看圖5,現在的資料表看上去應該就像這樣子了。同時,你也可查看屬性視窗來修改資料類型。
圖5
第四步:為工程添加報表
到目前為止,我們已經建立了工程,添加了報表檢視器與資料集;現在,是時候建立一份整潔、優美的報表了。
需按照以下步驟產生報表(rptProductList.rdlc):
從解決方案資源總管中選擇添加-新項目-報表,把名稱Report1.rdlc修改為rptProductList.rdlc,並單擊添加按鈕完成。
工程可能會像圖6這樣;而添加完報表之後,就可以開始使用資料集(DataSet)進行設計了。
圖6
無論你是第設計一次報表的新手,或是曆經沙場老手,都必須與以下三種最基本的報表地區打交道:頁首(或叫表頭)、頁尾、表體。一般來說,報表在設計時,就應該有一個腹稿,如多大的紙張、應該怎樣排版等等,通常都為信紙大小、縱向排版。當然了,如果能在動手之前,先在紙上畫個草圖,這樣更好。可以回過頭來看一1,在頁首,已經有了報表名及報表日期,表體中有產品的相關資訊列表,而頁尾中有頁碼。
那我們就從頁首開始吧。當添加新報表到工程時,預設情況下,在報表設計師中只能看到表體。按右鍵報表設計師的表體之外處,選擇頁首,這會在報表中添加一個頁首,可以隨意調整頁首與表體區的高度,請看圖7,圖7中減少了表體的高度,增加了頁首的高度。
圖7
在報表設計師的工具箱中,你可以看到用於設計報表的各種各樣的控制項。在我們這個例子中,會用到TextBox、Line和Table控制項。現在我們開始設計頁首了。拖動兩個TextBox並把它們置於頁首區,TextBox既能顯示靜態也能顯示動態資料,而Line控制項用於把頁首從表體區中分隔出來。控制項放置好之後,可以修改它們的屬性以顯示我們所需的值,例如可以指定一個TextBox為報表標題,而另一個TextBox顯示當前日期。選擇TextBox之後,可直接在其內輸入靜態文本。
請照以下修改標題TextBox:
Value = "Product List"
Color = Purple
而日期TextBox則修改為:
Value = "Run Data: " & Today
Color = Purple
[span] 要注意了,日期TextBox的Value屬性以"="符號打頭,這代表它不是一個簡單的靜態文本,而是一個運算式,這個運算式是字串"Run Date"與VB.NET指令碼Today的結果。
另外多說一點,你可對報表中所有對象指定任何你想要的名稱,一般對大多數控制項而言,保持預設名稱就好了,此處把標題TextBox的名稱(即Name屬性)指定為“txtTitle”。
參照圖8,完成頁首設計之後,應該看起來就像這樣子:
圖8
現在是表體了。表體是承載資訊的詳細地區,是整個報表最重要的部分,而且你也看到了,當添加報表到工程時,表體已經自動添加了,我們只需要在上面放些控制項就行了。
從傳統意義上來說,表體區是用於顯示詳細資料的(在本例中,為產品資訊),並且通常為多行資訊,而隨著報表上資料的增多,表體區也相應會擴充,但一般來說,報表只會設計為一頁(信紙或A4紙大小)。
在表體區中,有三種最常用的控制項:Table、Matrix、List,在本例中會使用Table控制項。在報表設計介面中,拖動並把Table控制項放置於表體區中,你會看到,這會產生一張三行三列的表,而中間一列則已被標記為:Header、Detail、Footer。
當你知道Table控制項只不過是一堆TextBox的組合,是不是有點吃驚呢。對了,Talbe中的每個單元(Cell)都與TextBox一樣,也就是說,可以在其中輸入靜態文本,或指定一個動態運算式。
在開始設計表體區之前,記得要多添加兩列(我們的報表中有5列喔),添加列非常簡單,依照以下步驟就行了:
1、 在表體區中選擇Table控制項。
2、 左鍵單擊最右邊一列的表頭(此處假設你是從右邊添加新列的)。
3、 按右鍵表頭,並選擇“Insert Column to the Right”(在右邊插入列)。
現在報表看起來應該像圖9了,可以依據列中的資料隨意調整列的寬度。
圖9
大家多半也用過Excel或類似的東西吧,可以把Table控制項看成是一張迷你工作表,在其中可以選擇邊框類型、改變任一儲存格的字型等等。因此,所需做的就是依之前設想好的格式來設計表格。
我們從第一列開始,隨後的每一列也一樣,單擊最上方的儲存格並依次輸入:
表頭1:“Product Name”
表頭2:“Packaging”
表頭3:“Unit Price”
表頭4:“Units in Stock”
表頭5:“Stock Value”
而在接下來的詳細資料區(即前面的Detail)中,需要輸入運算式,其為dsProduct.dtProductInfo中的列,在此既可以手工輸入運算式,也可以從資料來源(Data Sources)工具箱(見圖7左邊)中拖放實現。
如果想要手工輸入,請從資料區的第一列至最後一列,單擊儲存格並輸入:
Detail 1: "=Fields!ProductName.Value"
Detail 2: "=Fields!QuantityPerUnit.Value"
Detail 3: "=Fields!UnitsInStock.Value"
Detail 4: "=Fields!UnitPrice.Value"
Detail 5: "=Fields!UnitsInStock.Value * Fields!UnitPrice.Value"
請留意Detail 5,它是一個對Units in Stock與Unit Value相乘計算之後的輸出。另外提醒一點,如果是拖動列到Table控制項中的資料區來實現的,此時如果表頭為空白,它會自動添加表頭。
最後,在Table控制項的頁尾添加一累計欄,選擇表體區第4與第5列的頁尾儲存格,輸入:
儲存格4:“Total Value:”
儲存格5:"=SUM(Fields!UnitsInStock.Value * Fields!UnitPrice.Value)"
單擊儲存格5,這是使用了一個內建的SUM()函數來得到累計的結果。
最後只剩下頁尾區了,在開始編寫一些C#代碼之前,還需完成報表的頁尾,正如前面添加報表首一樣,在開啟的報表設計師中,按右鍵並選擇頁尾(Page Footer),見圖7。
拖動一個Line和TextBox控制項置於頁尾區,並在TextBox中輸入以下運算式:
Value: ="Page: " & Globals!PageNumber & "/" & Globals!TotalPages
大家可以看到,此處使用了PageNumber和TotalPages,兩 者皆為全域變數。
現在,報表應該像圖10這樣了,此處,還改變了一點顏色,把數值類資料靠右對齊,把Table當作一張Excel工作表好了,可以隨意調整為你想要的外觀。
圖10
快大功告成了!剩下的就是運算式產生器了。運算式產生器是Reporting Services中一個非常強大的工具,正11中所見,Stock Value是通過SUMFunction Compute得到的,DateSet中的所有資料都可以由“Fields!”關鍵字訪問。
圖11
第五步:編寫賦予報表生機的C#代碼
從解決方案資源總管中,選擇Form1,按右鍵並選擇查看代碼,為Form1_Load添加以下代碼:
using System.Data.SqlClient;
using Microsoft.Reporting.WinForms;
private void Form1_Load(object sender, EventArgs e)
{
//聲明連接字串
string cnString = @"(local); Initial Catalog=northwind;"+"User Id=northwind;Password=northwind";
//如果使用標準安全屬性,請改為以下代碼
//string cnString = @"Data Source=(local);Initial Catalog=northwind; Integrated Security=SSPI";
//聲明串連、命令對象及其他相關對象
SqlConnection conReport = new SqlConnection(cnString);
SqlCommand cmdReport = new SqlCommand();
SqlDataReader drReport;
DataSet dsReport = new dsProduct();
try
{
//開啟串連
conReport.Open();
//準備連線物件以把擷取的資料放入資料集
cmdReport.CommandType = CommandType.Text;
cmdReport.Connection = conReport;
cmdReport.CommandText = "Select TOP 5 * FROM Products Order By ProductName";
//從命令對象中讀取資料
drReport = cmdReport.ExecuteReader();
//有了ADO.NET,可把讀取來的資料直接載入到資料集中
dsReport.Tables[0].Load(drReport);
//關閉讀取及串連
drReport.Close();
conReport.Close();
//為查看器提供本地報表資料
rpvAbraKaDabra.LocalReport.ReportEmbeddedResource =
"rsWin101.rptProductList.rdlc";
//準備報表資料來源
ReportDataSource rds = new ReportDataSource();
rds.Name = "dsProduct_dtProductList";
rds.Value = dsReport.Tables[0];
rpvAbraKaDabra.LocalReport.DataSources.Add(rds);
//載入報表檢視器
rpvAbraKaDabra.RefreshReport();
}
catch (Exception ex)
{
//顯示錯誤資訊
MessageBox.Show(ex.Message);
}
finally
{
//檢查串連是否仍然開啟,如果是,關閉它。
if (conReport.State == ConnectionState.Open)
{
conReport.Close();
}
}
}
看到這,大家可能會想,為什麼在select查詢語句中使用了“TOP 5”,此處只是作示範的目的,對輸出作一限制,以得到1中的累計結果。另外,ReportDataSource的Name屬性應總為“DataSet_DataTable”。
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/mountplorer/archive/2009/05/07/4157216.aspx