创建动态折线图






1.05/5 (16投票s)
2006年5月25日
19分钟阅读

101219
创建动态折线图
引言
从数据库数据创建折线图
本文介绍了如何使用VB.NET为Web窗体创建折线图。我认为市面上已经有许多用于创建折线图和图表的第三方组件。它们不会让你了解其内部工作原理。因此,我使用VB.NET中的GDI+创建了一个折线图。此外,你还将能够快速创建折线图。
 使用代码
以下是用于创建折线图的函数代码
1)为它创建一个另一个vb类文件,该文件将根据用户会话创建折线图 :===
类文件的代码已经完成,现在我们需要创建一个实例
此文件在需要折线图的Web窗体中,并设置适当的属性。
这里我以得分对比报告为例(日期 vs. 离职率和缺勤率)
此类文件 将根据您从数据库中提取的数据值生成折线图。
使用折线图绘制折线图以比较两支球队的得分。
折线图vb类文件名(如(LineChartAbs.vb)代码
‘导入这些命名空间
Imports System.Data
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging
Imports System.Web.UI
Public Class LineChartAbs
    Public b As Bitmap
    Public Title As String = "默认标题"
    Public chartValues As ArrayList = New ArrayList
    Public Xorigin As Single = 0
    Public Yorigin As Single = 0
    Public ScaleX As Single
    Public ScaleY As Single
    Public Xdivs As Single = 2
    Public Ydivs As Single = 2
    Private Width As Integer
    Private Height As Integer
    Private g As Graphics
    Private p As Page
    Private btn As Button
    Structure datapoint
        Public x As Single
        Public y As Single
        Public xCaption As String
        Public yCaption As String
        Public ATTRAVERAGE As String
        Public valid As Boolean
    End Structure
    Public Sub New(ByVal myWidth As Integer, ByVal myHeight As Integer, ByVal myPage As Page)
        Width = myWidth
        Height = myHeight
        ScaleX = myWidth
        ScaleY = myHeight
        b = New Bitmap(myWidth, myHeight)
        g = Graphics.FromImage(b)
        p = myPage
    End Sub
 
    Public Sub AddValue(ByVal x As Integer, ByVal y As Double, ByVal xCaption As String, ByVal yCaption As String)
        Dim myPoint As datapoint
        myPoint.x = x
        myPoint.y = y
        myPoint.xCaption = xCaption
        myPoint.yCaption = yCaption
        'myPoint.ATTRAVERAGE = ATTRAVERAGE
        myPoint.valid = True
        chartValues.Add(myPoint)
    End Sub
    Public Sub AddValueN(ByVal x As Integer, ByVal y As Double, ByVal xCaption As String, ByVal ATTRAVERAGE As String)
        Dim myPoint As datapoint
        myPoint.x = x
        myPoint.y = y
        myPoint.xCaption = xCaption
        'myPoint.yCaption = yCaption
        myPoint.ATTRAVERAGE = ATTRAVERAGE
        myPoint.valid = True
        chartValues.Add(myPoint)
    End Sub
    Public Sub AddValue(ByVal x As Integer, ByVal y As Double)
        AddValue(x, y, x.ToString, y.ToString())
         
    End Sub
    Public Sub DisplayValues()
        Dim i As Integer
        Dim Labelvalue As String
        Dim blackBrushN As Brush = New SolidBrush(Color.Black)
        Dim axesFontN As Font = New Font("arial", 10)
        Dim ChartInset As Integer = 500
        Dim ChartWidth As Integer = Width - (2 * ChartInset)
        Dim ChartHeight As Integer = Height - (2 * ChartInset)
        For i = 0 To chartValues.Count
            If i >= chartValues.Count Then
                Labelvalue = ""
            Else
    Labelvalue = CType(chartValues(i), datapoint).xCaption
    Labelvalue = Labelvalue & "-" & CType(chartValues(i), datapoint).yCaption
 
    g.DrawString(Labelvalue, axesFontN, blackBrushN, Width + 1, Height)
      
            End If
        下一篇
    End Sub
    'Public Sub Draw(ByVal filename As String)
        Public Sub Draw()
        Dim i As Integer
        Dim x As Single
        Dim y As Single
        Dim y1, y2 As Single
        Dim x0 As Single
        Dim y0 As Single
        Dim PrintAonDot As Integer
        Dim myLabel As String
        Dim d1 As String
        Dim m1, m2, m3 As String
        Dim blackPen As Pen = New Pen(Color.Black, 1)
        Dim RedPen As Pen = New Pen(Color.FromArgb(186, 5, 5), 1)
        Dim bluePen As Pen = New Pen(Color.Blue, 1)
        Dim blueBrush As Brush = New SolidBrush(Color.Blue)
        Dim RedBrush As Brush = New SolidBrush(Color.FromArgb(109, 44, 0))
        Dim MarunBrush As Brush = New SolidBrush(Color.FromArgb(109, 44, 0))
        Dim blackBrush As Brush = New SolidBrush(Color.Black)
        Dim axesFont As Font = New Font("verdana", 8, FontStyle.Bold)
        p.Response.ContentType = "image/jpeg"
        'g.FillRectangle(New SolidBrush(Color.LightYellow), 0, 0, Width, Height)
        g.FillRectangle(New SolidBrush(Color.FromArgb(255, 216, 189)), 0, 0, Width, Height)
        'Dim ChartInset As Integer = 50   旧测试更改
        Dim ChartInset As Integer = 50
        Dim ChartWidth As Integer = Width - (2 * ChartInset)
        Dim ChartHeight As Integer = Height - (2 * ChartInset)
        g.DrawRectangle(New Pen(Color.Blue, 1), ChartInset, ChartInset, ChartWidth, ChartHeight)
        btn = New Button
        btn.ID = "btnBack"
        btn.Text = "deepchand"
g.DrawString(Title, New Font("verdana", 8, FontStyle.Bold), blueBrush, Width / 6, 5)
        i = 0
        i = 0
        While i <= Xdivs
            x = ChartInset + (i * ChartWidth) / Xdivs
            y = ChartHeight + ChartInset
            'myLabel = (Xorigin + (ScaleX * i / Xdivs)).ToString
            ' 此代码用于在格式中打印X轴值
            If i >= chartValues.Count Then
                'If i > chartValues.Count Then
                myLabel = "天数->" & vbCrLf & " "
                g.DrawString(myLabel, axesFont, blueBrush, x - 15, y + 10)
            Else
                'myLabel = CType(chartValues(i - 1), datapoint).xCaption  更改
                myLabel = CType(chartValues(i), datapoint).xCaption
                d1 = myLabel.Substring(0, 2).ToString
                m1 = myLabel.Substring(3, 3).ToString
                myLabel = d1 & vbCrLf & m1
                g.DrawString(myLabel, axesFont, blackBrush, x - 10, y + 10)
            End If
            'g.DrawString(myLabel, axesFont, blackBrush, x - 8, y + 10)
            g.DrawLine(blackPen, x, y + 2, x, y - 2)
            If i < chartValues.Count Then
                '' 在点上打印缺勤百分比
                myLabel = CType(chartValues(i), datapoint).yCaption
x = (ChartWidth * (CType(chartValues(i), datapoint).x - Xorigin) / ScaleX) + ChartInset
y = ChartHeight - (ChartHeight * (CType(chartValues(i), datapoint).y - Yorigin) / ScaleY) + ChartInset - 15
       g.DrawString(myLabel, axesFont, blackBrush, x - 10, y - 5)
                ''End 在点上打印缺勤百分比
            End If
            System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)
        End While
        i = 0
        i = 0 
        While i <= Ydivs
            x = ChartInset
            y = ChartHeight + ChartInset - (i * ChartHeight / Ydivs)
            myLabel = (Yorigin + (ScaleY * i / Ydivs)).ToString & "%"
            If i = Ydivs Then
                Dim s1 As StringFormat = New StringFormat(StringFormatFlags.DirectionVertical)
                myLabel = "<-缺勤"
                g.DrawString(myLabel, axesFont, blueBrush, 15, y - 45, s1)
            ElseIf (i Mod 5) = 0 Then
               g.DrawString(myLabel, axesFont, blackBrush, 20, y - 6)
            Else
                myLabel = ""
                g.DrawString(myLabel, axesFont, blackBrush, 20, y - 6)
            End If
            g.DrawLine(blackPen, x + 2, y, x - 2, y)
            
            System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)
        End While
        g.RotateTransform(180)
        g.TranslateTransform(0, -Height)
        g.TranslateTransform(-ChartInset, ChartInset)
        g.ScaleTransform(-1, 1)
        Dim prevPoint As datapoint = New datapoint
        prevPoint.valid = False
        i = 0
        For Each myPoint As datapoint In chartValues
            If prevPoint.valid = True Then
                x0 = ChartWidth * (prevPoint.x - Xorigin) / ScaleX
                y0 = ChartHeight * (prevPoint.y - Yorigin) / ScaleY
                'y1 = ChartHeight * (prevPoint.ATTRAVERAGE - Yorigin) / ScaleY
                x = ChartWidth * (myPoint.x - Xorigin) / ScaleX
                y = ChartHeight * (myPoint.y - Yorigin) / ScaleY
                'y2 = ChartHeight * (myPoint.ATTRAVERAGE - Yorigin) / ScaleY
                g.DrawLine(bluePen, x0, y0, x, y)
                g.FillEllipse(blueBrush, x0 - 2, y0 - 2, 6, 6)
                g.FillEllipse(blueBrush, x - 2, y - 2, 6, 6)
            End If
            prevPoint = myPoint
            i = i + 1
        下一篇
        b.Save(p.Response.OutputStream, ImageFormat.Jpeg)
        b.Dispose()
