Reputation: 177
I have a number of buttons on a form which provide additional information to the user, each using DCount to see if there is any information to display and if so, opening a popup form to display it. All had been working well but now for one particular button, it is taking anything between 30 seconds and a minute to open the popup form, which is obviously unacceptable. Can't understand why it worked fine originally but has now gone so slow. All the other buttons still open their form in under a second. VBA is:
Private Sub btnNotes_Click()
'open the popup notes for the current record, if there are associated records
If DCount("ID","qlkpIDForNotes") = 0 Then
MsgBox "There are no notes for this patient", vbOKOnly, "No information"
Else
DoCmd.OpenForm "fsubNotes",,,"ID = " & Me.displayID
End If
End Sub
The table being queried has approx 40,000 rows, where the largest table checked for the other buttons has about 12,000. Have tried doing the DCount directly on the table rather than through a query, but doesn't make any difference. Also tried taking out a section of the data from the original table, copying about 1100 rows into a new table and testing on that. It still took 12 seconds to open. Any ideas, anyone?
Upvotes: 1
Views: 1203
Reputation: 16786
Using DCount()
just to find out if there are any row in the table or query can be rather inefficient since DCount()
will have to run the whole query and go through all records to return the total count just so you can compare that to 0
.
Depending on the complexity of that query, and the joins in it, and whether the joins use fields that have indexes or not, the cost of having to run that query can be exponentially proportional to the number of records in the underlying tables.
To solve your issue try this:
make sure there is an index on the underlying table's ID
field in the qlkpIDForNotes
query, and that all fields used in the JOIN
or WHERE
clauses also have indexes.
check if you can use the main underlying table or use a simplified query just to test if there are records that may be returned by qlkpIDForNotes
, in short, you may not need to run that query in full just to find out if it would have some records.
use a separate function such as HasAny()
below instead of DCount()
when you only need to find out if a query returns any results:
'-------------------------------------------------------------------------'
' Returns whether the given query returned any result at all. '
' Returns true if at least one record was returned. '
' To call: '
' InUse = HasAny("SELECT TOP 1 ID FROM Product WHERE PartID=" & partID) '
'-------------------------------------------------------------------------'
Public Function HasAny(ByVal selectquery As String) As Boolean
Dim db As DAO.database
Dim rs As DAO.RecordSet
Set db = CurrentDb
Set rs = db.OpenRecordset(selectquery, dbOpenForwardOnly)
HasAny = (rs.RecordCount > 0)
rs.Close
Set rs = Nothing
Set db = Nothing
End Function
With this, you can simply rewrite your code as :
Private Sub btnNotes_Click()
'open the popup notes for the current record, if there are associated records '
If Not HasAny("qlkpIDForNotes") Then
MsgBox "There are no notes for this patient", vbOKOnly, "No information"
Else
DoCmd.OpenForm "fsubNotes",,,"ID = " & Me.displayID
End If
End Sub
Upvotes: 2