告别.NET生成报表统计图的烦恼 (转)
信息系統大多會涉及到數據的統計,如數據的導出及生成統計對比圖等,記得之前有一次要生成一個統計圖在WEB頁面上顯示,那時也是在網上找了段Code,完全是一點點畫橫縱軸坐標上面的畫出來的,而且出來的效果也一般。最近項目的需要又有類似的要求,當然也知道隨VS08一起免費發布的繪圖組件功能很強大,那繪圖組件要下載安裝,說是只支持.NET3.5(沒試驗過),不過園子里我看到了飛雪飄寒?的一篇博客(http://www.cnblogs.com/dreamof/archive/2008/07/18/1245887.html),只需引用一個dotnetCHARTING.dll,而且對于.NET1.1到.NET3.5都適用,在此非常感謝飛雪飄寒,這里我在他的基礎上作了一些補充說明。當然dreamof也提到了參考的來源網站http://www.dotnetcharting.com/,上面有近上千種圖樣,同時給出的調用方式,幾乎涵蓋了應用系統報表圖的所有方面。(文章最后補充了對柱狀和條形圖混合疊加的說明,僅供參考)
????? OK,開始正題,統計圖一般分柱狀圖,折線圖,扁圖,扁圖稍微用的少點,常見的一般是折線和柱狀圖,特殊概念的統計還是少不了扁圖的,我下面主要以柱狀和折線圖作說明。
柱狀和折線的又分單一圖和對比圖,對比圖也就是柱形的疊加,折線的疊加,當然柱形和折線也可以混合疊加。首先說下生成統計圖的相關屬性
Code?/**/
????????///?<summary>
????????///?圖片存放路徑
????????///?</summary>
????????public?string?PhaysicalImagePath
????????{
????????????set?{?_phaysicalimagepath?=?value;?}
????????????get?{?return?_phaysicalimagepath;?}
????????}
????????/**/
????????///?<summary>
????????///?圖片標題
????????///?</summary>
????????public?string?Title
????????{
????????????set?{?_title?=?value;?}
????????????get?{?return?_title;?}
????????}
????????/**/
????????///?<summary>
????????///?圖片x座標名稱
????????///?</summary>
????????public?string?XTitle
????????{
????????????set?{?_xtitle?=?value;?}
????????????get?{?return?_xtitle;?}
????????}
????????/**/
????????///?<summary>
????????///?圖片y座標名稱
????????///?</summary>
????????public?string?YTitle
????????{
????????????set?{?_ytitle?=?value;?}
????????????get?{?return?_ytitle;?}
????????}
????????/**/
????????///?<summary>
????????///?圖例名稱
????????///?</summary>
????????public?string?SeriesName
????????{
????????????set?{?_seriesname?=?value;?}
????????????get?{?return?_seriesname;?}
????????}
????????/**/
????????///?<summary>
????????///?圖片寬度
????????///?</summary>
????????public?int?PicWidth
????????{
????????????set?{?_picwidth?=?value;?}
????????????get?{?return?_picwidth;?}
????????}
????????/**/
????????///?<summary>
????????///?圖片高度
????????///?</summary>
????????public?int?PicHight
????????{
????????????set?{?_pichight?=?value;?}
????????????get?{?return?_pichight;?}
????????}
????????///?<summary>
????????///?統計圖類型(柱形,線形等)
????????///?</summary>
????????public?SeriesType?Type
????????{
????????????set?{?_type?=?value;?}
????????????get?{?return?_type;?}
????????}
????????///?<summary>
????????///?是否將輸出的圖片顯示成三維
????????///?</summary>
????????public?bool?Use3D
????????{
????????????set?{?_use3d?=?value;?}
????????????get?{?return?_use3d;?}
????????}
????????///?<summary>
????????///?對比圖形數據源
????????///?</summary>
????????public?SeriesCollection?DataSource
????????{
????????????set?{?_dt?=?value;?}
????????????get?{?return?_dt;?}
????????}
????????///?<summary>
????????///?生成統計圖片的名稱
????????///?</summary>
????????public?string?FileName
????????{
????????????set?{?_filename?=?value;?}
????????????get?{?return?_filename;?}
????????}
?
不用解釋,上面的屬性一看就應該能明白
一、 單一圖
單一圖的應用,比如某條公交線一年12個月中每月的載客量趨勢圖,如下(折線和柱狀圖):
通過dotnetCHARTING繪制上面的單一統計圖是非常方便的,只需給定一個DataTable類型的數據源,數據源的段包括橫軸的數值和縱軸的數值,即兩個字段
?
?
???/**////?<summary>????????///?生成單一圖形時的數據源模型
????????///?</summary>
????????///?<returns></returns>
????????private?DataTable?GetDataSource()
????????{
????????????//如sql?=?select?month,count?from?table?where?XXX
????????????return?db.RetDataTable(sql);
????????}
在生成統計圖時只需要合理組織數據源就可以了,dotnetcharting會根據數據庫的數值自動合理的分配縱軸的尺度,這點比較方便。調用也很簡單,如下面
?
private?void?Drawing()????????{
????????????Charting?c?=?new?Charting();
????????????c.Title?=?"2008年各月載客量";
????????????c.XTitle?=?"月份";
????????????c.YTitle?=?"載客量(萬人)";
????????????c.PicHight?=?350;
????????????c.PicWidth?=?650;
????????????c.SeriesName?=?"合計";//僅對于DataTable類型做數據源時,此屬性有效
????????????c.PhaysicalImagePath?=?"ChartImages";//統計圖片存放的文件夾名稱,缺少對應的文件夾生成不了統計圖片
????????????c.FileName?=?"Statistics";
????????????c.Type?=?SeriesType.Line;//折線型
????????????c.Use3D?=?false;?
????????????c.DataSource?=?GetDataSource();
????????????c.CreateStatisticPic(this.Chart1);
????????}?
?
/**////?<summary>????????///?生成單一統計圖片
????????///?</summary>
????????///?<param?name="chart"></param>
????????///?<param?name="type">圖形類別,如柱狀,折線型</param>
????????public?void?CreateStatisticPic(dotnetCHARTING.Chart?chart)
????????{
????????????chart.Title?=?this.Title;
????????????chart.XAxis.Label.Text?=?this.XTitle;
????????????chart.YAxis.Label.Text?=?this.YTitle;
????????????chart.TempDirectory?=?this.PhaysicalImagePath;
????????????chart.FileManager.FileName?=?this.FileName;
????????????chart.Width?=?this.PicWidth;
????????????chart.Height?=?this.PicHight;
????????????chart.Type?=?ChartType.Combo;
????????????chart.Series.Type?=?this.Type;
??????????????chart.Series.Name?=?this.SeriesName;
????????????chart.Series.Data?=?this.DataSource;
????????????chart.SeriesCollection.Add();
????????????chart.DefaultSeries.DefaultElement.ShowValue?=?true;
????????????chart.ShadingEffect?=?true;
????????????chart.Use3D?=?this.Use3D;
????????????chart.Series.DefaultElement.ShowValue?=?true;
????????}
?
個人覺得生成平面圖還好看些,三維的圖反而看起來別扭,下面也貼一張三維的單一圖效果看下
?
?
?生成的圖片名稱,如果不指定,系統會根據Tick數隨機生成圖片名稱,格式為png,這樣時間久了會很多圖片,當然可以在生成前先delete下文件下下的文件,
如果設定一個固定名稱,就只會有一個圖片,新的會覆蓋原有的,但是實際應用中這些做法都不太好,比如系統中有多種形式的報表,多個用戶同時在線生成統計圖
并且還要將該圖片導出到文檔,圖片名稱就不能重復了,要對應到用戶才行,可以這樣c.FileName = UserID+報表編號,假設系統中有10種類型的報表,系統用戶
有20個,最終的統計圖片文件夾下的文件隨著時間的推移最多達到200個圖片。也是可以接受的(也有的說如果是最新的統計圖片就不再重新生成,這樣當然好,但是
生成的圖片基本上都是按時間段動態查詢產生的,也不易控制),如果真的報表類型也多,用戶也多,做個定期刪除頁無妨。
?
二、對比圖
對比圖的應用,比如某年12個中公交和地鐵的載客量對比趨勢圖,如下(折線和柱狀圖)
?
與單一圖不一樣的是,生成對比圖的數據源必須是序列集合的類型SeriesCollection類型,也就是從數據庫取出的數據要處理成序列集合的形式,如下
?
?
?
?/**////?<summary>
????????///?生成統計圖片的數據源模型(單一或對比圖都可以)
????????///?</summary>
????????///?<returns></returns>
????????private?SeriesCollection?GetDataSource()
????????{
????????????SeriesCollection?SC?=?new?SeriesCollection();
????????????Random?rd?=?new?Random();
????????????//DataTable?newTable?=?new?DataTable();
????????????//newTable.Columns.Add("Month",?typeof(int));//月份
????????????//newTable.Columns.Add("Count",?typeof(float));//載客量
????????????//for?(int?i?=?1;?i?<=?12;?i++)
????????????//{
????????????//????newTable.Rows.Add(new?object[]?{?i,?rd.Next(50)?});
????????????//}
????????????/**/////生成單一圖,將返回的DataTable數據處理成序列集合類型的數據,以便保持數據源類型的統一
????????????//Series?s?=?new?Series();
????????????//s.Name?=?"載客量合計";
????????????//for?(int?b?=?1;?b?<=?12;?b++)?//X軸尺度個數,如一年12個月表示有12個尺度數
????????????//{
????????????//????Element?e?=?new?Element();
????????????//????e.Name?=?b.ToString();//對應于X軸個尺度的名稱
????????????//????e.YValue?=?rd.Next(50);//與X軸對應的Y軸的數值
????????????//????s.Elements.Add(e);
????????????//}
????????????//SC.Add(s);
????????????//?生成對比圖
????????????for?(int?a?=?1;?a?<=?2;?a++)?//對比的項數,如2008年各月的公交和地鐵載客量數據對比就相當于有兩個數據項
????????????{
????????????????Series?s?=?new?Series();
????????????????s.Name?=?(a?==?1???"公交載客量合計"?:?"地鐵載客量合計");//各個數據項代表的名稱,如公交和地鐵12個月載客量走勢圖,則一條表示公交,一條表示地鐵
????????????????for?(int?b?=?1;?b?<=?12;?b++)?//X軸尺度個數,如12個月表示有12個尺度數
????????????????{
????????????????????Element?e?=?new?Element();
????????????????????e.Name?=?b.ToString();//對應于X軸個尺度的名稱
????????????????????e.YValue?=?rd.Next(50);//與X軸對應的Y軸的數值
????????????????????s.Elements.Add(e);
????????????????}
????????????????SC.Add(s);
????????????}
??
????????????//可自定義填充圖的填充色,系統采取默認分配各數據項的填充色
????????????//SC[0].DefaultElement.Color?=?Color.Blue;
????????????//SC[1].DefaultElement.Color?=?Color.Red;
????????????//SC[2].DefaultElement.Color?=?Color.FromArgb(255,?99,?49);
????????????//SC[3].DefaultElement.Color?=?Color.FromArgb(0,?156,?255);
????????????return?SC;
????????}
?
?
/**////?<summary>
????????///?生成統計圖片
????????///?</summary>
????????///?<param?name="chart"></param>
????????///?<param?name="type">圖形類別,如柱狀,折線型</param>
????????public?void?CreateStatisticPic(dotnetCHARTING.Chart?chart)
????????{
????????????chart.Title?=?this.Title;
????????????chart.XAxis.Label.Text?=?this.XTitle;
????????????chart.YAxis.Label.Text?=?this.YTitle;
????????????chart.TempDirectory?=?this.PhaysicalImagePath;
????????????chart.FileManager.FileName?=?this.FileName;
????????????chart.Width?=?this.PicWidth;
????????????chart.Height?=?this.PicHight;
????????????chart.Type?=?ChartType.Combo;
????????????//chart.Series.Type?=?this.Type;//生成對比的線型圖時不適用
?????????????chart.DefaultSeries.Type?=?this.Type;?//統一使用默認的序列圖類型屬性
?????????????chart.Series.Name?=?this.SeriesName;
????????????chart.SeriesCollection.Add(this.DataSource);
????????????chart.DefaultSeries.DefaultElement.ShowValue?=?true;
????????????chart.ShadingEffect?=?true;
????????????chart.Use3D?=?this.Use3D;
????????????chart.Series.DefaultElement.ShowValue?=?true;
????????}
?
本文最后給出的下載示例中,統一采用數據源為序列集合,原本定義了兩種類型的數據源SeriesCollection和DataTable,后來有想過定義一個泛型或
IDataSource接受不同的數據源,覺得還是不怎么好,就統一用序列數據源類型。
?
三、柱狀和折線型的疊加(其實也屬于對比圖的一類)
應用場景如,公交和地鐵某年12個月的載客量對比,同時還要反映出12個公交和地鐵的發車次數的對比, 這時就要求縱軸的左右兩邊都有尺度,左邊縱軸可以
對應載客量,右邊縱軸可以對應發車次數,這種意義在于,可以看到在發車量相同的情況下,載客量對比是怎樣的,發車量不同的情況下,載客量又有什么變化,
通過這種對比可以制定方案對那些線路增加或減少發車次數,有點點類似于下面這樣的圖
?
上圖不算是一個完整的圖,因為柱狀和折線都少了一個對比,而且右邊的縱軸沒有刻度,但是這也是可以做到的
dotnetcharting官方網上近千個樣圖中其中我看到一個類似的http://www.dotnetcharting.com/gallery/view.aspx?id=RateCharts,
做一下處理是可以滿足要求的。
補充說明(2009-4-30):補充說明下Y軸右側有尺度的情況,如下圖:
?
?
要生成上圖的情況,數據源像下面做下處理,要增加對于右側Y軸的對比數據源,如下:
?
private?SeriesCollection?GetDataSource()????????{
????????????SeriesCollection?SC?=?new?SeriesCollection();
????????????Random?rd?=?new?Random();
????????????Series?s;
????????????//?生成對比圖
????????????for?(int?a?=?1;?a?<=?2;?a++)?//對比的項數,如2008年各月的公交和地鐵載客量數據對比就相當于有兩個數據項
????????????{
????????????????s?=?new?Series();
????????????????s.Name?=?(a?==?1???"公交載客量合計"?:?"地鐵載客量合計");//各個數據項代表的名稱,如公交和地鐵12個月載客量走勢圖,則一條表示公交,一條表示地鐵
????????????????for?(int?b?=?1;?b?<=?12;?b++)?//X軸尺度個數,如12個月表示有12個尺度數
????????????????{
????????????????????Element?e?=?new?Element();
????????????????????e.Name?=?b.ToString();//對應于X軸個尺度的名稱
????????????????????e.YValue?=?rd.Next(50);//與X軸對應的Y軸的數值
????????????????????s.Elements.Add(e);
????????????????}
????????????????SC.Add(s);
????????????}
????????????Axis?ctrAxis?=?new?Axis("發車次數");?//只繪一次右軸
????????????for?(int?a?=?1;?a?<=?2;?a++)?//發車此數對比
????????????{
????????????????s?=?new?Series();
????????????????ctrAxis.Orientation?=?dotnetCHARTING.Orientation.Right;
????????????????s.YAxis?=?ctrAxis;
????????????????s.Type?=?SeriesType.Line;
????????????????s.Name?=?(a?==?1???"公交發車次數"?:?"地鐵發車次數");
????????????????for?(int?b?=?1;?b?<=?12;?b++)
????????????????{
????????????????????Element?e?=?new?Element();
????????????????????e.Name?=?b.ToString();
????????????????????e.YValue?=?100?+?rd.Next(500);
????????????????????s.Elements.Add(e);
????????????????}
????????????????//s.DefaultElement.Color?=?a?==?1??Color.Pink?:?Color.SpringGreen;
????????????????SC.Add(s);
????????????}
????????????SC[0].DefaultElement.Color?=?Color.FromArgb(49,?255,?49);
????????????SC[1].DefaultElement.Color?=?Color.FromArgb(255,?255,?0);
????????????SC[2].DefaultElement.Color?=?Color.FromArgb(255,?99,?49);
????????????SC[3].DefaultElement.Color?=?Color.FromArgb(0,?156,?255);
????????????return?SC;
????????}
?
圖例在右側有點不雅,可以設置屬性和標題在一行顯示,那樣就比較好了,但是那樣的該版本不顯合計,也可以設置不顯示圖例,最新的版本的
我看了下效果很不錯,也截個圖看下
?
上圖新版本可以設置這樣的屬性 ?Chart1.TitleBox.Position = TitleBoxPosition.FullWithLegend;
??????????????????????????????????? Chart1.TitleBox.Label.Alignment = StringAlignment.Center;
本文的版本屬性是這樣的:
chart.TitleBox.Position = TitleBoxPosition.FullWithLegend;//圖例在標題行顯示,但是沒有合計信息
//chart.LegendBox.Position = LegendBoxPosition.None; 不顯示圖例,指不在右側顯示,對上面一行的屬性設置并沒有影響
另:柱形的寬度設置,也就是X軸的步長設置,這個問題一直沒解決,后來找到開發文檔看了才知道,是這樣的設置的
?chart.XAxis.StaticColumnWidth = 50; 避免X軸上坐標點少時,柱形很粗,但是要注意
一旦這樣設置了,就都是這樣的寬度,如果不設置就動態均勻分配部長。
(demo就不更新了)
PS:引用的dotnetcharting.dll有隱藏的鏈接,就是生成出來的統計圖的上邊和下邊的,當鼠標移上去時有導向.netcharting網站的鏈接,簡單
用JS腳本移除了鏈接的map標簽(網上給的方法是修改IL代碼后重新生成破解的dll,沒試過)。
?
總之,應用這個組件繪統計圖確實帶來了很大的方便和靈活性。
最后該小demo下載地址給出 :demo下載
轉載于:https://www.cnblogs.com/wujy/archive/2012/10/09/2717375.html
總結
以上是生活随笔為你收集整理的告别.NET生成报表统计图的烦恼 (转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle事务之一:锁和隔离
- 下一篇: 人人网SDK Demo项目学习获取系统L