|  | Click Here!

Search the site:
EXPERT SEARCH

| Programming Languages
| Databases
| Security
| Web Services
| Network Services
| Middleware
| Components
| Operating Systems
| User Interfaces
| Groupware & Collaboration
| Content Management
| Productivity Applications
| Hardware
| Fun & Games

EarthWeb sites
Crossnodes
Datamation
Developer.com
DICE
EarthWeb.com
EarthWeb Direct
ERP Hub
Gamelan
GoCertify.com
HTMLGoodies
Intranet Journal
IT Knowledge
IT Library
JavaGoodies
JARS
JavaScripts.com
open source IT
RoadCoders
Y2K Info

# Chapter 27

# The Chart and Grid Controls

by Evangelos Petroutsos

CONTENTS

- The Chart Example
- The GridChart Example
  - The Grid Control
  - Implementing the Application
- Review

The examples in this chapter demonstrate the Chart and Grid controls. We explored the Chart control in Chapter 9 "More ActiveX Controls," but in this chapter we are going to develop a much more elaborate document that not only graphs data but accepts user-supplied data and then graphs it. The examples of this chapter are complete, functional applications that can run from within Internet Explorer (and soon from within other browsers, too). They demonstrate the kind of functionality you can add to your Web pages with VBScript and ActiveX controls.

The first application relies on ActiveX controls and can be safely posted on the Web. The Chart application, shown in Figure 27.1, is a data-graphing application that lets the user enter data in the TextBox controls at the layout's lower-right corner. Each time the user changes a value in one of the values, the graph is updated automatically. The group of TextBox controls used for data entry was arranged as a spreadsheet, but since each cell requires its own TextBox control and the corresponding code, we couldn't place too many cells on the layout with this approach. We are going to eliminate this limitation later with the Grid control.
Figure 27.1 : The Chart application graph's user-supplied data at runtime.

For a real data-entry and graphing application, you need a Grid control. A Grid control is an old OLE control, which will already be installed on your system if you have Visual Basic or Visual C++. It's a miniature spreadsheet, with most of the functionality you need to implement a data-entry and graphing application, like the one shown in Figure 27.2. This example is called GridChart, and you'll see how it was implemented in the second half of this chapter. The code is more compact than the code of the Grid application, because we don't have to repeat identical subroutines for each cell and we can provide as many cells as necessary for the user to enter data.

Figure 27.2 : The GridChart application provides a Grid control, where the user can enter the data to be graphed.

The drawback of the GridChart application is that it can only be used locally or in an intranet environment, because it makes use of an old OLE control that does not come with Internet Explorer, and many users might not have it. We are assuming that you have Visual Basic installed on your system and you have access to this control. Besides, it won't be long before an ActiveX version of the Grid control becomes available. (Keep an eye on Microsoft's Workshop site, at `www.microsoft.com/workshop`.)

There's one more reason why the two controls are combined in the GridChart example. The data graphed by the Graph control is stored into the control in a two-dimensional array. The rows of the array correspond to different datasets and its columns to the individual points in each dataset. The structure of the Grid control is quite similar. The Grid control is a tabular arrangement of cells. The GridChart application maps the rows of the grid to datasets of the Chart control. The similarities between the two controls are not limited to the surface. The methods for accessing data points in the Chart control and cells in the Grid control are quite similar. In essence, you must first set the row and column index of the element you want to access. These two values uniquely identify an element (a cell in the Grid control and a data point in the Chart control). Then, you can access the element (read or set its value) with the `Text` property of the Grid control, or the `DataItem` of the Chart control. The remaining properties of both controls determine the appearance of the control (the appearance of the graph or the placement and look of the data in the grid's cells). They have intuitive names, and you can easily figure out their purpose. Even if you don't, you can look up the help files and experiment with their settings to get what you want. The important thing is to understand the basic mechanism for accessing the elements of these two controls, and you'll be able to use them very efficiently.

## The Chart Example

The Chart application is a demonstration of the various properties of the Chart control. It also shows how to change the control's data at runtime, by plugging new values into the control's data array. The user interface of the application consists of a Chart control, a number of OptionButton and CheckBox controls that control the graph's appearance, and a number of TextBox controls where the user may change the data values.

The OptionButton controls that control the appearance of the graph are by far less than the actual graph types, but when combined, they can specify all graph types. The settings of the `GraphType` property let you specify only eight different charts (Pie, Point, Line, Area, Column, Bar, HLC, OHLC chart), but each one comes in three flavors: simple, stacked, and full (100%). The Chart application lets you select separately the type of the graph and its variation, thus eliminating the need for 20 different Option buttons.

The Chart application was implemented as an HTML document. There are no layouts on the page of Figure 27.1. The various controls were aligned with an elaborate table structure, which you may ignore if you are not familiar with HTML. Placing the controls on a layout is actually simpler. The code of the application is shown in Listing 27.1.

> Listing 27.1. The Chart project's complete code.

>       1:

>       2: <HTML>

>       3: <HEAD>

>       4: <TITLE>Chart Control Demo</TITLE>

>       5: <SCRIPT LANGUAGE="VBS">

>       6:     Sub DoChartType(CType)

>       7:     Chart.ChartType=CType

>       8:     End Sub

>       9:     Sub DoChartStyle(CStyle)

>      10:            if Chart.ChartType < 2 then Exit Sub

>      11:     currentStyle=Chart.ChartType

>      12:     if CStyle = 0 then

>      13:         if (currentStyle-2) mod 2 = 0 then Exit Sub

>      14:         if (currentStyle-3) mod 2 = 0 then Chart.ChartType=currentStyle - 1

>      15:         if (currentStyle-4) mod 2 = 0 then Chart.ChartType=currentStyle - 2

>      16:         Exit Sub

>      17:     end if

>      18:     if CStyle = 1 then

>      19:         if (currentStyle-2) mod 2 = 0 then Chart.ChartType=currentStyle + 1

