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:
-
lblUserName
för enLabel
som anger ett användarnamn. -
txtUserName
för enTextBox
kontroll där användaren kan ange ett användarnamn. -
cboUserName
för enComboBox
kontroll där användaren kan ange eller välja ett användarnamn. -
lstUserName
för enListBox
kontroll där användaren kan välja ett användarnamn. -
btnOk
ellercmdOk
för enButton
kontroll 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.
-
UserNameLabel
för en skrivskyddad etikett som anger ett användarnamn. -
UserNameInput
för en kontroll där användaren kan ange eller välja ett användarnamn. -
OkButton
fö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 .