2013-04-11 2 views
9

Ниже представлен вопрос, на который я отвечу сам, однако это вызвало серьезное разочарование для меня, и у меня возникло множество проблем с поиском его в Интернете, поэтому я размещение здесь в надежде спасти какое-то время & усилия для других, и, возможно, для себя, если я забуду это в будущем:

для VBA (в моем случае, MS Excel), то Public декларации предполагается сделать переменную (или функцию), доступную по всему миру другими функциями или подпрограммами в этом модуле, а также в любом другом модуле.

Оказывается, это неверно, в случае с Forms
, и я подозреваю также, что в Sheets, но я не проверил последний.

Короче говоря, следующий не будет создавать общественности, доступ к переменной при создании в Form, и, следовательно, приведет к краху, говоря, что переменные bYesNo и dRate не определены в mModule1:
Публичные переменные не являются ДЕЙСТВИТЕЛЬНО публичными в VBA в формах

(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 


Однако, если вы сделаете небольшое изменение ниже, все это будет работать нормально:

(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 будет работать прекрасно и, предполагая, что fMyForm всегда называют первым, то к тому времени, PrintVals процедуры выполняется, значение из текстового поля и флажка в форме будет должным образом быть захвачены.

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

+3

Модули Userform и Sheet являются объектными модулями: они не ведут себя так же, как обычный модуль. Однако вы можете ссылаться на переменную в пользовательской форме аналогично тому, как вы относитесь к свойству класса. В вашем примере ссылка на 'fMyForm.bYesNo' будет работать нормально. Если вы не объявили bYesNo как Public, он не будет видимым для кода вне формы, поэтому, когда вы сделаете его Public, он действительно отличается от негосударственного. –

+3

Известно, что если вам нужны истинные общедоступные переменные, вам необходимо объявить их в модуле кода, а не в области кода формы/листа. См. Эту ссылку http://msdn.microsoft.com/en-us/library/office/gg264241.aspx 'Публичные переменные могут использоваться в любых процедурах в проекте. Если публичная переменная объявлена ​​в стандартном модуле или модуле класса, ее также можно использовать в любых проектах, которые ссылаются на проект, в котором объявлена ​​публичная переменная. ' –

+0

Что касается последнего комментария', который так плохо документирован, что поиск Google в 2013 году для чего-то, что, вероятно, было около десятилетия или более, так сложно искать. Возможно, вы ищете неправильное ключевое слово? Попробуйте найти это в Google? 'msdn VBA объявляет публичные переменные';) –

ответ

2

Первый комментарий:

UserForm и Листовые модули являются модулями объекта: они не ведут себя так же, как обычный модуль. Однако вы можете ссылаться на переменную в пользовательской форме аналогично тому, как вы относитесь к свойству класса. В вашем примере ссылка на fMyForm.bYesNo будет работать нормально. Если вы не объявили bYesNo как Public, он не будет видимым для кода вне формы, поэтому, когда вы сделаете его Public, он действительно отличается от негосударственного. - Тим Уильямс 11 апреля '13 в 21:39

на самом деле правильный ответ ...

+1

Пожалуйста, отметьте этот ответ как «ответ сообщества», –

0

Как быстро дополнение ответ сообщества ответ, только для хэдз-ап:

Когда вы создаете экземпляры форм, вы можете использовать сам объект формы, или вы можете создать новый экземпляр объекта формы, используя New и помещая его в переменную. Последний метод является более чистым IMO, поскольку это делает использование менее одноточечным.

Тем не менее, если в вашем пользовательском формате вы вызывают разгрузку (Me), все общественные участники будут очищены.Таким образом, если ваш код выглядит следующим образом:

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 

Решение я использую, чтобы предотвратить это, и это является хорошим альтернативным решением для ОРА, а также, является захват всех операций ввода-вывода с формой (т.е. всех представителей общественности) в отдельный класс и использовать экземпляр этого класса для связи с формой. Так, например,

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 
Смежные вопросы