最近在研究dev xtraReport的應用,雖然從08年就開始接觸dev,但是它的報表還是頭次接觸。在網上找了很多資料,但看來看去無非就那么兩篇,呵呵,真是天下文章一大抄!相對水晶報表,xtraReport在設計上是很強大的,在功能上也要比水晶報表完善很多。但是在這里要吐槽一下,dev的demo寫的真的不咋地,效果是出來了,找代碼還得找半天還不應定能找到。
言歸正傳,今天主要說的單表顯現和簡單主從表顯現實現。相對於國外報表來講,國內的報表很有中國特色,中規中矩的,所以也給設計人員帶來了些許方便。先來說說單表的報表實現。我在這里使用的是xtraReport的設計器來設計的報表,有興趣的可以從demo-xtraReports-RibbonReportDesigner打開它。在設計上,和水晶報表的設計有不同,但是參數的標識也是用"[]"的。
1、單表
報表設計
網頁運行效果
后台代碼(Ps:數據庫不是我的,大家不要噴我~~)
數據層

1 public DataTable GetData() 2 { 3 using (SqlConnection conn = new SqlConnection(connectionString)) 4 { 5 string _commandSql="SELECT [ID],[名稱],[添加時間] FROM [部門表]"; 6 using (SqlDataAdapter da = new SqlDataAdapter(_commandSql, conn)) 7 { 8 DataSet ds = new DataSet(); 9 da.Fill(ds); 10 return ds.Tables[0]; 11 } 12 } 13 }
實體類

1 public class Dept 2 { 3 public string ID{get;set;} 4 public string Name { get; set; } 5 public DateTime? CreateTime { get; set; } 6 }
前台頁面

1 <dx:ReportToolbar ID="ReportToolbar1" runat="server" ReportViewerID="ReportViewer1" ShowDefaultButtons="False"> 2 <Items> 3 <dx:ReportToolbarButton ItemKind="Search" /> 4 <dx:ReportToolbarSeparator /> 5 <dx:ReportToolbarButton ItemKind="PrintReport" /> 6 <dx:ReportToolbarButton ItemKind="PrintPage" /> 7 <dx:ReportToolbarSeparator /> 8 <dx:ReportToolbarButton Enabled="False" ItemKind="FirstPage" /> 9 <dx:ReportToolbarButton Enabled="False" ItemKind="PreviousPage" /> 10 <dx:ReportToolbarLabel ItemKind="PageLabel" /> 11 <dx:ReportToolbarComboBox ItemKind="PageNumber" Width="65px"> 12 </dx:ReportToolbarComboBox> 13 <dx:ReportToolbarLabel ItemKind="OfLabel" /> 14 <dx:ReportToolbarTextBox IsReadOnly="True" ItemKind="PageCount" /> 15 <dx:ReportToolbarButton ItemKind="NextPage" /> 16 <dx:ReportToolbarButton ItemKind="LastPage" /> 17 <dx:ReportToolbarSeparator /> 18 <dx:ReportToolbarButton ItemKind="SaveToDisk" /> 19 <dx:ReportToolbarButton ItemKind="SaveToWindow" /> 20 <dx:ReportToolbarComboBox ItemKind="SaveFormat" Width="70px"> 21 <elements> 22 <dx:ListElement Value="pdf" /> 23 <dx:ListElement Value="xls" /> 24 <dx:ListElement Value="xlsx" /> 25 <dx:ListElement Value="rtf" /> 26 <dx:ListElement Value="mht" /> 27 <dx:ListElement Value="html" /> 28 <dx:ListElement Value="txt" /> 29 <dx:ListElement Value="csv" /> 30 <dx:ListElement Value="png" /> 31 </elements> 32 </dx:ReportToolbarComboBox> 33 </Items> 34 <styles> 35 <LabelStyle><Margins MarginLeft='3px' MarginRight='3px' /></LabelStyle> 36 </styles> 37 </dx:ReportToolbar> 38 <br /> 39 <dx:ReportViewer ID="ReportViewer1" runat="server"> 40 </dx:ReportViewer>
前台代碼(重要)

1 protected void Page_Load(object sender, EventArgs e) 2 { 3 DataTable dt = new Controller().GetData(); 4 List<Dept> list = new List<Dept>(); 5 Dept deptInfo = null; 6 7 for (int i = 0; i < dt.Rows.Count; i++) 8 { 9 deptInfo = new Dept() 10 { 11 ID = dt.Rows[i]["ID"].ToString(), 12 Name = dt.Rows[i]["名稱"].ToString() 13 14 }; 15 if (dt.Rows[i]["添加時間"] == null) 16 deptInfo.CreateTime = null; 17 else 18 deptInfo.CreateTime = Convert.ToDateTime(dt.Rows[i]["添加時間"]); 19 list.Add(deptInfo); 20 } 21 22 XtraReport xpr = null; 23 if (dt != null) 24 { 25 xpr = XtraReport.FromFile(Server.MapPath("~") + "dept.repx", true); 26 xpr.DataSource = list; 27 } 28 xpr.CreateDocument(); 29 ReportViewer1.Report = xpr; 30 ReportViewer1.DataBind(); 31 }
這里要說的是:由於使用的List<>,所以在設計報表的時候,報表參數名稱要和實體對象中的屬性名稱相一致。
對於奇偶行樣式,可通過EvenStyle和OddStyle來設計實現。
2、主從表
報表設計
對於主從表的報表設計,建議使用Group和DetailReport來實現。
網頁運行效果
數據層

1 public DataSet GetMasterDetailData() 2 { 3 using (SqlConnection conn = new SqlConnection(connectionString)) 4 { 5 string _masterCommandSql = "SELECT [ID],[名稱],[添加時間] FROM [部門表]"; 6 string _detailCommandSql = "SELECT [編號],[姓名],[添加時間],[部門ID] FROM [用戶表]"; 7 DataSet ds = new DataSet(); 8 using (SqlDataAdapter da = new SqlDataAdapter(_masterCommandSql, conn)) 9 { 10 da.Fill(ds,"Master"); 11 } 12 using (SqlDataAdapter da = new SqlDataAdapter(_detailCommandSql, conn)) 13 { 14 da.Fill(ds,"Detail"); 15 } 16 return ds; 17 } 18 }
前台頁面

<dx:ReportToolbar ID="ReportToolbar1" runat="server" ShowDefaultButtons="False" ReportViewerID="ReportViewer1"> <Items> <dx:ReportToolbarButton ItemKind="Search" /> <dx:ReportToolbarSeparator /> <dx:ReportToolbarButton ItemKind="PrintReport" /> <dx:ReportToolbarButton ItemKind="PrintPage" /> <dx:ReportToolbarSeparator /> <dx:ReportToolbarButton Enabled="False" ItemKind="FirstPage" /> <dx:ReportToolbarButton Enabled="False" ItemKind="PreviousPage" /> <dx:ReportToolbarLabel ItemKind="PageLabel" /> <dx:ReportToolbarComboBox ItemKind="PageNumber" Width="65px"> </dx:ReportToolbarComboBox> <dx:ReportToolbarLabel ItemKind="OfLabel" /> <dx:ReportToolbarTextBox IsReadOnly="True" ItemKind="PageCount" /> <dx:ReportToolbarButton ItemKind="NextPage" /> <dx:ReportToolbarButton ItemKind="LastPage" /> <dx:ReportToolbarSeparator /> <dx:ReportToolbarButton ItemKind="SaveToDisk" /> <dx:ReportToolbarButton ItemKind="SaveToWindow" /> <dx:ReportToolbarComboBox ItemKind="SaveFormat" Width="70px"> <elements> <dx:ListElement Value="pdf" /> <dx:ListElement Value="xls" /> <dx:ListElement Value="xlsx" /> <dx:ListElement Value="rtf" /> <dx:ListElement Value="mht" /> <dx:ListElement Value="html" /> <dx:ListElement Value="txt" /> <dx:ListElement Value="csv" /> <dx:ListElement Value="png" /> </elements> </dx:ReportToolbarComboBox> </Items> <styles> <LabelStyle><Margins MarginLeft='3px' MarginRight='3px' /></LabelStyle> </styles> </dx:ReportToolbar> <dx:ReportViewer ID="ReportViewer1" runat="server"> </dx:ReportViewer>
前台代碼

