2009-07-05 9 views
17

Mam Word userform z ponad 60 kontrolkami różnych typów. Chciałbym ocenić formularz za każdym razem, gdy zostanie wywołane zdarzenie control_change i zmienić włączony stan przycisku przesyłania formularza. Jednak naprawdę nie chcę pisać i obsługiwać 60 programów obsługi zdarzeń zmian.VBA: Używanie WithEvents na UserForms

Odpowiedz

2

W takim przypadku masz kilka opcji, ponieważ obsługi zdarzeń nie mogą być udostępniane w VBA/VB6

Wariant 1: użyć funkcji manipulacja centralny, który nazywany jest od każdej procedury obsługi zdarzenia.

Sub Control1_ChangeEvent() 
    CommonChangeEvent // Just call the common handler, parameters as needed 
End Sub 

Sub Control2_ChangeEvent() 
    CommonChangeEvent 
End Sub 
... 
Sub CommonChangeEvent(/* Add necessary parameters */) 
    //Do the heavy lifting here 
End Sub 

Opcja 2: Organizowanie elementów sterujących w układach sterowania.

Sub TextBox_ChangeEvent(Index As Integer) 
    CommonChangeEvent 
End Sub 

Sub OtherControlType_ChangeEvent(Index As Integer) 
    CommonChangeEvent 
End Sub 

Łącząc obie opcje całkowity licznik obsługi zdarzeń będzie znacznie kurczyć, a pozostałe teleskopowe są tylko bezmózgowymi odcinki na jednej prawdziwej obsługi zdarzeń.

+5

Opcja 2 nie jest w tym przypadku opcją. VBA nie obsługuje tablic kontrolnych. –

21

Można utworzyć klasę zdarzeń-zdarzenia, która będzie zawierała kod obsługi zdarzeń dla wszystkich kontrolek określonego typu.

Na przykład utworzyć klasę o nazwie TextBoxEventHandler następująco:

Private WithEvents m_oTextBox as TextBox 

Public Property Set TextBox(ByVal oTextBox as TextBox) 
    Set m_oTextBox = oTextBox 
End Property 

Private Sub m_oTextBox_Change() 
    ' Do something 
End Sub 

Teraz trzeba utworzyć & zahaczyć instancję tej klasy dla każdej kontroli odpowiedniego typu na formularzu:

Private m_oCollectionOfEventHandlers As Collection 

Private Sub UserForm_Initialise() 

    Set m_oCollectionOfEventHandlers = New Collection 

    Dim oControl As Control 
    For Each oControl In Me.Controls 

     If TypeName(oControl) = "TextBox" Then 

      Dim oEventHandler As TextBoxEventHandler 
      Set oEventHandler = New TextBoxEventHandler 

      Set oEventHandler.TextBox = oControl 

      m_oCollectionOfEventHandlers.Add oEventHandler 

     End If 

    Next oControl 

End Sub 

Zauważ, że powodem, dla którego musisz dodać instancje obsługi zdarzeń do kolekcji, jest po prostu upewnienie się, że są one przywoływane, a tym samym nie zostaną odrzucone przez garbage collector, zanim skończysz z nimi.

Oczywiście tę technikę można rozszerzyć, aby poradzić sobie z innymi rodzajami kontroli. Można mieć oddzielne klasy obsługi zdarzeń dla każdego typu lub można użyć jednej klasy, która ma zmienną składową (i związaną z nią właściwość obsługi zdarzenia &) dla każdego z typów kontrolek, które należy obsłużyć.

+0

Kod działa świetnie. Czy jednak można to zrobić na tej samej formie użytkownika bez tworzenia oddzielnej klasy? – Alex

+0

@Alex: Nie, ponieważ potrzebujesz * instancji * klasy dla każdej kontrolki. W przeciwnym razie moduł obsługi zdarzenia nie będzie wiedział, dla której kontroli dotyczy wydarzenie. Jeśli tylko programy obsługi zdarzeń miały parametr "nadawcy", np. Obsługa zdarzeń C# ... –

+0

@GaryMcGill, wiem, że to jakiś czas temu (dobrze, dawno temu :)), ale dynamicznie dodam comboboxes w moim arkuszu. Zastanawiałem się, czy mogę zastosować to samo podejście do arkusza niż formularza? [Oto moje pytanie] (http://stackoverflow.com/questions/40340345/assign-code-to-change-method-of-a-combobox) – Zac