Cách trả về kết quả từ hàm VBA


277

Làm thế nào để tôi trả về một kết quả từ một chức năng?

Ví dụ:

Public Function test() As Integer
    return 1
End Function

Điều này đưa ra một lỗi biên dịch.

Làm thế nào để tôi thực hiện chức năng này trả về một số nguyên?


Câu trả lời:


429

Đối với các kiểu trả về không phải đối tượng, bạn phải gán giá trị cho tên hàm của mình, như thế này:

Public Function test() As Integer
    test = 1
End Function

Ví dụ sử dụng:

Dim i As Integer
i = test()

Nếu hàm trả về một loại Đối tượng, thì bạn phải sử dụng Settừ khóa như thế này:

Public Function testRange() As Range
    Set testRange = Range("A1")
End Function

Ví dụ sử dụng:

Dim r As Range
Set r = testRange()

Lưu ý rằng việc gán giá trị trả về cho tên hàm không chấm dứt việc thực thi hàm của bạn. Nếu bạn muốn thoát khỏi chức năng, thì bạn cần phải nói rõ ràng Exit Function. Ví dụ:

Function test(ByVal justReturnOne As Boolean) As Integer
    If justReturnOne Then
        test = 1
        Exit Function
    End If
    'more code...
    test = 2
End Function

Tài liệu: http://msdn.microsoft.com/en-us/l Library / office / gg264233% 28v = office.14% 29.aspx


32
Để đầy đủ, cần lưu ý rằng khi bạn trả về một đối tượng ( Rangeví dụ như ví dụ), bạn cần sử dụng Setgiống như bạn sẽ làm nếu đặt một biến đối tượng trong một phương thức thông thường. Vì vậy, nếu, ví dụ, "test" là một hàm trả về Phạm vi, câu lệnh return sẽ giống như thế này set test = Range("A1").
Jay Carr

Tại sao đó là @JayCarr?
PsychoData

4
@PologistsoData - Đơn giản vì đó là cách bạn đặt một biến đối tượng nói chung và thực hiện nó mà không setcó thể dẫn đến các vấn đề. Tôi đã có vấn đề khi làm điều đó mà không có, nhưng nếu tôi sử dụng thì settôi không :).
Jay Carr

1
Tôi nghĩ điều đáng nói là hành vi của hàm sẽ khác khi bạn gọi nó từ bảng tính, so với việc gọi nó từ một hàm VBA hoặc Sub khác.
Doug Jenkins

2
Khi được gọi trong VBA, hàm sẽ trả về một đối tượng phạm vi, nhưng khi được gọi từ một bảng tính, nó sẽ chỉ trả về giá trị, do đó, set test = Range("A1")chính xác tương đương với test = Range("A1").Value, trong đó "test" được định nghĩa là Biến, thay vì Phạm vi.
Doug Jenkins

86

Các hàm VBA coi chính tên hàm là một loại biến. Vì vậy, thay vì sử dụng returncâu lệnh "", bạn chỉ cần nói:

test = 1

Mặc dù vậy, lưu ý rằng điều này không thoát ra khỏi chức năng. Bất kỳ mã nào sau câu lệnh này cũng sẽ được thực thi. Do đó, bạn có thể có nhiều câu lệnh gán gán các giá trị khác nhau testvà bất kể giá trị là gì khi bạn đạt đến cuối hàm sẽ là giá trị được trả về.


Trên thực tế, bạn đã trả lời câu hỏi rõ ràng hơn với thông tin bổ sung (có thể tiềm ẩn dẫn đến một câu hỏi khác từ người mới đến VBA). Giữ thành tốt công việc
Adarsha

Xin lỗi, có vẻ như bạn vừa trả lời giống như câu trả lời của tôi, điều mà tôi đã có trước, nhưng chỉ cần thêm một thực tế là nó không thoát ra khỏi chức năng. Đó là một bổ sung tốt đẹp, tôi chỉ nghĩ rằng nó sẽ phù hợp hơn như là một nhận xét. Tôi không chắc chắn về nghi thức đúng đắn là gì, tôi đoán rằng nó hơi thô lỗ khi hạ thấp chỉ vì điều đó là một câu trả lời hay, nhưng nó sẽ không cho phép tôi hoàn tác nó.
Dân

41

Chỉ cần đặt giá trị trả về cho tên hàm vẫn không hoàn toàn giống với câu lệnh Java (hoặc khác) return, bởi vì trong java, returnthoát khỏi hàm, như thế này:

public int test(int x) {
    if (x == 1) {
        return 1; // exits immediately
    }

    // still here? return 0 as default.
    return 0;
}

Trong VB, tương đương chính xác mất hai dòng nếu bạn không đặt giá trị trả về ở cuối hàm . Vì vậy, trong VB, hệ quả chính xác sẽ như thế này:

Public Function test(ByVal x As Integer) As Integer
    If x = 1 Then
        test = 1 ' does not exit immediately. You must manually terminate...
        Exit Function ' to exit
    End If

    ' Still here? return 0 as default.
    test = 0
    ' no need for an Exit Function because we're about to exit anyway.
End Function 

Vì đây là trường hợp, thật tuyệt khi biết rằng bạn có thể sử dụng biến trả về như bất kỳ biến nào khác trong phương thức. Như thế này:

Public Function test(ByVal x As Integer) As Integer

    test = x ' <-- set the return value

    If test <> 1 Then ' Test the currently set return value
        test = 0 ' Reset the return value to a *new* value
    End If

End Function 

Hoặc, ví dụ cực đoan về cách biến trả về hoạt động (nhưng không nhất thiết là một ví dụ hay về cách bạn thực sự nên viết mã). Đây là một ví dụ sẽ giúp bạn thức dậy vào ban đêm:

Public Function test(ByVal x As Integer) As Integer

    test = x ' <-- set the return value

    If test > 0 Then

        ' RECURSIVE CALL...WITH THE RETURN VALUE AS AN ARGUMENT,
        ' AND THE RESULT RESETTING THE RETURN VALUE.
        test = test(test - 1)

    End If

End Function

2
"Thật tuyệt khi biết rằng bạn có thể sử dụng biến trả về như bất kỳ biến nào khác trong phương thức" hầu hết là đúng - nhưng ví dụ: nếu kiểu trả về là Variantvà mục tiêu của bạn là trả về một mảng thì một cái gì đó giống như ReDim test(1 to 100)sẽ gây ra lỗi. Ngoài ra, mặc dù nó tốt để điều trị loại hình cơ bản như Integersnhư vậy nó được coi là hơi unidiomatic. Nó làm cho mã khó đọc hơn. Các lập trình viên VBA quét các dòng gán cho tên hàm để hiểu hàm làm gì. Sử dụng tên hàm như một biến thông thường không cần thiết che khuất điều này.
John Coleman

@JohnColeman, hoàn toàn đồng ý ở cả hai điểm. Không có nghĩa là ví dụ cuối cùng là một trong những phương pháp được khuyến nghị. Nhưng, câu hỏi chủ đề liên quan đến Cách trả về một biến và vì vậy đây chỉ là một nỗ lực nhằm giải thích đầy đủ về kết quả trả về của VB và bằng cách mở rộng cách chúng hoạt động. Chắc chắn trường hợp cuối cùng không phải là một khuyến nghị. (Tôi chắc chắn sẽ không viết mã nhiều hơn một ví dụ.) Vì vậy, điểm của bạn được thực hiện tốt và bổ sung tốt. Cảm ơn bạn.
LimaNightHawk

hữu ích cho các chức năng smallish, và là điều mà bất kỳ lập trình VBA nên biết về, vì vậy tôi đã không có vấn đề với bạn nhắc đến nó. Tôi chỉ nghĩ rằng nên đưa vào một cảnh báo.
John Coleman

Cảm ơn giải thích làm thế nào Exit Functionliên quan đếnreturn
Austin D

@JohnColeman, Rõ ràng, bạn không thể ReDim test(1 to 100)không gây ra lỗi đơn giản vì 'test' không được khai báo là một mảng! và không có lý do nào khác! Bạn không thể khai báo một hàm như một mảng. Khai báo nó dưới dạng a Variant, sau đó chỉ cần xây dựng mảng đầu ra của bạn (nó có thể là Động hoặc Tĩnh) bên trong hàm này testvà sau đó gán ("=") mảng này testlàm giá trị trả về. Để tiếp tục thao tác, như ReDiming nó, bạn cần gán giá trị được trả về cho một biến, ví dụ Dim x as Variantvà gọi x = test, sau đó xlà những gì bạn đã thực hiện test!
Gene

-6

Đoạn mã dưới đây lưu trữ giá trị trả về vào biến retValvà sau đó MsgBoxcó thể được sử dụng để hiển thị giá trị:

Dim retVal As Integer
retVal = test()
Msgbox retVal
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.