>      20:         if (currentStyle-3) mod 2 = 0 then Exit Sub

>      21:         if (currentStyle-4) mod 2 = 0 then Chart.ChartType=currentStyle + 1

>      22:         Exit Sub

>      23:     end if

>      24:     if CStyle = 2 then

>      25:         if (currentStyle-2) mod 2 = 0 then Chart.ChartType=currentStyle + 2

>      26:         if (currentStyle-3) mod 2 = 0 then Chart.ChartType=currentStyle + 1

>      27:         if (currentStyle-4) mod 2 = 0 then Exit Sub

>      28:         Exit Sub

>      29:     End if

>      30:     End Sub

>      31:     Sub HorizontalGrid(HGrid)

>      32:        if HGrid.Checked = 1 then

>      33:           Chart.HGridStyle = 1

>      34:        else

>      35:           Chart.HGridStyle = 0

>      36:        end if

>      37:     End Sub

>      38:     Sub VerticalGrid(VGrid)

>      39:        if VGrid.Checked = 1 then

>      40:           Chart.VGridStyle = 1

>      41:        else

>      42:           Chart.VGridStyle = 0

>      43:        end if

>      44:     End Sub

>      45:

>      46:     Sub NewData(row, col, Data)

>      47:         Chart.RowIndex = row

>      48:         Chart.ColumnIndex = col

>      49:         Chart.DataItem =Data.Value

>      50:     End Sub

>      51: </SCRIPT>

>      52: </HEAD>

>      53: <BODY>

>      54: <H1>Chart Active Control Demo</H1>

>      55: This page demonstrates the properties of the Chart Active Control.<BR>

>      56: Every time you change the settings of the chart, or any data values, the chart

>                is updated automatically.

>      57: <P>

>      58: <TABLE BORDER>

>      59: <TR><TD>

>      60: <OBJECT

>      61:     classid="clsid:FC25B780-75BE-11CF-8B01-444553540000"

>      62:     id=Chart

>      63:     width=240

>      64:     height=260

>      65:         align=center

>      66:     hspace=0

>      67:     vspace=0>

>      68:     <param name="BackColor" value="14737632">

>      69:     <param name="ChartStyle" value="0">

>      70:     <param name="ChartType" value="4">

>      71:     <param name="HGridStyle" value="0">

>      72:     <param name="VGridStyle" value="0">

>      73:     <param name="ColorScheme" value="0">

>      74:     <param name="Rows" value="2">

>      75:     <param name="Columns" value="5">

>      76:     <param name="data[0][0]" value="15">

>      77:     <param name="data[0][1]" value="13">

>      78:     <param name="data[0][2]" value="22">

>      79:     <param name="data[0][3]" value="17">

>      80:     <param name="data[0][4]" value="14">

>      81:     <param name="data[1][0]" value="23">

>      82:     <param name="data[1][1]" value="18">

>      83:     <param name="data[1][2]" value="19">

>      84:     <param name="data[1][3]" value="24">

>      85:     <param name="data[1][4]" value="21">

>      86:

>      87: </OBJECT>

>      88: <TD BGCOLOR=#E0E0E0>

>      89: <FORM>

>      90: <TABLE>

>      91: <TR>

>      92: <TD COLSPAN=2 BGCOLOR=#FFFFCC>Chart Type</TD>

>      93: <TD BGCOLOR=#FFFFCC>Chart Style</TD>

>      94: </TR>

>      95: <TR>

>      96: <TD><INPUT TYPE="RADIO" NAME="TypeGroup" onClick="DoChartType(0)">Pie</TD>

>      97: <TD><INPUT TYPE="RADIO" NAME="TypeGroup" onClick="DoChartType(2)">Point</TD>

>      98: <TD><INPUT TYPE="RADIO" checked NAME="StyleGroup"

>                onClick="DoChartStyle(0)">Simple

>      99: </TR>

>     100: <TR>

>     101: <TD><INPUT TYPE="RADIO" NAME="TypeGroup" onClick="DoChartType(5)">Line</TD>

>     102: <TD><INPUT TYPE="RADIO" NAME="TypeGroup" onClick="DoChartType(8)">Area</TD>

>     103: <TD><INPUT TYPE="RADIO" NAME="StyleGroup" onClick="DoChartStyle(1)">Stacked

>     104: </TR>

>     105: <TR>

>     106: <TD><INPUT TYPE="RADIO" NAME="TypeGroup" CHECKED

>                onClick="DoChartType(11)">Column</TD>

>     107: <TD><INPUT TYPE="RADIO" NAME="TypeGroup" onClick="DoChartType(14)">Bar</TD>

>     108: <TD><INPUT TYPE="RADIO" NAME="StyleGroup"

>                onClick="DoChartStyle(2)">100%</TD></TD>

>     109: </TR>

>     110: <TR>

>     111: <TD COLSPAN=3 BGCOLOR=#FFFFCC>Grid</TD>

>     112: </TR>

>     113: <TR>

>     114: <TD><INPUT TYPE="CHECKBOX" NAME="HGrid"

>                onClick="HorizontalGrid(HGrid)">Horizontal</TD>

>     115: <TD><INPUT TYPE="CHECKBOX" NAME="VGrid"

>                onClick="VerticalGrid(VGrid)">Vertical</TD>

>     116: <TD></TD>

>     117: <TR>

>     118: <TD COLSPAN=3 BGCOLOR=#FFFFCC>Stock Prices</TD>

>     119: <TR>

>     120: <TD COLSPAN=3>

>     121: <TABLE>

>     122: <TD></TD>

>     123: <TD><INPUT TYPE="BUTTON" VALUE="MSOFT"></TD>

>     124: <TD><INPUT TYPE="BUTTON" VALUE="IBM"></TD>

>     125: <TD><INPUT TYPE="BUTTON" VALUE="DEC"></TD>

