Microsoft KB Archive/290348

= HOWTO: Use Custom Layout and Drawing with the Office Chart Component =

Article ID: 290348

Article Last Modified on 2/20/2007

-

APPLIES TO


 * Microsoft Office Web Components
 * Microsoft Office Web Components

-



This article was previously published under Q290348



SUMMARY
The Office XP Chart component and the Office 2003 Chart component expose functionality that enables you to position various objects in the Chartspace and to add custom text and drawings to the Chartspace at run time. This article describes how to implement custom layout and drawing with the Office XP Chart component and the Office 2003 Chart component with a code sample.



MORE INFORMATION
To position and size the various objects in a Chartspace, you must first set the AllowLayoutEvents property of the Chartspace to True. This allows you to handle the AfterLayout event, which is triggered after all chart objects have been laid out but before they are rendered. In this event, you can position and size chart objects, such as chart plot areas, legends, and titles.

To draw lines, shapes, and text in a Chartspace, set the AllowRenderEvents property of the Chartspace to True. This enables you to access the chart drawing object (ChChartDraw) in the BeforeRender, AfterRender, and AfterFinalRender events.
 * The BeforeRender event is triggered before each object in the Chartspace is rendered. In this event, you can query the ChartObject parameter to determine which chart object is about to be rendered so that you can add custom drawings to the chart that appears behind the object in the Chartspace but on top of objects already rendered. You can also choose to cancel the rendering of certain objects in the Chartspace by setting the Cancel parameter to True.
 * The AfterRender event is triggered after each object in the Chartspace is rendered. In this event, you can query the ChartObject parameter to determine which chart object was rendered so that you can add custom drawings to the chart that appears on top of the object in the Chartspace; the drawing appears behind any objects rendered later.
 * The AfterFinalRender event is triggered after all objects in the Chartspace have been rendered. Custom drawings that you create in this event appear on top of all other objects in the Chartspace.

Sample
The following sample demonstrates how you can handle the layout and render events to create a customized chart. The sample works in the following manner:
 * 1) Builds a standard column chart using literal data, and sets both the AllowLayoutEvents and AllowRenderEvents to True.
 * 2) After the initial chart is laid out, but before any objects in the chart are rendered, the AfterLayout event is handled to position and size the chart's plot area.
 * 3) Before the plot area is rendered, the BeforeRender event is handled to draw a rectangle with a texture. The rectangle is drawn before the axes, gridlines, and columns are rendered; therefore, the rectangle appears as a backdrop to those objects in the chart.
 * 4) After the gridlines are rendered, the AfterRender event is handled to draw a horizontal line that represents the average value of the columns in the chart. The line is drawn so that it lies in the correct location with respect to the value axis. Because the line is rendered after the gridlines but before the columns in the chart, the custom line appears behind the columns.
 * 5) Several additional items are drawn during the AfterFinalRender event so that the items are drawn on top of all other objects in the Chartspace:
 * 6) * a &quot;callout&quot; for the data point with the lowest value (the callout is comprised of a line with an arrowhead and an ellipse containing text). The coordinates for the specific data point are retrieved by using the GetValue method.
 * 7) * two lines of text at the bottom of the Chartspace. The lines of text are drawn in different font styles and act as a chart title with subtext. The TextWidth property of the drawing object is used to determine the width of the text before it is drawn so that it may be centered in the Chartspace.



To try the sample, save the following code as an HTML file, and then browse to the HTML file in Internet Explorer (IE). On the Web page that is rendered, click Build the Chart to create a column chart with drawings and custom text. Click Build the Chart twice more to observe different color schemes for the chart.

 Build the Chart 



Dim oChart, c Dim aSales(3) Dim nPlotTop, nPlotLeft, nPlotRight, nPlotBottom Dim aScheme Dim Counter

Set c = WebChart.Constants

Function BuildChart_OnClick 'Choose a color scheme. Counter = Counter + 1 Select Case (Counter Mod 3) Case 0: aScheme = Array(c.chTextureCanvas, c.chTextureParchment, &quot;OldLace&quot;, &quot;SaddleBrown&quot;) Case 1: aScheme = Array(c.chTextureDenim, c.chTextureBlueTissuePaper, &quot;MintCream&quot;, &quot;Navy&quot;) Case 2: aScheme = Array(c.chTextureOak, c.chTexturePapyrus, &quot;navajowhite&quot;, &quot;black&quot;) End Select 'Create a column chart with one series. WebChart.Clear Set oChart = WebChart.Charts.Add oChart.PlotArea.Interior.Color = c.chColorNone With oChart.SeriesCollection.Add .SetData c.chDimCategories, c.chDataLiteral, Array(&quot;Qtr1&quot;, &quot;Qtr2&quot;, &quot;Qtr3&quot;, &quot;Qtr4&quot;) Randomize Time Dim i       For i = 0 To 3 aSales(i) = Rnd * 100000 Next .SetData c.chDimValues, c.chDataLiteral, aSales .Interior.SetTextured aScheme(0) End With oChart.PlotArea.Border.Color = c.chColorNone 'Allow Render events to get a handle on the ChChartDraw object so that custom lines, 'shapes and text can be drawn on the chart. WebChart.AllowRenderEvents = True 'Allow layout events so that the chart's plot area can be repositioned and resized. WebChart.AllowLayoutEvents = True

