Joseph Frese
Keithley Instruments, Inc.

In Part I of this article, we described most of the VB6 code required to link input controls, such as text boxes and check boxes, to a user’s test system. These controls allow a remote user to configure a data acquisition (DAQ) card by entering a channel number, channel gain, sampling frequency, and number of samples on an HTML form. The test system then acquires the requested data and displays it on a web page as a JPEG graph, and (optionally) in text form. In this final part of the article, we define the replacements for custom tags that are used with the HTML template that was created. We also present some code that implements the WebClass/User Interaction in this test system. Results are illustrated with typical user screens.

WebClass/Template Interaction — The ProcessTag event subroutine is fired every time one of our custom tags is encountered. To define the replacements for the custom tags, use the code in Table 7 in the code window:

Table 7. Template1_ProcessTag() subroutine.

Private Sub Template1_ProcessTag(ByVal TagName As String, _

TagContents As String, _

SendTags As Boolean)

Dim I As Integer

Select Case LCase(TagName)


End Select

End Sub

The TagName parameter here is the custom tag as it appears in the template. TagContents is the string we’d like to replace the custom tag with, which we must define in the subroutine. SendTags allows you to send XML tokens to the client and is useful for debugging; its default value is false and for our purposes that’s just fine.

Because we have three custom tags, let’s deal with this subroutine in bite size chunks, one tag at a time. The following three tables present code snippets that you need to insert into the Select block of the Template1_ProcessTag() subroutine above.

Table 8. "[email protected]" code for Select block of the Template1_ProcessTag() subroutine.

Case "[email protected]" 'Show the graph (if one exists)

If strPic <> "" Then

TagContents = "<P ALIGN=CENTER><IMG SRC=" & strPic & ">"

End If

If ErrMsg <> "" Then

TagContents = TagContents & "<STYLE " & _

"TYPE=""text/css"">P.error {color: " & _

"red;)</STYLE><P ALIGN=Center " & _

"CLASS=""error"">" & ErrMsg

End If

The Case subroutine in Table 8 adds the graph JPG (if it exists) to the document. If it does not exist, then presumably strPic will be empty. The subroutine also displays in red any error messages that may exist.

Table 9. "[email protected]" code for Select block of the Template1_ProcessTag() subroutine.

Case "[email protected]" 'Write the input controls

TagContents = "<CENTER><TABLE BORDER=0>"

TagContents = TagContents & vbCrLf & _

"<TR><TD>Channel:</TD><TD><INPUT TYPE=""text""" & _

"NAME=""iChannel"" VALUE=""" & Channel & """></TD></TR>"

TagContents = TagContents & vbCrLf & _

"<TR><TD>Gain:</TD><TD><INPUT TYPE=""text""" & _

"NAME=""iGain"" VALUE=""" & Gain & """></TD></TR>"

TagContents = TagContents & vbCrLf & "<TR><TD>Number of " & _

"Samples:</TD><TD><INPUT TYPE=""text""" & _

"NAME=""iNumSamples"" VALUE=""" & NumSamples & _


TagContents = TagContents & vbCrLf & _

"<TR><TD>Frequency:</TD><TD><INPUT TYPE=""text""" & _

"NAME=""iFrequency"" VALUE=""" & Frequency & _


TagContents = TagContents & vbCrLf & _

"<TR><TD ALIGN=CENTER><INPUT TYPE=""checkbox""" & _

"NAME=""iShowData"" VALUE=""True"""

If ShowData Then TagContents = TagContents & "CHECKED"

TagContents = TagContents & "> Show data"

TagContents = TagContents & vbCrLf & "</TABLE></CENTER>"

In Table 9, the Case subroutine displays the input controls for the end-user. These include:

If the user checks this last box, then we need to display the data in text format, and that is precisely what the final Case in Table 10 accomplishes:

Table 10. "[email protected]" code for Select block of the Template1_ProcessTag() subroutine.

Case "[email protected]" 'Show the data (if requested)

If ShowData Then

TagContents = TagContents & vbCrLf & _


"<P><B><BIG>Data:</BIG></B><P>" & _