>     126: <TD><INPUT TYPE="BUTtON" VALUE="NETSCAPE"></TD>

>     127: <TD><INPUT TYPE="BUTTON" VALUE="NOVEL"></TD>

>     128: <TR>

>     129: <TD><INPUT TYPE="Button" VALUE="This week"></TD>

>     130: <TD><INPUT TYPE="Text" NAME="d00" SIZE=11 VALUE="15"

>                onChange="NewData 0, 0, d00"></TD>

>     131: <TD><INPUT TYPE="Text" NAME="d01" SIZE=11 VALUE="13"

>                onChange="NewData 0, 1, d01"></TD>

>     132: <TD><INPUT TYPE="Text" NAME="d02" SIZE=11 VALUE="22"

>                onChange="NewData 0, 2, d02"></TD>

>     133: <TD><INPUT TYPE="Text" NAME="d03" SIZE=11 VALUE="17"

>                onChange="NewData 0, 3, d03"></TD>

>     134: <TD><INPUT TYPE="Text" NAME="d04" SIZE=11 VALUE="14"

>                onChange="NewData 0, 4, d04"></TD>

>     135: <TR>

>     136: <TD><INPUT TYPE="Button" VALUE="Last Week"></TD>

>     137: <TD><INPUT TYPE="Text" NAME="d10" SIZE=11 VALUE="23"

>                onChange="NewData 1, 0, d10"></TD>

>     138: <TD><INPUT TYPE="Text" NAME="d11" SIZE=11 VALUE="18"

>                onChange="NewData 1, 1, d11"></TD>

>     139: <TD><INPUT TYPE="Text" NAME="d12" SIZE=11 VALUE="19"

>                onChange="NewData 1, 2, d12"></TD>

>     140: <TD><INPUT TYPE="Text" NAME="d13" SIZE=11 VALUE="24"

>                onChange="NewData 1, 3, d13"></TD>

>     141: <TD><INPUT TYPE="Text" NAME="d14" SIZE=11 VALUE="21"

>                onChange="NewData 1, 4, d14"></TD>

>     142: </TR>

>     143: </TABLE>

>     144: </TD>

>     145: </TR>

>     146: </TABLE>

>     147: </FORM>

>     148: </TD>

>     149: </TR>

>     150: </TABLE>

>     151: </BODY>

>     152: </HTML>

Notice that the OptionButton controls contain the `onChange` attribute in their definitions, which specifies the name of the procedure to be executed every time the user checks, or clears, them. The subroutines `DoChartType()` and `DoChartStyle()`do all the work in this program. The `DoChartType()` subroutine sets the basic type of the graph and the `DoStyleChart()` subroutine sets the flavor of the basic type. They both accept an argument, which is a number representing the chart's type and style. Both subroutines examine the value of their argument and set the value of the `GraphType` property accordingly. The `DoChartType()` subroutine accepts an integer argument, which is the value of the `GraphType` property for the simple version of the desired type (`0` for pie charts, `2` for line plots, `5` for point plots, and so on). The `DoChartStyle()` subroutine accepts an integer which is `0` for simple charts, `1` for stacked charts, and `2` for full charts.

The same method of invoking the proper subroutine is used when a TextBox's value changes, too. This time we used the `onChange` attribute, which calls the specified subroutine each time the control's value changes. When the value changes, all TextBox controls call the `NewData()` subroutine, with three arguments: the dataset and datapoint number and the new value. The dataset number is `0` or `1`, depending on the row of the TextBox, and the datapoint number is a value between `0` and `4`. (There are five datapoints in each dataset.)

The rest of the code is rather trivial, in the sense that it sets the various properties of the Chart control to adjust the graph's appearance. You might want to examine the `DoChartStyle()` subroutine, which sets the graph's type based on the arguments it receives when called.

## The GridChart Example

The GridChart document we are going to implement in this chapter is shown in Figure 27.1, and you will find it on the CD. It's one of the lengthiest applications presented in this book, and it demonstrates not only a few controls but the type of functionality you add to your VBScript applications with the help of ActiveX controls. As you will soon realize, the code is rather straightforward, once you understand the concepts of manipulating the Grid and Chart controls. Fortunately, there are many similarities between the two controls, and this will simplify the code too.

The GridChart project is similar in principle to the Grid project, except the data-entry aspect of the application has been vastly improved with the functionality of the Grid control. The drawback of this application is that you can't use it unless you have the Grid control installed on your system. (It's an OLE control that comes with Microsoft's languages and can be freely distributed with the application.) Moreover, the user will see a warning every time Internet Explorer loads the control, as discussed in the previous chapters. When the warning appears, click Yes to load the control. As long as you have the source code and can verify that you are loading a Microsoft control, there's no security risk for your computer.

The user interface of the GridChart project is straightforward. The grid is where the user enters data and the various command buttons perform a few basic operations. The Edit Grid button displays a pop-up menu, with the following commands:

Delete current row | Deletes all the cells in the current row.
Delete current column | Deletes all the cells in the current column.
Fill current row | Fills all the cells in the current row with a user-supplied value.
Fill current column | Fills all the cells in the current column with a user-supplied value.
Clear Grid | Clears the contents of the grid.

These commands are quite easy to implement, and they demonstrate the types of operations you can perform on the Grid control.

The Process Data button leads to another pop-up menu, with the following commands:

> MEAN of selected cells
> MIN of selected cells
> MAX of selected cells

These commands have not been implemented, but you will see how you can detect the selected cells in the grid and access their values shortly. Then you'll be able to implement these, as well as other, more complicated calculations with the selected cells.

The last button, Plot Data, copies the values of the selected cells to the Chart control, which plots them immediately.

The OptionButton and CheckButton controls next to the Chart control control the appearance of the graph. They simply set the `GraphType`, `HGridStyle`, and `VGridStyle` properties of the Grid accordingly-and you'll probably want to add more options to better control your graphs.

