Alternativ løsning til DCount og DLookup med MS SQL Server Backend
Et af de store problemer, vi er stødt på med Access, er brugen af DLookup og DCount ved brug af SQL Server-tabeller. Vi har for nylig arbejdet på at migrere en ren Access-løsning til SQL-server og stødte på forsinkelser ved indlæsningen af flere formularer. Dette skyldtes brugen af DLookup og DCount i VBA-koden.
Vi kom så med en løsning til hurtigt at løse de flere tilfælde med et par funktioner. Vi blev guidet af en anden løsning fra Allen Browne, som designede den udvidede DLookup her i dette link.
Allens løsning forbedrer ydeevnen af DLookup ved at:
- Inklusive en sorteringsrækkefølge for at sikre, at du får det resultat, du har brug for.
- Ryder op efter sig selv.
- Differentierer en null- og en nul-længde streng korrekt.
- Samlet forbedring af ydeevnen.
Vi har nu taget dette et skridt videre for at arbejde specifikt med SQL-tabeller eller visninger, disse vil ikke fungere med Access lokale tabeller, da vi specifikt bruger en ADO-forbindelse.
Jeg inkluderer koden til begge funktioner for at erstatte både DLookup og 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
Hvis du har en instans, der kræver brug af DSum, kan du nemt tilpasse DCount-funktionen, så du får det ønskede resultat.
Efter at have anvendt denne løsning fandt vi en dramatisk forbedring i ydeevnen af formularindlæsningen, og designet hjælper os med at anvende denne løsning til flere projekter. Jeg håber, at denne løsning er nyttig for dig, og hvis du har andre problemer, som vi kan hjælpe dig med, så kontakt os venligst på accessexperts.com.