Viết một hàm VBA "chuẩn"

Liên hệ QC

Nguyễn Duy Tuân

Nghị Hách
Thành viên danh dự
Tham gia
13/6/06
Bài viết
4,766
Được thích
10,281
Giới tính
Nam
Nghề nghiệp
Giáo viên, CEO tại Bluesofts
Trong thời gian dài vừa qua tôi đã làm nhiều ứng dụng trong VBA, đã viết rất nhiều hàm cho tôi và cho mọi người, có lẽ các hàm tôi và các bạn viết trong VBA không khác nhau lắm. Nhưng chúng ta đã làm khác với Microsoft về cách lập trình một hàm trong VBA. Có lẽ một phần do chúng ta khi viết hàm là để đạt được một mục đích nhất định chứ chưa phân tích hết các tình huống tổng quát xảy ra khi sử dụng hàm trên Sheet hay trong VBA.

Chúng ta có thể viết hàm SumA tính tổng
Mã:
Function SumA(ByVal Value As Range)
Dim Cell As Range
For Each Cell In Value
    SumA = SumA + Cell.Value
Next
End Function

Tôi tạo công thức tính tổng trên một Sheet như sau
=SumA(A1:A5)
Nếu A1:A5 chỉ chứa các giá trị là số thì kết quả đúng
Nếu ít nhất một ô kiểu giá trị khác số thì kết quả là #VALUE! - Sai kiểu giá trị.

Nếu tôi dùng
=SumA(2,3,5) - Sai vì SumA chỉ có một đối số (chứ không phải 3) -> Lỗi #VALUE!
=SumA(2) - Sai vì đối số của SumA có kiểu là Range -> Lỗi #VALUE!

Nếu tôi dùng hàm SUM của Excel thì đều chạy được, kết quả đúng theo yêu cầu
=SUM(A1:A5) - Đúng dù cho ít nhất một phần tử không phải kiểu số
=SUM(2,3,5) - Đúng vì Excel cho tối đa 30 đối số trong một hàm, các đối số đó là kiểu số
=SUM(A1:A5,"Tuân",3,5) Vẫn chạy đúng, hàm sẽ tự cộng các giá trị là kiểu số trong đó.

Hàm trong Excel thật tuyệt vời!
Như vậy hàm SumA của chúng ta chưa làm đúng nhiệm vụ như hàm SUM của Excel.
Tôi sẽ trình bày các bạn một cách viết hàm VBA_SUM có thể làm việc như hàm SUM của Excel về chức năng cũng như cách thức sử dụng.

Mã:
Function VBA_SUM(ByVal Value1 As Variant, _
                        Optional ByVal Value2, _
                        Optional ByVal Value3, _
                        Optional ByVal Value4, _
                        Optional ByVal Value5, _
                        Optional ByVal Value6, _
                        Optional ByVal Value7, _
                        Optional ByVal Value8, _
                        Optional ByVal Value9, _
                        Optional ByVal Value10, _
                        Optional ByVal Value11, _
                        Optional ByVal Value12, _
                        Optional ByVal Value13, _
                        Optional ByVal Value14, _
                        Optional ByVal Value15, _
                        Optional ByVal Value16, _
                        Optional ByVal Value17, _
                        Optional ByVal Value18, _
                        Optional ByVal Value19, _
                        Optional ByVal Value20, _
                        Optional ByVal Value21, _
                        Optional ByVal Value22, _
                        Optional ByVal Value23, _
                        Optional ByVal Value24, _
                        Optional ByVal Value25) As Variant [COLOR="SeaGreen"]'VB/VBA cho phép tối đa 25 đối số trong một hàm. Các hàm trong Excel là 30.[/COLOR]

Dim Value As Variant, ValueArg As Variant
Dim VT As VbVarType 'Kiểu giá trị có trong biến VARIANT
Dim Cell As Variant

'Gán các đối số vào trong mảng ValueArg
ValueArg = Array(Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, _
Value11, Value12, Value13, Value14, Value15, Value16, Value17, Value18, Value19, Value20, _
Value21, Value22, Value23, Value24, Value25)
'Neu khi su dung ham VBA_SUM(1,,"T") . Do so thu 2 va cac doi so thu 4 tro di se la Missing, co kieu la vbError

VBA_SUM = 0
For Each Value In ValueArg 'Tinh cho tat ca cac doi so
    
    VT = VarType(Value)
    
    [COLOR="SeaGreen"]'Kiểm tra nếu dữ liệu không hợp lệ[/COLOR]
    If VT = vbEmpty Or VT = vbError Or VT = vbString Or VT = vbNull Then
        GoTo EndFor
    End If
    
    If VT = vbObject Then 'Neu Value la mot Object
        If Value Is Nothing Then
            GoTo EndFor
        End If
    End If
    
    '8204 la kieu Range trong Excel
    If VT = 8204 Or VT = vbObject Or VT = vbArray Then 'Neu Value cã gia tri kieu Range hoac la mot Array
        For Each Cell In Value
            'Kiem tra kieu gia tri cua tung phan tu Cell(i)
            VT = VarType(Cell)
            If VT <> vbEmpty And VT <> vbError And VT <> vbString And VT <> vbNull Then
                VBA_SUM = VBA_SUM + Cell
            End If
        Next 'Cell
    Else
        VBA_SUM = VBA_SUM + Value
    End If

EndFor:

Next 'For Each Value

End Function

Để các thủ tục để test như sau
Mã:
Sub Test_SumOfRange()
    'Tinh trong vung A1:A5
    MsgBox VBA_SUM(Range("A1:A5"))
End Sub
Sub Test_SumOfArray()
Dim A As Variant
A = Array(1, 2, "a")
    MsgBox VBA_SUM(A)
End Sub
Sub Test_SumOfConst()
Dim b As Currency
b = 8
    MsgBox VBA_SUM(2, b)
End Sub

Sub Test_SumOfObject()
Dim obj As Object
Set obj = Nothing
    MsgBox VBA_SUM(obj, 2)
End Sub

Sub Test_SumOfParams()
Dim obj As Object, Object2 As Object
Set obj = Nothing
Set obj2 = Range("A1:A5")
    MsgBox VBA_SUM(obj, obj2, 2, , Range("A1:A5"), "Tuan")
End Sub

Trên chỉ là hàm VBA_SUM để tính tổng, với các hàm khác các bạn cũng có thể làm theo cấu trúc như vậy.
Các bạn có thể download file đính kèm dưới đây.

Các bạn có thể bổ sung các bài viết liên quan tới chủ đề này nhé!
 

File đính kèm

Lần chỉnh sửa cuối:
Web KT

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

Back
Top Bottom