225

leccion 6 - usando rdo

Embed Size (px)

DESCRIPTION

Documento en ingles. Usando RDO con VB 6

Citation preview

Page 1: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 1

Introduction to ODBC and RDO

Open Database Connectivity (ODBC) provides a set of application programming interface (API) functions which make it easier for a developer to connect to a wide range of database formats. ODBC gives the developer a method of designing programs that are not specific to database format whether you are using Oracle, SQL Server, Access, or others. ODBC drivers are DLLs that contain the functions that let you connect to various databases. Each ODBC driver is separate for each database format. ODBC drivers take the code from a program and convert the functions to the specific database format being used. RDO (Remote Data Objects) is a thin layer of code that acts as an ODBC "wrapper", enabling the developer to invoke ODBC functionality using familiar object method and property syntax.

The "Alphabet Soup" of Database Access

Prior to VB6 and the introduction of ADO (ActiveX Data Objects), VB programmers would generally use DAO (Data Access Objects) to interact with local databases such as MS Access and use RDO (Remote Data Objects) to interact with client/server databases such as Oracle and SQL Server. The concept behind ADO was Universal Data Access (UDA), where one database access method could be used for any data source; it was designed to replace both DAO and RDO. DAO remains a viable technology for interacting with MS Access databases as it is faster than ADO for that purpose; however, ADO is more flexible – using ADO, one could develop a prototype database application using MS Access in the back-end, and with a "flick of the wrist" (i.e., with very little coding changes) "upsize" that same application to use Oracle or SQL Server. As far as RDO is concerned, no new versions of it have been developed beyond the version that shipped with VB6, and there are no future plans for it.

In the VB4 and VB5 worlds, RDO was the main method used to interact with client/server databases. RDO works perfectly fine with VB6, so when folks migrated their VB5 applications over to VB6, little or no coding changes were required. However, ADO is the preferred method of database access for new VB6 applications .

About this Tutorial

This tutorial presents three small sample applications using RDO. All three applications use a local MS Access database, as this is suitable for illustrative purposes; in actual practice, RDO would not be a suitable choice for interacting with a local MS Access database. You could approach these sample applications "as if" the local Access database was an Oracle or SQL Server database sitting on a server somewhere – the coding techniques are the same.

The first sample application introduces the RDO Data Control (RDODC) which demonstrates a "quick and dirty" way to connect to a remote database. The second and third applications use RDO code: the second allows navigation and searching of a database table; the third allows navigation and updating on a database table. All three connect to an ODBC Data Source, which must be set up through the Windows Control Panel. How to do this is described below.

Page 2: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 2

Setting Up an ODBC Data Source

Follow the steps below to set up an ODBC Data Source (this process is also called "setting up a DSN", where "DSN" stands for "Data Source Name"). These steps assume Windows 2000 for the operating system. On other versions of Windows, some steps may vary slightly.

• Via Windows Control Panel, double-click on Administrative Tools, then Data Sources (ODBC). The ODBC Data Source Administrator screen is displayed, as shown below. Click on the System DSN tab.

• Click the Add button. The Create New Data Source dialog box will appear. Select Microsoft Access Driver (*.mdb) from the list and click the Finish button.

Page 3: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 3

• The ODBC Microsoft Access Setup dialog box will appear. For Data Source Name, type Biblio. If desired, you can type an entry for Description, but this is not required.

Page 4: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 4

• Click the Select button. The Select Database dialog box appears. On a default installation of VB6 or Visual Studio 6, the BIBLIO.MDB sample database should reside in the folder C:\Program Files\Microsoft Visual Studio\VB98. Navigate to that folder, select BIBLIO.MDB from the file list, and click OK.

Page 5: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 5

Note: If VB was installed in a different location on your system, navigate to the appropriate folder. If you do not have the BIBLIO.MDB sample database file on your system at all, you can download it here. In that case, copy the file to the folder of your choice, and navigate to that folder to select the database for this step.

• When you are returned to the ODBC Microsoft Access Setup screen, the database you selected should be reflected as shown below. Click OK to dismiss this screen.

• When you are returned to the ODBC Data Source Administrator screen, the new DSN should appear as shown below. Click OK to dismiss this screen.

Page 6: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 6

At this point, the Biblio database is ready to be used with RDO in the sample application.

Sample Application 1: Using the RDO Data Control (RDODC)

To build the first sample application, follow the steps below.

• Start a new VB project, and from the Components dialog box (invoked from the Project -> Components menu), select Microsoft RemoteData Control 6.0 (SP3) as shown below and click OK.

Page 7: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 7

The RDO Data Control should appear in your toolbox as shown below:

Page 8: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 8

• Put a remote data control (RDC) on your form, and set the properties as follows:

Property Value

Name rdoBiblio

DataSourceName Biblio

SQL select * from authors

• Now put three text boxes on the form, and set their Name, DataSource, and DataField properties as follows:

Name DataSource DataField

txtAuthor rdoBiblio Author txtAuID rdoBiblio Au_ID

txtYearBorn rdoBiblio Year Born

• Save and run the program. Notice how it works just like the other data control.

Page 9: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 9

• Now change the SQL property of the data control to select * from authors order by author and run the program again. Notice the difference.

• Change the SQL property back to what it was and add three command buttons to the form, and set their Name and Caption properties as follows:

Name Caption

cmdNameOrder Order by Name

cmdYearOrder Order by Year cmdIDOrder Order by ID

• Put the following code in the cmdNameOrder_Click event:

rdoBiblio.SQL = "select * from authors order by aut hor"

rdoBiblio.Refresh

• Put the following code in the cmdYearOrder_Click event:

rdoBiblio.SQL = "select * from authors order by [ye ar born]"

rdoBiblio.Refresh

• Put the following code in the cmdIDOrder_Click event:

rdoBiblio.SQL = "select * from authors order by au_ id"

rdoBiblio.Refresh

• Save and run the program and see what happens when you click the buttons.

A screen-shot of the sample app at run-time is shown below:

Page 10: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 10

Download the project files for this sample application here.

Sample Applications 2 and 3: Using RDO Code

Sample applications 2 and 3 use a database called PROPERTY.MDB and can be downloaded here.

The Property database contains just one table called "Property". The columns of this table are defined as follows:

Column Name Data Type Notes

PROPNO Number (Long Integer) A number that uniquely identifies the property in the table. Should be treated as the Primary Key (although it is not defined as such in the sample database).

EMPNO Number (Long Integer) A number that identifies the real estate agent selling the property. In a real system, this would be the foreign key to the employee number in an Employee table (such a table is not present in the sample database).

ADDRESS Text (20) The street address of the property. CITY Text (15) The city where the property is located.

Page 11: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 11

STATE Text (2) The state where the property is located (2-character US state abbreviation).

ZIP Text (5) The zip code where the property is located. NEIGHBORHOOD Text (15) The descriptive name of the neighborhood in

which the property is located. HOME_AGE Number (Long Integer) Age in years of the home. (A better table

design choice would be to have this field be the date in which the property was built and have the application compute the age based on the current date.)

BEDS Number (Long Integer) Number of bedrooms in the property. BATHS Number (Single) Number of bathrooms in the property (allows

for a decimal value such as 2.5, indicating 2 ½ bathrooms – i.e. 2 full bathrooms and 1 "powder room").

