Gráficos tipo torta en ASP.NET

Fecha: 16/Oct/2004 (13/Oct/2004)
Autor: Adrian Sergio Pulvirenti - adripulvi @ hotmail.com

 


Una alternativa para mostrar y comparar datos eficientemente es la posibilidad de incluir gráficos estadisticos en nuestros reportes. Para realizar esto, con versiones anteriores de VB o con ASP era practicamente imposible, o era necesario conseguir algun control de terceros que ya este funcionando en el mercado.
El objetivo de este ejemplo es demostrarles que con la clase Drawings ahora todo mucho mas sencillo. Les mostrare como crear un grafico comparativo de torta y con la misma idea pueden adaptarlo para crear graficos de barra, o pensar en graficos 3D.

A fines de ejemplo, voy a usar una base de datos que contiene tareas realizadas en una empresa y las horas usadas para cada tarea. Y el grafico de torta representara la cantidad de horas dedicadas a cada tarea.
El siguiente grafico es una salida real del codigo que mostrare a continuación:

El código está dividido en dos partes, la primera solo muestra como obtengo los datos, y la segundaes la que hace todo el trabajo (la clase del grafico propiamente dicho)

 

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim sConn As SqlConnection
    Dim comTabla As New SqlCommand()
    Dim ds As DataSet = New DataSet()
    Dim daTabla As New SqlDataAdapter()
    'Se crea una conexion
    sConn = New SqlConnection("server=xxxxx; uid=xxx; pwd=xxx; DataBase=TAREAS")
    sConn.Open()
    'Se resuelvo la querie que devuelve las horas acumuladas trabajadas agrupadas por tarea
    comTabla = New SqlCommand("SELECT tarea, SUM(horas) FROM tareas GROUP BY tarea ")
    comTabla.Connection = sConn
    daTabla.SelectCommand = comTabla
    daTabla.Fill(ds)
    'Se renderiza el grafico de torta
    Dim bc As gTorta = New gTorta()
    bc.Render(ds, Response.OutputStream)
End Sub
End Class

El proximo código representa a la clase gTorta.vb, y lo detallare por secciones:

No olvidarse primero de hacer los imports necesarios:

Imports System
Imports System.IO
Imports System.Drawing
Imports System.Drawing.Text
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging

Ahora creamos la clase gTorta que referenciamos en la sección anterior En este código pueden ver que el gráfico se setea en 400x400 pixeles, pero pueden configurarlo al tamaño que quieran. De la misma manera estoy poniendo un titulo "TEXTO" y fondo en blanco, pero pueden reemplazarlopor lo que deseen.

Public Class gTorta
    Public Sub Render(ByVal chartData As DataSet, ByVal target As Stream)
        Dim dt As DataTable = chartData.Tables(0)
        'Se crea un nuevo grafico y se configura
        Dim bm As Bitmap = New Bitmap(400, 400)
        Dim g As Graphics = Graphics.FromImage(bm)
        Call g.Clear(Color.White) 'Pongo el fondo el blanco
        Call g.DrawString("Texto", New Font("arial", 20), Brushes.Black, 5, 3) 'Aquí pueden ingresar un texto que quieran

Esta próxima sección es la que crea el gráfico de torta. La linea FillPie y DrawPie son la que lo dibujan propiamente dicho. Y tienen como parametros la posicion en pantalla.

Dim curAngle As Single = 0
Dim totalAngle As Single = 0
Dim i As Integer = 0
Dim sumData As Single = 0
Dim dr As DataRow
For Each dr In dt.Rows
    sumData += Convert.ToSingle(dr(1))
Next dr
For i = 0 To dt.Rows.Count - 1
    curAngle = Convert.ToSingle(dt.Rows(i)(1)) / sumData * 360
    Call g.FillPie(New SolidBrush(ColorIm(i)), 100, 65, 200, 200, totalAngle, curAngle)
    Call g.DrawPie(Pens.Black, 100, 65, 200, 200, totalAngle, curAngle)
    totalAngle += curAngle
Next i

A continuación mostramos las leyendas que asocian los colores a las tareas, y de paso agregamos el dato del porcentaje de la información mostrada.

Dim rectY As Integer = 300
Dim textY As Integer = 300
Dim percent As Single = 0
For i = 0 To dt.Rows.Count - 1
    g.FillRectangle(New SolidBrush(ColorIm(i)), 100, rectY, 20, 10)
    percent = Convert.ToSingle(dt.Rows(i)(1)) / sumData * 100
    g.DrawString(dt.Rows(i)(0).ToString() + " (" + percent.ToString("0") + "%)", New Font("Tahoma", 10), Brushes.Black, 130, textY)
    rectY = rectY + 20
    textY = textY + 20
Next i

Finalmente grabamos la imagen y liberamos los objetos

    bm.Save(target, ImageFormat.Gif)
    g.Dispose()
    bm.Dispose()
End Sub

A fin de optimizar y ordenar el codigo, creamos una función que para cada tipo de datos nos devuelve un color distinto.

Private Function ColorIm(ByVal itemIndex As Integer) As Color
    ' Esta función devuelve un color distinto para cada dato. Agregar mas 'cases' si se lo necesita.
    Dim NuevoColor As Color
    Select Case itemIndex
        Case 0
            NuevoColor = Color.Blue
        Case 1
            NuevoColor = Color.Green
        Case 2
            NuevoColor = Color.Red
        Case 3
            NuevoColor = Color.Yellow
    End Select
    Return NuevoColor
End Function

Espero que este codigo les sea de utilidad, Ah, y no se olviden de tarea transformar el código para que sirva como gráfico de barras ;-) Les dejo una un pista... usen DrawRectangle.

Saludos


ir al índice