Vba excel static переменные

Неявная и явная декларация

Если модуль кода не содержит Option Explicit в верхней части модуля, тогда компилятор автоматически (то есть «неявно») создает переменные для вас, когда вы их используете. Они будут использовать переменную типа Variant .

Public Sub ExampleDeclaration()    

    someVariable = 10                  ' 
    someOtherVariable = "Hello World"
    'Both of these variables are of the Variant type.

End Sub

В приведенном выше коде, если указан параметр Option Explicit , код будет прерываться, потому что ему не нужны необходимые инструкции Dim для someVariable и someOtherVariable .

Option Explicit

Public Sub ExampleDeclaration()   

    Dim someVariable As Long 
    someVariable = 10

    Dim someOtherVariable As String
    someOtherVariable = "Hello World"

End Sub

Рекомендуется использовать Option Explicit в модулях кода, чтобы гарантировать, что вы объявите все переменные.

См. VBA Best Practices, как установить этот параметр по умолчанию.

переменные

Объем

Переменная может быть объявлена ​​(при увеличении уровня видимости):

  • На уровне процедуры, используя ключевое слово Dim в любой процедуре; локальная переменная .
  • На уровне модуля, используя ключевое слово Private в модуле любого типа; частное поле .
  • На уровне экземпляра используйте ключевое слово Friend в модуле любого типа; поле друга .
  • На уровне экземпляра, используя ключевое слово Public в модуле класса любого типа; публичное поле .
  • Глобально, используя ключевое слово Public в стандартном модуле ; глобальная переменная .

Переменные всегда должны быть объявлены с наименьшей возможной областью: предпочитайте передавать параметры процедурам, а не объявлять глобальные переменные.

Дополнительную информацию см. В разделе Модификаторы доступа .


Местные переменные

Используйте ключевое слово Dim чтобы объявить локальную переменную :

Dim identifierName [As Type][, identifierName [As Type], ...]

Параметр [As Type] синтаксиса объявления является необязательным. Когда указано, он устанавливает тип данных переменной, который определяет, сколько памяти будет выделено этой переменной. Это объявляет переменную String :

Dim identifierName As String

Если тип не указан, тип неявно Variant :

Dim identifierName 'As Variant is implicit

Синтаксис VBA также поддерживает объявление нескольких переменных в одном выражении:

Dim someString As String, someVariant, someValue As Long

Обратите внимание, что [As Type] должен быть указан для каждой переменной (кроме «Variant»). Это относительно распространенная ловушка:

Dim integer1, integer2, integer3 As Integer 'Only integer3 is an Integer. 
                                            'The rest are Variant.

Статические переменные

Локальные переменные также могут быть Static . В VBA ключевое слово Static используется для того, чтобы переменная «запомнила» значение, которое она имела, в последний раз, когда была вызвана процедура:

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

Здесь коллекция values объявляется как Static локальная; потому что это переменная объекта , она инициализируется Nothing . Условие, следующее за объявлением, проверяет, была ли ссылка на объект Set раньше — если она выполняется в первый раз, процедура инициализируется. DoSomethingElse может добавлять или удалять элементы, и они все равно будут в коллекции в следующий раз, когда вызывается DoSomething .

альтернатива

Ключевое слово VBA Static легко может быть неправильно понято — особенно опытные программисты, которые обычно работают на других языках. На многих языках static используется для того, чтобы член класса (field, property, method, …) принадлежал типу, а не экземпляру . Код в static контексте не может ссылаться на код в контексте экземпляра . Ключевое слово VBA Static означает что-то совершенно другое.

Часто Static локальный объект может быть также реализован как Private переменная (поле) на уровне модуля, однако это бросает вызов принципу, с помощью которого переменная должна быть объявлена ​​с наименьшей возможной областью; доверяйте своим инстинктам, используйте то, что вы предпочитаете — оба будут работать … но использование Static без понимания того, что он делает, может привести к интересным ошибкам.


Дим против частного

Ключевое слово Dim является законным на уровне процедур и модулей; его использование на уровне модуля эквивалентно использованию ключевого слова Private :

Option Explicit
Dim privateField1 As Long 'same as Private privateField2 as Long
Private privateField2 As Long 'same as Dim privateField2 as Long

Ключевое слово Private доступно только на уровне модуля; это вызывает резервирование Dim для локальных переменных и объявление переменных модуля с помощью Private , особенно с контрастным ключевым словом Public которое должно быть использовано для объявления публичного участника. Также можно использовать Dim везде — то , что имеет значение консистенция:

«Частные поля»

  • DO использовать Private чтобы объявить переменную уровня модуля.
  • DO используйте Dim чтобы объявить локальную переменную.
  • НЕ используйте Dim чтобы объявить переменную уровня модуля.

