Sök…
Bästa metoder
En UserForm är en UserForm med en designer och en standardinstans . Designer kan nås genom att trycka på Shift + F7 när man tittar på koden bakom , och koden bakom kan nås genom att trycka på F7 när man tittar på designern .
Arbeta med en ny instans varje gång.
Som en klassmodul är en form därför en plan för ett objekt . Eftersom ett formulär kan innehålla tillstånd och data är det en bättre praxis att arbeta med en ny instans av klassen snarare än med standard / global:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
'...
End If
End With
Istället för:
UserForm1.Show vbModal
If Not UserForm1.IsCancelled Then
'...
End If
Arbeta med standardinstansen kan leda till subtila buggar när formuläret stängs med den röda "X" -knappen och / eller när Unload Me används i koden bakom.
Implementera logiken någon annanstans.
Ett formulär ska handla om något annat än presentation: en knapp Click handler som ansluter till en databas och driver en parametriserade fråga baserat på användarnas input, gör för många saker.
Istället implementerar den tillämpliga logiken i koden som är ansvarig för att visa formuläret, eller ännu bättre, i dedikerade moduler och procedurer.
Skriv koden på ett sådant sätt att UserForm bara någonsin är ansvarig för att veta hur man ska visa och samla in data: var informationen kommer från, eller vad som händer med uppgifterna i efterhand, är inget som berörs av det.
Uppringare ska inte bry sig om kontroller.
Gör en väldefinierad modell för formuläret att arbeta med, antingen i sin egen dedikerade klassmodul, eller inkapslats inom formulärets kod bakom sig själv - avslöja modellen med Property Get procedurer, och låt klientkoden fungera med dessa: detta gör formen en abstraktion över kontroller och deras snygga-grotta detaljer, som bara exponerar relevant information för klientkoden.
Detta betyder kod som ser ut så här:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
MsgBox .Message, vbInformation
End If
End With
Istället för det här:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
MsgBox .txtMessage.Text, vbInformation
End If
End With
Hantera händelsen QueryClose.
Formulär har vanligtvis en Stäng- knapp, och instruktioner / dialogrutor har Ok- och Avbryt- knappar; användaren kan stänga formuläret med hjälp av formulärets kontrollruta (den röda "X" -knappen), som förstör forminstansen som standard (ytterligare en god anledning att arbeta med en ny instans varje gång ).
With New UserForm1
.Show vbModal
If Not .IsCancelled Then 'if QueryClose isn't handled, this can raise a runtime error.
'...
End With
End With
Det enklaste sättet att hantera händelsen QueryClose är att ställa in Cancel parametern till True och sedan dölja formen istället för att stänga den:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Cancel = True
Me.Hide
End Sub
På så sätt förstör aldrig "X" -knappen instansen, och den som ringer kan säkert komma åt alla allmänna medlemmar.
Göm, stäng inte.
Koden som skapar ett objekt bör vara ansvarig för att förstöra det: det är inte formens ansvar att lossa och avsluta sig själv.
Undvik att använda Unload Me i ett formulärs kod bakom. Ring Me.Hide istället så att Me.Hide fortfarande kan använda objektet som det skapade när formuläret stängs.
Namnge saker.
Använd egenskaperna verktygsfönstret ( F4 ) för att noggrant namnge varje kontroll på ett formulär. Namnet på en kontroll används i koden bakom, så såvida du inte använder ett refactoring-verktyg som kan hantera detta, kommer att byta namn på en kontroll bryta koden - så det är mycket lättare att göra saker rätt i första hand än att försöka att pussla ut exakt vilken av de 20 textrutorna TextBox12 står för.
Traditionellt namnges UserForm-kontroller med prefix av ungersk stil:
-
lblUserNameför enLabelsom anger ett användarnamn. -
txtUserNameför enTextBoxkontroll där användaren kan ange ett användarnamn. -
cboUserNameför enComboBoxkontroll där användaren kan ange eller välja ett användarnamn. -
lstUserNameför enListBoxkontroll där användaren kan välja ett användarnamn. -
btnOkellercmdOkför enButtonkontroll märkt "Ok".
Problemet är att när t.ex. användargränssnittet blir nytt ComboBox och en ComboBox ändras till en ListBox , måste namnet ändras för att återspegla den nya kontrolltypen: det är bättre att namnge kontroller för vad de representerar, snarare än efter deras kontrolltyp - att koppla från kod från UI så mycket som möjligt.
-
UserNameLabelför en skrivskyddad etikett som anger ett användarnamn. -
UserNameInputför en kontroll där användaren kan ange eller välja ett användarnamn. -
OkButtonför en kommandoknapp märkt "Ok".
Oavsett vilken stil som väljs, är allt bättre än att lämna alla kontroller sina standardnamn. Konsistens i namngivningstil är också idealisk.
Hantera QueryClose
Händelsen QueryClose upp när ett formulär QueryClose på att stängas, oavsett om det är via användaråtgärder eller programmatiskt. CloseMode parametern innehåller ett VbQueryClose enumvärde som indikerar hur formen stängdes:
| Konstant | Beskrivning | Värde |
|---|---|---|
vbFormControlMenu | Formuläret stängs som svar på användarens åtgärder | 0 |
vbFormCode | Formuläret stängs som svar på ett Unload uttalande | 1 |
vbAppWindows | Windows-sessionen avslutas | 2 |
vbAppTaskManager | Windows Task Manager stänger värdapplikationen | 3 |
vbFormMDIForm | Stöds inte i VBA | 4 |
För bättre läsbarhet är det bäst att använda dessa konstanter istället för att använda deras värde direkt.
En avbokningsbar UserForm
Får ett formulär med en Avbryt- knapp

Formulärets kod bakom kan se ut så här:
Option Explicit
Private Type TView
IsCancelled As Boolean
SomeOtherSetting As Boolean
'other properties skipped for brievety
End Type
Private this As TView
Public Property Get IsCancelled() As Boolean
IsCancelled = this.IsCancelled
End Property
Public Property Get SomeOtherSetting() As Boolean
SomeOtherSetting = this.SomeOtherSetting
End Property
'...more properties...
Private Sub SomeOtherSettingInput_Change()
this.SomeOtherSetting = CBool(SomeOtherSettingInput.Value)
End Sub
Private Sub OkButton_Click()
Me.Hide
End Sub
Private Sub CancelButton_Click()
this.IsCancelled = True
Me.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = VbQueryClose.vbFormControlMenu Then
Cancel = True
this.IsCancelled = True
Me.Hide
End If
End Sub
Ringkoden kunde då visa formuläret och veta om den avbröts:
Public Sub DoSomething()
With New UserForm1
.Show vbModal
If .IsCancelled Then Exit Sub
If .SomeOtherSetting Then
'setting is enabled
Else
'setting is disabled
End If
End With
End Sub
IsCancelled returnerar True när du klickar på knappen Avbryt eller när användaren stänger formuläret med kontrollrutan .