### The Grid Control

The Grid control is a simple spreadsheet you can place on your layouts to either display or accept data from the user. It looks a lot like a spreadsheet, with cells arranged in a table, and each cell can be addressed via a row and a column number. The Grid control was designed for presenting data to the user and doesn't provide any means for accepting user input. This problem, however, is easily fixed by taking control of the `KeyPress` events on the control. You can supply some VBScript code in the Grid's `KeyPress` event to convert the user's keystrokes to digits and display them in the current cell.

Figure 27.3 shows a Grid control as it appears on a layout, in the ActiveX Control Pad. To place a Grid control on a layout, you must first add its icon to the toolbox, with the help of the Additional controls commands of its shortcut menu. In the Insert ActiveX control dialog box, select Grid Object and a little grid icon will be placed on the toolbox. (You can see it in the toolbox of Figure 27.3.) Use this icon to place Grid controls on your layouts just like all other controls.

Figure 27.3 : A Grid control placed on a layout with the ActiveX Control Pad.

The cells of the first row and column have a gray background because they were meant to be used as titles for the corresponding columns and rows. The unique feature of these cells is that they don't scroll along with the rest of the cells, so the titles always remain visible. You can change the number of title rows and columns with the `FixedCols` and `FixedRows` properties. Another characteristic of the title row and column is that when one of their cells is clicked, the entire row or column is selected.

Let's start by looking at the Grid control's properties, which we are going to use in the code. The number of visible columns and rows on the control is set by the `Rows` and `Cols` properties. Depending on the size of the control and the number and size of the cells, it's possible that not all cells will fit within the control's dimensions. In this case, you can attach a vertical and/or a horizontal scrollbar, to let the user quickly locate the section of the grid he or she wants to view. The scrollbars will not be visible during the design of the project and will appear when the document is opened with Internet Explorer only if they are needed.

Each column in the grid may have its own width, which is controlled by the `ColWidth` property. To set the width of the first column (the title column), use the statement

>     Grid1.ColWidth(0)=500

The width's value is expressed in twips, and there are 20 twips in a point. The previous statement sets the width of the first column to approximately 25 points. Likewise, each row may have a different height, which is controlled by the `RowHeight` property, whose syntax is quite similar. Notice that the user can change the width of columns and height of rows at runtime, by dragging the column and row separators with the mouse. If you place the mouse over a dividing line between two columns (or rows) and in the title section of the grid, it will assume the shape of a double arrow, indicating that it can be dragged to resize a row or column of cells.

To access a specific cell, assign its coordinates to the `Row` and `Col` properties of the control and then access its `Text` property. The `Text` property can be read or set. As you might recall, the same approach is used with the Chart control to assign values to its `Data` array, which holds the datapoints to be plotted. As with the Chart control, the indexing of the Grid control's rows and columns starts at 0. To read the value of the fifth cell on the second column, use the statements

>     Grid1.Row=4

>     Grid1.Col=1

>     thisnumber=Grid1.Text

or replace the third statement with one like the following to assign a new value to the cell:

`Grid1.Text=100.01`

To read all the values in the fourth row and store them in an array, you must use a loop like this one:

>     Grid1.Row=3

>     For icol=1 to MaxRows

>         Grid1.Col=icol

>         a(icol)=Grid1.Text

>     Next

If you want to read multiple rows and store them in a two-dimensional array, use two nested loops, the outer one scanning the selected rows and the inner one scanning the selected columns in each row. As you might have guessed already, we'll use a similar loop to copy the values of the selected cells on the grid to the chart's data array.

The `SelStartRow` and `SelStartCol` properties return the number of the first and last selected rows respectively. Likewise, the `SelStartCol` and `SelEndCol` properties return the first and last selected columns in the grid. Because the user will rarely fill in all the cells in a grid, use these four properties to limit the area of the grid you work with. When the user is ready to plot the grid's data, he or she must first select a range of cells with the mouse and then click on the Plot Data button. The program assumes that each dataset corresponds to a row of the grid and the columns are the datapoints. The code that copies the values from the grid to the Chart control's data array is shown here:

>     StartRow=Grid1.SelStartRow

>     StartCol=Grid1.SelStartCol

>     EndRow=Grid1.SelEndRow

>     EndCol=Grid1.SelEndCol

>     IEChart1.Columns=EndRow-StartRow+1

>     IEChart1.Rows=EndCol-StartCol+1

>     ccol=0

>     For irow=StartRow to EndRow

>         crow=0

>         For icol=StartCol to EndCol

>             Grid1.Row=irow

>             Grid1.Col=icol

>             IEChart1.RowIndex=crow

>             IEChart1.ColumnIndex=ccol

>             IEChart1.DataItem=Grid1.Text

>             crow=crow+1

>         Next

>         ccol=ccol+1

>     Next

First it sets the `StartRow`, `EndRow`, `StartCol`, and `EndCol` properties that delimit the area of the grid we are interested in. Then, it sets the `Columns` and `Rows` properties of the Chart control so that the correct number of datasets and data points in each dataset will be plotted. The two loops do the actual copying of the values from the Grid to the Chart control. Notice the similarities in the commands that select the current cell in the grid and the current data point in the current dataset in the Chart control. For both controls, we set a column and a row value, which identify a single element (a cell in the case of the Grid control and a data value in the case of the Graph control). Then we use the `Text` property to read the value of the current cell in the Grid control and the `DataItem` property of the Chart control to set the value of the current data point in the Graph control. As soon as all the values have been copied, the Chart control's graph will be updated. This code must be placed in the Plot Data Command button's `Click` event and is probably the most challenging (and most interesting) part of the application. Most of the remaining code simply sets the various properties of the controls.

### Implementing the Application

