水晶報表中如何動態增加字段

說明:
       最近項目中要用到水晶報表,水晶報表的功能的確非常強大,但是有一個問題一直困擾着我,那就是它對於每種數據表結構都必須建一個報表文件。儘管它有兩種使用方式,“pull”模式和“push”模式。但是推模式下仍然需要先根據dataset的結構生成相應的報表文件。這樣就很不靈活,試想如果之前並不知道數據集dataset的結構,怎麼用報表?即便知道有哪些表格,如果表格數太多,對於每個表格生成一個報表文件,那也是很繁瑣的一件事。所以,有沒有方法建立一個通用報表文件,然後可以在運行時根據dataset
的具體結構來確定報表的結構呢?查了很多資料,很少有詳細的解決方案。
       在翻閱了一些資料,借鑑了多種做法後,終於解決了這個問題,下面把思路闡述如下:

第一步:
    新建一個web網站,然後在項目中新建一個空白報表,命名爲CommonReport.rpt,打開報表,在字段資源管理器中右鍵選“數據庫字段”,選擇“數據庫專家”,在彈出窗口中選“創建新連接”中的OLEDB,然後選擇SQL Server的提供程序,點擊下一步,如圖p1所示,跟着嚮導做下去,中間要輸入連接信息,並選擇一個數據庫,“完成”後,可以看到連上了你所選的數據庫,我選了本地SQLServer服務器上的“Northwind”數據庫,它是Sql server中自帶的一個數據庫。然後隨便選擇這個庫裏的一張表,這裏我選擇第一張表“Categories”添加到右面,如圖p2所示。完成後,應該是圖p3所示結果,可以看到字段資源管理器中的數據庫字段裏有了一張表Categories,和它的四個字段,此時第一步完成了,後面不需要再管它了。 圖P2

圖P3

圖P4
圖P5

第二步:
    在“字段資源管理器”中建立公式字段,公式字段的個數根據數據庫裏所有表格中字段最多的那個表格的字段數來定。這裏我建立了6個公式字段,注意,這些公式字段都是空的。然後將這6個公式字段依次拖放到報表的詳細資料欄裏。
    右鍵點擊某個公式字段對應的頁眉中文本對象(如圖4中的“FormulaField6”)彈出菜單,選擇“設置對象格式”,得到圖中的格式化編輯器對話框。選擇對話框中的“抑制顯示”複選框後面的圖標按鈕,然後在彈出的對話框中輸入圖p4右下方的一段代碼(if… else…),如圖p4所示。
    完成後點“保存並關閉”。剩下的其它幾個字段如法炮製。完成後就可以保存報表文件,報表製作完成。

圖P1


圖P6


 

現在我們可以看到,不管數據庫服務器上有多少數據表,我們只要用CommonReport.rpt這一個報表文件就可以顯示了。

注意:

1, 做第一步的原因只是因爲需要一個表的連接,否則在調用report對象的setDataSource()方法時會報錯,提示“報表中沒有表存在”。換句話說就是爲報表文件生成表格時提供一個表名,報表最終顯示的並不是來自這張表裏的數據,

2, 4中那段代碼是用Crystal的語言寫的,作用是判斷當前列是否有數據,如果沒有則不在頁眉中顯示該列的標題。它的作用就是因爲我們所設的公式字段並不一定都用得上,因爲我們是按字段最多的情況確定的公式字段個數,多出來的公式字段就要屏蔽掉。

3, showReport.aspx.csCommonReport.SetDataSource(dataSet.Tables[CommonReport.Database.Tables[0].Name]);這個語句,參數必須明確指定dataSet中的表名,如果只用dataSet作爲參數,則報表中不顯示數據,不知道是什麼原因。

4, 這裏是用公式字段解決的,也可以用未綁定字段來解決這個問題,道理是一樣的。

5, 如圖p6所示,第一列沒有對齊。這是後來發現的問題,沒找到什麼原因。

參考資料:

http://blog.csdn.net/haibodotnet/archive/2003/11/09/21504.aspxcsdn上的一篇文章,參考了他的思路

http://msdn2.microsoft.com/zh-cn/library/ms225984(VS.80).aspxmsdn上水晶報表的類庫

Crystal Reports for Visual Studio .NET 高級編程》,David McAmis

第三步:
    新建網頁用來測試我們生成的報表,首先生成一個GetDataSet.aspx頁面,該頁面裝載時連接數據庫,生成DataSet,並將它存入Session對象中。還有一個按鈕,在事件處理代碼中調用另外一個頁面showReport.aspx
    showReport.aspx這個頁面裏面有個報表瀏覽器CrystalReportViewer控件,它從session中取出DataSet,用CrystalReportViewer顯示DataSet中的數據。
    
