Giải pháp thay thế cho DCount và DLookup với MS SQL Server Backend
Một trong những vấn đề chính mà chúng tôi gặp phải với Access là việc sử dụng DLookup và DCount khi sử dụng bảng SQL Server. Gần đây, chúng tôi đã làm việc để di chuyển giải pháp Access thuần túy sang máy chủ SQL và gặp phải sự chậm trễ khi tải một số biểu mẫu. Điều này là do việc sử dụng DLookup và DCount trong mã VBA.
Sau đó, chúng tôi đã đưa ra một giải pháp để giải quyết nhanh chóng nhiều trường hợp bằng một vài chức năng. Chúng tôi đã được hướng dẫn bởi một giải pháp khác được cung cấp bởi Allen Browne, người đã thiết kế DLookup Mở rộng tại đây trong liên kết này.
Giải pháp của Allen cải thiện hiệu suất của DLookup bằng cách:
- Bao gồm một thứ tự sắp xếp để đảm bảo bạn nhận được kết quả mình cần.
- Tự dọn dẹp.
- Phân biệt chính xác chuỗi Null và chuỗi có độ dài bằng không.
- Cải thiện tổng thể về hiệu suất.
Bây giờ chúng tôi đã thực hiện thêm một bước này để làm việc cụ thể với các bảng hoặc dạng xem SQL, chúng sẽ không hoạt động với các bảng cục bộ Access vì chúng tôi đang sử dụng kết nối ADO một cách cụ thể.
Tôi đang bao gồm mã cho cả hai hàm để thay thế cả DLookup và 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
Nếu bạn có một phiên bản yêu cầu sử dụng DSum thì bạn có thể dễ dàng điều chỉnh hàm DCount để cung cấp cho bạn kết quả cần thiết.
Sau khi áp dụng giải pháp này, chúng tôi nhận thấy sự cải thiện đáng kể trong hiệu suất tải biểu mẫu và thiết kế giúp chúng tôi áp dụng giải pháp này cho nhiều dự án. Tôi hy vọng giải pháp này hữu ích cho bạn và nếu bạn có bất kỳ vấn đề nào khác mà chúng tôi có thể giúp bạn, vui lòng liên hệ với chúng tôi tại accessexperts.com.