The first problem to deal with is how to make the Grid control accept user data. By default, the Grid control does not let the user enter data. But it recognizes the various `Keyboard` events, so it shouldn't be difficult to simulate data-entry operations. Indeed, you can place a few lines of VBScript code in the control `KeyPress` event to capture the keystrokes and translate them to digits to be displayed on the current cell. The code is fairly simple; it has to check the key pressed and make sure that it was a valid alphanumeric symbol and then append it to the current cell's contents. Providing the functionality of the various editing keys, especially mouse operations, is quite complicated, so we decided to let the user edit the cells' contents with the Backspace key only. Here's the code of the Grid's `KeyPress` event handler:

>     Sub Grid1_KeyPress(ByVal KeyAscii)

>     If KeyAscii=8 and Len(Grid1.Text)>0 Then

>        Grid1.Text=Left(Grid1.Text, Len(Grid1.Text)-1)

>        Exit Sub

>     End If

>     If KeyAscii<32 Then

>        Exit Sub

>     End If

>     Grid1.Text=Grid1.Text+chr(KeyAscii)

>     End Sub

The first `If` structure checks for the Backspace key. If the Backspace key was pressed and the cell contains text, it deletes the rightmost character. If the key pressed does not correspond to a printable character, the keystroke is ignored. If you open the GridChart application and test-drive it for a few minutes, you'll realize that this short code works quite well.

The various commands of the Edit pop-up menu are straightforward, too. They make use of the `Cols` and `Rows` properties of the Grid control to assign values to a range of cells with a `For...Next` loop. The subroutine that fills a row with a user-supplied value is

>     Sub FillRow()

>        Entry=InputBox("Please enter value to copy into current row")

>        irow=Grid1.Row

>        For icol=1 to Grid1.Cols-1

>           Grid1.Col=icol

>           Grid1.Text=Entry

>        Next

>     End Sub

The code for deleting the contents of the cells in a given row is

>     Sub DelRow()

>        irow=Grid1.Row

>        For icol=1 to Grid1.Cols-1

>           Grid1.Col=icol

>           Grid1.Text=""

>        Next

>     End Sub

We have already examined the code behind the Plot Data button, which copies the values of the selected cells from the Grid to the Chart control. The complete code of the GridChart project is shown in Listing 27.2.

> Listing 27.2. The GridChart project's complete code.

>       1: <SCRIPT LANGUAGE="VBScript">

>       2: <!--

>       3: Sub Form_onLoad()

>       4:    Grid1.Row=0

>       5:    For icol=1 to Grid1.Cols-1

>       6:       Grid1.Col=icol

>       7:       title="C" & icol

>       8:       Grid1.Text=title

>       9:    Next

>      10:    Grid1.Col=0

>      11:    For icol=1 to Grid1.Rows-1

>      12:       Grid1.Row=icol

>      13:       Grid1.Text="R" & icol

>      14:    Next

>      15: End Sub

>      16:

>      17: Sub CommandButton1_Click()

>      18:    call EditMenu.Popup()

>      19: End Sub

>      20:

>      21: Sub Grid1_KeyPress(ByVal KeyAscii)

>      22: If KeyAscii=8 and Len(Grid1.Text)>0 Then

>      23:    Grid1.Text=Left(Grid1.Text, Len(Grid1.Text)-1)

>      24:    Exit Sub

>      25: End If

>      26: If KeyAscii<32 Then

>      27:    Exit Sub

>      28: End If

>      29: Grid1.Text=Grid1.Text+chr(KeyAscii)

>      30: End Sub

>      31:

>      32: Sub DelRow()

>      33:    irow=Grid1.Row

>      34:    For icol=1 to Grid1.Cols-1

>      35:       Grid1.Col=icol

>      36:       Grid1.Text=""

>      37:    Next

>      38: End Sub

>      39:

>      40: Sub DelColumn()

>      41:    icol=Grid1.Column

>      42:    For irow=1 to Grid1.Rows-1

>      43:       Grid1.Row=irow

>      44:       Grid1.Text=""

>      45:    Next

>      46: End Sub

>      47:

>      48: Sub FillRow()

>      49:    Entry=InputBox("Please enter value to copy into current row")

>      50:    irow=Grid1.Row

>      51:    For icol=1 to Grid1.Cols-1

>      52:       Grid1.Col=icol

>      53:       Grid1.Text=Entry

>      54:    Next

>      55: End Sub

>      56:

>      57: sub FillColumn()

>      58:    Value=InputBox("Please enter value to copy into current column")

>      59:    icol=Grid1.Col

>      60:    for irow=1 to Grid1.Rows-1

>      61:       Grid1.Row=irow

>      62:       Grid1.Text=Value

>      63:    next

>      64: End sub

>      65:

>      66: sub ClearGrid()

>      67:    for icol=1 to Grid1.Cols

>      68:       for irow=1 to Grid1.Rows-1

>      69:          Grid1.Row=irow

>      70:          Grid1.Col=icol

>      71:          Grid1.Text=""

>      72:       next

>      73:    next

>      74: End sub

>      75:

>      76: Sub EditMenu_Click(ByVal item)

>      77:    if item=1 then DelRow()

>      78:    if item=2 then DelColumn()

>      79:    if item=3 then FillRow()

>      80:    if item=4 then FillColumn()

>      81:    if item=5 then ClearGrid()

>      82: End Sub

>      83:

>      84: Sub Mean()

>      85: msgbox "ENTER MEAN CALCULATIONS HERE"

>      86: End Sub

>      87:

>      88: Sub Max()

>      89: msgbox "ENTER MAX CALCULATIONS HERE"

>      90: End Sub

>      91:

>      92: Sub Min()

>      93: msgbox "ENTER MIN CALCULATIONS HERE"

>      94: End Sub

>      95:

>      96: Sub ProcessMenu_Click(ByVal item)

>      97:    if item=1 then Mean()

>      98:    if item=2 then Max()

>      99:    if item=3 then Min()

>     100: End Sub

>     101:

>     102: Sub CommandButton2_Click()

>     103: StartRow=Grid1.SelStartRow

