Web中绘制图形的方法大致有:

1. VML方式:功能强大,但是非常麻烦。

     推荐:http://www.elook.net.cn/vml/ 

2.使用控件:Dandus, Aspose.chart,ComponentOne使用方便。虽然有破解,但非开源。

ComponetOne: http://blog.csdn.net/ChengKing/category/146827.aspx

3.结合OFFICE Web Components开发。

4.使用商用工控组件。

5.自己编写程序。

数据棒图实现

棒图实现最简单,用颜色填充<span>元素即可。

<span id="Draw0">&nbsp;</span>

<span id="Draw1">&nbsp;</span>

<span id="Draw2">&nbsp;</span>


//开始画棒图
  for(i=0;i<20;++i){
    totalCost1[i]=Math.abs(totalCost[i])*100/sum*1.25;        //正值-蓝色显示
     if(totalCost[i]>0)
     {
     parent.rightFrame.eval("Draw"+[i]).innerHTML = "<img src=images/blue.gif height=12 width=" + totalCost1[i] + ">"
     }
     else                                                //负值-红色显示
     parent.rightFrame.eval("Draw"+[i]).innerHTML = "<img src=images/red.gif height=12 width=" + totalCost1[i] + ">"
  }
}


数据饼图实现

来自 Terrylee的技术专栏

ASP.NET之所以能够在客户端浏览器中形成各种数据图片,是因为在ASP.NET中提供了绘图功能,具体的作法是先在服务器端创建一个Bitmap实例,然后利用ASP.NET中提供的绘图功能,按照要生成的图片的模样,进行绘制,最后把绘制好的实例以数据流的方式传送到客户端的浏览器上,并形成图片显示出来。本文要介绍的在ASP.NET页面中实现数据饼图采用的基本也是这种方法。饼图有时称为"Pie"图,本文要实现的数据饼图模样具体如图01所示:

图01:在ASP.NET页面中产生的数据饼图

  一.本文程序设计和运行的软件环境:

  (1).微软公司视窗2000服务器版。

  (2).Visual Studio .Net正式版,.Net FrameWork SDK版本号3705。

  (3).MDAC 2.6(Microsoft Data Acess Component)以上版本。

  二.数据字典:
为了方便起见,本文选择的数据库类型为本地数据库--Access 2000,如果你使用的是其他数据库类型,只需对下面介绍的程序中的关于数据库连接的代码进行相应的修改就可以了。Access数据库名称为"db2.mdb",在此数据库中只定义了一张数据表"MonthSale",此表的结构如表01所示:

字段名称类型 说明
ID自动编号 主键 ,递增
YF 数字销售月份
SL数字 销量

         表01:MonthSale数据表的结构

  在定义完"db2.mdb"数据库中的"MonthSale"数据表后,在MonthSale数据表中按照表02所示添加记录:

ID YF SL
1 1 12
2 2 5
337
4 4 20
5 5 16
6 6 10
7 7 19
8 8 8
997
10 10 13
11 11 11
12 12 15

      表02:MonthSale数据表中的记录情况

  在MonthSale数据表中添加完这12条记录后,保存"db2.mdb"数据库到C盘的根目录中。

下面就要解决根据从数据库中读取的数据绘制Pie图的方法。

  (1).绘制数据Pie图的实现方法:

  图01所示的Pie图看似是由一个圆形按照从数据库中得到数据值的大小分割而成的,其实在具体实现时并非如此,图01所示的Pie图其实由许多根据从数据库中数值大小,绘制相应的扇型,并由这些扇型组合而成的

  (2).简介ASP.NET页面中绘制扇型要使用到的类及其方法:

  在本文和前文中,在ASP.NET页面中实现绘图功能主要使用的是Graphics类,Graphics类被封装在命名空间"System.Drawing"中。Graphics类中定义了很多方法和属性,这些方法和属性都与绘图有关,Graphics类中的常用成员具体可参阅表01和表02,表01是Graphics类中的常用方法及其说明,表02是Graphics类中常用属性及其说明:

方法 说明
Clear清除整个绘图面并以指定背景色填充。
Dispose释放由此Graphics对象使用的所有资源。
DrawArc 绘制一段弧线,它表示由一对坐标、宽度和高度指定的椭圆部分。
DrawEllipse绘制一个由边框定义的椭圆。
DrawIcon在指定坐标处绘制由指定的Icon对象表示的图像。
DrawIconUnstretched 绘制指定的Icon对象表示的图像,而不缩放该图像。
DrawImage 在指定位置并且按原始大小绘制指定的Image对象。
DrawImageUnscaled在坐标对所指定的位置并且按其原始大小绘制指定的Image对象。
DrawLine绘制一条连接由坐标对指定的两个点的线条。
DrawLines 绘制一系列连接一组Point结构的线段。
DrawPie 绘制一个扇形,该扇形由一个坐标对、宽度和高度以及两条射线所指定的椭圆定义。
DrawPolygon 绘制由一组Point结构定义的多边形。
DrawRectangle绘制由坐标对、宽度和高度指定的矩形。
DrawRectangles 绘制一系列由Rectangle结构指定的矩形。
DrawString 在指定位置并且用指定的Brush和Font对象绘制指定的文本字符串。
FillClosedCurve填充由Point结构数组定义的闭合基数样条曲线的内部。
FillEllipse 填充边框所定义的椭圆的内部,该边框由一对坐标、一个宽度和一个高度指定。
FillPie填充由一对坐标、一个宽度、一个高度以及两条射线指定的椭圆所定义的扇形区的内部。
FillPolygon
填充Point结构指定的点数组所定义的多边形的内部。
FillRectangle填充由一对坐标、一个宽度和一个高度指定的矩形的内部。
FillRectangles填充由Rectangle结构指定的一系列矩形的内部。
FillRegion填充Region 对象的内部。
Flush 强制执行所有挂起的图形操作并立即返回而不等待操作完成。
FromHdc 从设备上下文的指定句柄创建新的Graphics对象。
FromHwnd 从窗口的指定句柄创建新的Graphics对象。
FromImage 从指定的Image对象创建新Graphics对象。
GetHdc获取与此Graphics对象关联的设备上下文的句柄。
ReleaseHdc释放通过以前对此Graphics对象GetHdc方法的调用获得的设备上下文句柄。
ResetClip将此Graphics对象的剪辑区域重置为无限区域。
ResetTransform 将此Graphics对象的全局变换矩阵重置为单位矩阵。


           表01:Graphics类中的常用方法及其说明

  在本文中使用最多,也是最重要的方法就是:FillPie和DrawPie方法。这二个方法的具体使用方法,在下文中又详细介绍。

属性说明
Clip获取或设置Region对象,该对象限定此Graphics对象的绘图区域。
ClipBounds 获取RectangleF结构,该结构限定此Graphics对象的剪辑区域。
DpiX 获取此Graphics对象的水平分辨率。
DpiY获取此Graphics对象的垂直分辨率。
PageScale 获取或设置此Graphics对象的全局单位和页单位之间的比例。
PageUnit 获取或设置用于此Graphics对象中的页坐标的度量单位。
PixelOffsetMode 获取或设置一个值,该值指定在呈现此Graphics对象的过程中像素如何偏移。
RenderingOrigin 为抵色处理和阴影画笔获取或设置此Graphics对象的呈现原点。
SmoothingMode 获取或设置此Graphics对象的呈现质量。
TextRenderingHint 获取或设置与此Graphics对象关联的文本的呈现模式。
Transform 获取或设置此Graphics对象的全局变换。
VisibleClipBounds 获取或设置此Graphics对象的可见剪辑区域的边框。

             表02:Graphics类中的常用属性及其说明

  (3).利用FillPie和DrawPie方法绘制扇型的具体方法:

  DrawPie方法功能是绘制一个扇型,下面是 DrawPie方法的一种调用语法,此语法也是本文中主要的调用方式,具体如下:

  public void DrawPie ( Pen , float , float , float , float , float , float ) ;

  此种DrawPie调用方法是由七个参数组成,这七个参数的具体说明如下:

  第一个参数:定义绘制扇型的画笔类型;

  第二和第三个参数:定义扇型的坐标;

  第四和第五个参数:定义组成扇型的二个射线的长度;

  第六和第七个参数:定义扇型的开始角度和扇型旋转的角度大小。其中把X坐标的正方向定为0度角,计算扇型的开始角度的按照顺时针方向旋转,最先到达的扇型的那条射线和0度角之间的夹角。

  下列代码就是在ASP.NET页面中绘制一个扇型:

Bitmap bm = new Bitmap ( 600 , 300 ) ;
//创建一个长度为600,宽带为300的Bitmap实例
Graphics g ;
g = Graphics.FromImage ( bm ) ;
//由此Bitmap实例创建Graphic实例
g . Clear ( Color . Snow ) ;
g.DrawPie ( Pens.Red , 50 , 50 , 150 , 150 , 0 , 30 ) ;

 四.ASP.NET页面中实现数据Pie图实现步骤

  在实现数据Pie图之前,首先要确保在C盘的根目录存在"db.mdb"数据库,并且此数据库已经设定完毕,并且存在《在ASP.NET页面中实现数据棒图》一文中的数据。下面是ASP.NET实现数据Pie图的具体步骤,开发工具使用的是Visual Studio .Net,采用的是C#语言。

  1. 启动Visual Studio .Net。

  2. 选择菜单【文件】|【新建】|【项目】后,弹出【新建项目】对话框。

  3. 将【项目类型】设置为【Visual C#项目】。

  4. 将【模板】设置为【ASP.NET Web 应用程序】。

  5. 在【位置】的文本框中输入"http://localhost/Pie"。然后单击【确定】按钮,这样在Visual Studio .Net就会在当前项目文件所在目录中建立一个名称为"Pie"文件夹,里面存放是此项目的项目文件,项目中的其他文件存放的位置是计算机Internet信息服务的默认的Web站点所在的目录中新建的一个名称为"WebPieDemo"的文件夹中
 6. 把Visual Studio .Net的当前窗口切换到WebForm的代码编辑窗口,即:WebForm1.aspx.cs文件的编辑窗口。

  7. 在WebForm1.aspx.cs文件首部,用下列代码替换WebForm1.aspx.cs中导入命名空间的代码:

1 // 下面程序中使用的ImageFormat类所在的命名空间
2 using  System . Drawing . Imaging ;
3 // 下面程序中使用到关于数据库方面的类所在的命名空间
4 using  System . Data . OleDb ;

8. WebForm1.aspx.cs文件中的Page_Load事件处理代码中添加下列代码,下列代码的作用是打开数据库,读取数据,并以此数据形成数据Pie图:

  1 private   void  Page_Load( object  sender, System.EventArgs e)
  2          {
  3            // 在此处放置用户代码以初始化页面
  4            string sRouter = "c://db2.mdb" ;
  5
  6            //获得当前Access数据库在服务器端的绝对路径
  7            string strCon = " Provider = Microsoft.Jet.OLEDB.4.0; Data Source = " + sRouter ;
  8
  9            //创建一个数据库连接
 10            OleDbConnection myConn = new OleDbConnection ( strCon ) ;
 11            string strCom = " SELECT YF ,SL FROM MonthSale ORDER BY YF" ;
 12            myConn.Open ( ) ;
 13            OleDbCommand myCommand = new OleDbCommand ( strCom , myConn ) ;
 14            OleDbDataReader myOleDbDataReader = myCommand.ExecuteReader ( ) ;
 15            //创建OleDbDataReader实例,并以此实例来获取数据库中各条记录数据
 16
 17            int [ ] iXiaoSH = new int [ 12 ] ;
 18            //定义一个数组,用以存放从数据库中读取的销售数据
 19
 20            string [ ] sMoth = new string [ 12 ] ;
 21            //定义一个数组,用以存放从数据库中读取的销售月份
 22
 23            int iIndex = 0 ;
 24            while ( myOleDbDataReader.Read ( ) ) 
 25            {
 26                iXiaoSH [ iIndex ] = myOleDbDataReader.GetInt32 ( 1 ) ;
 27                sMoth [ iIndex ] = myOleDbDataReader.GetInt32 ( 0 ) . ToString() + "" ;
 28                iIndex++ ;
 29            }

 30            //读取Table01数据表中的各条数据,并存放在先前定义的二个数组中
 31
 32            myConn . Close ( ) ;
 33            myOleDbDataReader . Close ( ) ;
 34 
 35            Bitmap bm = new Bitmap ( 600 , 300 ) ;
 36            //创建一个长度为600,宽带为300的Bitmap实例
 37
 38            Graphics g ;
 39            g = Graphics.FromImage ( bm ) ;
 40            g . Clear ( Color . Snow ) ;
 41            g . DrawString ( " ××公司××××年度销售情况一览表" , new Font ( "宋体" , 16 ) , Brushes . Black , new Point ( 5 , 5 ) ) ;
 42            //在绘画图面的指定位置,以指定的字体、指定的颜色绘制指定的字符串。即为图表标题
 43
 44            //以下代码是是实现图01中的右上部区域
 45            //以上是在图01中为下面绘制定位
 46            Point myRec = new Point ( 515 , 30 ) ;
 47            Point myDec = new Point ( 540 , 30 ) ;
 48            Point myTxt = new Point ( 565 , 30 ) ;
 49            g . DrawString ( "单位:万套" , new Font ( "宋体" , 9 ) , Brushes . Black , new Point ( 515 , 12 ) ) ;
 50            for ( int i = 0 ; i < sMoth.Length ; i++ ) 
 51            {
 52                g . FillRectangle ( new SolidBrush ( GetColor ( i ) ) , myRec . X , myRec . Y , 20 , 10 ) ;
 53                //填充小方块
 54
 55                g . DrawRectangle ( Pens.Black , myRec . X , myRec . Y , 20 , 10 ) ;
 56                //绘制小方块
 57
 58                g . DrawString ( sMoth [ i ] . ToString ( ) , new Font ( "宋体"9 ) , Brushes . Black , myDec ) ;
 59                //绘制小方块右边的文字
 60
 61                g . DrawString ( iXiaoSH[i].ToString (), new Font ( "宋体"9 ) , Brushes . Black , myTxt ) ;
 62                myRec . Y += 15 ;
 63                myDec . Y += 15 ;
 64                myTxt . Y += 15 ;
 65            }

 66
 67            //以下代码是根据从数据库中得到的数值大小,绘制扇型,并以相应色彩填充扇型,//从而构成图01中的Pie图
 68            int iTatal = 0 ; 
 69            float fCurrentAngle = 0 ;
 70            float fStartAngle = 0;
 71            for ( int i = 0 ; i < iXiaoSH . Length ; i++ )
 72            {
 73                iTatal = iTatal + iXiaoSH [ i ] ;
 74            }

 75            for ( int i = 0 ; i < iXiaoSH . Length ; i++ )
 76            {
 77                //以下代码是获得要绘制扇型的开始角度
 78                if ( i == iXiaoSH . Length - 1 )
 79                {
 80                    fCurrentAngle = 360- fStartAngle ;
 81                }

 82                else
 83                {
 84                    int iTemp = iXiaoSH [ i ] ;
 85                    fCurrentAngle = ( iTemp * 360 ) / iTatal ;
 86                }

 87                //根据参数绘制扇型
 88
 89                g.DrawPie ( Pens.Black , 100 , 40 , 250 , 250 , fStartAngle , fCurrentAngle ) ;
 90                //以指定色彩填充绘制的扇型
 91
 92                g.FillPie ( new SolidBrush ( GetColor ( i ) ) , 100 , 40 , 250 , 250 , fStartAngle , fCurrentAngle ) ;
 93                fStartAngle += fCurrentAngle ;
 94            }

 95
 96            //画出图片的边框
 97            Pen p = new Pen ( Color.Black , 2 ) ;
 98            g . DrawRectangle ( p , 1 , 1 , 598 , 298 ) ;
 99
100            //向客户端输出数据流,并以此数据流形成Jpeg图片
101            bm.Save ( Response . OutputStream , ImageFormat . Jpeg ) ;
102        }


9. WebForm1.aspx.cs文件中的InitializeComponent过程之后,添加下列代码,下列代码的作用是定义一个名称为GetColor函数,此函数的功能根据索引号得到相应的系统颜色:

 1 /// <summary>
 2        /// 获取颜色
 3        /// </summary>
 4        /// <param name="itemIndex">数组的索引</param>
 5        /// <returns></returns>

 6          private  Color GetColor (  int  itemIndex ) 
 7          {
 8             Color MyColor ;
 9             int i = itemIndex ;
10            switch (i) 
11             {
12                  case 0 :
13                   MyColor = Color.Green;
14                   return MyColor;
15                  case 1 :
16                   MyColor = Color.Red;
17                    return MyColor;
18                  case 2:
19                   MyColor = Color.Yellow;
20                   return MyColor;
21                  case 3 :
22                   MyColor = Color.Blue;
23                   return MyColor;
24                  case 4 :
25                   MyColor = Color.Orange;
26                   return MyColor;
27                 case 5 :
28                   MyColor = Color.Aqua;
29                   return MyColor;
30                  case 6:
31                   MyColor = Color.SkyBlue;
32                   return MyColor;
33                  case 7:
34                   MyColor = Color.DeepPink;
35                   return MyColor;
36                  case 8:
37                   MyColor = Color.Azure;
38                   return MyColor;
39                  case 9:
40                   MyColor = Color.Brown;
41                   return MyColor;
42                  case 10:
43                   MyColor = Color.Pink;
44                   return MyColor;
45                  case 11:
46                   MyColor = Color.BurlyWood;
47                   return MyColor;
48                  case 12:
49                   MyColor = Color.Chartreuse;
50                   return MyColor;
51                  default:
52                   MyColor = Color.Pink;
53                   return MyColor;
54            }

55        }


至此,在上述步骤都正确执行后,在ASP.NET页面中实现数据Pie图的全部工作就完成了。此时单击快捷键F5,就可以得到如图01所示的数据Pie图了。

  五.总结:

  由于ASP.NET提供了丰富的绘图功能,所以结合这二篇文章的介绍,我想再实现其他的数据图表,应该也不算很困难。

完整的例子代码:

  1 using  System;
  2 using  System.Collections;
  3 using  System.ComponentModel;
  4 using  System.Data;
  5 using  System.Drawing;
  6 using  System.Web;
  7 using  System.Web.SessionState;
  8 using  System.Web.UI;
  9 using  System.Web.UI.WebControls;
 10 using  System.Web.UI.HtmlControls;
 11 // 下面程序中使用的ImageFormat类所在的命名空间
 12 using  System . Drawing . Imaging ;
 13 // 下面程序中使用到关于数据库方面的类所在的命名空间
 14 using  System . Data . OleDb ;
 15
 16
 17 namespace  WebPieDemo
 18 {
 19    /// <summary>
 20    /// WebForm1 的摘要说明。
 21    /// </summary>

 22    public class WebForm1 : System.Web.UI.Page
 23    {
 24        private void Page_Load(object sender, System.EventArgs e)
 25        {
 26            // 在此处放置用户代码以初始化页面
 27            string sRouter = "c://db2.mdb" ;
 28
 29            //获得当前Access数据库在服务器端的绝对路径
 30            string strCon = " Provider = Microsoft.Jet.OLEDB.4.0; Data Source = " + sRouter ;
 31
 32            //创建一个数据库连接
 33            OleDbConnection myConn = new OleDbConnection ( strCon ) ;
 34            string strCom = " SELECT YF ,SL FROM MonthSale ORDER BY YF" ;
 35            myConn.Open ( ) ;
 36            OleDbCommand myCommand = new OleDbCommand ( strCom , myConn ) ;
 37            OleDbDataReader myOleDbDataReader = myCommand.ExecuteReader ( ) ;
 38            //创建OleDbDataReader实例,并以此实例来获取数据库中各条记录数据
 39
 40            int [ ] iXiaoSH = new int [ 12 ] ;
 41            //定义一个数组,用以存放从数据库中读取的销售数据
 42
 43            string [ ] sMoth = new string [ 12 ] ;
 44            //定义一个数组,用以存放从数据库中读取的销售月份
 45
 46            int iIndex = 0 ;
 47            while ( myOleDbDataReader.Read ( ) ) 
 48            {
 49                iXiaoSH [ iIndex ] = myOleDbDataReader.GetInt32 ( 1 ) ;
 50                sMoth [ iIndex ] = myOleDbDataReader.GetInt32 ( 0 ) . ToString() + "" ;
 51                iIndex++ ;
 52            }

 53            //读取Table01数据表中的各条数据,并存放在先前定义的二个数组中
 54
 55            myConn . Close ( ) ;
 56            myOleDbDataReader . Close ( ) ;
 57 
 58            Bitmap bm = new Bitmap ( 600 , 300 ) ;
 59            //创建一个长度为600,宽带为300的Bitmap实例
 60
 61            Graphics g ;
 62            g = Graphics.FromImage ( bm ) ;
 63            g . Clear ( Color . Snow ) ;
 64            g . DrawString ( " ××公司××××年度销售情况一览表" , new Font ( "宋体" , 16 ) , Brushes . Black , new Point ( 5 , 5 ) ) ;
 65            //在绘画图面的指定位置,以指定的字体、指定的颜色绘制指定的字符串。即为图表标题
 66
 67            //以下代码是是实现图01中的右上部区域
 68            //以上是在图01中为下面绘制定位
 69            Point myRec = new Point ( 515 , 30 ) ;
 70            Point myDec = new Point ( 540 , 30 ) ;
 71            Point myTxt = new Point ( 565 , 30 ) ;
 72            g . DrawString ( "单位:万套" , new Font ( "宋体" , 9 ) , Brushes . Black , new Point ( 515 , 12 ) ) ;
 73            for ( int i = 0 ; i < sMoth.Length ; i++ ) 
 74            {
 75                g . FillRectangle ( new SolidBrush ( GetColor ( i ) ) , myRec . X , myRec . Y , 20 , 10 ) ;
 76                //填充小方块
 77
 78                g . DrawRectangle ( Pens.Black , myRec . X , myRec . Y , 20 , 10 ) ;
 79                //绘制小方块
 80
 81                g . DrawString ( sMoth [ i ] . ToString ( ) , new Font ( "宋体"9 ) , Brushes . Black , myDec ) ;
 82                //绘制小方块右边的文字
 83
 84                g . DrawString ( iXiaoSH[i].ToString (), new Font ( "宋体"9 ) , Brushes . Black , myTxt ) ;
 85                myRec . Y += 15 ;
 86                myDec . Y += 15 ;
 87                myTxt . Y += 15 ;
 88            }

 89
 90            //以下代码是根据从数据库中得到的数值大小,绘制扇型,并以相应色彩填充扇型,//从而构成图01中的Pie图
 91            int iTatal = 0 ; 
 92            float fCurrentAngle = 0 ;
 93            float fStartAngle = 0;
 94            for ( int i = 0 ; i < iXiaoSH . Length ; i++ )
 95            {
 96                iTatal = iTatal + iXiaoSH [ i ] ;
 97            }

 98            for ( int i = 0 ; i < iXiaoSH . Length ; i++ )
 99            {
100                //以下代码是获得要绘制扇型的开始角度
101                if ( i == iXiaoSH . Length - 1 )
102                {
103                    fCurrentAngle = 360- fStartAngle ;
104                }

105                else
106                {
107                    int iTemp = iXiaoSH [ i ] ;
108                    fCurrentAngle = ( iTemp * 360 ) / iTatal ;
109                }

110                //根据参数绘制扇型
111
112                g.DrawPie ( Pens.Black , 100 , 40 , 250 , 250 , fStartAngle , fCurrentAngle ) ;
113                //以指定色彩填充绘制的扇型
114
115                g.FillPie ( new SolidBrush ( GetColor ( i ) ) , 100 , 40 , 250 , 250 , fStartAngle , fCurrentAngle ) ;
116                fStartAngle += fCurrentAngle ;
117            }

118
119            //画出图片的边框
120            Pen p = new Pen ( Color.Black , 2 ) ;
121            g . DrawRectangle ( p , 1 , 1 , 598 , 298 ) ;
122
123            //向客户端输出数据流,并以此数据流形成Jpeg图片
124            bm.Save ( Response . OutputStream , ImageFormat . Jpeg ) ;
125        }

126
127        Web 窗体设计器生成的代码
146
147        /// <summary>
148        /// 获取颜色
149        /// </summary>
150        /// <param name="itemIndex">数组的索引</param>
151        /// <returns></returns>

152        private Color GetColor ( int itemIndex ) 
153        {
154             Color MyColor ;
155             int i = itemIndex ;
156            switch (i) 
157             {
158                  case 0 :
159                   MyColor = Color.Green;
160                   return MyColor;
161                  case 1 :
162                   MyColor = Color.Red;
163                    return MyColor;
164                  case 2:
165                   MyColor = Color.Yellow;
166                   return MyColor;
167                  case 3 :
168                   MyColor = Color.Blue;
169                   return MyColor;
170                  case 4 :
171                   MyColor = Color.Orange;
172                   return MyColor;
173                 case 5 :
174                   MyColor = Color.Aqua;
175                   return MyColor;
176                  case 6:
177                   MyColor = Color.SkyBlue;
178                   return MyColor;
179                  case 7:
180                   MyColor = Color.DeepPink;
181                   return MyColor;
182                  case 8:
183                   MyColor = Color.Azure;
184                   return MyColor;
185                  case 9:
186                   MyColor = Color.Brown;
187                   return MyColor;
188                  case 10:
189                   MyColor = Color.Pink;
190                   return MyColor;
191                  case 11:
192                   MyColor = Color.BurlyWood;
193                   return MyColor;
194                  case 12:
195                   MyColor = Color.Chartreuse;
196                   return MyColor;
197                  default:
198                   MyColor = Color.Pink;
199                   return MyColor;
200            }

201        }

202    }

203}

204

 

在ASP.NET页面中实现数据柱状图

棒图有时又称为"Bar"图,在ASP.NET中拥有了一个新功能--绘图功能,通过此功能就能够按照要实现的图表的模样来绘制,最后在客户端的浏览器中形成一个图片,从而显示出图表来。

  本文就是介绍在ASP.NET页面中实现Bar图的具体方法。希望本篇文章能够让您领会到ASP.NET中强大的绘图功能,而我们知道图表只有在和数据库关联以后,才能够显示出更强大的优势。下面就来介绍在ASP.NET页面中从数据库中提起数据,并以此数据形成Bar图的具体实现方法。

 一.本文程序设计和运行的软件环境:

  (1).微软公司视窗2000服务器版。

  (2).Visual Studio .Net正式版,.Net FrameWork SDK版本号3705。

  (3).MDAC 2.6(Microsoft Data Acess Component)以上版本。

  二.建立数据源

  为了方便起见,本文选择的数据库类型为本地数据库--Access 2000,如果你使用的是其他数据库类型,只需对下面介绍的程序中的关于数据库连接的代码进行相应的修改就可以了。Access数据库名称为"db2.mdb",在此数据库中只定义了一张数据表"MonthSale",此表的结构如表01所示:

字段名称类型 说明
ID自动编号 主键 ,递增
YF 数字销售月份
SL数字 销量

         表01:MonthSale数据表的结构

  在定义完"db2.mdb"数据库中的"MonthSale"数据表后,在MonthSale数据表中按照表02所示添加记录:

ID YF SL
1 1 12
2 2 5
337
4 4 20
5 5 16
6 6 10
7 7 19
8 8 8
997
10 10 13
11 11 11
12 12 15

      表02:Table01数据表中的记录情况

  在MonthSale数据表中添加完这12条记录后,保存"db2.mdb"数据库到C盘的根目录中。
三.ASP.NET页面中实现数据Bar图的关键步骤及其实现方法:

  在ASP.NET页面中实现数据Bar图首先必须解决二大问题:

  (1).首先要解决在ASP.NET页面中实现数据库连接和从数据库中读取数据的方法。

  程序要实现从数据库中一条条的读取数据,则要使用OleDbDataReader类,OleDbDataReader类提供了从数据库中逐条读取数据的方法。下面代码是连接C盘根目录下的"db2.mdb"数据库,逐条读取MonthSale数据表中的记录,并把数据存放到定义的二个数组中:

 1 string  sRouter  =   " c://db2.mdb "  ;
 2              // 获得当前Access数据库在服务器端的绝对路径
 3
 4              string  strCon  =   "  Provider = Microsoft.Jet.OLEDB.4.0; Data Source =  "   +  sRouter ;
 5              // 创建一个数据库连接
 6
 7             OleDbConnection myConn  =   new  OleDbConnection ( strCon ) ;
 8              string  strCom  =   "  SELECT YF ,SL FROM MonthSale ORDER BY YF "  ;
 9             myConn.Open ( ) ;
10             OleDbCommand myCommand  =   new  OleDbCommand ( strCom , myConn ) ;
11             OleDbDataReader myOleDbDataReader  =  myCommand.ExecuteReader ( ) ;
12              // 创建OleDbDataReader实例,并以此实例来获取数据库中各条记录数据
13
14              int  [ ] iXiaoSH  =   new   int  [  12  ] ;
15              // 定义一个数组,用以存放从数据库中读取的销售数据
16
17              string  [ ] sMoth  =   new   string  [  12  ] ;
18              // 定义一个数组,用以存放从数据库中读取的销售月份
19
20              int  iIndex  =   0  ;
21              while  ( myOleDbDataReader.Read ( ) ) 
22              {
23                iXiaoSH [ iIndex ] = myOleDbDataReader.GetInt32 ( 1 ) ;
24                sMoth [ iIndex ] = myOleDbDataReader.GetInt32 ( 0 ) . ToString ( ) + "" ;
25                iIndex++ ;
26            }

27              // 读取Table01数据表中的各条数据,并存放在先前定义的二个数组中
28
29             myConn . Close ( ) ;
30             myOleDbDataReader . Close ( ) ;
31              // 关闭各种资源


(2).根据得到数据,绘制图片,并显示出来:

  通过第一步,已经把从数据库中的读取的数据存放到"iXiaoSH"和"sMoth"数组中。下面就要解决依据这些数据绘制出Bar图?首先先了解一下在ASP.NET页面中将要实现的数据Bar图的模样。具体可如图01所示:

图01:在ASP.NET中实现的数据Bar图

  程序中把图01所示各个元素,按照区域分成了五个部分,这五个部分将在后面介绍的程序中分别实现:

  1. 构建整个图片

  首先要创建一Bitmap实例,并以此来构建一个Graphics实例,Graphics实例提供了各种绘制方法,这样才能按照数据的要求在Bitmap实例上绘制各种图形。下面代码是在ASP.NET中创建Bitmap实例,并以此实例来构建 Graphics实例的具体方法:

1 Bitmap bm  =   new  Bitmap (  600  ,  250  ) ;
2              // 创建一个长度为600,宽带为250的Bitmap实例
3
4             Graphics g ;
5             g  =  Graphics.FromImage ( bm ) ;
6              // 由此Bitmap实例创建Graphic实例
7
8             g . Clear ( Color.Snow) ;
9              // 用Snow色彩为背景色填充此绘画图面

2. 图01中的标题部分文字:

  这是通过Graphics实例中提供的DrawString方法以指定的字体、颜色、在指定的位置绘制指定的字符串。下面代码的作用是绘制图01中标题:

1 g . DrawString (  "  ××公司××××年度销售情况统计表 "  ,  new  Font (  " 黑体 "  ,  16  ) , Brushes . Black ,  new  Point (  5  ,  5  ) ) ;
2              // 在绘画图面的指定位置,以指定的字体、指定的颜色绘制指定的字符串。即为图表标题
3

3. 图01中的提示区域,即图01中的右上角显示的内容:

  要绘制这部分内容首先要定位,可以把这部分要绘制的内容分成三个小部分:

  其一,是图01中的"单位:万套"文字,这部分处理起来比较简单,当选定要在图片中输出的文字坐标后,调用Graphics实例中提供的DrawString方法就可以了;
  
  其二,是绘制图01中的小方块,首先要调用Graphics实例中的DrawRectangle方法在指定位置,以指定的颜色,绘制指定大小的方块,然后再条约Graphics实例中的FillRectangle填充这个小方块就完成了;

  其三,是绘制小方块右边的文字。同样要使用Graphics实例中提供的DrawString方法,只不过位置坐标和字体要进行相应改变罢了。下面代码功能是绘制图01右上角显示的内容:

 1 // 以下代码是是实现图右上部
 2             Point myRec  =   new  Point (  535  ,  30  ) ;
 3             Point myDec  =   new  Point (  560  ,  26  ) ;
 4
 5              // 以上是在图01中为下面绘制定位
 6             g . DrawString (  " 单位:万套 "  ,  new  Font (  " 宋体 "  ,  9  ) , Brushes . Black ,  new  Point (  525  ,  12  ) ) ;
 7    
 8    
 9              for  (  int  i  =   0  ; i  <  sMoth.Length ; i ++  ) 
10              {
11                g . DrawRectangle ( Pens.Black , myRec . X , myRec . Y , 20 , 10 ) ;
12                //绘制小方块
13
14                g . FillRectangle ( new SolidBrush ( GetColor ( i ) ) , myRec.X , myRec.Y , 20 , 10 ) ;
15                //填充小方块
16
17                g . DrawString ( sMoth [ i ] . ToString ( ) , new Font ( "宋体" , 9 ) , Brushes . Black , myDec ) ;
18                //绘制小方块右边的文字
19
20                myRec . Y += 15 ;
21                myDec . Y += 15 ;
22            }


4. 根据从数据库中读取的数据,绘制数据Bar图:

  此部分与第三部分比较类似,最主要的区别在于,绘制的位置不相同,下面代码是在图01中绘制数据Bar图,并提示Bar图所代表的数量:

 

 1 // 以下代码是绘制Bar图,及其销售数量
 2              int  iBarWidth  =   40  ;
 3              int  scale  =   10  ;
 4              for  (  int  i  =   0  ; i  <  iXiaoSH . Length ; i ++  ) 
 5              {
 6                g . DrawRectangle ( Pens.Black, ( i * iBarWidth ) + 15 , 250 - ( iXiaoSH [ i ] * scale ) , 20 , ( iXiaoSH [ i ] * scale ) + 5 ) ;
 7                //绘制Bar图
 8
 9                g . FillRectangle ( new SolidBrush (GetColor ( i )) , ( i * iBarWidth ) + 15 , 250 - ( iXiaoSH [ i ] * scale ) , 20 , ( iXiaoSH [ i ] * scale ) + 5 ) ;
10                //以指定的色彩填充Bar图
11
12                g . DrawString ( iXiaoSH [ i ] . ToString ( ) , new Font ( "宋体" , 9 ) , Brushes . Black , ( i * iBarWidth ) + 20 , 235 - ( iXiaoSH [ i ] * scale ) ) ;
13                //显示Bar图代表的数据
14            }