FOOTAGE Number (Long Integer) The footage of the property. ASKING Number (Long Integer) Asking price of the property in whole dollars. BID Number (Long Integer) Bid amount of the potential buyer in whole

dollars. SALEPRICE Number (Long Integer) Sale price (amount the property actually sold

for) in whole dollars.

Before coding or running sample application 2 or 3, you must set up an ODBC data source as was done for the previous sample application.

After downloading the file, move it to the folder of your choice. Then follow the exact same steps as before to set up the DSN, with these two exceptions:

(1) On the ODBC Microsoft Access Setup dialog box, type PropDB for the Data Source Name.

(2) In the Select Database dialog box, navigate to the location where you have placed the PROPERTY.MDB file.

Sample Application 2

To build Sample Application 2, start a new VB project and perform the following steps.

• From the Project -> References menu, check Microsoft Remote Data Object 2.0 and click OK.

Page 12: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 12

• This project uses the StatusBar control, so include the Microsoft Windows Common Controls 6.0 (SP6) from the Components dialog box, accessed from the Project -> Components menu.

Page 13: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 13

• Create the form shown below. The names of the text boxes in the top frame are shown in the form. Set the Enabled property of the frame to False, which will automatically disable all of the textboxes within it, which is desired because this application does not allow updating of the data. The settings for the other controls are given below.

Page 14: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 14

The navigation buttons have the following properties:

Name Caption

cmdMoveFirst <<

cmdMovePrevious <

cmdMoveNext >

cmdMoveLast >>

The text box in the middle of the form has the following properties:

Name txtCurrentQuery

MultiLine True

Locked True

Page 15: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 15

The command buttons have the following properties:

Name Caption

cmdAllData Reload All Records

cmdGetData Run Query Now

In the "Select Criteria" frame:

The check boxes are an array:

Name Caption

chkCriteria(0) EmpNo

chkCriteria(1) City

chkCriteria(2) State

The labels are also an array:

Name Caption Enabled

lblCriteria(0) = False

lblCriteria(1) Like False

lblCriteria(2) Like False

The textboxes are also an array:

Name Caption Enabled

txtCriteria(0) EmpNo False

txtCriteria(1) City False

txtCriteria(2) State False

Place the StatusBar on the form and set its Style property to 1 – sbrSimple.

2. Code the General Declarations section as shown below. Here, two RDO objects, rdoConnection and rdoResultset, are defined at the form level.

The rdoConnection object represents an open connection to a remote data source and a specific database on that data source, or an allocated but as yet unconnected object, which can be used to subsequently establish a connection.

The rdoResultset object represents the rows that result from running a query,

Page 16: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 16

Option Explicit

Dim mobjRDOConn As rdoConnection

Dim mobjRDORst As rdoResultset

Dim mstrSQL As String

3. Code the Form_Load event. Here, the OpenConnection methods is introduced.

OpenConnection is method of an existing rdoEnvironment object. An rdoEnvironment object defines a logical set of connections and transaction scope for a particular user name. rdoEnvironments(0) is a member of the rdoEnvironments collection and is created automatically when you include RDO in your program. The rdoEnvironments collection is one of several collections of the base RDO object, rdoEngine. The rdoEngine object is created automatically when you include RDO in your program.

The syntax for the OpenConnection method is:

Set connection = environment.OpenConnection(dsName[, prompt[, readonly[, connect[, options]]]])

In this sample program, "PropDB" is used for the dsName argument, as this was the Data Source Name given during the ODBC setup. The prompt argument controls whether or not the user is prompted for their UserID and password via the "ODBC Data Sources" dialog box. Provided that enough information is given within the other arguments of the OpenConnection method, the constant rdDriverNoPrompt will suppress the prompt. The third argument, readonly is a Boolean indicating whether or not the connection should be open for read/write access. The sample program omits this argument, thus defaulting to False, meaning the connection is open for read/write access. The connect argument is a string expression used to pass arguments to the ODBC driver manager for opening the database. In the case of the sample application, we are passing a user id of "admin" and a blank password in the connection string, which are the defaults for an unsecured MS Access database.

'-------------------------------------------------- ---------------------------

Private Sub Form_Load()

'-------------------------------------------------- ---------------------------

'set up the form and connect to the data source

On Error GoTo LocalError

Page 17: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 17

'center the form:

Me.Top = (Screen.Height - Me.Height) / 2

Me.Left = (Screen.Width - Me.Width) / 2

' Connect to the Property database:

Set mobjRDOConn = rdoEngine.rdoEnvironments(0).Open Connection _

("PropDB", rdDriverNoPrompt, , "UID=admin;PWD=")

Call cmdAllData_Click

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

4. Code the cmdAllData_Click event, which sets or resets the Resultset object with a query to display all the rows in the table. Here, the OpenResultset method is introduced.

The OpenResultset method causes an rdoResultset object to be created. The syntax is:

Set variable = connection.OpenResultset(name [,type [,locktype [,option]]])

The name argument is a string that specifies the source of the rows for the new rdoResultset. This argument can specify the name of an rdoTable object, the name of an rdoQuery, or an SQL statement that might return rows. In the case of the sample application, it is the SQL statement "select * from property". The type argument specifies which type of cursor to create (using rdOpenKeyset allows the use of the "Move" methods (MoveFirst, MoveNext, etc.), so that option was coded here). The locktype argument specifies the concurrency option that controls how other users are granted or refused access to the data being updated. A value of rdConcurRowVer specifies optimistic concurrency based on row ID.

Page 18: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 18

'-------------------------------------------------- ---------------------------

Private Sub cmdAllData_Click()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

Dim lngX As Long

'select or reload the data to be displayed:

mstrSQL = "select * from property"

Set mobjRDORst = mobjRDOConn.OpenResultset(mstrSQL, rdOpenKeyset, rdConcurRowVer)

txtCurrentQuery.Text = mstrSQL

'The number of records will be displayed in the sta tus bar,

'but the RowCount property is not correct until the last

'record has been accessed (so do a MoveLast followe d by a MoveFirst).

mobjRDORst.MoveLast

mobjRDORst.MoveFirst

'load data into the text boxes

Call DataLoad

' reset the state of the search criteria controls

For lngX = 0 To 2

chkCriteria(lngX).Value = vbUnchecked

Next

Exit Sub

Page 19: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 19

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

5. Create the user-defined subprocedure DataLoad. This subprocedure gets the data from the resultset and puts each field into a text box. Data from the resultset is accessed via the rdoColumns collection.

The rdoColumns collection in RDO is similar to the Fields collection in DAO. A field can be referenced with or without specifying rdoColumns, either by the field name in quotes or by its ordinal position in the resultset. The field can also be referenced with the bang (!) operator. All of the following would be valid ways of referencing the field "propno":

mobjRDORst.rdoColumns("propno")

mobjRDORst ("propno")

mobjRDORst.rdoColumns(0)

mobjRDORst(0)

mobjRDORst!propno

'-------------------------------------------------- ---------------------------

Private Sub DataLoad()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

'copy the data from the resultset to the text boxes :

txtPropNo.Text = mobjRDORst.rdoColumns("propno")

txtEmpNo.Text = mobjRDORst.rdoColumns("empno")

txtAddress.Text = mobjRDORst.rdoColumns("address")

Page 20: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 20

txtCity.Text = mobjRDORst.rdoColumns("city")

txtState.Text = mobjRDORst.rdoColumns("state")

txtZip.Text = mobjRDORst.rdoColumns("zip")

Call SetRecNum

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

6. Create the user-defined subprocedure SetRecNum. This sub displays the number of the current record at the bottom of the screen. The AbsolutePosition, RowCount, and PercentPosition properties of the Resultset are used here.

The AbsolutePosition property specifies the current row in a resultset.

The RowCount property specifies the number of rows in a resultset that have been accessed (the full count is only accurate after a "MoveLast" has been executed).

The PercentPosition property indicates the location of the current resultset row based on a percentage.

'-------------------------------------------------- ---------------------------

Private Sub SetRecNum()

'-------------------------------------------------- ---------------------------

StatusBar1.SimpleText = "row " & mobjRDORst.Absolut ePosition _

& " of " & mobjRDORst.RowCount _

& ", " & Format(mobjRDORst.PercentPosition, "#0.00" ) _

& "% of ResultSet"

End Sub

Page 21: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 21

7. Code the events for the navigation buttons as shown below, using the resultset "Move" methods to move to the first, last, next, or previous record, respectively.

'-------------------------------------------------- ---------------------------

Private Sub cmdMoveFirst_Click()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

mobjRDORst.MoveFirst

Call DataLoad

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

'-------------------------------------------------- ---------------------------

Private Sub cmdMoveLast_Click()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

mobjRDORst.MoveLast

Call DataLoad

Exit Sub

LocalError:

Page 22: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 22

MsgBox Err.Number & " - " & Err.Description

End Sub

'-------------------------------------------------- ---------------------------

Private Sub cmdMoveNext_Click()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

mobjRDORst.MoveNext

If mobjRDORst.EOF Then

Beep

mobjRDORst.MoveLast

End If

Call DataLoad

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

'-------------------------------------------------- ---------------------------

Private Sub cmdMovePrevious_Click()

'-------------------------------------------------- ---------------------------

Page 23: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 23

On Error GoTo LocalError

mobjRDORst.MovePrevious

If mobjRDORst.BOF Then

Beep

mobjRDORst.MoveFirst

End If

Call DataLoad

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

8. When one of the check boxes is clicked, the label and text box next to it should be enabled (or disabled, if clicking the check box unchecks it). Note also that the cmdGetData button (the one with the "Run Query Now" caption) should only be enabled if one of the checkboxes is checked.

'-------------------------------------------------- ---------------------------

Private Sub chkCriteria_Click(Index As Integer)

'-------------------------------------------------- ---------------------------

' disable the 'Run Query Now' button

cmdGetData.Enabled = False

Page 24: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 24

'when the user clicks on a check box, enable the la bel and text

'box that go with it.

If chkCriteria(Index).Value = vbChecked Then

txtCriteria(Index).Enabled = True

lblCriteria(Index).Enabled = True

txtCriteria(Index).SetFocus

txtCriteria(Index).SelStart = 0

txtCriteria(Index).SelLength = Len(txtCriteria(Inde x).Text)

' enable the 'Run Query Now' button only if a box i s checked.

cmdGetData.Enabled = True

Else

txtCriteria(Index).Enabled = False

lblCriteria(Index).Enabled = False

End If

End Sub

9. After the user has selected which fields to use and entered values in the text boxes, they click the cmdGetData button to create a new Resultset with new data. Note that if the user selects (checks) a field, but does not enter search criteria in the corresponding textbox, an error message is generated and the query is not run.

'-------------------------------------------------- ---------------------------

Private Sub cmdGetData_Click()

'-------------------------------------------------- ---------------------------

Page 25: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 25

'run the query that the user has created

On Error GoTo LocalError

Dim blnFirstOne As Boolean

Dim i As Integer

blnFirstOne = True

mstrSQL = "select * from property where "

If chkCriteria(0).Value = vbChecked Then

If (txtCriteria(0).Text = "") Or (Not IsNumeric(txt Criteria(0).Text)) Then

MsgBox "Employee number is missing or non-numeric. Query not run.", _

vbExclamation, _

"RDO Example"

Exit Sub

End If

blnFirstOne = False

mstrSQL = mstrSQL & "empno = " & txtCriteria(0).Tex t

End If

If chkCriteria(1).Value = vbChecked Then

If txtCriteria(1).Text = "" Then

MsgBox "City criteria is missing. Query not run.", _

vbExclamation, _

"RDO Example"

Page 26: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 26

Exit Sub

End If

If blnFirstOne = False Then

mstrSQL = mstrSQL & " and"

End If

blnFirstOne = False

mstrSQL = mstrSQL & " city like '" & txtCriteria(1) .Text & "'"

End If

If chkCriteria(2).Value = vbChecked Then

If txtCriteria(2).Text = "" Then

MsgBox "State criteria is missing. Query not run.", _

vbExclamation, _

"RDO Example"

Exit Sub

End If

If blnFirstOne = False Then

mstrSQL = mstrSQL & " and"

End If

blnFirstOne = False

mstrSQL = mstrSQL & " state like '" & txtCriteria(2 ).Text & "'"

End If

'create a new resultset using the new query

Page 27: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 27

Set mobjRDORst = mobjRDOConn.OpenResultset(mstrSQL, rdOpenKeyset, rdConcurRowVer)

txtCurrentQuery.Text = mstrSQL

'make sure that the query did not return 0 rows:

If mobjRDORst.RowCount = 0 Then

MsgBox "Your query returned 0 rows!"

MsgBox "The query you generated was:" & vbCrLf & ms trSQL

'reload the form with all the records

cmdAllData_Click

Else

'move to last row to set the RowCount property

mobjRDORst.MoveLast

mobjRDORst.MoveFirst

'load data into the text boxes

Call DataLoad

MsgBox "Your query returned " & mobjRDORst.RowCount & " records."

End If

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

10. Save and run. Note: When entering the "Like" criteria for City and/or State, you can use the wildcard character % to represent any number of characters and the wildcard character _ (underscore) the represent a

Page 28: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 28

single character. For example, entering "M%" for the City criteria would return all rows where the city field begins with the letter "M".

Download the project files for this sample application here.

Sample Application 3

Sample Application 3 demonstrates how to add, update, and delete records with RDO.

When the application is first run, the user is prompted to enter a minimum asking price to possibly limit the number of records they want to work with (i.e., "I only want to work with properties that are selling for $200,000 or more). If the user wants to work with all properties, they would simply accept the default of 0 from the prompt. If the user clicks the Cancel button, the application will end.

Once the user has entered the minimum asking price, the main screen of the application is displayed. Initially, the screen is in "browse" mode, where the user can use the navigation buttons to move to the first, previous, next or last record. The data cannot be edited in this mode. If they want to initiate an add or an update, delete a record, or exit the application, they may do so via the appropriate button. Saving or cancelling is not applicable in this mode, so those buttons are disabled.

Page 29: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 29

If the user clicks the Add button, the fields on the screen are enabled and cleared, and the user can enter the information for the new property. All buttons except Save and Cancel are now disabled. After the user has made entries in the fields, he or she would click Save to add the new record to the database table, or, if they changed their mind, would click Cancel to discard the new record. In either case (clicking Save or Cancel) the user is returned to browse mode. When Save is clicked, the application validates the entries and will only save the record if all fields pass edit (otherwise, a message will appear indicating the problem entry and focus will be set to the problem field).

Page 30: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 30

If the user clicks the Update button, the fields on the screen are enabled and the user can modify any or all of the fields (except for the Property Number, which is the primary key of the table). All buttons except Save and Cancel are now disabled. After the user has made modifications in the desired fields, he or she would click Save to update the record to the database table, or, if they changed their mind, would click Cancel to discard the changes. In either case (clicking Save or Cancel) the user is returned to browse mode. When Save is clicked, the application validates the entries and will only save the record if all fields pass edit (otherwise, a message will appear indicating the problem entry and focus will be set to the problem field).

Page 31: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 31

If the user clicks the Delete button, the user is asked to confirm that they want to delete the current record. If they respond Yes, the record is deleted from the database table, and the main screen shows the next record in the table.

To build Sample Application 3, start a new VB project and perform the following steps.

• From the Project -> References menu, check Microsoft Remote Data Object 2.0 and click OK.

Page 32: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 32

• This project uses the StatusBar control, so include the Microsoft Windows Common Controls 6.0 (SP6) from the Components dialog box, accessed from the Project -> Components menu. Check this item and click OK.

Page 33: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 33

• Create the form shown below. The settings for the various controls are given below.

Page 34: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 34

• There are nine textboxes in the main frame of the form. The names and MaxLength settings for these are given below:

Name Properties

txtPropNo MaxLength: 5

txtEmpNo MaxLength: 4

txtAddress MaxLength: 20

txtCity MaxLength: 15

txtState MaxLength: 2

txtZip MaxLength: 5

txtBeds MaxLength: 1

txtBaths MaxLength: 3 (allows fractional amount, like 1.5) txtAsking MaxLength: 0 (not specified)

• Set up the Command Buttons as follows:

Name Caption

cmdMoveFirst <<

cmdMovePrevious <

cmdMoveNext >

cmdMoveLast >>

Page 35: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 35

cmdAdd Add

cmdUpdate Update

cmdDelete Delete

cmdSave Save

cmdCancel Cancel cmdExit Exit

• All controls on your form should have their TabIndex property set such that the tabbing order is correct.

• Add a Module to the project, name it modCommon, and enter the code shown below. The code contains procedures described as follows:

CenterForm Sub to center a form on the screen

ValidKey Function to validate a keystroke for use in the KeyPress event of a textbox

ConvertUpper Function to convert an alphabetic character entered in a textbox to uppercase, used in the KeyPress event of a textbox

SelectTextBoxText Sub to highlight the text of a textbox when it receives focus. Used in the GotFocus event of a textbox.

TabToNextTextBox Sub to "autotab" from one textbox to another when maximum number of characters that can be entered into the first textbox has been reached.

UnFormatNumber Function to strip out non-numeric characters (dollar signs, commas, etc.) from a formatted number.

Option Explicit

Public Const gstrNUMERIC_DIGITS As String = "012345 6789"

Public Const gstrUPPER_ALPHA_PLUS As String = "ABCD EFGHIJKLMNOPQRSTUVWXYZ,'-"

Public gblnPopulating As Boolean

'-------------------------------------------------- ----------------------

Public Sub CenterForm(pobjForm As Form)

'-------------------------------------------------- ----------------------

With pobjForm

.Top = (Screen.Height - .Height) / 2

Page 36: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 36

.Left = (Screen.Width - .Width) / 2

End With

End Sub

'-------------------------------------------------- ----------------------

Public Function ValidKey(pintKeyValue As Integer, _

pstrSearchString As String) As Integer

'-------------------------------------------------- ----------------------

' Common function to filter out keyboard characters passed to this

' function from KeyPress events.

'

' Typical call:

' KeyAscii = ValidKey(KeyAscii, gstrNUMERIC_DIGITS)

'

If pintKeyValue < 32 _

Or InStr(pstrSearchString, Chr$(pintKeyValue)) > 0 Then

'Do nothing - i.e., accept the control character or any key

' in the search string passed to this function ...

Else

'cancel (do not accept) any other key ...

pintKeyValue = 0

Page 37: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 37

End If

ValidKey = pintKeyValue

End Function

'-------------------------------------------------- ----------------------

Public Function ConvertUpper(pintKeyValue As Intege r) As Integer

'-------------------------------------------------- ----------------------

' Common function to force alphabetic keyboard char acters to uppercase

' when called from the KeyPress event.

' Typical call:

' KeyAscii = ConvertUpper(KeyAscii)

'

If Chr$(pintKeyValue) >= "a" And Chr$(pintKeyValue) <= "z" Then

pintKeyValue = pintKeyValue - 32

End If

ConvertUpper = pintKeyValue

End Function

Page 38: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 38

'-------------------------------------------------- ---------------------------

Public Sub SelectTextBoxText(pobjTextbox As TextBox )

'-------------------------------------------------- ---------------------------

With pobjTextbox

.SelStart = 0

.SelLength = Len(.Text)

End With

End Sub

'-------------------------------------------------- ---------------------------

Public Sub TabToNextTextBox(pobjTextBox1 As TextBox , pobjTextBox2 As TextBox)

'-------------------------------------------------- ---------------------------

If gblnPopulating Then Exit Sub

If pobjTextBox2.Enabled = False Then Exit Sub

If Len(pobjTextBox1.Text) = pobjTextBox1.MaxLength Then

pobjTextBox2.SetFocus

End If

End Sub

'-------------------------------------------------- ---------------------------

Public Function UnFormatNumber(pstrNumberIn As Stri ng) As String

Page 39: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 39

'-------------------------------------------------- ---------------------------

Dim lngX As Long

Dim strCurrChar As String

Dim strNumberOut As String

strNumberOut = ""

For lngX = 1 To Len(pstrNumberIn)

strCurrChar = Mid$(pstrNumberIn, lngX, 1)

If InStr("0123456789.", strCurrChar) > 0 Then

strNumberOut = strNumberOut & strCurrChar

End If

Next

UnFormatNumber = strNumberOut

End Function

• Code the General Declarations section as shown below. Here, as in the previous sample application, two RDO objects, rdoConnection and rdoResultset, are defined at the form level, as are some other form-level variables that will be needed.

Option Explicit

Private mobjRDOConn As rdoConnection

Private mobjRDORst As rdoResultset

Private mstrSQL As String

Private mdblMinAsking As Double

Page 40: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 40

Private mblnUpdatePending As Boolean

Private mstrUpdateType As String

Private mavntUSStates As Variant

• Code the Form_Load event as shown below. In it, a programmer-defined Sub named GetMinimumAsking is called (that routine is the one that displays the initial prompt to the user to enter the minimum asking price of the properties they want to work with). Then, the variant array mavntUSStates is loaded with the 50 US state abbreviations, needed for validating the state input by the user. This is followed by a call to the CenterForm sub. Then, the RDO OpenConnection is invoked so that we can use the Property database in the application. This is followed by a call to the programmer-defined Sub GetPropertyData (which runs the query to create the recordset that will be used to browse the Property table records), followed by a call to the programmer-defined Sub SetFormState (which enables and disables controls at the appropriate time).

'-------------------------------------------------- ---------------------------

Private Sub Form_Load()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

' obtain the minimum asking price for the propertie s to be worked with

GetMinimumAsking

' load the array of states to be used for validatio n

mavntUSStates = Array("AK", "AL", "AR", "AZ", "CA", "CO", "CT", "DC", _

"DE", "FL", "GA", "HI", "IA", "ID", "IL", "IN", _

"KS", "KY", "LA", "MA", "MD", "ME", "MI", "MN", _

"MO", "MS", "MT", "NC", "ND", "NE", "NH", "NJ", _

"NM", "NV", "NY", "OH", "OK", "OR", "PA", "RI", _

Page 41: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 41

"SC", "SD", "TN", "TX", "UT", "VA", "VT", "WA", _

"WI", "WV", "WY")

'center the form:

CenterForm Me

' Connect to the Property database:

Set mobjRDOConn = rdoEngine.rdoEnvironments(0).Open Connection _

("PropDB", rdDriverNoPrompt, , "UID=admin;PWD=")

Call GetPropertyData

SetFormState False

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

Code the GetMinimumAsking Sub, which uses the InputBox function to prompt to the user to enter the minimum asking price of the properties they want to work with. The resulting value is then stored in the form-level variable mdblMinAsking.

'-------------------------------------------------- ---------------------------

Private Sub GetMinimumAsking()

Page 42: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 42

'-------------------------------------------------- ---------------------------

Dim strInputBoxPrompt As String

Dim strAsking As String

strInputBoxPrompt = "Enter the minimum asking price (for example, 200000) " _

& "for the properties that you want to work with th is session." _

& vbNewLine _

& "To work with ALL properties, leave the default o f zero."

strAsking = InputBox(strInputBoxPrompt, "Minimum As king Price", "0")

If strAsking = "" Then

' user clicked Cancel button on the input box, so e nd the app

End

End If

mdblMinAsking = Val(strAsking)

End Sub

Code the GetPropertyData Sub, which builds the SQL to get the property records meeting the minimum asking price condition. The OpenResultset method is then invoked to execute the SQL and return the resultset. This is done in a loop in case the resultset does not return any records due to the fact no records in the table met the asking price condition. In that situation, the user is given the opportunity to specify a different asking price value. Assuming we get to a point where we get records back, we do a MoveLast (to ensure a correct record count) followed by a MoveFirst to position to the first record in the resultset. Following this, the programmer-defined Sub PopulateFormFields is called (which displays the fields from the current record in their corresponding textboxes on the form).

'-------------------------------------------------- ---------------------------

Page 43: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 43

Private Sub GetPropertyData()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

Dim blnGotData As Boolean

blnGotData = False

Do

'select or reload the data to be displayed:

mstrSQL = "select propno" _

& " , empno" _

& " , address" _

& " , city" _

& " , state" _

& " , zip" _

& " , beds" _

& " , baths" _

& " , asking" _

& " from property" _

& " where asking >= " & mdblMinAsking _

& " order by propno"

Set mobjRDORst = mobjRDOConn.OpenResultset(mstrSQL, _

rdOpenKeyset, _

rdConcurRowVer)

Page 44: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 44

If mobjRDORst.EOF Then

If MsgBox("There are no properties with an asking p rice >= " _

& Format$(mdblMinAsking, "Currency") _

& ". Do you want to try again with a different valu e?", _

vbYesNo + vbQuestion, _

"Asking Price") _

= vbYes Then

GetMinimumAsking

Else

End

End If

Else

blnGotData = True

End If

Loop Until blnGotData

'The number of records will be displayed in the sta tus bar,

'but the RowCount property is not correct until the last

'record has been accessed (so do a MoveLast followe d by a MoveFirst).

mobjRDORst.MoveLast

mobjRDORst.MoveFirst

'load data into the text boxes

Call PopulateFormFields

Page 45: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 45

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

Code the PopulateFormFields Sub, which assigns the fields from the current record to their corresponding textboxes on the form. Note that the gblnPopulating Boolean variable is set to True prior to the assignments and set to False after the assignments. This value is used to control whether or not certain code executes in the event procedures for some of these textboxes. The Sub SetRecNum is then called.

'-------------------------------------------------- ---------------------------

Private Sub PopulateFormFields()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

gblnPopulating = True

'copy the data from the resultset to the text boxes :

txtPropNo.Text = mobjRDORst.rdoColumns("propno")

txtEmpNo.Text = mobjRDORst.rdoColumns("empno")

txtAddress.Text = mobjRDORst.rdoColumns("address")

txtCity.Text = mobjRDORst.rdoColumns("city")

txtState.Text = mobjRDORst.rdoColumns("state")

txtZip.Text = mobjRDORst.rdoColumns("zip")

txtBeds.Text = mobjRDORst.rdoColumns("beds")

txtBaths.Text = mobjRDORst.rdoColumns("baths")

Page 46: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 46

txtAsking.Text = Format$(mobjRDORst.rdoColumns("ask ing"), "Currency")

gblnPopulating = False

Call SetRecNum

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

Code the SetRecNum Sub. This sub is identical to the one used in Sample Application 2. It displays the number of the current record at the bottom of the screen using the AbsolutePosition, RowCount, and PercentPosition properties of the Resultset object.

'-------------------------------------------------- ---------------------------

Private Sub SetRecNum()

'-------------------------------------------------- ---------------------------

StatusBar1.SimpleText = "row " & mobjRDORst.Absolut ePosition _

& " of " & mobjRDORst.RowCount _

& ", " & Format(mobjRDORst.PercentPosition, "#0.00" ) _

& "% of ResultSet"

End Sub

Code the SetFormState Sub, which takes in a Boolean argument used to set the Enabled property of the controls on the form. Based on whether the value True or False is passed to this sub, this sub ensures that the textboxes are enabled for adds and updates and disabled for browsing; it also ensures that the various command buttons are enabled or disabled at the appropriate time. This Sub also sets the form-level Boolean variable mblnUpdatePending.

Page 47: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 47

'-------------------------------------------------- ---------------------------

Private Sub SetFormState(pblnEnabled As Boolean)

'-------------------------------------------------- ---------------------------

txtPropNo.Enabled = pblnEnabled

txtEmpNo.Enabled = pblnEnabled

txtAddress.Enabled = pblnEnabled

txtCity.Enabled = pblnEnabled

txtState.Enabled = pblnEnabled

txtZip.Enabled = pblnEnabled

txtBeds.Enabled = pblnEnabled

txtBaths.Enabled = pblnEnabled

txtAsking.Enabled = pblnEnabled

cmdSave.Enabled = pblnEnabled

cmdCancel.Enabled = pblnEnabled

cmdAdd.Enabled = Not pblnEnabled

cmdUpdate.Enabled = Not pblnEnabled

cmdDelete.Enabled = Not pblnEnabled

cmdExit.Enabled = Not pblnEnabled

cmdMoveFirst.Enabled = Not pblnEnabled

cmdMoveNext.Enabled = Not pblnEnabled

Page 48: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 48

cmdMovePrevious.Enabled = Not pblnEnabled

cmdMoveLast.Enabled = Not pblnEnabled

mblnUpdatePending = pblnEnabled

End Sub

Code the Form_Unload event. In it, the form-level Boolean variable mblnUpdatePending is tested to see if (well, an update is pending – i.e., whether an add or update is in progress). If the user is in the middle of an add or update and then clicks the "X" button on the upper-right corner of the form, they will receive the message that they must save or cancel prior to exiting the application, and the form will NOT be unloaded (because we are assigning a non-zero value to the Cancel argument in that situation). Provided that an add or update is not in progress, we set the database objects to Nothing and the Unload will complete.

'-------------------------------------------------- ---------------------------

Private Sub Form_Unload(Cancel As Integer)

'-------------------------------------------------- ---------------------------

If mblnUpdatePending Then

MsgBox "You must save or cancel the current operati on prior to exiting.", _

vbExclamation, _

"Exit"

Cancel = 1

Else

Set mobjRDORst = Nothing

Set mobjRDOConn = Nothing

End If

Page 49: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 49

End Sub

Code the events for the various Textboxes as shown below. The code in these events ensure the following:

• For all, highlight the text in the textbox when it receives focus.

• For all but the last textbox, if the maximum number of characters typed into the textbox is reached, auto-tab to the next textbox.

• Only numeric digits should be entered into the property number, employee number, zip codes, and beds textboxes.

• Only numeric digits and optionally one decimal point should be entered into the baths and asking textboxes.

• Force uppercase on the state textbox.

• When the asking textbox receives focus, the value in there should be unformatted. When the asking textbox loses focus, its value should be formatted as currency.

'-------------------------------------------------- ---------------------------

' Textbox events

'-------------------------------------------------- ---------------------------

' property #

Private Sub txtPropNo_GotFocus()

SelectTextBoxText txtPropNo

End Sub

Private Sub txtPropNo_KeyPress(KeyAscii As Integer)

KeyAscii = ValidKey(KeyAscii, gstrNUMERIC_DIGITS)

End Sub

Private Sub txtPropNo_Change()

Page 50: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 50

TabToNextTextBox txtPropNo, txtEmpNo

End Sub

' emp #

Private Sub txtEmpNo_GotFocus()

SelectTextBoxText txtEmpNo

End Sub

Private Sub txtEmpNo_KeyPress(KeyAscii As Integer)

KeyAscii = ValidKey(KeyAscii, gstrNUMERIC_DIGITS)

End Sub

Private Sub txtEmpNo_Change()

TabToNextTextBox txtEmpNo, txtAddress

End Sub

' address

Private Sub txtAddress_GotFocus()

SelectTextBoxText txtAddress

End Sub

Private Sub txtAddress_Change()

TabToNextTextBox txtAddress, txtCity

End Sub

Page 51: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 51

' city

Private Sub txtCity_GotFocus()

SelectTextBoxText txtCity

End Sub

Private Sub txtCity_Change()

TabToNextTextBox txtCity, txtState

End Sub

' state

Private Sub txtState_GotFocus()

SelectTextBoxText txtState

End Sub

Private Sub txtState_KeyPress(KeyAscii As Integer)

KeyAscii = ConvertUpper(KeyAscii)

End Sub

Private Sub txtState_Change()

TabToNextTextBox txtState, txtZip

End Sub

' zip

Private Sub txtZip_GotFocus()

SelectTextBoxText txtZip

Page 52: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 52

End Sub

Private Sub txtZip_KeyPress(KeyAscii As Integer)

KeyAscii = ValidKey(KeyAscii, gstrNUMERIC_DIGITS)

End Sub

Private Sub txtZip_Change()

TabToNextTextBox txtZip, txtBeds

End Sub

' beds

Private Sub txtBeds_GotFocus()

SelectTextBoxText txtBeds

End Sub

Private Sub txtBeds_KeyPress(KeyAscii As Integer)

KeyAscii = ValidKey(KeyAscii, gstrNUMERIC_DIGITS)

End Sub

Private Sub txtBeds_Change()

TabToNextTextBox txtBeds, txtBaths

End Sub

' baths

Private Sub txtBaths_GotFocus()

SelectTextBoxText txtBaths

Page 53: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 53

End Sub

Private Sub txtBaths_KeyPress(KeyAscii As Integer)

KeyAscii = ValidKey(KeyAscii, gstrNUMERIC_DIGITS & ".")

' if text already has a decimal point, do not allow another ...

If Chr$(KeyAscii) = "." And InStr(txtBaths.Text, ". ") > 0 Then

KeyAscii = 0

End If

End Sub

Private Sub txtBaths_Change()

TabToNextTextBox txtBaths, txtAsking

End Sub

' asking price

Private Sub txtAsking_GotFocus()

txtAsking.Text = UnFormatNumber(txtAsking.Text)

SelectTextBoxText txtAsking

End Sub

Private Sub txtAsking_KeyPress(KeyAscii As Integer)

KeyAscii = ValidKey(KeyAscii, gstrNUMERIC_DIGITS & ".")

' if text already has a decimal point, do not allow another ...

If Chr$(KeyAscii) = "." And InStr(txtAsking.Text, " .") > 0 Then

KeyAscii = 0

Page 54: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 54

End If

End Sub

Private Sub txtAsking_LostFocus()

txtAsking.Text = Format$(txtAsking.Text, "Currency" )

End Sub

Code the events for the navigation buttons as shown below, using the resultset "Move" methods to move to the first, last, next, or previous record, respectively.

'-------------------------------------------------- ---------------------------

Private Sub cmdMoveFirst_Click()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

mobjRDORst.MoveFirst

Call PopulateFormFields

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

'-------------------------------------------------- ---------------------------

Private Sub cmdMoveLast_Click()

'-------------------------------------------------- ---------------------------

Page 55: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 55

On Error GoTo LocalError

mobjRDORst.MoveLast

Call PopulateFormFields

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

'-------------------------------------------------- ---------------------------

Private Sub cmdMoveNext_Click()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

mobjRDORst.MoveNext

If mobjRDORst.EOF Then

Beep

mobjRDORst.MoveLast

End If

Call PopulateFormFields

Exit Sub

LocalError:

Page 56: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 56

MsgBox Err.Number & " - " & Err.Description

End Sub

'-------------------------------------------------- ---------------------------

Private Sub cmdMovePrevious_Click()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

mobjRDORst.MovePrevious

If mobjRDORst.BOF Then

Beep

mobjRDORst.MoveFirst

End If

Call PopulateFormFields

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

Code the Click event for the cmdAdd button. In it, the textboxes are cleared, the SetFormState sub is called (passing it a parameter of True, which will enable the textboxes and the Save and Cancel buttons and disable all the other buttons), set the form-level variable mstrUpdateType to "A" (indicating that an add is pending) and sets focus to the Property Number field.

'-------------------------------------------------- ---------------------------

Page 57: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 57

Private Sub cmdAdd_Click()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

'clear all the text boxes:

txtPropNo.Text = ""

txtEmpNo.Text = ""

txtAddress.Text = ""

txtCity.Text = ""

txtState.Text = ""

txtZip.Text = ""

txtBeds.Text = ""

txtBaths.Text = ""

txtAsking.Text = ""

SetFormState True

mstrUpdateType = "A"

txtPropNo.SetFocus

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

Page 58: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 58

Code the Click event for the cmdUpdate button. In it, the SetFormState sub is called (passing it a parameter of True, which will enable the textboxes and the Save and Cancel buttons and disable all the other buttons), set the form-level variable mstrUpdateType to "U" (indicating that an update is pending), disables the Property Number field (because it is the primary key and should not be changed) and sets focus to the Employee Number field.

'-------------------------------------------------- ---------------------------

Private Sub cmdUpdate_Click()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

SetFormState True

mstrUpdateType = "U"

' being that propno is the primary key, it should n ot be updatable

txtPropNo.Enabled = False

txtEmpNo.SetFocus

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

End Sub

Code the Click event for the cmdSave button. The user would click this button after they have completed entries for an add or update. This sub first invokes the ValidateAllFields function, which returns a Boolean indicating whether or not all entries passed their edit checks. If not, we exit the sub and the record is not saved; the user remains in "update pending" mode and has the opportunity to correct the entries. Provided that validation is successful, the sub proceeds. The mstrUpdateType variable is checked to see whether we are dealing with an add or an update.

Page 59: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 59

If we are dealing with an add, we invoke the AddNew method of the rdoResultset object (named mobjRDORst in this application). The AddNew method prepares a new row you can edit and subsequently add to the rdoResultset object using the Update method. After you modify the new row, you must use the Update method to save the changes and add the row to the result set. No changes are made to the database until you use the Update method. (The Update method is invoked after the content of the textboxes has been assigned to the database fields.)

If we are dealing with an update, we invoke the Edit method of the rdoResultset object (named mobjRDORst in this application). The Edit method enables changes to data values in the current row of an updatable rdoResultset object. Prior to invoking the Edit method, the data columns of an rdoResultset are read-only. Behind the scenes, executing the Edit method copies the current row from an updatable rdoResultset object to the copy buffer for subsequent editing. Changes made to the current row’s columns are copied to the copy buffer. After you make the desired changes to the row, use the Update method to save your changes or the CancelUpdate method to discard them. (If you move on to another record after invoking Edit but without invoking Update, your changes will be lost.)

Once the appropriate method has been invoked (either the AddNew or Edit), the content of the textboxes is assigned to the database fields, then the Update method is invoked. The Update method saves the contents of the copy buffer row to a specified updatable rdoResultset object and discards the copy buffer. (The Update method is the method that actually saves the data, and it must have been preceded by an AddNew or Edit.)

The mstrUpdateType variable is checked once again, and if we are dealing with an add, there is some extra work to do. Although the new record has been added, the original resultset still does not contain the new record. The Requery method must be invoked, which updates the data in an rdoResultset object by re-executing the query on which the object is based. Logic is then necessary to position to the new record. The SetRecNum sub must then be called to display the status bar information about the new record. Note: RDO does not have a Seek or FindFirst method, thus it is not possible to simply position a recordset to a particular row based on the value of a column. The workaround used by this sample application is to read rows sequentially (via the MoveNext method) until the desired row is found. This workaround is only practical for relatively small resultsets like the Property table – this would not be practical for a resultset containing thousands of rows.

In either case (add or update), the SetFormState sub is called with a parameter of False, which causes the textboxes and the Save and Cancel buttons to be disabled and all other buttons to be enabled.

Note that in the statement that assigns the contents of the txtAsking textbox to the asking field of the table, our UnFormatNumber function is used to strip off the non-numeric characters. This is because we are using a display format that includes a dollar sign and commas on the txtAsking control, and an error would occur if we attempted to assign this directly to the asking field, which is defined as numeric.

'-------------------------------------------------- ---------------------------

Private Sub cmdSave_Click()

'-------------------------------------------------- ---------------------------

Page 60: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 60

On Error GoTo LocalError

If Not ValidateAllFields Then Exit Sub

If mstrUpdateType = "A" Then

mobjRDORst.AddNew

Else

mobjRDORst.Edit

End If

'save the data to the database:

mobjRDORst.rdoColumns("propno") = txtPropNo.Text

mobjRDORst.rdoColumns("empno") = txtEmpNo.Text

mobjRDORst.rdoColumns("address") = txtAddress.Text

mobjRDORst.rdoColumns("city") = txtCity.Text

mobjRDORst.rdoColumns("state") = txtState.Text

mobjRDORst.rdoColumns("zip") = txtZip.Text

mobjRDORst.rdoColumns("beds") = txtBeds.Text

mobjRDORst.rdoColumns("baths") = txtBaths.Text

mobjRDORst.rdoColumns("asking") = UnFormatNumber(tx tAsking.Text)

mobjRDORst.Update

If mstrUpdateType = "A" Then

Page 61: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 61

'after the new record is added, the db must be re-q ueried

'so that the resultset contains the new record:

mobjRDORst.Requery

'since the number of records has changed, move to t he

'last record to reset the RowCount property:

mobjRDORst.MoveLast

mobjRDORst.MoveFirst

' reposition to the record just added

Do Until mobjRDORst.EOF

If mobjRDORst("propno") = Val(txtPropNo.Text) Then

Exit Do

End If

mobjRDORst.MoveNext

Loop

'display status info about the new record

SetRecNum

End If

Reset:

SetFormState False

Exit Sub

LocalError:

MsgBox Err.Number & " - " & Err.Description

Page 62: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 62

'if an error occured, the user should be instructed

'how to fix it or the invalid data should be remove d

'from the text boxes and another record displayed

Resume Reset

End Sub

Code the Click event for the cmdDelete button. The user is first asked to confirm that they want to delete the record, and if so, the Delete method of the resultset object (mobjRDORst) is invoked, which deletes the current row in an updatable resultset object. The Requery method is then invoked so that the record is removed from the resultset that the user is working with. Logic is then needed to position to a different record (either the next record after the deleted one, or, if it was the last record that was deleted, the record that preceded the deleted record). PopulateFormFields must then be called to display the contents of the new current record.

'-------------------------------------------------- ---------------------------

Private Sub cmdDelete_Click()

'-------------------------------------------------- ---------------------------

On Error GoTo LocalError

'when the current record is deleted, the current lo cation in the recordset

'is invalid. use the Requery method to re-execute t he query and update

'the data.

If MsgBox("Are you sure you want to delete this rec ord?", _

vbYesNo + vbQuestion, _

"Delete") = vbNo Then

Exit Sub

End If

Page 63: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 63

mobjRDORst.Delete

mobjRDORst.Requery

'since the number of records has changed, move to t he last record to

'reset the RowCount property:

mobjRDORst.MoveLast

mobjRDORst.MoveFirst

' reposition to one past the record just deleted

Do Until mobjRDORst.EOF

If mobjRDORst("propno") > Val(txtPropNo.Text) Then

Exit Do

End If

mobjRDORst.MoveNext

Loop

' If it was the last record that was deleted, this will position us

' to the "new" last record ...

If mobjRDORst.EOF Then mobjRDORst.MoveLast

'load data into the text boxes:

Call PopulateFormFields

Exit Sub

LocalError:

Page 64: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 64

MsgBox Err.Number & " - " & Err.Description

End Sub

The ValidateAllFields function, which returns a Boolean value indicating whether or not all fields have passed validation checks. This function calls upon two "helper" functions: PropertyExists and ValidState. When the user is doing an add, the PropertyExist function is called to see whether or not the proposed Property Number is already being used in the Property table. If so, the user is informed that they can't use that number (because it is the primary key and must be unique) and so they must use a different number. The ValidState routine is called to ensure that the user has entered a valid US state. The code for all three functions is shown below.

'-------------------------------------------------- ---------------------------

Private Function ValidateAllFields() As Boolean

'-------------------------------------------------- ---------------------------

ValidateAllFields = False 'guilty until proven inno cent

If mstrUpdateType = "A" Then

If txtPropNo.Text = "" Then

MsgBox "Property # must not be blank.", vbExclamati on, "Property #"

txtPropNo.SetFocus

Exit Function

ElseIf PropertyExists Then

MsgBox "Property # already exists. Please use a dif ferent #.", _

vbExclamation, _

"Property #"

txtPropNo.SetFocus

Exit Function

Page 65: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 65

End If

End If

If txtEmpNo.Text = "" Then

MsgBox "Emp # must not be blank.", vbExclamation, " Emp #"

txtEmpNo.SetFocus

Exit Function

End If

If txtAddress.Text = "" Then

MsgBox "Address must not be blank.", vbExclamation, "Address"

txtAddress.SetFocus

Exit Function

End If

If txtCity.Text = "" Then

MsgBox "City must not be blank.", vbExclamation, "C ity"

txtCity.SetFocus

Exit Function

End If

If Not ValidState Then

MsgBox "Missing or invalid state.", vbExclamation, "State"

txtState.SetFocus

Exit Function

End If

Page 66: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 66

If txtZip.Text = "" Or Len(txtZip.Text) = 5 Then

' it's OK

Else

MsgBox "Zip code must either be blank or exactly 5 digits.", vbExclamation, "Zip Code"

txtZip.SetFocus

Exit Function

End If

If Val(txtBeds.Text) = 0 Then

MsgBox "Beds must not be zero.", vbExclamation, "Be ds"

txtBeds.SetFocus

Exit Function

End If

If Val(txtBaths.Text) = 0 Then

MsgBox "Baths must not be zero.", vbExclamation, "B aths"

txtBaths.SetFocus

Exit Function

End If

If Val(UnFormatNumber(txtAsking.Text)) = 0 Then

MsgBox "Asking must not be zero.", vbExclamation, " Asking"

txtAsking.SetFocus

Exit Function

End If

Page 67: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 67

' if we make it here, all fields have passed edit

ValidateAllFields = True

End Function

'-------------------------------------------------- ---------------------------

Private Function PropertyExists() As Boolean

'-------------------------------------------------- ---------------------------

Dim objTempRst As rdoResultset

Dim strSQL As String

strSQL = "select count(*) as the_count from propert y where propno = " & txtPropNo.Text

Set objTempRst = mobjRDOConn.OpenResultset(strSQL, _

rdOpenKeyset, _

rdConcurRowVer)

If objTempRst("the_count") > 0 Then

PropertyExists = True

Else

PropertyExists = False

End If

End Function

Page 68: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 68

'-------------------------------------------------- ------------------------------

Private Function ValidState() As Boolean

'-------------------------------------------------- ------------------------------

Dim lngX As Long

Dim blnStateFound As Boolean

blnStateFound = False

For lngX = 0 To UBound(mavntUSStates)

If txtState.Text = mavntUSStates(lngX) Then

blnStateFound = True

Exit For

End If

Next

ValidState = blnStateFound

End Function

Code the Click event for the cmdCancel button. The user would click this button if, during an add or update, they decide to abandon the operation. Here, PopulateFormFields is called to reset the textboxes to their content prior to the user clicking the Add or Update button, and SetFormState is called with a parameter of False, which causes the textboxes and the Save and Cancel buttons to be disabled and all other buttons to be enabled.

'-------------------------------------------------- ---------------------------

Private Sub cmdCancel_Click()

'-------------------------------------------------- ---------------------------

PopulateFormFields

SetFormState False

Page 69: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 69

End Sub

Code the Click event for the cmdExit button, which issues the Unload Me statement to fire the Form_Unload event, which will unload the form and end the application.

'-------------------------------------------------- ---------------------------

Private Sub cmdExit_Click()

'-------------------------------------------------- ---------------------------

Unload Me

End Sub

Download the project files for this sample application here.

The Execute Method

The Execute method of the RDO Connection object can be used to run an action query or execute an SQL statement that does not return rows. Such queries include UPDATE, INSERT, and DELETE statements.

In the cmdSave_Click procedure, the following code segment:

If mstrUpdateType = "A" Then

mobjRDORst.AddNew

Else

mobjRDORst.Edit

End If

'save the data to the database:

mobjRDORst.rdoColumns("propno") = txtPropNo.Text

Page 70: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 70

mobjRDORst.rdoColumns("empno") = txtEmpNo.Text

mobjRDORst.rdoColumns("address") = txtAddress.Text

mobjRDORst.rdoColumns("city") = txtCity.Text

mobjRDORst.rdoColumns("state") = txtState.Text

mobjRDORst.rdoColumns("zip") = txtZip.Text

mobjRDORst.rdoColumns("beds") = txtBeds.Text

mobjRDORst.rdoColumns("baths") = txtBaths.Text

mobjRDORst.rdoColumns("asking") = UnFormatNumber(tx tAsking.Text)

mobjRDORst.Update

could be replaced by:

If mstrUpdateType = "A" Then

mobjRDOConn.Execute "INSERT INTO property( propno " _

& " , empno" _

& " , address" _

& " , city" _

& " , state" _

& " , zip" _

& " , beds" _

& " , baths" _

& " , asking" _

& ") VALUES (" _

& " " & txtPropNo.Text _

& ", " & txtEmpNo.Text _

& ", '" & Replace$(txtAddress.Text, "'", "''") & "' " _

Page 71: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 71

& ", '" & Replace$(txtCity.Text, "'", "''") & "'" _

& ", '" & txtState.Text & "'" _

& ", '" & txtZip.Text & "'" _

& ", " & txtBeds.Text _

& ", " & txtBaths.Text _

& ", " & UnFormatNumber(txtAsking.Text) _

& ")"

Else

mobjRDOConn.Execute "UPDATE property " _

& " SET empno = " & txtEmpNo.Text _

& " , address = '" & Replace$(txtAddress.Text, "'", "''") & "'" _

& " , city = '" & Replace$(txtCity.Text, "'", "''") & "'" _

& " , state = '" & txtState.Text & "'" _

& " , zip = '" & txtZip.Text & "'" _

& " , beds = '" & txtBeds.Text & "'" _

& " , baths = '" & txtBaths.Text & "'" _

& " , asking = '" & UnFormatNumber(txtAsking.Text) & "'" _

& " WHERE propno = " & txtPropNo.Text

End If

Note 1: Note that the portion of the code above that executes the SQL UPDATE statement includes a WHERE clause which insures that only the row for the current property number is updated. Recall from the SQL tutorial that an UPDATE statement should always have a WHERE clause to explicitly limit the row(s) to be updated. Without a WHERE clause, ALL rows of the table would be updated.

Note 2: As pointed out in the DAO tutorials, for text fields, if there is the possibility that the value to be updated or inserted will contain an apostrophe, an extra measure should be taken to "double" the apostrophes when building the SQL string – otherwise, the apostrophe embedded in the string will be interpreted as the premature ending of the SQL string and a syntax error will most likely

Page 72: leccion 6 - usando rdo

[VISUAL BASIC CON BASE DE DATOS] IDSYSTEMS 2012

Leccion 6 – Usando RDO Página 72

result. The easiest way to provide this "insurance" against embedded apostrophes is to use the Replace$ function on the string in question to replace any occurrences of a single apostrophe with two apostrophes.

In the cmdDelete_Click procedure, the following statement:

mobjRDORst.Delete

could be replaced by:

mobjRDOConn.Execute "DELETE FROM property WHERE pro pno = " & txtPropNo.Text

Recall from the SQL tutorial that, like an UPDATE staement, a DELETE statement should always have a WHERE clause to explicitly limit the row(s) to be deleted. Without a WHERE clause, ALL rows of the table would be deleted.