>     104: StartCol=Grid1.SelStartCol

>     105: EndRow=Grid1.SelEndRow

>     106: EndCol=Grid1.SelEndCol

>     107:

>     108: IEChart1.Columns=EndRow-StartRow+1

>     109: IEChart1.Rows=EndCol-StartCol+1

>     110:

>     111: ccol=0

>     112: For irow=StartRow to EndRow

>     113:     crow=0

>     114:     For icol=StartCol to EndCol

>     115:         Grid1.Row=irow

>     116:         Grid1.Col=icol

>     117:         IEChart1.RowIndex=crow

>     118:         IEChart1.ColumnIndex=ccol

>     119:         IEChart1.DataItem=Grid1.Text

>     120:         crow=crow+1

>     121:     Next

>     122:     ccol=ccol+1

>     123: Next

>     124: End Sub

>     125:

>     126: Sub CommandButton3_Click()

>     127: ProcessMenu.PopUp()

>     128: end Sub

>     129:

>     130: Sub OptionButton1_Change()

>     131:     IEChart1.ChartType=1

>     132: End Sub

>     133:

>     134: Sub OptionButton2_Change()

>     135:     IEChart1.ChartType=5

>     136: End Sub

>     137:

>     138: Sub OptionButton3_Change()

>     139:     IEChart1.ChartType=14

>     140: End Sub

>     141:

>     142: Sub OptionButton4_Change()

>     143:     IEChart1.ChartType=8

>     144: End Sub

>     145:

>     146: Sub CheckBox1_Change()

>     147:     If CheckBox1.Value Then

>     148:         IEChart1.HGridStyle=1

>     149:     Else

>     150:         IEChart1.HGridStyle=0

>     151:     End If

>     152: End Sub

>     153:

>     154: Sub CheckBox2_Change()

>     155:     If CheckBox2.Value Then

>     156:         IEChart1.VGridStyle=1

>     157:     Else

>     158:         IEChart1.VGridStyle=0

>     159:     End If

>     160: End Sub

>     161:

>     162: -->

>     163: </SCRIPT>

>     164: <DIV STYLE="LAYOUT:FIXED;WIDTH:556pt;HEIGHT:314pt;">

>     165:     <OBJECT ID="Image1"

>     166:      CLASSID="CLSID:D4A97620-8E8F-11CF-93CD-00AA00C08FDF"

>                           STYLE="TOP:149pt;LEFT:17pt;WIDTH:528pt;HEIGHT:165pt;ZINDEX:0;">

>     167:         <PARAM NAME="BorderStyle" VALUE="0">

>     168:         <PARAM NAME="SizeMode" VALUE="3">

>     169:         <PARAM NAME="SpecialEffect" VALUE="1">

>     170:         <PARAM NAME="Size" VALUE="18627;5821">

>     171:         <PARAM NAME="PictureAlignment" VALUE="0">

>     172:         <PARAM NAME="VariousPropertyBits" VALUE="19">

>     173:     </OBJECT>

>     174:     <OBJECT ID="Grid1"

>     175:      CLASSID="CLSID:A8C3B720-0B5A-101B-B22E-00AA0037B2FC"

>                           STYLE="TOP:17pt;LEFT:17pt;WIDTH:429pt;HEIGHT:123pt;ZINDEX:1;">

>     176:         <PARAM NAME="_Version" VALUE="65536">

>     177:         <PARAM NAME="_ExtentX" VALUE="15134">

>     178:         <PARAM NAME="_ExtentY" VALUE="4339">

>     179:         <PARAM NAME="_StockProps" VALUE="77">

>     180:         <PARAM NAME="BackColor" VALUE="16777215">

>     181:         <PARAM NAME="Rows" VALUE="20">

>     182:         <PARAM NAME="Cols" VALUE="20">

>     183:     </OBJECT>

>     184:     <OBJECT ID="CommandButton1"

>     185:      CLASSID="CLSID:D7053240-CE69-11CD-A777-00DD01143C57"

>                           STYLE="TOP:66pt;LEFT:454pt;WIDTH:83pt;HEIGHT:25pt;TABINDEX:1;

>                           ZINDEX:2;">

>     186:         <PARAM NAME="Caption" VALUE="Edit Grid">

>     187:         <PARAM NAME="Size" VALUE="2911;882">

>     188:         <PARAM NAME="FontHeight" VALUE="240">

>     189:         <PARAM NAME="FontCharSet" VALUE="0">

>     190:         <PARAM NAME="FontPitchAndFamily" VALUE="2">

>     191:         <PARAM NAME="ParagraphAlign" VALUE="3">

>     192:         <PARAM NAME="FontWeight" VALUE="0">

>     193:     </OBJECT>

>     194:     <OBJECT ID="CommandButton2"

>     195:      CLASSID="CLSID:D7053240-CE69-11CD-A777-00DD01143C57"

>                                  STYLE="TOP:116pt;LEFT:454pt;WIDTH:83pt;HEIGHT:25pt;

>     							 TABINDEX:2;ZINDEX:3;">

>     196:         <PARAM NAME="Caption" VALUE="Plot Data">

>     197:         <PARAM NAME="Size" VALUE="2911;882">

>     198:         <PARAM NAME="FontHeight" VALUE="240">

>     199:         <PARAM NAME="FontCharSet" VALUE="0">

>     200:         <PARAM NAME="FontPitchAndFamily" VALUE="2">

>     201:         <PARAM NAME="ParagraphAlign" VALUE="3">

>     202:         <PARAM NAME="FontWeight" VALUE="0">

>     203:     </OBJECT>

>     204:     <OBJECT ID="CommandButton3"

>     205:      CLASSID="CLSID:D7053240-CE69-11CD-A777-00DD01143C57"

>                           STYLE="TOP:91pt;LEFT:454pt;WIDTH:83pt;HEIGHT:25pt;TABINDEX:3;

