Lấy nhiều loại dữ liệu từ SQL Server vào Excel

Blue Softs Liên hệ QC

MinhKhai

Giải pháp Ếc-xào
Tham gia
16/4/08
Bài viết
885
Được thích
546
Em có sưu tầm được đoạn code để lấy dữ liệu từ SQL Server như file đính kèm
File đã kết nối và chạy ra dữ liệu như ý.
Như đoạn code gốc, Sub chạy ra dữ liệu chính từ ô A8. Tuy nhiên ngoài dữ liệu chính em cần chạy cả dữ liệu phụ trên cùng sheet kiểu như lấy tên, địa chỉ, mã số thuế của khách từ database.
Cách em làm là nhân bản cái Sub Connect_To_SQLServer để lấy các dữ liệu phụ. Thực tế thì em cần cùng lúc lấy nhiều thông tin khác nữa để tạo nên bảng kê đầy đủ, không lẽ cứ nhân bản cái SUB kia lên cho đầy trong Module ?
Vậy nhờ anh chị chỉ giúp cách đưa tham số để lấy được nhiều dữ liệu với các lệnh SQL khác nhau và trả dữ liệu ở chỗ khác nhau mà ko phải nhân bản nhiều Sub
Xin cảm ơn
 

File đính kèm

  • BangKe.xlsb
    44.4 KB · Đọc: 58

ducdoom

Thành viên chính thức
Tham gia
24/12/18
Bài viết
60
Được thích
49
Xin chào!
Với vấn đề của bạn mình xin gợi ý bạn tạo 1 Function riêng để lấy dữ liệu từ Server.
Function này sẽ trả về là 1 RecordSet.
Dưới đây là code mình gợi ý thuận toán, không chú trọng cú pháp đúng sai của VBA:
Mã:
Function Get_Data_From_SQLServer(ByVal Server_Name As String, ByVal Database_Name As String, ByVal SQL_Statement As String) As Recordset
    'Ham nay se tra ve 1 Recordset
    
    '...
    'connect den Server de lay du lieu
    'tra ve 1 recordset, tam goi la RecordSet_Result
    '...
    
    Get_Data_From_SQLServer = RecordSet_Result
    
End Function

Sau đó, tại Sub chính bạn chỉ cần gọi Function vừa tạo để lấy dữ liệu. muốn lấy dữ liệu gì thì chỉ cần thay đổi tham số SQL_Statement là ok.
Mã:
Sub Run_Report_1()
    '...
    
    'lay data taxCode; ghi du lieu vao range A1
    Dim recordSet_taxCode As ADODB.Recordset
    Set recordSet_taxCode = Get_Data_From_SQLServer(serverName, databaseName, SQLstatement)
    With Sheet2
            .Range("A1").CopyFromRecordset recordSet_taxCode
    End With
    
    'lay data address; ghi du lieu vao range A2
    Dim recordSet_Address As ADODB.Recordset
    Set recordSet_Address = Get_Data_From_SQLServer(serverName, databaseName, SQLstatement)
    With Sheet2
            .Range("A2").CopyFromRecordset recordSet_Address
    End With
    
    '...
End Sub
 

MinhKhai

Giải pháp Ếc-xào
Tham gia
16/4/08
Bài viết
885
Được thích
546
Xin chào!
Với vấn đề của bạn mình xin gợi ý bạn tạo 1 Function riêng để lấy dữ liệu từ Server.
Cảm ơn bạn. Với file thực tế như đính kèm, bạn lắp ghép giúp mình được không vì mình không rành về VBA, code trong đó cũng sưu tầm của người khác. Cảm ơn bạn nhiều
 

ongke0711

Thành viên tích cực
Tham gia
7/9/06
Bài viết
1,085
Được thích
1,294
Giới tính
Nam
Như đoạn code gốc, Sub chạy ra dữ liệu chính từ ô A8. Tuy nhiên ngoài dữ liệu chính em cần chạy cả dữ liệu phụ trên cùng sheet kiểu như lấy tên, địa chỉ, mã số thuế của khách từ database.