1 protected void Page_Load(object sender, EventArgs e) 2 { 3 DataSet ds=new Controller().GetMasterDetailData(); 4 5 DataColumn masterColumn=ds.Tables["Master"].Columns["ID"]; 6 DataColumn detailColumn=ds.Tables["Detail"].Columns["部門ID"]; 7 8 DataRelation relation = new DataRelation("relation1",masterColumn,detailColumn); 9 ds.Relations.Add(relation); 10 11 XtraReport xpr = XtraReport.FromFile(Server.MapPath("~") + "dept_and_users.repx", true); 12 13 GroupField gf = new GroupField("ID", XRColumnSortOrder.Ascending); 14 ((GroupHeaderBand)(xpr.FindControl("GroupHeader1", true))).GroupFields.Add(gf); 15 16 xpr.DataMember = "Master"; 17 xpr.DataSource = ds; 18 19 20 21 ((DetailBand)(xpr.FindControl("Detail1", true))).Report.DataMember = "relation1"; 22 ((DetailBand)(xpr.FindControl("Detail1", true))).Report.DataSource = ds; 23 24 //xpr.FindControl("tableCell10", true).DataBindings.Add("Text", ds, "relation1.編號"); 25 //xpr.FindControl("tableCell11", true).DataBindings.Add("Text", ds, "relation1.姓名"); 26 //xpr.FindControl("tableCell12", true).DataBindings.Add("Text", ds, "relation1.添加時間"); 27 28 XRTableCellCollection cc = ((XRTable)(xpr.FindControl("table4", true))).Rows[0].Cells; 29 BindingFields(ds,cc,"relation."); 30 xpr.CreateDocument(); 31 ReportViewer1.Report = xpr; 32 ReportViewer1.DataBind(); 33 } 34 35 private void BindingFields(DataSet ds, XRTableCellCollection cc,string relationName) 36 { 37 for (int i = 0; i < ds.Tables["Detail"].Columns.Count-1; i++) 38 { 39 cc[i].DataBindings.Add("Text", ds, relationName + ds.Tables["Detail"].Columns[i].Caption); 40 } 41 }
這里需要注意的幾點,這幾點都是必需的:1、設定dataset中表與表之間的關系
1 DataColumn masterColumn=ds.Tables["Master"].Columns["ID"]; 2 DataColumn detailColumn=ds.Tables["Detail"].Columns["部門ID"]; 3 4 DataRelation relation = new DataRelation("relation1",masterColumn,detailColumn); 5 ds.Relations.Add(relation);
2、設定groupheader的分組依據字段
1 GroupField gf = new GroupField("ID", XRColumnSortOrder.Ascending); 2 ((GroupHeaderBand)(xpr.FindControl("GroupHeader1", true))).GroupFields.Add(gf);
3、成員綁定
1 xpr.DataMember = "Master"; 2 xpr.DataSource = ds; 3 ((DetailBand)(xpr.FindControl("Detail1", true))).Report.DataMember = "relation1"; 4 ((DetailBand)(xpr.FindControl("Detail1", true))).Report.DataSource = ds;
對於從表的數據綁定,都需要使用DataBindings屬性,所以,下面的代碼要這樣寫:
1 XRTableCellCollection cc = ((XRTable)(xpr.FindControl("table4", true))).Rows[0].Cells; 2 BindingFields(ds,cc,"relation.");
1 private void BindingFields(DataSet ds, XRTableCellCollection cc,string relationName) 2 { 3 for (int i = 0; i < ds.Tables["Detail"].Columns.Count-1; i++) 4 { 5 cc[i].DataBindings.Add("Text", ds, relationName + ds.Tables["Detail"].Columns[i].Caption); 6 } 7 }
上面就是從報表設計器設計報表,從代碼中調用報表的全部內容。當然還有直接在VS當中創建報表,這種方式和上面的操作大同小異,而且網上的代碼也很多,這里就不再介紹了。還有一種方式就是運行時創建報表,這樣的好處是,在報表表頭、表尾大體相同的情況下,可以省下很大一部分時間。園子里這樣的文章不少,也不乏寫的好的,大家都找找吧。