2009-03-04 3 views
3

Ich möchte dies tun: "Wenn es ein Modul ist X mit einer Funktion Y dann rufen Sie es, sonst nicht."Gibt es ein CallByName-Äquivalent für globale Funktionen?

Ich bin mir bewusst, dass ich CallByName(Object, MethodName, ...) verwenden kann, um eine Methode oder eine Eigenschaft einer Objektinstanz aufzurufen.

Kann man ein globales Sub/Function aufrufen, das nicht an ein Objekt gebunden ist?

//Module1 
Public Sub DoSomething 
End Sub 

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

Ich weiß, es wäre besser, meinen Code Refactoring DoSomething in eine Klasse wickeln, aber zur Zeit ist dies nicht möglich, da es den Code meiner Mitarbeiter in einer Art und Weise brechen würde, die nicht in einem festen könnte wenige Stunden.

Antwort

3

Es wäre wirklich einfacher CallByName eine Klasse - können Sie nicht einfach die Module mit einer Klasse umhüllen, die die Aufrufe an das Modul umleitet?

Es ist möglich, Routinen in Modulen namentlich mit einem FunctionDelegator aufzurufen. Dies wird in Matt Curlands ausgezeichnetem Buch Advanced Visual Basic 6 erklärt.

Googling könnte Sie einige Hacks mit CallWindowProc finden, aber Matt Curland sagt, dass das gefährlich ist. Die so ziemlich das letzte Wort in der Sache :)

ist

EDIT: RS Conley Antwort eine Klasse kein Modul verwenden, verwenden, die eine Instanz Eigenschaft von GlobalMultiUse hat und Sie werden CallByName nutzen können. Dies funktioniert, wenn sich der Code in einer DLL und nicht in einer EXE befindet. RS Conley schlägt in jedem Fall vor, eine minimale EXE mit fast allen Funktionen in einer DLL zu haben: das mag stimmen.

1

Könnte die konditionelle Kompilation für Ihr Problem in Ordnung sein?

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

dann in den Projekteinstellungen würden Sie die folgenden conditionnal Kompilierung Argumente hinzufügen:

  • Wenn DoSomething vorhanden ist: DoSomething_IsPresent = -1
  • Wenn DoSomething nicht vorhanden ist: DoSomething_IsPresent = 0

Übrigens, seien Sie vorsichtig mit dem "On Error Resume Next“in:

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

Wenn DoSomething in Module1 ist, aber ein nicht behandelter Fehler Sie werden es nicht bemerken.

1

Sie kein Modul verwenden, eine Klasse verwenden, die eine Instanz Eigenschaft von GlobalMultiUse hat und Sie werden CallByName verwenden

+0

Schöne Idee. Wird die Klasse nicht in ein DLL-Projekt verschoben? Was Sie tun könnten & es würde den Client-Code des Moduls nicht brechen. Ich konnte es in einer EXE nicht schaffen. (Musste zu ActiveX exe wechseln, um sogar Klasse auf GlobalMultiUse zu setzen.) – MarkJ

+0

Korrigieren Sie, ob sich die Klasse in einer EXE befindet. Ich mache das selten mehr und bevorzuge mindestens ein EXE, das mit einer DLL verknüpft ist. Es ist nur flexibler auf diese Weise. –

+0

Sie könnten Recht haben. Vielleicht sollten Sie die Antwort bearbeiten, um das zu erklären? Es ist möglich, DR hat nicht bereits den Code in einer DLL. BTW Wenn Sie keine Einwände haben, werde ich meine Antwort bearbeiten, um Ihre Idee zu integrieren. Hinterlasse einen Kommentar, wenn du möchtest, dass ich es herausnehme. Ich habe +1 auf deine Antwort. – MarkJ

1

Das Lage sein sollte, es Leute tun. Ich akzeptiere Spenden.

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 
+0

'ActiveWorkbook' ist Teil des Excel-Objektmodells, wenn ich mich richtig erinnere, also ist das nicht dieser VBA-Code statt VB6-Code? –

+0

absolut. Aber wenn Sie Excel/Office nicht verwenden müssen, sollten Sie VB nicht verwenden, denke ich – nicolas

Verwandte Themen