Nhờ kiểm tra lỗi ở dòng code đếm số bản ghi (2 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

MinhKhai

Giải pháp Ếc-xào
Tham gia
16/4/08
Bài viết
941
Được thích
572
Em có dùng đoạn code như hình dưới để lấy dữ liệu từ SQL Server. Nói chung code chạy bình thường ngoại trừ khi thêm dòng i = Rst.RecordCount như được tô trong hình. Mục đích là em chỉ muốn lấy số lượng bản ghi khi query được.
Em có 1 file khác (sưu tập trên mạng) có code gần giống thì lại không gặp vấn đề ở dòng này.
Nhờ các bác xem giúp code bị lỗi cái gì

(Do file kết nối SQL nếu up lên cũng không test được nên em gửi chụp hình)

Xin cảm ơn !


1597162180067.png
 
Thử thay Dim i As Integer thành Dim i as Long.
 
Em có dùng đoạn code như hình dưới để lấy dữ liệu từ SQL Server. Nói chung code chạy bình thường ngoại trừ khi thêm dòng i = Rst.RecordCount như được tô trong hình. Mục đích là em chỉ muốn lấy số lượng bản ghi khi query được.
Em có 1 file khác (sưu tập trên mạng) có code gần giống thì lại không gặp vấn đề ở dòng này.
Nhờ các bác xem giúp code bị lỗi cái gì

(Do file kết nối SQL nếu up lên cũng không test được nên em gửi chụp hình)

Xin cảm ơn !


View attachment 242906
Bạn dùng kiểu mặc định cho i rồi debug xem i nhận giá trị gì. Biết rồi thì xử dễ mà.
 
Cảm ơn bạn. Mình đã thay trước đó nhưng vẫn bị vậy

rst.RecordCount của bạn chắc trả về trị: -1.
Xem lại tham số CursorLocation, dùng adUserClient.
Thường thì dùng thêm:
rst.MoveFirst
rst.MoveLast
Nếu recordset lớn quá thì cách này không hiệu quả.
 
Em có dùng đoạn code như hình dưới để lấy dữ liệu từ SQL Server. Nói chung code chạy bình thường ngoại trừ khi thêm dòng i = Rst.RecordCount như được tô trong hình. Mục đích là em chỉ muốn lấy số lượng bản ghi khi query được.
Em có 1 file khác (sưu tập trên mạng) có code gần giống thì lại không gặp vấn đề ở dòng này.
Nhờ các bác xem giúp code bị lỗi cái gì

(Do file kết nối SQL nếu up lên cũng không test được nên em gửi chụp hình)

Xin cảm ơn !


View attachment 242906
Bạn thử làm như sau xem được không?

PHP:
i=Sheet3.Range("AA3").CopyFromRecordset(Rst)
Sheet3.[A1]=i
 
Bạn không bảo cái recordset xác định nguồn gốc con trỏ (cursor) cho nên nó mặc định con trỏ của bên server (tức là bên SQL Server). Và vì bạn không xác định kiểu con trỏ nên bên server mặc định kiểu con trỏ là một chiều (forward only). Với lối mặc định này, RecordCount không thể tính được.

Để có thể tính RecordCount, bạn có hai chọn lựa:

1. bảo bên server dùng con trỏ static
đổi 2 dòng này:
Rst.Activeconnection = Conn
Rst.Open Source:=MyQuery
thành
Rst.Open MyQuery, Conn, adOpenStatic
Chú: dùng adOpenKeyset cũng được; nhưng tôi không khuyến khích vì nó sẽ đụng chạm tới locks của server, và các Server Admin có thể không cho kết nối.

2. chuyển con trỏ về bên client (tức là bên code VBA-ADO của bạn)
thêm dòngn này trước khi open:
Rst.CursorLocation = adUseClient

Nếu thấy rắc rối quá thì có thể dùng cách ở bài #6. Hàm CopyFromRecordset trả về số records mà nó copy được.
Sheet3.[A1].Value = Sheet3.Range("AA3").CopyFromRecordset(Rst)
 
Lần chỉnh sửa cuối:
Nhìn hình đón thì bài 5, bài 7 là khả năng chính xác
 
rst.RecordCount của bạn chắc trả về trị: -1.
Xem lại tham số CursorLocation, dùng adUserClient.
Thường thì dùng thêm:
rst.MoveFirst
rst.MoveLast
Nếu recordset lớn quá thì cách này không hiệu quả.
Cảm ơn bạn, đúng là nó trả về giá trị -1.
Có điều lạ là vẫn file đó không thay đổi gì khi chạy tại máy của mình thì báo lỗi Type Mismatch. Chạy ở máy khác thì Code chạy bình thường (Dim i as Integer hay Long đều chạy) và ra giá trị i = -1. Quay trở lại máy của mình, nếu sửa Dim i là double thì code lại chạy và ra i = -1 . Mình chưa hiểu nguyên nhân
Bài đã được tự động gộp:

Bạn thử làm như sau xem được không?

PHP:
i=Sheet3.Range("AA3").CopyFromRecordset(Rst)
Sheet3.[A1]=i
Cảm ơn bạn, dùng đoạn code bạn gợi ý thì Sub chạy tốt, không báo lỗi và ra kết quả số bản ghi đúng. Bạn giải thích để mình hiểu thêm với.
 
Bạn không bảo cái recordset xác định nguồn gốc con trỏ (cursor) cho nên nó mặc định con trỏ của bên server (tức là bên SQL Server). Và vì bạn không xác định kiểu con trỏ nên bên server mặc định kiểu con trỏ là một chiều (forward only). Với lối mặc định này, RecordCount không thể tính được.

Để có thể tính RecordCount, bạn có hai chọn lựa:

1. bảo bên server dùng con trỏ static
đổi 2 dòng này:
Rst.Activeconnection = Conn
Rst.Open Source:=MyQuery
thành
Rst.Open MyQuery, Conn, adOpenStatic
Chú: dùng adOpenKeyset cũng được; nhưng tôi không khuyến khích vì nó sẽ đụng chạm tới locks của server, và các Server Admin có thể không cho kết nối.

2. chuyển con trỏ về bên client (tức là bên code VBA-ADO của bạn)
thêm dòngn này trước khi open:
Rst.CursorLocation = adUseClient

Nếu thấy rắc rối quá thì có thể dùng cách ở bài #6. Hàm CopyFromRecordset trả về số records mà nó copy được.
Sheet3.[A1].Value = Sheet3.Range("AA3").CopyFromRecordset(Rst)
Cảm ơn bác đã hướng dẫn. Cái gợi ý thứ 3 của bác thì Code chạy tốt, kết quả đúng.
Tuy nhiên 2 gợi ý đầu code chạy vẫn báo lỗi. Không rõ em sai chỗ nào ?
1597231519718.png
Bài đã được tự động gộp:

Nhìn hình đón thì bài 5, bài 7 là khả năng chính xác
Bài 5 thì chính xác là i =-1 nhưng chưa ra giải pháp còn Bài 7 thì chỉ lựa chọn 3 là hoạt động bạn ạ
 
Cảm ơn bác đã hướng dẫn. Cái gợi ý thứ 3 của bác thì Code chạy tốt, kết quả đúng.
Tuy nhiên 2 gợi ý đầu code chạy vẫn báo lỗi. Không rõ em sai chỗ nào ?
...
Đó là một bug trong Excel 2010 phiên bản 64-bit.
Nếu Double được thì bạn có 3 chọn lựa:
1. cứ dùng double (đặt tên biến là rCount, chứ không ai i mà double cả).
2. thử ép kiểu i = CLng(Rst.RecordCount)
3. thử declare i là Long Long
Nếu không, bạn có thể tải hotfix của Microsoft về để chữa (tôi quên mất link, chịu khó gú gồ)

Các máy khác không bị lỗi này có lẽ là do chúng chạy Excel khác, hoặc phiên bản 32-bit. Hoặc chúng dùng ADO phiên bản mới hơn.

Chú thích: ở bài #7 tôi có giải thích tại sao ra -1 rồi. Nó là do chế độ mặc định con trỏ.
 
Đó là một bug trong Excel 2010 phiên bản 64-bit.
Nếu Double được thì bạn có 3 chọn lựa:
1. cứ dùng double (đặt tên biến là rCount, chứ không ai i mà double cả).
2. thử ép kiểu i = CLng(Rst.RecordCount)
3. thử declare i là Long Long
Nếu không, bạn có thể tải hotfix của Microsoft về để chữa (tôi quên mất link, chịu khó gú gồ)

Các máy khác không bị lỗi này có lẽ là do chúng chạy Excel khác, hoặc phiên bản 32-bit. Hoặc chúng dùng ADO phiên bản mới hơn.

Chú thích: ở bài #7 tôi có giải thích tại sao ra -1 rồi. Nó là do chế độ mặc định con trỏ.
Cái gợi ý
Đó là một bug trong Excel 2010 phiên bản 64-bit.
Nếu Double được thì bạn có 3 chọn lựa:
1. cứ dùng double (đặt tên biến là rCount, chứ không ai i mà double cả).
2. thử ép kiểu i = CLng(Rst.RecordCount)
3. thử declare i là Long Long
Nếu không, bạn có thể tải hotfix của Microsoft về để chữa (tôi quên mất link, chịu khó gú gồ)

Các máy khác không bị lỗi này có lẽ là do chúng chạy Excel khác, hoặc phiên bản 32-bit. Hoặc chúng dùng ADO phiên bản mới hơn.

Chú thích: ở bài #7 tôi có giải thích tại sao ra -1 rồi. Nó là do chế độ mặc định con trỏ.
Xin lỗi bác do em test không kỹ
Cả 3 đáp án của bác ở bài #7 đều chạy được tốt ở máy khác. Nó chỉ không chạy ở máy tính em thường dùng.
Em đã so sánh 2 máy: Máy chạy Code tốt thì Windows 7 (64b) và Office 2016 (64b), Máy chạy Code trên báo lỗi: Windows 10 (64b) + Office 2016 (64b)
Một lần nữa cảm ơn bác
 
Cảm ơn bạn, đúng là nó trả về giá trị -1.
Có điều lạ là vẫn file đó không thay đổi gì khi chạy tại máy của mình thì báo lỗi Type Mismatch. Chạy ở máy khác thì Code chạy bình thường (Dim i as Integer hay Long đều chạy) và ra giá trị i = -1. Quay trở lại máy của mình, nếu sửa Dim i là double thì code lại chạy và ra i = -1 . Mình chưa hiểu nguyên nhân
Bài đã được tự động gộp:


Cảm ơn bạn, dùng đoạn code bạn gợi ý thì Sub chạy tốt, không báo lỗi và ra kết quả số bản ghi đúng. Bạn giải thích để mình hiểu thêm với.
Ở cuối bài #7, bác @VetMini đã giải thích rồi mà bạn.
Nếu thấy rắc rối quá thì có thể dùng cách ở bài #6. Hàm CopyFromRecordset trả về số records mà nó copy được.
Sheet3.[A1].Value = Sheet3.Range("AA3").CopyFromRecordset(Rst)
 
Web KT

Bài viết mới nhất

Back
Top Bottom