‘ 您在 ASPX 页面传递文件名时取消注释此代码 2005 年 11 月 18 日
        'b.Save("d:\Graph\Absent.gif", ImageFormat.Gif)         
 ''''开始此代码行将输出保存为指定位置的图像
        'Try
        '    b.Save(filename, ImageFormat.Gif)
        '    b.Dispose()
        'Catch ex As Exception
        '    'Response.Write("error:" & ex.Message.ToString)
        'End Try
        ''''结束此代码行将输出保存为指定位置的图像
    End Sub
    Public Sub DrawAverage()
        Dim i As Integer
        Dim x As Single
        Dim y As Single
        Dim x0 As Single
        Dim y0 As Single
        Dim PrintAonDot As Integer
        Dim myLabel As String
        Dim d1 As String
        Dim m1, m2, m3 As String
        Dim blackPen As Pen = New Pen(Color.Black, 1)
        Dim bluePen As Pen = New Pen(Color.Blue, 1)
        Dim blueBrush As Brush = New SolidBrush(Color.Blue)
        Dim blackBrush As Brush = New SolidBrush(Color.Black)
        Dim axesFont As Font = New Font("verdana", 8, FontStyle.Bold)
        p.Response.ContentType = "image/jpeg"
        'g.FillRectangle(New SolidBrush(Color.LightYellow), 0, 0, Width, Height)
