• Shopee đêm nay có mã cho ngày 5/5

kiến thức [Excel VBA] Thao tác với dữ liệu bằng công thức SQL trực tiếp trên sheet

NguyenDang95

Senior Member
Áp dụng cho: Excel 365, Excel 2021.

Một tệp Excel có thể thực hiện chức năng như một cơ sở dữ liệu để thực hiện nhiều thao tác trích lọc, truy vấn dữ liệu khác nhau. Ngoài Power Query (ngôn ngữ Power Query M), chúng ta có thể dùng SQL (trong trường hợp này là Access SQL) truy vấn trực tiếp đến tệp Excel, điều này thật sự hữu ích khi dữ liệu khá lớn và những công cụ có sẵn của Excel xử lý chậm hẳn.
Code:
Option Explicit
'Tham chiếu đến thư viện Microsoft ActiveX Data Object 6.1 Library.
Public Function EXECUTESQL(SQLStatement As String) As Variant
Dim objCnn As ADODB.Connection
    Dim objCmd As ADODB.Command
    Dim objRs As ADODB.Recordset
    Dim arrResult() As Variant, arrMergedArray() As Variant, arrColumnNames() As Variant
    Dim strCnn As String, strColumnName As String
    Dim i As Long
    EXECUTESQL = CVErr(xlErrNA)
    strCnn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ActiveWorkbook.FullName & ";Extended Properties='Excel 12.0 Xml;HDR=YES';"
    Set objCnn = New ADODB.Connection
    With objCnn
        .ConnectionString = strCnn
        .Open
    End With
    Set objCmd = New ADODB.Command
    With objCmd
        .ActiveConnection = objCnn
        .CommandText = SQLStatement
        Set objRs = .Execute
    End With
    If Not objRs Is Nothing Then
        On Error Resume Next
        arrResult = Application.WorksheetFunction.Transpose(objRs.GetRows)
        ReDim arrColumnNames(0 To objRs.Fields.Count - 1)
        For i = 0 To objRs.Fields.Count - 1
            arrColumnNames(i) = objRs.Fields.Item(i).Name
        Next
        arrMergedArray = PrepareOutputData(arrColumnNames, arrResult)
        Erase arrColumnNames
        Erase arrResult
        If Err.Number <> 0 Then
            EXECUTESQL = CVErr(xlErrNA)
            Err.Clear
            Exit Function
        End If
    End If
    objRs.Close
    objCnn.Close
    EXECUTESQL = arrMergedArray
    Set objCnn = Nothing
    Set objCmd = Nothing
    Set objRs = Nothing
End Function

Private Function PrepareOutputData(ColumnNames As Variant, TableData As Variant)
    Dim arrResult() As Variant
    Dim i As Long, j As Long
    If Is2DArray(TableData) Then
        ReDim arrResult(0 To UBound(TableData), 0 To UBound(ColumnNames))
        For i = 0 To UBound(ColumnNames)
            arrResult(0, i) = ColumnNames(i)
        Next
        For i = 1 To UBound(TableData)
            For j = 0 To UBound(ColumnNames)
                arrResult(i, j) = TableData(i, j + 1)
            Next
        Next
    Else
        ReDim arrResult(0 To 1, 0 To UBound(ColumnNames))
        For i = 0 To UBound(ColumnNames)
            arrResult(0, i) = ColumnNames(i)
        Next
        For j = 0 To UBound(ColumnNames)
            arrResult(1, j) = TableData(j + 1)
        Next
    End If
    PrepareOutputData = arrResult
End Function

Private Function Is2DArray(InputArray As Variant) As Boolean
    Dim lngMaxColumnIndex As Long
    On Error Resume Next
    lngMaxColumnIndex = UBound(InputArray, 2)
    If Err.Number = 9 Then
        Err.Clear
        Is2DArray = False
    Else: Is2DArray = True
    End If
End Function

Sử dụng hàm đã viết trong VBA:
1659974004233.png

Lưu ý: Do ô (Cell) trong Excel chỉ cho phép chứa tối đa 255 ký tự, cho nên đối với truy vấn SQL quá dài, chúng ta có thể chia nhỏ thành nhiều phần rồi dùng hàm Concatenate để nối lại thành chuỗi hoàn chỉnh.

Tìm hiểu thêm:

Run SQL queries on Excel files (Power Automate)​

https://docs.microsoft.com/en-us/power-automate/desktop-flows/how-to/sql-queries-excel
 