«Тусклый везде»

  • DO используйте Dim чтобы объявить что-либо частным / местным.
  • НЕ используйте Private чтобы объявить переменную уровня модуля.
  • ИЗБЕГАЙТЕ объявление Public полей. *

* В общем, следует избегать объявления Public или Global полей.


поля

Переменная, объявленная на уровне модуля, в разделе объявлений в верхней части тела модуля является полем . Public поле, объявленное в стандартном модуле, является глобальной переменной :

Public PublicField As Long

Доступ к переменной с глобальной областью можно получить из любого места, включая другие проекты VBA, которые будут ссылаться на проект, в котором он объявлен.

Чтобы сделать переменную global / public, но только видимую изнутри проекта, используйте модификатор Friend :

Friend FriendField As Long

Это особенно полезно в надстройках, где намерение заключается в том, что другие проекты VBA ссылаются на проект надстройки и могут потреблять открытый API.

Friend FriendField As Long 'public within the project, aka for "friend" code
Public PublicField As Long 'public within and beyond the project

Поля друзей недоступны в стандартных модулях.


Поля экземпляра

Переменная, объявленная на уровне модуля, в разделе объявлений в верхней части тела модуля класса (включая ThisWorkbook , ThisDocument , Worksheet , UserForm и модулях классов ) является полем экземпляра : оно существует только до тех пор, пока существует экземпляр класс вокруг.

'> 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

Инкапсулирующие поля

Данные Instance часто хранится Private и дублирован инкапсулируются. Закрытое поле можно открыть с помощью процедуры Property . Чтобы публично публиковать приватную переменную, не предоставляя доступ к записи вызывающему, модуль класса (или стандартный модуль) реализует элемент « Property Get :

Option Explicit
Private encapsulated As Long

Public Property Get SomeValue() As Long
    SomeValue = encapsulated
End Property

Public Sub DoSomething()
    encapsulated = 42
End Sub

Сам класс может изменить инкапсулированное значение, но вызывающий код может получить доступ только к Public членам (и членам Friend , если вызывающий объект находится в одном проекте).

Чтобы разрешить вызывающему абоненту:

  • Инкапсулированное значение , модуль предоставляет элемент Property Let .
  • Ссылка на инкапсулированные объекты , модуль предоставляет член Property Set .

Константы (Const)

Если у вас есть значение, которое никогда не изменяется в вашем приложении, вы можете определить именованную константу и использовать ее вместо буквенного значения.

Вы можете использовать Const только на уровне модуля или процедуры. Это означает, что контекст объявления для переменной должен быть классом, структурой, модулем, процедурой или блоком и не может быть исходным файлом, пространством имен или интерфейсом.

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

Хотя можно считать хорошей практикой указывать константные типы, это строго не требуется. Не указывая тип, он все равно приведет к правильному типу:

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

Обратите внимание, что это специфично для констант и в отличие от переменных, где не указано, что тип приводит к типу Variant.

Хотя можно явно объявить константу как String, невозможно объявить константу в виде строки с использованием синтаксиса строки фиксированной ширины

'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"

Модификаторы доступа

Dim должна быть зарезервирована для локальных переменных. На уровне модуля предпочитайте явные модификаторы доступа:

  • Private для частных полей, доступ к которым возможен только в том модуле, в котором они объявлены.
  • Public для общедоступных полей и глобальных переменных, к которым может обращаться любой вызывающий код.
  • Friend для переменных, публикуемых в рамках проекта, но недоступных для других проектов VBA, связанных с надстройками (для надстроек)
  • Global также может использоваться для Public полей в стандартных модулях, но является незаконным в модулях классов и в любом случае является устаревшим — вместо этого предпочитайте Public модификатор. Этот модификатор также не является законным для процедур.

Модификаторы доступа применимы как к переменным, так и к процедурам.

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

Дополнительный модуль

Открытые Sub процедуры в стандартных модулях отображаются как макросы и могут быть прикреплены к элементам управления и сочетания клавиш в документе хоста.

И наоборот, публичные процедуры Function в стандартных модулях отображаются как пользовательские функции (UDF) в хост-приложении.

Указание отдельного модуля Option Private Module в верхней части стандартного модуля не позволяет его членам отображаться как макросы и UDF для приложения-хозяина.

Тип подсказки

Тип подсказки сильно обескуражен. Они существуют и документируются здесь по причинам исторической и обратной совместимости. As [DataType] этого следует использовать синтаксис As [DataType] .

