Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lære Introduksjon til brukerformer | Brukerinteraksjon
Excel VBA for Forretningsautomatisering

Introduksjon til brukerformer

Sveip for å vise menyen

Note
Merk

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.

Figur 5.3

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.

Skjemaopprettingsflyt

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
Gjennomgang linje for linje
expand arrow
  • 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.Add legger til en faktisk ny rad innenfor tabellens grenser i stedet for å skrive forbi siste brukte celle manuelt;
  • txtCompanyName.Value, cboCity.Value og de andre leser det brukeren har skrevet eller valgt i den aktuelle kontrollen — .Value er 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.Value og de andre kontrollverdiene utilgjengelige, siden kontrollene ikke lenger eksisterer når skjemaet er lukket.
Note
Merk

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.

Note
Merk

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

  1. 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.
  2. Legg til to CommandButtons, cmdSave og cmdCancel, og skriv prosedyrene UserForm_Initialize og cmdCancel_Click nøyaktig som vist.
  3. Skriv cmdSave_Click som vist, og legg deretter til en midlertidig knapp et annet sted i arbeidsboken med koden frmAddCustomer.Show for å teste åpning av skjemaet.
  4. 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.
Tips
expand arrow

1. Lage skjemaet

  • Sett inn → UserForm i VBE, og gi det nytt navn via Egenskapsvinduets (Name)-felt til frmAddCustomer — 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å cmdCancel hopper du rett til cmdCancel_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 Sub fra VBE i stedet for å legge til en regneark-knapp.
  • frmAddCustomer.Show er 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 tblCustomers etterpå for en ny rad med en ID på formen C00x.
Løsning
expand arrow
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.

Testing av skjemaet
Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 5. Kapittel 2

Spør AI

expand

Spør AI

ChatGPT

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

Note
Merk

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.

Figur 5.3

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.

Skjemaopprettingsflyt

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
Gjennomgang linje for linje
expand arrow
  • 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.Add legger til en faktisk ny rad innenfor tabellens grenser i stedet for å skrive forbi siste brukte celle manuelt;
  • txtCompanyName.Value, cboCity.Value og de andre leser det brukeren har skrevet eller valgt i den aktuelle kontrollen — .Value er 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.Value og de andre kontrollverdiene utilgjengelige, siden kontrollene ikke lenger eksisterer når skjemaet er lukket.
Note
Merk

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.

Note
Merk

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

  1. 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.
  2. Legg til to CommandButtons, cmdSave og cmdCancel, og skriv prosedyrene UserForm_Initialize og cmdCancel_Click nøyaktig som vist.
  3. Skriv cmdSave_Click som vist, og legg deretter til en midlertidig knapp et annet sted i arbeidsboken med koden frmAddCustomer.Show for å teste åpning av skjemaet.
  4. 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.
Tips
expand arrow

1. Lage skjemaet

  • Sett inn → UserForm i VBE, og gi det nytt navn via Egenskapsvinduets (Name)-felt til frmAddCustomer — 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å cmdCancel hopper du rett til cmdCancel_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 Sub fra VBE i stedet for å legge til en regneark-knapp.
  • frmAddCustomer.Show er 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 tblCustomers etterpå for en ny rad med en ID på formen C00x.
Løsning
expand arrow
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.

Testing av skjemaet
Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 5. Kapittel 2
some-alt