Last edited:
Một tệp Excel có thể thực hiện chức năng như một cơ sở dữ liệu để thực hiện nhiều thao tác trích lọc, truy vấn dữ liệu khác nhau. Ngoài Power Query (ngôn ngữ Power Query M), chúng ta có thể dùng SQL (trong trường hợp này là Access SQL) truy vấn trực tiếp đến tệp Excel, điều này thật sự hữu ích khi dữ liệu khá lớn và những công cụ có sẵn của Excel xử lý chậm hẳn.
Code:
Option Explicit
'Tham chiếu đến thư viện Microsoft ActiveX Data Object 6.1 Library.
Public Function EXECUTESQL(SQLStatement As String) As Variant
Dim objCnn As ADODB.Connection
    Dim objCmd As ADODB.Command
    Dim objRs As ADODB.Recordset
    Dim arrResult() As Variant, arrMergedArray() As Variant, arrColumnNames() As Variant
    Dim strCnn As String, strColumnName As String
    Dim i As Long
    EXECUTESQL = CVErr(xlErrNA)
    strCnn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ActiveWorkbook.FullName & ";Extended Properties='Excel 12.0 Xml;HDR=YES';"
    Set objCnn = New ADODB.Connection
    With objCnn
        .ConnectionString = strCnn
        .Open
    End With
    Set objCmd = New ADODB.Command
    With objCmd
        .ActiveConnection = objCnn
        .CommandText = SQLStatement
        Set objRs = .Execute
    End With
    If Not objRs Is Nothing Then
        On Error Resume Next
        arrResult = Application.WorksheetFunction.Transpose(objRs.GetRows)
        ReDim arrColumnNames(0 To objRs.Fields.Count - 1)
        For i = 0 To objRs.Fields.Count - 1
            arrColumnNames(i) = objRs.Fields.Item(i).Name
        Next
        arrMergedArray = PrepareOutputData(arrColumnNames, arrResult)
        Erase arrColumnNames
        Erase arrResult
        If Err.Number <> 0 Then
            EXECUTESQL = CVErr(xlErrNA)
            Err.Clear
            Exit Function
        End If
    End If
    objRs.Close
    objCnn.Close
    EXECUTESQL = arrMergedArray
    Set objCnn = Nothing
    Set objCmd = Nothing
    Set objRs = Nothing
End Function

Private Function PrepareOutputData(ColumnNames As Variant, TableData As Variant)
    Dim arrResult() As Variant
    Dim i As Long, j As Long
    ReDim arrResult(0 To UBound(TableData), 0 To UBound(ColumnNames))
    For i = 0 To UBound(ColumnNames)
        arrResult(0, i) = ColumnNames(i)
    Next
    For i = 1 To UBound(TableData)
        For j = 0 To UBound(ColumnNames)
            arrResult(i, j) = TableData(i, j + 1)
        Next
    Next
    PrepareOutputData = arrResult
End Function

Sử dụng hàm đã viết trong VBA:
View attachment 1311391
Lưu ý: Do ô (Cell) trong Excel chỉ cho phép chứa tối đa 255 ký tự, cho nên đối với truy vấn SQL quá dài, chúng ta có thể chia nhỏ thành nhiều phần rồi dùng hàm Concatenate để nối lại thành chuỗi hoàn chỉnh.

Tìm hiểu thêm:

Run SQL queries on Excel files (Power Automate)​

https://docs.microsoft.com/en-us/power-automate/desktop-flows/how-to/sql-queries-excel
viết hàm vầy
thì vào cell nó chạy có chậm quá không hay tương đương với hàm bình thường hả bác
 
Một tệp Excel có thể thực hiện chức năng như một cơ sở dữ liệu để thực hiện nhiều thao tác trích lọc, truy vấn dữ liệu khác nhau. Ngoài Power Query (ngôn ngữ Power Query M), chúng ta có thể dùng SQL (trong trường hợp này là Access SQL) truy vấn trực tiếp đến tệp Excel, điều này thật sự hữu ích khi dữ liệu khá lớn và những công cụ có sẵn của Excel xử lý chậm hẳn.
Code:
Option Explicit
'Tham chiếu đến thư viện Microsoft ActiveX Data Object 6.1 Library.
Public Function EXECUTESQL(SQLStatement As String) As Variant
Dim objCnn As ADODB.Connection
    Dim objCmd As ADODB.Command
    Dim objRs As ADODB.Recordset
    Dim arrResult() As Variant, arrMergedArray() As Variant, arrColumnNames() As Variant
    Dim strCnn As String, strColumnName As String
    Dim i As Long
    EXECUTESQL = CVErr(xlErrNA)
    strCnn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ActiveWorkbook.FullName & ";Extended Properties='Excel 12.0 Xml;HDR=YES';"
    Set objCnn = New ADODB.Connection
    With objCnn
        .ConnectionString = strCnn
        .Open
    End With
    Set objCmd = New ADODB.Command
    With objCmd
        .ActiveConnection = objCnn
        .CommandText = SQLStatement
        Set objRs = .Execute
    End With
    If Not objRs Is Nothing Then
        On Error Resume Next
        arrResult = Application.WorksheetFunction.Transpose(objRs.GetRows)
        ReDim arrColumnNames(0 To objRs.Fields.Count - 1)
        For i = 0 To objRs.Fields.Count - 1
            arrColumnNames(i) = objRs.Fields.Item(i).Name
        Next
        arrMergedArray = PrepareOutputData(arrColumnNames, arrResult)
        Erase arrColumnNames
        Erase arrResult
        If Err.Number <> 0 Then
            EXECUTESQL = CVErr(xlErrNA)
            Err.Clear
            Exit Function
        End If
    End If
    objRs.Close
    objCnn.Close
    EXECUTESQL = arrMergedArray
    Set objCnn = Nothing
    Set objCmd = Nothing
    Set objRs = Nothing
