利用reportviewer與C#生成報表

下面,我們開始創建報表,首先要編寫一個生成報表的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是通過SUM函數計算得到的,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”。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章