g.FillRectangle(New SolidBrush(Color.FromArgb(255, 216, 189)), 0, 0, Width, Height)
        'Dim ChartInset As Integer = 50   旧测试更改
        Dim ChartInset As Integer = 50
        Dim ChartWidth As Integer = Width - (2 * ChartInset)
        Dim ChartHeight As Integer = Height - (2 * ChartInset)
        g.DrawRectangle(New Pen(Color.Blue, 1), ChartInset, ChartInset, ChartWidth, ChartHeight)
        'g.DrawString(Title, New Font("arial", 14), blackBrush, Width / 3, 10)
        g.DrawString(Title, New Font("verdana", 8, FontStyle.Bold), blueBrush, Width / 6, 5)
        i = 0
        i = 0
        While i <= Xdivs
            x = ChartInset + (i * ChartWidth) / Xdivs
            y = ChartHeight + ChartInset
            ' 此代码用于在格式中打印X轴值
            If i >= chartValues.Count Then
                myLabel = "周数->" & vbCrLf & " "
                'g.DrawString(myLabel, axesFont, blueBrush, x - 17, y + 10)
            Else
                'myLabel = CType(chartValues(i - 1), datapoint).xCaption  更改
                myLabel = CType(chartValues(i), datapoint).xCaption
                d1 = myLabel.Substring(0, 2).ToString
                m1 = myLabel.Substring(3, 3).ToString
                myLabel = d1 & vbCrLf & m1
            End If
            g.DrawString(myLabel, axesFont, blackBrush, x - 8, y + 10)
            g.DrawLine(blackPen, x, y + 2, x, y - 2)
            If i < chartValues.Count And i >= 3 Then
                '' 打印平均离职率百分比到点上
                myLabel = CType(chartValues(i), datapoint).ATTRAVERAGE
                x = (ChartWidth * (CType(chartValues(i), datapoint).x - Xorigin) / ScaleX) + ChartInset
                y = ChartHeight - (ChartHeight * (CType(chartValues(i), datapoint).y - Yorigin) / ScaleY) + ChartInset - 15
                g.DrawString(myLabel, axesFont, blackBrush, x, y)
                ''End 打印平均离职率百分比到点上
            End If
            System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)
        End While
        i = 0
        i = 0
        While i <= Ydivs
            x = ChartInset
            y = ChartHeight + ChartInset - (i * ChartHeight / Ydivs)
            myLabel = (Yorigin + (ScaleY * i / Ydivs)).ToString & "%"
            'g.DrawString(myLabel, axesFont, blackBrush, 5, y - 6) 旧测试更改
            g.DrawString(myLabel, axesFont, blackBrush, 25, y - 6)
            g.DrawLine(blackPen, x + 2, y, x - 2, y)
            System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)
        End While
        g.RotateTransform(180)
        g.TranslateTransform(0, -Height)
        g.TranslateTransform(-ChartInset, ChartInset)
        g.ScaleTransform(-1, 1)
        Dim prevPoint As datapoint = New datapoint
        prevPoint.valid = False
        i = 0
        For Each myPoint As datapoint In chartValues
            If prevPoint.valid = True Then
                x0 = ChartWidth * (prevPoint.x - Xorigin) / ScaleX
                y0 = ChartHeight * (prevPoint.y - Yorigin) / ScaleY
                x = ChartWidth * (myPoint.x - Xorigin) / ScaleX
                y = ChartHeight * (myPoint.y - Yorigin) / ScaleY
                'If CType(chartValues(i), datapoint).ATTRAVERAGE.Trim > 0 Then
                'g.DrawLine(bluePen, x0, y0, x, y)
                'End If
                If i >= 3 Then
                    g.DrawLine(bluePen, x0, y0, x, y)
                    g.FillEllipse(blueBrush, x0 - 2, y0 - 2, 6, 6)
                    g.FillEllipse(blueBrush, x - 2, y - 2, 6, 6)
                End If
                i = i + 1
            End If
            'myLabel = myPoint.yCaption
            'g.DrawString(myLabel, axesFont, blackBrush, x0 + 1, y0 + 1)
            prevPoint = myPoint
        下一篇
        b.Save(p.Response.OutputStream, ImageFormat.Jpeg)
    End Sub
    Protected Overrides Sub Finalize()
        g.Dispose()
        b.Dispose()
    End Sub