End Function

Private Function PrepareOutputData(ColumnNames As Variant, TableData As Variant)
    Dim arrResult() As Variant
    Dim i As Long, j As Long
    ReDim arrResult(0 To UBound(TableData), 0 To UBound(ColumnNames))
    For i = 0 To UBound(ColumnNames)
        arrResult(0, i) = ColumnNames(i)
    Next
    For i = 1 To UBound(TableData)
        For j = 0 To UBound(ColumnNames)
            arrResult(i, j) = TableData(i, j + 1)
        Next
    Next
    PrepareOutputData = arrResult
End Function

Sử dụng hàm đã viết trong VBA:
View attachment 1311391
Lưu ý: Do ô (Cell) trong Excel chỉ cho phép chứa tối đa 255 ký tự, cho nên đối với truy vấn SQL quá dài, chúng ta có thể chia nhỏ thành nhiều phần rồi dùng hàm Concatenate để nối lại thành chuỗi hoàn chỉnh.

Tìm hiểu thêm:

Run SQL queries on Excel files (Power Automate)​

https://docs.microsoft.com/en-us/power-automate/desktop-flows/how-to/sql-queries-excel
Mình cũng làm như bạn nhưng khi gõ xong công thức thì nó chỉ ra mỗi kết quả là ô B8 và có chữ là: "STT" thôi. Không biết mình làm sai ở đâu nhỉ, giúp mình với. Mình dùng Excel 2010 có được không?
 
Mình cũng làm như bạn nhưng khi gõ xong công thức thì nó chỉ ra mỗi kết quả là ô B8 và có chữ là: "STT" thôi. Không biết mình làm sai ở đâu nhỉ, giúp mình với. Mình dùng Excel 2010 có được không?
Cho mình xin ảnh chụp dữ liệu + công thức đi thím.
 
Đây bác ơi
À, hiểu rồi, công thức của mình trả về một mảng, mà chỉ có bản Excel 365 với Excel 2021 mới hỗ trợ mảng động (dynamic array), với của thím đang dùng là Excel 2010 nên công thức mới trả về phần tử đầu tiên trong mảng là vì vậy.
Giải pháp: Thím nâng cấp lên Excel 2021 xem sao nhé.
 
Mãi mới thấy 1 bài chia sẻ về sql. Mình nghĩ sql này sẽ rất nhanh so vs công thức bt chứ nhỉ.
Mà win 7 cài đc office 2021 k nhỉ. Mình cũng đang chạy win 7 office 2010
 
Mãi mới thấy 1 bài chia sẻ về sql. Mình nghĩ sql này sẽ rất nhanh so vs công thức bt chứ nhỉ.
Mà win 7 cài đc office 2021 k nhỉ. Mình cũng đang chạy win 7 office 2010
1. Mình nghĩ khi dữ liệu quá lớn thì dùng SQL sẽ hiệu quả hơn, còn nếu dữ liệu ít thì dùng luôn mấy hàm tiêu chuẩn của Excel cho tiện.
2. Theo thông tin trên trang của Microsoft: https://support.microsoft.com/en-us...68-06a8493f3cb9#ID0EBDF=Other_Office_versions
Windows 7 không hỗ trợ Office 2021 nhé thím, nếu muốn cài đặt thì thím phải nâng cấp lên phiên bản tối thiểu là Windows 10.
 
Vậy sql khá khó dùng cho win 7 vì hiện tại công ty toàn chạy win 7
Nếu vậy thì thay vì viết hàm như ví dụ trên thì thím có thể viết một macro gồm một userform cho phép thím viết truy vấn SQL đến tệp Excel đang làm việc và trả kết quả ra vị trí bất kỳ trong sheet.
 
File code ở trong đó à bác. Mỗi lần dùng cho file mới thì làm ntn bác. Hướng dẫn e tí. E hơi gà
 
Back
Top