Alternativ lösning för DCount och DLookup med MS SQL Server Backend
Ett av de stora problemen vi har stött på med Access är användningen av DLookup och DCount vid användning av SQL Server-tabeller. Vi har nyligen arbetat med att migrera en ren Access-lösning till SQL-server och stötte på förseningar vid laddningen av flera formulär. Detta berodde på användningen av DLookup och DCount i VBA-koden.
Vi kom sedan på en lösning för att snabbt lösa de flera instanserna med ett par funktioner. Vi vägleddes av en annan lösning från Allen Browne som designade Extended DLookup här i den här länken.
Allens lösning förbättrar prestandan för DLookup genom att:
- Inklusive en sorteringsordning för att säkerställa att du får det resultat du behöver.
- Städar efter sig.
- Därskiljer en noll- och en nolllängdssträng korrekt.
- Övergripande förbättring av prestanda.
Vi har nu tagit detta ett steg längre för att arbeta specifikt med SQL-tabeller eller vyer, dessa kommer inte att fungera med lokala Access-tabeller eftersom vi specifikt använder en ADO-anslutning.
Jag inkluderar koden för båda funktionerna för att ersätta både DLookup och 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
Om du har en instans som kräver användning av DSum kan du enkelt anpassa DCount-funktionen för att ge dig önskat resultat.
Efter att ha tillämpat denna lösning fann vi en dramatisk förbättring av prestandan för formulärladdningen och designen hjälper oss att tillämpa denna lösning på flera projekt. Jag hoppas att den här lösningen är till hjälp för dig och om du har några andra problem som vi kan hjälpa dig med, vänligen kontakta oss på accessexperts.com.