Глобальная переменная в проекте VBA Excel. Объявление глобальной переменной в модуле проекта VBA и обращение к ней из других модулей того же проекта.
Объявление глобальной переменной
Глобальная переменная — это переменная, которая объявлена в одном из модулей проекта VBA и доступна для использования во всех остальных модулях.
Чтобы переменная стала глобальной, она должна быть объявлена в начале модуля перед первой процедурой (раздел Declarations) с помощью оператора Public. Этот способ работает во всех модулях проекта VBA Excel.
Допускается объявление глобальной переменной с помощью оператора Global, но такой способ считается устаревшим и на сайте разработчиков уже не упоминается. Объявить глобальную переменную с оператором Global можно только в стандартном модуле.
Пример объявления глобальных переменных в любом модуле проекта VBA:
Public myGlobVar1 ‘по умолчанию — As Variant Public myGlobVar2 As String Public myGlobVar3 As Double |
Объявление глобальных переменных
Обращение к глобальной переменной
Примеры обращения к глобальной переменной, объявленной в разных типах модулей проекта VBA Excel. Актуально для обращения из модуля любого типа данного проекта.
Переменная в стандартном модуле
Если глобальная переменная (myGlobVar) объявлена в стандартном модуле (Module1) с уникальным именем, не повторяющимся в других модулях, к ней можно обращаться из других модулей по одному имени (в примере — из модуля формы):
Private Sub CommandButton1_Click() myGlobVar = «Глобальная переменная» TextBox1.Text = myGlobVar End Sub |
Стандартное обращение с указанием имени модуля (Module1), в котором объявлена глобальная переменная (myGlobVar):
Private Sub CommandButton1_Click() Module1.myGlobVar = «Глобальная переменная» TextBox1.Text = Module1.myGlobVar End Sub |
Переменная в модуле книги
Глобальная переменная (myGlobVar), объявленная в модуле книги, доступна при обращении к ней из других модулей с помощью следующего кода VBA Excel:
Sub Primer1() ThisWorkbook.myGlobVar = «Глобальная переменная» MsgBox ThisWorkbook.myGlobVar End Sub |
Переменная в модуле листа
Обращение к глобальной переменной (myGlobVar), объявленной в модуле рабочего листа (Лист1), из других модулей по имени листа (в проводнике проекта находится без скобок слева от имени ярлыка):
Sub Primer2() Лист1.myGlobVar = «Глобальная переменная» MsgBox Лист1.myGlobVar End Sub |
По имени ярлыка (в проводнике проекта находится в полукруглых скобках справа от имени листа):
Sub Primer3() Worksheets(«Лист1»).myGlobVar = «Глобальная переменная» MsgBox Worksheets(«Лист1»).myGlobVar End Sub |
Переменная в модуле формы
Глобальная переменная (myGlobVar), объявленная в модуле формы (UserForm1), доступна при обращении к ней из других модулей с помощью следующего кода VBA Excel:
Sub Primer4() UserForm1.myGlobVar = «Глобальная переменная» MsgBox UserForm1.myGlobVar End Sub |
Переменная в личной книге макросов
Обращение к глобальной переменной (myGlobVar), объявленной в модуле ЭтаКнига
проекта VBAProject (PERSONAL.XLSB)
из модуля проекта VBA обычной книги Excel:
Sub Primer5() Workbooks(«PERSONAL.XLSB»).myGlobVar = «Глобальная переменная» MsgBox Workbooks(«PERSONAL.XLSB»).myGlobVar End Sub |
Мне не удалось получить доступ из проекта VBA текущей книги Excel к глобальной переменной, объявленной в стандартном модуле личной книги макросов.
Return to VBA Code Examples
We have already covered an introduction to variables, constants and VBA data types in an introductory tutorial. We are going to cover Public variables in this tutorial. The definition of a Public variable is a variable that any module, Sub Procedure, Function or Class can access and use within a certain workbook.
Declaring a Public Variable in VBA
There are five main keywords that you can use to declare a variable in VBA. These are:
- The Dim keyword
- The Static keyword
- The Global keyword
- The Public keyword
- The Private keyword
The Global variable and the Public variable are very similar.
In order to declare a Public variable, you have to place your variable in the Declarations section of your VBA code below the Option Explicit statement, outside of any of your Sub Procedures or Functions and you also have to use the Public keyword. This is shown below:
Public MyVariable as Integer
When you declare a variable as a public variable, you are also inferring to the scope of that variable. You determine the scope of a variable by the keyword you use to declare it and where you place it in your code.
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!
Learn More!
<<Return to VBA Examples
When writing VBA macros, the concept of Private or Public is important. It defines how VBA code within one module can interact with VBA code in another module. This concept applies to both Private Subs and Private Functions.
As a simple analogy – on social media, you can set parts of your profile so that everybody can see it (Public), or only those you allow, such as friends or followers, to see it (Private). The Private vs. Public concept in VBA is similar, but since we’re talking about VBA here, it’s not quite as straightforward.
Before we launch into the difference between Public and Private, we first need to understand what Modules are and how they work.
Modules
Modules are the place where VBA code is written and stored. There are many different module types in Excel, and we use each module for a different purpose.
Worksheet Modules
Worksheet Modules are generally used to trigger code related to that specific worksheet. Each worksheet contains its own module, so if there are 6 worksheets, then we have 6 Worksheet Modules.
In the screenshot above, the VBA code is contained within the Worksheet Module of Sheet1. As we have used the Worksheet_Activate event, the code is triggered only when Sheet1 is activated. Any event-based code (such as worksheet activation) in a Worksheet Module only applies to the worksheet in which the code is stored.
Workbook Module
The Workbook Module is generally used to trigger code related to workbook-level events.
In the screenshot above, we have used the Workbook_Open event. Therefore, the VBA code will run when a workbook is opened. Every workbook has its own module.
UserForm Module
UserForm Modules generally contain code that relates to UserForm events. Each UserForm has its own module.
In the screenshot above, the VBA code will run when the user clicks on CommandButton1 in the UserForm.
Standard Modules
Standard Modules are not related to any specific objects and do not have any events related to them. Therefore, standard Modules are not triggered by user interaction. If we are relying on triggered events, we need the Workbook, Worksheet, or UserForm Modules to track the event. However, that event may then call a macro within a Standard Module.
TIP: Find out how to run a macro from another macro here: Run a macro from a macro (from another workbook)
The screenshot above shows a code that password protects the ActiveSheet, no matter which workbook or worksheet.
Other Module Types
The final type of VBA module available is a Class Module. These are for creating custom objects and operate very differently from the other module types. Class Modules are outside the scope of this post.
The terms Public and Private are used in relation to Modules. The basic concept is that Public variables, Subs, or Functions can be seen and used by all modules in the workbook, while Private variables, Subs, and Functions can only be used by code within the same module.
Declaring a Private Sub or Function
To treat a Sub or Function as Private, we use the Private keyword at the start of the name.
Private Sub nameOfSub()
Private Function nameOfFunction()
Declaring a Public Sub or Function
To treat a Sub or Function as Public, we can use the Public keyword. However, if the word Public or Private is excluded, VBA treats the sub/function as if it were public. As a result, the following are all Public, even though they do not all include the keyword.
Public Sub nameOfSub()
Sub nameOfSub()
Public Function nameOfFunction()
Function nameOfFunction()
Let’s look at Subs and Functions in a bit more detail
Sub procedures (Subs)
When thinking about the difference between a Public Sub and a Private Sub, the two primary considerations are:
- Do we want the macro to appear in the list of available macros within Excel’s Macro window?
- Do we want the macro to be run from another Macro?
Does it appear in the Macro window?
One of the most important features of Private subs is that they do not appear in Excel’s Macro window.
Let’s assume Module1 contains the following two macros:
Private Sub NotVisible()
MsgBox "This is a Private Sub"
End Sub
Public Sub IAmVisible()
MsgBox "This is a Public Sub"
End Sub
The Macro dialog box only displays the Public sub.
I don’t want you to jump to the conclusion that all Public Subs will appear in the Macro window, as that is not true. Any Public sub which requires arguments, also does not appear in this window, but it can still be executed if we know how to reference it.
Can the code be run from another macro?
When we think about Private Subs, it is best to view them as VBA code that can only be called by other code within the same module. So, for example, if Module1 contains a Private Sub, it cannot be called by any code in another module.
Using a simple example, here is a Private Sub in Module1:
Private Sub ShowMessage()
MsgBox "This is a Private Sub"
End Sub
Now let’s try to call the ShowMessage macro from Module2.
Sub CallAPrivateMacro()
Call ShowMessage
End Sub
Running CallAPrivateMacro generates an error, as the two macros are in different modules.
If the ShowMessage macro in Module1 were a Public Sub, it would execute correctly.
There are many ways to run a macro from another macro. One such method allows us to run a Private Sub from another Module. If we use the Application.Run command, it will happily run a Private sub. Let’s change the code in Module2 to include the Application.Run command:
Sub CallAPrivateMacro()
Application.Run "ShowMessage"
End Sub
Instead of an error, the code above will execute the ShowMessage macro.
Working with object-based module events
Excel creates the Worksheet, Workbook, and UserForm Module events as Private by default, but they don’t need to be. If they are changed to Public, they can be called from other modules. Let’s look at an example.
Enter the following code into the Workbook Module (notice that I have changed it to a Public sub).
Public Sub Workbook_Open()
MsgBox "Workbook Opened"
End Sub
We can call this from another macro by using the object’s name followed by the name of the Public sub.
Sub RunWorkbook_Open()
Call ThisWorkbook.Workbook_Open
End Sub
This means that we can run the Workbook_Open event whenever we need to. If the sub in the Workbook Module is Private, we can still use the Application.Run method noted above.
Functions
VBA functions are used to return calculated values. They have two primary uses:
- To calculate a value within a cell on a worksheet (known as User Defined Functions)
- To calculate a value within the VBA code
Like Subs, Functions created without the Private or Public declaration are treated as Public.
Calculating values within the worksheet (User Defined Functions)
User Defined Functions are worksheet formulas that operate similarly to other Excel functions, such as SUMIFS or XLOOKUP.
The following code snippets are included within Module1:
Public Function IAmVisible(myText As String)
IAmVisible = myText
End Function
Private Function NotVisible(myText As String)
NotVisible = myText
End Function
If we look at the Insert Function dialog box, the IAmVisible function is available as a worksheet function.
Functions must be declared in a Standard Module to be used as User Defined Functions in an Excel worksheet.
Function within the VBA Code
Functions used within VBA code operate in the same way as subs; Private functions should only be visible from within the same module. Once again, we can revert to the Application.Run command to use a Private function from another module.
Let’s assume the following code were entered into Module2:
Sub CallAPrivateFunction()
MsgBox Application.Run("NotVisible", "This is a Private Function")
End Sub
The code above will happily call the NotVisible private function from Module1.
Variables
Variables hold values or references to objects that change while the macro runs. Variables come in 3 varieties, Public, Private and Dim.
Public Variables
Public variables must be declared at the top of the code module, directly after the Option Explicit statement (if you have one), and before any Subs or Functions.
The following is incorrect and will create an error if we try to use the Public Variable.
Option Explicit
Sub SomethingElseAtTheTop()
MsgBox "Public Variable is not first"
End Sub
Public myPublicMessage As String
The correct approach would be: (The Public variable is declared before any subs or functions):
Option Explicit
Public myPublicMessage As String
Sub SomethingAfterPrivateVariables()
MsgBox "Public Variable is first"
End Sub
As it is a Public variable, we can use and change the variable from any module (of any type) in the workbook. Look at this example code below, which could run from Module2:
Sub UsePublicVariable()
myPublicMessage = "This is Public"
MsgBox myPublicMessage
End Sub
Private Variables
Private Variables can only be accessed and changed by subs and functions within the same Module. They too, must also be declared at the top of the VBA code.
The following demonstrates an acceptable usage of a Private variable.
Module1:
Option Explicit
Private myPrivateMessage As String
Sub UsePrivateVariable()
myPrivateMessage = "This is Private"
MsgBox myPrivateMessage
End Sub
Dim Variables
Most of us learn to create variables by using the word Dim. However, Dim variables behave differently depending on how they are declared.
Dim variables declared within a Sub or Function can only be used within that Sub or Function. In the example below, the Dim has been declared inside a Sub called CreateDim, but used within a sub called UseDim. If we run the UseDim code, it cannot find the Dim variable and will error.
Sub CreateDim()
Dim myDimMessage
End Sub
Sub UseDim()
myDimMessage = "Dim inside Sub"
MsgBox myDimMessage
End Sub
If a Dim variable is created at the top of the module, before all the Subs or Functions, it operates like a Private variable. The following code will run correctly.
Option Explicit
Dim myDimMessage
Sub UseDim()
myDimMessage = "Dim inside Sub"
MsgBox myDimMessage
End Sub
Does this really matter?
You might think it sounds easier to create everything as Public; then it can be used anywhere. A logical, but dangerous conclusion. It is much better to control all sections of the code. Ask yourself, if somebody were to use your macro from Excel’s Macro window, should it work? Or if somebody ran your function as a User Defined Function, should it work? Answers to these questions are a good guiding principle to help decide between Public and Private.
It is always much better to limit the scope of your Subs, Functions, and variables initially, then expand them when required in specific circumstances.
About the author
Hey, I’m Mark, and I run Excel Off The Grid.
My parents tell me that at the age of 7 I declared I was going to become a qualified accountant. I was either psychic or had no imagination, as that is exactly what happened. However, it wasn’t until I was 35 that my journey really began.
In 2015, I started a new job, for which I was regularly working after 10pm. As a result, I rarely saw my children during the week. So, I started searching for the secrets to automating Excel. I discovered that by building a small number of simple tools, I could combine them together in different ways to automate nearly all my regular tasks. This meant I could work less hours (and I got pay raises!). Today, I teach these techniques to other professionals in our training program so they too can spend less time at work (and more time with their children and doing the things they love).
Do you need help adapting this post to your needs?
I’m guessing the examples in this post don’t exactly match your situation. We all use Excel differently, so it’s impossible to write a post that will meet everybody’s needs. By taking the time to understand the techniques and principles in this post (and elsewhere on this site), you should be able to adapt it to your needs.
But, if you’re still struggling you should:
- Read other blogs, or watch YouTube videos on the same topic. You will benefit much more by discovering your own solutions.
- Ask the ‘Excel Ninja’ in your office. It’s amazing what things other people know.
- Ask a question in a forum like Mr Excel, or the Microsoft Answers Community. Remember, the people on these forums are generally giving their time for free. So take care to craft your question, make sure it’s clear and concise. List all the things you’ve tried, and provide screenshots, code segments and example workbooks.
- Use Excel Rescue, who are my consultancy partner. They help by providing solutions to smaller Excel problems.
What next?
Don’t go yet, there is plenty more to learn on Excel Off The Grid. Check out the latest posts:
Хитрости »
1 Май 2011 225461 просмотров
Что такое переменная и как правильно её объявить?
Переменная — это некий контейнер, в котором VBA хранит данные. Если подробнее, то это как коробочка, в которую Вы можете положить что-то на хранение, а затем по мере необходимости достать. Только в данном случае в переменной мы храним число, строку или иные данные, которые затем можем извлекать из неё и использовать в коде по мере необходимости.
Для чего нужна переменная? Чтобы хранить значение и применить его позже в любой момент. Например, в ячейке А1 записана сумма, а нажатием на кнопку запускается обновление отчета. После обновления отчета сумма в А1 изменится. Необходимо сверить сумму до обновления с суммой после и в зависимости от этого сделать какое-либо действие. Переменная как раз позволит запомнить значение ячейки до того, как она обновится и использовать именно это значение после обновления.
- Требования к переменным
- Типы данных, хранимых в переменных
- Как объявлять переменные
- Как правильно назвать переменную
- Пример использования переменных
- Константы
В качестве имен переменных можно использовать символы букв и числа, но первой в имени переменной всегда должна быть буква. Не допускается использование точки, запятой, пробела и иных знаков препинания, кроме нижнего подчеркивания. Длина имени не должна превышать 254 символов. Так же нельзя использовать в качестве имен для переменных зарезервированные константы редактора VBA(например Sub, Msgbox, ubound, Date и т.п.). Так же для переменных неважен регистр букв.
Теперь рассмотрим основные декларированные в VBA
типы данных, которые можно хранить в переменных:
Тип данных | Занимает байт в памяти | Пределы значений |
---|---|---|
Byte | 1 | Целые числа от 0 до 255 |
Boolean | 2 | True или False |
Integer | 2 | Целые числа от (-32768) до 32767 |
Long | 4 | Целые числа от (-2147483648) до 2147483647 |
Single | 4 | От (–3.402823Е+38) до (–1.401298Е-45) и от 1.401298Е-45 до 3.402823Е+38 |
Double | 8 | От ±1.79769313486232Е+308 до ±4.94065645841247Е-324 |
Decimal | 12 | От ±79228162514264337593543950335 без десятичных знаков до ±7,9228162514264337593543950335 с 28-ю знаками после запятой |
Currency | 8 | От (–922337203685477.5808) до 922337203685477.5807 |
Date | 8 | От 01.01.100 до 31.12.9999(не надо путать с датами в Excel — 01.01.1900 до 31.12.9999) |
String | 10(+длина строки) | От 0 до 65400 символов для фиксированных строк и чуть более 2 млрд. для строк переменной длины |
Object | 4 | Любой объект |
Array | Определяется кол-вом и размером элементов | — |
Variant | от 16-ти | Любой из встроенных типов данных |
Как видно из таблицы больше всего памяти занимает Variant. Притом это если он хранит числовые данные. Если же такая переменная будет хранить данные строкового типа(текст), то размер занимаемой памяти будет измеряться уже начиная с 22 байт + длина строки, хранящейся в переменной. Чем больше памяти занимает переменная, тем дольше она инициализируется в памяти и тем медленнее код будет выполняться. Вот поэтому и важно явно задавать тип данных, хранимых в переменной — это называется объявить переменную.
Тип данных Decimal больше не используется, поэтому объявить переменную данного типа в VBA не получится — подобная попытка приведет к синтаксической ошибке. Для работы с данными типа Decimal переменную необходимо изначально объявить как Variant или вообще без типа (например Dim a), т.к. тип данных Variant используется в VBA по умолчанию и принимает любой тип данных.
Так же переменным можно назначать и другие типы данных, которых нет в таблице выше — это типы, которые поддерживаются объектной моделью приложений, к которым «подключен» VBA. Например, если зайти в VBA из Excel, то библиотека типов объектной модели Excel подключена по умолчанию и для переменных становится доступно множество типов этой объектной модели. Многие из них знакомы всем: Workbook, Worksheet, Range, Cells, Chart и т.д. Т.е. это книги, листы, ячейки, диаграммы. Типов много, почти на каждый объект и коллекцию. Рассматривать здесь все бессмысленно. Могу лишь привести пару строк кода:
Dim rRange as Range 'назначили переменной тип ячейка/диапазон Set rRange = Range("A1") 'присвоили ссылку на ячейку A1 текущего листа
Про объявление переменных подробно написано чуть ниже.
А более подробно про обращение к диапазонам из VBA можно почитать в этой статье: Как обратиться к диапазону из VBA
На самом деле все очень просто. Это делается при помощи операторов области действия: Dim, Public,Static и оператора присвоения типа As. Самый распространенный оператор — Dim. Его и возьмем в качестве примера. Синтаксис объявления:
[оператор области действия] Имя_переменной As [тип данных]
Очень частая ошибка при объявлении переменных, совершаемая начинающими изучать VBA:
Dim MyVar1, MyVar2, MyVar3 As Integer
Вроде бы исходя из логики всем переменным присвоен тип данных Integer. Но это ошибочное суждение. Тип Integer присвоен только последней переменной, к которой он «привязан» оператором As — MyVar3. Все остальные переменные имеют тип данных Variant. Т.е. если Вы не задаете каждой переменной свой тип хранимых данных явно(т.е. не указываете для неё тип данных через As), то VBA сам присваивает для такой переменной тип данных Variant, т.к. он может хранить любой тип данных. А вот так выглядит правильное присвоение типа данных:
Dim MyVar1 As Integer, MyVar2 As Integer, MyVar3 As Integer
Это и есть объявление переменных. Т.е. сначала идет оператор области действия (Dim, Public,Static), сразу за ним имя переменной, затем оператор As и тип.
Но это не все. Некоторые типы переменным можно присваивать еще короче — даже без оператора As:
Dim MyVar1%, MyVar2%, MyVar3%
Всего шесть типов, которые можно объявить подобным методом:
! — Single
# — Double
$ — String
% — Integer
& — Long
@ — Currency
На что стоит обратить внимание, при объявлении переменных подобным образом: между именем переменной и знаком типа не должно быть пробелов.
Я лично в большинстве статей предпочитаю использовать первый метод, т.е. полное указание типа. Это читабельнее и понятнее. В каких-то проектах могу использовать краткое указание, в общих(разработка в команде) — полное. В своих кодах Вы вправе использовать удобный Вам метод — ошибки не будет.
Теперь разберемся с операторами области действия(Dim, Public и Static):
- Dim — данный оператор используется для объявления переменной, значение которой будет храниться только в той процедуре, внутри которой данная переменная объявлена. Во время запуска процедуры такая переменная инициализируется в памяти и использовать её значение можно внутри только этой процедуры, а по завершению процедуры переменная выгружается из памяти(обнуляется) и данные по ней теряются. Переменную, объявленную подобным образом еще называют локальной переменной. Однако с помощью данного оператора можно объявить переменную, которая будет доступна в любой процедуре модуля. Необходимо объявить переменную вне процедуры — в области объявлений(читать как первой строкой в модуле, после строк объявлений типа — Option Explicit). Тогда значение переменной будет доступно в любой процедуре лишь того модуля, в котором данная переменная была объявлена. Такие переменные называются переменными уровня модуля. Также для использования переменных во всех процедурах и функциях одного конкретного модуля можно использовать оператор Private. Но он в данном случае ничем не отличается от Dim, а пишется длиннее Плюс, Private нельзя использовать внутри процедуры или функции(только в области объявлений), что еще больше сужает её применимость. По сути чаще этот оператор применяется к функциям и процедурам(об этом см.ниже)
- Static — данный оператор используется для объявления переменной, значение которой предполагается использовать внутри конкретной процедуры, но не теряя значения данной переменной по завершении процедуры. Переменные данного типа обычно используют в качестве накопительных счетчиков. Такая переменная инициализируется в памяти при первом запуске процедуры, в которой она объявлена. По завершении процедуры данные по переменной не выгружаются из памяти, но однако они не доступны в других процедурах. Как только Вы запустите процедуру с этой переменной еще раз — данные по такой переменной будут доступны в том виде, в котором были до завершения процедуры. Выгружается из памяти такая переменная только после закрытия проекта(книги с кодом).
- Public — данный оператор используется для объявления переменной, значение которой будет доступно в любой процедуре проекта(в обычных модулях, модулях класса, модулях форм, модулях листов и книг). Переменная, объявленная подобным образом, должна быть объявлена вне процедуры — в области объявлений. Такая переменная загружается в память во время загрузки проекта(при открытии книги) и хранит значение до выгрузки проекта(закрытия книги). Использовать её можно в любом модуле и любой процедуре проекта. Важно: объявлять подобным образом переменную необходимо строго в стандартном модуле. Такие переменные называются переменными уровня проекта. В простонародье такие переменные еще называют глобальными(возможно из-за того, что раньше подобные переменные объявлялись при помощи оператора Global, который в настоящее время устарел и не используется).
Для большего понимания того, где и как объявлять переменные уровня проекта два небольших примера.
Неправильное объявлениеOption Explicit Sub main() Public MyVariable As String MyVariable = "Глобальная переменная" 'показываем текущее значение переменной MsgBox MyVariable 'пробуем изменить значение переменной Call sub_main 'показываем измененное значение переменной MsgBox MyVariable End Sub 'доп.процедура изменения значения переменной Sub ChangeMyVariable() MyVariable = "Изменили её значение" End Sub
переменные не будут видны во всех модулях всех процедур и функций проекта, потому что:
1. Оператор Public недопустим внутри процедуры(между Sub и End Sub), поэтому VBA при попытке выполнения такой процедуры обязательно выдаст ошибку — Invalid Attribut in Sub or Function.
2. Даже если Public заменить на Dim — это уже будет переменная уровня процедуры и для других процедур будет недоступна.
3. Т.к. объявление неверное — вторая процедура(ChangeMyVariable) ничего не знает о переменной MyVariable и естественно, не сможет изменить именно её.
Правильное объявление'выше глобальных переменных и констант могут быть только декларации: Option Explicit 'принудительное объявление переменных Option Base 1 'нижняя граница объявляемых массивов начинается с 1 Option Compare Text 'сравнение текста без учета регистра 'глобальная переменная - первой строкой, выше всех процедур Public MyVariable As String 'далее процедуры и функции Sub main() MyVariable = "Глобальная переменная" 'показываем текущее значение переменной MsgBox MyVariable, vbInformation, "www.excel-vba.ru" 'пробуем изменить значение переменной Call ChangeMyVariable 'показываем измененное значение переменной MsgBox MyVariable, vbInformation, "www.excel-vba.ru" End Sub 'доп.процедура изменения значения переменной Sub ChangeMyVariable() MyVariable = "Изменили её значение" End Sub
Если при этом вместо Public записать Dim, то эта переменная будет доступна из всех функций и процедур того модуля, в котором записана, но недоступна для функций и процедур других модулей.
Переменные уровня проекта невозможно объявить внутри модулей классов(ClassModule, ЭтаКнига(ThisWorkbook), модулей листов, модулей форм(UserForm) — подробнее про типы модулей: Что такое модуль? Какие бывают модули?) - Операторы области действия так же могут применяться и к процедурам. Для процедур доступен еще один оператор области действия — Private. Объявленная подобным образом процедура доступна только из того модуля, в котором записана и такая процедура не видна в диалоговом окне вызова макросов(Alt+F8)
'процедура записана в Module1 'эта процедура будет доступна для вызова исключительно из процедур в этом же модуле 'но не будет доступна при вызове из других модулей Private Sub PrivateMain() MsgBox "Процедура может быть вызвана только из модуля, в котором записана", vbInformation, "www.excel-vba.ru" End Sub 'другая процедура, записанная в этом же модуле Sub CallPrivate() Call PrivateMain End Sub
'эта процедура записана в другом модуле - Module2 'при попытке вызова этой процедурой получим ошибку ' Sub or Function not defined ' потому что процедура PrivateMain объявлена только для Module1 Sub CallPrivate_FromModule1() Call PrivateMain End Sub
При этом, если из Excel нажать сочетание клавиш Alt+F8, то в окне будут доступны только CallPrivate_FromModule1 и CallPrivate. Процедура PrivateMain будет недоступна.
«Что самое сложное в работе программиста? — выдумывать имена переменным.» :-)А ведь придумать имя переменной тоже не так-то просто. Можно, конечно, давать им имена типа: a, d, f, x, y и т.д.(я сам иногда так делаю, но либо в простых кодах, либо для специального запутывания кода). Но стоит задуматься: а как Вы с ними будете управляться в большом коде? Код строк на 10 еще потерпит такие имена, а вот более крупные проекты — не советовал бы я в них оперировать такими переменными. Вы сами запутаетесь какая переменная как объявлена и какой тип данных может хранить и что за значение ей присвоено. Поэтому лучше всего давать переменным осмысленные имена и следовать соглашению об именовании переменных. Что за соглашение? Все очень просто: перед основным названием переменной ставится префикс, указывающий на тип данных, который мы предполагаем хранить в данной переменной. Про имеющиеся типы данных я уже рассказал выше. А ниже приведена примерная таблица соответствий префиксов типам данных:
Префикс | Тип хранимых данных |
---|---|
b | Boolean |
bt | Byte |
i | Integer |
l | Long |
s | Single |
d | Double |
c | Currency |
dt | Date |
str | String |
obj | Object |
v | Variant |
Лично я немного для себя её переделал, т.к. некоторые обозначения мне кажутся скудными. Например Double я обозначаю как dbl, а Single как sgl. Это мне кажется более наглядным.
В чем еще плюс явного указания префикса данных. В VBA есть такие операторы как Def, при помощи которых можно указать тип данных по умолчанию для переменных, первая буква имени которых попадает в заданный в операторе диапазон. Например:
DefBool B Sub test() Dim bCheck End Sub
Автоматически переменной bCheck будет присвоен тип Boolean, т.к. она начинается с буквы b — регистр здесь не имеет значения(впрочем как в VBA в целом). Оператор Def задается в области объявления. Можно задать не одну букву, а целый диапазон букв:
DefBool B-C Sub test() Dim bCheck, cCheck End Sub
Но я считаю, что одной буквы для одного типа вполне достаточно. Можно задать сразу несколько операторов Def.
DefBool B DefStr S Sub test() Dim bCheck, sCheck End Sub
Ниже приведен полный перечень операторов типов и данные, которые задает каждый из них:
DefBool — Задает тип Boolean
DefByte — Задает тип Byte
DefCur — Задает тип Currency
DefDate — Задает тип Date
DefDbl — Задает тип Double
DefInt — Задает тип Integer
DefLng — Задает тип Long
DefObj — Задает тип Object
DefSng — Задает тип Single
DefStr — Задает тип String
DefVar — Задает тип Variant
По умолчанию в VBA применена инструкция DefVar для всех букв(иначе говоря для всех переменных, которым не назначен тип данных явно через оператор As).
Ну и немаловажный момент это непосредственно осмысленное имя переменной. Имя переменной должно примерно отражать то, что в ней будет храниться. Например, Вы создаете отчет и Вам надо объявить две переменные: одна имя листа, другая имя книги. Можно было сделать так: str1, str2. Коротко, здорово. Но если подумать — и как можно понять, какая из этих переменных что хранит? Никак. Надо просматривать код и вспоминать, какой переменной какое значение было присвоено. Не совсем удобно, правда? А если бы Вы задали имена так: strBookName, strSheetName, то вроде как более понятно, что мы в них будем хранить. Это удобно не только вам самим при работе с кодом, но и другим людям, которые, возможно в будущем будут пользоваться Вашим кодом. Им будет удобнее читать код, если он будет оформлен грамотно, а переменные названы осмысленно. И не стоит экономить на длине имени — имя должно быть понятным. Без фанатизма, конечно :-). Хоть VBA и позволяет нам создавать переменные длиной до 254 символов, но читать такую переменную так же неудобно, как и с одним символом. Но здесь уже все зависит от Ваших предпочтений и фантазии.
Небольшое дополнение: лучше привыкать давать названия переменным на латинице(т.е. английский алфавит), т.к. для VBA английский язык «родной» и лучше использовать его.
Sub main() 'объявляем переменные с назначением конкретных типов 'As String - текст 'As Long - целое число Dim sAddress As String, sNewAddress As String, sShName As String Dim lRow As Long Dim rRange as Range 'назначили переменной тип ячейка/диапазон 'присвоили переменной rRange ссылку на текущую выделенную ячейку Set rRange = Selection 'меняем выделение - выделяем ячейку D9 Range("D9").Select 'назначаем переменной адрес выделенных ячеек sAddress = Selection.Address 'назначаем переменной lRow значение первой строки выделенной области lRow = Selection.Row 'показываем сообщение MsgBox "Адрес выделенной области: " & sAddress, vbInformation, "www.excel-vba.ru" MsgBox "Номер первой строки: " & lRow, vbInformation, "www.excel-vba.ru" 'назначаем другой переменной значение адреса ячейки A1 sNewAddress = "A1" 'выделяем ячейку, заданную переменной sNewAddres Range(sNewAddress).Select MsgBox "Адрес выделенной области: " & sNewAddress, vbInformation, "www.excel-vba.ru" 'выделяем изначально выделенную ячейку, используя переменную rRange rRange.Select MsgBox "Адрес выделенной области: " & rRange.Address, vbInformation, "www.excel-vba.ru" 'задаем значение переменной sShName = "excel-vba" 'переименовываем активный лист на имя, заданное переменной ActiveSheet.Name = sShName End Sub
Просмотреть пошагово выполнение данного кода поможет статья: Отлов ошибок и отладка кода VBA
Важно! Назначение значений переменным задается при помощи знака равно(=). Однако, есть небольшой нюанс: для переменных типа Object(а так же других объектных типов(Workbook, Worksheet, Range, Cells, Chart и т.п.)) присвоение идет при помощи ключевого оператора Set:
'присвоили переменной rRange ссылку на текущую выделенную ячейку Set rRange = Selection
это так же называется присвоением ссылки на объект. Почему именно ссылки? Все просто: при помещении в переменную непосредственно ячейки или диапазона(Set var = Range(«A1») или Set rRange = Selection) нет никакого запоминания самой ячейки. В переменную помещается лишь ссылка на эту ячейку(можете считать, что это как ссылка в формулах) со всеми вытекающими: такое назначение не запоминает свойства ячейки до или после — в переменной хранится ссылка на конкретную ячейку и доступ есть исключительно к свойствам ячейки на текущий момент. Чтобы запомнить для этой ячейки значение, цвет или даже адрес (а так же и другие свойства) до её изменения и применить запомненное даже после изменения/перемещения самой ячейки — необходимо запоминать в переменные именно свойства ячейки:
Sub main() Dim val, l_InteriorColor As Long, l_FontColor As Long Dim rRange As Range 'назначили переменной тип ячейка/диапазон 'присвоили переменной rRange ссылку на активную ячейку Set rRange = ActiveCell 'запоминаем свойства ячейки val = rRange.Value 'значение l_InteriorColor = rRange.Interior.Color 'цвет заливки l_FontColor = rRange.Font.Color 'цвет шрифта 'копируем другую ячейку и вставляем на место активной ActiveSheet.Range("D1").Copy rRange 'проверяем, что rRange теперь имеет совершенно другие свойста - как у D1 MsgBox "Значение rRange: " & rRange.Value & vbNewLine & _ "Цвет заливки rRange: " & rRange.Interior.Color & vbNewLine & _ "Цвет шрифта rRange: " & rRange.Font.Color & vbNewLine, vbInformation, "www.excel-vba.ru" 'назначаем свойства из сохраненных в переменных rRange.Value = val 'значение rRange.Interior.Color = l_InteriorColor 'цвет заливки rRange.Font.Color = l_FontColor 'цвет шрифта 'проверяем, что rRange возвращены параметры до копирования MsgBox "Значение rRange: " & rRange.Value & vbNewLine & _ "Цвет заливки rRange: " & rRange.Interior.Color & vbNewLine & _ "Цвет шрифта rRange: " & rRange.Font.Color & vbNewLine, vbInformation, "www.excel-vba.ru" End Sub
Это так же распространяется на все другие объекты. Т.е. те переменные, значения которым назначаются через оператор Set.
Для других же типов Set не нужен и в переменную значение заносится без этих нюансов.
Так же есть и иной вид «переменных» — константы. Это такая же переменная, только(как следует из её названия) — она не может быть изменена во время выполнения кода, т.к. является величиной постоянной и значение её назначается только один раз — перед выполнением кода.
Const sMyConst As String = "Имя моей программы"
Константам могут быть назначены данные тех же типов, что и для переменных, за исключением типа Object, т.к. Object это всегда ссылка на объект, который как правило обладает «динамическими»(т.е. обновляющимися) свойствами. А изменение для констант недопустимо.
Для дополнительной области видимости/жизни констант используется только Public. Если область видимости не указана, то константа будет доступна только из того модуля, в котором объявлена. Здесь обращаю внимание на то, что Dim уже не используется, т.к. Dim это идентификатор только для переменных. Пару важных отличий объявления констант от объявления переменных:
- при объявлении константы необходимо обязательно указывать явно, что это константа ключевым словом Const
- сразу в момент объявления необходимо назначить константе значение: = «Имя моей программы»
Во всем остальном объявление и применение констант идентично объявлению переменных. Коротко приведу пару примеров.
Если константа объявлена внутри процедуры:
Sub TestConst() Const sMyConst As String = "Имя моей программы" MsgBox sMyConst 'показываем сообщение с именем программы End Sub
то она не может быть использована в другой процедуре:
Sub TestConst() Const sMyConst As String = "Имя моей программы" MsgBox sMyConst 'показываем сообщение с именем программы End Sub Sub TestConst2() MsgBox sMyConst 'вызовет ошибку Variable not defined End Sub
Чтобы использовать одну константу во всех процедурах модуля(того, в котором она объявлена), необходимо объявить её в области объявлений:
Const sMyConst As String = "Имя моей программы" Sub TestConst() MsgBox sMyConst 'показываем сообщение с именем программы End Sub Sub TestConst2() MsgBox sMyConst 'уже не вызовет ошибку Variable not defined End Sub
Чтобы использовать одну константу во всех процедурах проекта(книги), необходимо объявить её как Public:
Public Const sMyConst As String = "Имя моей программы" Sub TestConst() MsgBox sMyConst 'показываем сообщение с именем программы End Sub Sub TestConst2() MsgBox sMyConst 'не вызовет ошибку Variable not defined, даже если процедура в другом модуле End Sub
Подробнее можно прочитать выше — как я уже писал для констант применяются те же правила, что и для переменных.
Также см.:
Variable not defined или что такое Option Explicit и зачем оно нужно?
Что такое модуль? Какие бывают модули?
Что такое макрос и где его искать?
Отлов ошибок и отладка кода VBA
Статья помогла? Поделись ссылкой с друзьями!
Видеоуроки
Поиск по меткам
Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика
В данной статье мы рассмотрим работу с локальными и глобальными переменными VBA языка, а именно: как ведут себя переменные, объявленные в блоке модуля и в блоке отдельной процедуры; познакомимся с ключевыми словами Public, Private и Static; Определим логику назначении типов данных при объявлении нескольких переменных в одной строке; напишем парочку примеров.
В прошлых статьях мы кратко рассмотрели переменные и типы данных, теперь настало время более подробно вникнуть во все тонкости…
Содержание
- Объявление нескольких переменных VBA
- Объявление переменных в VBA локальной и глобальной видимости
- Ключевые слова Private, Public и Static
Объявление нескольких переменных VBA
Рассмотрим такой пример: надо объявить три переменные разного типа, например, Byte, String и Long, это может выглядеть так:
dim A as Byte, B as String, C as Long
Но вот что делать, если все три переменные должны быть одного типа, такой код будет неверен:
Тут A и В будут типа Variant и только C – Long. Что бы все правильно сработало, нам нужно каждой переменной назначить заданный тип:
dim A as Long, B as Long, C as Long
Объявление переменных в VBA локальной и глобальной видимости
Если переменная VBA объявлена в начале модуля, то она сохраняется в памяти до тех пор, пока работает макрос, если объявление происходит в теле процедуры, то переменная будет удалена из памяти сразу, после выполнения блока кода заданной процедуры. Добавьте в редакторе Visual Basic новую форму и модуль.
Параметры формы: разместите на форме три компонента Label и три кнопки, как показано на рисунке. Имя формы (свойство Name) – VariableForm, имя модуля – VariableModule.
В редакторе кода для модуля пропишите:
Sub VariableModule() VariableForm.Show End Sub
Тут мы просто определяем, что при запуске макроса нужно запустить форму.
В редакторе кода для формы пропишите:
'************************************************** ' Объявление локальных и глобальных переменных в VBA '************************************************** ' Включаем проверку переменных VBA Option Explicit ' Глобальная переменная Dim GVar As Integer 'Нельзя присвоить значение вне процедуры!!! 'GVar = 10 Sub GetGlobal() ' Увеличиваем значение на 5 GVar = GVar + 5 Label1.Caption = "Глобальное значение " & GVar End Sub Sub GetLocal_1() Dim LVar As Integer ' Увеличиваем значение на 2 LVar = LVar + 2 Label2.Caption = "Локальное значение " & LVar End Sub Sub GetLocal_2() Dim LVar As Integer ' Увеличиваем значение на 3 LVar = LVar + 3 Label3.Caption = "Локальное значение " & LVar End Sub Private Sub CommandButton1_Click() Call GetGlobal End Sub Private Sub CommandButton2_Click() Call GetLocal_1 End Sub Private Sub CommandButton3_Click() Call GetLocal_2 End Sub Private Sub UserForm_Click() End Sub Private Sub UserForm_Initialize() ' настройка первого текстового поля Label1.FontSize = 12 Label1.ForeColor = &HFF0000 Call GetGlobal ' настройка второго текстового поля Label2.FontSize = 12 Label2.ForeColor = &H6400 Call GetLocal_1 ' настройка третьего текстового поля Label3.FontSize = 12 Label3.ForeColor = &HFF Call GetLocal_2 End Sub
В самом начале мы объявляем глобальную переменную VBA – GVar типа Integer, в комментарии указано, что вне процедуры присвоить значение переменной нельзя. Далее следуют три процедуры, в первой процедуре происходит увеличение значение глобальной GVar на 5, результат будет записываться в свойство Caption первого компонента Label. Вторя и третья процедуры производят аналогичные действия, только для объявленных в них локальных переменных VBA, LVar, происходит увеличение значения на 2 и на 3, соответственно. События Click (нажатие кнопки мыши) для кнопок будет вызывать заданные процедуры.
При запуске макроса в полях будут отображаться значения 5, 2 и 3. При нажатии на “Кнопка 1” будет происходить вызов процедуры GetGlobal и увеличение значения переменной GVar на 5. Для “Кнопка 2” и “Кнопка 3” будут вызываться процедуры GetLocal_1 и GetLocal_2, однако ничего увеличиваться не будет, так как переменные LVar являются локальными и при каждом вызове заданных процедур их значение будет обнуляться.
Ключевые слова Private, Public и Static
Private – аналогично ключевому слову Dim, использование Private вместо Dim актуально в том случае, если вы хотите, что бы данное ключевое слово напоминало о том, что переменная доступна только в пределах данной процедуры или функции.
Public – позволяет сделать переменную VBA доступной из любой части проекта, однако, это будет актуальным лишь в том случае, если объявление переменных в VBA происходит в разделе Declarations (Объявления) самого модуля. Если же вы пропишите Public вместо Dim в теле процедуры, то видимость все ровно будет доступна только в данной процедуре.
Static – данное ключевое слово актуально использовать вместо Dim тогда, когда нужно сохранять значение переменной в теле процедуры. Для примера, мы перепишем предыдущий код таким образом:
Sub GetLocal_1() Static LVar As Integer ' Увеличиваем значение на 2 LVar = LVar + 2 Label2.Caption = "Локальное значение " & LVar End Sub Sub GetLocal_2() Static LVar As Integer ' Увеличиваем значение на 3 LVar = LVar + 3 Label3.Caption = "Локальное значение " & LVar End Sub
Мы просто изменили ключевое слово Dim на Static, и теперь переменные LVar не будут удаляться из памяти после выполнения процедур. Объявление переменных в VBA. Обратите внимание, что мы объявили переменные с одним именем, это можно, так как они находятся в отдельных процедурах.