Solution alternative à DCount et DLookup avec MS SQL Server Backend
L'un des principaux problèmes que nous avons rencontrés avec Access est l'utilisation de DLookup et DCount lors de l'utilisation de tables SQL Server. Nous avons récemment travaillé sur la migration d'une solution pure Access vers SQL Server et avons rencontré des retards sur le chargement de plusieurs formulaires. Cela était dû à l'utilisation de DLookup et DCount dans le code VBA.
Nous avons ensuite trouvé une solution pour résoudre rapidement les multiples instances avec quelques fonctions. Nous avons été guidés par une autre solution fournie par Allen Browne qui a conçu l'Extended DLookup ici dans ce lien.
La solution d'Allen améliore les performances de DLookup en :
- Inclure un ordre de tri pour vous assurer d'obtenir le résultat dont vous avez besoin.
- Nettoyer après lui-même.
- Différencie correctement une chaîne Null et une chaîne de longueur nulle.
- Amélioration globale des performances.
Nous avons maintenant franchi une étape supplémentaire pour travailler spécifiquement avec des tables ou des vues SQL, celles-ci ne fonctionneront pas avec les tables locales Access car nous utilisons spécifiquement une connexion ADO.
J'inclus le code des deux fonctions pour remplacer à la fois DLookup et DCount
Public 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
Si vous avez une instance qui nécessite l'utilisation de DSum, vous pouvez facilement adapter la fonction DCount pour vous donner le résultat requis.
Après avoir appliqué cette solution, nous avons constaté une amélioration spectaculaire des performances de chargement des formulaires et la conception nous aide à appliquer cette solution à plusieurs projets. J'espère que cette solution vous sera utile et si vous rencontrez d'autres problèmes pour lesquels nous pouvons vous aider, veuillez nous contacter sur accessexperts.com.