>                           ZINDEX:4;">

>     206:         <PARAM NAME="Caption" VALUE="Process Data">

>     207:         <PARAM NAME="Size" VALUE="2911;882">

>     208:         <PARAM NAME="FontHeight" VALUE="240">

>     209:         <PARAM NAME="FontCharSet" VALUE="0">

>     210:         <PARAM NAME="FontPitchAndFamily" VALUE="2">

>     211:         <PARAM NAME="ParagraphAlign" VALUE="3">

>     212:         <PARAM NAME="FontWeight" VALUE="0">

>     213:     </OBJECT>

>     214:     <OBJECT ID="iechart1"

>     215:      CLASSID="CLSID:FC25B780-75BE-11CF-8B01-444553540000"

>                           STYLE="TOP:157pt;LEFT:50pt;WIDTH:313pt;HEIGHT:140pt;ZINDEX:5;">

>     216:         <PARAM NAME="_ExtentX" VALUE="11033">

>     217:         <PARAM NAME="_ExtentY" VALUE="4948">

>     218:         <PARAM NAME="Rows" VALUE="4">

>     219:         <PARAM NAME="Columns" VALUE="3">

>     220:         <PARAM NAME="ChartType" VALUE="8">

>     221:         <PARAM NAME="Data[0][0]" VALUE="0">

>     222:         <PARAM NAME="Data[0][1]" VALUE="10">

>     223:         <PARAM NAME="Data[0][2]" VALUE="11">

>     224:         <PARAM NAME="Data[1][0]" VALUE="7">

>     225:         <PARAM NAME="Data[1][1]" VALUE="11">

>     226:         <PARAM NAME="Data[1][2]" VALUE="12">

>     227:         <PARAM NAME="Data[2][0]" VALUE="6">

>     228:         <PARAM NAME="Data[2][1]" VALUE="12">

>     229:         <PARAM NAME="Data[2][2]" VALUE="13">

>     230:         <PARAM NAME="Data[3][0]" VALUE="11">

>     231:         <PARAM NAME="Data[3][1]" VALUE="13">

>     232:         <PARAM NAME="Data[3][2]" VALUE="14">

>     233:         <PARAM NAME="HorizontalAxis" VALUE="0">

>     234:         <PARAM NAME="VerticalAxis" VALUE="0">

>     235:         <PARAM NAME="hgridStyle" VALUE="0">

>     236:         <PARAM NAME="vgridStyle" VALUE="0">

>     237:         <PARAM NAME="ColorScheme" VALUE="0">

>     238:         <PARAM NAME="BackStyle" VALUE="1">

>     239:         <PARAM NAME="Scale" VALUE="100">

>     240:         <PARAM NAME="DisplayLegend" VALUE="1">

>     241:         <PARAM NAME="BackColor" VALUE="16777215">

>     242:         <PARAM NAME="ForeColor" VALUE="32768">

>     243:     </OBJECT>

>     244:     <OBJECT ID="OptionButton1"

>     245:      CLASSID="CLSID:8BD21D50-EC42-11CE-9E0D-00AA006002f3"

>                           STYLE="TOP:173pt;LEFT:396pt;WIDTH:108pt;HEIGHT:18pt;TABINDEX:4;

>                           ZINDEX:6;">

>     246:         <PARAM NAME="BackColor" VALUE="2147483663">

>     247:         <PARAM NAME="ForeColor" VALUE="2147483666">

>     248:         <PARAM NAME="DisplayStyle" VALUE="5">

>     249:         <PARAM NAME="Size" VALUE="3810;635">

>     250:         <PARAM NAME="Caption" VALUE="Pie Chart">

>     251:         <PARAM NAME="FontName" VALUE="Verdana">

>     252:         <PARAM NAME="FontHeight" VALUE="200">

>     253:         <PARAM NAME="FontCharSet" VALUE="0">

>     254:         <PARAM NAME="FontPitchAndFamily" VALUE="2">

>     255:         <PARAM NAME="FontWeight" VALUE="0">

>     256:     </OBJECT>

>     257:     <OBJECT ID="OptionButton2"

>     258:      CLASSID="CLSID:8BD21D50-EC42-11CE-9E0D-00AA006002f3"

>                           STYLE="TOP:191pt;LEFT:396pt;WIDTH:108pt;HEIGHT:18pt;TABINDEX:5;

>                           ZINDEX:7;">

>     259:         <PARAM NAME="BackColor" VALUE="2147483663">

>     260:         <PARAM NAME="ForeColor" VALUE="2147483666">

>     261:         <PARAM NAME="DisplayStyle" VALUE="5">

>     262:         <PARAM NAME="Size" VALUE="3810;635">

>     263:         <PARAM NAME="Caption" VALUE="Line Plot">

>     264:         <PARAM NAME="FontName" VALUE="Verdana">

>     265:         <PARAM NAME="FontHeight" VALUE="200">

>     266:         <PARAM NAME="FontCharSet" VALUE="0">

>     267:         <PARAM NAME="FontPitchAndFamily" VALUE="2">

>     268:         <PARAM NAME="FontWeight" VALUE="0">

>     269:     </OBJECT>

>     270:     <OBJECT ID="OptionButton3"

>     271:      CLASSID="CLSID:8BD21D50-EC42-11CE-9E0D-00AA006002f3"

>                           STYLE="TOP:206pt;LEFT:396pt;WIDTH:108pt;HEIGHT:18pt;TABINDEX:6;

>                           ZINDEX:8;">

>     272:         <PARAM NAME="BackColor" VALUE="2147483663">

>     273:         <PARAM NAME="ForeColor" VALUE="2147483666">

>     274:         <PARAM NAME="DisplayStyle" VALUE="5">

>     275:         <PARAM NAME="Size" VALUE="3810;635">

>     276:         <PARAM NAME="Caption" VALUE="Bar Graph">

