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 wird static verwendet, um ein Klassenmitglied (Feld, Eigenschaft, Methode, ...) zum Typ und nicht zur Instanz zu machen . Code im static Kontext kann nicht auf Code im Instanzkontext verweisen. Das VBA-Schlüsselwort Static 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 Mitglied Property 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ür Public Felder in Standardmodulen, ist aber illegal in Klassenmodulen und ist veraltet sowieso - das bevorzugt Public 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

static_UDF
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)



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow