Excel Vba Call A Function: Hướng Dẫn Chi Tiết Từ Cơ Bản Đến Nâng Cao

1. Giới thiệu chung về VBA và hàm (Function) trong Excel

Microsoft Excel không chỉ là một công cụ bảng tính mạnh mẽ mà còn là một môi trường lập trình tích hợp thông qua Visual Basic for Applications (VBA). VBA cho phép người dùng tự động hoá các tác vụ lặp lại, xây dựng các công cụ tùy chỉnh và mở rộng khả năng tính toán của Excel. Trong số các thành phần cơ bản của VBA, Function (hàm) đóng vai trò quan trọng vì nó giúp tách rời logic xử lý thành các khối mã có thể tái sử dụng, dễ bảo trì và dễ kiểm thử.

Khi nói tới “Excel VBA call a function”, chúng ta đang nói tới việc gọi một hàm đã được định nghĩa trong một module VBA từ một vị trí khác – có thể là từ một Sub (procedure), một hàm khác, một nút bấm trên worksheet, hay thậm chí là từ một công thức Excel (UDF – User Defined Function). Bài viết này sẽ đi sâu vào:

  1. Cách tạo và định nghĩa một Function trong VBA.
  2. Các cách gọi Function trong các ngữ cảnh khác nhau.
  3. Các lưu ý quan trọng (đối số, kiểu trả về, scope, error handling…).
  4. Ví dụ thực tế từ cơ bản tới nâng cao.
  5. Những mẹo tối ưu và best practices khi làm việc với Function trong Excel VBA.

Mục tiêu cuối cùng là bạn sẽ nắm vững cách call a function trong Excel VBA, từ đó xây dựng các giải pháp tự động hoá hiệu quả và chuyên nghiệp.

2. Cú pháp cơ bản để định nghĩa một Function trong VBA

Trong VBA, một Function được khai báo bằng từ khóa Function, tiếp theo là tên hàm, danh sách các tham số (nếu có) và kiểu dữ liệu trả về. Cú pháp tổng quát:

Function TênHàm(ThamSo1 As Kiểu1, ThamSo2 As Kiểu2, ...) As KiểuKếtQuả ' Các câu lệnh xử lý TênHàm = GiáTrịKếtQuả ' Gán giá trị trả về cho tên hàm
End Function

2.1. Ví dụ đơn giản: tính tổng hai số

Function TongHaiSo(a As Double, b As Double) As Double TongHaiSo = a + b
End Function

Trong ví dụ trên:

  • TongHaiSo là tên hàm, nhận hai tham số a và b kiểu Double.
  • Dòng TongHaiSo = a + b gán kết quả cho hàm, đây là cách trả về giá trị trong VBA.

2.2. Kiểu dữ liệu (Data Types)

VBA hỗ trợ nhiều kiểu dữ liệu, bao gồm:

KiểuMô tả
IntegerSố nguyên trong khoảng -32,768 đến 32,767
LongSố nguyên lớn hơn Integer
DoubleSố thực (floating‑point) với độ chính xác cao
StringChuỗi ký tự
BooleanTrue hoặc False
VariantKiểu dữ liệu mặc định, có thể chứa bất kỳ kiểu nào
DateNgày tháng
ObjectTham chiếu tới một đối tượng (worksheet, range, …)

Chọn đúng kiểu dữ liệu sẽ giúp giảm lỗi và tối ưu hiệu suất.

2.3. Tham số tùy chọn (Optional) và giá trị mặc định

Bạn có thể khai báo tham số là tùy chọn bằng từ khóa Optional. Khi không truyền giá trị, tham số sẽ nhận giá trị mặc định (Empty cho Variant, 0 cho số, “” cho String, v.v.) hoặc một giá trị bạn chỉ định:

Function GiaiThua(n As Long, Optional showMsg As Boolean = False) As Long Dim i As Long, result As Long result = 1 For i = 2 To n result = result i Next i If showMsg Then MsgBox "Giai thừa của " & n & " là " & result End If GiaiThua = result
End Function

3. Các cách gọi (Call) Function trong VBA

3.1. Gọi trực tiếp trong một Sub

Đây là cách phổ biến nhất. Bạn chỉ cần viết tên hàm và truyền các đối số (nếu có). Nếu hàm trả về giá trị, bạn có thể gán nó cho một biến hoặc sử dụng ngay trong một biểu thức.

Sub DemoGoiFunction() Dim sum As Double sum = TongHaiSo(5.5, 3.2) ' Gọi hàm và gán kết quả MsgBox "Tổng = " & sum
End Sub

Lưu ý: Khi gọi hàm mà không cần giá trị trả về, bạn có thể sử dụng từ khóa Call và đặt đối số trong dấu ngoặc:

Call GiaiThua(5, True) ' Không gán kết quả, chỉ thực thi

Nếu không dùng Call, bạn phải bỏ dấu ngoặc quanh tham số:

GiaiThua 5, True ' Cú pháp này cũng hợp lệ

3.2. Gọi hàm từ một hàm khác

Bạn có thể lồng hàm trong hàm để tái sử dụng logic.

Function TinhDienTichHinhTron(radius As Double) As Double TinhDienTichHinhTron = WorksheetFunction.Pi() radius ^ 2
End Function Function TinhChuViHinhTron(radius As Double) As Double TinhChuViHinhTron = 2 WorksheetFunction.Pi() radius
End Function Sub DemoLopHinhTron() Dim r As Double: r = 4 Dim area As Double, perimeter As Double area = TinhDienTichHinhTron(r) ' Gọi hàm tính diện tích perimeter = TinhChuViHinhTron(r) ' Gọi hàm tính chu vi MsgBox "Bán kính = " & r & vbCrLf & _ "Diện tích = " & area & vbCrLf & _ "Chu vi = " & perimeter
End Sub

3.3. Gọi hàm từ một công thức trên worksheet (UDF)

Nếu bạn muốn hàm của mình có thể được sử dụng như một hàm Excel thông thường, bạn chỉ cần khai báo hàm ở một module chuẩn (Standard Module) và không sử dụng các đối tượng Excel trong hàm (tránh Application.ScreenUpdating = False trong UDF). Ví dụ:

Function TongBaSo_UDF(a As Double, b As Double, c As Double) As Double TongBaSo_UDF = a + b + c
End Function

Sau khi lưu macro, bạn có thể nhập công thức trong ô Excel:

=TongBaSo_UDF(1, 2, 3)

3.4. Gọi hàm từ một Control (Button, ComboBox…)

Khi bạn gán một macro (Sub) cho một nút bấm, trong Sub đó bạn có thể gọi hàm như bình thường.

Sub BtnTinhTong_Click() Dim result As Double result = TongHaiSo(Val(Range("A1").Value), Val(Range("B1").Value)) Range("C1").Value = result
End Sub

3.5. Gọi hàm qua Application.Run

Excel Vba Call A Function
Excel Vba Call A Function

Trong một số trường hợp (ví dụ: gọi hàm từ một workbook khác, hoặc gọi hàm có tên động), bạn có thể dùng:

Dim result As Variant
result = Application.Run("TênWorkbook.xlsm!TênModule.TenHam", arg1, arg2)

Điều này rất hữu ích khi bạn muốn thực thi hàm trong một file khác mà không mở trực tiếp.

4. Quản lý phạm vi (Scope) và khả năng truy cập

4.1. Public vs Private

  • Public: Hàm có thể được gọi từ bất kỳ module, workbook, hoặc thậm chí từ một workbook khác (kèm Application.Run).
  • Private: Hàm chỉ có thể được gọi trong cùng một module.
Public Function CongHaiSo(a As Double, b As Double) As Double CongHaiSo = a + b
End Function Private Function TruHaiSo(a As Double, b As Double) As Double TruHaiStr = a - b
End Function

Nếu bạn muốn hàm trở thành UDF, nó phải là Public và nằm trong module chuẩn (không phải trong ThisWorkbook hay Sheet).

4.2. Module chuẩn vs Module lớp (Class Module)

  • Standard Module: Dùng cho các hàm chung, UDF, và các thủ tục không gắn vào đối tượng.
  • Class Module: Khi bạn muốn tạo đối tượng tùy chỉnh, các hàm trong Class Module thường là Method và phải được gọi thông qua một instance của lớp.