>     277:         <PARAM NAME="FontName" VALUE="Verdana">

>     278:         <PARAM NAME="FontHeight" VALUE="200">

>     279:         <PARAM NAME="FontCharSet" VALUE="0">

>     280:         <PARAM NAME="FontPitchAndFamily" VALUE="2">

>     281:         <PARAM NAME="FontWeight" VALUE="0">

>     282:     </OBJECT>

>     283:     <OBJECT ID="OptionButton4"

>     284:      CLASSID="CLSID:8BD21D50-EC42-11CE-9E0D-00AA006002f3"

>                           STYLE="TOP:224pt;LEFT:396pt;WIDTH:108pt;HEIGHT:18pt;TABINDEX:7;

>                           ZINDEX:9;">

>     285:         <PARAM NAME="BackColor" VALUE="2147483663">

>     286:         <PARAM NAME="ForeColor" VALUE="2147483666">

>     287:         <PARAM NAME="DisplayStyle" VALUE="5">

>     288:         <PARAM NAME="Size" VALUE="3810;635">

>     289:         <PARAM NAME="Caption" VALUE="Area Graph">

>     290:         <PARAM NAME="FontName" VALUE="Verdana">

>     291:         <PARAM NAME="FontHeight" VALUE="200">

>     292:         <PARAM NAME="FontCharSet" VALUE="0">

>     293:         <PARAM NAME="FontPitchAndFamily" VALUE="2">

>     294:         <PARAM NAME="FontWeight" VALUE="0">

>     295:     </OBJECT>

>     296:     <OBJECT ID="CheckBox1"

>     297:      CLASSID="CLSID:8BD21D40-EC42-11CE-9E0D-00AA006002f3"

>                           STYLE="TOP:264pt;LEFT:396pt;WIDTH:99pt;HEIGHT:17pt;TABINDEX:8;

>                           ZINDEX:10;">

>     298:         <PARAM NAME="BackColor" VALUE="2147483663">

>     299:         <PARAM NAME="ForeColor" VALUE="2147483666">

>     300:         <PARAM NAME="DisplayStyle" VALUE="4">

>     301:         <PARAM NAME="Size" VALUE="3493;600">

>     302:         <PARAM NAME="Caption" VALUE="Horizontal Grid">

>     303:         <PARAM NAME="FontName" VALUE="Verdana">

>     304:         <PARAM NAME="FontHeight" VALUE="200">

>     305:         <PARAM NAME="FontCharSet" VALUE="0">

>     306:         <PARAM NAME="FontPitchAndFamily" VALUE="2">

>     307:         <PARAM NAME="FontWeight" VALUE="0">

>     308:     </OBJECT>

>     309:     <OBJECT ID="CheckBox2"

>     310:      CLASSID="CLSID:8BD21D40-EC42-11CE-9E0D-00AA006002f3"

>                           STYLE="TOP:280pt;LEFT:396pt;WIDTH:99pt;HEIGHT:17pt;TABINDEX:9;

>                           ZINDEX:11;">

>     311:         <PARAM NAME="BackColor" VALUE="2147483663">

>     312:         <PARAM NAME="ForeColor" VALUE="2147483666">

>     313:         <PARAM NAME="DisplayStyle" VALUE="4">

>     314:         <PARAM NAME="Size" VALUE="3493;600">

>     315:         <PARAM NAME="Caption" VALUE="Vertical Grid">

>     316:         <PARAM NAME="FontName" VALUE="Verdana">

>     317:         <PARAM NAME="FontHeight" VALUE="200">

>     318:         <PARAM NAME="FontCharSet" VALUE="0">

>     319:         <PARAM NAME="FontPitchAndFamily" VALUE="2">

>     320:         <PARAM NAME="FontWeight" VALUE="0">

>     321:     </OBJECT>

>     322: </DIV>

Notice that the definition of the `Chart` object contains random data. You can remove the `PARAM` tags that assign values to the `Data` array, or assign the same values to this array and the first few cells of the grid so that when the document is loaded, the graph will match the data on the grid.

Another item worth noticing is the assignment of titles to the grid's fixed cells. This action takes place when the layout is loaded. Because the cells of the first column and row are fixed, the user cannot edit them at runtime.

The GridChart application doesn't contain any error handlers. For example, it assumes that the user has already selected a range of cells before he or she attempts to plot them, and that they contain numeric data. If this isn't true, an error message will be displayed and the program will stop. There's a lot you can do to improve not only the application's interface and appearance, but its operation too. GridChart is a good starting point for a data-plotting applications, but there is quite a bit of error checking you can add to the program.

## Review

The last example of this section demonstrates two very flexible controls that are commonly used together: the Grid control and the Chart control. Although the Grid control was designed to facilitate the display of data in a spreadsheet arrangement, with a few lines of code in its `KeyDown` and `KeyPress` events, you can turn it into a data-entry tool. The Chart control displays numeric data, like the ones stored on a Grid control, as graphs.

The two controls have more functional similarities, too. They both manipulate data stored in a two-dimensional array. The two-dimensional structure of the Grid's data is rather obvious. The Chart control uses a similar arrangement for storing multiple datasets, with as many data points per dataset. To access a cell in a grid, you must specify its address, which is the row and column number of the cell. To access a data point in a Chart control, you must specify the dataset it belongs to, and its order in the dataset. The address of a cell in a Grid control is specified with the help of the `Row` and `Col` properties, and a data point in a Chart control is specified with the `RowIndex` and `ColIndex` properties. Once the address of an element has been specified with the properties mentioned here, you can use the `Text` property of the Grid control or the `DataItem` property of the Chart control to read or set its value. The two controls provide a number of properties for specifying the appearance of the data or the chart, but you can easily figure out most of them, or experiment with the various settings to get what you want.

| Use of this site is subject certain Terms & Conditions. Copyright (c) 1996-1999 EarthWeb, Inc.. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Please read our privacy policy for details.