GetDataSet.aspx.cs的代碼:

using System;

using System.Data;

using System.Configuration;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Data.SqlClient;

public partial class GetDataSet : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        SqlConnection sqlConnection = new SqlConnection ( "Server=localhost;User Id=sa;Initial Catalog=Northwind" ) ;

        sqlConnection.Open();

        SqlDataAdapter sqlDataAdapter1 = new SqlDataAdapter("SELECT CustomerID , CompanyName,City,Country FROM Customers", sqlConnection);

        DataSet dsDataSet = new DataSet () ;

        sqlDataAdapter1.Fill (dsDataSet,"Customers") ;

        //使用SqlDataAdapter的Fill方法填充DataSet

        sqlConnection.Close ( ) ;

       //關閉數據連接

        Session["DataSet"] = dsDataSet;

    }

    protected void Button1_Click(object sender, EventArgs e)

    {

        Page.RegisterClientScriptBlock("open", "<script   language='javascript'>window.open('showReport.aspx','_blank')</script>");

    }

}

showReport.aspx.cs的詳細代碼:

using System;

using System.Data;

using System.Configuration;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using CrystalDecisions.CrystalReports.Engine;

public partial class showReport : System.Web.UI.Page

{

    private ReportDocument CommonReport;

    ///<summary>

    ///根據具體查詢得到的ADO.NET數據集配置水晶報表

    ///</summary>

    private void ConfigureCrystalReports()

    {

        //生成一個報表對象

        CommonReport = new ReportDocument();

        //報表文件路徑

        string reportPath = Server.MapPath("CommonReport.rpt");

        //根據路徑裝載指定報表文件,以進行報表配置操作

        CommonReport.Load(reportPath);

        //從Session中取得數據集,該數據集是從其它頁面查詢數據庫得到後保存在Session中的

        DataSet dataSet = (DataSet)Session["DataSet"];

        //將數據集中的表格的名稱修改爲報表文件中連接的數據表的名字,保證兩個表格名稱一致

        dataSet.Tables[0].TableName=CommonReport.Database.Tables[0].Name;

        //獲取數據集中字段個數,也是報表中要顯示的列的個數

        int CountOfColumns = dataSet.Tables[0].Columns.Count;

       

        //定義一個字符串數組,在for循環中生成每個公式字段對象的文本(格式是"{tablename.columnname}"),並保存到數組中以備使用

        String[] Text4formularFields = new String[CountOfColumns];

        for (int index = 0; index < CountOfColumns; index++)

        {

            Text4formularFields[index] = "{" + CommonReport.Database.Tables[0].Name + "." + dataSet.Tables[0].Columns[index].ColumnName + "}";            

        }

        //獲取報表文件的數據定義對象

        DataDefinition dataDefinition = CommonReport.DataDefinition;

        //獲取數據對象中的公式字段集合

        FormulaFieldDefinitions formularFields = dataDefinition.FormulaFields;

        for (int columnIndex = 0; columnIndex < CountOfColumns;columnIndex++)

        {

            //將公式字段的空白文本替換爲根據當前數據集dataSet具體字段生成的文本

            formularFields[columnIndex].Text=Text4formularFields[columnIndex];

           

            //頁眉中的文本對象(也就是報表中每列的標題)設置爲dataSet的具體字段名

            TextObject CurrentText = (TextObject)(CommonReport.ReportDefinition.Sections["Section2"].ReportObjects[columnIndex]);

            CurrentText.Text = dataSet.Tables[0].Columns[columnIndex].ColumnName;

        }

        //設置報表對象的數據源爲dataSet中的同名表格

        CommonReport.SetDataSource(dataSet.Tables[CommonReport.Database.Tables[0].Name]);

        //綁定到報表瀏覽器

        CrystalReportViewer1.ReportSource = CommonReport;

    }

    private void Page_Init(object sender, EventArgs e)

    {

        ConfigureCrystalReports();

    }

   

    protected void Page_Load(object sender, EventArgs e)

    {

    }

}

上面兩個頁面運行後的效果,如圖p5所示。
    如果把GetDataSet.aspx.cs文件中的SQL查詢字符串換成SELECT EmployeeID , LastName,FirstName,Title,Country FROM Employees,其它的地方都不改動,報表文件還是用CommonReport.rpt。得到的報表輸出如圖p6所示。

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