' Class Module: clsCalculator
Public Function Cong(a As Double, b As Double) As Double Cong = a + b
End Function ' Trong module chuẩn
Sub DemoClass() Dim calc As New clsCalculator MsgBox calc.Cong(5, 7)
End Sub

5. Xử lý lỗi (Error Handling) trong Function

Khi một hàm gặp lỗi, tốt nhất là không để lỗi lan ra Sub gọi, mà trả về một giá trị lỗi hoặc thông báo. Hai cách phổ biến:

5.1. Sử dụng On Error GoTo

Function Chia(a As Double, b As Double) As Variant On Error GoTo ErrHandler Chia = a / b Exit Function ErrHandler: Chia = CVErr(xlErrDiv0) ' Trả về lỗi #DIV/0! trong Excel
End Function

5.2. Trả về một tuple (Array) chứa trạng thái và dữ liệu

Function LayDuLieu(ByVal key As String) As Variant Dim result(1) As Variant On Error GoTo ErrHandler result(0) = True ' Trạng thái thành công result(1) = Application.VLookup(key, Sheets("Data").Range("A:B"), 2, False) LayDuLieu = result Exit Function ErrHandler: result(0) = False result(1) = "Không tìm thấy" LayDuLieu = result
End Function

Sau đó, khi gọi:

Sub DemoLayDuLieu() Dim res As Variant res = LayDuLieu("ABC") If res(0) Then MsgBox "Giá trị: " & res(1) Else MsgBox "Lỗi: " & res(1) End If
End Sub

6. Các ví dụ thực tế

6.1. Tự động tạo báo cáo tổng hợp

Giả sử bạn có nhiều sheet chứa dữ liệu bán hàng và muốn tính tổng doanh thu cho mỗi tháng. Bạn có thể viết một hàm tổng hợp và gọi nó từ một Sub.

Function TongDoanhThu(sheetName As String, monthNum As Integer) As Double Dim ws As Worksheet Dim rng As Range, cell As Range Dim total As Double Set ws = ThisWorkbook.Worksheets(sheetName) Set rng = ws.Range("A2:A1000") ' Cột ngày For Each cell In rng If Month(cell.Value) = monthNum Then total = total + cell.Offset(0, 2).Value ' Giả sử cột C là doanh thu End If Next cell TongDoanhThu = total
End Function Sub TaoBaoCaoTong() Dim months As Variant, i As Integer, result As Double months = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) For i = LBound(months) To UBound(months) result = TongDoanhThu("BánHàng2025", months(i)) Sheets("BáoCáo").Cells(i + 1, 2).Value = result Next i MsgBox "Báo cáo đã được cập nhật."
End Sub

6.2. Hàm UDF tính ngày làm việc tiếp theo (skip weekends & holidays)

Public Function NgayLamViecTieptheo(startDate As Date, daysToAdd As Long) As Date Dim i As Long, curDate As Date Dim holidays As Range Set holidays = ThisWorkbook.Worksheets("Config").Range("Holidays") ' Danh sách ngày lễ curDate = startDate For i = 1 To daysToAdd curDate = curDate + 1 Do While Weekday(curDate, vbMonday) > 5 Or Not IsError(Application.Match(curDate, holidays, 0)) curDate = curDate + 1 Loop Next i NgayLamViecTieptheo = curDate
End Function

Sau khi lưu, bạn có thể dùng trên sheet:

=NgayLamViecTieptheo(A2, 10)

6.3. Gọi hàm từ một workbook khác

Giả sử workbook Utility.xlsm chứa hàm TinhThuong.

' Utility.xlsm - Module1
Public Function TinhThuong(a As Double, b As Double) As Double TinhThuong = a / b
End Function

Trong workbook hiện tại:

Sub DemoGoiTuWorkbookKhac() Dim result As Double result = Application.Run("'Utility.xlsm'!TinhThuong", 50, 5) MsgBox "Kết quả: " & result
End Sub

