2013-04-11 14 views
9

Di seguito è una domanda che risponderò a me stesso, tuttavia ha causato un GRANDE affare di frustrazione per me e ho avuto un sacco di problemi a cercarlo sul web, quindi sono distacco qui nella speranza di salvare un po 'di tempo & sforzo per gli altri, e forse per me stesso, se non ricordo questo in futuro:

per VBA (nel mio caso, MS Excel), la dichiarazione Public si suppone faccia la variabile (o funzione) accessibile globalmente da altre funzioni o subroutine in quel modulo, così come in qualsiasi altro modulo.

Risulta che questo non è vero, nel caso di Forms
, e ho il sospetto anche in Sheets, ma non ho verificato quest'ultimo.

In breve, il seguente non creerà un pubblico, variabili accessibili quando creati in un Form, e sarà quindi in crash, dicendo che le variabili bYesNo e drate non sono definite in mModule1:
Le variabili pubbliche non sono VERAMENTE pubbliche in VBA in Moduli

(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 


Tuttavia, se si effettua la leggera alterazione di sotto, tutto funzionerà bene:

(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 funziona perfettamente soddisfacente e, supponendo che il fMyForm è sempre chiamato prima, poi con il tempo la routine PrintVals viene eseguito, i valori del testo e casella nel modulo saranno adeguatamente catturate.

Onestamente non riesco a capire cosa MS stava pensando con questo cambiamento, ma la mancanza di coerenza è un'enorme aspirazione all'efficienza, l'apprendimento di idiosincrasie come queste, che sono così scarsamente documentate che una ricerca di Google nel 2013 per qualcosa che è probabile è stato in giro per un decennio o più è così difficile da cercare.

+3

I moduli Userform e Sheet sono moduli Object: non si comportano allo stesso modo di un modulo normale. Puoi comunque fare riferimento a una variabile in un userform in modo simile a come faresti riferimento a una proprietà di classe. Nel tuo esempio riferito a 'fMyForm.bYesNo' funzionerebbe bene. Se non avessi dichiarato bYesNo come pubblico, non sarebbe visibile al codice al di fuori del modulo, quindi quando lo rendi pubblico è in realtà diverso da non pubblico. –

+3

È noto che se si desiderano vere variabili pubbliche è necessario dichiararle in un modulo di codice e non nell'area di codice Modulo/Foglio. Vedi questo link http://msdn.microsoft.com/en-us/library/office/gg264241.aspx 'Le variabili pubbliche possono essere utilizzate in qualsiasi procedura del progetto. Se una variabile pubblica è dichiarata in un modulo standard o in un modulo di classe, può essere utilizzata anche in tutti i progetti che fanno riferimento al progetto in cui è dichiarata la variabile pubblica. –

+0

Per quanto riguarda l'ultimo commento, che sono così scarsamente documentati che una ricerca di Google nel 2013 per qualcosa che è probabilmente in giro da un decennio o più è così difficile da cercare. Forse stai cercando usando la parola chiave sbagliata? Prova a cercare questo in Google? 'msdn VBA dichiara variabili pubbliche';) –

risposta

2

primo commento:

form e sonore moduli sono moduli di oggetto: tuttavia non si comportano allo stesso modo di un modulo regolare. Puoi comunque fare riferimento a una variabile in un userform in modo simile a come faresti riferimento a una proprietà di classe. Nel tuo esempio riferito a fMyForm.bYesNo funzionerebbe bene. Se non avessi dichiarato bYesNo come pubblico, non sarebbe visibile al codice al di fuori del modulo, quindi quando lo rendi pubblico è in realtà diverso da non pubblico. - Tim Williams 11 aprile '13 a 21:39

è in realtà una risposta corretta ...

+1

Si prega di contrassegnare questa risposta come" risposta della comunità " –

0

Come un rapido add-on risposta alla risposta della comunità, solo per un heads-up:

Quando si istanziano i moduli, è possibile utilizzare l'oggetto modulo stesso oppure è possibile creare una nuova istanza dell'oggetto modulo utilizzando New e inserendolo in una variabile. L'ultimo metodo è IMO più pulito, poiché questo rende l'utilizzo meno singleton-ish.

Tuttavia, quando nel proprio userform si chiama Unload (Me), tutti i membri pubblici verranno cancellati.Quindi, se il codice è questa:

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 

La soluzione che uso per evitare questo, ed è una soluzione alternativa bello per il PO pure, è quello di catturare tutti IO con la forma (vale a dire tutti i membri pubblici) in una classe separata e utilizzare un'istanza di tale classe per comunicare con il modulo. Quindi, ad es.

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 
Problemi correlati