Introduksjon til brukerformer
Sveip for å vise menyen
UserForms har begrenset eller manglende funksjonalitet i Excel for Mac — VBA IDE på Mac mangler full støtte for utforming av UserForms i mange versjoner, noe som kan føre til nettopp denne typen uforklarlig oppførsel.
MsgBox og InputBox dekker enkle ja/nei-spørsmål og ettlinjesvar, men når en kunde faktisk trenger flere felt samtidig — et firmanavn, en kontaktperson, en by, en status. Det er dette en UserForm er til for: et lite tilpasset vindu med egne etiketter, tekstbokser, nedtrekksmenyer og knapper, bygget inne i VBE og styrt helt av koden din.
Opprette et skjema
I VBE, høyreklikk prosjektet ditt i Project Explorer og velg Sett inn → UserForm. En tom utformingsflate vises, sammen med en flytende verktøykasse med kontroller du kan dra inn på skjemaet.
Etiketter, tekstbokser, kombinasjonsbokser og knapper
Hver kontroll du drar inn på skjemaet får et standardnavn som TextBox1 eller CommandButton1 — funksjonelt, men meningsløst når et skjema har seks eller syv kontroller. Den viktigste vanen i denne delen vises i Egenskapsvinduet: gi nytt navn til hver kontroll umiddelbart etter at den er lagt til, ved å bruke et kort prefiks som identifiserer typen (txt for TextBox, cbo for ComboBox, cmd for CommandButton, opt for OptionButton, chk for CheckBox, lst for ListBox) etterfulgt av et beskrivende navn. txtCompanyName er tydelig i koden om tre uker; TextBox1 er det ikke.
Etiketter er vanlige, ikke-interaktive tekstfelt ("Firmanavn:") — brukeren kan se dem, men aldri skrive i eller klikke på dem. Tekstbokser er der fri tekst skrives inn. Kombinasjonsbokser viser en nedtrekksliste med valg, som er akkurat det cboCity og cboStatus brukes til — å begrense City og Status til en kjent liste i stedet for å la brukeren skrive fritt "chicago", "Chicago,IL" og "CHI" for det samme i ulike poster.
Skrive kode bak skjemaet
Dobbeltklikk på en hvilken som helst kontroll på designflaten for å gå direkte til koden — VBA oppretter automatisk en hendelsesprosedyre med navnet ControlName_EventName, og kode skrevet inni denne kjøres hver gang den spesifikke hendelsen skjer for den aktuelle kontrollen. Standardhendelsen for en knapp er Click:
Private Sub UserForm_Initialize()
' runs once, automatically, when the form is first shown
cboCity.AddItem "Chicago"
cboCity.AddItem "Boston"
cboCity.AddItem "Austin"
cboCity.AddItem "Seattle"
cboCity.AddItem "Denver"
cboStatus.AddItem "Active"
cboStatus.AddItem "Inactive"
cboStatus.AddItem "Prospect"
End Sub
Private Sub cmdCancel_Click()
Unload Me
End Sub
UserForm_Initialize er en spesiell hendelsesprosedyre som kjøres automatisk i det øyeblikket skjemaet lastes inn — før brukeren ser noe — noe som gjør dette til riktig sted å fylle ComboBoxes med .AddItem i stedet for å skrive inn valgene manuelt i egenskapsvinduet, spesielt når valgene kan endres eller hentes fra et regneark. Unload Me inne i cmdCancel_Click lukker skjemaet helt; Me refererer alltid til skjemaet koden kjører i, så denne linjen fungerer uendret uansett hva du eventuelt gir skjemaet nytt navn.
Gjennomgangseksempel: Lagre en ny kunde
Dette er prosedyren bak Lagre-knappen — den som faktisk skriver en ny rad inn i tblCustomers:
Private Sub cmdSave_Click()
Dim tbl As ListObject
Dim newRow As ListRow
Set tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers")
Set newRow = tbl.ListRows.Add
newRow.Range(1, 1).Value = "C" & Format(tbl.ListRows.Count + 1, "000")
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 = cboStatus.Value
MsgBox txtCompanyName.Value & " was added successfully."
Unload Me
End Sub
- Set
tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers")går hele veien fra skjemaet tilbake til arbeidsboken — et UserForm er bare et annet kodeelement, så alt om ListObjects gjelder uendret; tbl.ListRows.Addlegger til en faktisk ny rad innenfor tabellens grenser i stedet for å skrive forbi siste brukte celle manuelt;txtCompanyName.Value,cboCity.Valueog de andre leser det brukeren har skrevet eller valgt i den aktuelle kontrollen —.Valueer felles for nesten alle kontrolltyper, derfor fungerer samme mønster for både TextBoxes og ComboBoxes;- Den genererte kunde-ID-linjen er en forenklet plassholder for denne øvelsen — ekte ID-generering må sjekke for hull eller gjenbrukte ID-er, noe denne linjen ikke gjør;
- Unload Me til slutt lukker skjemaet først etter at raden er skrevet — å lukke tidligere ville gjort
txtCompanyName.Valueog de andre kontrollverdiene utilgjengelige, siden kontrollene ikke lenger eksisterer når skjemaet er lukket.
Skjemaets "Company Name"-etikett er kun en mer brukervennlig tekst for tabellens Customer-kolonne — koden skriver txtCompanyName.Value inn i denne kolonnen uavhengig av etikettens ordlyd, siden det kun er TextBox-navnet som betyr noe for VBA, ikke den synlige teksten.
Customer ID er ikke med i skjemaet fordi det genereres automatisk av koden ("C0" & (tbl.ListRows.Count + 100)) i stedet for å bli skrevet inn av brukeren — dette gjenspeiler hvordan ekte systemer automatisk nummererer nye poster i stedet for å stole på at en person velger en unik ID.
Oppgave
- Sett inn et nytt UserForm, gi det navnet
frmAddCustomer, og legg til tre TextBoxes (txtCompanyName,txtContact,txtEmail) og to ComboBoxes (cboCity, cboStatus), hver med tilhørende etikett. - Legg til to CommandButtons,
cmdSaveogcmdCancel, og skriv prosedyreneUserForm_InitializeogcmdCancel_Clicknøyaktig som vist. - Skriv
cmdSave_Clicksom vist, og legg deretter til en midlertidig knapp et annet sted i arbeidsboken med kodenfrmAddCustomer.Showfor å teste åpning av skjemaet. - Fyll ut skjemaet for en fiktiv sjette kunde og klikk Save — bekreft at en ny rad vises i tblCustomers med verdiene du har skrevet inn.
1. Lage skjemaet
- Sett inn → UserForm i VBE, og gi det nytt navn via Egenskapsvinduets
(Name)-felt tilfrmAddCustomer— ikke Caption-feltet, som kun endrer tittellinjen. - Dra inn ett Label + ett TextBox-par for hver av Company Name, Contact og Email; ett Label + ett ComboBox-par for City og Status.
- Gi hvert kontroll nytt navn umiddelbart etter at det er lagt til — dette er vanen kapittelet la vekt på. Labels trenger ikke kodevennlige navn siden de aldri refereres i koden, men alle TextBox/ComboBox/Button må ha det.
2. UserForm_Initialize og cmdCancel_Click
- Dobbeltklikk på skjemaets tomme bakgrunn (ikke en kontroll) for å komme til
UserForm_Initialize— dobbeltklikker du påcmdCancelhopper du rett tilcmdCancel_Click. - Begge prosedyrene ble gitt deg nøyaktig i kapittelet — skriv dem inn uendret.
3. Testing med en midlertidig knapp
- Denne knappen trenger ikke ligge på skjemaet — legg den på et hvilket som helst regneark via Utvikler → Sett inn → Knapp (skjemakontroll), eller bare kjør en enlinjes
Subfra VBE i stedet for å legge til en regneark-knapp. frmAddCustomer.Shower hele koden som trengs for å vise skjemaet.
4. Testing av full lagring
- Fyll ut alle feltene og velg verdier fra begge nedtrekkslistene før du klikker Lagre — et tomt ComboBox-valg vil skrive en tom celle.
- Sjekk
tblCustomersetterpå for en ny rad med en ID på formenC00x.
Private Sub UserForm_Initialize()
' runs once, automatically, when the form is first shown
cboCity.AddItem "Chicago"
cboCity.AddItem "Boston"
cboCity.AddItem "Austin"
cboCity.AddItem "Seattle"
cboCity.AddItem "Denver"
cboStatus.AddItem "Active"
cboStatus.AddItem "Inactive"
cboStatus.AddItem "Prospect"
End Sub
Private Sub cmdCancel_Click()
Unload Me
End Sub
Private Sub cmdSave_Click()
Dim tbl As ListObject
Dim newRow As ListRow
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 = cboStatus.Value
MsgBox txtCompanyName.Value & " was added successfully."
Unload Me
End Sub
For å teste det, kjør dette fra et hvilket som helst vanlig modul (ikke UserFormens egen kode):
Sub ShowAddCustomerForm()
frmAddCustomer.Show
End Sub
Trykk F5 med markøren inne i ShowAddCustomerForm — skjemaet skal åpnes, og når du fyller det ut og klikker Lagre, skal en ny rad legges til i tblCustomers.
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
Introduksjon til brukerformer
UserForms har begrenset eller manglende funksjonalitet i Excel for Mac — VBA IDE på Mac mangler full støtte for utforming av UserForms i mange versjoner, noe som kan føre til nettopp denne typen uforklarlig oppførsel.
MsgBox og InputBox dekker enkle ja/nei-spørsmål og ettlinjesvar, men når en kunde faktisk trenger flere felt samtidig — et firmanavn, en kontaktperson, en by, en status. Det er dette en UserForm er til for: et lite tilpasset vindu med egne etiketter, tekstbokser, nedtrekksmenyer og knapper, bygget inne i VBE og styrt helt av koden din.
Opprette et skjema
I VBE, høyreklikk prosjektet ditt i Project Explorer og velg Sett inn → UserForm. En tom utformingsflate vises, sammen med en flytende verktøykasse med kontroller du kan dra inn på skjemaet.
Etiketter, tekstbokser, kombinasjonsbokser og knapper
Hver kontroll du drar inn på skjemaet får et standardnavn som TextBox1 eller CommandButton1 — funksjonelt, men meningsløst når et skjema har seks eller syv kontroller. Den viktigste vanen i denne delen vises i Egenskapsvinduet: gi nytt navn til hver kontroll umiddelbart etter at den er lagt til, ved å bruke et kort prefiks som identifiserer typen (txt for TextBox, cbo for ComboBox, cmd for CommandButton, opt for OptionButton, chk for CheckBox, lst for ListBox) etterfulgt av et beskrivende navn. txtCompanyName er tydelig i koden om tre uker; TextBox1 er det ikke.
Etiketter er vanlige, ikke-interaktive tekstfelt ("Firmanavn:") — brukeren kan se dem, men aldri skrive i eller klikke på dem. Tekstbokser er der fri tekst skrives inn. Kombinasjonsbokser viser en nedtrekksliste med valg, som er akkurat det cboCity og cboStatus brukes til — å begrense City og Status til en kjent liste i stedet for å la brukeren skrive fritt "chicago", "Chicago,IL" og "CHI" for det samme i ulike poster.
Skrive kode bak skjemaet
Dobbeltklikk på en hvilken som helst kontroll på designflaten for å gå direkte til koden — VBA oppretter automatisk en hendelsesprosedyre med navnet ControlName_EventName, og kode skrevet inni denne kjøres hver gang den spesifikke hendelsen skjer for den aktuelle kontrollen. Standardhendelsen for en knapp er Click:
Private Sub UserForm_Initialize()
' runs once, automatically, when the form is first shown
cboCity.AddItem "Chicago"
cboCity.AddItem "Boston"
cboCity.AddItem "Austin"
cboCity.AddItem "Seattle"
cboCity.AddItem "Denver"
cboStatus.AddItem "Active"
cboStatus.AddItem "Inactive"
cboStatus.AddItem "Prospect"
End Sub
Private Sub cmdCancel_Click()
Unload Me
End Sub
UserForm_Initialize er en spesiell hendelsesprosedyre som kjøres automatisk i det øyeblikket skjemaet lastes inn — før brukeren ser noe — noe som gjør dette til riktig sted å fylle ComboBoxes med .AddItem i stedet for å skrive inn valgene manuelt i egenskapsvinduet, spesielt når valgene kan endres eller hentes fra et regneark. Unload Me inne i cmdCancel_Click lukker skjemaet helt; Me refererer alltid til skjemaet koden kjører i, så denne linjen fungerer uendret uansett hva du eventuelt gir skjemaet nytt navn.
Gjennomgangseksempel: Lagre en ny kunde
Dette er prosedyren bak Lagre-knappen — den som faktisk skriver en ny rad inn i tblCustomers:
Private Sub cmdSave_Click()
Dim tbl As ListObject
Dim newRow As ListRow
Set tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers")
Set newRow = tbl.ListRows.Add
newRow.Range(1, 1).Value = "C" & Format(tbl.ListRows.Count + 1, "000")
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 = cboStatus.Value
MsgBox txtCompanyName.Value & " was added successfully."
Unload Me
End Sub
- Set
tbl = ThisWorkbook.Worksheets("Customers").ListObjects("tblCustomers")går hele veien fra skjemaet tilbake til arbeidsboken — et UserForm er bare et annet kodeelement, så alt om ListObjects gjelder uendret; tbl.ListRows.Addlegger til en faktisk ny rad innenfor tabellens grenser i stedet for å skrive forbi siste brukte celle manuelt;txtCompanyName.Value,cboCity.Valueog de andre leser det brukeren har skrevet eller valgt i den aktuelle kontrollen —.Valueer felles for nesten alle kontrolltyper, derfor fungerer samme mønster for både TextBoxes og ComboBoxes;- Den genererte kunde-ID-linjen er en forenklet plassholder for denne øvelsen — ekte ID-generering må sjekke for hull eller gjenbrukte ID-er, noe denne linjen ikke gjør;
- Unload Me til slutt lukker skjemaet først etter at raden er skrevet — å lukke tidligere ville gjort
txtCompanyName.Valueog de andre kontrollverdiene utilgjengelige, siden kontrollene ikke lenger eksisterer når skjemaet er lukket.
Skjemaets "Company Name"-etikett er kun en mer brukervennlig tekst for tabellens Customer-kolonne — koden skriver txtCompanyName.Value inn i denne kolonnen uavhengig av etikettens ordlyd, siden det kun er TextBox-navnet som betyr noe for VBA, ikke den synlige teksten.
Customer ID er ikke med i skjemaet fordi det genereres automatisk av koden ("C0" & (tbl.ListRows.Count + 100)) i stedet for å bli skrevet inn av brukeren — dette gjenspeiler hvordan ekte systemer automatisk nummererer nye poster i stedet for å stole på at en person velger en unik ID.
Oppgave
- Sett inn et nytt UserForm, gi det navnet
frmAddCustomer, og legg til tre TextBoxes (txtCompanyName,txtContact,txtEmail) og to ComboBoxes (cboCity, cboStatus), hver med tilhørende etikett. - Legg til to CommandButtons,
cmdSaveogcmdCancel, og skriv prosedyreneUserForm_InitializeogcmdCancel_Clicknøyaktig som vist. - Skriv
cmdSave_Clicksom vist, og legg deretter til en midlertidig knapp et annet sted i arbeidsboken med kodenfrmAddCustomer.Showfor å teste åpning av skjemaet. - Fyll ut skjemaet for en fiktiv sjette kunde og klikk Save — bekreft at en ny rad vises i tblCustomers med verdiene du har skrevet inn.
1. Lage skjemaet
- Sett inn → UserForm i VBE, og gi det nytt navn via Egenskapsvinduets
(Name)-felt tilfrmAddCustomer— ikke Caption-feltet, som kun endrer tittellinjen. - Dra inn ett Label + ett TextBox-par for hver av Company Name, Contact og Email; ett Label + ett ComboBox-par for City og Status.
- Gi hvert kontroll nytt navn umiddelbart etter at det er lagt til — dette er vanen kapittelet la vekt på. Labels trenger ikke kodevennlige navn siden de aldri refereres i koden, men alle TextBox/ComboBox/Button må ha det.
2. UserForm_Initialize og cmdCancel_Click
- Dobbeltklikk på skjemaets tomme bakgrunn (ikke en kontroll) for å komme til
UserForm_Initialize— dobbeltklikker du påcmdCancelhopper du rett tilcmdCancel_Click. - Begge prosedyrene ble gitt deg nøyaktig i kapittelet — skriv dem inn uendret.
3. Testing med en midlertidig knapp
- Denne knappen trenger ikke ligge på skjemaet — legg den på et hvilket som helst regneark via Utvikler → Sett inn → Knapp (skjemakontroll), eller bare kjør en enlinjes
Subfra VBE i stedet for å legge til en regneark-knapp. frmAddCustomer.Shower hele koden som trengs for å vise skjemaet.
4. Testing av full lagring
- Fyll ut alle feltene og velg verdier fra begge nedtrekkslistene før du klikker Lagre — et tomt ComboBox-valg vil skrive en tom celle.
- Sjekk
tblCustomersetterpå for en ny rad med en ID på formenC00x.
Private Sub UserForm_Initialize()
' runs once, automatically, when the form is first shown
cboCity.AddItem "Chicago"
cboCity.AddItem "Boston"
cboCity.AddItem "Austin"
cboCity.AddItem "Seattle"
cboCity.AddItem "Denver"
cboStatus.AddItem "Active"
cboStatus.AddItem "Inactive"
cboStatus.AddItem "Prospect"
End Sub
Private Sub cmdCancel_Click()
Unload Me
End Sub
Private Sub cmdSave_Click()
Dim tbl As ListObject
Dim newRow As ListRow
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 = cboStatus.Value
MsgBox txtCompanyName.Value & " was added successfully."
Unload Me
End Sub
For å teste det, kjør dette fra et hvilket som helst vanlig modul (ikke UserFormens egen kode):
Sub ShowAddCustomerForm()
frmAddCustomer.Show
End Sub
Trykk F5 med markøren inne i ShowAddCustomerForm — skjemaet skal åpnes, og når du fyller det ut og klikker Lagre, skal en ny rad legges til i tblCustomers.
Takk for tilbakemeldingene dine!