5. 绘制图片边框,并形成Jpeg文件格式在客户端显示:

  绘制图片边框,使用的Graphics实例中的DrawRectangle方法。至于采用Jpeg格式文件在客户端显示,是因为Jpeg文件占用的空间较小,利于网络传送。下面代码是绘制图01中的边框,并形成Jpeg文件:

1 // 以下代码是绘制边框,并形成Jpeg文件,供浏览器显示出来
2             Pen p  =   new  Pen ( Color.Black ,  2  ) ;
3             g . DrawRectangle ( p ,  1  ,  1  ,  598  ,  248  ) ;
4             bm.Save ( Response . OutputStream , ImageFormat.Gif) ;


四.ASP.NET页面中实现数据Bar图实现步骤:

  掌握了上面的关键步骤及其解决方法后,在ASP.NET实现数据Bar相对就容易许多了,下面是ASP.NET页面中实现数据Bar图的具体实现步骤,在开发工具上选用的是Visual Stuido .Net企业构建版,采用的开发语言是C#。

  1. 启动Visual Studio .Net

  2. 选择菜单【文件】|【新建】|【项目】后,弹出【新建项目】对话框

  3. 将【项目类型】设置为【Visual C#项目】

  4. 将【模板】设置为【ASP.NET Web 应用程序】

  5. 在【位置】的文本框中输入"http://localhost/Bar"。然后单击【确定】按钮,这样在Visual Studio .Net就会在当前项目文件所在目录中建立一个名称为"WebBarDemo"文件夹,里面存放是此项目的项目文件,项目中的其他文件存放的位置是计算机Internet信息服务的默认的Web站点所在的目录中新建的一个名称为"WebBarDemo"的文件夹中。具体如图02所示:

 图02:新建一个ASP.NET项目对话框

  6. 把Visual Studio .Net的当前窗口切换到WebForm的代码编辑窗口,即:WebForm1.aspx.cs文件的编辑窗口。

  7. 在WebForm1.aspx.cs文件首部,用下列代码替换WebForm1.aspx.cs中导入命名空间的代码

1 // 下面程序中使用的ImageFormat类所在的命名空间
2 using  System.Drawing.Imaging;
3 // 下面程序中使用到关于数据库方面的类所在的命名空间
4 using  System.Data.OleDb;

 8. WebForm1.aspx.cs文件中的Page_Load事件处理代码中添加下列代码,下列代码的作用是打开数据库,读取数据,并以此数据形成数据Bar图:

 1 private   void  Page_Load( object  sender, System.EventArgs e)
 2          {
 3            // 在此处放置用户代码以初始化页面
 4
 5            string sRouter = "c://db2.mdb" ;
 6            //获得当前Access数据库在服务器端的绝对路径
 7
 8            string strCon = " Provider = Microsoft.Jet.OLEDB.4.0; Data Source = " + sRouter ;
 9            //创建一个数据库连接
10
11            OleDbConnection myConn = new OleDbConnection ( strCon ) ;
12            string strCom = " SELECT YF ,SL FROM MonthSale ORDER BY YF" ;
13            myConn.Open ( ) ;
14            OleDbCommand myCommand = new OleDbCommand ( strCom , myConn ) ;
15            OleDbDataReader myOleDbDataReader = myCommand.ExecuteReader ( ) ;
16            //创建OleDbDataReader实例,并以此实例来获取数据库中各条记录数据
17
18            int [ ] iXiaoSH = new int [ 12 ] ;
19            //定义一个数组,用以存放从数据库中读取的销售数据
20
21            string [ ] sMoth = new string [ 12 ] ;
22            //定义一个数组,用以存放从数据库中读取的销售月份
23
24            int iIndex = 0 ;
25            while ( myOleDbDataReader.Read ( ) ) 
26            {
27                iXiaoSH [ iIndex ] = myOleDbDataReader.GetInt32 ( 1 ) ;
28                sMoth [ iIndex ] = myOleDbDataReader.GetInt32 ( 0 ) . ToString ( ) + "" ;
29                iIndex++ ;
30            }

31            //读取Table01数据表中的各条数据,并存放在先前定义的二个数组中
32
33            myConn . Close ( ) ;
34            myOleDbDataReader . Close ( ) ;
35            //关闭各种资源
36
37            Bitmap bm = new Bitmap ( 600 , 250 ) ;
38            //创建一个长度为600,宽带为250的Bitmap实例
39
40            Graphics g ;
41            g = Graphics.FromImage ( bm ) ;
42            //由此Bitmap实例创建Graphic实例
43
44            g . Clear ( Color.Snow) ;
45            //用Snow色彩为背景色填充此绘画图面
46
47            g . DrawString ( " ××公司××××年度销售情况统计表" , new Font ( "黑体" , 16 ) , Brushes . Black , new Point ( 5 , 5 ) ) ;
48            //在绘画图面的指定位置,以指定的字体、指定的颜色绘制指定的字符串。即为图表标题
49
50            //以下代码是是实现图右上部
51            Point myRec = new Point ( 535 , 30 ) ;
52            Point myDec = new Point ( 560 , 26 ) ;
53
54            //以上是在图01中为下面绘制定位
55            g . DrawString ( "单位:万套" , new Font ( "宋体" , 9 ) , Brushes . Black , new Point ( 525 , 12 ) ) ;
56   
57   
58            for ( int i = 0 ; i < sMoth.Length ; i++ ) 
59            {
60                g . DrawRectangle ( Pens.Black , myRec . X , myRec . Y , 20 , 10 ) ;
61                //绘制小方块
62
63                g . FillRectangle ( new SolidBrush ( GetColor ( i ) ) , myRec.X , myRec.Y , 20 , 10 ) ;
64                //填充小方块
65
66                g . DrawString ( sMoth [ i ] . ToString ( ) , new Font ( "宋体" , 9 ) , Brushes . Black , myDec ) ;
67                //绘制小方块右边的文字
68
69                myRec . Y += 15 ;
70                myDec . Y += 15 ;
71            }

72
73            //以下代码是绘制Bar图,及其销售数量
74            int iBarWidth = 40 ;
75            int scale = 10 ;
76            for ( int i = 0 ; i < iXiaoSH . Length ; i++ ) 
77            {
78                g . DrawRectangle ( Pens.Black, ( i * iBarWidth ) + 15 , 250 - ( iXiaoSH [ i ] * scale ) , 20 , ( iXiaoSH [ i ] * scale ) + 5 ) ;
79                //绘制Bar图
80
81                g . FillRectangle ( new SolidBrush (GetColor ( i )) , ( i * iBarWidth ) + 15 , 250 - ( iXiaoSH [ i ] * scale ) , 20 , ( iXiaoSH [ i ] * scale ) + 5 ) ;
82                //以指定的色彩填充Bar图
83
84                g . DrawString ( iXiaoSH [ i ] . ToString ( ) , new Font ( "宋体" , 9 ) , Brushes . Black , ( i * iBarWidth ) + 20 , 235 - ( iXiaoSH [ i ] * scale ) ) ;
85                //显示Bar图代表的数据
86            }

87
88            //以下代码是绘制边框,并形成Jpeg文件,供浏览器显示出来
89            Pen p = new Pen ( Color.Black , 2 ) ;
90            g . DrawRectangle ( p , 1 , 1 , 598 , 248 ) ;
91            bm.Save ( Response . OutputStream , ImageFormat.Gif) ;
92        }


9. WebForm1.aspx.cs文件中的InitializeComponent过程之后,添加下列代码,下列代码的作用是定义一个名称为GetColor函数,此函数的功能根据索引号得到相应的系统颜色:

 1 /// <summary>
 2        /// 获取颜色
 3        /// </summary>
 4        /// <param name="itemIndex">数组的索引</param>
 5        /// <returns></returns>

 6          private  Color GetColor (  int  itemIndex ) 
 7          {
 8             Color MyColor ;
 9             int i = itemIndex ;
10            switch (i) 
11             {
12                  case 0 :
13                   MyColor = Color.Green;
14                   return MyColor;
15                  case 1 :
16                   MyColor = Color.Red;
17                    return MyColor;
18                  case 2:
19                   MyColor = Color.Yellow;
20                   return MyColor;
21                  case 3 :
22                   MyColor = Color.Blue;
23                   return MyColor;
24                  case 4 :
25                   MyColor = Color.Orange;
26                   return MyColor;
27                 case 5 :
28                   MyColor = Color.Aqua;
29                   return MyColor;
30                  case 6:
31                   MyColor = Color.SkyBlue;
32                   return MyColor;
33                  case 7:
34                   MyColor = Color.DeepPink;
35                   return MyColor;
36                  case 8:
37                   MyColor = Color.Azure;
38                   return MyColor;
39                  case 9:
40                   MyColor = Color.Brown;
41                   return MyColor;
42                  case 10:
43                   MyColor = Color.Pink;
44                   return MyColor;
45                  case 11:
46                   MyColor = Color.BurlyWood;
47                   return MyColor;
48                  case 12:
49                   MyColor = Color.Chartreuse;
50                   return MyColor;
51                  default:
52                   MyColor = Color.Pink;
53                   return MyColor;
54            }

55        }


10. 至此,在上述步骤都正确执行后,在ASP.NET页面中实现数据Bar图的全部工作就完成了。在确定上面建立的Access数据库"db.mdb"位于C盘的根目录中之后,单击快捷键F5,就可以得到如图01所示的数据Bar图了。

  五.总结:

  在ASP.NET页面中实现各种图表,其所使用的就是ASP.NET的绘图功能,而这一功能是ASP.NET的前一个版本所不具备的。上面的这些介绍,不仅介绍了在ASP.NET绘制各种图片的方法,还介绍了数据库连接和从数据库中逐条读取记录的方法。这些方法对您了解和掌握在ASP.NET中操作数据库是非常有用的。