For I = 0 To NumSamples / 3 - 1

TagContents = TagContents & vbCrLf & Data(I) & "<BR>"

Next I

TagContents = TagContents & "</TD><TD VALIGN=Top WIDTH=33%>"

For I = NumSamples / 3 To 2 * NumSamples / 3 - 1

TagContents = TagContents & vbCrLf & Data(I) & "<BR>"

Next I

TagContents = TagContents & "</TD><TD VALIGN=Top WIDTH=33%>"

For I = 2 * NumSamples / 3 To NumSamples - 1

TagContents = TagContents & vbCrLf & Data(I) & "<BR>"

Next I

TagContents = TagContents & "</TD></TR></TABLE></TD></TR>"

End If

This final Case uses a lot of HTML code to essentially format our data into three even columns.

(Presumably, the data has been stored in the Data() array and NumSamples has been set to the size of this array.)

That wraps up the Template1_ProcessTag subroutines controlling our WebClass/Template interaction. If we click the RUN button on the Visual Basic debug toolbar to run our code, we begin to see the fruits of our labor. (VB will first ask you to select a Start Component and may ask you to name a Virtual Directory for the project to execute in; for our purposes, accepting the defaults for these values is fine.) Your default web browser should automatically open and display a page similar to the one below:


The fact that our input controls showed up (with the default values we specified in WebClass_Start) means that our project is proceeding as planned; however, if you click the Submit button, you’re taken to a blank page. To actually acquire data, we need to implement the Template1_Form1 subroutine.

WebClass/User Interaction — Since the Template1_Form1 event is fired when the user hits the "submit" button, we create the code in Table 11 to request the pertinent information from the form. This information is used to execute our data acquisition.

Table 11. Template1_Form1() event subroutine.

Private Sub Template1_Form1()

Dim Test As New clsTestSystem

'Get user input from web page

Channel = Request("iChannel")

Gain = Request("iGain")

NumSamples = Request("iNumSamples")

Frequency = Request("iFrequency")

ShowData = Request("iShowData")

'Validate the input parameters

If Not (IsNumeric(Channel) And IsNumeric(Gain) And _

IsNumeric(NumSamples) And IsNumeric(Frequency)) _

Then GoTo InputErr

'Acquire the data

If (0 = Test.AcquireData(Channel, Gain, Frequency, _

NumSamples, Data())) Then

'If no error, create the graph and assign name to strPic

strPic = Test.CreateGraph(Data, NumSamples)

If strPic = "" Then ErrMsg = "Error graphing data!"


'Otherwise, set ErrMsg

strPic = ""

ErrMsg = "Error acquiring data!"

End If


Set Test = Nothing

'Fire the Template1_Respond event

Set NextItem = Template1

Exit Sub


StrPic = ""

ErrMsg = "Input error!"

GoTo EndSub

End Sub

The subroutine above begins by requesting the values from our input controls. Each of the Request functions take the name property of the appropriate input tag and return that control’s value. The subroutine then validates the parameters before feeding them to our test system DLL, which acquires the requested data and (if there are no errors) generates the graph JPG. Relevant global variables (Data(), strPic, and ErrMsg) are updated along the way. Finally, the last line of the routine fires the Template1_Respond event, so our HTML template gets parsed, processed, and written again. If you execute this now-completed project and hit the Submit button, and your test system DLL was written correctly, your browser window should look something like the following:

If you check the "Show data" box and hit the "submit" button again, individual data points will be reported:

Now you can make TestInterface.DLL and share your project with your friends and neighbors. Just make sure your personal web server is running, and point any computer on your network to the proper URL (which should be http://yourIPaddress/Project1/WebClass1.asp, if you kept the default values for the virtual directory and the WebClass’s ASP name). You’ve just made your test system accessible to everyone on your local Intranet, and if you’re on the Internet, to everyone in the world.

About the Author

Joseph Frese joined Keithley Instruments in Cleveland after receiving a bachelor’s degree in Computer Engineering from Case Western Reserve University. He currently is a Development Engineer for Keithley’s Data Acquisition product line.

# # #