[AccessD] Problem of a listbox's response on network... Part 3

Jim Lawrence accessd at shaw.ca
Fri Jan 24 18:04:31 CST 2014


Hi all:

Now that I have listed some of the basics of using of using ADO to make an application be able to connect into the data servers from anywhere in the network and from any where in the province...objects like list and combo boxes have to be filled. 

Note: The code is not a complete operational example. It just covers the high point and leaves out the common detail. 

The list box is real easy. I just have a list box table template and populate in real-time when needs.

' You should first clear the recieving table or generate a new one. 

  ...
  Dim rs2 As DAO.Recordset

  if db1.TableDefs(lsTemporaryTable).Name <> "" Then _
     lbTableExists = True
 
  If lbTableExists = True Then
     strSQL = "DELETE " & lsTemporaryTable & _
              ".* FROM " & lsTemporaryTable
  Else
     strSQL = "SELECT " & lsTableTemplateName & _
              ".* INTO " & lsTemporaryTable & _
              " FROM " & lsTableTemplateName
  End If

  db1.Execute strSQL

  ' Refresh the current MDB's table list.
  If lbTableExists = False Then db1.TableDefs.Refresh

  ' Create a local table defined recordset from a table. Probably the only time a DAO
  ' table might be necessary. Locally DAO is faster than ADO but only marginally.
  Set rs2 = db1.OpenRecordset(lsTemporaryTable, dbOpenDynaset)
  
  ...

  Set rs1 = New ADODB.Recordset

  ' Must be a client side cursor/recordset
  rs1.CursorLocation = adUseClient

  ' Note: recordset created on the client side default to
  ' Static and Read-only. I always add the following
  ' options to the standardize and clarify for future
  ' programmers.
  rs1.Open objCmd, , adOpenForwardOnly, adLockReadOnly

  ' Transfer data from ADO recordset to the empty
  ' recorsdset and temporary table.
  ' fill the table...
	
  With rs1
    If .BOF = False Or .EOF = False Then
      .MoveFirst
      Do While .EOF = False
         rs2.AddNew
         For i = 0 To .Fields.Count - 1
            rs2.Fields(i).Value = .Fields(i).Value
         Next
         rs2.Update
         .MoveNext
      Loop
    Else
      lsTemporaryTable = ""   'No data
    End If
  End With

' Refresh the current MDB's table list.
  If lbTableExists = False Then db1.TableDefs.Refresh 

At the end of that you can have a table with information for a list box source. It can be created upon request or via refresh so it is always kept reasonably current.

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

When it comes to ComboBoxes it can be a little more complicated but it works similarily. In the combobox object "row source type" property, like "FillCompanyServiceCategoryList" create a public function as displayed below. The function must be assembled in the follow format.

Public Function FillCompanyServiceCategoryList(ctlBox As Control, id As Variant, row As Variant, col As Variant, CODE As Variant) As Variant
    
    'Common Combo and List box fill function.
    'Assumes rsCompanyServiceCategory recordset is the supplied data and has
    'equal or more fields than required in the control.
    
    On Error GoTo Err_FillCompanyServiceCategoryList
    
    Dim mvReturnVal As Variant
    
    mvReturnVal = Null
    
    With rsCompanyServiceCategoryList
        Select Case CODE
            Case acLBInitialize                 ' Initialize.
                Set rsCompanyServiceCategoryList = New ADODB.Recordset

Note: the "rsCompanyServiceCategory" function call, gathers the data as described in the previous two chapters. Every time this function is initiated or refreshed it repopulates. If the app is done right it will either refresh from the source data or from recordset stored in memory or from a local table. Make sure the source data is using a static object not a forward-only object or the function will fail at case acLBGetValue. 
   
                Set rsCompanyServiceCategoryList = rsCompanyServiceCategory.Clone
                
                If .BOF = False Or .EOF = False Then
                    .MoveFirst
                    mvReturnVal = .RecordCount
                Else
                    mvReturnVal = 0
                End If
            Case acLBOpen                       ' Open.
                mvRetu rnVal = Timer             ' Generate unique ID for control.
                gvComboTimer = mvReturnVal
            Case acLBGetRowCount                ' Get number of rows.
                mvReturnVal = .RecordCount
            Case acLBGetColumnCount             ' Get number of columns.
                mvReturnVal = ctlBox.ColumnCount
            Case acLBGetColumnWidth             ' Column width.
                mvReturnVal = -1                ' -1 forces use of default width.
            Case acLBGetFormat                  ' Get format
                 mvReturnVal = -1
            Case acLBGetValue                   ' Get data.
                .MoveFirst
                .Move (row)
                mvReturnVal = .Fields(col)
        End Select
    End With
    
    FillCompanyServiceCategoryList = mvReturnVal

Exit_FillCompanyServiceCategoryList:
    Exit Function
    
Err_FillCompanyServiceCategoryList:
    'Handles error situation caused an apparent unrelated error(s)
    'generated in other modules. (It loses its brains...)
    If Err.Number <> 91 Then
        ShowErrMsg "FillCompanyServiceCategoryList"
    End If
    Resume Exit_FillCompanyServiceCategoryList
    
End Function

In summary if the application is set up right it will be very resilient in environments where the data source is not always present or the connections are slow or unstable. I have lost more data and corrupted more DAO databases trying to function in a similar situation and so abandoned that technology except where absolute stability can be guaranteed...and that, from experience, is only on the host computer you are presently using. 

Eventually, this system worked so well, that there could be a hundred people of a possible thousand on the network and there were no lags, that anyone noticed and in five years there was no reported loss of data. (...always an excuse used by "bound" proponents...)

Note: when using such a system you can not use auto-numbering. It is best to have a Stored Procedure on you data server which issues up the appropriate values. Also a date-time field should be kept with each record so any delay getting online can be managed in case the data becomes stale or dated and requires a refresh.

Data sourced from a number of databases can be easily assembled using UNION or UNION ALL queries.        

After the above described Registration and documentation application was created, then a province wide Judge Scheduling system was build and finally a Project management program was assembled. The Project Management was built using five distinct databases. It pulled the contractors and employees, from one source, accounting data from another and assembled all with the documentation like documents, faxes, invoices, emails related to this current project...al linked to a single form. From there it was easy to see if the project was remaining in scope and within budget. To finish it off, the application would generate Excel graphs showing progress and detail suitable for gantt charting and similar management. Unfortunately, the result became too popular and it ended as too many interests were being challenged. The local IT who was heavily invested in Oracle and Oracle forms, other Oracle support companies and even Oracle itself who held province exclusivity.   

Eight years and many millions of dollars later, the MS Access applications have all been replaced but it just goes to show how far ahead of the loop Access use to be...and could still be if Microsoft had not lost it way. Now a days there are a host of great applications that have filled the gaps and even far surpassed MS Access's lead but will there ever again be one system that consolidated so many features?     
  
End of part 3

Jim



More information about the AccessD mailing list