完整的例子程序:

  1 using  System;
  2 using  System.Collections;
  3 using  System.ComponentModel;
  4 using  System.Data;
  5 using  System.Drawing;
  6 using  System.Web;
  7 using  System.Web.SessionState;
  8 using  System.Web.UI;
  9 using  System.Web.UI.WebControls;
 10 using  System.Web.UI.HtmlControls;
 11
 12 // 下面程序中使用的ImageFormat类所在的命名空间
 13 using  System.Drawing.Imaging;
 14 // 下面程序中使用到关于数据库方面的类所在的命名空间
 15 using  System.Data.OleDb;
 16
 17 namespace  WebBarDemo
 18 {
 19    /// <summary>
 20    /// WebForm1 的摘要说明。
 21    /// </summary>

 22    public class WebForm1 : System.Web.UI.Page
 23    {
 24        private void Page_Load(object sender, System.EventArgs e)
 25        {
 26            // 在此处放置用户代码以初始化页面
 27
 28            string sRouter = "c://db2.mdb" ;
 29            //获得当前Access数据库在服务器端的绝对路径
 30
 31            string strCon = " Provider = Microsoft.Jet.OLEDB.4.0; Data Source = " + sRouter ;
 32            //创建一个数据库连接
 33
 34            OleDbConnection myConn = new OleDbConnection ( strCon ) ;
 35            string strCom = " SELECT YF ,SL FROM MonthSale ORDER BY YF" ;
 36            myConn.Open ( ) ;
 37            OleDbCommand myCommand = new OleDbCommand ( strCom , myConn ) ;
 38            OleDbDataReader myOleDbDataReader = myCommand.ExecuteReader ( ) ;
 39            //创建OleDbDataReader实例,并以此实例来获取数据库中各条记录数据
 40
 41            int [ ] iXiaoSH = new int [ 12 ] ;
 42            //定义一个数组,用以存放从数据库中读取的销售数据
 43
 44            string [ ] sMoth = new string [ 12 ] ;
 45            //定义一个数组,用以存放从数据库中读取的销售月份
 46
 47            int iIndex = 0 ;
 48            while ( myOleDbDataReader.Read ( ) ) 
 49            {
 50                iXiaoSH [ iIndex ] = myOleDbDataReader.GetInt32 ( 1 ) ;
 51                sMoth [ iIndex ] = myOleDbDataReader.GetInt32 ( 0 ) . ToString ( ) + "" ;
 52                iIndex++ ;
 53            }

 54            //读取Table01数据表中的各条数据,并存放在先前定义的二个数组中
 55
 56            myConn . Close ( ) ;
 57            myOleDbDataReader . Close ( ) ;
 58            //关闭各种资源
 59
 60            Bitmap bm = new Bitmap ( 600 , 250 ) ;
 61            //创建一个长度为600,宽带为250的Bitmap实例
 62
 63            Graphics g ;
 64            g = Graphics.FromImage ( bm ) ;
 65            //由此Bitmap实例创建Graphic实例
 66
 67            g . Clear ( Color.Snow) ;
 68            //用Snow色彩为背景色填充此绘画图面
 69
 70            g . DrawString ( " ××公司××××年度销售情况统计表" , new Font ( "黑体" , 16 ) , Brushes . Black , new Point ( 5 , 5 ) ) ;
 71            //在绘画图面的指定位置,以指定的字体、指定的颜色绘制指定的字符串。即为图表标题
 72
 73            //以下代码是是实现图右上部
 74            Point myRec = new Point ( 535 , 30 ) ;
 75            Point myDec = new Point ( 560 , 26 ) ;
 76
 77            //以上是在图01中为下面绘制定位
 78            g . DrawString ( "单位:万套" , new Font ( "宋体" , 9 ) , Brushes . Black , new Point ( 525 , 12 ) ) ;
 79   
 80   
 81            for ( int i = 0 ; i < sMoth.Length ; i++ ) 
 82            {
 83                g . DrawRectangle ( Pens.Black , myRec . X , myRec . Y , 20 , 10 ) ;
 84                //绘制小方块
 85
 86                g . FillRectangle ( new SolidBrush ( GetColor ( i ) ) , myRec.X , myRec.Y , 20 , 10 ) ;
 87                //填充小方块
 88
 89                g . DrawString ( sMoth [ i ] . ToString ( ) , new Font ( "宋体" , 9 ) , Brushes . Black , myDec ) ;
 90                //绘制小方块右边的文字
 91
 92                myRec . Y += 15 ;
 93                myDec . Y += 15 ;
 94            }

 95
 96            //以下代码是绘制Bar图,及其销售数量
 97            int iBarWidth = 40 ;
 98            int scale = 10 ;
 99            for ( int i = 0 ; i < iXiaoSH . Length ; i++ ) 
100            {
101                g . DrawRectangle ( Pens.Black, ( i * iBarWidth ) + 15 , 250 - ( iXiaoSH [ i ] * scale ) , 20 , ( iXiaoSH [ i ] * scale ) + 5 ) ;
102                //绘制Bar图
103
104                g . FillRectangle ( new SolidBrush (GetColor ( i )) , ( i * iBarWidth ) + 15 , 250 - ( iXiaoSH [ i ] * scale ) , 20 , ( iXiaoSH [ i ] * scale ) + 5 ) ;
105                //以指定的色彩填充Bar图
106
107                g . DrawString ( iXiaoSH [ i ] . ToString ( ) , new Font ( "宋体" , 9 ) , Brushes . Black , ( i * iBarWidth ) + 20 , 235 - ( iXiaoSH [ i ] * scale ) ) ;
108                //显示Bar图代表的数据
109            }

110
111            //以下代码是绘制边框,并形成Jpeg文件,供浏览器显示出来
112            Pen p = new Pen ( Color.Black , 2 ) ;
113            g . DrawRectangle ( p , 1 , 1 , 598 , 248 ) ;
114            bm.Save ( Response . OutputStream , ImageFormat.Gif) ;
115        }

116
117        Web 窗体设计器生成的代码
136        
137        /// <summary>
138        /// 获取颜色
139        /// </summary>
140        /// <param name="itemIndex">数组的索引</param>
141        /// <returns></returns>

142        private Color GetColor ( int itemIndex ) 
143        {
144             Color MyColor ;
145             int i = itemIndex ;
146            switch (i) 
147             {
148                  case 0 :
149                   MyColor = Color.Green;
150                   return MyColor;
151                  case 1 :
152                   MyColor = Color.Red;
153                    return MyColor;
154                  case 2:
155                   MyColor = Color.Yellow;
156                   return MyColor;
157                  case 3 :
158                   MyColor = Color.Blue;
159                   return MyColor;
160                  case 4 :
161                   MyColor = Color.Orange;
162                   return MyColor;
163                 case 5 :
164                   MyColor = Color.Aqua;
165                   return MyColor;
166                  case 6:
167                   MyColor = Color.SkyBlue;
168                   return MyColor;
169                  case 7:
170                   MyColor = Color.DeepPink;
171                   return MyColor;
172                  case 8:
173                   MyColor = Color.Azure;
174                   return MyColor;
175                  case 9:
176                   MyColor = Color.Brown;
177                   return MyColor;
178                  case 10:
179                   MyColor = Color.Pink;
180                   return MyColor;
181                  case 11:
182                   MyColor = Color.BurlyWood;
183                   return MyColor;
184                  case 12:
185                   MyColor = Color.Chartreuse;
186                   return MyColor;
187                  default:
188                   MyColor = Color.Pink;
189                   return MyColor;
190            }

191        }

192
193    }

194}

195

 

曲线图实现

<%@ Import Namespace="System" %> 
<%@ Import Namespace="System.Drawing" %> 
<%@ Import Namespace="System.Drawing.Drawing2D" %> 
<%@ Import Namespace="System.Drawing.Imaging" %> 

<script language="C#" runat="server"> 

   class LineChart 
{; 
//Sample ASPX C# LineChart Class, Steve Hall, 2002 
public Bitmap b; 
public string Title="Default Title"; 
public ArrayList chartvalues = new ArrayList(); 
public float Xorigin=0, Yorigin=0; 
public float ScaleX, ScaleY; 
public float Xdivs=2, Ydivs=2; 

private int Width, Height; 
private Graphics g; 
private Page p; 

struct datapoint {; 
public float x; 
public float y; 
public bool valid; 
}; 

//initialize 
public LineChart(int myWidth, int myHeight, Page myPage) {; 
Width = myWidth; Height = myHeight; 
ScaleX = myWidth; ScaleY = myHeight; 
b = new Bitmap(myWidth, myHeight); 
g = Graphics.FromImage(b); 
p = myPage; 
}; 

public void Addvalue(int x, int y) {; 
datapoint myPoint; 
myPoint.x=x; 
myPoint.y=y; 
myPoint.valid=true; 
chartvalues.Add(myPoint); 
}; 

public void Draw() {; 
int i; 
float x, y, x0, y0; 
string myLabel; 
Pen blackPen = new Pen(Color.Black,1); 
Brush blackBrush = new SolidBrush(Color.Black); 
Font axesFont = new Font("arial",10); 

//first establish working area 
p.Response.ContentType="image/jpeg"; 
g.FillRectangle(new 
SolidBrush(Color.LightYellow),0,0,Width,Height); 
int ChartInset = 50; 
int ChartWidth = Width-(2*ChartInset); 
int ChartHeight = Height-(2*ChartInset); 
g.DrawRectangle(new 
Pen(Color.Black,1),ChartInset,ChartInset,ChartWidth,ChartHeight); 

//must draw all text items before doing the rotate below 
g.DrawString(Title, new Font("arial",14), blackBrush, 
Width/3, 10); 
//draw X axis labels 
for(i=0; i<=Xdivs; i++) {; 
x=ChartInset+(i*ChartWidth)/Xdivs; 
y=ChartHeight+ChartInset; 
myLabel = (Xorigin + (ScaleX*i/Xdivs)).ToString(); 
g.DrawString(myLabel, axesFont, blackBrush, x-4, 
y+10); 
g.DrawLine(blackPen, x, y+2, x, y-2); 
}; 
//draw Y axis labels 
for(i=0; i<=Ydivs; i++) {; 
x=ChartInset; 
y=ChartHeight+ChartInset-(i*ChartHeight/Ydivs); 
myLabel = (Yorigin + (ScaleY*i/Ydivs)).ToString(); 
g.DrawString(myLabel, axesFont, blackBrush, 5, y-6); 
g.DrawLine(blackPen, x+2, y, x-2, y); 
}; 

//transFORM drawing coords to lower-left (0,0) 
g.RotateTransFORM(180); 
g.TranslateTransFORM(0,-Height); 
g.TranslateTransFORM(-ChartInset,ChartInset); 
g.ScaleTransFORM(-1, 1); 

//draw chart data 
datapoint prevPoint = new datapoint(); 
prevPoint.valid=false; 
foreach(datapoint myPoint in chartvalues) {; 
if(prevPoint.valid==true) {; 
x0=ChartWidth*(prevPoint.x-Xorigin)/ScaleX; 
y0=ChartHeight*(prevPoint.y-Yorigin)/ScaleY; 
x=ChartWidth*(myPoint.x-Xorigin)/ScaleX; 
y=ChartHeight*(myPoint.y-Yorigin)/ScaleY; 
g.DrawLine(blackPen,x0,y0,x,y); 
g.FillEllipse(blackBrush,x0-2,y0-2,4,4); 
g.FillEllipse(blackBrush,x-2,y-2,4,4); 
}; 
prevPoint = myPoint; 
}; 

//finally send graphics to browser 
b.Save(p.Response.OutputStream, ImageFORMat.Jpeg); 
}; 

~LineChart() {; 
g.Dispose(); 
b.Dispose(); 
}; 
}; 


   void Page_Load(Object sender, EventArgs e) {; 
LineChart c = new LineChart(640, 480, Page); 
c.Title="My Line Chart"; 
c.Xorigin=0; c.ScaleX=500; c.Xdivs=5; 
c.Yorigin=0; c.ScaleY=1000; c.Ydivs=5; 
c.Addvalue(50,50); 
c.Addvalue(100,100); 
c.Addvalue(200,150); 
c.Addvalue(450,450); 
c.Draw(); 
}; 

</script> 
<%@ Import Namespace="System" %> 
<%@ Import Namespace="System.Drawing" %> 
<%@ Import Namespace="System.Drawing.Drawing2D" %> 
<%@ Import Namespace="System.Drawing.Imaging" %> 