Góp thêm ý kiến đó là: bạn nên thiết kế lại Sheet (hay Form) theo dạng như Form tìm kiếm vì bạn có nhiều điều kiện để lọc dữ liệu từ database.
- Thiết kế sẳn tất cả các ô dữ liệu có thể phát sinh trong tìm kiếm, lọc dữ liệu, tránh phải sửa lại sau này.
- Sau khi có tất cả các điều kiện cần lọc thì đưa vô một lần vào trong code (câu lệnh SQL Where...), không cần tạo nhiều câu lênh SQL Where như file hiện tại của bạn.

Hình minh hoạ:

Screen Shot 2020-02-06 at 9.35.03 AM.png
 

Huyyeu99999

Thành viên chính thức
Tham gia
27/12/19
Bài viết
50
Được thích
27
Nghề nghiệp
Chuyên gia nhiều chuyện
Sao na ná phổ cập vậy anh
 

NguyenthiH

thành viên mù VBA
Tham gia
11/12/16
Bài viết
815
Được thích
130
Giới tính
Nữ
Form của anh @ongke0711 lúc nào nhìn cũng "Bắt mắt", giao diện đẹp quá.
 

MinhKhai

Giải pháp Ếc-xào
Tham gia
16/4/08
Bài viết
885
Được thích
546
Góp thêm ý kiến đó là: bạn nên thiết kế lại Sheet (hay Form) theo dạng như Form tìm kiếm vì bạn có nhiều điều kiện để lọc dữ liệu từ database.
- Thiết kế sẳn tất cả các ô dữ liệu có thể phát sinh trong tìm kiếm, lọc dữ liệu, tránh phải sửa lại sau này.
- Sau khi có tất cả các điều kiện cần lọc thì đưa vô một lần vào trong code (câu lệnh SQL Where...), không cần tạo nhiều câu lênh SQL Where như file hiện tại của bạn.

Hình minh hoạ:

View attachment 231671
Cách như hình của bạn vừa hiện đại vừa thuận tiện. Bạn có thể share cho mình được không ?
Nói thật với bạn là mình đang mon men vào Code nên rất gà mờ. Mong muốn dùng Excel thay cho ứng dụng là có nhưng dù ai đó cho 1 tool hoàn chỉnh cũng chưa chắc bảo trì hay tùy biến được, vì thế mới chỉ hỏi những thứ ở tầm đơn giản nằm trong khả năng tùy chỉnh nó. Những gợi ý của bạn mà có file đính kèm thì dễ hiểu biết bao. Rất cảm ơn bạn đã giúp đỡ.
 

ongke0711

Thành viên tích cực
Tham gia
7/9/06
Bài viết
1,085
Được thích
1,294
Giới tính
Nam
Nói thật với bạn là mình đang mon men vào Code nên rất gà mờ. Mong muốn dùng Excel thay cho ứng dụng là có nhưng dù ai đó cho 1 tool hoàn chỉnh cũng chưa chắc bảo trì hay tùy biến được, vì thế mới chỉ hỏi những thứ ở tầm đơn giản nằm trong khả năng tùy chỉnh nó. Những gợi ý của bạn mà có file đính kèm thì dễ hiểu biết bao.

Form này tôi làm trên Access nhưng bạn vẫn có thể thiết kế bằng Userform của Excel hoặc để gần gũi với Excel hơn nữa thì bạn thiết kế ngay trên Sheet (Sheet Form). Code thì nó cũng sẽ gần như nhau chỉ có khác là cách lấy tham số truyền vào cho các Sub/Function thôi.
Bạn cứ dùng công cụ bạn thân thuộc nhất mà thiết kế để sau này còn biết đường mà bảo trì, bảo dưỡng...Cái hình trên là để định hướng thiết kế và từ đó code nó sẽ đi theo cho thuận tiện, bao quát hơn v.v..
Bạn cứ thử làm trên Sheet form xem như thế nào.

Còn về cái ý gom tất cả các điều kiện lọc dữ liệu vô chung một câu lệnh SQL: "...Where..." để xử lý thì nó đại khái như sau: Cái ví dụ này tôi có làm demo trong bài post lúc trước của bác Hai Lúa Miền Tây: Lọc nhiều điều kiện

Screen Shot 2020-02-06 at 12.45.09 PM.png


Code bên dưới là đưa cả 3 điều kiện lọc dữ liệu của range (A1:B3) vào chung mệnh đề WHERE.

