DevExpress.XtraReports报表,动态设置报表布局
本文描述的動(dòng)態(tài)開發(fā)報(bào)表的方式已封裝成DLL,現(xiàn)向外發(fā)布,需要請(qǐng)猛擊這里。
引言
上回負(fù)責(zé)報(bào)表這塊,說不能再像以前的項(xiàng)目一樣的做報(bào)表了,以前項(xiàng)目300多張報(bào)表,一張一張的畫,一張一張的寫存儲(chǔ)過程,工作量大啊,當(dāng)然現(xiàn)在的項(xiàng)目報(bào)表沒有那么多。這么說我的工作就要是要節(jié)省工作量,我經(jīng)過分析,得出兩個(gè)結(jié)論:第一:報(bào)表的數(shù)據(jù)源得由程序員自己去取來,短時(shí)間想做個(gè)像報(bào)表設(shè)計(jì)器那樣能根據(jù)復(fù)雜的業(yè)務(wù)而“制作”數(shù)據(jù)源是不可能的;第二:報(bào)表的布局復(fù)雜多變,即使減少工作量,也無法避免對(duì)一個(gè)復(fù)雜變量的賦值工作。
開始思考
我們的每張報(bào)表分頁頭數(shù)據(jù)部分,明細(xì)數(shù)據(jù)部分,頁腳數(shù)據(jù)部分三塊。頁頭數(shù)據(jù)和頁腳數(shù)據(jù)都只是一條記錄,每個(gè)字段的值都顯示在它的標(biāo)題后面,如:姓名:×××。明細(xì)數(shù)據(jù)比較多,而且顯示格式像下面這樣:
| 標(biāo)題1 | 標(biāo)題2 | 標(biāo)題3 |
| 1 | a | 張 |
| 2 | b | 李 |
它們每行顯示的列數(shù)多少都是可以自定義的,如果定義的頁頭數(shù)據(jù)的列數(shù)是3,而頁頭數(shù)據(jù)有5個(gè)字段,多出來的就要顯示在下一行;同時(shí)每個(gè)字段占用的列數(shù)也是可以自定義的,假如頁頭數(shù)據(jù)有5個(gè)字段,每字段分別占用1、2、1、1、1列,每行顯示3列,那么它就會(huì)顯示成:
| 姓名:××× | 住址:***************** | |
| 性別:男 | 籍貫:×× | 出生年月:××× |
??????? /// <summary>
??????? /// 頁標(biāo)頭列數(shù)(默認(rèn)3)
??????? /// </summary>
??????? private int mHeaderTableColumnCount = 3;
??????? /// <summary>
??????? /// 明細(xì)表列數(shù)(默認(rèn)10)
??????? /// </summary>
??????? private int mDetailTableColumnCount = 10;
??????? /// <summary>
??????? /// 頁腳列數(shù)(默認(rèn)5)
??????? /// </summary>
??????? private int mFooterTableColumnCount = 5;
我想其中最難的就是每個(gè)要顯示的字段的位置大小問題和用什么數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)這樣的布局問題,我用了一個(gè)三維數(shù)組,它的說明如下:
??????? /// <summary>
??????? /// 表示報(bào)表布局的數(shù)組[i][j][k]
??????? /// i=0:頁頭布局,i=1:明細(xì)布局,i=2:頁腳布局
??????? /// j:按順序顯示的字段(j=0:報(bào)表標(biāo)題字段)
??????? /// k=0:字段名,k=1:標(biāo)題,k=2:列跨度,k=3:格式化字符串(可選)
??????? /// </summary>
??????? public string[][][] ReportLayout = null;
所有數(shù)據(jù)存儲(chǔ)在一個(gè)DataSet中,DataSet里的第一個(gè)Table是頁頭數(shù)據(jù),第二個(gè)是明細(xì)數(shù)據(jù),第三個(gè)是頁腳數(shù)據(jù)。
??????? /// <summary>
??????? /// 報(bào)表數(shù)據(jù)源,0頁頭表1明細(xì)表2頁腳表
??????? /// </summary>
??????? public DataSet mDs = null;
開始工作
接下來就是用程序定義各個(gè)XRTable(表)、XRTableRow(行)、XRTableCell(列),并根據(jù)ReportLayout數(shù)組的值設(shè)置它們的位置和大小等等屬性。這里就放上對(duì)明細(xì)數(shù)據(jù)布局的代碼(其中一直用ReportLayout[1],這里的1就是指的明細(xì),如果是頁頭數(shù)據(jù)就是0了)。
????????????{
????????????????columnWidth?=?PageWidth?/?mDetailTableColumnCount;
????????????????tempHeight?=?0;
????????????????for?(tempCount?=?0,?i?=?0;?i?<?ReportLayout[1].Length;?i++)
????????????????????tempCount?+=?Convert.ToInt32(ReportLayout[1][i][2]);
????????????????XRTable?detailTable?=?new?XRTable();
????????????????detailTable.Location?=?new?System.Drawing.Point(0,?tempHeight);
????????????????detailTable.Size?=?new?System.Drawing.Size(PageWidth,
mDetailRowHeight?*?(tempCount?+?mDetailTableColumnCount?-?1)?/?mDetailTableColumnCount);
????????????????detailTable.Borders?=?(DevExpress.XtraPrinting.BorderSide)((DevExpress.XtraPrinting.BorderSide.Left?|?DevExpress.XtraPrinting.BorderSide.Right)?|?DevExpress.XtraPrinting.BorderSide.Bottom);
????????????????for?(j?=?0,?i?=?0;?j?<?(tempCount?+?mDetailTableColumnCount?-?1)?/?mDetailTableColumnCount;?j++)
????????????????{
????????????????????XRTableRow?r?=?new?XRTableRow();
????????????????????r.Size?=?new?System.Drawing.Size(PageWidth,?mDetailRowHeight);
????????????????????for?(int?k?=?0;?i?<?mReportLayout[1].Length?&&?(k?+?Convert.ToInt32(ReportLayout[1][i][2]))?<=?mDetailTableColumnCount;?k?+=?Convert.ToInt32(ReportLayout[1][i][2]),?i++)
????????????????????{
????????????????????????XRTableCell?c?=?new?XRTableCell();
????????????????????????c.Size?=?new?System.Drawing.Size(columnWidth?*?Convert.ToInt32(ReportLayout[1][i][2]),?mDetailRowHeight);
????????????????????????c.Font?=?new?System.Drawing.Font("宋體",?9F);
????????????????????????c.TextAlignment?=?(ReportLayout[1][i][0].Substring(0,?1)?==?"N"?||?ReportLayout[1][i][0].Substring(0,?1)?==?"n")???DevExpress.XtraPrinting.TextAlignment.MiddleRight?:?DevExpress.XtraPrinting.TextAlignment.MiddleLeft;
????????????????????????c.DataBindings.AddRange(new?DevExpress.XtraReports.UI.XRBinding[]?{?
new?DevExpress.XtraReports.UI.XRBinding("Text",?mDs.Tables[1],?ReportLayout[1][i][0],?ReportLayout[1][i].Length?>=?4???ReportLayout[1][i][3]?:?string.Empty)?});
????????????????????????r.Cells.AddRange(new?DevExpress.XtraReports.UI.XRTableCell[]?{?c?});
????????????????????????c.Tag?=?ReportLayout[1][i][2];
????????????????????}
????????????????????detailTable.Rows.AddRange(new?DevExpress.XtraReports.UI.XRTableRow[]?{?r?});
????????????????}
????????????????mReport.Detail.Controls.AddRange(new?DevExpress.XtraReports.UI.XRTable[]?{?detailTable?});
????????????}
這里是數(shù)據(jù)綁定(c.DataBindings),如果是頁頭里面的話就應(yīng)該是:
c.Text = mReportLayout[0][i][1] + ": " + mDs.Tables[0].Rows[0][mReportLayout[0][i][0]];
對(duì)于明細(xì)還應(yīng)該在頁頭里面加個(gè)XRTable,來放置標(biāo)題,這個(gè)就不說了,根據(jù)上面的代碼很容易理解怎么做。
還有分組和合計(jì),也用數(shù)組來存儲(chǔ)它們的布局:
??????? /// <summary>
??????? /// 表示統(tǒng)計(jì)字段的布局[i][j]
??????? /// i:按順序顯示的字段
??????? /// j=0:字段名,j=1:列跨度,j=2:匯總函數(shù),j=3:格式化字符串(可選)
??????? /// </summary>
??????? public string[][] TotalLayout = null;
??????? /// <summary>
??????? /// 表示分組字段的布局[i][j][k]
??????? /// i:第i個(gè)分組
??????? /// j:每次分組要顯示的字段
????????///?k=0:字段名,k=1:列跨度,k=2:匯總函數(shù),k=3:格式化字符串(可選)
??????? /// </summary>
??????? public string[][] GroupLayout = null;
根據(jù)注釋,同上面的那段代碼的一個(gè)道理,只是要對(duì)每個(gè)XRTableCell加下面的代碼:
if (GroupLayout[i][j].Length >= 3)
{
??? XRSummary Summary = new XRSummary();
??? Summary.Func = (DevExpress.XtraReports.UI.SummaryFunc)Enum.Parse(typeof(DevExpress.XtraReports.UI.SummaryFunc), GroupLayout[i][j][2], true);
??? Summary.FormatString = GroupLayout[i][j].Length >= 4 ? GroupLayout[i][j][3] : string.Empty;
????Summary.Running = SummaryRunning.Group;//如果是合計(jì)則應(yīng)該是SummaryRunning.Report
??? c.Summary = Summary;
}
在做的過程中還發(fā)現(xiàn)單元格的線對(duì)不齊的事情,總是相差1個(gè)象素,后來得到同事的建議,每次定義一個(gè)XRTable就計(jì)算它的位置的大小把它設(shè)置好,就想現(xiàn)在上面的代碼那樣,而不是在將該XRTable中的XRTableRow和XRTableCell都定義完了也設(shè)置好它們的屬性了再來設(shè)置XRTable的屬性,這樣就對(duì)齊了,看來XRTableRow和XRTableCell的位置大小屬性都是根據(jù)XRTable來的,剛剛定義的XRTable它的大小應(yīng)該是100px,綁定到它的XRTableRow和XRTableCell會(huì)根據(jù)自身的大小按比例縮放使總大小為100px,之后你再設(shè)置XRTable的大小到1000px,它們?cè)侔丛瓉淼谋壤s放到總大小為1000px,這樣一來二去就有點(diǎn)誤差了,呵呵,這也是很符合道理的。
實(shí)施
以后我們做報(bào)表就只要定義個(gè)我的類(假如類名是:Report)的一個(gè)實(shí)例(rpt),定義的同時(shí)給構(gòu)造函數(shù)傳參(我在這個(gè)類中定義了個(gè)這樣的構(gòu)造函數(shù),參數(shù)中包含了我們要對(duì)報(bào)表布局以及數(shù)據(jù)源DataSet的所有變量),然后一個(gè)rpt.ShowPreview();就顯示報(bào)表了(我的類中的有這個(gè)方法,這個(gè)方法調(diào)用了上面說的設(shè)置報(bào)表的布局等代碼,之后用DevExpress.XtraReports報(bào)表本身的ShowPreview()來顯示報(bào)表),一切OK。下面這張圖PS了下。
轉(zhuǎn)載于:https://www.cnblogs.com/pains/archive/2007/12/02/979619.html
總結(jié)
以上是生活随笔為你收集整理的DevExpress.XtraReports报表,动态设置报表布局的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 灵活运用 SQL Server 数据库的
- 下一篇: 判断list集合不为空