End Class
*************************************************************************************************
2) 为此创建一个ASPX页面,名为Display.aspx,用于创建LineChart函数。
*********************************************************************
‘导入这些命名空间
Imports System.Data
Imports System.Data.OracleClient
   ‘ 变量声明
    Dim orclCommand As OracleCommand
    Dim rdr As OracleDataReader
    Private OraCn As New OracleConnection(ConfigurationSettings.AppSettings("connString"))  'OracleConnection()
    '注意:Web窗体设计器需要以下占位符声明。
    '请勿删除或移动它。
    Private designerPlaceholderDeclaration As System.Object
    Dim Itm As ListItem
    Dim Sqlstr As String
‘该页面的Page_Load事件
    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        If Not Page.IsPostBack Then
            Session("numSelIndex") = 0
            Sqlstr = "用于获取日期范围的SQL查询"
            OraCn.Open()
            orclCommand = New OracleCommand(Sqlstr, OraCn)
            rdr = orclCommand.ExecuteReader
            Itm = New ListItem
            Itm.Text = "---选择---"
            Itm.Value = ""
            Itm.Selected = True
            CmbFrWeek.Items.Add(Itm)
            CmbToWeek.Items.Add(Itm)
            While rdr.Read
                Itm = New ListItem
                Itm.Text = rdr.GetValue(0)
                Itm.Value = rdr.GetValue(0)
                CmbFrWeek.Items.Add(Itm)
                CmbToWeek.Items.Add(Itm)
            End While
            rdr.Close()
            OraCn.Close()
           
        End If
    End Sub
    Private SubBtnReport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnReport.Click
        Dim NoOfWeek As Integer
        Dim Enddate, M As String
        Dim StartDate, Enddate1 As String
        Dim TotalPer, RowNo As Integer
        Dim DynWdith As Integer
        Dim XFromDate As String
        Dim XFromDate1 As Integer
        Dim YattritionPer, YattritionPerAvg As Double
        Dim Grdflag As Boolean = True
        试试
            If CmbToWeek.SelectedIndex < 1 And CmbFrWeek.SelectedIndex < 1 Then
                Label9.Text = "请选择正确的日期"
                Label9.Visible = True
                flgFormSubmit.Value = 0
                Exit Sub
            ElseIf (CmbToWeek.SelectedIndex - CmbFrWeek.SelectedIndex) < 4 Then  
                Label9.Text = "选择的日期应该超过5天"
                flgFormSubmit.Value = 0
                Label9.Visible = True
                Exit Sub
            ElseIf CmbToWeek.SelectedIndex <= CmbFrWeek.SelectedIndex Then
                Label9.Text = "开始日期必须小于结束日期"
                flgFormSubmit.Value = 0
                Label9.Visible = True
                Exit Sub
            ElseIf (CmbToWeek.SelectedIndex - CmbFrWeek.SelectedIndex) > 31 Then
                Label9.Text = "日期不能选择超过一个月"
                Label9.Visible = True
                flgFormSubmit.Value = 0
                Exit Sub
            Else
                Label9.Text = ""
            End If
          Label9.Text = ""
            If CmbFrWeek.SelectedIndex = 1 Then
                Enddate = "2003年5月24日"
            Else
                Enddate = CmbFrWeek.Items(CmbFrWeek.SelectedIndex - 1).Value
            End If
            NoOfWeek = (CmbToWeek.SelectedIndex - CmbFrWeek.SelectedIndex) + 2
            ' 此代码用于
            OraCn.Open()