Điều này hoạt động ngay cả khi Utility.xlsm không mở (Excel sẽ mở ngầm).

7. Best Practices khi viết và gọi Function trong VBA

Thực hànhLý do
Đặt tên hàm rõ ràng, ngắn gọn, có ý nghĩaDễ đọc, bảo trì và tránh xung đột với hàm Excel có sẵn.
Sử dụng kiểu dữ liệu cụ thể (không dùng Variant nếu không cần)Nâng cao hiệu suất và giảm lỗi kiểu dữ liệu.
Luôn khai báo Option Explicit ở đầu moduleBuộc khai báo biến, tránh lỗi đánh máy.
Giới hạn phạm vi (Public/Private) hợp lýNgăn rò rỉ logic không cần thiết và giảm xung đột.
Tránh thay đổi trạng thái Excel trong UDF (ScreenUpdating, Calculation, …)Vì UDF được tính lại tự động, thay đổi này có thể gây lỗi hoặc chậm.
Xử lý lỗi trong hàm, trả về giá trị lỗi (CVErr) nếu dùng trong sheetNgười dùng sẽ thấy thông báo lỗi Excel quen thuộc (#VALUE!, #DIV/0!).
Document hàm bằng commentGiúp người khác (và bạn trong tương lai) hiểu nhanh cách dùng.
Nếu hàm trả về mảng, sử dụng Variant và khai báo ArrayĐảm bảo Excel có thể đưa ra kết quả mảng trong ô.
Kiểm tra độ dài đối số trước khi thực hiện tính toánNgăn ngừa lỗi runtime khi dữ liệu không hợp lệ.
Sử dụng ByVal cho các đối số không cần thay đổiTránh sửa đổi dữ liệu không mong muốn và tăng tốc.
Đối với hàm cần truy cập workbook/worksheet, truyền đối tượng làm đối sốGiảm phụ thuộc vào ActiveSheet/ActiveWorkbook.

8. Tổng kết

Việc call a function trong Excel VBA không chỉ là một thao tác kỹ thuật đơn giản mà còn là nền tảng để xây dựng các giải pháp tự động hoá mạnh mẽ. Từ việc định nghĩa một hàm cơ bản, quản lý phạm vi, xử lý lỗi, cho tới việc tạo UDF có thể sử dụng trực tiếp trên worksheet, mỗi bước đều có những chi tiết quan trọng cần lưu ý.

Trong thực tế, bạn sẽ thường gặp các tình huống:

  • Tái sử dụng logic: Thay vì sao chép mã, bạn đóng gói vào hàm và gọi lại ở nhiều nơi.
  • Tối ưu hiệu suất: Hàm được viết hiệu quả sẽ giảm thời gian tính toán, đặc biệt khi làm việc với dữ liệu lớn.
  • Tương tác giữa các workbook: Application.Run mở ra khả năng xây dựng hệ thống macro phân tán.
  • Tích hợp với UI: Gọi hàm từ button, combo box, hoặc form giúp người dùng cuối thao tác dễ dàng.

Hy vọng qua bài viết chi tiết trên, bạn đã nắm vững cách tạo, gọi và quản lý các Function trong Excel VBA. Hãy áp dụng những kiến thức này vào dự án thực tế, liên tục tối ưu và mở rộng để đạt được hiệu suất và tính ổn định tối đa. Chúc bạn thành công trong hành trình lập trình VBA!

⚠️
LƯU Ý QUAN TRỌNG: Miễn trừ trách nhiệm: Mặc dù chúng tôi luôn nỗ lực để đảm bảo tính chính xác và cập nhật của thông tin, nhưng các quy định về giáo dục và tuyển sinh có thể thay đổi theo thời gian. BigSchool không chịu trách nhiệm về bất kỳ sai sót nào hoặc kết quả phát sinh từ việc sử dụng thông tin trên trang này. Độc giả nên liên hệ trực tiếp với nhà trường hoặc cơ quan chức năng để có thông tin mới nhất. Ngoài ra, BigSchool tuyệt đối không bán sản phẩm, khóa học hay cung cấp dịch vụ được nhắc đến trong bài.

Viết một bình luận