2009-10-09 12:00 635人阅读 评论(0) 收藏 举报
 分类:
.net程序设计(C#)(21) 
 

目录(?)[+]

 

文章出处:http://www.cnblogs.com

告别.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,开始正题,统计图一般分柱状图,折线图,扁图,扁图稍微用的少点,常见的一般是折线和柱状图,特殊概念的统计还是少不了扁图的,我下面主要以柱状和折线图作说明。

柱状和折线的又分单一图和对比图,对比图也就是柱形的叠加,折线的叠加,当然柱形和折线也可以混合叠加。首先说下生成统计图的相关属性

  1.  /**/
  2.         /// <summary>
  3.         /// 图片存放路径
  4.         /// </summary>
  5.         public string PhaysicalImagePath
  6.         {
  7.             set { _phaysicalimagepath = value; }
  8.             get { return _phaysicalimagepath; }
  9.         }
  10.         /**/
  11.         /// <summary>
  12.         /// 图片标题
  13.         /// </summary>
  14.         public string Title
  15.         {
  16.             set { _title = value; }
  17.             get { return _title; }
  18.         }
  19.         /**/
  20.         /// <summary>
  21.         /// 图片x座标名称
  22.         /// </summary>
  23.         public string XTitle
  24.         {
  25.             set { _xtitle = value; }
  26.             get { return _xtitle; }
  27.         }
  28.         /**/
  29.         /// <summary>
  30.         /// 图片y座标名称
  31.         /// </summary>
  32.         public string YTitle
  33.         {
  34.             set { _ytitle = value; }
  35.             get { return _ytitle; }
  36.         }
  37.  
  38.         /**/
  39.         /// <summary>
  40.         /// 图例名称
  41.         /// </summary>
  42.         public string SeriesName
  43.         {
  44.             set { _seriesname = value; }
  45.             get { return _seriesname; }
  46.         }
  47.         /**/
  48.         /// <summary>
  49.         /// 图片宽度
  50.         /// </summary>
  51.         public int PicWidth
  52.         {
  53.             set { _picwidth = value; }
  54.             get { return _picwidth; }
  55.         }
  56.         /**/
  57.         /// <summary>
  58.         /// 图片高度
  59.         /// </summary>
  60.         public int PicHight
  61.         {
  62.             set { _pichight = value; }
  63.             get { return _pichight; }
  64.         }
  65.  
  66.         /// <summary>
  67.         /// 统计图类型(柱形,线形等)
  68.         /// </summary>
  69.         public SeriesType Type
  70.         {
  71.             set { _type = value; }
  72.             get { return _type; }
  73.         }
  74.  
  75.         /// <summary>
  76.         /// 是否将输出的图片显示成三维
  77.         /// </summary>
  78.         public bool Use3D
  79.         {
  80.             set { _use3d = value; }
  81.             get { return _use3d; }
  82.         }
  83.  
  84.         /// <summary>
  85.         /// 对比图形数据源
  86.         /// </summary>
  87.         public SeriesCollection DataSource
  88.         {
  89.  
  90.             set { _dt = value; }
  91.             get { return _dt; }
  92.         }
  93.  
  94.         /// <summary>
  95.         /// 生成统计图片的名称
  96.         /// </summary>
  97.         public string FileName
  98.         {
  99.             set { _filename = value; }
  100.             get { return _filename; }
  101.         }

不用解释,上面的属性一看就应该能明白

一、 单一图

单一图的应用,比如某条公交线一年12个月中每月的载客量趋势图,如下(折线和柱状图):

通过dotnetCHARTING绘制上面的单一统计图是非常方便的,只需给定一个DataTable类型的数据源,数据源的段包括横轴的数值和纵轴的数值,即两个字段

  1.    /// <summary>
  2.         /// 生成单一图形时的数据源模型
  3.         /// </summary>
  4.         /// <returns></returns>
  5.         private DataTable GetDataSource()
  6.         {
  7.             //如sql = select month,count from table where XXX
  8.             return db.RetDataTable(sql);
  9.         }

在生成统计图时只需要合理组织数据源就可以了,dotnetcharting会根据数据库的数值自动合理的分配纵轴的尺度,这点比较方便。调用也很简单,如下面

  1. private void Drawing()
  2.         {
  3.             Charting c = new Charting();
  4.  
  5.             c.Title = "2008年各月载客量";
  6.             c.XTitle = "月份";
  7.             c.YTitle = "载客量(万人)";
  8.             c.PicHight = 350;
  9.             c.PicWidth = 650;
  10.             c.SeriesName = "合计";//仅对于DataTable类型做数据源时,此属性有效
  11.             c.PhaysicalImagePath = "ChartImages";//统计图片存放的文件夹名称,缺少对应的文件夹生成不了统计图片
  12.             c.FileName = "Statistics";
  13.             c.Type = SeriesType.Line;//折线型
  14.             c.Use3D = false; 
  15.             c.DataSource = GetDataSource();
  16.             c.CreateStatisticPic(this.Chart1);
  17.  
  18.         } 
  1. /// <summary>
  2.         /// 生成单一统计图片
  3.         /// </summary>
  4.         /// <param name="chart"></param>
  5.         /// <param name="type">图形类别,如柱状,折线型</param>
  6.         public void CreateStatisticPic(dotnetCHARTING.Chart chart)
  7.         {
  8.             chart.Title = this.Title;
  9.             chart.XAxis.Label.Text = this.XTitle;
  10.             chart.YAxis.Label.Text = this.YTitle;
  11.             chart.TempDirectory = this.PhaysicalImagePath;
  12.             chart.FileManager.FileName = this.FileName;
  13.             chart.Width = this.PicWidth;
  14.             chart.Height = this.PicHight;
  15.             chart.Type = ChartType.Combo;
  16.             chart.Series.Type = this.Type;
  17.               chart.Series.Name = this.SeriesName;
  18.             chart.Series.Data = this.DataSource;
  19.             chart.SeriesCollection.Add();
  20.             chart.DefaultSeries.DefaultElement.ShowValue = true;
  21.             chart.ShadingEffect = true;
  22.             chart.Use3D = this.Use3D;
  23.             chart.Series.DefaultElement.ShowValue = true;
  24.         }

个人觉得生成平面图还好看些,三维的图反而看起来别扭,下面也贴一张三维的单一图效果看下

生成的图片名称,如果不指定,系统会根据Tick数随机生成图片名称,格式为png,这样时间久了会很多图片,当然可以在生成前先delete下文件下下的文件,

如果设定一个固定名称,就只会有一个图片,新的会覆盖原有的,但是实际应用中这些做法都不太好,比如系统中有多种形式的报表,多个用户同时在线生成统计图

并且还要将该图片导出到文档,图片名称就不能重复了,要对应到用户才行,可以这样c.FileName = UserID+报表编号,假设系统中有10种类型的报表,系统用户

有20个,最终的统计图片文件夹下的文件随着时间的推移最多达到200个图片。也是可以接受的(也有的说如果是最新的统计图片就不再重新生成,这样当然好,但是

生成的图片基本上都是按时间段动态查询产生的,也不易控制),如果真的报表类型也多,用户也多,做个定期删除页无妨。

二、对比图

对比图的应用,比如某年12个中公交和地铁的载客量对比趋势图,如下(折线和柱状图)

与单一图不一样的是,生成对比图的数据源必须是序列集合的类型SeriesCollection类型,也就是从数据库取出的数据要处理成序列集合的形式,如下

  1.  /// <summary>
  2.         /// 生成统计图片的数据源模型(单一或对比图都可以)
  3.         /// </summary>
  4.         /// <returns></returns>
  5.         private SeriesCollection GetDataSource()
  6.         {
  7.             SeriesCollection SC = new SeriesCollection();
  8.             Random rd = new Random();
  9.  
  10.             //DataTable newTable = new DataTable();
  11.             //newTable.Columns.Add("Month", typeof(int));//月份
  12.             //newTable.Columns.Add("Count", typeof(float));//载客量
  13.             //for (int i = 1; i <= 12; i++)
  14.             //{
  15.             //    newTable.Rows.Add(new object[] { i, rd.Next(50) });
  16.             //}
  17.             ////生成单一图,将返回的DataTable数据处理成序列集合类型的数据,以便保持数据源类型的统一
  18.             //Series s = new Series();
  19.             //s.Name = "载客量合计";
  20.             //for (int b = 1; b <= 12; b++) //X轴尺度个数,如一年12个月表示有12个尺度数
  21.             //{
  22.             //    Element e = new Element();
  23.             //    e.Name = b.ToString();//对应于X轴个尺度的名称
  24.             //    e.YValue = rd.Next(50);//与X轴对应的Y轴的数值
  25.             //    s.Elements.Add(e);
  26.             //}
  27.             //SC.Add(s);
  28.  
  29.             // 生成对比图
  30.             for (int a = 1; a <= 2; a++) //对比的项数,如2008年各月的公交和地铁载客量数据对比就相当于有两个数据项
  31.             {
  32.                 Series s = new Series();
  33.                 s.Name = (== 1 ? "公交载客量合计" : "地铁载客量合计");//各个数据项代表的名称,如公交和地铁12个月载客量走势图,则一条表示公交,一条表示地铁
  34.                 for (int b = 1; b <= 12; b++) //X轴尺度个数,如12个月表示有12个尺度数
  35.                 {
  36.                     Element e = new Element();
  37.                     e.Name = b.ToString();//对应于X轴个尺度的名称
  38.                     e.YValue = rd.Next(50);//与X轴对应的Y轴的数值
  39.                     s.Elements.Add(e);
  40.                 }
  41.                 SC.Add(s);
  42.             }
  43.   
  44.  
  45.             //可自定义填充图的填充色,系统采取默认分配各数据项的填充色
  46.             //SC[0].DefaultElement.Color = Color.Blue;
  47.             //SC[1].DefaultElement.Color = Color.Red;
  48.             //SC[2].DefaultElement.Color = Color.FromArgb(255, 99, 49);
  49.             //SC[3].DefaultElement.Color = Color.FromArgb(0, 156, 255);
  50.             return SC;
  51.         }
  1. /// <summary>
  2.         /// 生成统计图片
  3.         /// </summary>
  4.         /// <param name="chart"></param>
  5.         /// <param name="type">图形类别,如柱状,折线型</param>
  6.         public void CreateStatisticPic(dotnetCHARTING.Chart chart)
  7.         {
  8.             chart.Title = this.Title;
  9.             chart.XAxis.Label.Text = this.XTitle;
  10.             chart.YAxis.Label.Text = this.YTitle;
  11.             chart.TempDirectory = this.PhaysicalImagePath;
  12.             chart.FileManager.FileName = this.FileName;
  13.             chart.Width = this.PicWidth;
  14.             chart.Height = this.PicHight;
  15.             chart.Type = ChartType.Combo;
  16.             //chart.Series.Type = this.Type;//生成对比的线型图时不适用
  17.              chart.DefaultSeries.Type = this.Type; //统一使用默认的序列图类型属性
  18.              chart.Series.Name = this.SeriesName;
  19.             chart.SeriesCollection.Add(this.DataSource);
  20.             chart.DefaultSeries.DefaultElement.ShowValue = true;
  21.             chart.ShadingEffect = true;
  22.             chart.Use3D = this.Use3D;
  23.             chart.Series.DefaultElement.ShowValue = true;
  24.         }

本文最后给出的下载示例中,统一采用数据源为序列集合,原本定义了两种类型的数据源SeriesCollection和DataTable,后来有想过定义一个泛型或

IDataSource接受不同的数据源,觉得还是不怎么好,就统一用序列数据源类型。

三、柱状和折线型的叠加(其实也属于对比图的一类)

应用场景如,公交和地铁某年12个月的载客量对比,同时还要反映出12个公交和地铁的发车次数的对比, 这时就要求纵轴的左右两边都有尺度,左边纵轴可以

对应载客量,右边纵轴可以对应发车次数,这种意义在于,可以看到在发车量相同的情况下,载客量对比是怎样的,发车量不同的情况下,载客量又有什么变化,

通过这种对比可以制定方案对那些线路增加或减少发车次数,有点点类似于下面这样的图

上图不算是一个完整的图,因为柱状和折线都少了一个对比,而且右边的纵轴没有刻度,但是这也是可以做到的

dotnetcharting官方网上近千个样图中其中我看到一个类似的http://www.dotnetcharting.com/gallery/view.aspx?id=RateCharts

做一下处理是可以满足要求的。

补充说明(2009-4-30):补充说明下Y轴右侧有尺度的情况,如下图:

要生成上图的情况,数据源像下面做下处理,要增加对于右侧Y轴的对比数据源,如下:

  1. private SeriesCollection GetDataSource()
  2.         {
  3.             SeriesCollection SC = new SeriesCollection();
  4.             Random rd = new Random();
  5.             Series s;
  6.             // 生成对比图
  7.             for (int a = 1; a <= 2; a++) //对比的项数,如2008年各月的公交和地铁载客量数据对比就相当于有两个数据项
  8.             {
  9.                 s = new Series();
  10.                 s.Name = (== 1 ? "公交载客量合计" : "地铁载客量合计");//各个数据项代表的名称,如公交和地铁12个月载客量走势图,则一条表示公交,一条表示地铁
  11.                 for (int b = 1; b <= 12; b++) //X轴尺度个数,如12个月表示有12个尺度数
  12.                 {
  13.                     Element e = new Element();
  14.                     e.Name = b.ToString();//对应于X轴个尺度的名称
  15.                     e.YValue = rd.Next(50);//与X轴对应的Y轴的数值
  16.                     s.Elements.Add(e);
  17.                 }
  18.                 SC.Add(s);
  19.             }
  20.  
  21.             Axis ctrAxis = new Axis("发车次数"); //只绘一次右轴
  22.  
  23.             for (int a = 1; a <= 2; a++) //发车此数对比
  24.             {
  25.                 s = new Series();
  26.                 ctrAxis.Orientation = dotnetCHARTING.Orientation.Right;
  27.                 s.YAxis = ctrAxis;
  28.                 s.Type = SeriesType.Line;
  29.                 s.Name = (== 1 ? "公交发车次数" : "地铁发车次数");
  30.                 for (int b = 1; b <= 12; b++)
  31.                 {
  32.                     Element e = new Element();
  33.                     e.Name = b.ToString();
  34.                     e.YValue = 100 + rd.Next(500);
  35.                     s.Elements.Add(e);
  36.                 }
  37.                 //s.DefaultElement.Color = a == 1? Color.Pink : Color.SpringGreen;
  38.                 SC.Add(s);
  39.             }
  40.             SC[0].DefaultElement.Color = Color.FromArgb(49, 255, 49);
  41.             SC[1].DefaultElement.Color = Color.FromArgb(255, 255, 0);
  42.             SC[2].DefaultElement.Color = Color.FromArgb(255, 99, 49);
  43.             SC[3].DefaultElement.Color = Color.FromArgb(0, 156, 255);
  44.  
  45.             return SC;
  46.         }

图例在右侧有点不雅,可以设置属性和标题在一行显示,那样就比较好了,但是那样的该版本不显合计,也可以设置不显示图例,最新的版本的

我看了下效果很不错,也截个图看下

上图新版本可以设置这样的属性  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下载

告别.NET生成报表统计图的烦恼的更多相关文章

  1. C#.net使用DotNetCharting控件生成报表统计图

    在做项目时要对数据进行统计分析,所以必须生成一些报表统计图(如柱形图.饼图.曲线图等),网上强烈推荐了使用DotNetCharting控件来实现,于是自己对DotNetCharting控件进行了简单的 ...

  2. .net使用DotNetCharting控件生成报表统计图总结

    最近在做项目时要对数据进行统计分析,所以必须生成一些报表统计图(如柱形图.饼图.曲线图等),网上强烈推荐了使用DotNetCharting控件来实现,于是自己对DotNetCharting控件进行了简 ...

  3. 使用C#通过调用minitab的COM库自动化生成报表

    本文介绍通过C#调用minitab com组建自动化生成报表的方法. 首先需要在minitab中通过手动配置的方式生成报表来得到该报表的命令行,过程如下 选择菜单“编辑器”->“启用命令”启用命 ...

  4. 使用google chart api生成报表图片

    使用google chart api生成报表图片 截图 折线图 饼图 柱状图   实现方法 原理是调用google的报表服务,动态拼接url字符串,得到一张图片,数据和说明文字都是从url中传进去的. ...

  5. 使用Python定时执行一任务,自动登录某web系统,生成报表,然后发送邮件给指定人员

    一.项目需求 每周从A系统生成一张Excel报表,发送此报表给指定人员,相关人员依据此报表去完成后续的工作. 项目限制: 1.无法通过EDI系统交互的方式从后台读取数据 2.由于公司网络环境限制,不能 ...

  6. 使用python获取整月每一天的系统监控数据生成报表

    1.安装阿里开源监控工具tsar tsar官方网站 wget -O tsar.zip https://github.com/alibaba/tsar/archive/master.zip --no-c ...

  7. 使用FastReport报表工具生成报表PDF文档

    在我们开发某个系统的时候,客户总会提出一些特定的报表需求,固定的报表格式符合他们的业务处理需要,也贴合他们的工作场景,因此我们尽可能做出符合他们实际需要的报表,这样我们的系统会得到更好的认同感.本篇随 ...

  8. C# WinfForm 控件之dev报表 XtraReport (八)动态生成报表

    功能说明:生成一个报表文件DV1,保存到本地AA.rep,再重新加载这个文件到DV2 1.布局如下图: panel1 上有三个button panel2上有个documentView dv1 pane ...

  9. jenkins持续集成Allure生成报表+邮件推送

    本次基于<jenkins 生成HTML报表,邮件推送>的基础上将生成HTML报表修改为Allure生成报表,可以参考官方文档:https://docs.qameta.io/allure/# ...

随机推荐

  1. HDU 4135 Co-prime(容斥:二进制解法)题解

    题意:给出[a,b]区间内与n互质的个数 思路:如果n比较小,我们可以用欧拉函数解决,但是n有1e9.要求区间内互质,我们可以先求前缀内互质个数,即[1,b]内与n互质,求互质,可以转化为求不互质,也 ...

  2. swift设计模式学习 - 模板方法模式

    移动端访问不佳,请访问我的个人博客 设计模式学习的demo地址,欢迎大家学习交流 模板方法模式 模板方法模式,定义一个操作中算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结 ...

  3. [BZOJ3613][Heoi2014]南园满地堆轻絮 二分答案

    Description 小 Z 是 ZRP(Zombies’ Republic of Poetry,僵尸诗歌共和国)的一名诗歌爱好者,最近 他研究起了诗词音律的问题.   在过去,诗词是需要编成曲子唱 ...

  4. C#学习笔记(三):逻辑关系运算符和if语句

    条件语句 分支语句和循环语句是程序里最重要的逻辑. IF语句.分支语句.循环语句 using System; using System.Collections.Generic; using Syste ...

  5. 【Coursera】Fourth Week(2)

    Netscape JavaScript and Firefox 当Microsoft收购Netscape失败之后: JavaScript 创造并用于与 Visual Basic 竞争(1995). N ...

  6. UVa 10766 Organising the Organisation(矩阵树定理)

    https://vjudge.net/problem/UVA-10766 题意: 给出n, m, k.表示n个点,其中m条边不能直接连通,求生成树个数. 思路: 这也算个裸题,把可以连接的边连接起来, ...

  7. Python day9函数部分

    函数的学习:函数对于一门编程语言来说挺重要的,尤其是c语言,是完全使用函数来编写的 1.函数的定义:逻辑结构化和过程化的一种编程方法 def squre(x): "求一个数的平方 retur ...

  8. apache安装方式

    1.首先需要下载apachi,apache_2.2.22.msi 2.双击安装包进行安装,安装过程中可能出现一些选择性问题,将重点部分截图如下: 说明:这三个内容就按如上输入即可. 说明:选择自定义安 ...

  9. 用EL時(el-api.jar,el-ri.jar ),要設isELIgnored="false"

    用EL時(el-api.jar,el-ri.jar ),要設isELIgnored="false" 否则jstl标签不显示. 加上 <%@page isELIgnored="false ...

  10. [Java学习] Java instanceof 运算符

    多态性带来了一个问题,就是如何判断一个变量所实际引用的对象的类型 . C++使用runtime-type information(RTTI),Java 使用 instanceof 操作符. insta ...