‘创建用于存储图形主数据的全局临时表
 '将显示在折线图中的表格
            Dim cmd As New OracleCommand("Proc_Absent_New", OraCn)
            cmd.CommandType = CommandType.StoredProcedure
            Dim FromWeek As OracleParameter = cmd.Parameters.Add("frmDay", OracleType.DateTime)
            FromWeek.Direction = ParameterDirection.Input
            FromWeek.Value = UCase(Trim(Enddate.ToString()))
            Dim NoOfWeeks As OracleParameter = cmd.Parameters.Add("NoOfDays", OracleType.Int32, 20)
            NoOfWeeks.Direction = ParameterDirection.Input
            NoOfWeeks.Value = UCase(Trim(NoOfWeek.ToString()))
            cmd.ExecuteNonQuery()
            cmd.Dispose()
‘创建用于存储图形主数据的全局临时表
 '将显示在折线图中的表格
            Sqlstr = "SELECT COUNT(*)RowNo,ROUND(MAX(absentper)+1) FROM ABSENT_TEMP "
            'OraCn.Open()
            orclCommand = New OracleCommand(Sqlstr, OraCn)
            rdr = orclCommand.ExecuteReader
            While rdr.Read()
                TotalPer = rdr.GetValue(1)
                DynWdith = rdr.GetValue(1)
                RowNo = rdr.GetValue(0)
            End While
            rdr.Close()
            orclCommand.Dispose()
            
'****此代码用于绘图类声明对象
'****从临时表中选择值
            Sqlstr = "select Fromday,ABSENTPER, rownum,to_char(Fromday, 'dd-Mon') fdate from ABSENT_TEMP "
            orclCommand = New OracleCommand(Sqlstr, OraCn)
            rdr = orclCommand.ExecuteReader
            StartDate = CmbToWeek.Items(CmbToWeek.SelectedIndex).Value
            Enddate1 = CmbFrWeek.Items(CmbFrWeek.SelectedIndex).Value