<script language="C#" runat="server"> 

   class LineChart 
{; 
//Sample ASPX C# LineChart Class, Steve Hall, 2002 
public Bitmap b; 
public string Title="Default Title"; 
public ArrayList chartvalues = new ArrayList(); 
public float Xorigin=0, Yorigin=0; 
public float ScaleX, ScaleY; 
public float Xdivs=2, Ydivs=2; 

private int Width, Height; 
private Graphics g; 
private Page p; 

struct datapoint {; 
public float x; 
public float y; 
public bool valid; 
}; 

//initialize 
public LineChart(int myWidth, int myHeight, Page myPage) {; 
Width = myWidth; Height = myHeight; 
ScaleX = myWidth; ScaleY = myHeight; 
b = new Bitmap(myWidth, myHeight); 
g = Graphics.FromImage(b); 
p = myPage; 
}; 

public void Addvalue(int x, int y) {; 
datapoint myPoint; 
myPoint.x=x; 
myPoint.y=y; 
myPoint.valid=true; 
chartvalues.Add(myPoint); 
}; 

public void Draw() {; 
int i; 
float x, y, x0, y0; 
string myLabel; 
Pen blackPen = new Pen(Color.Black,1); 
Brush blackBrush = new SolidBrush(Color.Black); 
Font axesFont = new Font("arial",10); 

//first establish working area 
p.Response.ContentType="image/jpeg"; 
g.FillRectangle(new 
SolidBrush(Color.LightYellow),0,0,Width,Height); 
int ChartInset = 50; 
int ChartWidth = Width-(2*ChartInset); 
int ChartHeight = Height-(2*ChartInset); 
g.DrawRectangle(new 
Pen(Color.Black,1),ChartInset,ChartInset,ChartWidth,ChartHeight); 

//must draw all text items before doing the rotate below 
g.DrawString(Title, new Font("arial",14), blackBrush, 
Width/3, 10); 
//draw X axis labels 
for(i=0; i<=Xdivs; i++) {; 
x=ChartInset+(i*ChartWidth)/Xdivs; 
y=ChartHeight+ChartInset; 
myLabel = (Xorigin + (ScaleX*i/Xdivs)).ToString(); 
g.DrawString(myLabel, axesFont, blackBrush, x-4, 
y+10); 
g.DrawLine(blackPen, x, y+2, x, y-2); 
}; 
//draw Y axis labels 
for(i=0; i<=Ydivs; i++) {; 
x=ChartInset; 
y=ChartHeight+ChartInset-(i*ChartHeight/Ydivs); 
myLabel = (Yorigin + (ScaleY*i/Ydivs)).ToString(); 
g.DrawString(myLabel, axesFont, blackBrush, 5, y-6); 
g.DrawLine(blackPen, x+2, y, x-2, y); 
}; 

//transFORM drawing coords to lower-left (0,0) 
g.RotateTransFORM(180); 
g.TranslateTransFORM(0,-Height); 
g.TranslateTransFORM(-ChartInset,ChartInset); 
g.ScaleTransFORM(-1, 1); 

//draw chart data 
datapoint prevPoint = new datapoint(); 
prevPoint.valid=false; 
foreach(datapoint myPoint in chartvalues) {; 
if(prevPoint.valid==true) {; 
x0=ChartWidth*(prevPoint.x-Xorigin)/ScaleX; 
y0=ChartHeight*(prevPoint.y-Yorigin)/ScaleY; 
x=ChartWidth*(myPoint.x-Xorigin)/ScaleX; 
y=ChartHeight*(myPoint.y-Yorigin)/ScaleY; 
g.DrawLine(blackPen,x0,y0,x,y); 
g.FillEllipse(blackBrush,x0-2,y0-2,4,4); 
g.FillEllipse(blackBrush,x-2,y-2,4,4); 
}; 
prevPoint = myPoint; 
}; 

//finally send graphics to browser 
b.Save(p.Response.OutputStream, ImageFORMat.Jpeg); 
}; 

~LineChart() {; 
g.Dispose(); 
b.Dispose(); 
}; 
}; 


   void Page_Load(Object sender, EventArgs e) {; 
LineChart c = new LineChart(640, 480, Page); 
c.Title="My Line Chart"; 
c.Xorigin=0; c.ScaleX=500; c.Xdivs=5; 
c.Yorigin=0; c.ScaleY=1000; c.Ydivs=5; 
c.Addvalue(50,50); 
c.Addvalue(100,100); 
c.Addvalue(200,150); 
c.Addvalue(450,450); 
c.Draw(); 
}; 

</script> 


Microsoft Office Web Components

Microsoft Office Web Components 包含在 Microsoft Office 2000 中。它们是用于向 Web 页添加电子表格、图表和数据处理功能的 ActiveX 控件的集合。可以直接在浏览器中处理数据,并以图表的形式显示数据。由于其基于Office的强大功能,以及与Office相同的用户界面,无疑是ASP.NET中图表生成的明智选择。
本章主要包括以下几个方面内容:
● 基于GDI+的图表生成。
● 基于Office Web Components的图表生成。
● 基于Office Web Components的报表生成。
经过本章的学习,将掌握ASP.NET中统计图表的实现,利用图表将网站的数据完美呈现给用户。
方案设计
本节分别介绍GDI+与Office Web Components的具体使用,为后面的章节打下基础。
使用GDI+
GDI+ 是 GDI(Windows XP之前版本提供的图形设备接口)的后续版本。GDI+ 是一种应用程序编程接口 (API),负责在屏幕和打印机上显示信息。
在ASP.NET中,利用GDI+可以创建简单的柱状图和饼图。
ASP.NET页面GDI+图像使用
在完整的生成柱状图和饼图之前,先从简单的ASP.NET页面图像使用开始。
在System.Draw命名空间中包含了创建、编辑图像的所有类。创建图像时,主要使用Bitmap类和Graphics类。为了便于理解,可以把Bitmap类想象成画板,Graphics类想象成画笔。Bitmap类主要用于创建画板以及在完成后图像的保存。Graphics类主要用来绘制图像、图形和线条。
首先使用下面的代码创建画板。(本小节所有代码需要添加System.Drawing命名空间与System.Drawing.Image命名空间)
Bitmap myPalette = new Bitmap(600, 400); //创建600*400的画板
有了画板,还需要创建Graphics类的实例来创建画笔,指定画板。代码如下
Graphics myGraphics = Graphics.FromImage(myPalette);
有了画笔和画板,只要使用Graphics类中的各种方法在画板上绘制图像、图形和线条就可以了。
Graphics类中的方法分为两类:绘制方法与填充方法。例如,DrawRectangle方法与FillRectangle方法。绘制方法仅仅绘制出图形的轮廓,而填充方法绘制出图形的轮廓同时填充图形的内部。
下面的代码绘制了简单的图形:
int width=150,height=50;
// 创建黑色背景椭圆
myGraphics.FillEllipse(new SolidBrush(Color.Black), 300, 150, width, height);
// 创建蓝色背景椭圆
myGraphics.FillEllipse(new SolidBrush(Color.LightBlue), 300, 150, width - 10, height - 10);
// 创建输出文本
string textOut = "ASP.NET";
//指定字体
Font fontOut = new Font("Times New Roman", 16, FontStyle.Bold|FontStyle.Italic);
//指定文本居中
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
// 绘制文本
myGraphics.DrawString(textOut,fontOut,new SolidBrush(Color.Black),new Rectangle(0,0,width,height),stringFormat);
图已经画好了,只剩下将图保存下来。要将保存的图在网页中显示,可以在下面两种方式中任选其一:
● 将图像保存在服务器的文件系统中,使用HTML的<img>标记来显示。
● 直接将图像的二进制流输出到Response对象的输出流。
两种方式各有千秋。第一种方式适合于创建不需要变动的图片(例如网站广告图片),能够创建一次,满足今后的所有要求。但会在服务器端保留下临时文件。第二种方式适用于动态的创建图片供页面显示,不能满足今后的需要,却也不会留下临时文件。
下面分别写出这两种方式的代码:
● 保存文件方式代码:
保存文件方式首先需要在Aspx文件中添加<Img>标记
<!-- 指定显示文件为tmpFile.jpg -->
<img src = “tmpFile.jpg”>
然后在代码中保存文件即可:
//将文件保存为当前页面所在目录下的tmpFile.jpg
myPalette.Save(Server.MapPath("")+@"/tmpFile.jpg",ImageFormat.Jpeg);
● 直接输出方式代码:
//直接将图片以二进制流的方式输出到Response对象的输出流。
myPalette.Save(Response.OutputStream, ImageFormat.Jpeg);
将代码加入页面的PageLoad事件中即可得到如图18-1效果。
      
       图18-1 GDI+图像使用效果
创建柱状图
在知道了如何使用GDI+创建简单图像并显示到页面后,创建复杂一些的柱状图就非常自然了。
使用简单的FillRectangle,DrawRectangle,DrawString方法,即可实现基本的柱状图。代码如下:
//初始化Bitmap类实例与Graphics类实例准备画图
const int width = 600, height = 400;
Bitmap myPalette = new Bitmap(width,height);
Graphics myGraphics = Graphics.FromImage(myPalette);
// 绘制白色背景
myGraphics.FillRectangle(new SolidBrush(Color.White), 0, 0, width, height);
// 设定显示数据
string [] DataName = {"Jan","Feb","Mar","Apr","May","Jun"};
int [] Data = {100,20,50,60,240,20};
//设定显示颜色
Color [] myColors = {
Color.Blue,
Color.Red,
Color.Yellow,
Color.Purple,
Color.Orange,
Color.Brown
};
//绘制柱图
for(int i = 0;i<DataName.Length;i++)
{
//填充柱图
myGraphics.FillRectangle(new SolidBrush(myColors[i]),(i*40)+30,300 - Data[i],20,Data[i]+5);
//绘制柱图边界
myGraphics.DrawRectangle(new Pen(Color.Black),(i*40)+30,300 - Data[i],20,Data[i]+5);
//绘制柱图上方数据
myGraphics.DrawString(Data[i].ToString(), new Font("宋体", 9), Brushes.Black, new PointF((i*40)+30,300-Data[i]-20));
//绘制柱图下标
myGraphics.DrawString(DataName[i], new Font("宋体", 9), Brushes.Black, new PointF((i*40)+30,320));
}
//输出图像
myPalette.Save(Response.OutputStream, ImageFormat.Jpeg);
// 清除所用绘图对象
myGraphics.Dispose();
myPalette.Dispose();
将上述代码写入页面CodeBehind文件的PageLoad事件中即可看到如图18-2效果:
       
          图18-2 GDI+柱状图效果
使用Office Web Components
Office Web Components是用于向 Web 页添加电子表格、图表和数据处理功能的 ActiveX控件的集合。
利用Office Web Components可以方便的来绘制简单的柱状图与饼图。不必像在GDI+中需要考虑画图的细节。
使用Office Web Components要求
使用Office Web Components需要系统中装有Office2000以上版本。在工程的引用中添加Office Web Components即可。
具体步骤如下:
在解决方案资源管理器的引用文件夹上单击鼠标右键选择添加引用,在出现的添加引用对话框中选择COM标签,选择Microsoft Office Web Components,双击选中,点击确定即可。图18-3、18-4显示了该过程。
       
            图18-3 添加引用           图18-4 添加Office Web Components引用

使用Office Web Components绘制柱状图
使用Office Web Components绘制图表不同于直接使用GDI+,主要的工作从绘图的细节转移到对于图表的设置。步骤如下:
● Step1 创建ChartSpace对象来放置图表
ChartSpace是用来放置图表的类,图表完成后用它来输出。
OWC.ChartSpace objCSpace = new OWC.ChartSpaceClass ();
● Step2 使用ChartSpace对象的Add方法创建图表
ChartSpace的Add方法创建图表,参数表示所创建图表的索引。
OWC.WCChart objChart = objCSpace.Charts.Add (0);
● Step3 指定图表的类型
通过设定Chart类对象的Type属性来指定图表的类型。
objChart.Type = OWC.ChartChartTypeEnum.chChartTypeColumnClustered;
本例创建柱状图,选择了chChartTypeColunmClustered类型。
其他的类型包括:chChartTypeArea 面积图、chChartTypeBarClustered 条形图、chChartTypePie 饼图、chChartType RadarLine 雷达线图、chChartTypeSmoothLine 平滑曲线图、chChartTypeDoughnut 环形图等等。
图18-5至18-10显示了部分图表的简单实例。
       
         图18-5 曲线图          图18-6 条形图          图18-7 面积图
       
         图18-8 环形图           图18-9 饼图          图18-10 雷达图
