Робота з елементами керування форми
Свайпніть щоб показати меню
TextBoxes і ComboBoxes охоплюють більшість випадків введення даних, але деякі інші елементи керування природніше виражають певні типи вибору — і правильне зчитування їхніх значень має кілька важливих нюансів, які варто знати, перш ніж покладатися на них.
CheckBoxes
Властивість Value для CheckBox — це звичайне булеве значення: True, якщо встановлено прапорець, і False, якщо ні:
If chkWelcomeEmail.Value = True Then
MsgBox "A welcome email would be sent here."
End If
Кожен CheckBox на формі повністю незалежний від інших — встановлення chkWelcomeEmail не впливає на chkNewsletter, що саме і потрібно, коли вибори не є взаємовиключними.
OptionButtons
OptionButtons працюють навпаки: у межах однієї групи вибір одного автоматично знімає вибір з усіх інших — саме така поведінка потрібна для вибору Status на скріншоті, оскільки клієнт не може бути одночасно і Active, і Inactive. Щоб дізнатися, який саме вибрано, потрібно перевірити значення кожного окремо:
Dim status As String
If optActive.Value = True Then
status = "Active"
ElseIf optInactive.Value = True Then
status = "Inactive"
ElseIf optProspect.Value = True Then
status = "Prospect"
End If
Взаємовиключність забезпечується автоматично і повністю обробляється VBA — не потрібно писати код для зняття вибору з інших двох, коли вибрано один. Проте важливо правильно групувати: OptionButtons виключають одне одного лише в межах одного контейнера (самої форми або Frame, розміщеного на ній), тому дві окремі групи OptionButtons на одній формі — наприклад, Status і Priority — мають бути розміщені у двох різних Frame, інакше VBA розглядатиме їх як одну взаємовиключну групу.
ListBoxes
ListBox відображає кілька варіантів одночасно без необхідності відкривати список, як у випадку зі списком City на рисунку 5.5. Заповнюється так само, як ComboBox, за допомогою .AddItem, а вибір зчитується через .Value або .ListIndex:
Private Sub UserForm_Initialize()
lstCities.AddItem "Chicago"
lstCities.AddItem "Boston"
lstCities.AddItem "Austin"
End Sub
Private Sub cmdAssign_Click()
If lstCities.ListIndex = -1 Then
MsgBox "Please select a city first."
Exit Sub
End If
MsgBox "Assigning to: " & lstCities.Value
End Sub
ListIndex — це позиція вибраного елемента, починаючи з 0 для першого — і важливо, що значення -1 означає, що ще нічого не вибрано, саме це перевіряє cmdAssign_Click, щоб зловити користувача, який натиснув кнопку, не вибравши місто. .Value повертає вибраний текст безпосередньо, що зазвичай зручніше, ніж числова позиція, яку дає .ListIndex.
Multi-Page Forms
Елемент MultiPage (вкладки Details / Preferences у верхній частині рисунка 5.5) групує пов’язані елементи керування на окремих сторінках однієї фізичної форми — корисно, коли на формі забагато полів для комфортного розміщення на одному екрані. Кожна сторінка визначається за позицією, і лише елементи на поточній видимій сторінці мають значення для користувача, хоча всі вони існують і доступні для читання з коду незалежно від того, яка сторінка відкрита:
Private Sub MultiPage1_Change()
If MultiPage1.Value = 1 Then
MsgBox "Now viewing Preferences"
End If
End Sub
MultiPage1.Value використовує таке ж нумерування з нуля, як і ListIndex — перша сторінка має значення 0, друга (Preferences на рисунку 5.5) — 1, а подія Change спрацьовує автоматично щоразу, коли користувач натискає іншу вкладку.
Завдання
- Додати Frame з трьома OptionButton (optActive, optInactive, optProspect) до frmAddCustomer, замінивши попередній ComboBox cboStatus, і написати блок If...ElseIf, як показано вище, для зчитування вибору.
- Додати дві незалежні CheckBox (chkWelcomeEmail, chkNewsletter) і переконатися під час тестування, що вибір однієї не впливає на іншу.
- Додати ListBox (lstCities), який заповнюється у UserForm_Initialize, і написати перевірку, що показує помилку, якщо користувач намагається продовжити без вибору (ListIndex = -1).
- Додаткове завдання: розмістити поля Company Name, Contact та Email на одній сторінці MultiPage з назвою "Details", а CheckBox і OptionButton — на другій сторінці з назвою "Preferences".
1. Заміна cboStatus на Frame з OptionButton
- Спочатку видаліть
cboStatusта його мітку з форми — ви замінюєте його, а не додаєте поруч. - Перетягніть елемент Frame на форму, потім перетягніть усі три OptionButton всередину меж Frame — саме ця вкладеність робить їх взаємовиключними як одну групу.
- Перейменуйте кожен OptionButton окремо у вікні властивостей; сам Frame може мати простий підпис, наприклад "Status", але не потребує зручної для коду назви, якщо ви не плануєте звертатися до нього напряму.
- Для зчитування вибору потрібно перевіряти
.Valueкожного OptionButton окремо черезIf...ElseIf— немає єдиної властивості, яка показує, "який саме з групи обраний". - Оскільки
cboStatus.Valueбільше не існує, уcmdSave_Clickпотрібно створити зміннуstatusна основі OptionButton і записати її уnewRowзамість попереднього значення.
2. Додавання двох незалежних CheckBox
- Вони розміщуються безпосередньо на формі (не у Frame) — CheckBox поза спільним контейнером ніколи не впливають одна на одну незалежно від групування.
- Для "перевірки під час тестування" просто виберіть одну, потім іншу, і переконайтеся, що жодна не знімає вибір з першої.
3. Додавання та перевірка ListBox
- Заповнюйте його так само, як і
cboCity— багаторазові виклики.AddItemуUserForm_Initialize. ListIndex = -1означає, що нічого ще не вибрано — це саме та умова, яку потрібно перевірити перед збереженням.- Ця перевірка має бути у тому ж блоці валідації, що й інші обов'язкові поля, додаючи повідомлення до того ж рядка
errors.
4. Додаткове завдання з MultiPage
- Перетягніть елемент MultiPage на форму — за замовчуванням він містить дві сторінки, саме стільки й потрібно.
- Перейменуйте кожну сторінку через контекстне меню → Page Order, або виберіть вкладку сторінки та змініть підпис у полі Caption у вікні властивостей (Caption визначає текст на вкладці; є окреме поле (Name), якщо потрібно звертатися до сторінки у коді).
- Щоб перемістити існуючі елементи на сторінку, перетягніть їх фізично на видиму область цієї сторінки у режимі конструктора — посилання на елементи у коді не змінюються, оскільки ім'я елемента не залежить від сторінки, на якій він розташований.
Private Sub UserForm_Initialize()
cboCity.AddItem "Chicago"
cboCity.AddItem "Boston"
cboCity.AddItem "Austin"
cboCity.AddItem "Seattle"
cboCity.AddItem "Denver"
lstCities.AddItem "Chicago"
lstCities.AddItem "Boston"
lstCities.AddItem "Austin"
lstCities.AddItem "Seattle"
lstCities.AddItem "Denver"
End Sub
Private Sub cmdCancel_Click()
Unload Me
End Sub
Private Sub cmdSave_Click()
Dim tbl As ListObject
Dim newRow As ListRow
Dim errors As String
Dim status As String
' --- Reset field colors ---
txtCompanyName.BackColor = vbWhite
txtContact.BackColor = vbWhite
txtEmail.BackColor = vbWhite
' --- Required field checks ---
If Trim(txtCompanyName.Value) = "" Then
errors = errors & "- Company Name is required" & vbNewLine
txtCompanyName.BackColor = RGB(255, 199, 206)
End If
If Trim(txtContact.Value) = "" Then
errors = errors & "- Contact is required" & vbNewLine
txtContact.BackColor = RGB(255, 199, 206)
End If
If Trim(txtEmail.Value) = "" Then
errors = errors & "- Email is required" & vbNewLine
txtEmail.BackColor = RGB(255, 199, 206)
End If
' --- Status via OptionButtons ---
If optActive.Value = True Then
status = "Active"
ElseIf optInactive.Value = True Then
status = "Inactive"
ElseIf optProspect.Value = True Then
status = "Prospect"
Else
errors = errors & "- Please select a Status" & vbNewLine
End If
' --- ListBox check ---
If lstCities.ListIndex = -1 Then
errors = errors & "- Please select a city from the list" & vbNewLine
End If
If errors <> "" Then
MsgBox "Please fix the following:" & vbNewLine & errors, vbExclamation
Exit Sub
End If
' --- All checks passed — safe to save now ---
Set tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers")
Set newRow = tbl.ListRows.Add
newRow.Range(1, 1).Value = "C0" & (tbl.ListRows.Count + 100)
newRow.Range(1, 2).Value = txtCompanyName.Value
newRow.Range(1, 3).Value = txtContact.Value
newRow.Range(1, 4).Value = txtEmail.Value
newRow.Range(1, 5).Value = cboCity.Value
newRow.Range(1, 6).Value = status
If chkWelcomeEmail.Value = True Then
MsgBox "A welcome email would be sent to " & txtEmail.Value & "."
End If
MsgBox txtCompanyName.Value & " was added successfully."
Unload Me
End Sub
Примітки щодо тестування:
- Пункт 2 (CheckBox) не має окремої перевірки — просто натисніть
chkWelcomeEmailтаchkNewsletterнезалежно й переконайтеся, що кожна перемикається без впливу на іншу. - Пункт 4 (MultiPage) — це лише зміна макета, жодних змін у коді не потрібно, оскільки кожен елемент зберігає свою назву незалежно від сторінки, на якій він розташований.
- Зверніть увагу, що
cboCity.Valueвсе ще використовується для фактичного збереження (newRow.Range(1, 5)), тоді якlstCitiesіснує окремо як незалежний контроль для перевірки згідно з завданням — вони не пов'язані між собою, якщо ви самостійно не реалізуєте це.
Дякуємо за ваш відгук!
Запитати АІ
Запитати АІ
Запитайте про що завгодно або спробуйте одне із запропонованих запитань, щоб почати наш чат