Существует ли эквивалент CallByName для глобальных функций? - PullRequest
3 голосов
/ 04 марта 2009

Я хочу сделать это: «Если есть модуль X , содержащий функцию Y , то вызовите его, в противном случае - нет».

Я знаю, что могу использовать CallByName(Object, MethodName, ...) для вызова метода или свойства экземпляра объекта.

Можно ли вызвать глобальную подпрограмму / функцию, которая не связана с объектом?

//Module1
Public Sub DoSomething
End Sub

//Module2
Public Sub TriggerDoSomething
  On Error Resume Next
  CallByName2 "Module1", "DoSomething", ...
End Sub

Я знаю, что было бы лучше провести рефакторинг моего кода, чтобы обернуть DoSomething в класс, но в настоящее время это невозможно, так как это может нарушить код моих коллег таким образом, который не может быть исправлен за несколько часов .

Ответы [ 4 ]

4 голосов
/ 04 марта 2009

Действительно, CallByName было бы проще - не могли бы вы просто обернуть модуль (-и) классом, который перенаправляет вызовы в модуль?

Можно вызывать подпрограммы в модулях по имени, используя FunctionDelegator. Это объясняется в превосходной книге Мэтта Курланда Advanced Visual Basic 6 .

Google может найти вам хаков с помощью CallWindowProc, но Мэтт Керланд говорит, что это опасно. Что в значительной степени последнее слово по этому вопросу:)


РЕДАКТИРОВАТЬ: ответ RS Conley не использует модуль, используйте класс, который имеет свойство экземпляра GlobalMultiUse, и вы сможете использовать CallByName. Это будет работать, если ваш код находится в DLL, а не в EXE. RS Conley предлагает в любом случае более гибко иметь минимальный EXE-файл с почти всеми функциями в DLL: это вполне может быть правдой.

1 голос
/ 12 мая 2011

Это должно сделать это, ребята. Я принимаю пожертвования.

Public Sub callbyname2(proc As String)
    Dim vbComp As VBComponent
     For Each vbComp In ActiveWorkbook.VBProject.VBComponents
        On Error Resume Next
        Application.Run (vbComp.name & "." & proc)
        If Err.Number <> 1004 Then
            Exit For
        End If
    Next
End Sub
1 голос
/ 04 марта 2009

Не используйте модуль, используйте класс со свойством экземпляра GlobalMultiUse, и вы сможете использовать CallbyName

1 голос
/ 04 марта 2009

Может ли условная компиляция быть в порядке для вашей проблемы?

//Module2
Public Sub TriggerDoSomething
    #If DoSomething_IsPresent Then
        DoSomething
    #End if
End Sub

Затем в настройках вашего проекта вы добавите следующие аргументы условной компиляции:

  • Если DoSomething присутствует: DoSomething_IsPresent = -1
  • Если DoSomething отсутствует: DoSomething_IsPresent = 0

Кстати, будьте осторожны с «При появлении ошибки далее» в:

//Module2
Public Sub TriggerDoSomething
  On Error Resume Next
  CallByName2 "Module1", "DoSomething", ...
End Sub

Если DoSomething присутствует в Module1, но имеет необработанную ошибку, вы не заметите ее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...