● Step4 设定图示说明
图示说明主要包括图例(用颜色表示数据类型)、图题(图表的标题)、XY轴的数据说明(一般用来说明各轴上的数据单位)。设定代码如下:
//指定图表是否需要图例
objChart.HasLegend = true;

//给定标题
objChart.HasTitle = true;
objChart.Title.Caption= "上半年月收入图";

//给定x,y轴的图示说明
objChart.Axes[0].HasTitle = true;
objChart.Axes[0].Title.Caption = "万元";
objChart.Axes[1].HasTitle = true;
objChart.Axes[1].Title.Caption = "月份";
● Step5 添加数据
添加数据主要设定Chart类对象的SeriesCollection属性。首先使用SeriesCollection的Add方法创建一组数据。然后使用SetData方法具体添加数据。代码如下:
(注意:数据的格式是以'/t'间隔的字符串)
//添加一组图表数据
objChart.SeriesCollection.Add(0);
//给定该组数据的名字
objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimSeriesNames,
+ (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral,”上半年收入”);
//给定数据分类
objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimCategories,
+ (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral,
"Jan"+'/t'+"Feb"+'/t'+"Mar"+'/t'+"Apr"+'/t'+"May"+'/t'+"Jun"+'/t' );
//给定数据值
objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimValues,
(int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral,
"100"+'/t'+"20"+'/t'+"50"+'/t'+"60"+'/t'+"240"+'/t'+"20"+'/t');
● Step6 显示数据
显示数据是使用Chart类对象的ExportPicture方法将生成的图表创建为图片,然后显示的。代码如下:
//输出成GIF文件,参数为文件名、格式、图片大小
objCSpace.ExportPicture(Server.MapPath("")+@"/tmpFile.gif", "GIF", 400, 300);
//从生成的图片创建Bitmap对象,输出到Response输出流
Bitmap myPalette = new Bitmap(Server.MapPath("")+@"/tmpFile.gif",true);
myPalette.Save(Response.OutputStream,System.Drawing.Imaging.ImageFormat.Gif);
经过了以上的步骤,将代码输入页面的PageLoad事件代码段中,运行程序就可以得到如图18-11效果。
        
        图18-11 Office Web Components柱状图示例
使用Office Web Components绘制饼图
绘制饼图与绘制柱状图的区别不是很大,需要注意的是饼图没有XY轴,所以不能设置XY轴的图示说明。在绘制柱状图的代码上去掉关于XY轴图示说明的代码即可。
完整代码如下:
//初始化图表数据
string [] DataName = {"Jan","Feb","Mar","Apr","May","Jun"};
int [] Data = {100,20,50,60,240,20};
//声明存储数据分类和数据值的字符串
string strDataName = "";
string strData = "";
//循环按格式生成存储数据分类与数据值的字符串
for(int i=0;i< Data.Length;i++)
{
strCategory += DataName[i]+'/t';
strValue += Data[i].ToString()+'/t';
}
//创建ChartSpace对象来放置图表
OWC.ChartSpace objCSpace = new OWC.ChartSpaceClass ();

//在ChartSpace对象中添加图表,Add方法返回chart对象
OWC.WCChart objChart = objCSpace.Charts.Add (0);

//指定图表的类型为饼图
objChart.Type = OWC.ChartChartTypeEnum.chChartTypePie;
//指定图表是否需要图例
objChart.HasLegend = true;
//给定标题
objChart.HasTitle = true;
objChart.Title.Caption= "上半年月收入图";

//添加一个series
objChart.SeriesCollection.Add(0);

//给定数据分类
objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimCategories,
+ (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral,strDataName);

//给定数据值
objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimValues,
(int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral,strData);
//输出成GIF文件.
objCSpace.ExportPicture(Server.MapPath("")+@"/tmpFile.gif", "GIF", 400, 300);
Bitmap myPalette = new Bitmap(Server.MapPath("")+@"/tmpFile.gif",true);
myPalette.Save(Response.OutputStream,System.Drawing.Imaging.ImageFormat.Gif);
将上述代码写入页面文件的PageLoad事件处理代码中,运行得到如图18-12效果。
         
        图18-12 Office Web Components饼图示例
公司盈利状况统计
前面介绍了Office Web Components的情况,本节将通过公司盈利状况统计来介绍Office Web Components柱状图在具体实例中的使用。
数据库设计
为了实现公司盈利状况统计。首先,需要设计相关的数据库表。在实际情况中,公司的盈利就是收入的总和与支出的总和之差。而每笔收入与支出都是在一次交易中完成的。基于以上考虑,同时为了实现简单。设计数据库表单如下:
表名 T_Deal 别名 交易表
表项      说明   类型     是否可空
DealTime   交易时间  DateTime     否
DealIncome  交易金额  int       否
DealContent  交易内容  Varchar(50)   否
DealObject  交易对象  Varchar(20)   是
Comment    备注    Varchar(50)   是
注意:为了简单起见,用交易金额统一表示收入与支出。用正数的交易金额表示收入,负数的交易金额表示支出。这样计算盈利时只需将交易金额求和即可。
按照上表的格式在SqlServer中创建表。添加样例数据供程序使用。
然后创建下面的存储过程来实现公司盈利状况的统计。
CREATE PROCEDURE sp_SelectIncome
@year int
AS

Select sum(DealCount),Datepart(mm,DealTime) From T_Deal
where DATEPART(yy,DealTime)=@year
Group By Datepart(mm,DealTime)
GO
该存储过程选择交易时间的年份与输入参数@year相等的数据,并将选择得到的数据按交易时间的月份分组。返回每组交易金额的总和以及该组的交易月份。
界面设计
新建Web工程WebChart。将WebForm1.aspx改名为OWCChart.aspx。同时,将其代码文件中的类名改为OWCChart。
界面如图18-13所示:
      
          图18-13 公司盈利统计界面
该界面主要包括两部分:一个PlaceHolder控件用来放置生成的图表构成显示图表部分。一个用来选择统计年份的DropDownList控件,一个用来确定生成图表的Button控件,一个用来显示错误信息的Label控件构成了图表的生成部分。
同样为了界面整洁使用Table将所用控件放在表格中。按照图18-13安排好界面后就可以为控件设置属性了,主要包括以下几个方面的设置:
● PlaceHolder控件的设置
PlaceHolder控件在本程序中用于放置生成的图表,只需设置其Id属性为ChartPlaceHolder即可。
● DropDownList控件的设置
DropDownList控件在本程序中用于选择统计年份,设置其Id属性为ddlYear。并为其添加ListItem 2000,2001,2002,2003。
<asp:ListItem Value="2000">2000</asp:ListItem>
<asp:ListItem Value="2001">2001</asp:ListItem>
<asp:ListItem Value="2002">2002</asp:ListItem>
<asp:ListItem Value="2003">2003</asp:ListItem>
● Button控件的设置
Button控件设置Id属性为btnSumbit,Text属性为“确定”即可。
● Label控件的设置
Label控件设置Id属性为Info即可。
代码实现
在完成了上面的界面设计后,就要进入后台代码的编写了。下面就将分模块介绍各部分功能的代码实现。
数据读入
为了显示公司盈利状况统计,首先需要将统计的结果从数据库中读入。读入数据的代码包括以下两部分。
● 创建数据库联接
为了方便程序的配置,将数据库联接字段保存在Web.Config文件中。如此一来,在需要修改数据库联接字段时只需要修改Web.Config文件即可,不需要修改程序代码,重新编译。
在Web.Config文件中的<configuration>字段中加入如下代码:
<appSettings>
<add key="ConnectStr"
value="server=localhost;uid=yourid;pwd=yourpas;database=Info;"/>
</appSettings>
其中localhost要改为自己的数据库服务器名,uid,pwd分别为数据库用户id和密码,database为数据库名。
设置好联接字段后就可在代码中对其进行引用了。
主要使用AppSettingReader对象的GetValue方法获取”ConnectStr”字段信息,该方法需要两个参数,第一个指定要引用的字段,第二个参数指定需要的类型。返回一个Object类型的变量。需要使用Convert的ToString方法将其转换为字符串类型
引用代码如下:
//全局数据库联接
System.Data.SqlClient.SqlConnection MyConnection;
private void Page_Load(object sender, System.EventArgs e)
{
// 在此处放置用户代码以初始化页面
if(Page.IsPostBack==false) // 页面首次加载时
{

//创建Web.Config文件应用程序设置字段读取对象
System.Configuration.AppSettingsReader ConnectionString = new System.Configuration.AppSettingsReader();
//创建数据库联接
MyConnection = new System.Data.SqlClient.SqlConnection();
//设置数据库联接的连接字段
MyConnection.ConnectionString = Convert.ToString(ConnectionString.GetValue("ConnectStr",System.Type.GetType("System.String")));
}
}
● 利用数据库联接读取数据
有了前面创建的数据库联接就可以从数据库中读取数据了。
读取数据代码如下:
//读取数据函数,参数为需要统计的年份,返回DataSet
DataSet ReadData(string Year)
{
//创建DataSet
DataSet dsIncome = new DataSet();
//设置存储过程名
string SpName = "sp_SelectIncome";
//创建Sql命令
SqlCommand IncomeCmd = new SqlCommand(SpName,MyConnection);
//设定数据库命令类型为存储过程
IncomeCmd.CommandType = CommandType.StoredProcedure;
//打开数据库联接
MyConnection.Open();
//创建并设定存储过程参数
SqlParameter IncomeYear = new SqlParameter("@year",SqlDbType.Int,4);
IncomeYear.Value=Convert.ToInt16(Year);
//为Sql命令添加参数
IncomeCmd.Parameters.Add(IncomeYear);
//创建Sql数据桥接器
SqlDataAdapter adapter = new SqlDataAdapter(SpName,MyConnection);
//指定桥接器Sql命令
adapter.SelectCommand = IncomeCmd;
//填充DataSet
adapter.Fill(dsIncome,"Income");
//关闭数据库联接
MyConnection.Close();
}
数据显示
使用ReadData方法读出数据,接下来就是显示数据了。显示数据同样需要两个步骤。
● 处理数据库读出的数据
由于从数据库读出的数据不能完全满足显示的要求,有可能某个月份没有交易,那么返回的DataSet中就不会包含该月的数据。但显示时需要所有月份的数据。所以直接显示数据之前先要对数据进行加工。代码如下:
//创建存储数据的数组,MyMonthIncome存放每月数据,MyMonthName存放月份缩写
int[] MyMonthIncome = new int[12];
string[] MyMonthName = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};