End Function

Function WebChart_AfterLayout(drawObject)

'Resize the chart's plot area to provide room at the top, bottom, and 'right of the chart for custom drawn shapes and text. nPlotTop = oChart.PlotArea.Top + 50 oChart.PlotArea.Top = nPlotTop nPlotBottom = oChart.PlotArea.Bottom - 80 oChart.PlotArea.Bottom = nPlotBottom nPlotRight = oChart.PlotArea.Right - 100 oChart.PlotArea.Right = nPlotRight nPlotLeft = oChart.PlotArea.Left + 20 oChart.PlotArea.Left = nPlotLeft End Function

Function WebChart_BeforeRender(drawObject, chartObject, Cancel)

'Draw a textured rectangle for the backdrop of the chart before the plot area is rendered. If TypeName(chartObject) = &quot;ChPlotArea&quot; Then drawObject.Interior.SetTextured aScheme(1) drawObject.Border.Weight = 2 drawObject.Border.Color = aScheme(3) drawObject.DrawRectangle 10, 10, oChart.Right - 10, oChart.Axes(c.chAxisPositionBottom).Bottom End If End Function

Function WebChart_AfterRender(drawObject, chartObject)

'After the gridlines are rendered, draw a line in the plot area that represents the average 'of the data points. Note: The line is drawn after the gridlines but before the data points 'are drawn so that the line appears behind the data points. If TypeName(chartObject) = &quot;ChGridlines&quot; Then Dim nAvg nAvg = (aSales(0) + aSales(1) + aSales(2) + aSales(3)) / 4 Dim nIncrement, nAvgLineY nIncrement = (nPlotBottom - nPlotTop) / ( _           oChart.Scalings(c.chDimValues).Maximum - oChart.Scalings(c.chDimValues).Minimum) nAvgLineY = nPlotBottom - nIncrement * nAvg drawObject.Line.DashStyle = c.chLineDashDotDot drawObject.Line.Color = aScheme(3) drawObject.Line.Weight = 4 drawObject.DrawLine nPlotLeft + 1, nAvgLineY, nPlotRight - 1, nAvgLineY 'Add text at the right of the drawn line to display the value it represents. drawObject.Font.Color = aScheme(3) Dim sText sText = &quot;Avg = &quot; & CLng(nAvg) drawObject.DrawText sText, nPlotRight + 10, nAvgLineY - drawObject.TextHeight(sText) / 2 End If End Function

Function WebChart_AfterFinalRender(drawObject)

Dim sText 'Draw a vertical line at the data point with the smallest value (the minimum). Dim oPoint, oCoord Dim nMinPoint nMinPoint = 0 Dim i   For i = 1 To 3 If aSales(i) < aSales(nMinPoint) Then nMinPoint = i   Next Set oPoint = oChart.SeriesCollection(0).Points(nMinPoint) Set oCoord = oChart.SeriesCollection(0).ValueToPoint( _       oPoint.GetValue(c.chDimCategories), oPoint.GetValue(c.chDimValues)) drawObject.DrawLine oCoord.x, nPlotTop - 10, oCoord.x, oCoord.y   'Draw an arrowhead for the line. drawObject.Interior.Color = &quot;black&quot; drawObject.DrawPolygon Array(oCoord.x, oCoord.x + 5, oCoord.x - 5, oCoord.x), _ Array(oCoord.y, oCoord.y - 12, oCoord.y - 12, oCoord.y)   'Draw an ellipse with text inside of it (a callout for the line with the arrowhead). Dim nWidth, nHeight, nPaddingX, nPaddingY sText = &quot;The Minimum&quot; nWidth = drawObject.TextWidth(sText) nHeight = drawObject.TextHeight(sText) nPaddingX = 20 nPaddingY = 5 drawObject.Interior.Color = aScheme(2) drawObject.DrawEllipse oCoord.x - nWidth / 2 - nPaddingX, nPlotTop - 10 - nHeight - nPaddingY, _ oCoord.x + nWidth / 2 + nPaddingX, nPlotTop - 10 + nPaddingY drawObject.DrawText sText, oCoord.x - nWidth / 2, nPlotTop - 10 - nHeight 'Draw two separate lines of custom text beneath the plot area and center the text. 'with the chart space drawObject.Font.Size = 16 drawObject.Font.Bold = True sText = &quot;Custom Chart Text&quot; drawObject.DrawText sText, _ (WebChart.object.Right - WebChart.object.Left) / 2 - drawObject.TextWidth(sText) / 2, _ nPlotBottom + 40 drawObject.Font.Size = 9 drawObject.Font.Bold = False drawObject.Font.Color = aScheme(3) sText = &quot;Additional custom chart text that is a subtitle&quot; drawObject.DrawText sText, _ (WebChart.object.Right - WebChart.object.Left) / 2 - drawObject.TextWidth(sText) / 2, _ nPlotBottom + 70 End Function

