2013-04-11 13 views
9

Poniżej znajduje się pytanie, na które odpowiem sam, jednak spowodowało to WIELKA porcja frustracji i miałem wiele problemów z wyszukiwaniem go w sieci, więc jestem delegowania tutaj w nadziei, oszczędzając trochę czasu & wysiłek dla innych, a może dla siebie, jeśli zapomnę to w przyszłości:

dla VBA (w moim przypadku, MS Excel), deklaracja Public ma uczynić zmienną (lub funkcja) dostępna globalnie przez inne funkcje lub podprogramy w tym module, jak również w każdym innym module.
Okazało się, że to nie jest prawda, w przypadku Forms
, i podejrzewam też, że w Sheets, ale nie zweryfikowałem tego ostatniego.

W skrócie, następujące NIE utworzy publiczną, dostępną zmienna gdy tworzony w Form, a więc upaść, mówiąc, że zmienne bYesNo i dRate są niezdefiniowane w mModule1:
Zmienne publiczne NIE są NAPRAWDĘ publiczne w VBA w Formularzach

(inside fMyForm) 
Public bYesNo As Boolean` 
Public dRate As Double 

Private Sub SetVals() 
    bYesNo = Me.cbShouldIHaveADrink.value 
    dRate = CDec(Me.tbHowManyPerHour.value) 
End Sub 
(Presume the textbox & checkbox are defined in the form) 

(inside mModule1) 
Private Sub PrintVals() 
    Debug.Print CStr(bYesNo) 
    Debug.Print CStr(dRate) 
End Sub 


jeśli jednak dokonać zmiany nieznaczne poniżej, to wszystko działa prawidłowo:

(inside fMyForm) 

Private Sub SetVals() 
    bYesNo = Me.cbShouldIHaveADrink.value 
    dRate = CDec(Me.tbHowManyPerHour.value) 
End Sub 
(Presume the textbox & checkbox are defined in the form) 

(inside mModule1) 
Public bYesNo As Boolean` 
Public dRate As Double 
Private Sub PrintVals() 
    Debug.Print CStr(bYesNo) 
    Debug.Print CStr(dRate) 
End Sub 


mModule1 zadziała perfekcyjnie i przy założeniu, że fMyForm zawsze nazywa, potem przez czas rutynowych PrintVals uruchomieniu wartości z pola tekstowego i wyboru w formularzu zostaną prawidłowo niewoli.

Szczerze nie mogę ewentualnie pojąć co MS myślał o tej zmianie, ale brak spójności jest ogromny ssać efektywności idiosyncracies takich jak te, które są tak słabo udokumentowane, że wyszukiwarka Google w 2013 roku za coś, co ma prawdopodobnie nauki już od dziesięciu lat jest tak trudnym zadaniem do przeszukania.

+3

Moduły użytkowe i moduły arkusza to moduły obiektów: nie zachowują się tak samo, jak zwykły moduł. Możesz jednak odnieść się do zmiennej w userform w podobny sposób, w jaki sposób odwołasz się do właściwości klasy. W twoim przykładzie odwołanie do 'fMyForm.bYesNo' będzie działało dobrze. Jeśli nie zadeklarowałbyś bYesNo jako Publicznego, kod nie byłby widoczny dla kodu spoza formularza, więc kiedy robisz to Publicznie, to naprawdę różni się od niepublicznego. –

+3

Jest to znany fakt, że jeśli chcesz prawdziwe publiczne zmienne, musisz zadeklarować je w module kodu, a nie w obszarze Kod formularza/arkusza. Zobacz ten link http://msdn.microsoft.com/en-us/library/office/gg264241.aspx 'Zmiennych publicznych można używać w dowolnych procedurach w projekcie. Jeśli publiczna zmienna jest zadeklarowana w standardowym module lub module klasy, może być również używana w dowolnych projektach, które odwołują się do projektu, w którym zadeklarowano publiczną zmienną. " –

+0

Odnośnie ostatniego komentarza", który jest tak słabo udokumentowany, że wyszukiwarka Google w 2013 roku coś, co prawdopodobnie istnieje od dekady lub dłużej, jest tak trudne do przeszukania. "Może szukasz czegoś używając niewłaściwego słowa kluczowego? Spróbuj przeszukać to w Google? 'msdn VBA deklaruje publiczne zmienne';) –

Odpowiedz

2

pierwszy komentarz:

moduły UserForm i arkusz są moduły obiektu: oni nie zachowują się w ten sam sposób jak zwykły moduł. Możesz jednak odnieść się do zmiennej w userform w podobny sposób, w jaki sposób odwołasz się do właściwości klasy. W twoim przykładzie odwołanie do fMyForm.bYesNo działałoby poprawnie. Jeśli nie zadeklarowałbyś bYesNo jako Publicznego, kod nie byłby widoczny dla kodu spoza formularza, więc kiedy robisz to Publicznie, to naprawdę różni się od niepublicznego. - Tim Williams 11 kwietnia '13 w 21:39

jest rzeczywiście poprawna odpowiedź ...

+1

Proszę oznaczyć tę odpowiedź jako "odpowiedź społeczności" –

0

jako szybki dodatek odpowiedzi na odpowiedź społeczności, tylko dla heads-up:

Kiedy tworzysz swoje formularze, możesz użyć samego obiektu formularza lub możesz utworzyć nowe wystąpienie obiektu formularza, używając polecenia Nowy i umieszczając go w zmiennej. Ta ostatnia metoda jest czystsza IMO, ponieważ sprawia to, że użycie jest mniej jednolite.

Jednak w formularzu użytkownika wywołanie funkcji Zwolnij (ja), wszyscy członkowie publiczni zostaną wyczyszczeni.Tak więc, jeśli Twój kod wygląda tak:

Dim oForm as frmWhatever 
    Set oForm = New frmWhatever 
    Call oForm.Show(vbModal) 
    If Not oForm.bCancelled Then ' <- poof - bCancelled is wiped clean at this point 

Rozwiązanie używam, aby temu zapobiec, i jest to miła alternatywa rozwiązanie dla PO jak dobrze jest, aby uchwycić wszystkie IO z postaci (czyli wszystkich członków publicznych) do oddzielnej klasy i użyj instancji tej klasy do komunikacji z formularzem. Tak więc np.

Dim oFormResult As CWhateverResult 
    Set oFormResult = New CWhateverResult 
    Dim oForm as frmWhatever 
    Set oForm = New frmWhatever 
    Call oForm.Initialize(oFormResult) 
    Call oForm.Show(vbModal) 
    If Not oFormResult.bCancelled Then ' <- safe 
Powiązane problemy