Desenvolvimento - Visual Basic .NET
ASP.NET - Gráficos Barra e Pizza (System.Drawing)
Agora no .NET dispomos de um conjunto de classes System.Drawing que nos possibilita construir todo tipo de apresentação gráfica que for desejado.
por Ramon Durães
Figura 01 - Gráfico Barras
Figura 02 - Gráfico Pizza
Figura 03 - Gráfico Barras
Iniciando o Projeto
Inicie um novo projeto web e chame de aspnetgraficos, depois crie uma pasta chamada de Class conforme Figura 4, será nessa pasta que vamos adicionar nossas classes.
Figura 04 - Adicionando nova pasta ao projeto
Figura 05 - Definindo nome para pasta
Conforme falei no inicio, esse projeto vai se basear em classes já prontas oferecidas no pacote do StartKit. Para adicionar a primeira classe clique com botão direito na pasta Class escolha ADD>New item, escolha um item do tipo Class e dê o nome de Chart.VB conforme Figura 06, repita os passos adicionando novos arquivos e dando os seguintes nomes (PieChart.vb,BarGraph.vb,ChartItem.vb).
Figura 06 - Adicionando arquivo de Classe
Concluída essa etapa você já deve ter os seguintes 04(Quatro) arquivos na pasta Class conforme Figura 07.
Figura 07 - 04 (Quatro) arquivos adicionados.Agora copie o código apresentado nas Listagens de 1 a 4 para respectivo arquivo de classe substituindo todo código existente no mesmo.
Listagem 1 - Código para Classe Chart.vb
Imports System
Imports System.Drawing
Imports System.Collections
Namespace ASPNET.StarterKit.Chart
"*********************************************************************
" http://www.asp.net
" StartKIT
" Chart Class
"
" Base class implementation for BarChart and PieChart
"
"*********************************************************************
Public MustInherit Class Chart
Private _colorLimit As Integer = 12
Private _color As Color() = {Color.Chocolate, Color.YellowGreen, Color.Olive, Color.DarkKhaki,
Color.Sienna, Color.PaleGoldenrod, Color.Peru, Color.Tan, Color.Khaki, Color.DarkGoldenrod,
Color.Maroon, Color.OliveDrab}
" Represent collection of all data points for the chart
Private _dataPoints As New ChartItemsCollection()
" The implementation of this method is provided by derived classes
Public MustOverride Function Draw() As Bitmap
Public Property DataPoints() As ChartItemsCollection
Get
Return _dataPoints
End Get
Set(ByVal Value As ChartItemsCollection)
_dataPoints = Value
End Set
End Property
Public Sub SetColor(ByVal index As Integer, ByVal NewColor As Color)
If index < _colorLimit Then
_color(index) = NewColor
Else
Throw New Exception("Color Limit is " + _colorLimit)
End If
End Sub "SetColor
Public Function GetColor(ByVal index As Integer) As Color
If index < _colorLimit Then
Return _color(index)
Else
Throw New Exception("Color Limit is " + _colorLimit)
End If
End Function "GetColor
End Class "Chart
End Namespace "ASPNET.StarterKit.Chart
|
Listagem 2 - Código para Classe Chartitem.vb
Imports System Imports System.Collections Imports System.Diagnostics Imports System.Drawing Namespace ASPNET.StarterKit.Chart "********************************************************************* " " ChartItem Class " " This class represents a data point in a chart " "********************************************************************* Public Class ChartItem Private _label As String Private _description As String Private _value As Single Private _color As Color Private _startPos As Single Private _sweepSize As Single Private Sub New() End Sub "New Public Sub New(ByVal label As String, ByVal desc As String, ByVal data As Single, ByVal start As Single, ByVal sweep As Single, ByVal clr As Color) _label = label _description = desc _value = data _startPos = start _sweepSize = sweep _color = clr End Sub "New Public Property Label() As String Get Return _label End Get Set(ByVal Value As String) _label = Value End Set End Property Public Property Description() As String Get Return _description End Get Set(ByVal Value As String) _description = Value End Set End Property Public Property Value() As Single Get Return _value End Get Set(ByVal Value As Single) _value = Value End Set End Property Public Property ItemColor() As Color Get Return _color End Get Set(ByVal Value As Color) _color = Value End Set End Property Public Property StartPos() As Single Get Return _startPos End Get Set(ByVal Value As Single) _startPos = Value End Set End Property Public Property SweepSize() As Single Get Return _sweepSize End Get Set(ByVal Value As Single) _sweepSize = Value End Set End Property End Class "ChartItem "********************************************************************* " " Custom Collection for ChartItems " "********************************************************************* Public Class ChartItemsCollection Inherits CollectionBase Default Public Property Item(ByVal index As Integer) As ChartItem Get Return CType(List(index), ChartItem) End Get Set(ByVal Value As ChartItem) List(index) = Value End Set End Property Public Function Add(ByVal value As ChartItem) As Integer Return List.Add(value) End Function "Add Public Function IndexOf(ByVal value As ChartItem) As Integer Return List.IndexOf(value) End Function "IndexOf Public Function Contains(ByVal value As ChartItem) As Boolean Return List.Contains(value) End Function "Contains Public Sub Remove(ByVal value As ChartItem) List.Remove(value) End Sub "Remove End Class "ChartItemsCollection End Namespace "ASPNET.StarterKit.Chart |
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.Drawing.Imaging
Imports System.Drawing.Drawing2D
Namespace ASPNET.StarterKit.Chart
"*********************************************************************
"
" BarGraph Class
"
" This class uses GDI+ to render Bar Chart.
"
"*********************************************************************
Public Class BarGraph
Inherits Chart
Private _graphLegendSpacer As Single = 15.0F
Private _labelFontSize As Integer = 7
Private _legendFontSize As Integer = 9
Private _legendRectangleSize As Single = 10.0F
Private _spacer As Single = 5.0F
" Overall related members
Private _backColor As Color
Private _fontFamily As String
Private _longestTickValue As String = String.Empty " Used to calculate max value width
Private _maxTickValueWidth As Single " Used to calculate left offset of bar graph
Private _totalHeight As Single
Private _totalWidth As Single
" Graph related members
Private _barWidth As Single
Private _bottomBuffer As Single " Space from bottom to x axis
Private _displayBarData As Boolean
Private _fontColor As Color
Private _graphHeight As Single
Private _graphWidth As Single
Private _maxValue As Single = 0.0F " = final tick value * tick count
Private _scaleFactor As Single " = _maxValue / _graphHeight
Private _spaceBtwBars As Single " For now same as _barWidth
Private _topBuffer As Single " Space from top to the top of y axis
Private _xOrigin As Single " x position where graph starts drawing
Private _yOrigin As Single " y position where graph starts drawing
Private _yLabel As String
Private _yTickCount As Integer
Private _yTickValue As Single " Value for each tick = _maxValue/_yTickCount
" Legend related members
Private _displayLegend As Boolean
Private _legendWidth As Single
Private _longestLabel As String = String.Empty " Used to calculate legend width
Private _maxLabelWidth As Single = 0.0F
Public Property FontFamily() As String
Get
Return _fontFamily
End Get
Set(ByVal Value As String)
_fontFamily = Value
End Set
End Property
Public WriteOnly Property BackgroundColor() As Color
Set(ByVal Value As Color)
_backColor = Value
End Set
End Property
Public WriteOnly Property BottomBuffer() As Integer
Set(ByVal Value As Integer)
_bottomBuffer = Convert.ToSingle(Value)
End Set
End Property
Public WriteOnly Property FontColor() As Color
Set(ByVal Value As Color)
_fontColor = Value
End Set
End Property
Public Property Height() As Integer
Get
Return Convert.ToInt32(_totalHeight)
End Get
Set(ByVal Value As Integer)
_totalHeight = Convert.ToSingle(Value)
End Set
End Property
Public Property Width() As Integer
Get
Return Convert.ToInt32(_totalWidth)
End Get
Set(ByVal Value As Integer)
_totalWidth = Convert.ToSingle(Value)
End Set
End Property
Public Property ShowLegend() As Boolean
Get
Return _displayLegend
End Get
Set(ByVal Value As Boolean)
_displayLegend = Value
End Set
End Property
Public Property ShowData() As Boolean
Get
Return _displayBarData
End Get
Set(ByVal Value As Boolean)
_displayBarData = Value
End Set
End Property
Public WriteOnly Property TopBuffer() As Integer
Set(ByVal Value As Integer)
_topBuffer = Convert.ToSingle(Value)
End Set
End Property
Public Property VerticalLabel() As String
Get
Return _yLabel
End Get
Set(ByVal Value As String)
_yLabel = Value
End Set
End Property
Public Property VerticalTickCount() As Integer
Get
Return _yTickCount
End Get
Set(ByVal Value As Integer)
_yTickCount = Value
End Set
End Property
Public Sub New()
AssignDefaultSettings()
End Sub "New
Public Sub New(ByVal bgColor As Color)
AssignDefaultSettings()
BackgroundColor = bgColor
End Sub "New
"*********************************************************************
"
" This method collects all data points and calculate all the necessary dimensions
" to draw the bar graph. It is the method called before invoking the Draw() method.
" labels is the x values.
" values is the y values.
"
"*********************************************************************
Public Overloads Sub CollectDataPoints(ByVal labels() As String, ByVal values() As String)
If labels.Length = values.Length Then
Dim i As Integer
For i = 0 To labels.Length - 1
Dim temp As Single = Convert.ToSingle(values(i))
Dim shortLbl As String = MakeShortLabel(labels(i))
" For now put 0.0 for start position and sweep size
DataPoints.Add(New ChartItem(shortLbl, labels(i), temp, 0.0F, 0.0F, GetColor(i)))
" Find max value from data; this is only temporary _maxValue
If _maxValue < temp Then
_maxValue = temp
End If
" Find the longest description
If _displayLegend Then
Dim currentLbl As String = labels(i) + " (" + shortLbl + ")"
Dim currentWidth As Single = CalculateImgFontWidth(currentLbl, _legendFontSize, FontFamily)
If _maxLabelWidth < currentWidth Then
_longestLabel = currentLbl
_maxLabelWidth = currentWidth
End If
End If
Next i
CalculateTickAndMax()
CalculateGraphDimension()
CalculateBarWidth(DataPoints.Count, _graphWidth)
CalculateSweepValues()
Else
Throw New Exception("X data count is different from Y data count")
End If
End Sub "CollectDataPoints
"*********************************************************************
"
" Same as above; called when user doesn"t care about the x values
"
"*********************************************************************
Public Overloads Sub CollectDataPoints(ByVal values() As String)
Dim labels As String() = values
CollectDataPoints(labels, values)
End Sub "CollectDataPoints
"*********************************************************************
"
" This method returns a bar graph bitmap to the calling function. It is called after
" all dimensions and data points are calculated.
"
"*********************************************************************
Public Overrides Function Draw() As Bitmap
Dim height As Integer = Convert.ToInt32(_totalHeight)
Dim width As Integer = Convert.ToInt32(_totalWidth)
Dim bmp As New Bitmap(width, height)
Dim graph As Graphics = Nothing
Try
graph = Graphics.FromImage(bmp)
graph.CompositingQuality = CompositingQuality.HighQuality
graph.SmoothingMode = SmoothingMode.AntiAlias
" Set the background: need to draw one pixel larger than the bitmap to cover all area
graph.FillRectangle(New SolidBrush(_backColor), -1, -1, bmp.Width + 1, bmp.Height + 1)
DrawVerticalLabelArea(graph)
DrawBars(graph)
DrawXLabelArea(graph)
If _displayLegend Then
DrawLegend(graph)
End If
Finally
If Not (graph Is Nothing) Then
graph.Dispose()
End If
End Try
Return bmp
End Function "Draw
"*********************************************************************
"
" This method draws all the bars for the graph.
"
"*********************************************************************
Private Sub DrawBars(ByVal graph As Graphics)
Dim brsFont As SolidBrush = Nothing
Dim valFont As Font = Nothing
Dim sfFormat As StringFormat = Nothing
Try
brsFont = New SolidBrush(_fontColor)
valFont = New Font(_fontFamily, _labelFontSize)
sfFormat = New StringFormat()
sfFormat.Alignment = StringAlignment.Center
Dim i As Integer = 0
" Draw bars and the value above each bar
Dim item As ChartItem
For Each item In DataPoints
Dim barBrush As SolidBrush = Nothing
Try
barBrush = New SolidBrush(item.ItemColor)
Dim itemY As Single = _yOrigin + _graphHeight - item.SweepSize
" When drawing, all position is relative to (_xOrigin, _yOrigin)
graph.FillRectangle(barBrush, _xOrigin + item.StartPos, itemY, _barWidth, item.SweepSize)
" Draw data value
If _displayBarData Then
" This draws the value on center of the bar
Dim startX As Single = _xOrigin + i * (_barWidth + _spaceBtwBars)
Dim startY As Single = itemY - 2.0F - valFont.Height " Positioned on top of each bar by 2 pixels
Dim recVal As New RectangleF(startX, startY, _barWidth + _spaceBtwBars, valFont.Height)
graph.DrawString(item.Value.ToString("#,###.##"), valFont, brsFont, recVal, sfFormat)
End If
i += 1
Finally
If Not (barBrush Is Nothing) Then
barBrush.Dispose()
End If
End Try
Next item
Finally
If Not (brsFont Is Nothing) Then
brsFont.Dispose()
End If
If Not (valFont Is Nothing) Then
valFont.Dispose()
End If
If Not (sfFormat Is Nothing) Then
sfFormat.Dispose()
End If
End Try
End Sub "DrawBars
"*********************************************************************
"
" This method draws the y label, tick marks, tick values, and the y axis.
"
"*********************************************************************
Private Sub DrawVerticalLabelArea(ByVal graph As Graphics)
Dim lblFont As Font = Nothing
Dim brs As SolidBrush = Nothing
Dim lblFormat As StringFormat = Nothing
Dim pen As pen = Nothing
Dim sfVLabel As StringFormat = Nothing
Try
lblFont = New Font(_fontFamily, _labelFontSize)
brs = New SolidBrush(_fontColor)
lblFormat = New StringFormat()
pen = New pen(_fontColor)
sfVLabel = New StringFormat()
lblFormat.Alignment = StringAlignment.Near
" Draw vertical label at the top of y-axis and place it in the middle top of y-axis
Dim recVLabel As New RectangleF(0.0F, _yOrigin - 2 * _spacer - lblFont.Height, _xOrigin * 2, lblFont.Height)
sfVLabel.Alignment = StringAlignment.Center
graph.DrawString(_yLabel, lblFont, brs, recVLabel, sfVLabel)
" Draw all tick values and tick marks
Dim i As Integer
For i = 0 To _yTickCount - 1
Dim currentY As Single = _topBuffer + i * _yTickValue / _scaleFactor " Position for tick mark
Dim labelY As Single = currentY - lblFont.Height / 2 " Place label in the middle of tick
Dim lblRec As New RectangleF(_spacer, labelY, _maxTickValueWidth, lblFont.Height)
Dim currentTick As Single = _maxValue - i * _yTickValue " Calculate tick value from top to bottom
graph.DrawString(currentTick.ToString("#,###.##"), lblFont, brs, lblRec, lblFormat) " Draw tick value
graph.DrawLine(pen, _xOrigin, currentY, _xOrigin - 4.0F, currentY) " Draw tick mark
Next i
" Draw y axis
graph.DrawLine(pen, _xOrigin, _yOrigin, _xOrigin, _yOrigin + _graphHeight)
Finally
If Not (lblFont Is Nothing) Then
lblFont.Dispose()
End If
If Not (brs Is Nothing) Then
brs.Dispose()
End If
If Not (lblFormat Is Nothing) Then
lblFormat.Dispose()
End If
If Not (pen Is Nothing) Then
pen.Dispose()
End If
If Not (sfVLabel Is Nothing) Then
sfVLabel.Dispose()
End If
End Try
End Sub "DrawVerticalLabelArea
"*********************************************************************
"
" This method draws x axis and all x labels
"
"*********************************************************************
Private Sub DrawXLabelArea(ByVal graph As Graphics)
Dim lblFont As Font = Nothing
Dim brs As SolidBrush = Nothing
Dim lblFormat As StringFormat = Nothing
Dim pen As pen = Nothing
Try
lblFont = New Font(_fontFamily, _labelFontSize)
brs = New SolidBrush(_fontColor)
lblFormat = New StringFormat()
pen = New pen(_fontColor)
lblFormat.Alignment = StringAlignment.Center
" Draw x axis
graph.DrawLine(pen, _xOrigin, _yOrigin + _graphHeight, _xOrigin + _graphWidth, _yOrigin + _graphHeight)
Dim currentX As Single
Dim currentY As Single = _yOrigin + _graphHeight + 2.0F " All x labels are drawn 2 pixels below x-axis
Dim labelWidth As Single = _barWidth + _spaceBtwBars " Fits exactly below the bar
Dim i As Integer = 0
" Draw x labels
Dim item As ChartItem
For Each item In DataPoints
currentX = _xOrigin + i * labelWidth
Dim recLbl As New RectangleF(currentX, currentY, labelWidth, lblFont.Height)
Dim lblString As String = IIf(_displayLegend, item.Label, item.Description)
graph.DrawString(lblString, lblFont, brs, recLbl, lblFormat)
i += 1
Next item
Finally
If Not (lblFont Is Nothing) Then
lblFont.Dispose()
End If
If Not (brs Is Nothing) Then
brs.Dispose()
End If
If Not (lblFormat Is Nothing) Then
lblFormat.Dispose()
End If
If Not (pen Is Nothing) Then
pen.Dispose()
End If
End Try
End Sub "DrawXLabelArea
"*********************************************************************
"
" This method determines where to place the legend box.
" It draws the legend border, legend description, and legend color code.
"
"*********************************************************************
Private Sub DrawLegend(ByVal graph As Graphics)
Dim lblFont As Font = Nothing
Dim brs As SolidBrush = Nothing
Dim lblFormat As StringFormat = Nothing
Dim pen As pen = Nothing
Try
lblFont = New Font(_fontFamily, _legendFontSize)
brs = New SolidBrush(_fontColor)
lblFormat = New StringFormat()
pen = New pen(_fontColor)
lblFormat.Alignment = StringAlignment.Near
" Calculate Legend drawing start point
Dim startX As Single = _xOrigin + _graphWidth + _graphLegendSpacer
Dim startY As Single = _yOrigin
Dim xColorCode As Single = startX + _spacer
Dim xLegendText As Single = xColorCode + _legendRectangleSize + _spacer
Dim legendHeight As Single = 0.0F
Dim i As Integer
For i = 0 To DataPoints.Count - 1
Dim point As ChartItem = DataPoints(i)
Dim [text] As String = point.Description + " (" + point.Label + ")"
Dim currentY As Single = startY + _spacer + i * (lblFont.Height + _spacer)
legendHeight += lblFont.Height + _spacer
" Draw legend description
graph.DrawString([text], lblFont, brs, xLegendText, currentY, lblFormat)
" Draw color code
graph.FillRectangle(New SolidBrush(DataPoints(i).ItemColor), xColorCode, currentY + 3.0F,
_legendRectangleSize, _legendRectangleSize)
Next i
" Draw legend border
graph.DrawRectangle(pen, startX, startY, _legendWidth, legendHeight + _spacer)
Finally
If Not (lblFont Is Nothing) Then
lblFont.Dispose()
End If
If Not (brs Is Nothing) Then
brs.Dispose()
End If
If Not (lblFormat Is Nothing) Then
lblFormat.Dispose()
End If
If Not (pen Is Nothing) Then
pen.Dispose()
End If
End Try
End Sub "DrawLegend
"*********************************************************************
"
" This method calculates all measurement aspects of the bar graph from the given data points
"
"*********************************************************************
Private Sub CalculateGraphDimension()
FindLongestTickValue()
" Need to add another character for spacing; this is not used for drawing, just for calculation
_longestTickValue += "0"
_maxTickValueWidth = CalculateImgFontWidth(_longestTickValue, _labelFontSize, FontFamily)
Dim leftOffset As Single = _spacer + _maxTickValueWidth
Dim rtOffset As Single = 0.0F
If _displayLegend Then
_legendWidth = _spacer + _legendRectangleSize + _spacer + _maxLabelWidth + _spacer
rtOffset = _graphLegendSpacer + _legendWidth + _spacer
Else
rtOffset = _spacer " Make graph in the middle
End If
_graphHeight = _totalHeight - _topBuffer - _bottomBuffer " Buffer spaces are used to print labels
_graphWidth = _totalWidth - leftOffset - rtOffset
_xOrigin = leftOffset
_yOrigin = _topBuffer
" Once the correct _maxValue is determined, then calculate _scaleFactor
_scaleFactor = _maxValue / _graphHeight
End Sub "CalculateGraphDimension
"*********************************************************************
"
" This method determines the longest tick value from the given data points.
" The result is needed to calculate the correct graph dimension.
"
"*********************************************************************
Private Sub FindLongestTickValue()
Dim currentTick As Single
Dim tickString As String
Dim i As Integer
For i = 0 To _yTickCount - 1
currentTick = _maxValue - i * _yTickValue
tickString = currentTick.ToString("#,###.##")
If _longestTickValue.Length < tickString.Length Then
_longestTickValue = tickString
End If
Next i
End Sub "FindLongestTickValue
"*********************************************************************
"
" This method calculates the image width in pixel for a given text
"
"*********************************************************************
Private Function CalculateImgFontWidth(ByVal [text] As String, ByVal size As Integer, ByVal family As
String) As Single
Dim bmp As Bitmap = Nothing
Dim graph As Graphics = Nothing
Dim font As font = Nothing
Try
font = New font(family, size)
" Calculate the size of the string.
bmp = New Bitmap(1, 1, PixelFormat.Format32bppArgb)
graph = Graphics.FromImage(bmp)
Dim oSize As SizeF = graph.MeasureString([text], font)
Return oSize.Width
Finally
If Not (graph Is Nothing) Then
graph.Dispose()
End If
If Not (bmp Is Nothing) Then
bmp.Dispose()
End If
If Not (font Is Nothing) Then
font.Dispose()
End If
End Try
End Function "CalculateImgFontWidth
"*********************************************************************
"
" This method creates abbreviation from long description; used for making legend
"
"*********************************************************************
Private Function MakeShortLabel(ByVal [text] As String) As String
Dim label As String = [text]
If [text].Length> 2 Then
Dim midPostition As Integer = Convert.ToInt32(Math.Floor(([text].Length / 2)))
label = [text].Substring(0, 1) + [text].Substring(midPostition, 1) + [text].Substring([text].Length - 1, 1)
End If
Return label
End Function "MakeShortLabel
"*********************************************************************
"
" This method calculates the max value and each tick mark value for the bar graph.
"
"*********************************************************************
Private Sub CalculateTickAndMax()
Dim tempMax As Single = 0.0F
" Give graph some head room first about 10% of current max
_maxValue *= 1.1F
If _maxValue <> 0.0F Then
" Find a rounded value nearest to the current max value
" Calculate this max first to give enough space to draw value on each bar
Dim exp As Double = Convert.ToDouble(Math.Floor(Math.Log10(_maxValue)))
tempMax = Convert.ToSingle((Math.Ceiling((_maxValue / Math.Pow(10, exp))) * Math.Pow(10, exp)))
Else
tempMax = 1.0F
End If
" Once max value is calculated, tick value can be determined; tick value should be a whole number
_yTickValue = tempMax / _yTickCount
Dim expTick As Double = Convert.ToDouble(Math.Floor(Math.Log10(_yTickValue)))
_yTickValue = Convert.ToSingle((Math.Ceiling((_yTickValue / Math.Pow(10, expTick))) * Math.Pow(10,
expTick)))
" Re-calculate the max value with the new tick value
_maxValue = _yTickValue * _yTickCount
End Sub "CalculateTickAndMax
"*********************************************************************
"
" This method calculates the height for each bar in the graph
"
"*********************************************************************
Private Sub CalculateSweepValues()
" Called when all values and scale factor are known
" All values calculated here are relative from (_xOrigin, _yOrigin)
Dim i As Integer = 0
Dim item As ChartItem
For Each item In DataPoints
" This implementation does not support negative value
If item.Value>= 0 Then
item.SweepSize = item.Value / _scaleFactor
End If
" (_spaceBtwBars/2) makes half white space for the first bar
item.StartPos = _spaceBtwBars / 2 + i * (_barWidth + _spaceBtwBars)
i += 1
Next item
End Sub "CalculateSweepValues
"*********************************************************************
"
" This method calculates the width for each bar in the graph
"
"*********************************************************************
Private Sub CalculateBarWidth(ByVal dataCount As Integer, ByVal barGraphWidth As Single)
" White space between each bar is the same as bar width itself
_barWidth = barGraphWidth / (dataCount * 2) " Each bar has 1 white space
_spaceBtwBars = _barWidth
End Sub "CalculateBarWidth
"*********************************************************************
"
" This method assigns default value to the bar graph properties and is only
" called from BarGraph constructors
"
"*********************************************************************
Private Sub AssignDefaultSettings()
" default values
_totalWidth = 700.0F
_totalHeight = 450.0F
_fontFamily = "Verdana"
_backColor = Color.White
_fontColor = Color.Black
_topBuffer = 30.0F
_bottomBuffer = 30.0F
_yTickCount = 2
_displayLegend = False
_displayBarData = False
End Sub "AssignDefaultSettings
End Class "BarGraph
End Namespace "ASPNET.StarterKit.Chart
|
Imports System
Imports System.Collections
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Drawing.Drawing2D
Namespace ASPNET.StarterKit.Chart
"*********************************************************************
"
" PieChart Class
"
" This class uses GDI+ to render Pie Chart.
"
"*********************************************************************
Public Class PieChart
Inherits Chart
Private _bufferSpace As Integer = 125
Private _chartItems As ArrayList
Private _perimeter As Integer
Private _backgroundColor As Color
Private _borderColor As Color
Private _total As Single
Private _legendWidth As Integer
Private _legendHeight As Integer
Private _legendFontHeight As Integer
Private _legendFontStyle As String
Private _legendFontSize As Single
Public Sub New()
_chartItems = New ArrayList
_perimeter = 250
_backgroundColor = Color.White
_borderColor = Color.FromArgb(63, 63, 63)
_legendFontSize = 8
_legendFontStyle = "Verdana"
End Sub "New
Public Sub New(ByVal bgColor As Color)
_chartItems = New ArrayList
_perimeter = 250
_backgroundColor = bgColor
_borderColor = Color.FromArgb(63, 63, 63)
_legendFontSize = 8
_legendFontStyle = "Verdana"
End Sub "New
"*********************************************************************
"
" This method collects all data points and calculate all the necessary dimensions
" to draw the chart. It is the first method called before invoking the Draw() method.
"
"*********************************************************************
Public Sub CollectDataPoints(ByVal xValues() As String, ByVal yValues() As String)
_total = 0.0F
Dim i As Integer
For i = 0 To xValues.Length - 1
Dim ftemp As Single = Convert.ToSingle(yValues(i))
_chartItems.Add(New ChartItem(xValues(i), xValues.ToString(), ftemp, 0, 0, Color.AliceBlue))
_total += ftemp
Next i
Dim nextStartPos As Single = 0.0F
Dim counter As Integer = 0
Dim item As ChartItem
For Each item In _chartItems
item.StartPos = nextStartPos
item.SweepSize = item.Value / _total * 360
nextStartPos = item.StartPos + item.SweepSize
counter = counter + 1
item.ItemColor = GetColor(counter)
Next
CalculateLegendWidthHeight()
End Sub "CollectDataPoints
"*********************************************************************
"
" This method returns a bitmap to the calling function. This is the method
" that actually draws the pie chart and the legend with it.
"
"*********************************************************************
Public Overrides Function Draw() As Bitmap
Dim perimeter As Integer = _perimeter
Dim pieRect As New Rectangle(0, 0, perimeter, perimeter - 1)
Dim bmp As New Bitmap(perimeter + _legendWidth, perimeter)
Dim grp As Graphics = Nothing
Dim sf As StringFormat = Nothing
Try
grp = Graphics.FromImage(bmp)
sf = New StringFormat
"Paint Back ground
grp.FillRectangle(New SolidBrush(_backgroundColor), 0, 0, perimeter + _legendWidth, perimeter)
"Align text to the right
sf.Alignment = StringAlignment.Far
"Draw all wedges and legends
Dim i As Integer
For i = 0 To _chartItems.Count - 1
Dim item As ChartItem = CType(_chartItems(i), ChartItem)
Dim brs As SolidBrush = Nothing
Try
brs = New SolidBrush(item.ItemColor)
grp.FillPie(brs, pieRect, item.StartPos, item.SweepSize)
grp.FillRectangle(brs, perimeter + _bufferSpace, i * _legendFontHeight + 15, 10, 10)
grp.DrawString(item.Label, New Font(_legendFontStyle, _legendFontSize), New SolidBrush(Color.Black),
perimeter + _bufferSpace + 20, i * _legendFontHeight + 13)
grp.DrawString(item.Value.ToString("C"), New Font(_legendFontStyle, _legendFontSize), New
SolidBrush(Color.Black), perimeter + _bufferSpace + 200, i * _legendFontHeight + 13, sf)
Finally
If Not (brs Is Nothing) Then
brs.Dispose()
End If
End Try
Next i
"draws the border around Pie
grp.DrawEllipse(New Pen(_borderColor, 2), pieRect)
"draw border around legend
grp.DrawRectangle(New Pen(_borderColor, 1), perimeter + _bufferSpace - 10, 10, 220, _chartItems.Count *
_legendFontHeight + 25)
"Draw Total under legend
grp.DrawString("Total", New Font(_legendFontStyle, _legendFontSize, FontStyle.Bold), New
SolidBrush(Color.Black), perimeter + _bufferSpace + 30, (_chartItems.Count + 1) * _legendFontHeight, sf)
grp.DrawString(_total.ToString("C"), New Font(_legendFontStyle, _legendFontSize, FontStyle.Bold), New
SolidBrush(Color.Black), perimeter + _bufferSpace + 200, (_chartItems.Count + 1) * _legendFontHeight,
sf)
grp.SmoothingMode = SmoothingMode.AntiAlias
Finally
If Not (sf Is Nothing) Then
sf.Dispose()
End If
If Not (grp Is Nothing) Then
grp.Dispose()
End If
End Try
Return bmp
End Function "Draw
"*********************************************************************
"
" This method calculates the space required to draw the chart legend.
"
"*********************************************************************
Private Sub CalculateLegendWidthHeight()
Dim fontLegend As New Font(_legendFontStyle, _legendFontSize)
_legendFontHeight = fontLegend.Height + 5
_legendHeight = fontLegend.Height * (_chartItems.Count + 1)
If _legendHeight> _perimeter Then
_perimeter = _legendHeight
End If
_legendWidth = _perimeter + _bufferSpace
End Sub "CalculateLegendWidthHeight
End Class "PieChart
End Namespace "ASPNET.StarterKit.Chart
|
Listagem 5 - Código para Classe GerarGrafico.aspx.vb
Imports aspnetgraficos.ComponenteGrafico
Public Class GerarGrafico
Inherits System.Web.UI.Page
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
"////////////////////////////////////////
"/Recebe parametros para gerar o Grafico /
"////////////////////////////////////////
Dim xValues, yValues, Tipo_Grafico_str As String
xValues = Request.QueryString("xValues")
yValues = Request.QueryString("yValues")
Tipo_Grafico_str = Request.QueryString("Tipo_Grafico")
If Not (xValues Is Nothing) And Not (yValues Is Nothing) Then
Response.Clear()
Response.ContentType = "image/gif"
Dim bmp As Bitmap
Dim memStream As New System.IO.MemoryStream
Select Case Tipo_Grafico_str
Case "Barra"
Dim bar As New BarGraph(Color.White)
bar.VerticalLabel = "R$"
bar.VerticalTickCount = 5
bar.ShowLegend = True
bar.ShowData = False
bar.Height = 400
bar.Width = 700
bar.CollectDataPoints(xValues.Split("|".ToCharArray()), yValues.Split("|".ToCharArray()))
bmp = bar.Draw()
Case "Barra2"
Dim bar As New BarGraph(Color.White)
Dim i As Integer
For i = 0 To 6
bar.SetColor(i, Color.Sienna)
Next i
bar.VerticalTickCount = 2
bar.ShowLegend = False
bar.ShowData = True
bar.Height = 119
bar.Width = 195
bar.TopBuffer = 5
bar.BottomBuffer = 15
bar.FontColor = Color.Gray
bar.CollectDataPoints(xValues.Split("|".ToCharArray()), yValues.Split("|".ToCharArray()))
bmp = bar.Draw()
Case Else
Dim pc As New PieChart(Color.White)
pc.CollectDataPoints(xValues.Split("|".ToCharArray()), yValues.Split("|".ToCharArray()))
bmp = pc.Draw()
End Select
"Retorna o grafico para o Browser
bmp.Save(memStream, System.Drawing.Imaging.ImageFormat.Gif)
memStream.WriteTo(Response.OutputStream)
End If
End Sub
End Class
|
Agora vamos adicionar uma nova pagina que será utilizada para nossos testes, adicione o arquivo chamado de default.aspx, depois adicione um dropdownlist (ID=dpTipo,AutoPostBack=True), adicione um Image (ID=imgGrafico) conforme Figura 08. Depois adicione o código da Listagem 06.
Listagem 6 - Código para Classe default.aspx.vb
Public Class _default
Inherits System.Web.UI.Page
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub dpTipo_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles dpTipo.SelectedIndexChanged
Dim valor As String = dpTipo.SelectedItem.Value
Select Case valor
Case "1"
imgGrafico.Visible = True
imgGrafico.ImageUrl = "GerarGrafico.aspx?xvalues=Compras|Vendas&yvalues=6|7&tipo_grafico=Barra"
Case "2"
imgGrafico.Visible = True
imgGrafico.ImageUrl = "GerarGrafico.aspx?xvalues=Compras|Vendas&yvalues=600|1000&tipo_grafico=Pizza"
Case "3"
imgGrafico.Visible = True
imgGrafico.ImageUrl = "GerarGrafico.aspx?xvalues=Compras|Vendas&yvalues=600|1000&tipo_grafico=Barra2"
Case "4"
imgGrafico.Visible = True
imgGrafico.ImageUrl = "GerarGrafico.aspx?tipo_grafico=Barra2&" + db()
Case "5"
imgGrafico.Visible = True
imgGrafico.ImageUrl = "GerarGrafico.aspx?tipo_grafico=Pizza&" + db()
Case Else
imgGrafico.Visible = False
End Select
End Sub
Function db() As String
"Configure aqui a senha de acesso ao banco de dados
Dim da As New System.Data.SqlClient.SqlDataAdapter("select top 10 CustomerID ID,Freight TOTAL from
Orders", "Data Source=127.0.0.1;User ID=sa;Password=;Initial Catalog=NorthWind")
Dim dt As New DataTable
da.Fill(dt)
Dim i As Int32
Dim xvalues As New System.Text.StringBuilder
Dim yvalues As New System.Text.StringBuilder
For i = 0 To dt.Rows.Count - 1
If i <> 0 Then
xvalues.Append("|")
yvalues.Append("|")
End If
xvalues.Append(dt.Rows(i)(0))
yvalues.Append(dt.Rows(i)(1))
Next
Return "xvalues=" + xvalues.ToString + "&" + "yvalues=" + yvalues.ToString
End Function
End Class
|
Agora já temos uma pagina de teste. Basta selecionar o tipo do gráfico desejado que o combo vai passar os parâmetros para a pagina gerargrafico.aspx que retorna a imagem do gráfico.
Finalizando
Adicionar gráfico hoje em uma aplicação web só vem a engrandecer o produto. O .NET oferece todas classes basicas para você realizar a implementação do gráfico que imaginar. Porém para esse caso eu recomendo a utilização de componentes prontos no mercado, que já fazem esse trabalho muito bem. Deixe para implementar no System.Drawing quando não encontrar o recurso pronto. Agora se você é um cara que se indentifica com esse tipo de implementação, essa é a hora!
Sugestões:
http://www.dotnetcharting.com
http://www.dundas.com
http://www.softwarefx.com
http://www.advsofteng.com
http://www.componentone.com
Clique aqui para baixar o código fonte.
O que você gostaria saber?
Aguardo seu comentário! Ele é muito importante. Participe!!! Até próximo artigo!
Você é de Salvador Bahia, então participe do grupo de usuários .NET http://www.mutex.com.br
- Entity Framework 4: Repositório GenéricoVisual Basic .NET
- As edições 14 da Easy .net Magazine e 88 da .net Magazine já estão disponíveis.ADO.NET
- Postando no Twiiter com .NET e Migre.meC#
- Setup ApplicationsVisual Basic .NET
- Problemas na manipulação de arquivos do MS Excel com .NETVisual Basic .NET