//声明存放显示用字符串的变量,strMonthName存放月份信息,strMonthIncome存放数据
string strMonthName = "";
string strMonthIncome = "";
//对存在数据的月份将数据保存在MyMonthName
for(int i=0;i< dsIncome.Tables["Income"].Rows.Count;i++)
{
MyMonthIncome[Convert.ToInt16(dsIncome.Tables["Income"].Rows[i][1])-1] = Convert.ToInt16(dsIncome.Tables["Income"].Rows[i][0]);
}
//用已有的数据来生成图表显示所需的字符串
for(int i=0;i< 12;i++)
{
strMonthName += MyMonthName[i]+'/t';
strMonthIncome += MyMonthIncome[i].ToString()+'/t';
}
● 使用Office Web Components显示数据
经过上一步骤,图表显示所需的字符串已经放入了strMonthName和strMonthIncome中,下面使用18.2节中关于Office Web Components的知识就可以大功告成了。需要注意的是在生成图片后使用了PlaceHolder的.Controls属性的Add方法将动态生成的<img>标签放入页面。为了方便后面的使用,将显示数据的代码写为函数。代码如下:
private void MakeLineChart(string Year)
{
//使用ReadData函数读出数据
DataSet dsIncome = ReadData(Year);
//以下插入处理数据库读出的数据部分的代码,不再重复
//….上一步骤中处理数据库读出数据代码

//创建ChartSpace对象来放置图表
OWC.ChartSpace mySpace = new OWC.ChartSpaceClass ();
//在ChartSpace对象中添加图表,Add方法返回chart对象
OWC.WCChart myChart = mySpace.Charts.Add (0);

//指定图表的类型为线性图
myChart.Type = OWC.ChartChartTypeEnum.chChartTypeLine;
//指定图表是否需要图例
myChart.HasLegend = true;
//给定标题
myChart.HasTitle = true;
myChart.Title.Caption= ddlYear.SelectedItem.Text + "月收入图";
//给定x,y轴的图示说明
myChart.Axes[0].HasTitle = true;
myChart.Axes[0].Title.Caption = "万元";
myChart.Axes[1].HasTitle = true;
myChart.Axes[1].Title.Caption = "月份";
//添加一个series
myChart.SeriesCollection.Add(0);
//给定series的名字
myChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimSeriesNames,
+ (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral, strSeriesName);
//给定分类
myChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimCategories,
+ (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral, strCategory);
//给定值
myChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimValues,
(int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral, strValue);
//输出成GIF文件.
string strAbsolutePath = (Server.MapPath(".")) + @"/images/tempFile.gif";
mySpace.ExportPicture(strAbsolutePath, "GIF", 700, 350);
//创建GIF文件的相对路径.
string strRelativePath = "./images/tempFile.gif”
//生成显示图片的<img>标签
string strImageTag = "<IMG SRC='" + strRelativePath + "'/>";
//把图片添加到placeholder.
ChartPlaceHolder.Controls.Add(new LiteralControl(strImageTag));
18.3.3.3 按钮点击事件
有了前面的MakeLineChart函数,在aspx页面的设计模式下双击btnSumbit创建按钮点击事件。修改代码如下:
private void btnSubmit_Click(object sender, System.EventArgs e)
{
MakeLineChart(ddlYear.SelectedItem.Text);
}
至此,公司盈利状况统计功能完全实现,运行结果如图18-16:
        
         图18-16 公司盈利状况统计效果
公司收入分块图
上一节介绍了Office Web Components的柱状图的使用,实现了对公司盈利状况统计。本节将通过公司收入分块图的实现来介绍Office Web Components中饼装图的使用。
数据库设计
为了实现公司收入分块图,为T_Deal表增添交易类别字段。扩充后的T_Deal表如下:
表名 T_Deal 别名 交易表
表项      说明   类型     是否可空
DealTime   交易时间  DateTime     否
DealIncome  交易金额  int       否
DealContent  交易内容  Varchar(50)   否
DealObject  交易对象  Varchar(20)   是
DealCategory 交易类别  Varchar(20)   否
Comment     备注   Varchar(50)   是
按照新表的格式重新在SqlServer中创建表。添加样例数据供程序使用。并且创建如下存储过程实现公司收入分块统计。
CREATE PROCEDURE sp_SelectCategory
@year int
AS

Select sum(DealCount),DealCategory From T_Deal
where DATEPART(yy,DealTime)=@year
Group By DealCategory
GO
该存储过程选择交易时间的年份与输入参数@year相等的数据,并将选择得到的数据按交易类别分组。返回每组交易金额的总和以及该组的交易类别。
界面设计
为了简便同时利用已有成果,在现有的基础上修改无疑是最好的选择。因此,本节的程序直接在上一节的程序上修改。在原有界面上添加一个DropDownList来选择不同的图表内容。新的界面如图18-17:
      
         图18-17 公司收入分布界面
新增的DropDownList属性设置为Id=ddlChartType,并为其添加Item
<asp:ListItem Value="Income">公司盈利状况</asp:ListItem>
<asp:ListItem Value="Category">公司收入分块图</asp:ListItem>
代码实现
在完成了上面的界面设计后,就要进入后台代码的编写了。由于是在上一节的基础上,所以只需增加新功能。
数据读入
由于已经有了创建数据库联接部分,下面只需要读出数据即可。数据读入部分代码与上一节的代码相似,不同之处只是所调用的存储过程不同,为了简化代码,修改ReadData函数,为其增加参数SpName 指定调用的存储过程。将原有程序中声明SpName的语句删除即可。
//读取数据函数,参数Yesr为需要统计的年份SpName为调用存储过程名,返回DataSet
DataSet ReadData(string Year,string SpName)
{
//创建DataSet
DataSet dsIncome = new DataSet();
//设置存储过程名,通过新增参数完成,将此句去除
//string SpName = "sp_SelectIncome";
//以下部分不做修改,不再重复

}
注意:修改ReadData函数后,在上一节MakeLineChart函数中调用ReadData的代码需要为其增加参数。
private void MakeLineChart(string Year)
{
//使用ReadData函数读出数据
DataSet dsIncome = ReadData(Year,“sp_SelectIncome”);
//以下部分不做修改

}
数据显示
使用ReadData方法读出数据,接下来就是显示数据了。显示数据的代码也只需对上一节代码做部分修改即可。声明绘制分类收入的函数,将MakeLineChart函数内容复制并修改如下:
private void MakePieChart(string Year)
{
//使用ReadData函数读出数据
DataSet dsCategory = ReadData(Year);
//创建存储数据的数组,MyCategory存放类别数据,MyMonthName存放类别名称
int[] MyCategory = new int[dsIncome.Tables["Income"].Rows.Count];
string[] MyCategoryName = new string[dsIncome.Tables["Income"].Rows.Count];

//声明存放显示用字符串的变量,strMonthName存放月份信息,strMonthIncome存放数据
string strCategoryName = "";
string strCategory = "";
//声明总收入,用来计算各分类收入百分比
int IncomeSum = 0;
//将数据放入数组,同时计算总收入
for(int i=0;i< dsIncome.Tables["Income"].Rows.Count;i++)
{
MyCategory[i] = Convert.ToInt16(dsIncome.Tables["Income"].Rows[i][0]);
MyCategoryName[i] = Convert.ToString(dsIncome.Tables["Income"].Rows[i][1]);
IncomeSum += MyCategory[i];
}
//用已有的数据来生成图表显示所需的字符串
for(int i=0;i< dsIncome.Tables["Income"].Rows.Count;i++)
{
//计算出各分类所占百分比
int PercentCategory= 100*MyCategory[i]/IncomeSum;
strCategory += MyCategoryName[i]+" "+PercentCategory.ToString()+ "%"+'/t';
strValue += MyCategory[i].ToString()+'/t';
}
//下面代码与上一节基本相同不再重复
//仅给出需要修改的部分

//指定图表的类型为线性图 改为饼图
myChart.Type = OWC.ChartChartTypeEnum.chChartTypePie;
//指定图表是否需要图例
myChart.HasLegend = true;
//给定标题
myChart.HasTitle = true;
myChart.Title.Caption= ddlYear.SelectedItem.Text + "收入图";
//给定x,y轴的图示说明 ,去掉XY轴图示说明部分
/*
myChart.Axes[0].HasTitle = true;
myChart.Axes[0].Title.Caption = "万元";
myChart.Axes[1].HasTitle = true;
myChart.Axes[1].Title.Caption = "月份";
*/

}
18.3.3.3 按钮点击事件
由于增加了新功能,按钮点击的代码修改如下:
private void btnSubmit_Click(object sender, System.EventArgs e)
{
//根据ddlChartType的选项判断执行的内容
if(ddlChartType.SelectedItem.Value=="Income")
MakeLineChart(ddlYear.SelectedItem.Text); //显示公司盈利统计
else if(ddlChartType.SelectedItem.Value=="Category")
MakePieChart(ddlYear.SelectedItem.Text);//显示收入分布
}
至此,公司盈利状况统计功能完全实现,运行后选择收入分布点击确定按钮。结果如图18-18:
       
        图18-18 公司收入分块图效果
报表产出
前面的几个小节完成了对数据的统计并以图表的形式呈现给用户,使用户能够一目了然的获取所需信息。这一节将把统计结果以Excel报表的形式输出,以免用户提交报表时手工输入的麻烦,提高工作效率。
报表产出主要使用了Office Web Components的Spreadsheet控件。利用该控件创建并编辑数据表格,并将最终结果输出到Excel报表。步骤如下:
● Step1创建SpreadsheetClass对象,用来放置数据表格
类似于Chart控件中的ChartSpace,Spread控件中也需要创建一个放置SpreadsheetClass的对象作为单个表的容器。
SpreadsheetClass exl = new SpreadsheetClass();
● Step2利用SpreadsheetClass的ActiveSheet获得当前处于活动状态的表格
一个SpreadsheetClass对象就相当于一个运行中的Excel,通过其ActiveSheet属性能够得到当前处于活动状态的表格。一个Worksheet对象就相当于Excel中的一张表格。将SpreadsheetClass对象的ActiveSheet属性赋值给Worksheet对象。就可以在后面的代码中对表格进行操作了。
OWC.Worksheet ws = exl.ActiveSheet;
● Step3 编辑表格
编辑表格使用的是Worksheet对象的Cells属性。Cells属性就代表着表格中的每个单元格。使用Cells[row,col]的格式引用,row表示行号,col表示列号。需要注意的是行号和列号都是从1开始的,而不是像C#的数组是从0开始。例如Cells[2,2]就表示表格的第二行,第二列的单元格。下面是产生盈利状况统计报表的编辑表格代码(该段代码添加在MakePieChart函数末尾,其中的变量延用之前的声明):
//为表格设定标题
ws.Cells[1, 1] = "收入(万元)";
ws.Cells[1,2] = "类别";
ws.Cells[1,3] = "所占比重";
//将数据写入表格
for(int i=0;i<dsIncome.Tables[0].Rows.Count;i++)
{
ws.Cells[i+2,1] = MyCategory[i].ToString();
ws.Cells[i+2,2] = MyCategoryName[i];
int Percent = MyMonthIncome[i]*100/IncomeSum;
ws.Cells[i+2,3] = Percent.ToString() + "%";
}
//将总收入写入表格
ws.Cells[dsIncome.Tables[0].Rows.Count + 2,1] = IncomeSum.ToString();
ws.Cells[dsIncome.Tables[0].Rows.Count + 2,2] = "总和";
ws.Cells[dsIncome.Tables[0].Rows.Count + 2,3] = "100%";
Step4 导出表格
导出表格使用Worksheet对象的Export方法,将表格导出为Excel文件即可。考虑到可能出现异常,使用了try,catch来捕获可能出现的异常,输出错误信息。
try
{
//输出Excel报表到服务器文件系统
ws.Export(Server.MapPath(" ") + @"/Excel/report.xls", OWC.SheetExportActionEnum.ssExportActionNone);
}
catch
{
//错误时输出错误提示
Info.Text = "保存报表错误,请与管理员联系";
}
将上述代码添加到MakePieChart函数的末尾,重新运行,在工程所在文件夹下的子Excel目录中就会有report.xls文件。其结果如图18-19。
       
        图18-19 生成报表结果图
小结
这一章先对ASP.NET中生成统计图表进行了介绍,然后对GDI+与Office Web Components的使用进行了详细说明,为后面做好了知识储备。随后利用公司盈利状况统计和公司收入分块图两个实例详细的介绍了如何利用Office Web Components与数据库结合绘制统计图表以及生成报表。
通过本章的学习,读者对于.NET中统计报表的生成有了深刻的理解,相信精美、清晰的报表一定会为成为Web程序的亮点。

原文:http://www.cnblogs.com/sgsoft/articles/68025.html

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