‘创建我们之前创建的折线图类的对象
            Dim c1 As LineChartAbs = New LineChartAbs(RowNo * 50, 550, Page)
            c1.Title = "  缺勤图  " & vbCrLf & "  " & Convert.ToDateTime(Enddate1).ToString("dd/MM/yyyy") & "-" & Convert.ToDateTime(StartDate).ToString("dd/MM/yyyy")
           
            c1.Xorigin = 0
            c1.ScaleX = NoOfWeek - 0
            c1.Xdivs = NoOfWeek - 0
            c1.Yorigin = 0
            If TotalPer > 12 Then
                c1.ScaleY = Math.Ceiling(TotalPer / 10) * 10
                c1.Ydivs = CInt((Math.Ceiling(TotalPer / 10) * 10))
            Else
                c1.ScaleY = TotalPer    '如果缺勤百分比小于10%,则实现此比例
                c1.Ydivs = CInt(TotalPer) * 5
                
            End If
            'c1.ScaleY = 100
            'c1.Ydivs = 50
            While rdr.Read
                
    XFromDate = rdr.GetValue(2) - 1
                XFromDate1 = CType(XFromDate, Integer) * 1
                YattritionPer = rdr.GetValue(1)
                c1.AddValue(XFromDate1, YattritionPer, rdr.GetValue(3), rdr.GetValue(1))
            End While
            rdr.Close()
            c1.Draw()
''''开始此代码行将输出保存为指定位置的图像
            Dim strFilePath, strUser As String
            Dim strPath As String
            Session("login") = "Absenteesimg"
            strUser = Session("login")
            试试
                strFilePath = Server.MapPath(".") & "/Graphs/" & strUser & ".gif"
            Catch ex As Exception
                Response.Write("Error:" & ex.Message.ToString)
            End Try
            c1.Draw(strFilePath)
            Response.Redirect("Graph.aspx")
            '在此结束,正确显示
        Catch ex As Exception
                Response.Write("Error Occured" & ex.StackTrace)
            最后
                OraCn.Close()
                'Label9.Text = ""
                'Session("numSelIndex") = CmbToWeek.SelectedIndex
                'Session("formsubmit") = 0
            End Try
    End Sub
End Class
******************************************************************************
3) 创建一个名为Graph.aspx的文件,并写入以下代码。
在此页面中调用由上一个Display ASPX页面生成的Generate Graph。
'**********************************************************************
在其中放置一个图像控件,并调用已保存的图形。
IMG TAGE设置图像的路径。
src="Graphs\Absenteesimg.gif"
优点:
         1)    多个用户可以同时访问。
2)      根据用户会话生成图像(图表)。
3)      以报表形式将gif图像与数据导出到Excel文件。
4)      为每个用户请求生成动态图表。
数据的图形表示,使用户更容易理解系统数据的输出。 
*****************************************************************************
可能的增强功能
 CreatePieChart 函数缺乏第三方图形组件可能带来的冲击力和吸引力,但该函数仅用不到15分钟的时间就创建出来了,成本为零(除了我的时间),最重要的是,源代码随处可见,方便您进行任何未来的修改或增强。
CreatePieChart 函数缺乏第三方图形组件可能带来的冲击力和吸引力,但该函数仅用不到15分钟的时间就创建出来了,成本为零(除了我的时间),最重要的是,源代码随处可见,方便您进行任何未来的修改或增强。 CreatePieChart 函数的一个可能增强之处是添加传递SQL字符串而不是数据库表名的功能。目前,CreatePieChart 图只能为具有非常简单数据模型的数据库创建饼图。能够指定SQL字符串意味着您可以创建来自多个表的数据的图表,或者通过指定WHERE子句来仅绘制数据库表中的某些行。
CreatePieChart 函数的一个可能增强之处是添加传递SQL字符串而不是数据库表名的功能。目前,CreatePieChart 图只能为具有非常简单数据模型的数据库创建饼图。能够指定SQL字符串意味着您可以创建来自多个表的数据的图表,或者通过指定WHERE子句来仅绘制数据库表中的某些行。