Public Sub ExampleDeclaration()

        Dim someInteger% '% Equivalent to "As Integer"
        Dim someLong&    '& Equivalent to "As Long"
        Dim [email protected] '@ 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

Типовые подсказки значительно уменьшают читаемость кода и поощряют венгерскую нотацию, которая также препятствует читаемости:

Dim strFile$
Dim iFile%

Вместо этого, объявляйте переменные ближе к их использованию и называйте вещи тем, что они используются, а не после их типа:

Dim path As String
Dim handle As Integer

Типовые подсказки также могут использоваться в литералах, чтобы обеспечить соблюдение определенного типа. По умолчанию числовой литерал, меньший, чем 32 768, будет интерпретироваться как литерал Integer , но с подсказкой типа вы можете контролировать это:

Dim foo 'implicit Variant
foo = 42& ' foo is now a Long
foo = 42# ' foo is now a Double
Debug.Print TypeName(42!) ' prints "Single"

Типные подсказки обычно не нужны для литералов, потому что они будут назначены переменной, объявленной с явным типом, или неявно преобразуются в соответствующий тип при передаче в качестве параметров. Неявные преобразования можно избежать, используя одну из явных функций преобразования типов:

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

Строковые возвращаемые встроенные функции

Большинство встроенных функций, которые обрабатывают строки, представлены в двух версиях: свободно напечатанная версия, которая возвращает Variant , и строго типизированную версию (заканчивающуюся на $ ), которая возвращает String . Если вы не назначаете возвращаемое значение для Variant , вы должны предпочесть версию, которая возвращает String противном случае происходит неявное преобразование возвращаемого значения.

Debug.Print Left(foo, 2)  'Left returns a Variant
Debug.Print Left$(foo, 2) 'Left$ returns a String

Эти функции:

  • 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 $

Обратите внимание, что это псевдонимы функций, не совсем намеки на тип . Функция Left соответствует скрытой функции B_Var_Left , а версия Left$ соответствует скрытой функции B_Str_Left .

В ранних версиях VBA знак $ не является допустимым символом, а имя функции должно быть заключено в квадратные скобки. В Word Basic было много и много функций, которые возвращали строки, которые заканчивались в $.

Объявление строк фиксированной длины

В VBA строки могут быть объявлены с определенной длиной; они автоматически дополняются или усекаются, чтобы поддерживать указанную длину.

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

Когда использовать статическую переменную

Статическая переменная, объявленная локально, не разрушается и не теряет своего значения при выходе из процедуры Sub. Последующие вызовы процедуры не требуют повторной инициализации или присвоения, хотя вы можете «нулевать» любые запоминаемые значения.

Они особенно полезны при позднем связывании объекта в вспомогательном подэлементе, который вызывается повторно.

Фрагмент 1: повторное использование объекта Scripting.Dictionary на многих листах

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

Snippet 2: создать рабочий лист UDF, который опоздает с привязкой к объекту VBScript.RegExp

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
Пример UDF со статическим объектом, заполненным полмиллиона строк

* Истекшее время, чтобы заполнить 500K строк с помощью UDF:
— с Dim rgx As Object : 148.74 секунд
— с Static rgx As Object : 26.07 секунд

* Они должны учитываться только для относительного сравнения. Ваши собственные результаты будут варьироваться в зависимости от сложности и
объем выполненных операций.

Помните, что UDF не рассчитывается один раз в жизни книги. Даже энергонезависимый UDF будет пересчитываться всякий раз, когда значения в пределах диапазона (ов), которые он ссылается, могут быть изменены. Каждое последующее событие пересчета только увеличивает преимущества статически объявленной переменной.

  • Статическая переменная доступна для времени жизни модуля, а не для процедуры или функции, в которой она была объявлена ​​и назначена.
  • Статические переменные могут быть объявлены только локально.
  • Статическая переменная содержит много одинаковых свойств переменной уровня частного модуля, но с более ограниченной областью.

Ссылки по теме: Static (Visual Basic)

title keywords f1_keywords ms.prod ms.assetid ms.date ms.localizationpriority

Static statement (VBA)

vblr6.chm1009031

vblr6.chm1009031

office

56b817bc-7324-cc0b-10ec-7ffea364b91e

12/03/2018

medium

Used at the procedure level to declare variables and allocate storage space. Variables declared with the Static statement retain their values as long as the code is running.

Syntax

Static varname [ ( [ subscripts ] ) ] [ As [ New ] type ], [ varname [ ( [ subscripts ] ) ] [ As [ New ] type ]] . . .

The Static statement syntax has these parts:

Part Description
varname Required. Name of the variable; follows standard variable naming conventions.
subscripts Optional. Dimensions of an array variable; up to 60 multiple dimensions may be declared. The subscripts argument uses the following syntax:

[ lowerTo ] upper [ , [ lowerTo ] upper ] . . .

When not explicitly stated in lower, the lower bound of an array is controlled by the Option Base statement. The lower bound is zero if no Option Base statement is present.

New Optional. Keyword that enables implicit creation of an object. If you use New when declaring the object variable, a new instance of the object is created on first reference to it, so you don’t have to use the Set statement to assign the object reference. The New keyword can’t be used to declare variables of any intrinsic data type and can’t be used to declare instances of dependent objects.
type Optional. Data type of the variable; may be Byte, Boolean, Integer, Long, Currency, Single, Double, Decimal (not currently supported), Date, String (for variable-length strings), String length (for fixed-length strings), Object, Variant, a user-defined type, or an object type. Use a separate As type clause for each variable being defined.

Remarks

After module code is running, variables declared with the Static statement retain their value until the module is reset or restarted. In class modules, variables declared with the Static statement retain their value in each class instance until that instance is destroyed. In form modules, static variables retain their value until the form is closed.

Use the Static statement in nonstatic procedures to explicitly declare variables that are visible only within the procedure, but whose lifetime is the same as the module in which the procedure is defined.

Use a Static statement within a procedure to declare the data type of a variable that retains its value between procedure calls. For example, the following statement declares a fixed-size array of integers:

Static EmployeeNumber(200) As Integer 

The following statement declares a variable for a new instance of a worksheet:

Static X As New Worksheet 

If the New keyword isn’t used when declaring an object variable, the variable that refers to the object must be assigned an existing object by using the Set statement before it can be used. Until it is assigned an object, the declared object variable has the special value Nothing, which indicates that it doesn’t refer to any particular instance of an object. When you use the New keyword in the declaration, an instance of the object is created on the first reference to the object.

If you don’t specify a data type or object type, and there is no Deftype statement in the module, the variable is Variant by default.

[!NOTE]
The Static statement and the Static keyword are similar, but used for different effects. If you declare a procedure by using the Static keyword (as in Static Sub CountSales ()), the storage space for all local variables within the procedure is allocated once, and the value of the variables is preserved for the entire time the program is running. For nonstatic procedures, storage space for variables is allocated each time the procedure is called and released when the procedure is exited. The Static statement is used to declare specific variables within nonstatic procedures to preserve their value for as long as the program is running.

When variables are initialized, a numeric variable is initialized to 0, a variable-length string is initialized to a zero-length string («»), and a fixed-length string is filled with zeros. Variant variables are initialized to Empty. Each element of a user-defined type variable is initialized as if it were a separate variable.

[!NOTE]
When you use Static statements within a procedure, put them at the beginning of the procedure with other declarative statements such as Dim.

Example

This example uses the Static statement to retain the value of a variable for as long as the module code is running.

' Function definition. 
Function KeepTotal(Number) 
    ' Only the variable Accumulate preserves its value between calls. 
    Static Accumulate 
    Accumulate = Accumulate + Number 
    KeepTotal = Accumulate 
End Function 
 
' Static function definition. 
Static Function MyFunction(Arg1, Arg2, Arg3) 
    ' All local variables preserve value between function calls. 
    Accumulate = Arg1 + Arg2 + Arg3 
    Half = Accumulate / 2 
    MyFunction = Half 
End Function

See also

  • Data types
  • Statements

[!includeSupport and feedback]

Return to VBA Code Examples

A VBA Static variable retains its value even when the procedure ends.

Declaring a Static Variable

You declare a Static variable using the Static keyword as shown below:

Sub DeclaringAStaticVariable()

Static myVariable As Integer
MsgBox myVariable
myVariable = myVariable + 2

Range("A1").Value = myVariable

End Sub

The first time you press F5, you get a Message box showing the initial value of myVariable which is 0. The value of 2 is placed in cell A1.

Message Box showing Initial Value of Variable

The Second Variable Value

If you press F5 again immediately afterwards, you get the following Message box showing the value of myVariable which is 2, and the value of 4, placed in your worksheet in cell A1.

Second Variable Value in Worksheet

As you can see the variable is retaining its value even as the Sub Procedure ends, if you used the Dim keyword instead of the Static keyword to declare the variable, the Message Box would always show the value of 0. Also, the result in cell A1, would be 2, every time you clicked F5. Since the variable would not retain its value once the Sub Procedure ended.

VBA Coding Made Easy

Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!
vba save as

Learn More!

Понравилась статья? Поделить с друзьями:
  • Vba excel protect all sheets
  • Vba excel sql like
  • Vba excel properties list
  • Vba excel sql connect
  • Vba excel project locked