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 en Label som anger ett användarnamn.
  • txtUserName för en TextBox kontroll där användaren kan ange ett användarnamn.
  • cboUserName för en ComboBox kontroll där användaren kan ange eller välja ett användarnamn.
  • lstUserName för en ListBox kontroll där användaren kan välja ett användarnamn.
  • btnOk eller cmdOk för en Button 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

någon provform

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 .



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow