在實際應用中,統計人員有根據要求制作特定統計報表的需要。本文參考了網上文章《在水晶報表中實現任意選擇指定字段顯示(阿泰)》,並在vs2008、sql2005環境下使用C#開發測試。測試運行界面如下圖所示:

1、創建報表所用的數據集文件
創建windows窗體應用程序CustomerReport。為了使用XSD數據集配置文件創建報表格式定義所用的數據集,在方案中新建一個名為“用於生成數據集的項目”的窗體應用項目。右鍵點擊“用於生成數據集的項目”項目名,選擇添加-->新建項。如下圖所示,在彈出界面中選擇創建數據集:

在打開的DataSet1.xsd界面中,右鍵點擊添加數據表,或直接從工具箱的數據集控件中拖放一個DataTable控件。如下圖所示,右鍵點擊DataTable控件,為其添加自定義列。這里定義了六個字段,字段(列)名稱可以隨意。
這里選擇以Northwind數據庫的Employees表為模板,自定義的六個字段分別對應表EmployeeID、LastName、FirstName、Title、BirthDate、Address等六個字段,所以要注意自定義字段的數據類型必須與它們一一對應。其中EmployeeID可以選擇INT32類型,BirthDate為System.DateTime類型。

如下圖所示,編輯DataSet1.xsd的屬性,在數據集項目中選擇CustomerReport項目,作為數據集類文件的輸出項目。修改數據集類文件名為DataSet1.cs:

把文件保存一下,系統會自動在CustomerReport項目中創建DataSet1.cs數據集類文件。
2、創建和設置報表文件
右鍵點擊項目名稱CustomerReport,選擇添加新建項,添加Crystal空白報表。如下圖所示:

如下圖所示,在字段資源管理器中右鍵點擊“數據庫字段-->數據庫專家”,添加定義報表所用的數據表:




通過定義,確定了報表可以接受的數據表DataTable及其字段(列)的數據類型。對於一般報表,只要把剛才添加的字段拖放到報表格式的“詳細資料”欄內就可以了,但這里要定義的是動態報表,需要使用公式字段作為報表列。
在字段資源管理器中右鍵點擊公式字段-->新建,創建六個公式字段。如下圖所示:

輸入公式字段名后回車,不作詳細設置,只要一個字段名就可。
除了詳細資料(列)所用的公式字段,報表的頁眉(列名稱)需要用到參數字段。如下圖所示,再定義六個參數字段,字段類型都選擇字串類型:

將六個公式字段依次拖到報表格式的詳細資料欄:

如圖所示,可以選中頁眉和詳細資料調整其位置和寬度,當然也可以把一行的各字段都選上,右鍵設置對齊方式等。
把頁眉中系統默認添加的字段名都刪除掉,把剛才新建的六個參數字段依次拖放到頁眉中,並設置格式(還可以把頁眉設置為黑體)。如下圖所示:

使用報表工具Box Object和Line Object為報表添加表格框和表格線。如下圖所示:

3、如下圖所示,為Form1表單添加字段選擇控件。注意控件的Text屬性要與數據庫表的字段名相同:

4、為按鈕添加點擊事件處理方法,代碼如下:
private void button1_Click(object sender, EventArgs e)
{
String fieldString = "";
if(checkBox1.Checked)
fieldString = checkBox1.Text;
if(checkBox2.Checked)
fieldString = fieldString + "," +checkBox2.Text;
if(checkBox3.Checked)
fieldString = fieldString + "," +checkBox3.Text;
if(checkBox4.Checked)
fieldString = fieldString + "," +checkBox4.Text;
if(checkBox5.Checked)
fieldString = fieldString + "," +checkBox5.Text;
if(checkBox6.Checked)
fieldString = fieldString + "," +checkBox6.Text;
if (fieldString == "")
{
MessageBox.Show("請選擇要顯示的字段");
return;
}
//刪除第一個逗號,使字串最終顯示為 "字段1,字段2,字段3"
if (fieldString.Substring(0, 1) == ",")
fieldString = fieldString.Substring(1, fieldString.Length - 1);
Form2 form = new Form2(fieldString);
form.Show();
}
以上代碼主要是獲取查詢字段。
5、創建顯示報表的窗體Form2
添加窗體Form,從報表工具中選擇CrystalReportViewer拖放到窗體中: 
6、編輯Form2代碼如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CrystalDecisions.Shared;
using System.Data.SqlClient;
using CrystalDecisions.CrystalReports.Engine;
namespace CustomerReport
{
public partial class Form2 : Form
{
private String fieldString;
private String[] fieldArray;
public Form2(String fieldString)
{
InitializeComponent();
this.fieldString = fieldString;
}
private void Form2_Load(object sender, EventArgs e)
{
int i, j;
ParameterFields paramFields = new ParameterFields();
ParameterField paramField;
//參數離散值定義
ParameterDiscreteValue discreteVal;
fieldArray = fieldString.Split(',');
//MessageBox.Show(fieldArray[2]);
SqlConnection conn = new SqlConnection("server=GTJ-KQS75Q8RX6P\\MYSQLDB;
database=Northwind;user id=sa;password=sa");
String sqlstr = "select " + fieldString + " from Employees";
SqlDataAdapter ada = new SqlDataAdapter(sqlstr, conn);
DataSet ds = new DataSet();
//表名稱要與報表定義引入的數據表名一致
ada.Fill(ds, "DataTable1");
//定義報表對象
ReportDocument myReport = new CrystalReport1();
//參數設置部分.設置第一個離散值並將其傳遞給該參數(傳遞參數做為表頭)
for (i = 0; i < fieldArray.Length; i++)
{
paramField = new ParameterField();
paramField.ParameterFieldName = "myParaField" + (i + 1).ToString();
discreteVal = new ParameterDiscreteValue();
discreteVal.Value = fieldArray[i];
paramField.CurrentValues.Add(discreteVal);
paramFields.Add(paramField);
paramField.AllowCustomValues = false;
//公式字段設置。
//如果字段類型為整數,報表顯示默認可能顯示小數,需要使用totext函數轉換一下。
if (fieldArray[i] == "EmployeeID")
myReport.DataDefinition.FormulaFields["myField" + (i + 1).ToString()].Text
= "totext(tonumber({DataTable1." + fieldArray[i] + "}),0)";
else
myReport.DataDefinition.FormulaFields["myField" + (i + 1).ToString()]
.Text = "{DataTable1." + fieldArray[i] + "}";
}
//設置未選擇的列標題為空
for (j = i + 1; j <= 6; j++)
{
paramField = new ParameterField();
paramField.ParameterFieldName = "myParaField" + j.ToString();
discreteVal = new ParameterDiscreteValue();
discreteVal.Value = "";
paramField.CurrentValues.Add(discreteVal);
paramFields.Add(paramField);
paramField.AllowCustomValues = false;
}
//報表參數綁定
crystalReportViewer1.ParameterFieldInfo = paramFields;
//報表數據源綁定
myReport.SetDataSource(ds);
crystalReportViewer1.ReportSource = myReport;
//MessageBox.Show(ds.Tables[0].Rows[1][1].ToString());
}
}
}
參考文章:
在水晶報表中實現任意選擇指定字段顯示 (阿泰)