XtraReports报表高级用法 ——DevE×press For VS.NET高级技巧系列(六) 孥福红 摘 要:XtraReports是开发的新一代适用于Windows.NET和ASP.NET开发的控件。XtraReports 组件可以整合于Visual Studio IDE之中,带来更高的动作效率,同时,对于应用软件和网站报表 发布它具有更大的灵活性。 关键词:DevExpress控件;XtraReports Suite高级用法;XtraPivotGridControl技巧;统计分析灵活 打印:自动报表 开发环境:VS2010 C#,Access,DevExpress控件包 件、以及其他一些相关的控件,之后对XrPivotGrid控件设置 10.2.5。 一个DataSource用于指定报表的数据来源。如图1所示。 示例软件运行环境:.Netframework2.0,Windows XP/ Windows2003/Windows7/Access 2003。 运行示例:解压缩。运行DevControlpractice.exe,点击 “数据挖掘分析”, “查询”之后随意拖拉字段到需要的地方, 最后点击“打印图表”按钮,即可看到报表。 XtraRport Suit控件包包含了许多相关的打印控件:BarCode, CheckBo ̄Label Line,PageBreak,Pagelnfo,PaneL PictureBox, RichTextBox,Table, ZipCode。XrPivotGrid, and SubRepo ̄. XtraReports还允许在一份报表中同时引用第三方控件(图表,栅 格等等)一就像它们出现在Windows系统的窗体中的情形一样。 图1报表设计器 Grid控件进行字段的增加和相关属性 一般而言,当创作报表后.需要花费很多精力来排列行或 之后,需要对Xpivot者控件。为了创作列表报表的样式.不得不处理行和控件的形 设置,如图2所示,包括FieldName(报表要显示的数据列名 状.而这些与表格并无关联。因此只能撤销掉XtraReports控 称),Area(数据列的显示位置,包括数据列区域ColumnArea, 件,而没有其他选择办法。甚至在完成了所有这些之后,不可 行区域RowArea和数据区域DataArea3项),Caption(数据列 避免地有人会叫“请在左边添加更多列”,这时你不得不全部 的标题)3个属性是必须设置的。如图3所示。 重新开始。费时费力不说,而且不能满足不同用户的不同需 求,使得软件的适用性大大降低,严重损伤产品的品级。 使用XtraReports表格控件的高级用法来应对这种需求.就 不会发生这些情况了.因为它会带来类似于Word表格的方式一 样,使用表格控件,无须再进行重新位置定位了。因为客户只 管随意拖拉他们需要的数据列,所见即所得。根本无需在软件 中去进行任何设定,一切都由最终的操作者来决定。这样就完 全满足了客户的需要,软件也就能游刃有余地处理客户的各种 图2 XrpivotGrid控件属性 图3字段设计器 打印需要,同时也大大减轻了开发工作的工作量,使得有更多 进行了上述的设计以后,一个交叉报表就基本完成了。 的精力和时间用来处理其他的事情。 如果客户提出任何的调整意见,比如字段顺序的调整.或 者字段名称的调整等诸如此类的问题,那么、上述的整个设计 1 传统的手工交叉报表 开发过程就必须逐一重新来,之后再重新编译和发布程序,费 要开发一个交叉报表,通常会需要先建立一个XtraReports 时费力且给人一种“软件很不好用”的印象。下面的办法可以 类,并在设计界面加报表头带区、明细带区、XrPivotGrid控 避免这种情况。 蚺 一一 ………一………… …… ……………… ……………… 实用第一 智慧密集 h ^ … _ H H 自 … … 2 开发思路 通过上面讲到的交叉报表开发过程.不难发现:要做一 个交叉报表,其实大致需要做这样几个步骤: (1)创建XrPivotGrid控件并设置DataSouce属性。 (2)创建需要显示的数据列并设置显示名称、显示位置、 显示风格等属性。 (3)显示报表。 那么,是否可以用代码来自动完成这些工作呢?答案是肯 定的。 2.1 创建报表以及报表中常用的各个带区 这个环节相信熟悉C群开发的朋友都并不陌生.只是新建 一些类的实例并设置一些常规属性罢了。具体来说包括: 新建报表实例:XtraReport rep=new XtraReport 0。 设置报表的纸张类型:rep.PaperKind=System.Drawing. Printing.PaperKind.A4。 是否横向打印:rep.Landscape=true。 创建报表的报表头:ReDortHeaderBand reportHeader=new ReportHeaderBand 0。 创建报表的报表尾:ReportFooterBand reportFooter=new ReportFooterBand 0。 创建报表的页头:PageHeaderBand pageHeader=new PageHeaderBand 0。 创建报表的页尾:PageFooterBand pageFoot=new PageFooterBand 0。 2.2解析XtraPivotGrid控件的字段设置并解析成 DataTable 要实现客户随意拖拉字段顺序。很显然报表自身是没法实 现的。因为面向用户的报表只能用于打印和预览而无法让用户 直接调整。可以在程序中设置一查询统计窗体用于数据的分析 统计.在该窗体中应用XtraPivotGrid控件,便于用户根据实际 的需要随时调整所需的数据以及各种字段的表现形式,当用户 需要按自己的心意打印时,只需要把用户调整好的状态打印下 来,就能实现上述的需要了。 当做好了这样的窗体以后.接下来需要做的只是打印出来 客户设置好的统计分析表格从而形成一张交叉报表即可。大体的 思路是:取得XtraPivotGrid控件的行字段(RowAreaColumns),列 字段(DataArearColumn),形成DataTable的列,之后,把表格 中相应的数据都作为一条记录读人到DataTable中去,这样就构 成了一个完整的待打印的数据集。拿到这个数据集以后,就可以 按照常规的方法来打印报表了。要取得用户最终拖拉的结果,最 好的办法莫过于把XtraPivotGrid控件直接传递给报表构建类了。 XtraPivotGrid控件中显示的数据.来自于ColumnAewa and RowArea的字段,因此只要从这个控件中取出符合这个条件的 i52 妇20 12.撞砖09与雏 数据,并把它们添加到DataTable中即可。代码如下: ///<summary> ///构建数据集DataTable,填充数据列: ///</summary> ///<param name=”pivot”></param> llI<param name= dataTablel ></param> private static void FillDatasetCotumns(PjvOtGridCOntrOI pivot,DataTable dataTable1) { ∥注意此方法、用于添加各个列:增加CoiumnAewa //and RowArea的字段即可: //dataTable1.Columns.Add(“RowFields ,typeof(string)); string tempColumnText:““: List<PivOtGridFieId> fieldslnColumnArea = GetFieIdsInArea(pjvot,PivotArea.RowArea);// ̄得行字段列表; for(int l-O i<fieldslnCotumnArea.Count;i++) { dataTable1.Columns.Add(fieldslnColumnArea 【_】.ToString0,typeof(o bject)): } fieldslnColumnArea:GetFieldslnArea(pivot, PivotArea ColumnArea);//J ̄得列字段列表 for(int i=O:I<pivot.Cells.ColumnCount;i++) { PivOtCellEVentArgs pcea=pivot.Cells.GetCelllnfo(i,O): tempColumnText= ”: if(pcea.ColumnValueType=:PivotGridValueType.Value) { foreach(PivotGridField field in fieldslnColumnArea) tempColumnText+=pcea.GetFieldValue (field) ToString0+ I";//add formatting if it's necessary tempColumnText=tempColumnText.Remove (tempColumnText.Length一3,3) ,/从列字段中获取到数据列 ,/的列头信息并添加到DataTable中。 dataTable1.Columns.Add(tempColumnText, typeof(decima1)): tempColumnText=““: ) else { if(pcea.ColumnValueType ToString()=--.”GrandTotal ) { dataTablel。ColumnS.Add(”合计 ,typeof(decima1)); ) else dataTable1.Columns.Add{pcea.ColumnValueType. ToStringO,typeof(object)); ) } trv { //dataTable1.Columns.Remove(“ID“): ) catch() ) 经过代码处理。就把XrtaPivotGrid控件中所有的数据列组 织到了一个可操控的DataTable中,接下来需要做的是把具体 的数据添加到Datatable中去。代码如下: ///<summary> /,/填充数据集数据 ///</summary> ///<param name=“pivot“></param> ///<param name= dataTablel”></Daram> private static void F川DatasetE×tracted(PivOtGridCOntrOI pivot,DataTable dataTable 1) ( List<object>rowvalues=new List<object>0; string tempRowText=”“: List <PivOtGridFieId > fieldslnRowArea = GetFjeldsInArea vot,PivotArea.RowArea); for(int i=O:i<pivot.Cells RowCount;i++) { ∥注意此方法、用于取得各个PivotG rid单元格的值; PivotCellEventArgs pcea=pivot.Cells.GetCelllnfo(0,i): rowvalues.Clear(); //" ̄Du左侧行字段列表的单元格数据到DataTable的行中: if(pcea.RowValueType==PivOtGridValueType.Value) { foreach(PivOtGr1dFie{d item in fieldslnRowArea) trv { if(item.FieldName!=”ID“) { tempRowText=…+pcea.GetFieldValue(item).ToStringO;// +”I“;//add formatting jf it's necessary rowvalues Add(tempRowText); ) else rowvalues.Add( ): ) catch//异常只有一种可能:分组小计一栏中, ∥列名字段的值被合并无法显示,所以取不到正确的控件,这个 //时候赋值为空即可 { rowvalues.Add(nul1); ) ) else { tempRowText:pcea.RowValueType.ToString0; rowvalues.Clear(); for(int a=O:a<fieldslnRowArea.Count;a+十) { rowvalues.Add( ) ) } //添加数据区域的单元格数据到datatable中去。 for(int j=O:j<pivot.Cells.ColumnCount;j++) ( pcea=pivot.Cells.GetCelllnfo(j,i): if(pcea.Value!=nul1) rowvatues.Add(pcea.Value): else rowvalues.Add(DBNulI.Value); ) dataTable1.Rows.Add(rowvalues ToArray0); ) ) 有了这些代码,就完全拿到了待打印的全部数据,接下来 需要处理的就是打印的各个数据列的宽度了。 因为要实现“所见即所得”的打印效果.所以,取得的 DataTable各个数据列和数据完全以用户在界面上拖拉的位置 为依据进行排列的,那么,在打印到报表上的时候,依然遵从 这一规则:按照DataTable列中每一列的顺序和宽度,依次在 报表中打印出来即可。其基本原理为:在报表中打印DataTable 的每一列:每列的打印宽度以用户在界面上拖拉的宽度为基 数.再依据屏幕表格总宽度和报表纸张宽度的比例为系数进 行缩放,这样便实现按界面来打印报表。但这样做有一个不 足:当列数过多的时候,容易导致每一列的宽度过小,从而导 致报表很不美观。解决的办法是对于RowFiedArear区域(行 区域)的字段,进行宽度自适应的处理:而对于数据区域 (DataArea)的字段,则指定一个固定的宽度进行打印。这样 就实现了完全的自适应打印模式了。具体实现逻辑,请参阅代 码中的方法: private List<int>GetColumnsBest FitAsPivotGridWidth(XtraReport rep,DataTable dataTable, Font font,PivOtGridContr0I pivot) 最后,需要做的就是在报表中新建两个表格:用于显示数据 列头文字的表格tableI-leader和用于显示明细数据的表格 tableDetail,然后逐一把每一列的数据添加到这两个表格中即可。 public static void AddCellsToTables《XRTable header, XRTable detail,DataColumn dc,int columnWidth,booI isFirstColumnInTable) 到此为止,自动报表完全实现了。最终用户可以在软件运 行的时候,根据实际需要随意拖拉每一个数据列到需要的地方 进行统计分析,然后点击打印按钮就可以打印出一模一样的报 表。这样,就能满足相同的数据,不同用户可以随意打印自己 需要的报表.从而避免了软件开发人员需要为此重复开发多种 报表的麻烦.极大地提高了软件的灵活性,减少了程序员的劳 动强度。 ………… ……… …… …………… …… ’J … … 实用第一 智慧密集 … … … … 3 自动交叉报表的使用样例 如图4,图5所示。 图4 哪 无端代码的髓意鲢计分析撤袭 嚣 懈 #晰 黼 帆 峨 呲 鹕q 辄 Ij 地 i{ “i ∞ J * i鞴 一一…一…一一'硪 一…………… …一…一……一卞一 而 {皇二 E孺…一一一………i二 二二二二 二二z 二 二二二 一…一………~~哺解_二 二 £ 二 二二二二二 二空 凰 聒 …一’一一1一 丽 图5 接下来。在这个界面中,拖拉更多的字段到统计表格中形 成更为复杂的统计分析数据,然后点击打印按钮查看一下自动 生成的报表的样例.如图6.图7所示。 骢 § ; .曼 枷 骂 穗骢 嚣蟪| s I 黑 一臻 镪髓 肇 鹊獭 . 燃 藏 ∞ 硼 一 … l i j; 嚣 囊一 i鼍t 淼 恐蒜乏l 戈衙代码的随意统计分拼报袭 日 …l一 ∞ 删 蚂 z l{1 』 图7 可以看到界面中的数据,报表中也全部都打印出来了。而 实现这个,只是模拟最终用户进行了简单的拖拉而已,并没有 对程序进行一个字符的改动。 4 自动交叉报表类代码 using System; using System.Collections.Generic; us ing System.Data; usi‘ng System.Drawing; us。ing System.Windows.FOrms: us‘ing DevExpress.XtraRepo ̄s.UI; us‘ing DevExpress.XtraPivotGrid; us’ing DevExpress.XtraEditors; namespace DevControlpractice.LFH.Function { ///<summary> ,//报表类型 ///<Isummary> public enum RepOrtGeneratOr pe { SinglePage, FixedColumnWidth, BestFitColumns, FitAsPivotGrid, ) public class LFH—Piv0tRepOrtGeneratOr { #region自定义属性 private PivOtGridCOntrOl pivot; ///<summary> ///PivotGridControl控件名称 ///<Isummary> public PivotGridControl Pivot { get{return pivot;} setf pivot:value;) } private ReportGeneratorType kind=ReDOrtGeneratOr Type.FitAsPivotGrid; ///<summary> ///ReportGenerator_rype.SinglePage,单行打印(无限纸张 ///宽度) ///ReportGenerator.rype.FixedColumnWidth固定列宽 ///(允许自动换行,但每一列的宽度均相等且为指定的固定值) ///.ReportGeneratorType.BestFitColumns自适应纸张宽 ///度(按PivotGrid控件运行期间的各个数据列的宽度比例在纸 ///张上打印) ///</summary> public ReportGeneratorrype Kind { get{return kind;} set{kind=value;) ) private int columnWidth=l 00; ///<summary> ///默认每一个列的宽度 ///</summarv> public int ColumnWidth { get{return columnWidth;) set{columnWidth=value;) ) private bool repeatRowHeader=true; ///<summary> /,/是否每一页均打印标题栏。默认true ///<Isummary> public bool RepeatRowHeader f get{return repeatRowHeader;) set{repeatRowHeader=value;) } private System.Drawing.Printing.PaperKind paper= System.Drawing.Printing.PaperKind.A4; ///<summary> ///纸张类型 默认System.Drawing.Printing.PaperKind.A4 ///</sut ̄mary> public System Drawing.Printing.PaperKind Paper { get{return paper;} set{paper=value;) ) private boolisDataCellBFitColumWidth=false; —///<summary> ///FitAsPivotGrid模式下、DataCell列宽是否固定《若不 ,//固定、则参与全部宽度分配,但列数较多时会换行导致表格不 ,//美观) ///</summary> public bool IsDataCellBFitColumWidth { get{return—isDataCellBFitColumWidth;) set{一isDataCellBFitColumWidth:value;) ) private bool isPaperLandScape=true; ///<summary> ///是否横向打印(true、false)默认真 ///</summary> public bool IsPaperLandScape { get{return isPaperLandScape;) set{isPaperLandScape=value;) } private string—sReportTitle=“未定义报表” ///<summary> ///报表标题 ///</summary> public string SReportTitle { get{return_sReportTitle;) set(一sReportTitte:value;J ) private string—sReportDate=“” ///<summary> /,/报表数据起始目期(字符串:2011-09-01到2011~ m、Q一01、 ///</summary> public string SReportDate { get{return—sReportDate;) set(_sReportDate:value;l } private stringsRepOrtPintDate: ‘; —///<summary > ///报表打印日期:系统当前日期; ///<isummary> public string SReDOrtPintDate { get(return—sReportPintDate:) set f—sReportPintDate:value;) ) private List<int>一columnsWidth=null; ///<summary> ///字段宽度列表(指定每个行字段的宽度即可,不指定的 //,按ColumnWidth,但若选择了全屏自适应模式BestFitColu ///mns、则自动计算宽度) ///<isummary> public List<int>ColumnsWidth { get{return_columnsWidth;) set{一columnsWidth=value;) ) #endregion ///<summary> /,/构造报表 ///</summary> //,<retums></retums> public XtraReport initRep() f XtraReport rep=new XtraReportO; rep.PaperKind=Paper;//System.Drawing.Printing. /PaperKind.A4; rep.Landscape=isPaperLandScape;//true; rep.DataSource=F_llDataset(PivOt):/,DtPrint; rep.DataMember = ((DataSet)rep.DataSource). Tables[O].TableName;//DtPrint.TableName; lnItBands(rep) InitStyles(rep); InitDeta IsBasedo九×RTabIelrep,Kind,ColumnWidth, RepeatRowHeader,Pivot); return rep; } ///<summary> ///根据传人的PivotGridcontrol构造报表数据集 脑瓣 实用第 智慧密集 ///<Isumma ̄> ///<param name= pivot >待打印的PivotG contro}</ ///param> ///<returns></returns> public static DataSet F.IlDataset(PivotG rjdCOntrOI pivot) ( DataSet dataSetl=lFlew DataSetO; dataSet1.DataSetName=。。PivotGridColumns“: DataTable dataTablel=ilFew DataTable0; dataSet1.Tables.Add(dataTable1): FillDatasetColumns(pivot,dataTable1): FillDatasetExtracted(pivot,dataTable1): return dataSetl: ) #region PreparingDataSet ///<summary> ///填充数据集数据 ///</summaw> ///<param name=“pivot“></param> ///<param name=”dataTablel“></param> private static void IDatasetExtractedIPivotGridControl pivot,DataTabte dataTable1) { List<object>rowvalues=new List<object>O: string tempRowText= : List <PjvotG rldFleki > fieldslnRowArea = GetFieldslnArea(pivot,PivotArea.RowArea); for(int j=O: <pivot.Cells.RowCount;i++) { ,//注意这里,改写此方法、用于添加各个列:现有方 ,//法是组装各个字段的值; PivotCellEventArgs pcea=pivot.Cells.GetCelllnfo(O, rowvalues.Clear(); if(pcea.RowValueType=:PivotGridValueType.Value) ( foreach(PivotGridFieId item in}fieldslnRowArea) try { if《item FieldName!=“ID”) { tempRowText=” +pcea.GetFieldValue(item) ToStringO;//4-”{“;//add formatting if it's necessary rowvalues.Add(tempRowText); } else rowvalues.Add( ): ) catch//异常只有一种可能:分组小计一栏中, //列名字段的值被合并无法显示,所以取不到正确的控件,这个 寸候赋值为空即可 { rowvalues.Add(nul1); l5 箍 与雄 ) //tempRowText=tempRowText.Remove //(tempRowText.Length一3,3): ) else { tempRowText=pcea.RowValueType.ToString0; rowvalues.Clear(); for(int a=0:a<fieldslnRowArea.Count;a++) { rowvalues.Add(” ) } ) for《int j=0:j<pivot.Cells.ColumnCount;j十+) { pcea=pivot.Cells.GetCelllnfo(j,i) If(pcea。Value!=nul1) rowvalues.Add(pcea.Value); else rowvalues.Add(DBNul1.Value); } dataTable1.Rows.Add(rowvalues.ToArrayO); ) ) ///<summa ̄> ///构建数据集DataTable,填充数据列; ///<Isumma ̄> ///<param name=“pivot”></Daram> ///<param name=”dataTable1”></param> private static void FiIIDatasetColumns(PivotGridControl pivot DataTable dataTable1) { //注意这里,改写此方法、用于添加各个列;增加 lfColumnAewa and RowArea的字段即可: //dataTable1.Columns.Add( RowFields“ typeof(string)); string tempColumnText= : List <PivOtGndFie1d > fieldslnColumnArea = GetFieldsInArea《pivOt,PivotArea.RowArea); for(int i=O:i<fieldslnColumnArea.Count;i++) { dataTable1.Columns.Add(fieldslnColumnArea 【i].ToStringO,typeof(object)); ) fietdslnColumnArea = GetFie}dsInArea (pivot, PivotArea.ColumnArea); for(int i=0:i<pivot.Cells.ColumnCount;i++) { PivotCellEventArgs pcea:pivot.Cells.GetCelllnfo(i,0) tempColumnText= : if(pcea.ColumnValueType::PivotGridValueType.Value) { foreach(PivotGridField field in fieldslnColumnArea) tempColumnText+=pcea.GetFieldValue (field).ToString0-t-”l”;//add formatting if it's necessary tempColumnText=tempColumnText.Remove (tempColumnText.Length一3,3): dataTabte1.Columns.Add(tempColumnText,typeof(decima1)); tempColumnText=“”: } else { if(pcea.ColumnValueType.ToString0==“GrandTotal“) { dataTable1.Columns.Add(”合计 ,typeof(decima1)); ) else dataTable1.Columns.Add(pcea.ColumnValueType. ToString0,typeof(object)); ) } trv { //dataTable1.Columns.Remove(“ID”): ) catch{) } ///<summary> ///获取 votGridControI控件列域和值域的字段名称列表: ///</summary> ///<param name=“pivot。’></param> ///<param name=”area“></Daram> //_/<returns></returns> private static List<PivotGridField>GetFieldslnArea (Piv0tGridControI pivot,PivotArea area) { List<PivotG rjdF.eId>fields=new List<Piv0tGridField>(): int iMaxlndex=O: for(int i=O:i<pivot.Fields.Count;i+十) { //if{(pivot。Fields[i].Area!:PivotArea.DataArea) //&&(pivot.Fields[i].Area!=PivotArea.FilterArea)) if(pivot.Fields[i].Area==area) if(pivot.Fields[i].Arealndex>iMaxlndex)iMaxlndex=i: ) for(int i;O:i<=iMaxlndex;i++) { foreach(PivotGridField item in pivot.Fields) try { if《(item.Arealndex==i)&&(item.Area==area)) { fields.Add(item); ) } catch() ) return fields; } #endregion ///<summarv> /,/初始化报表的带状区域(报表头、报表尾等) ///</summary> ///<param name=”rep。。></param> public void InitBands(×traRepOrt rep) { //Create bands ReportHeaderBand reportHeader=new ReportHeaderBand(): reportHeader.HeightF=75F; reportHeader.WidthF=《rep.PageWidth一(rep.Margins. Left-I-rep Margins.Right)); reportHeader.Name:”reportHeader“: XRLabel xrTitel=new XRLabel(); xrTite1.LocationFloat=new DevExpress.Utils.PointFIoat(OF,0F): xrTite1.Font=new System.Drawing.Font(”宋体”, 1 8F,System.Drawing.FontStyle.Bold); xrTite1.Name= xrTitel。‘: xrTite1.Padding=new DevExpress.XtraPrinting.Paddinglnfo (2,2,O,0,100F); //xrTite1 SizeF=new System.Drawing SizeF《660.7498F, 52.1 6667F); xrTite1.WidthF=(rep.PageWidth一(rep.Margins.Left -I-rep.Margins.Right)); xrTite1.StylePriority.UseFont=false; xrTite1.StylePriority.UseTextAlignment=false; xrTite1.Text=SReportTitle;//”资金收支日报表” xrTite1.TextAlignment=DevExpress.XtraPrinting. TextAlignment.MiddleCenter; XRLabel xrReDOrt PrintDate=new XRLabel0; xrReDOrtPrintDate.LocationFIoat=new DevExpress. Utils.P0intFlOat(741.91 66F 50.33334F); ×rRep0rtPnntDate.Name=“xrRepOrtP rintDate : xrReDOrtPrjntDate.Padding=new DevExpress. XtraPrinting.Paddinglnfo(2,2,0 0,1 00F); xrReDOrtPrintDate.SizeF=new System.Drawing. SizeF(227.0833F,23F); xrReDOrtPrintDate.StylePriority.UseTextAlignment=false; xrReportPrintDate.Text=SReportPintDate:,/“xrLabel3 : f(SRepOrtPintDate==“”) xrReponPrintDate.Text=“打印日期:”-I-System. DateTime Now.ToString(”yyyy—MM—dd”): xrReDOrtPrintDate.TextAlignment=DevExpress. XtraPrinting.TextAlignment.MiddleRight; || //xrReportDate |l XRLabel xrReportDate:new XRLabel0; //1 印, 实用第 一 慧密集 xrReportDate.Font=new System.Drawing.Font(”宋体”,9F): xrReportDate LocationFIoat=new DevExpress. Utils.POintFlOat(0F,50F): xrReportDate.Name=。。xrReportDate。’: xrReportDate.Padding=new DevExpress. XtraPrinting.Paddinglnfo(2,2,0,0,1 00F); xrRepOrtDateSizeF=newSysten^LDrawingSizeF(346875F,23F); xrReportDate.StylePriority.UseFont=false; xrReportDate.StylePriodty.UseTextAlignment=false; xrReportDate.Text=SRepOrtDate://”xrReportDate“: xrReportDate.TextAlignment=DevExpress. XtraPrinting.TextAlignment.MiddleLeft; reportHeader.Controls.AddRange(new DevExpress. XtraReports.UI.XRControl[】{ xrTitel, ×rRepOrtPrintDate, ×rReportDate)): DetailBand detail=new DetailBand(): PageHeaderBand pageHeader=new PageHeaderBand(): ReportFOOterBand reportFooter=new RepOrcFOOterBand{): detail.Height=20; reportFooter.Height=380; pageHeader.Height=20; PageFooterBand pageFoot=new PageFooterBand(): DevExpress.XtraReports.UI.XRPagelnfo xrPagelnfol =new XRPagelnfo0; xrPagelnfo1.LocationFIoat=new DevExpress.Utils. PointFIOat(794.5002F,0F): xrPagelnfo1.Name=“xrPagelnfol”: xrPagelnfo1.Padding=new DevExpress.XtraPrinting Paddinglnfo(2,2,0,0,1 0OF); xrPagelnfo1.SizeF=new System.Drawing.SizeF(1 00F,23F); pageFoot.Controls.AddRange (new DevExpress. XtraReports.UI.XRControl[1{ xrPagelnfo1)): pageFoot.HeightF=39.58333F; pageFoot.Name=‘。ReportFooter“: //Place the bands onto a report rep.Bands.AddRange(new DevExpress.XtraReports.UI.Bandn {reportHeader,detail,pageHeader,pageFoot,reportFooter)); ) ///<summa ry> ///设置报表的显示风格: ///</summa ry> ///<param name=“rep”><,Daram> public static void InitStyles(XtraReport rep) { //Create different odd and even styles ×RCOntr0IStvIe oddStyle=new XRControlStyle0; XRControlStyle evenStyle=new XRControlStyle0; //Specify the odd style appearance oddStyte.BackColor=Color.LightBlue; oddStyle.StyteUsing.UseBackColor=true; oddStyle.StyleUsing.UseBorders=false; //oddStyle.Name:“OddSt ̄,le”: //Specify the even style appearance evenStyle.BackColor=Color.LightPink; evenStyle.StyteUsing.UseBackColor=true; evenStyle.StyleUsing.UseBorders=false; //evenStyle.Name=“EvenStyle”: ||Add styles to report s sty‘le sheet rep.StyleSheet.AddRange(new DevExpress. XtraReports.UI.XRControlStyle[】{oddStyle.evenStyle)): } ///<summary> ///构建报表明细数据所用的表格 ///<isummary> ///<param name= rep”></param> ///<param name=”kind“></param> ///<param name=”columnWidth“></param> ///<param name= repeatRowHeader ></param> ///<param name=”pivot”></Daram> public void InitDetailsBasedonXRTable(XtraReport rep, ReportGeneratorType kind,int columnWidth,bool repeatRow Header,PivOtGr dControI pivot) { if《!repeatRowHeader ll kind==ReportGenerator Tvpe.SinglePage) InitDetaiIsBasedon×RTableWithoutRepeatingRowHeader(rep. kind,columnWidth); else InitDetailsBasedonXRTableRepeatingRowHeader {rep,kind,columnWidth,pivot); } ///<summary > ///构建报表明细数据报表头(每页均打印报表头) ///</summary> ///<param name=“rep。。></param> ///<param name=“kind”></param> ///<param name=“columnWidth”></Daram> ///<param name=“pivot”></Daram> private void InitDetailsBasedOn×RTable RepeatingRowHeader(XtraReport rep,ReportGenerat0rTVpe kind,int columnWidth,PivotGridCOntrOl pivot) { Font font=new Font(”宋体“ 9.00f); DataTable dataTable=f(DataSet)rep.DataSource). TabIes【0l://Dt nt.,/ int prOcessedPage=O int usablePageWidth=rep.PageWidth—frep. Margins.Left 4-rep.Margins.Right); List<int>columnsWidth=null; if(ColumnsWidth!=nul1) columnsWidth=ColumnsWidth; eISe tableHeader.EndlnitO; tableDetail.Endlnit0; InitNewTablelnstancesAt《rep,font,out tableHeader,out { f(kind==ReportGeneratorType.FixedColumnWidth) columnsWidth=DefineColumnsWidth(columnWidth, dataTable.Columns.Count); tableDetail,new PointF(usablePageWidth processedPage,O】): tableHeader.Beginlnit0; else if(kind==ReportGeneratorType.FitAsPivotGrid) { columnsWidth==GetColumnsBestFitAsPivotGridWidth (rep,dataTable,font,pivot); ) else ( columnsWidth==new List<int>0; for(int a=O:a<dataTable.Columns.Count;a++) { int tempWidth0=GetColumnsBestFitWidth(dataTable, dataTable.Columns[a].Caption,font); columnsWidth.Add(tempWidth0); } ) ) XRTable tableHeader=null; XRTable tableDetaiI=null; InitNewTablelnstancesAt(rep,font,out tabteHeader, out tableDetail.new PointF(0,O)): tableHeader.Beginlnit0; tableDetail.Beginlnit0; trv ( int iColumns=dataTable.Columns.Count; int iLength=columnsWidth.Count; int iAdd=iColumns—-iLength; if(iAdd>0) { for(int j=O:j<iAdd;j++) { columnsWidth.Add(70); ) } ) catch() jnt i=1: AddCellsToTabtes(tableHeader,tableDetail, dataTable.Columns[0],columnsWidth[0],true); int remainingSpace=usablePageWidth—columnsWidth[0]; do { .f(columnsWidth[il>remainingSpace) { prOcessedPage++: tableHeader.WidthF=USablePageWidth—remainingSpace; tableDetail.WidthF=usablePageWidth—remainingSpace; tableDetail.Beginlnit0; AddCellsToTables(tableHeader,tableDeta dataTable.Columns[0],columnsWidth[0],true); remainingSpace=usablePageWidth—columnsWidth[0]; ) else { AddCellsToTables(tableHeader,tableDeta dataTable.Columns[i],columnsWidth[i],false); remainingSpace——=columnsWidth[i]; i++: ) ) while fi<columnsWidth.Count); tableHeader.W dthF:usablePageWidth—remainingSpace tableDetail.WjdthF=usablePageWidth—remainingSpace tableHeader.EndlnitO; tableDetail.Endlnit0; ) ///<summary> /,/添加表格单元格到表格中去用于显示数据 ///<Isummary> ///<param name=。‘header‘‘></param> ///<param name=‘‘detail。‘></param> ///<param name=“dc“></param> ///<param name=“columnWidth“></param> ///<param name=“isFirstColumnlnTable“></param> public static void AddCellsToTables(XRTable header, XRTable detail,DataColumn dc,int columnWidth,bool isFirstColumnlnTable) { XRTableCell headerCelI=new×RTableCelI(): headerCel1.Text=dc.Caption; header TextAlignment:DevExpress.XtraPrinting. TextAlignment.MiddleCenter; //header.Font.Bold=true; XRTableCell detailCelI=new XRTableCellO; detailCel1.DataBindings.Add(’‘Text”,null,dc.Caption); headerCel1.Width=columnWidth; detaiICel1.Width:columnWidth; if((dc.DataType) FullName=:”System.Decimal“) detailCel1.TextAlignment=DevExpress.XtraPrinting. TextAlignment.MiddleRight; if(isFirstColumnlnTable) { headerCel1.Borders=DevExpress.XtraPrinting. BorderSide.Left I DevExpress.XtraPrinting.BorderSide.Top I 实用第 智慧密集 DevExpress.XtraPrinting.BorderSide.Bottom; detailCel1.Borders=DevExpress.XtraPrinting.BorderSide. Left l DevExpress.XtraPrinting.BorderSide.Bottom; ) else ( headerCel1.Borders=DevExpress.XtraPrinting.BorderSide.All; detailCel1.Borders=DevExpress.XtraPrinting.Border Side.Left}DevExpress.XtraPrinting.BorderSide Right I DevEx press.XtraPrinting.BorderSide.Bottom; ) l|Place the cells into the corresponding tables header.Rows[O].Cells.Add(headerCe}}): detail.Rows[O].Cells.Add(detaiICel1): ) public static void InitNewTablelnstancesAt(XtraReport report,Font font,out XRTable header,out XRTable detail, 一Poi 一。 一ntF l ocation) { header=InitXRTable(font,false); detail=InitXRTable(font.true); header.LocationF=Iocation; detail.LocationF:location; XRTableRow headerRow=new XRTableRowO; header.Rows.Add(headerRow); XRTableRow detaiIRow=new XRTableRowO; detail.Rows.Add(detailRow); report.Bands【BandKind.PageHeader].Controls.Add(header); report.Bands【BandKind.Detail].Controls.Add(detail); ) ///<summary> ,,/初始化表格 ///</summa ry> ///<param name=“font”><,Daram> ///<param name=‘。withStyles ></param> //l/<returns></returns> private static XRTable InitXRTable (Font font,boo withStyles) { XRTable table=new XRTableO; table.Font=font; table.Height=20; |f(withStyles) { table.EvenStyleName=“EvenStyle“: table OddSt ̄rleName=。。OddStyle“: } return table; } ///<summary> ///定义列宽数组 ///<Isummary> :60 电脑壤程技巧2012.O9 与罐熬 ///<param name= columnWidth ></Daram> ///<param name=“count“></Daram> ///<returns></returns> private static List<int>DefineColumnsWidth(int columnWidth,int count) { List<int>columnsWidth=new List<int>O; for lint i:0:i<count;i++) columnsWidth.Add(columnWidth); return columnsWidth; ) llj<summa > ///构建报表明细数据报表头(只在第一页打印报表头) ///</summary> ///<param name=“rep ></param> ///<param name=“kind“></param> ///<param name=”co!umnWidth。‘></param> static void InitDetailsBasedonXRTableWithoutRepeating RowHeader(XtraReport rep,ReportGeneratorType kind,int columnWidth) { Font font=new Font(”Tahoma” 9.75f); DataSet ds=((DataSet)rep.DataSource); 1nt colCount=ds.Tables[O].Columns.Count; int cotWidth=0: XRTable tableHeader:null; XRTable tableDetaiI=null; InitNewTablelnstancesAt(rep,font,out tableHeader, out tableDetail,new PointF(O,0)): List<int>columnsWidth=null; switch《kind) { case ReportGene阳tor_rype.FixedColumnWidth: colWidth=columnWidth; tableHeader.Width:columnWidth colCount; tableDetail.Width=columnWidth colCount; break; case ReportGeneratorType.BestFitColumns: columnsWidth=GetColumnsBestFitWidth(ds.Tables[O],font); colWidth=0: tableHeader.Width=GetTotalWidth(columnsWidth); tableDetail.Width=tableHeader.Width; break; case ReportGeneratorType.FitAsPivotGrid: tableHeader.Width=(rep.PageWidth一(rep Margins.Left+rep.Margins.Right)); tableDetail.Width=(rep.PageWidth一(rep Margins.Left+rep.Margins.Right)); break; default: colWidth=(rep.PageWidth~{rep.Margins Left-I-rep.Margins.Right))/colCount; tableHeader.Width :(rep.PageWidth一(rep Margins.Left+rep.Margins.Right)); tableDetail.Width =(rep.PageWidth一(rep Margins.Left 4-rep.Margins.Right)); break; } tableHeader.Beginlnit0; tableDetail.Beginlnit0; //Create table cells,fill the header cells with text, //bind the cells to data for(int i=0:i<colCount;i++) { AddCel JsTo丁abIes(tableHeader,tableDetail,ds.Tables【0】. Columns kind==ReportGeneratorType.BestFitColumns 7 columnsWidth[i】:coIWidth,i==0 7 true:false); ) tableDetail.Endlnit0; tableHeader.Endlnit0; //Place the table onto a report S Detail band ) ///<summary> /,/得到所有字段总宽度 ///</summa ry> ///<param name=”columnsWidth。。></param> ,//<retums></retums> private static int GetTotalWidth(List<int>columnsWidth) { int i=0: foreach(int coIWidth in columnsWidth) i+=colWidth; return i: ) ///<summary> ///得到自适应宽度模式下各个报表列的宽度列表 ///</summary> ///<param name=“rep”></Daram> ///<param name=”dataTable“><,Daram> ///<param name= font“></Daram> ///<param name=。‘pivot”></param> ///<retums></returns> private List<int>GetColumnsBestFitAsPivotGridWidth (XtraReport rep,DataTable dataTable,Font font,PivotGrid Control pivot) { List<int>optimalColumnWidth=new List<int>0; float maxWidth=O: float tempWidth=0: float iAIIWidth=(rep.PageWidth一(rep.Margins.Left -4rep.Margins.Right)); for(int i=O:i<pivot.Fields.Count;i++) ∥if((pivot.Fields[i].Area!:PivotArea.DataArea) //&&(pivot Fields[i].Area!=PivotArea.FilterArea)J if((pivot.Fields[i].Area==PivotArea.RowArea)) tempW idth:tempWidth 4-pivot,Fields[i],Width; for《int i=O:i<pivot.Cells.ColumnCount;i++) { PivotCellEventArgs pcea=pivot.Cells.GetCelllnfo(i.O): if(pcea.ColumnValueType==PivotGridValueType.Value) f tempWidth=tempWidth 4-pcea.ColumnField.Width; } else { if(pcea.ColumnValueType.ToString()=:”GrandTotal”) ( tempWidth=tempWidth 4-pcea.Bounds.Width; ) ) ) float iBL=tempWidth/iAtlWidth; ,/这里做一个调整:若行字段的宽度超过纸宽的一半、 //贝U按特定比例来计算比例。 for(int j=O j<dataTable Columns.Count;j+十) { for(int i=0 i<pivot.Fields.Count;i++) { . if{IsDataCellBFitColumWidth)//l ̄适应数据列宽度 ( if 《(pivot.Fields【_】_Area!:PivotArea DataArea)&&《pivot Fieldsli】.Area!=PivotArea.FilterArea)) //if I(pivot.Fields[i].Area==PivotArea. //RowArea)lI(pivot.Fields[i].Area==PivotArea.RowArea)l l//(pivot.Fields[i].Area==PivotArea.DataArea)) ( if(pivot.Fields Caption=:dataTable Columns[j].ColumnName) { int iWidth=Convert.Tolnt32((pivot.Fields[i].Width/iB L)): maxWidth=maxWidth 4-iWidth; tempWidth=tempWidth 4-pivot.Fields[i]Width; jWidth:Convert.ToInt32(×RConvert.Convert(iWidth GraphicsUnit.Pixel,GraphicsUnit.Inch) 100 4-”: optimalColumnWidth.Add(iWidth); } ) ) else { ∥if((pivot.Fields[i].Area I=PivotArea. //DataArea)&&(pivot.Fields[i].Area!=PivotArea.FilterArea)) if ((pivot.Fields Area==PivotArea RowArea)ll(pivot.Fields【i].Area==PivotArea.RowArea)I (pivot.Fields[i].Area==PivotArea.DataArea)) ( 实用第 智慧密集 if(pivot.FieldsⅢ.Caption==dataTable。 Columns[j].ColumnName) { int{Width=Convert,Tolnt32((pivot.Fieids[i ̄.W dth f B L11: maxWidth=maxWidth 4-iWidth; tempWidth=tempWidth-I-pivot.Fields[i].Width; iWidth = Convert.Tolnt32 fXRConvert.Convert (iWidth,GraphicsUnit.Pixel,GraphicsUnit.Inch) 100+1): optimalCotumnWidth.Add(iWidth); ) ) ) ) ) f{lsDataCel1BFitCOlumWidth) { #region自适应数据歹Ij宽度 List<PivOtGridField> fieldslnColumnArea = GetF eldsInArea(Divot,PivotArea.RowArea); fieldslnColumnArea = GetFieldsInArea(pivot, PivotArea.ColumnArea); for(int i:O:i<pivot.Cells.ColumnCount;i+十) { PivOtCellEventArgs pcea=pivot.Ceils.GetCelllnfo(i,O): string tempColumnText= : if(pcea ColumnValueType==PivotGridValueType.Value) { foreach(PivotG rjdField field in fieldslnColumnArea) tempColumnText+=pcea.GetFieldValue (field).ToString();//add formatting if it's necessary //tempColumnText=tempColumnText. Remove(tempColumnText); int tempWidth0=GetColumnsBestFitWidth(dataTable, tempColumnText,font); optimalColumnWidth.Add(tempWidth0); ) else ( if(pcea.ColumnValueType.ToString()== GrandTotal“) { int tempWidth0=GetColumnsBestFitWidth(dataTable,“ 合计“,font); optimalColumnWidth.Add(tempWidth0); } ) ) #endregion ) else { #region非自适应数据列宽度 for(int i=0:i<pivot.Cells.ColumnCount;i++) 62_ 2012.09 电麓缡栏技巧与 壤 b { PivotCellEventArgs pcea=pivot.Cells.GetCelllnfo(i,O): if{pcea.ColumnValueType==PivotGridValueType.Value) { optimalColumnWidth.Add(Convert.ToI nt32 ((pcea.ColumnField.Width/iBL))): maxWidth=maxWidth-t-Convert.ToInt32 ((pcea.ColumnField.Width/iBL)): tempWidth=tempWidth+pivot.Fields[i].Width; ) else ( if《pcea.ColumnValueType ToString()==”GrandTotal”) { {nt iColumns=dataTable.Columns.Count; int iLength=optimalColumnWidth.Count; int iAdd=iColumns——iLength; float iLastWidth= AllWidth—maxWidth; float;ColumnWidth=iLastWidth,iAdd; int iColumnwide = Convert.TOI nt32 (System.Math.Truncate(iLastWidth)); int iLastColumnWidth=Convert.ToInt32(System. Math.Truncate《iLastWidth—iColumnwide (iAdd一1))): optimalColumnWidth.Add(iColumnwide); ||optimalColumnWidth,Add(pcea.Bounds.Width); ) ) } #endregion } return optimalColumnWidth; ) private static int GetColumnsBestFitWidth(DataTable dataTable,string P,Font font) { int maxWidth=8O: nttempWidth=80; for(int a:O:a<dataTable.Columns。Count;a++) ( .f(dataTable.Columns[a].Caption==p) for{int i=O:i<dataTable.Rows.Count;i++) { tempWidth =TextRenderer.MeasureText (dataTable.Rows[i][a].ToString0,font).Width; maxWidth=maxWidth>tempWidth?80:tempWidth; } ) ∥maxWidth=Convert.T0Int32{×RConvert.Convert(maxWidth, GraphicsUnit.Pixel,GraphicsUnit.Inch) 1 OO+1): return maxWidth: ) (下转第70页) …… ………………………………~…………………… 实用第一 智慧密集 … … … … … … … …… … … JScrollPane jScrollPane2=new JScro¨Pane(): JTextArea TextAreal:new JTextArea(); Dimension screenSize=Toolkit.getDefauItTOOIkIt ().getScreenSize(): int width=screenSize.width; JTextArea iTextArea2=new JTextArea0; public ChatPanel(MainFrame f){ this.f=f: f.jSplitPane1.remove(f.jSplitPane1.getLeftComponent0); f setLocation(width—f.widthMFdefault,O): ——this.setLavOut(borderLayout1) this.add(iPanell,iava.awt BorderLayout.CENTER); this.add ̄Panel2,iava.awt.BorderLayout.SOUTH); Button1.setText( 关闭”): lButton1.addActionLjstener(this): f.jSplitPane1.updateU10; f.jSplitPane1.setDividerLocat on(O): f setVisible(true); ) iButton2.setText(”发送 ): iButton2.addActionListener(this); } //发送按钮的事件处理 if(e.getActionCommand0.equals(“发送”)){ iPanel1.setLay0ut《borderLayout2): //i殳置borderLayout2中组件之间的垂直间距为1O个像素 borderLayout2.setVgap(1 O): iTextArea1.setEditabIe(fa}se): String chatUsername=f jList1.getSelectedValue0.toString0; String message=jTextArea2.getText(); jTextArea 1.append("to”+chatUsername+“:“+message+。、n”): iTextArea2 setText( ): iScrollPane2.setPreferredSize(new Dimension(400,6O)): ) ) ) iPanel2.add(jButton2); iPanel2.add(jButton1): jPanel1.add(jScrollPanel,java.awt.BorderLayout.CENTER); jScrotlPane1.getViewport0.add(jTextArea1): jPanel1.add Scr0llPane2,java.awt.BorderLayout.SOUTH); jScroltPane2.getViewport0.add(jTextArea2); } 参考文献 [1】Cay s.Horstmann,Gary Cornel1.Java核心技术.北京:机 械工业出版社,2008. public void actionPerformed(ActionEvent e){ [2]Peter van der Linden.Java 2教程(第六版).北京:电子 工业出版社,2005. ∥关闭按钮的事件处理 if(e.getActionCommand0.equals( 关闭“)){ if(f.jSplitPane1.getLeftComponent0 1=nul1)( f setSize(f.width.—MFdefault,f.getHeight()); ——[3】孙浏毅.Java宝典.北京:电子工业出版社,2009. (收稿日期:2011-12—24) .S (上接第62页) ///<summary> f0r(int i=1:i<dataTable.Columns.Count;i++) { tempWidth=TextRenderer.MeasureText ///自动计算各个数据歹U的打印宽度 ///<Isummary> ///<param name=’’dataTable”></param> ///<param name=”font“></param> ///<returns></retums> private static List<int>GetColumnsBestFitWidth 《dataTable.Columns[1】_ColumnName.ToString0,font).Width; maxWidth=50>tempWidth 7 50:tempWidth; optimalColumnWidth.Add(Convert.TOInt32(×RCOnVert.Convert (maxWidth,GraphicsUnit.Pixel,GraphicsUnit.Inch) 1 0O+1)): ) return optimalColumnWidth; (DataTable dataTable,Font font) { List<int>optimalColumnWidth=new List<int>0; float maxWidth=0: ) ) ) float tempWidth=0: for(int i=1:i<dataTable.Rows.Count;i++) { tempWidth=TextRenderer.MeasureText(dataTable.Rows 5 结语 XtraReports是一套非常强大的报表控件,几乎可以满足 任何的报表打印需求。而如何挖掘它隐藏的高级使用技巧,则 是需要不断地总结、不断地分析。真诚希望与广大的读者朋友 们一起探讨软件开发中的更多技巧和思路。 (收稿日期:2012一O1—05) ¨】IO】.ToString0,font).Width; maxWidth=maxWidth>tempWidth?maxWidth:tempWidth; } optimalColumnWidth.Add(Convert.Tolnt32(XRConvert Convert (maxWidth,GraphicsUnit.Pixel,GraphicsUnit Inch) 1 00+1)):