VBA Excel: Как соотносится код в модулях, формах и рабочих листах
Никак не пойму как соотносятся между собой коды, размещенные в модулях, формах и рабочих листах.
Тоесть, в каком месте в каком случае нужно писать?
(может кто-то подскажет где конкретно об этом в нете можно почитать)
И еще совсем практический вопрос: как сделать, чтобы значение, например, текстбокса первой формы было доступно при роботе второй формы?
Ооочень нужна помощь:(
Помогите плз начинающим.
Никак не пойму как соотносятся между собой коды, размещенные в модулях, формах и рабочих листах.
Тоесть, в каком месте в каком случае нужно писать?
(может кто-то подскажет где конкретно об этом в нете можно почитать)
И еще совсем практический вопрос: как сделать, чтобы значение, например, текстбокса первой формы было доступно при роботе второй формы?
Ооочень нужна помощь:(
Если коротко, то ситуация такая:
1. Модуль - для хранения функций, процедур, переменныx (если он объявлены как Public на верху модуля, то доступны везде). В случае с Excel'ем:
- если в модуле объявить публичную процедуру Public Sub, то он будет считать ее макросом и можно будет ее увидеть в списке доступных макросов через меню Сервис/Макросы...
- если же объявить Public функцию, то ее можно будет выбрать в меню функции в разделе: Пользовательские функции.
2. Каждая форма (в Excel'е они называются UserForm) всегда имеет свой модуль. Они неразрывно связаны. В конструкторе VB при выборе формы можно переключаться между видом самйо формы с контролами и модулем формы. Это модуль не является модулем как в пункте 1, он отличается и потому их выделяют отдельно и называют - модуль формы.
В модуле формы как и в обычном модуле можно тоже объявлять функции, процедуры и переменные, но помимо этого, именно в нем хранится код обработки СОБЫТИЙ контролов на форме и самой формы.( В верху из выпадающего списка, можно выбрать контрол, а чуть правее - событие и компиллятор автоматом добавит в модуль процедуру обработки события для данного контрола)
Вторая особенность (которая является ответом на твой второй вопрос) заключается в том, что все функции, процедуры, переменные, а также контролы формы доступны будут только в то время, когда форма - ЗАГРУЖЕНА. Если форма не загружена, ты не сможешь обратиться ни контролу на форме, ни к public переменной из модуля формы (а также функ. и процедуре)
Под словом загружена - я не имел ввиду, что форма должна быть видима. В VB есть различие между ЗАГРУЗИТЬ форму и ПОКАЗАТЬ форму.
Load UserForm1 - загрузить форму, при это форма будет висеть в памяти и к ней можно будет обращаться, но она будет НЕВИДИМА.
UserForm1.Show - показать форму.
Тонкость тут такая (которая часто путает новичков).
Если форма НЕЗАГРУЖЕНА, то строка UserForm1.Show приведет автоматом к ЗАГРУЗКЕ формы и ее ПОКАЗУ.
Если форма была предварительно ЗАГРУЖЕНА, то метод UserForm1.Show приведет соответственно только к ее показу.
Load UserForm1 удобно использовать для загрузки формы и установки нач. значений для контролов перед ее показом потом пользователю сразу во все красе. А то как-то не очень красиво выглядит, когда форма показывается, а потом на глазах у пользователя конторолы начинают быстренька заполняться новыми значениями :)
Кроме того, часто используют еще и такой трюк, когда заранее известно что пользователь с большое долей вероятности после первой формы откроет еще и вторую, то можно вторую форму загрузить заранее, пока пользователь наслаждается первой формой, а как только он запросит вторую форму, мы уже быстро показываем ему вторую форму, т.к. она уже была загружена но скрыта. Или наоборот делают, когда пользователь закрывают форму, ее программно просто скрывают - UserForm1.Hide и форма скрывается с глаз, НО продолжает висеть в памяти и очень быстро может быть вызвана повторно на экран.
Выгрузить форму программно можно так - Unload UserForm1
3. Модуль листа/книги представляет из себя по сути - модуль формы. Смысл такой же. Сам лист/книга имеют события на которые можно написать код и кроме того на сам лист (книги это не касается) можно разместить контрол(кнопку, поле и т.д.) обработчики которых будут доступны опять же в модуле листа.
P.S. на счет почитать про это - лучше все таки не ограничивать себя и почитать про все. Тем более что редко когда можно найти в книжках ответ ИМЕННО на твой вопрос. Да это обычно и не нужно, если человек понимает основы, все остальное всего лишь производное
Может быть тебе снова будет не лень мне помочь, потому что я все-таки не до конца разобралась.
Моя проблема будет более наглядна на примере:
На рабочем листе есть кнопка, нажатие которой вызывает 1ую форму; пользователь на ней заполняет поля и нажимает "ок", после чего 1ая форма исчезает и появляется 2ая, вид которой зависит от того, что ввел пользователь на 1ой.
Мой вопрос: надо ли мне что-то писать в модуле? Если да, то часть, отвечающую за что?
Или в модуле я пишу только если хочу, чтобы процедуры и функции были доступны через Сервис/Макросы и в разделе Пользовательские функции соответственно?
Спасибо большое за развернутый ответ!
Может быть тебе снова будет не лень мне помочь, потому что я все-таки не до конца разобралась.
Моя проблема будет более наглядна на примере:
На рабочем листе есть кнопка, нажатие которой вызывает 1ую форму; пользователь на ней заполняет поля и нажимает "ок", после чего 1ая форма исчезает и появляется 2ая, вид которой зависит от того, что ввел пользователь на 1ой.
Мой вопрос: надо ли мне что-то писать в модуле? Если да, то часть, отвечающую за что?
Или в модуле я пишу только если хочу, чтобы процедуры и функции были доступны через Сервис/Макросы и в разделе Пользовательские функции соответственно?
Нет, модули прежде всего предназначены для хранения функций и процедур. Их можно будет вызвать из любого места проекта (если они конечно на Private), и такой модуль удобно использовать в других проектах. Например можно собрать в модуле функции по опред. тематики, а потом при необходимости включать этот модуль во все нужные тебе проекты. Очень удобно, раз написал и годы потом используешь.
А то что Public функции и процедуры видны в соотв. меню Excel'я - это уже просто фишка Excel'я, которую можно учитывать если ты хочешь написать макрос (или пользовательскую функцию) - но это уже твой выбор.
В твоем примере - если ты не знаешь что написать в модуле - то не пиши :)
Просто я имел ввиду, что для вызова первой и второй формы модуль не нужен. Просто если ты наваяишь пару универсальных функций, которые используются этими формами, то удобнее их разместить в модуле, а не в модуле формы.
Если у тя кнопка на листе, то код будет выглядеть так:
в модуле листа:
Private Sub CommandButton1_Click()
' открываем первую форму
UserForm1.Show
End Sub
в модуле формы USerForm1, обработчик события нажатия на кнопку OK (назовем ее - ButOK):
Private Sub ButOK_Click()
' открываем вторую форму
UserForm2.Show
' закрываем первую форму
Unload UserForm1
End Sub
главное не наоборот, а то после строчки Unload UserForm1 программа перейдет сразу на событие QueryClose(закрытие формы)
Правда возник еще один "глобальный вопрос": есть ли возможность задать глобальные переменные, которые будут доступны для всех модулях проекта (и в модулях форм, и в модулях рабочих листов, ...)?
П.С.: спасибо за помощь. Эт я впервые в форум пишу:)
Спасибо еще раз, многое прояснилось наконец:)
Правда возник еще один "глобальный вопрос": есть ли возможность задать глобальные переменные, которые будут доступны для всех модулях проекта (и в модулях форм, и в модулях рабочих листов, ...)?
П.С.: спасибо за помощь. Эт я впервые в форум пишу:)
Пункт 1 моего первого сообщения - Public перенные объявленные в модуле в вверху доступны всегда и везде (кроме другого проекта).
Я никак не могу в хелпе найти как обратится к, например, кнопке, расположенной на листе 1 не из модуля этого листа:'( Тоесть мне надо поменять значения свойств этой кнопки.
Перепробовала почти все, что смогла придумать.
Помогите, плз
Интересно,а по выходным ты тоже помогаешь страждущим?:)
Я никак не могу в хелпе найти как обратится к, например, кнопке, расположенной на листе 1 не из модуля этого листа:'( Тоесть мне надо поменять значения свойств этой кнопки.
Перепробовала почти все, что смогла придумать.
Помогите, плз
Полный путь такой:
Workbooks("Книга1").Worksheets("Лист1").CommandButton1.Caption = "Привет"
Еще проблема:
В модуле рабочего листа в динамичекий массив (который описан в модуле) запоминается значение ячейки, а потом ячейка меняет значение, ваполняются процедуры, описанные в модулях формы, и через некоторое время очередная процедура обращается к этом массиву. Но пока не напишешь ReDim, он не узнает этот массив, а если напишешь - так он же становится "как новенький", тоесть пустой:(
А как все-таки сделать, чтобы можно было из другого модуля эти значения получить?
Заранее благодарна за ответ.
Вот у мой пример: первая кнопка заполняет массив, вторая выводит его на экран
У меня в модуле было :
Public Ynazvy() As String
А в модуле формы осталось Dim Ynazvy() As String;)
Невнимательная, вообщем.
Ты знаешь, с этим разобралась:)
У меня в модуле было :
Public Ynazvy() As String
А в модуле формы осталось Dim Ynazvy() As String;)
Невнимательная, вообщем.
Ага, на этой ошибке хорошо видно как VB действует при перекрывании имен:
В данном случае, т.к. переменные были объявлены в разных модулях - это допускается. При это местная переменная имеет всегда приоритет над переменной з другого модуля.
Точно такая же ситуация возможно когда ты объявляешь одинаковые переменные: одну на верху модуля (наз. объявить переменную на уровне модуля), а другую внутри функции, которая находится в этом же модуле. Тогда опять же, переменная внутри функции будет иметь приоритет над переменной которая действует по всему модулю.
Кстати, чтоб таких ошибок не совершать, лучше использовать соглашение Редика, когда в названии переменной код. ее тип, а также область видимости.
Например: spFio - s - это String; p - публичная; Fio - имя переменной, начинается с большой буквы, чтобы отличить от имя от префиксов.