VBA
Variablen deklarieren
Suche…
Implizite und explizite Erklärung
Wenn ein Codemodul keine Option Explicit
am oberen Option Explicit
des Moduls enthält, erstellt der Compiler automatisch (dh "implizit") Variablen, wenn Sie diese verwenden. Sie haben standardmäßig den Variablentyp Variant
.
Public Sub ExampleDeclaration()
someVariable = 10 '
someOtherVariable = "Hello World"
'Both of these variables are of the Variant type.
End Sub
Wenn im obigen Code Option Explicit
angegeben ist, wird der Code unterbrochen, da die erforderlichen Dim
Anweisungen für someVariable
und someOtherVariable
.
Option Explicit
Public Sub ExampleDeclaration()
Dim someVariable As Long
someVariable = 10
Dim someOtherVariable As String
someOtherVariable = "Hello World"
End Sub
Es wird empfohlen, Option Explicit in Codemodulen zu verwenden, um sicherzustellen, dass Sie alle Variablen deklarieren.
Informationen zum Festlegen dieser Option finden Sie unter VBA-Best Practices .
Variablen
Umfang
Eine Variable kann deklariert werden (um den Sichtbarkeitsgrad zu erhöhen):
- Verwenden Sie auf Prozedurebene das
Dim
Schlüsselwort in einer beliebigen Prozedur. eine lokale Variable . - Auf Modulebene mit dem Schlüsselwort "
Private
in einem beliebigen Modultyp. ein privates Feld . - Auf Instanzebene mit dem
Friend
Schlüsselwort in einem beliebigen Klassenmodul. ein Freundfeld - Auf Instanzebene: Verwenden Sie das Schlüsselwort
Public
in einem beliebigen Klassenmodul. ein öffentliches Feld . - Verwenden Sie das
Public
Schlüsselwort global in einem Standardmodul . eine globale Variable .
Variablen sollten immer mit dem kleinstmöglichen Umfang deklariert werden: Bevorzugen Sie die Übergabe von Parametern an Prozeduren, anstatt globale Variablen zu deklarieren.
Weitere Informationen finden Sie unter Zugriffsmodifizierer .
Lokale Variablen
Verwenden Sie das Dim
Schlüsselwort, um eine lokale Variable zu deklarieren:
Dim identifierName [As Type][, identifierName [As Type], ...]
Der Teil [As Type]
der Deklarationssyntax ist optional. Wenn angegeben, wird der Datentyp der Variablen festgelegt, der bestimmt, wie viel Speicher dieser Variablen zugewiesen wird. Dies deklariert eine String
Variable:
Dim identifierName As String
Wenn kein Typ angegeben wird, ist der Typ implizit Variant
:
Dim identifierName 'As Variant is implicit
Die VBA-Syntax unterstützt auch das Deklarieren mehrerer Variablen in einer einzigen Anweisung:
Dim someString As String, someVariant, someValue As Long
Beachten Sie, dass für jede Variable (als 'Variant'-Variable) der [As Type]
angegeben werden muss. Dies ist eine relativ häufige Falle:
Dim integer1, integer2, integer3 As Integer 'Only integer3 is an Integer.
'The rest are Variant.
Statische Variablen
Lokale Variablen können auch Static
. In VBA wird das Static
Schlüsselwort verwendet, um eine Variable an den Wert zu erinnern, den sie beim letzten Aufruf einer Prozedur hatte:
Private Sub DoSomething()
Static values As Collection
If values Is Nothing Then
Set values = New Collection
values.Add "foo"
values.Add "bar"
End If
DoSomethingElse values
End Sub
Hier wird die values
als Static
lokal deklariert. Da es sich um eine Objektvariable handelt , wird sie mit Nothing
initialisiert. Die Bedingung , dass die Erklärung folgt überprüft , ob die Objektreferenz wurde Set
vor - wenn es das erste Mal ist das Verfahren läuft, wird die Sammlung initialisiert. DoSomethingElse
möglicherweise Elemente hinzu oder entfernt sie, und diese werden beim nächsten DoSomething
weiterhin in der Auflistung DoSomething
.
Alternative
Das
Static
Schlüsselwort von VBA kann leicht missverstanden werden - insbesondere von erfahrenen Programmierern, die normalerweise in anderen Sprachen arbeiten. In vielen Sprachen wirdstatic
verwendet, um ein Klassenmitglied (Feld, Eigenschaft, Methode, ...) zum Typ und nicht zur Instanz zu machen . Code imstatic
Kontext kann nicht auf Code im Instanzkontext verweisen. Das VBA-SchlüsselwortStatic
bedeutet etwas völlig anderes.
Eine Static
lokale Variable kann häufig genauso gut als Private
Variable auf Modulebene (Feld) implementiert werden. Dies stellt jedoch das Prinzip in Frage, nach dem eine Variable mit dem kleinstmöglichen Umfang deklariert werden sollte. Vertrauen Sie auf Ihre Instinkte, verwenden Sie, was Sie bevorzugen - beide werden funktionieren ... aber Static
ohne zu verstehen, was es tut, kann zu interessanten Fehlern führen.
Dim vs. Private
Das Schlüsselwort Dim
ist auf Verfahrens- und Modulebene legal. Die Verwendung auf Modulebene entspricht der Verwendung des Private
Schlüsselworts:
Option Explicit
Dim privateField1 As Long 'same as Private privateField2 as Long
Private privateField2 As Long 'same as Dim privateField2 as Long
Das Schlüsselwort " Private
ist nur auf Modulebene zulässig. Dadurch werden Dim
für lokale Variablen reserviert und Modulvariablen mit Private
deklariert, insbesondere mit dem Public
Schlüsselwort Public
, das ohnehin verwendet werden müsste, um ein öffentliches Mitglied zu deklarieren. Alternativ kann Dim
überall verwendet werden - worauf es ankommt, ist die Konsistenz :
"Private Felder"
- DO verwendet
Private
eine Variable auf Modulebene zu erklären. - DO verwenden
Dim
eine lokale Variable zu deklarieren. - Verwenden Sie KEINE
Dim
eine Variable auf Modulebene zu erklären.
"Überall verdunkeln"
- DO verwendet
Dim
alles privat / local zu erklären. - Verwenden Sie KEIN
Private
, um eine Variable auf Modulebene zu deklarieren. - AVOID- Deklaration für
Public
Felder. *
* Generell sollte man sowieso vermeiden, Public
oder Global
Felder zu deklarieren.
Felder
Eine auf Modulebene im Deklarationsabschnitt oben im Modulhauptteil deklarierte Variable ist ein Feld . Ein in einem Standardmodul deklariertes Public
Feld ist eine globale Variable :
Public PublicField As Long
Auf eine Variable mit globalem Gültigkeitsbereich kann von überall aus zugegriffen werden, einschließlich anderer VBA-Projekte, die auf das Projekt verweisen, in dem es deklariert ist.
Verwenden Sie den Friend
Modifizierer, um eine Variable global / public zu machen, jedoch nur innerhalb des Projekts sichtbar zu machen:
Friend FriendField As Long
Dies ist besonders nützlich in Add-Ins, bei denen die Absicht besteht, dass andere VBA-Projekte auf das Add-In-Projekt verweisen und die öffentliche API verwenden können.
Friend FriendField As Long 'public within the project, aka for "friend" code
Public PublicField As Long 'public within and beyond the project
Freundfelder sind in Standardmodulen nicht verfügbar.
Instanzfelder
Eine Variable auf Modulebene deklarierte, im Deklarationsbereich an der Oberseite des Körpers eines Klassenmodul (einschließlich ThisWorkbook
, ThisDocument
, Worksheet
, UserForm
und Klasse - Module), ist eine Instanz Feld: es existiert nur solange , wie es eine Instanz die Klasse um.
'> Class1
Option Explicit
Public PublicField As Long
'> Module1
Option Explicit
Public Sub DoSomething()
'Class1.PublicField means nothing here
With New Class1
.PublicField = 42
End With
'Class1.PublicField means nothing here
End Sub
Felder einkapseln
Instanzdaten werden häufig als Private
gehalten und gekapselt überspielt. Ein privates Feld kann mithilfe einer Property
Prozedur Property
werden. Um eine private Variable öffentlich zugänglich zu machen, ohne dem Aufrufer Schreibzugriff zu gewähren, implementiert ein Klassenmodul (oder ein Standardmodul) ein Property Get
Member:
Option Explicit
Private encapsulated As Long
Public Property Get SomeValue() As Long
SomeValue = encapsulated
End Property
Public Sub DoSomething()
encapsulated = 42
End Sub
Die Klasse selbst kann den gekapselten Wert ändern, der aufrufende Code kann jedoch nur auf die Public
Mitglieder (und die Friend
Mitglieder, wenn sich der Aufrufer im selben Projekt befindet) zugreifen.
Um dem Anrufer das Ändern zu ermöglichen:
- Ein gekapselter Wert , ein Modul macht ein
Property Let
. - Ein gekapselter Objektverweis , ein Modul macht ein
Property Set
MitgliedProperty Set
.
Konstanten (Const)
Wenn Sie einen Wert haben, der in Ihrer Anwendung nie geändert wird, können Sie eine benannte Konstante definieren und anstelle eines Literalwerts verwenden.
Sie können Const nur auf Modul- oder Prozedurebene verwenden. Dies bedeutet, dass der Deklarationskontext für eine Variable eine Klasse, eine Struktur, ein Modul, eine Prozedur oder ein Block sein muss und keine Quelldatei, Namespace oder Schnittstelle sein kann.
Public Const GLOBAL_CONSTANT As String = "Project Version #1.000.000.001"
Private Const MODULE_CONSTANT As String = "Something relevant to this Module"
Public Sub ExampleDeclaration()
Const SOME_CONSTANT As String = "Hello World"
Const PI As Double = 3.141592653
End Sub
Die Angabe von Konstantentypen kann zwar als bewährte Methode angesehen werden, ist jedoch nicht unbedingt erforderlich. Wenn Sie den Typ nicht angeben, führt dies immer noch zum richtigen Typ:
Public Const GLOBAL_CONSTANT = "Project Version #1.000.000.001" 'Still a string
Public Sub ExampleDeclaration()
Const SOME_CONSTANT = "Hello World" 'Still a string
Const DERIVED_CONSTANT = SOME_CONSTANT 'DERIVED_CONSTANT is also a string
Const VAR_CONSTANT As Variant = SOME_CONSTANT 'VAR_CONSTANT is Variant/String
Const PI = 3.141592653 'Still a double
Const DERIVED_PI = PI 'DERIVED_PI is also a double
Const VAR_PI As Variant = PI 'VAR_PI is Variant/Double
End Sub
Beachten Sie, dass dies spezifisch für Konstanten ist und im Gegensatz zu Variablen, bei denen die Angabe des Typs nicht zu einem Variant-Typ führt.
Es ist zwar möglich, eine Konstante explizit als String zu deklarieren, es ist jedoch nicht möglich, eine Konstante mit einer String-Syntax mit fester Breite zu deklarieren
'This is a valid 5 character string constant
Const FOO As String = "ABCDE"
'This is not valid syntax for a 5 character string constant
Const FOO As String * 5 = "ABCDE"
Zugriffsmodifizierer
Die Dim
Anweisung sollte für lokale Variablen reserviert sein. Bevorzugen Sie auf Modulebene explizite Zugriffsmodifizierer:
-
Private
für private Felder, auf die nur innerhalb des Moduls zugegriffen werden kann, in dem sie deklariert sind. -
Public
für öffentliche Felder und globale Variablen, auf die mit beliebigem aufrufendem Code zugegriffen werden kann. -
Friend
für Variablen innerhalb des Projekts öffentlich, aber für andere referenzierende VBA-Projekte nicht zugänglich (relevant für Add-Ins) -
Global
kann auch verwendet wird fürPublic
Felder in Standardmodulen, ist aber illegal in Klassenmodulen und ist veraltet sowieso - das bevorzugtPublic
statt Modifikator. Dieser Modifikator ist auch für Verfahren nicht zulässig.
Zugriffsmodifizierer sind auf Variablen und Prozeduren gleichermaßen anwendbar.
Private ModuleVariable As String
Public GlobalVariable As String
Private Sub ModuleProcedure()
ModuleVariable = "This can only be done from within the same Module"
End Sub
Public Sub GlobalProcedure()
GlobalVariable = "This can be done from any Module within this Project"
End Sub
Option Privates Modul
Öffentliche parameterlose Sub
in Standardmodulen werden als Makros verfügbar gemacht und können an Steuerelemente und Tastenkombinationen im Hostdokument angehängt werden.
Umgekehrt werden öffentliche Function
in Standardmodulen als benutzerdefinierte Funktionen (UDFs) in der Hostanwendung verfügbar gemacht.
Wenn Sie das Option Private Module
oben in einem Standardmodul angeben, wird verhindert, dass seine Mitglieder als Makros und UDFs für die Hostanwendung angezeigt werden.
Typ Hinweise
Typhinweise werden stark entmutigt. Sie existieren und werden hier aus historischen Gründen und aus Gründen der Rückwärtskompatibilität dokumentiert. Verwenden Sie stattdessen die Syntax As [DataType]
.
Public Sub ExampleDeclaration()
Dim someInteger% '% Equivalent to "As Integer"
Dim someLong& '& Equivalent to "As Long"
Dim someDecimal@ '@ Equivalent to "As Currency"
Dim someSingle! '! Equivalent to "As Single"
Dim someDouble# '# Equivalent to "As Double"
Dim someString$ '$ Equivalent to "As String"
Dim someLongLong^ '^ Equivalent to "As LongLong" in 64-bit VBA hosts
End Sub
Durch Typhinweise wird die Lesbarkeit von Code erheblich verringert und eine ungarische Notation unterstützt, die auch die Lesbarkeit behindert:
Dim strFile$
Dim iFile%
Deklarieren Sie stattdessen Variablen näher an ihrer Verwendung und benennen Sie die Dinge nach dem Verwendungszweck, nicht nach ihrem Typ:
Dim path As String
Dim handle As Integer
Typhinweise können auch für Literale verwendet werden, um einen bestimmten Typ durchzusetzen. Standardmäßig wird ein numerisches Literal, das kleiner als 32.768 ist, als Integer
Literal interpretiert. Mit einem Typhinweis können Sie Folgendes steuern:
Dim foo 'implicit Variant
foo = 42& ' foo is now a Long
foo = 42# ' foo is now a Double
Debug.Print TypeName(42!) ' prints "Single"
Typhinweise werden für Literale normalerweise nicht benötigt, da sie einer mit einem expliziten Typ deklarierten Variablen zugewiesen werden oder implizit in den entsprechenden Typ konvertiert werden, wenn sie als Parameter übergeben werden. Implizite Konvertierungen können mit einer der expliziten Typkonvertierungsfunktionen vermieden werden:
'Calls procedure DoSomething and passes a literal 42 as a Long using a type hint
DoSomething 42&
'Calls procedure DoSomething and passes a literal 42 explicitly converted to a Long
DoSomething CLng(42)
Integrierte Funktionen mit String-Rückgabe
Die Mehrheit der integrierten Funktionen, die Strings verarbeiten, gibt es in zwei Versionen: Eine lose typisierte Version, die eine Variant
zurückgibt, und eine stark typisierte Version (die mit $
endet), die einen String
zurückgibt. Wenn Sie den Rückgabewert nicht einer Variant
zuweisen, sollten Sie die Version vorziehen, die einen String
zurückgibt. Andernfalls erfolgt eine implizite Konvertierung des Rückgabewerts.
Debug.Print Left(foo, 2) 'Left returns a Variant
Debug.Print Left$(foo, 2) 'Left$ returns a String
Diese Funktionen sind:
- VBA.Conversion.Error -> VBA.Conversion.Error $
- VBA.Conversion.Hex -> VBA.Conversion.Hex $
- VBA.Conversion.Oct -> VBA.Conversion.Oct $
- VBA.Conversion.Str -> VBA.Conversion.Str $
- VBA.FileSystem.CurDir -> VBA.FileSystem.CurDir $
- VBA. [_ HiddenModule] .Input -> VBA. [_ HiddenModule] .Input $
- VBA. [_ HiddenModule] .InputB -> VBA. [_ HiddenModule] .InputB $
- VBA.Interaction.Command -> VBA.Interaction.Command $
- VBA.Interaction.Environ -> VBA.Interaction.Environ $
- VBA.Strings.Chr -> VBA.Strings.Chr $
- VBA.Strings.ChrB -> VBA.Strings.ChrB $
- VBA.Strings.ChrW -> VBA.Strings.ChrW $
- VBA.Strings.Format -> VBA.Strings.Format $
- VBA.Strings.LCase -> VBA.Strings.LCase $
- VBA.Strings.Left -> VBA.Strings.Left $
- VBA.Strings.LeftB -> VBA.Strings.LeftB $
- VBA.Strings.LTtrim -> VBA.Strings.LTrim $
- VBA.Strings.Mid -> VBA.Strings.Mid $
- VBA.Strings.MidB -> VBA.Strings.MidB $
- VBA.Strings.Right -> VBA.Strings.Right $
- VBA.Strings.RightB -> VBA.Strings.RightB $
- VBA.Strings.RTrim -> VBA.Strings.RTrim $
- VBA.Strings.Space -> VBA.Strings.Space $
- VBA.Strings.Str -> VBA.Strings.Str $
- VBA.Strings.String -> VBA.Strings.String $
- VBA.Strings.Trim -> VBA.Strings.Trim $
- VBA.Strings.UCase -> VBA.Strings.UCase $
Beachten Sie, dass diese Funktion Aliase sind, nicht ganz Type Hints. Die Left
Funktion entspricht der verborgenen B_Var_Left
Funktion, während die Left$
-Version der verborgenen B_Str_Left
Funktion entspricht.
In sehr frühen Versionen von VBA ist das Zeichen $
kein erlaubtes Zeichen und der Funktionsname musste in eckige Klammern gesetzt werden. In Word Basic gab es viele, viele weitere Funktionen, die Zeichenfolgen zurückgaben, die mit $ endeten.
Zeichenfolgen mit fester Länge deklarieren
In VBA können Strings mit einer bestimmten Länge deklariert werden. Sie werden automatisch aufgefüllt oder abgeschnitten, um die angegebene Länge beizubehalten.
Public Sub TwoTypesOfStrings()
Dim FixedLengthString As String * 5 ' declares a string of 5 characters
Dim NormalString As String
Debug.Print FixedLengthString ' Prints " "
Debug.Print NormalString ' Prints ""
FixedLengthString = "123" ' FixedLengthString now equals "123 "
NormalString = "456" ' NormalString now equals "456"
FixedLengthString = "123456" ' FixedLengthString now equals "12345"
NormalString = "456789" ' NormalString now equals "456789"
End Sub
Wann wird eine statische Variable verwendet?
Eine lokal deklarierte statische Variable wird nicht zerstört und verliert ihren Wert nicht, wenn die Sub-Prozedur beendet wird. Nachfolgende Aufrufe der Prozedur erfordern keine Neuinitialisierung oder Zuweisung, obwohl Sie eventuell gespeicherte Werte auf Null setzen möchten.
Dies ist besonders nützlich, wenn ein Objekt in einem "Helfer" -Unter, das wiederholt aufgerufen wird, zu spät gebunden wird.
Ausschnitt 1: Verwenden Sie ein Scripting.Dictionary-Objekt in vielen Arbeitsblättern erneut
Option Explicit
Sub main()
Dim w As Long
For w = 1 To Worksheets.Count
processDictionary ws:=Worksheets(w)
Next w
End Sub
Sub processDictionary(ws As Worksheet)
Dim i As Long, rng As Range
Static dict As Object
If dict Is Nothing Then
'initialize and set the dictionary object
Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Else
'remove all pre-existing dictionary entries
' this may or may not be desired if a single dictionary of entries
' from all worksheets is preferred
dict.RemoveAll
End If
With ws
'work with a fresh dictionary object for each worksheet
' without constructing/destructing a new object each time
' or do not clear the dictionary upon subsequent uses and
' build a dictionary containing entries from all worksheets
End With
End Sub
Ausschnitt 2: Erstellen Sie eine Arbeitsblatt-UDF, die das VBScript.RegExp-Objekt später bindet
Option Explicit
Function numbersOnly(str As String, _
Optional delim As String = ", ")
Dim n As Long, nums() As Variant
Static rgx As Object, cmat As Object
'with rgx as static, it only has to be created once
'this is beneficial when filling a long column with this UDF
If rgx Is Nothing Then
Set rgx = CreateObject("VBScript.RegExp")
Else
Set cmat = Nothing
End If
With rgx
.Global = True
.MultiLine = True
.Pattern = "[0-9]{1,999}"
If .Test(str) Then
Set cmat = .Execute(str)
'resize the nums array to accept the matches
ReDim nums(cmat.Count - 1)
'populate the nums array with the matches
For n = LBound(nums) To UBound(nums)
nums(n) = cmat.Item(n)
Next n
'convert the nums array to a delimited string
numbersOnly = Join(nums, delim)
Else
numbersOnly = vbNullString
End If
End With
End Function
Beispiel für eine UDF mit statischem Objekt, das über eine halbe Million Zeilen gefüllt ist
* Verstrichene Zeiten zum Füllen von 500.000 Zeilen mit UDF: - mit Dim rgx As Object : 148,74 Sekunden - mit Static rgx As Object : 26,07 Sekunden * Diese sollten nur für den relativen Vergleich berücksichtigt werden. Ihre eigenen Ergebnisse variieren je nach Komplexität und
Umfang der durchgeführten Operationen.
Denken Sie daran, dass eine UDF während der Lebensdauer einer Arbeitsmappe nicht einmal berechnet wird. Sogar eine nichtflüchtige UDF wird neu berechnet, wenn sich die Werte in dem Bereich bzw. den Bereichen ändern, auf die sie verweisen. Jedes nachfolgende Neuberechnungsereignis erhöht nur die Vorteile einer statisch deklarierten Variablen.
- Eine statische Variable steht für die Lebensdauer des Moduls zur Verfügung, nicht die Prozedur oder Funktion, in der es deklariert und zugewiesen wurde.
- Statische Variablen können nur lokal deklariert werden.
- Statische Variablen enthalten viele der gleichen Eigenschaften wie eine private Modulebenenvariable, jedoch mit eingeschränktem Umfang.
Zugehörige Verweise: Statisch (Visual Basic)