Alternative Lösung zu DCount und DLookup mit MS SQL Server Backend
Eines der Hauptprobleme, auf die wir bei Access gestoßen sind, ist die Verwendung von DLookup und DCount bei der Verwendung von SQL Server-Tabellen. Wir haben kürzlich an der Migration einer reinen Access-Lösung zu SQL Server gearbeitet und sind beim Laden mehrerer Formulare auf Verzögerungen gestoßen. Dies lag an der Verwendung von DLookup und DCount im VBA-Code.
Wir haben uns dann eine Lösung ausgedacht, um die mehreren Instanzen schnell mit ein paar Funktionen aufzulösen. Wir haben uns von einer anderen Lösung leiten lassen, die von Allen Browne bereitgestellt wurde, der das Extended DLookup hier in diesem Link entworfen hat.
Die Lösung von Allen verbessert die Leistung von DLookup um:
- Einschließlich einer Sortierreihenfolge, um sicherzustellen, dass Sie das gewünschte Ergebnis erhalten.
- Nach sich selbst aufräumen.
- Unterscheidet korrekt einen Null- und einen Null-String.
- Gesamtleistungsverbesserung.
Wir sind jetzt einen Schritt weiter gegangen, um speziell mit SQL-Tabellen oder -Ansichten zu arbeiten, diese funktionieren nicht mit lokalen Access-Tabellen, da wir speziell eine ADO-Verbindung verwenden.
Ich füge den Code für beide Funktionen ein, um sowohl DLookup als auch DCount
zu ersetzenPublic Function ESQLLookup(strField As String, strTable As String, Optional Criteria As Variant, _ Optional OrderClause As Variant) As Variant Dim rs As ADODB.Recordset 'To retrieve the value to find. Dim rsMVF As ADODB.Recordset 'Child recordset to use for multi-value fields. Dim varResult As Variant 'Return value for function. Dim strSQL As String 'SQL statement. Dim strOut As String 'Output string to build up (multi-value field.) Dim lngLen As Long 'Length of string. Const strcSep = "," 'Separator between items in multi-value list. 'Initialize to null. varResult = Null 'Encapsulate Domain in brackets if none exist to allow special characters in the Domain string If Left$(strTable, 1) <> "[" Then strTable = "[" & strTable & "]" End If 'Build the SQL string. strSQL = "SELECT TOP 1 " & strField & " FROM " & strTable If Not IsMissing(Criteria) Then strSQL = strSQL & " WHERE " & Criteria End If If Not IsMissing(OrderClause) Then strSQL = strSQL & " ORDER BY " & OrderClause End If strSQL = strSQL & ";" 'Lookup the value. OpenMyRecordset rs, strSQL, rrOpenForwardOnly, rrLockReadOnly, True If rs.RecordCount > 0 Then 'Will be an object if multi-value field. If VarType(rs(0)) = vbObject Then Set rsMVF = rs(0).Value Do While Not rsMVF.EOF If rs(0).Type = 101 Then 'dbAttachment strOut = strOut & rsMVF!FileName & strcSep Else strOut = strOut & rsMVF![Value].Value & strcSep End If rsMVF.MoveNext Loop 'Remove trailing separator. lngLen = Len(strOut) - Len(strcSep) If lngLen > 0& Then varResult = Left(strOut, lngLen) End If Set rsMVF = Nothing Else 'Not a multi-value field: just return the value. varResult = rs(0) End If End If rs.Close 'Assign the return value. ESQLLookup = varResult ErrEx.Catch 11 ' Division by Zero Debug.Print strSQL MsgBox "To troubleshoot this error, please evaluate the data that is being processed by:" _ & vbCrLf & vbCrLf & strSQL, vbCritical, "Division by Zero Error" ErrEx.CatchAll MsgBox "Error " & err.Number & ": " & err.Description, vbCritical, "Unexpected error" ErrEx.Finally Set rs = Nothing End Function
Public Function ESQLCount(strField As String, strTable As String, Optional Criteria As Variant) As Variant Dim rs As ADODB.Recordset 'To retrieve the value to find. Dim varResult As Variant 'Return value for function. Dim strSQL As String 'SQL statement. Dim lngLen As Long 'Length of string. 'Initialize to null. varResult = Null 'Encapsulate Domain in brackets if none exist to allow special characters in the Domain string If Left$(strTable, 1) <> "[" Then strTable = "[" & strTable & "]" End If 'Build the SQL string. strSQL = "SELECT COUNT(" & strField & ") AS TotalCount FROM " & strTable If Not IsMissing(Criteria) Then strSQL = strSQL & " WHERE " & Criteria End If strSQL = strSQL & ";" 'Lookup the value. OpenMyRecordset rs, strSQL, rrOpenForwardOnly, rrLockReadOnly, True varResult = Nz(rs.Fields("TotalCount"), 0) rs.Close 'Assign the return value. ESQLCount = varResult ErrEx.CatchAll MsgBox "Error " & err.Number & ": " & err.Description, vbCritical, "Unexpected error" Resume Next ErrEx.Finally Set rs = Nothing End Function
Wenn Sie eine Instanz haben, die die Verwendung von DSum erfordert, können Sie die DCount-Funktion einfach anpassen, um das gewünschte Ergebnis zu erhalten.
Nach der Anwendung dieser Lösung stellten wir eine dramatische Verbesserung der Leistung beim Laden von Formularen fest, und das Design hilft uns, diese Lösung auf mehrere Projekte anzuwenden. Ich hoffe, diese Lösung ist hilfreich für Sie, und wenn Sie weitere Probleme haben, bei denen wir Ihnen helfen können, wenden Sie sich bitte unter accessexperts.com an uns.