Mã:
'Tong hop dieu kien loc
    s = "SELECT * FROM [" & sRngName & "] WHERE 1=1"
    s1 = " AND [" & Sheet3.Range("A1") & "]" & Sheet3.Range("B1")                   'Balance
    s2 = " AND [" & Sheet3.Range("A2") & "] =" & Sheet3.Range("B2")                 'ID
    s3 = " AND [" & Sheet3.Range("A3") & "] ='" & Sheet3.Range("B3") & "'"    'Remark
    If Not IsEmpty(Sheet3.Range("B1")) Then
        s = s & s1
    End If
    If Not IsEmpty(Sheet3.Range("B2")) Then
        s = s & s2
    End If
    If Not IsEmpty(Sheet3.Range("B3")) Then
        s = s & s3
    End If
    s = s & " ORDER BY [ID]"
    'Debug.Print s
 

MinhKhai

Giải pháp Ếc-xào
Tham gia
16/4/08
Bài viết
885
Được thích
546
Form này tôi làm trên Access nhưng bạn vẫn có thể thiết kế bằng Userform của Excel hoặc để gần gũi với Excel hơn nữa thì bạn thiết kế ngay trên Sheet (Sheet Form). Code thì nó cũng sẽ gần như nhau chỉ có khác là cách lấy tham số truyền vào cho các Sub/Function thôi.
Bạn cứ dùng công cụ bạn thân thuộc nhất mà thiết kế để sau này còn biết đường mà bảo trì, bảo dưỡng...Cái hình trên là để định hướng thiết kế và từ đó code nó sẽ đi theo cho thuận tiện, bao quát hơn v.v..
Bạn cứ thử làm trên Sheet form xem như thế nào.

Còn về cái ý gom tất cả các điều kiện lọc dữ liệu vô chung một câu lệnh SQL: "...Where..." để xử lý thì nó đại khái như sau: Cái ví dụ này tôi có làm demo trong bài post lúc trước của bác Hai Lúa Miền Tây: Lọc nhiều điều kiện

View attachment 231674


Code bên dưới là đưa cả 3 điều kiện lọc dữ liệu của range (A1:B3) vào chung mệnh đề WHERE.

Mã:
'Tong hop dieu kien loc
    s = "SELECT * FROM [" & sRngName & "] WHERE 1=1"
    s1 = " AND [" & Sheet3.Range("A1") & "]" & Sheet3.Range("B1")                   'Balance
    s2 = " AND [" & Sheet3.Range("A2") & "] =" & Sheet3.Range("B2")                 'ID
    s3 = " AND [" & Sheet3.Range("A3") & "] ='" & Sheet3.Range("B3") & "'"    'Remark
    If Not IsEmpty(Sheet3.Range("B1")) Then
        s = s & s1
    End If
    If Not IsEmpty(Sheet3.Range("B2")) Then
        s = s & s2
    End If
    If Not IsEmpty(Sheet3.Range("B3")) Then
        s = s & s3
    End If
    s = s & " ORDER BY [ID]"
    'Debug.Print s
Cảm ơn bạn rất nhiều đã cung cấp những gợi ý quý.
Đối với điều kiện lọc, mình đã tính tới việc dùng hàm If và Concatenate kết hợp với Validation để tạo câu lệnh SQL hoàn chỉnh tại 1 ô của Excel, từ đó code vba sẽ tham chiếu đến ô này để truy vấn.
Vấn đề trước mắt của mình là, mình có sẵn những câu lệnh SQL, tại nhiều ô trong Excel, làm sao để dùng 1 Sub trong VBA để lần lượt dùng các câu SQL đó và trả kết quả trên 1 sheet (Giống hàm BS_SQL của Addin ATools).
 

ppc0312

whom?
Tham gia
2/4/08
Bài viết
623
Được thích
317
Cảm ơn bạn rất nhiều đã cung cấp những gợi ý quý.
Đối với điều kiện lọc, mình đã tính tới việc dùng hàm If và Concatenate kết hợp với Validation để tạo câu lệnh SQL hoàn chỉnh tại 1 ô của Excel, từ đó code vba sẽ tham chiếu đến ô này để truy vấn.
Vấn đề trước mắt của mình là, mình có sẵn những câu lệnh SQL, tại nhiều ô trong Excel, làm sao để dùng 1 Sub trong VBA để lần lượt dùng các câu SQL đó và trả kết quả trên 1 sheet (Giống hàm BS_SQL của Addin ATools).
Thì đọc giá trị cell chứa lệnh SQL đó vào 1 biến nào đó ví dụ strSQL rồi thực thi nó (cái này chắc biết rồi) - thế là được
 

