If youve ever worked with ODBC linked tables, you know how great it is to be able to use Windows -based development software to manipulate data from the AS/400. You also know the downside: Working with ODBC linked tables is slow. Well, thanks to Microsofts ActiveX Data Objects (ADO) and Client Access Express V4R4 for Windows OLE DB connectivity, you can have your cake and eat it, too. ADO/OLE DB allows you to use robust, flexible Windows software design tools without the slow performance of ODBC linked tables. And the best part i s that once you learn the technique, you can use it in Visual Basic (VB), Microsoft Access, Microsoft Excel, or even Active Server Pages (ASP). If youre running Microsoft Office and Client Access/400, you have all the tools you need to get ADO up and runn ing.
This article shows you how to use Microsoft Access 97, ADO, and Client Access Express for Windows OLE DB support to create a report of files and their fields in a selected library. To begin, I note one key difference between ADO and ODBC linked tables. When working with ODBC, you link the table and forget about it. When using ADO, you download only the records you need into a Microsoft Access table using standard SQL and do the rest of your processing from there.
Using ADO is faster for several reason s. For one, you are making the AS/400 do what it does best crunch data. Second, you are dealing with only the records you need in Access, not the entire table(s) from the AS/400. And finally, because the data is local to the PC (in an Access table), it is processed much faster than if it were in a linked table. (Editors Note: This article and code are written for Microsoft Access 97, but the code has also been tested in Access 2000. There are some subtle differences between the 97 and 2000 versions of Micr osoft Access that may confuse users of Access 2000 who are attempting to follow this article step by step. To remedy this, both an Access 97 and an Access 2000 version of the database and code are available for download from the MC Web site at www.midrange computing.com/mc/. Access 2000 users will need to recompile
the module after changing user ID, password, and system names for the project to execute properly.)
No, Im not referring to woodworking. The first thing you need to do is create the Access tables that will be used to hold the records downloaded from the AS/400. To create these tables, click (from the Tables tab) on New and select Design View. Use the information in Figure 1 to create tblTables when the table design form is display ed. Make sure you type all of the information exactly as it appears. (Field and table names in Access are case sensitive.) The tblTables table will contain data about the AS/400 files downloaded from the SYS_TABLES logical file in QSYS2. Define the Library and File fields as the primary key for this table and make sure that Allow Zero Length is set to Yes for the Heading field. After saving tblTables, use the same procedure to create the tblFields table. This table holds the file/field data downloaded from the SYS_COLUMNS logical in QSYS2. Define the primary key for this table using the Library, File, and Sequence fields and ensure that the Description field has Allow Zero Length set to Yes. Once you have the tables defined, you can start coding.
To retrieve the file data from the AS/400, you will be working with Microsoft Access Visual Basic modules. (Some familiarity with Access and VB will be helpful in completing this exercise.) To create the module, go to the Modules tab and click on New. Bef ore you can use the ADO libraries, you need to reference them. To do this, go to the Tools menu and click on References. You should see an item in the list of available references named Microsoft ActiveX Data Objects 2.x Libraries. Make sure that the box n ext to this item is checked; clicking this box gives your module access to the ADO/OLE DB objects.
The ADO/OLE DB objects are made up of several other objects. One is the Connection object, which defines the provider and data source information as well as the user name and password information for the data source. Another is the Command object, which is used to send commands to the data source. Finally, at least one Recordset object is used to retrieve the data defined by the Command object. The Connection object has an errors collection that is used in error trapping. The Command object is associated with the parameters collection, which is used to pass values into a parameterized SQL statement. The Recordset object uses its fields collection to access the data stored in the Recordset. You can improve performance by adjusting the CacheSize property on the ADO/OLE DB recordset. As a general rule, a value between 1,000 and 2,000 will give the best performance, but you will probably want to experiment and see what value gives you the best results. Create a new VB module by selecting the Modules tab and clicking on New. Now, type in the DownData subroutine shown in Figure 2. This will be used to retrieve data from the AS/400. Make sure you save this module unde r the name DownData also. This module first defines the ADO Connection object (conn), then defines the ADO Command object (cmd), which is used to pass the SQL commands through ADO. The module then defines the SQL statement to select the records from the sy stem table for the requested library. You should use parameterized SQL statements rather than concatenate the library name because the statements offer better performance. The ? is
the placeholder for the parameter. You can then pass in the parameter by using the parameters collection on the cmd object (i.e., cmd. parameter(0) is the first parameter, cmd.parameter(1) is the second, and so on).
Using the parameters collection gives better performance because the query optimizer doesnt have to optimize the SQL statements every time the command is run. (The query optimizer runs the same SQL statement, only with a different parameter.) Now, the program can read through the records in the recordset that was defined by the SQL statement. The program adds these records to the tblTables Access table using the AddNew method on the tblTables object. You will use this same technique to read all of the field information from the tblSysColumns table and populate the records into the tblFields access table.
This is the same basic technique you might use to read data from any database file on your AS/400. The technique is similar to the one you would use to read data and write it out in an RPG program. Once the module downloads the requested data, it will display the report in Print Preview mode. The subfunction will display an error -message box if the library name entered is invalid. (Editors Note: If you are using Microsoft Access 2000, you need to compile the code before it will execute. To compile, select Compile fro m the Debug menu.)
Form, Query, and Report Definitions
Now that you have the code to download AS/400 data to Access, you can create a simple form to act as a prompt for the library name. To create this form, go to the Forms tab and select New. When the Ne w Form box appears, select Design View and click on OK. First, we will add a text box to the form. To do this, select the text box icon from the form designer toolbox. This is the icon that resembles a lowercase ab. Now, click on the area of your form wher e you want to place the new text box and drag to create a small one -line text box. Make sure the size of the box will be large enough to allow for the entry of an AS/400 library name. Now, right -click on the text box and select Properties from the menu. On the Other tab, enter the Name property as txtLibrary. Now, select the Command button from the toolbox and use it to create a new Command button on your form. If the Command button wizard is displayed, simply click Cancel. Using the same technique we used for the text box, rename the Command button as cmdRun. While on the Properties box, click on the Events tab. Select the OnClick event of the cmdRun button and type Call DownData; this gives control to the subroutine. Next, right -click on the top of your form window and select Properties from the Context menu. Now, click on the Format tab and change the BorderStyle property to Dialog; changing this property prevents the box from being resized at runtime. When you close the form, Access will ask if you want to save it; save the form as frmFileInformation. Next, you need to create a query to join the two temporary tables. You will use this query to create the file information report. Click on the Queries tab, select New, and create the query in Design View. Close the Show Table dialog; do not add any tables to the query. When the QBE screen appears, click on the View menu and select SQL View. When the SQL View is displayed, replace the Select statement with the SQL statements in Figure 3. Again, remember to type all of the lines exactly as they appear. Now, save the query as qryHeaderDetailJoin.
You now need to create the report. To do this, click on New from the Reports tab, select Design View, and select qryHeaderDetailJoin from the combo list box. When the design screen appears, resize the page to 8 inch width. Next, go to the File menu and select Page Setup and reduce all margins to .25. Doing this will allow you to use a larger area of the page for your report.
At this point, you need to define the repor t groups. Report groups will let you define how the records will sort and group. To set up the groups, go to the View menu and click Sorting and Grouping. When the dialog is displayed, select the Library and File fields as the first two sort fields and cha nge both fields Group Header property to Yes. Now, add the Sequence field as the third sort field. Make sure the Sequence fields Group Header and Group Footer properties are both No and close the Sorting and Grouping box.
From the View menu, click on Fi eld List to display the available fields from the query. Using Figure 4 as a guide, position the fields on the page: Simply click on the field in the list and drag it to the proper area of the report screen. As you do this, you will notice that Access will automatically create a label as the field heading. When dragging fields to the detail section, delete those labels; create your own heading labels for those field and report headings using Label objects. You may also want to add lines along the bottom of each of the group sections, as well as at the bottom of the page header and footer, to make the report easier to read. Finally, create a text box in the Page Footer section of the report. Right -click on the new text box and select Properties. Now, click on the Data tab and set the Control Source property to =Page & [Page] & of & [Pages]. Doing this will display the page number and total number of pages on the bottom of each page of the report. Click on the File menu and select Save As to save the new report under the name rptFileInformation.
Running the Report
Now that the grunt work is done, open the frmFileInformation form created earlier, type the name of one of your AS/400 libraries in the box provided, and click on Run Report. The output displayed should look similar to what is shown in Figure 5. This report gives you a list of files in the selected library as well as field information for each file. Possible improvements to this example are to add System Name, User ID, and Password fields to the prompt window to allow the report to be freely distributed or to print all indexes available for each table on the report.
Once youve started using ADO, youll find uses for it other than report programs. The quick speed of data access allows you to crea te front -ends for your AS/400 data in Access/VB or even ASP. Also, the low overhead required allows you to develop applications almost as quickly as ADO accesses data. Now that you have the tools, I am sure you will find much to do with ADO.
References and Related Materials
A Fast Path to AS/400 Client/Server Using AS/400 OLE DB Support, Redbook (SG24 5183-00)
AS/400 Client/Server Programming with ADO, Microsoft Excel 2000, and OLE DB, Michael Sansoterra, AS/400 Network Expert, May/June 1999
Ask the SDK Wizard, David Mayle, MC, September 1999
IBM Client Access OLE DB Support Web page: www.as400.ibm.com/clientaccess/oledb/
Launching SQL Statements Through Microsoft Access Pass -through Queries, Michael Sansoterra, AS/400 Network Expert, Novem ber/
Making PC Application-to-AS/400 Programming a Snap with IBMs AS/400 SDK for ActiveX and OLE DB, Brant Klepel, AS/400 Network Expert, January/February 1999 (available on the ANE Classics Web page at www.midrangecomputing. com/ane/classics.cfm)
More AS/400 Client/Server Programming with ADO and VBA, Michael Sansoterra, AS/400 Network Expert, July/August 1999
Slam-dunking AS/400 Data into Microsoft Excel with OLE DB, Brant Klepel, MC, May 1999
The ODBC and OLE DB Strategy Guide, Howard F. Arner, Jr., MC, September 1999
Figure 1: These are the two tables that will be used to hold data downloaded through ADO.
Dim conn As New ADODB.Connection Define ADO Connection
Dim cmd As New ADODB.Command Define Command Object
Dim tblSysTables As New ADODB.Recordset Define ADO recordset for SysTables
Dim tblSysColumns As New ADODB.Recordset Define ADO recordset for SysColumns
Dim connStr As String Connection String
Dim tblTables As Recordset Access Table for Systables data
Dim tblFields As Recordset Access table for SysColumns data
First we define our connection Provider will always be IBMDA400. Other options
should be changed to match your system, user name & password
On Error GoTo OpenErr
Replace USERNAME, PASSWORD with valid values on your system.
'Replace AS400SYS with your Client Access system name.
connStr = Provider=IBMDA400;User ID=USERNAME;Password=PASSWORD;Data Source=AS400SYS
conn.ConnectionString = connStr
conn.Open Open the connection
DoCmd.SetWarnings False Disable displaying of warning messages
DoCmd.RunSQL DELETE * FROM tblTables Clear Temporary Tables
DoCmd.RunSQL DELETE * FROM tblFields
cmd.ActiveConnection = conn
Associate our command object with the connection object
This statement selects all records from the SYSTABLES file where the library matches
the value sent in through parameter(0).
'It selects only Data Files with a type of Physical or Logical
cmd.CommandText = SELECT SYS_DNAME, SYS_TNAME, TYPE, LABEL FROM QSYS2.SYSTABLES _ & WHERE SYS_DNAME = ? AND (TYPE = P OR TYPE =L)"_
& " AND FILE_TYPE='D'"
cmd.Parameters(0) = Forms!frmFileInformation.txtLibrary
Pass library name from prompt form
tblSysTables.CacheSize = 1500
tblSysTables.open cmd.Execute Set recordset using SQL statement
Set tblTables = CurrentDb.OpenRecordset(tblTables)
While Not tblSysTables.EOF
.Fields(Library) = tblSysTables.Fields(SYS_DNAME)
.Fields(File) = tblSysTables.Fields(SYS_TNAME)
.Fields(Description) = tblSysTables.Fields(LABEL)
.Fields(FileType) = tblSysTables.Fields(TYPE)
If tblSysTables.RecordCount = 0 Then
MsgBox Invalid Library or No Files in Library, vbOKOnly, Error!
Selects all records from the SYSCOLUMNS file where the library matches
the value sent in through parameter(0)
cmd.CommandText = "SELECT SYS_DNAME, SYS_TNAME, COLNO, SYS_CNAME," _
& "COLTYPE, LENGTH, SCALE, LABELTEXT FROM " _
& "QSYS2.SYSCOLUMNS WHERE SYS_DNAME = ?"
cmd.Parameters(0) = Forms!frmFileInformation.txtLibrary
Pass library name from prompt form
tblSysColumns.CacheSize = 1500
Set recordset using SQL statement
Set tblFields = CurrentDb.OpenRecordset(tblFields)
While Not tblSysColumns.EOF
.Fields(Library) = tblSysColumns.Fields(SYS_DNAME)
.Fields(File) = tblSysColumns.Fields(SYS_TNAME)
.Fields(Sequence) = tblSysColumns.Fields(COLNO)
.Fields(Field) = tblSysColumns.Fields(SYS_CNAME)
.Fields(Heading) = tblSysColumns.Fields(LABELTEXT)
.Fields(FieldType) = tblSysColumns.Fields(COLTYPE)
.Fields(FieldLength) = tblSysColumns.Fields(LENGTH)
.Fields(DecPlaces) = tblSysColumns.Fields(SCALE)
Now we preview our report.
DoCmd.OpenReport rptFileInformation, acViewPreview
MsgBox Err.Description & & conn.Errors(0).Source, vbCritical
DoCmd.SetWarnings True Turn warning messages back on
Figure 2: This code will be used to download data from your AS400 files into Access tables.
Figure 3: Use these SQL statements to create an Access query to join the tblTable table to the tblFields table.
Figure 4: Create your report layout using this figure as a guide.