Arbeide med skjemakontroller
Sveip for å vise menyen
TextBoxes og ComboBoxes dekker de fleste dataregistreringer, men noen andre kontroller uttrykker visse valg på en mer naturlig måte — og det å lese verdiene deres korrekt har noen reelle fallgruver det er verdt å kjenne til før du stoler på dem.
CheckBoxes
En CheckBox sin Value-egenskap er en enkel boolsk verdi — True når den er avkrysset, False når den ikke er det:
If chkWelcomeEmail.Value = True Then
MsgBox "A welcome email would be sent here."
End If
Hver CheckBox på et skjema er helt uavhengig av de andre — å krysse av chkWelcomeEmail har ingen effekt på chkNewsletter, noe som er akkurat den oppførselen du ønsker når valgene ikke utelukker hverandre.
OptionButtons
OptionButtons oppfører seg motsatt: innenfor samme gruppe vil det å velge én automatisk fjerne valget fra alle de andre — akkurat det Status-valgene på skjermbildet trenger, siden en kunde ikke kan være både Aktiv og Inaktiv samtidig. For å lese av hvilken som er valgt, må du sjekke verdien til hver enkelt:
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
Gjensidig utelukkelse håndteres automatisk av VBA — du trenger aldri å skrive kode som fjerner avkrysningen på de andre når én velges. Gruppinndeling er viktig: OptionButtons utelukker bare hverandre innenfor samme beholder (selve skjemaet, eller en Frame-kontroll plassert på det), så to separate grupper med OptionButtons på samme skjema — for eksempel Status og Prioritet — må ligge i to ulike Frames, ellers vil VBA behandle alle som én enkelt gjensidig utelukkende gruppe.
ListBoxes
En ListBox viser flere valg samtidig uten at du må klikke den opp, slik som City-listen i Figur 5.5. Fyll den på samme måte som en ComboBox, med .AddItem, og les utvalget tilbake enten via .Value eller .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 er posisjonen til det valgte elementet, talt fra 0 for det første elementet — og viktigst, den er -1 når ingenting er valgt ennå, noe som er sjekken cmdAssign_Click bruker for å fange en bruker som klikker knappen uten å velge en by først. .Value gir deg den valgte teksten direkte, noe som vanligvis er mer nyttig enn den numeriske posisjonen .ListIndex gir.
Multi-Page Forms
En MultiPage-kontroll (fanene Details / Preferences øverst i Figur 5.5) grupperer relaterte kontroller på separate sider i samme fysiske skjema — nyttig når et skjema har for mange felt til å få plass på én skjerm. Hver side adresseres etter posisjon, og bare kontrollene på den synlige siden er relevante for brukeren, selv om alle fortsatt eksisterer og kan leses fra kode uansett hvilken side som vises:
Private Sub MultiPage1_Change()
If MultiPage1.Value = 1 Then
MsgBox "Now viewing Preferences"
End If
End Sub
MultiPage1.Value følger samme 0-baserte telling som ListIndex — første side er 0, andre (Preferences, i Figur 5.5) er 1 — og Change-hendelsen utløses automatisk hver gang brukeren klikker på en annen fane.
Oppgave
- Legg til en ramme (Frame) som inneholder tre alternativknapper (optActive, optInactive, optProspect) i frmAddCustomer, og erstatt den tidligere cboStatus ComboBox. Skriv If...ElseIf-blokken vist ovenfor for å lese valget.
- Legg til to uavhengige avkrysningsbokser (chkWelcomeEmail, chkNewsletter) og bekreft under testing at det å merke én aldri påvirker den andre.
- Legg til en listeboks (lstCities) som fylles i UserForm_Initialize, og skriv en sjekk som viser en feilmelding hvis brukeren prøver å fortsette uten å ha valgt noe (ListIndex = -1).
- Utfordring: plasser feltene Company Name, Contact og Email på én MultiPage-side kalt "Details", og avkrysningsboksene og alternativknappene på en annen side kalt "Preferences".
1. Erstatte cboStatus med en ramme med alternativknapper
- Slett først
cboStatusog dens etikett fra skjemaet — du erstatter den, ikke legger til i tillegg. - Dra en Frame-kontroll inn på skjemaet, og dra deretter alle tre alternativknappene inn i rammens område — denne innkapslingen gjør dem gjensidig utelukkende som én gruppe.
- Gi hver alternativknapp nytt navn individuelt i egenskapsvinduet; selve rammen kan ha en enkel bildetekst som "Status", men trenger ikke et kodenavn med mindre du skal referere til den direkte.
- For å lese valget må du sjekke hver alternativknapps
.Valueindividuelt medIf...ElseIf— det finnes ingen enkelt egenskap som forteller deg "hvilken i gruppen som er valgt". - Siden
cboStatus.Valueikke lenger finnes, måcmdSave_Clickha enstatus-variabel bygget fra alternativknappene i stedet, som skrives inn inewRowpå samme sted.
2. Legge til to uavhengige avkrysningsbokser
- Disse plasseres direkte på skjemaet (ikke inne i rammen) — avkrysningsbokser utenfor en delt beholder påvirker aldri hverandre uansett gruppering.
- For å "bekrefte under testing", merk bare av i én, deretter den andre, og se at ingen av dem fjerner merkingen fra den første.
3. Legge til og validere en listeboks
- Fyll den på samme måte som
cboCityble fylt — gjentatte.AddItem-kall iUserForm_Initialize. ListIndex = -1betyr spesifikt at ingenting er valgt ennå — det er akkurat denne tilstanden du skal sjekke før lagring kan fortsette.- Denne sjekken hører hjemme i samme valideringsblokk som de andre obligatoriske feltene, og legges til i samme
errors-streng.
4. MultiPage-utfordring
- Dra en MultiPage-kontroll inn på skjemaet — den har to sider som standard, akkurat så mange du trenger.
- Gi hver side nytt navn via høyreklikk → Page Order, eller ved å velge sidens fane og bruke egenskapsvinduets Caption-felt (Caption styrer fanens synlige tekst; det finnes også et eget (Name)-felt hvis du vil referere til en side i kode).
- For å flytte eksisterende kontroller til en side, dra dem fysisk inn på den sidens synlige område i designvisning — kodereferanser til dem endres ikke, siden kontrollens navn ikke avhenger av hvilken side den ligger på.
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
Testnotater:
- Punkt 2 (avkrysningsbokser) har ingen egen validering — bare klikk på
chkWelcomeEmailogchkNewsletteruavhengig og bekreft at hver kan slås av og på uten å påvirke den andre. - Punkt 4 (MultiPage) er kun en layoutendring — ingen kodeendringer er nødvendig utover det som allerede finnes her, siden hver kontroll beholder sitt eget navn uansett hvilken side den ligger på.
- Merk at
cboCity.Valuefortsatt brukes for selve lagringen (newRow.Range(1, 5)), menslstCitieskun eksisterer som en separat, uavhengig validert kontroll i henhold til oppgaven — de to er ikke koblet sammen med mindre du selv velger å utvide det slik.
Takk for tilbakemeldingene dine!
Spør AI
Spør AI
Spør om hva du vil, eller prøv ett av de foreslåtte spørsmålene for å starte chatten vår
Arbeide med skjemakontroller
TextBoxes og ComboBoxes dekker de fleste dataregistreringer, men noen andre kontroller uttrykker visse valg på en mer naturlig måte — og det å lese verdiene deres korrekt har noen reelle fallgruver det er verdt å kjenne til før du stoler på dem.
CheckBoxes
En CheckBox sin Value-egenskap er en enkel boolsk verdi — True når den er avkrysset, False når den ikke er det:
If chkWelcomeEmail.Value = True Then
MsgBox "A welcome email would be sent here."
End If
Hver CheckBox på et skjema er helt uavhengig av de andre — å krysse av chkWelcomeEmail har ingen effekt på chkNewsletter, noe som er akkurat den oppførselen du ønsker når valgene ikke utelukker hverandre.
OptionButtons
OptionButtons oppfører seg motsatt: innenfor samme gruppe vil det å velge én automatisk fjerne valget fra alle de andre — akkurat det Status-valgene på skjermbildet trenger, siden en kunde ikke kan være både Aktiv og Inaktiv samtidig. For å lese av hvilken som er valgt, må du sjekke verdien til hver enkelt:
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
Gjensidig utelukkelse håndteres automatisk av VBA — du trenger aldri å skrive kode som fjerner avkrysningen på de andre når én velges. Gruppinndeling er viktig: OptionButtons utelukker bare hverandre innenfor samme beholder (selve skjemaet, eller en Frame-kontroll plassert på det), så to separate grupper med OptionButtons på samme skjema — for eksempel Status og Prioritet — må ligge i to ulike Frames, ellers vil VBA behandle alle som én enkelt gjensidig utelukkende gruppe.
ListBoxes
En ListBox viser flere valg samtidig uten at du må klikke den opp, slik som City-listen i Figur 5.5. Fyll den på samme måte som en ComboBox, med .AddItem, og les utvalget tilbake enten via .Value eller .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 er posisjonen til det valgte elementet, talt fra 0 for det første elementet — og viktigst, den er -1 når ingenting er valgt ennå, noe som er sjekken cmdAssign_Click bruker for å fange en bruker som klikker knappen uten å velge en by først. .Value gir deg den valgte teksten direkte, noe som vanligvis er mer nyttig enn den numeriske posisjonen .ListIndex gir.
Multi-Page Forms
En MultiPage-kontroll (fanene Details / Preferences øverst i Figur 5.5) grupperer relaterte kontroller på separate sider i samme fysiske skjema — nyttig når et skjema har for mange felt til å få plass på én skjerm. Hver side adresseres etter posisjon, og bare kontrollene på den synlige siden er relevante for brukeren, selv om alle fortsatt eksisterer og kan leses fra kode uansett hvilken side som vises:
Private Sub MultiPage1_Change()
If MultiPage1.Value = 1 Then
MsgBox "Now viewing Preferences"
End If
End Sub
MultiPage1.Value følger samme 0-baserte telling som ListIndex — første side er 0, andre (Preferences, i Figur 5.5) er 1 — og Change-hendelsen utløses automatisk hver gang brukeren klikker på en annen fane.
Oppgave
- Legg til en ramme (Frame) som inneholder tre alternativknapper (optActive, optInactive, optProspect) i frmAddCustomer, og erstatt den tidligere cboStatus ComboBox. Skriv If...ElseIf-blokken vist ovenfor for å lese valget.
- Legg til to uavhengige avkrysningsbokser (chkWelcomeEmail, chkNewsletter) og bekreft under testing at det å merke én aldri påvirker den andre.
- Legg til en listeboks (lstCities) som fylles i UserForm_Initialize, og skriv en sjekk som viser en feilmelding hvis brukeren prøver å fortsette uten å ha valgt noe (ListIndex = -1).
- Utfordring: plasser feltene Company Name, Contact og Email på én MultiPage-side kalt "Details", og avkrysningsboksene og alternativknappene på en annen side kalt "Preferences".
1. Erstatte cboStatus med en ramme med alternativknapper
- Slett først
cboStatusog dens etikett fra skjemaet — du erstatter den, ikke legger til i tillegg. - Dra en Frame-kontroll inn på skjemaet, og dra deretter alle tre alternativknappene inn i rammens område — denne innkapslingen gjør dem gjensidig utelukkende som én gruppe.
- Gi hver alternativknapp nytt navn individuelt i egenskapsvinduet; selve rammen kan ha en enkel bildetekst som "Status", men trenger ikke et kodenavn med mindre du skal referere til den direkte.
- For å lese valget må du sjekke hver alternativknapps
.Valueindividuelt medIf...ElseIf— det finnes ingen enkelt egenskap som forteller deg "hvilken i gruppen som er valgt". - Siden
cboStatus.Valueikke lenger finnes, måcmdSave_Clickha enstatus-variabel bygget fra alternativknappene i stedet, som skrives inn inewRowpå samme sted.
2. Legge til to uavhengige avkrysningsbokser
- Disse plasseres direkte på skjemaet (ikke inne i rammen) — avkrysningsbokser utenfor en delt beholder påvirker aldri hverandre uansett gruppering.
- For å "bekrefte under testing", merk bare av i én, deretter den andre, og se at ingen av dem fjerner merkingen fra den første.
3. Legge til og validere en listeboks
- Fyll den på samme måte som
cboCityble fylt — gjentatte.AddItem-kall iUserForm_Initialize. ListIndex = -1betyr spesifikt at ingenting er valgt ennå — det er akkurat denne tilstanden du skal sjekke før lagring kan fortsette.- Denne sjekken hører hjemme i samme valideringsblokk som de andre obligatoriske feltene, og legges til i samme
errors-streng.
4. MultiPage-utfordring
- Dra en MultiPage-kontroll inn på skjemaet — den har to sider som standard, akkurat så mange du trenger.
- Gi hver side nytt navn via høyreklikk → Page Order, eller ved å velge sidens fane og bruke egenskapsvinduets Caption-felt (Caption styrer fanens synlige tekst; det finnes også et eget (Name)-felt hvis du vil referere til en side i kode).
- For å flytte eksisterende kontroller til en side, dra dem fysisk inn på den sidens synlige område i designvisning — kodereferanser til dem endres ikke, siden kontrollens navn ikke avhenger av hvilken side den ligger på.
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
Testnotater:
- Punkt 2 (avkrysningsbokser) har ingen egen validering — bare klikk på
chkWelcomeEmailogchkNewsletteruavhengig og bekreft at hver kan slås av og på uten å påvirke den andre. - Punkt 4 (MultiPage) er kun en layoutendring — ingen kodeendringer er nødvendig utover det som allerede finnes her, siden hver kontroll beholder sitt eget navn uansett hvilken side den ligger på.
- Merk at
cboCity.Valuefortsatt brukes for selve lagringen (newRow.Range(1, 5)), menslstCitieskun eksisterer som en separat, uavhengig validert kontroll i henhold til oppgaven — de to er ikke koblet sammen med mindre du selv velger å utvide det slik.
Takk for tilbakemeldingene dine!