ongke0711

Thành viên tích cực
Tham gia
7/9/06
Bài viết
1,085
Được thích
1,294
Giới tính
Nam
Vấn đề trước mắt của mình là, mình có sẵn những câu lệnh SQL, tại nhiều ô trong Excel, làm sao để dùng 1 Sub trong VBA để lần lượt dùng các câu SQL đó và trả kết quả trên 1 sheet (Giống hàm BS_SQL của Addin ATools).

Nếu bạn muốn nói tới mấy câu lệnh SQL đã làm sẳn trong file demo của bạn thì tôi khuyên nên bỏ cách làm này đi, nó sai bài và lãng phí tài nguyên máy.

Screen Shot 2020-02-07 at 10.04.26 PM.png

Mỗi câu lệnh Select lại kết nối tới SQL Server lấy chút dữ liệu, tải về rồi kết nối, lấy dữ liệu.
Bạn phải làm là:
- Tạo câu lệnh Select để lấy toàn bộ dữ liệu mình cần một lần.

Mã:
SELECT NAME, ADDR, TAXCODE FROM LT_CUSTOMER Where CUSTOMER = " & "'" & BangKe1!K2 & "'"

- Sau khi lấy được Recordset từ câu lệnh SQL trên sẽ gán giá trị từng field cho từng Cell như yêu cầu.

Mã:
.Range("A4").Value = rst!NAME
.Range("A5").Value = rst!ADDR
.Range("A6").Value = rst!TAXCODE
 

MinhKhai

Giải pháp Ếc-xào
Tham gia
16/4/08
Bài viết
885
Được thích
546
Nếu bạn muốn nói tới mấy câu lệnh SQL đã làm sẳn trong file demo của bạn thì tôi khuyên nên bỏ cách làm này đi, nó sai bài và lãng phí tài nguyên máy.

View attachment 231748

Mỗi câu lệnh Select lại kết nối tới SQL Server lấy chút dữ liệu, tải về rồi kết nối, lấy dữ liệu.
Bạn phải làm là:
- Tạo câu lệnh Select để lấy toàn bộ dữ liệu mình cần một lần.

Mã:
SELECT NAME, ADDR, TAXCODE FROM LT_CUSTOMER Where CUSTOMER = " & "'" & BangKe1!K2 & "'"

- Sau khi lấy được Recordset từ câu lệnh SQL trên sẽ gán giá trị từng field cho từng Cell như yêu cầu.

Mã:
.Range("A4").Value = rst!NAME
.Range("A5").Value = rst!ADDR
.Range("A6").Value = rst!TAXCODE
Bạn nói rất trúng điều mình đang cần. Chưa nói đến lãng phí tài nguyên, mà chỉ riêng việc tạo các Sub cho nó để ra 1 bảng kết quả đã nản rồi. Do Code trong file mình đi nhặt được từ trên Youtube nên có ý tưởng mà ko biết làm. Bạn sửa code trong file thành hoàn chỉnh giúp mình với nhé. Cảm ơn bạn nhiều
 

luckypham

Thành viên mới
Tham gia
13/6/16
Bài viết
2
Được thích
0
Góp thêm ý kiến đó là: bạn nên thiết kế lại Sheet (hay Form) theo dạng như Form tìm kiếm vì bạn có nhiều điều kiện để lọc dữ liệu từ database.
- Thiết kế sẳn tất cả các ô dữ liệu có thể phát sinh trong tìm kiếm, lọc dữ liệu, tránh phải sửa lại sau này.
- Sau khi có tất cả các điều kiện cần lọc thì đưa vô một lần vào trong code (câu lệnh SQL Where...), không cần tạo nhiều câu lênh SQL Where như file hiện tại của bạn.

Hình minh hoạ:

View attachment 231671
có thể chia sẻ mình file này của bạn để mình nghiên cứu được không bạn. Thanks bạn
 
Top Bottom