Очень часто при работе с формами(UserForm) приходится заполнять значениями КомбоБоксы(ComboBox) и ТекстБоксы(TextBox). Иногда однотипными данными. Или очистить их все после выполнения какого-либо действия. А может проверить, все ли элементы заполнены, прежде чем продолжать действие. Если КомбоБоксов/ТекстБоксов пару штучек - не проблема
TextBox1 = "" TextBox2 = "" |
и всех делов. А если их порядка двадцати? Или больше? Мало того, что писать это все долго, так еще и код растягивается, как портянка. Но это можно сделать гораздо проще и удобнее. Воспользоваться можно несколькими способами.
Плюс ко всему, подобные действия может потребоваться производить не только с элементами на пользовательских формах(UserForm), но и с элементами на листе(ActiveX и элементами управления форм: вкладка
Этот способ наиболее популярен, если необходимо произвести однотипные действия со всеми ТекстБоксами на форме:
Sub All_TextBoxes() Dim oControl As Control For Each oControl In UserForm1.Controls If TypeOf oControl Is MSForms.TextBox Then oControl.Value = "" End If Next oControl End Sub |
В примере элементы формы очищаются, но в код можно подставить любое действие - добавление нового элемента списка(для ComboBox), поменять представление данных в TextBox, проверить наличие данных в проверяемом элементе и т.д. Тут уж зависит от поставленной задачи. Конечно, подобным способом можно проделать разные действия и с остальными элементами формы. Только надо будет заменить тип для проверки элементов:
ComboBox - MSForms.ComboBox CheckBox - MSForms.CheckBox CommandButton - MSForms.CommandButton Frame - MSForms.Frame Image - MSForms.Image Label - MSForms.Label ListBox - MSForms.ListBox MultiPage - MSForms.MultiPage SpinButton - MSForms.SpinButton TabStrip - MSForms.TabStrip ToggleButton - MSForms.ToggleButton |
Это не единственный способ проделывания однотипных действий с элементами формы. Код ниже использует имена элементов для обращения к ним:
Sub All_TextBoxes() Dim li As Long For li = 1 To 10 UserForm1.Controls("TextBox" & li).Value = li Next li End Sub |
Недостаток данного метода: имена элементов должны строго соответствовать используемым в коде и лишь нумерация на конце имени должна различаться. За нумерацию отвечает переменная li и, конечно, цикл, в котором задается начальное и конечные значения. В примере ТекстБоксам с именами от "TextBox1" до "TextBox10" будут подставлены значения номеров самих ТекстБоксов. Но такой недостаток может быть очень полезным. Например, если необходимо проделать действия не над всеми ТекстБоксами, а лишь над некоторыми из них. Тогда все, что необходимо дать ТекстБоксам определенные имена с нумерацией("ToDB1","ToDB2" и т.д.) и в зависимости от имени можно проделывать различные действия: стирать значения, менять свойства элементов и т.д.
И есть еще один плюс такого подхода: когда необходимо заполнить значения ТекстБоксов значениями ячеек. Скажем надо заполнить 10 ТекстБоксов(с именами
Sub Fill_TextBoxes_FromCells() Dim li As Long For li = 1 To 10 UserForm1.Controls("TextBox" & li).Value = Sheets("Лист2").Range("A" & li).Value 'или применить Cells вместо Range 'UserForm1.Controls("TextBox" & li).Value = Sheets("Лист2").Cells(li, 1).Value Next li End Sub |
Tips_Macro_WorkWithGroupControls.xls (51,5 КиБ, 4 234 скачиваний)
P.S. Небольшое дополнение: нужные элементы можно просто помещать внутрь объекта Frame. Тогда можно будет применять цикл исключительно по элементам внутри этого Frame(предположим, что Frame называется Frame1):
Sub All_TextBoxes_InFrame() Dim oControl As Control For Each oControl In Frame1.Controls If TypeOf oControl Is MSForms.TextBox Then oControl.Value = "" End If Next oControl End Sub |
Кстати говоря, примерно так же можно перебрать элементы ActiveX не на форме, а на листе(вставляются на лист через вкладку
Sub Off_ActiveXCheckBoxes() Dim oControl 'цикл по всем объектам на листе For Each oControl In ActiveSheet.DrawingObjects 'определяем тип объекта - должен быть OLEObject(так определяется ActiveX) If TypeName(oControl) = "OLEObject" Then 'необходимо дополнительно проверить тип элемента If TypeOf oControl.Object Is MSForms.CheckBox Then oControl.Object.Value = 0 End If End If Next oControl End Sub |
Для этих элементов на листе в строке
Но помимо ActiveX(к слову устаревших и не рекомендованных к использованию) на листе могут быть и другие, более новые флажки - элементы форм(вставляются на лист через вкладку
Sub Off_ShapeCheckBoxes() Dim oControl 'цикл по всем объектам на листе For Each oControl In ActiveSheet.DrawingObjects 'определяем тип объекта - если это Элемент форм, то будет указание на конкретный тип If TypeName(oControl) = "CheckBox" Then oControl.Value = 0 End If Next oControl End Sub |
В данном случае для определения конкретного типа контрола используется TypeName. В коде выше нам нужны CheckBox-ы и на них и проверяем. А вот список основных элементов форм, которые доступны по умолчанию для всех версий для вставки на лист:
DropDown - поле со списком
CheckBox - флажок
Spinner - счетчик
ListBox - список
OptionButton - радиокнопка
GroupBox - группа(рамка)
Label - надпись
ScrollBar - полоса прокрутки
Если совместить, то можно снять флажки со всех checkBox-ов - и ActiveX и Элементов форм:
Sub Off_AllCheckBoxes() Dim oControl 'цикл по всем объектам на листе For Each oControl In ActiveSheet.DrawingObjects 'определяем тип флажка: ActiveX или Элемент форм Select Case TypeName(oControl) Case "OLEObject" 'ActiveX - необходимо дополнительно проверить тип элемента If TypeOf oControl.Object Is MSForms.CheckBox Then oControl.Object.Value = 0 End If Case "CheckBox" 'Элемент форм CheckBox oControl.Value = 0 End Select Next oControl End Sub |
В итоге, определяя конкретный тип элемента можно производить над ним нужные действия.
Добрый день! Дмитрий, а есть ли способ переименовать элементы управления формы кодом?
Если я присваиваю для объекта из коллекции Controls новое свойство Name, то возникает ошибка:
Runtime error 382 Could not set the name property. Can not set property at runtime
Насколько я знаю, переименовать из кода созданные руками элементы встроенными методами нельзя. Переименование доступно только для созданных так же программно элементов.