2011-09-13 50 views
8

Tôi đang cố gọi một hàm có tên biến được tạo tại thời gian chạy dựa trên giá trị hộp tổ hợp. Điều này là đơn giản trong hầu hết các ngôn ngữ nhưng tôi dường như không thể tìm ra nó trong Excel VBA, tôi nghi ngờ điều này là bởi vì tôi không thực sự hiểu cách trình biên dịch hoạt động. Tôi đã tìm thấy một số bài viết được đóng nhưng không hoàn toàn dường như làm các trick. Mã dưới đây là sai nhưng nên đưa ra một ý tưởng về những gì tôi muốn.Chức năng gọi hàm VBA Excel có tên biến

Cảm ơn

Sub main() 
    'run formatting macros for each institution on format button click 

    Dim fn As String 
    Dim x As Boolean 

    'create format function name from CB value   
    fn = "format_" & CBinst.Value 

    'run function that returns bool 
    x = Eval(fn) 

    ... 

End Sub 

Trả lời

15

CallByName là những gì bạn sẽ cần phải hoàn thành nhiệm vụ.

dụ: Mã trong Sheet1

Option Explicit 
Public Function Sum(ByVal x As Integer, ByVal y As Integer) As Long 
    Sum = x + y 
End Function 

Mã là Module1 (bas mô-đun)

Option Explicit 

Sub testSum() 
Dim methodToCall As String 
methodToCall = "Sum" 

MsgBox CallByName(Sheet1, methodToCall, VbMethod, 1, 2) 
End Sub 

Chạy phương pháp testSum gọi phương thức Sum sử dụng tên của phương pháp được đưa ra trong một biến chuỗi , chuyển 2 tham số (1 và 2). Giá trị trả về của hàm gọi hàm được trả về dưới dạng đầu ra của CallByName.

+0

Rất đẹp. Tôi đã cố gắng Đánh giá, vì tôi không biết điều đó. –

+0

Tuyệt vời, cảm ơn! – BWG

+0

Hi .. nếu tôi không muốn chức năng 'tổng' trong Sheet1 .. nhưng nói trong Module1. Làm thế nào tôi có thể gọi Module1 'tổng' chức năng bằng cách sử dụng CallByName. Điều này dường như không hoạt động. Xin cho biết. – ihightower

0

Bạn nên viết một hàm chấp nhận giá trị CB như một tham số và sau đó sử dụng một trường hợp chọn để gọi hàm định dạng thích hợp.

Something tương tự như sau

Function SelectFormatting(Name as String) As Boolean 
Select Case CBinst.Value 
Case "Text1": 
    SelectFormatting = Text1FormattingFunction() 
Case "Text2": 
    . 
    . 
    . 
End Select 
End Function 
+0

Cảm ơn cho câu trả lời Với. Đây thực sự là cách đơn giản để giải quyết vấn đề này. Tôi hy vọng sẽ có thêm trường hợp cho mỗi giá trị CB vì hai lý do: 1) mã sẽ được cập nhật thường xuyên bởi những người có khả năng mã hóa khác nhau và sẽ tốt hơn nếu cho phép họ thêm tùy chọn và định dạng CB mới chức năng mà không cần chạm vào ruột của chương trình và 2) danh sách CB có thể trở nên khá dài. Có lẽ đây chỉ là vô lý về kỹ thuật. – BWG

1

trên sẽ làm việc nhưng không phải với một số lượng lớn các tên

Sử dụng Application.Run (MacroName, thông số)

Bạn phải có thể chắc chắn rằng có một vĩ mô nhưng nó là tốt hơn so với ở trên vì không có câu lệnh chọn nào.

0

đối với câu trả lời của tôi ở trên, bạn cũng có thể tìm thấy hữu ích này để kiểm tra xem các vĩ mô tồn tại

'================================================================================= 
'- CHECK IF A MODULE & SUBROUTINE EXISTS 
'- VBA constant : vbext_pk_Proc = All procedures other than property procedures. 
'- An error is generated if the Module or Sub() does not exist - so we trap them. 
'--------------------------------------------------------------------------------- 
'- VB Editor : Tools/References - add reference TO ...... 
'- .... "Microsoft Visual Basic For Applications Extensibility" 
'---------------------------------------------------------------------------------- 
'- Brian Baulsom October 2007 
'================================================================================== 
Sub MacroExists() 
    Dim MyModule As Object 
    Dim MyModuleName As String 
    Dim MySub As String 
    Dim MyLine As Long 
    '--------------------------------------------------------------------------- 
    '- test data 
    MyModuleName = "TestModule" 
    MySub = "Number2" 
    '---------------------------------------------------------------------------- 
    On Error Resume Next 
    '- MODULE 
    Set MyModule = ActiveWorkbook.VBProject.vbComponents(MyModuleName).CodeModule 
    If Err.Number <> 0 Then 
    MsgBox ("Module : " & MyModuleName & vbCr & "does not exist.") 
    Exit Sub 
    End If 
    '----------------------------------------------------------------------------- 
    '- SUBROUTINE 
    '- find first line of subroutine (or error) 
    MyLine = MyModule.ProcStartLine(MySub, vbext_pk_Proc) 
    If Err.Number <> 0 Then 
    MsgBox ("Module exists  : " & MyModuleName & vbCr _ 
      & "Sub " & MySub & "() : does not exist.") 
    Else 
    MsgBox ("Module : " & MyModuleName & vbCr _ 
     & "Subroutine : " & MySub & vbCr _ 
     & "Line Number : " & MyLine) 
    End If 
End Sub 
'----------------------------------------------------------------------------------- 
Các vấn đề liên quan