Option explicit что это
Все, пора поговорить о переменных. Перегружать информацией я тебя не буду, но минимум знать надо.
Очень желательно, чтобы программа начиналась с инструкции Option Explicit в секции General. Эта инструкция заставляет программиста явно объявлять переменные. При ее отсутствии всякое слово, не противоречащее синтаксису VB, может быть переменной.
Что происходит, если мы не используем инструкцию Option Explicit? А то, что мы вообще можем не объявлять переменные. Это ведь здорово! А вот и нет! А почему нет, видно из следующего:
При отсутствии Option Explicit, если нам нужна новая переменная, мы просто вводим ее в код программы, например,
и опс, Visual Basic уже подсуетился и зарезервировал для переменной памяти, причем зарезервировал по полной программе — максимально. Дело в том, что если явно не задавать тип переменнной, VB считает переменную типом Variant, так как такая переменная может содержать почти любые данные: и целые, и дробные, и строковые. Зато и памяти эта переменная использует очень много. Если же мы явно объявим переменную и зададим ее тип сообразно с нашими потребностями, то рациональное использование памяти — на лицо.
Если тебя это соображение не убедило, то представим ситуацию, когда ты повторно используешь свою переменную для, например, изменения ее значения. И при этом делаешь опечатку (а опечаток делается очень много), пропускаешь букву h:
Для Visual Basic в этом никакой ошибки нет. Он при компиляции быстренько резервирует память под новую переменную NewCislo, считая ее типом Variant и у него никаких проблем. Проблемы у тебя. И критичные. Во-первых, ты имеешь ненужную переменную NewCislo со значением 1, о которой ты знать не знаешь. Во-вторых, если ты ожидаешь, что значение твоей начальной переменной NewChislo увеличилось на 1 и стало 8, то это совершенно напрасно. А вот ожидать, что результат выполнения твоей программы даст непредсказуемый результат можно смело.
Иное дело, если ты использовал инструкцию Option Explicit. В этом случае, при запуске программы, Visual Basic тут же найдет новую необъявленную переменную и остановит выполнение программы на строке с ошибкой.
Если я тебя убедил, тогда, чтобы не писать инструкцию Option Explicit в каждом новом проекте, нажми кнопку “Инструменты” (Tools), выбери “Опции” и в окрывшемся окне на вкладке “Редактор” поставь галочку напротив надписи “Требовать определение переменной”, потом OK. Теперь, всякий раз при создании нового проекта (но только нового, в старые эту инструкцию надо прописывать в (General) вручную.), VB сам, автоматически, будет прописывать Option Explicit .
Любое слово, кроме зарезервированных VB, можно сделать именем переменной. Но начинаться имя должно с буквенного символа. Например Peremenaia, Ima1, X, LastNumber, z001. Не надо использовать в именах математические операторы. И нельзя объявлять две переменные с одинаковыми именами. В принципе, для удобства чтения кода и солидности существуют определенные рекомендованные правила (что-то вроде стандартов) написания имен переменных. Но, так как использование этих правил — сугубо личное дело каждого, я их придерживаться не буду. Если охота, поищи в Интернете что-нибудь про Венгерское соглашение, Венгерскую нотацию или соглашение Реддика.
Итак, при явном объвлении переменной очень желательно явно задавать ее тип. В крайне редких случаях, когда тип хранимых данных в переменной заранее неизвестен, используется как раз тип Variant. В Visual Basic наиболее часто используются следующие типы данных (а соответственно переменных):
Long ‘длинное целое число со знаком от –2 147 483 648 до 2 147 483 647
Integer ‘целое число со знаком от –32 768 до 32767
String ‘строка символов
Boolean ‘логическое, принимает два значения или “True” (Истина) или “False” (Ложь)
Пока что нам этого хватит. Если интересно, то перечень типов данных, поддерживаемые VB, можно посмотреть здесь.
Теперь, где и как их объявлять. Если ты объявишь переменную в теле процедуры объекта, например кнопки, то доступна она будет только в этой процедуре. В другой, скажем, кнопке, ее использовать нельзя. Чтобы переменную использовать во всей форме, надо объявить ее в разделе деклараций (это в самом верху кода – (General) – (Declarations). Для этих случаев можно использовать инструкцию Dim. Ну, а чтоб она была доступна во всей программе (в разных, например, формах) она должна быть объявлена в стандартном модуле с ключевым словом Public. Но модулей мы пока не создавали и оставим это до поры в стороне. Ну вот, на первое время этого о переменных хватит. Чтобы было совсем понятно, вот пример объявления переменных:
Option Explicit
Dim MyStream As String
Dim K14 As Long
Dim Flag As Boolean
Dim Numder As Integer
Private Sub Form_Load()
Dim Flag2 As Boolean
Dim m99little As String
End Sub
Таймер. Программа “Часики”. |
Теперь разберем использование нового объекта — Timer (таймера). Слева, где компоненты формы, они же инструменты-элементы, нарисован такой будильничек. Это таймер и есть. Он всегда невидимый, но нужный элемент. Всего их одновременно можно использовать около 30 штук. Но нам такое количество таймеров не надо.
Создадим новый exe-проект и поместим один таймер на форму. На основе его мы сделаем сейчас маленькие часики. В свойствах этого таймера поставьте следующие установки:
Enabled – False (по умолчанию True) означает, что таймер выключен
Interval – 1000 (время, в миллисекундах, через которое таймер срабатывает, если конечно включен). Таймер будет срабатывать каждые 1000 мск, т.е. каждую секунду, как в нормальных часах.
Кроме того, нам понадобятся три лейбла: Label1 для секунд, Label2 для минут и Label3 – сами догадайтесь для чего. Правильно, для часов. Все.
Изменим свойства лейблов следующим образом:
Alignment – 2-Центровка (Это чтоб цифры были по центру лейблов)
BorderStyle – 1-Фиксировано (это чтоб размер формы нельзя было изменить)
Caption – 00 (на всякий случай, т.е. значение лейблов изначально будет “00”)
Нажми Font и выбери размер шрифта 14, а начертание – полужирное. После этого подбери подходящий размер окон Лейблов, чтобы цифры в них выглядели симпатично.
Должно получиться как на рис.8.
Создадим процедуру Form_Load .
Option Explicit
Private Sub Form1_Load()
З атем в теле процедуры, как у всякой приличной программы, меняем заголовок формы.
Form1.Caption = "Часики"
Дальше, для того, чтобы наши часы сразу показывали текущее время, надо его взять из компьютера. Чтобы получить системное время, есть функция Time (Label1.Caption=Time). Но она дает полное время одной строкой (16:23:42). Нам тогда придется выбирать из нее секунды, минуты и часы, чтобы распихать по свои лейблам. А чтобы этого не делать, можно взять готовые функции, которые предоставят нам это все по частям:
Label1.Caption = Second(Time) ‘стало быть секунды
Label2.Caption = Minute(Time) ‘ну, минуты
Label3.Caption = Hour(Time) ‘ и часы
Теперь, при запуске того, что мы наваяли, у нас будет показываться текущее время. Это, конечно, прогресс, но вот только часики-то стоят. Трясти монитор не стоит, они от этого не пойдут, а вот запустить таймер одной простой строчкой мы сможем:
Timer1.Enabled = True
Вот она, булева алгебра (ну еще не алгебра, но уже кое-что). То есть Timer1.Enabled может быть либо включен ( True ) , либо выключен ( False ). На этом п роцедура Form1_Load() закончена:
Чтобы получить хоть какие-нибудь блага от запущенного таймера и заставить наши часики ходить, создадим процедуру, которая будет исполняться при наступлении события срабатывания таймера. Событие это у таймера единственное и называется тоже .Timer. Возникает оно в тот момент, когда таймер досчитывает до предела, установленного в свойстве Interval и соответственно сбрасывается на ноль.
Private Sub Timer1_Timer()
Наши секунды должны увеличиваться на одну за каждое срабатывание таймера. Поэтому пишем счетчик, который будет увеличивать значение наших секунд на единицу при каждом срабатывании таймера:
Label1.Caption = Label1.Caption + 1
И вот мы вплотную подошли к проблеме условного оператора (а лучше инструкции) If, без которого — никуда. Суть этой инструкции в том, что он позволяет при неком создавшемся условии производить изменения в ходе программы в зависимости от этого условия.
Инструкция условия If. |
Этоу инструкцию можно использовать в блоковой форме: полном (развернутом) виде и неполном (без строк ElseIf), а также в одну строку.
В полном виде в блоковой форме синтаксис этой инструкции будет выглядеть следующим образом:
If Условие1 Then
группа операторов1
ElseIf Условие2 Then
группа операторов2
.
ElseIf УсловиеN Then
группа операторовN
Else
Последняя группа операторов
End If
Условие представляет из себя оператор, значение которого может принимать True (Истина) или False (Ложь). Например, если Условие1 представляет из себя выражение X>1, то оно истинно, если X равно 2, то оно ложно при значении X равном 1. Если Условие1 истинно, то выполняется группа операторов1, остальные группы операторов не выполняются, если даже в каких-нибудь последующих ветках УсловиеN истинно. Если Условие1 ложно, то группа операторов1 не выполняется, а производится проверка Условие2 в следующей ветке ElseIf . И опять же, если Условие2 истинно, то выполняется группа операторов2, последующие группы операторов не выполняются и их условия не проверяются. В противном случае происходит переход к следующей ветке ElseIf . Если ни в одной ветке нет истинных операторов, выполняется последняя группа операторов вне зависимости от каких-либо условий. Логическая схема инструкции If представлена в таблице:
Name already in use
VBA-Docs / Language / Reference / User-Interface-Help / option-explicit-statement.md
- Go to file T
- Go to line L
- Copy path
- Copy permalink
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
Option Explicit statement
Used at the module level to force explicit declaration of all variables in that module.
Option Explicit
If used, the Option Explicit statement must appear in a module before any procedures.
When Option Explicit appears in a module, you must explicitly declare all variables by using the Dim, Private, Public, ReDim, or Static statements. If you attempt to use an undeclared variable name, an error occurs at compile time.
If you don’t use the Option Explicit statement, all undeclared variables are of Variant type unless the default type is otherwise specified with a Deftype statement.
[!NOTE] Use Option Explicit to avoid incorrectly typing the name of an existing variable or to avoid confusion in code where the scope of the variable is not clear.
This example uses the Option Explicit statement to force explicit declaration of all variables. Attempting to use an undeclared variable causes an error at compile time. The Option Explicit statement is used at the module level only.
excel-vba
Лучшие практики VBA
Мы все знаем их, но эти практики гораздо менее очевидны для тех, кто начинает программировать в VBA.
ВСЕГДА Используйте «Option Explicit»
В окне редактора VBA в меню «Сервис» выберите «Параметры»:
Затем на вкладке «Редактор» убедитесь, что «Требовать переменную декларацию» отмечен:
При выборе этой опции автоматически добавляется Option Explicit в верхней части каждого модуля VBA.
Небольшое примечание: это верно для модулей, модулей классов и т. Д., Которые пока не были открыты. Поэтому, если вы уже рассмотрели, например, код Sheet1 перед тем как активировать опцию «Требовать объявление переменной», Option Explicit не будет добавлен!
Option Explicit требует, чтобы каждая переменная была определена перед использованием, например, с помощью оператора Dim . Без Option Explicit , любое непризнанное слово будет приниматься компилятором VBA как новая переменная типа Variant , вызывая чрезвычайно сложные ошибки, связанные с типографскими ошибками. Если Option Explicit включена, любые непризнанные слова вызовут ошибку компиляции, указывая на строку нарушения.
Пример :
Если вы запустите следующий код:
Появится следующее сообщение:
Вы сделали ошибку, написав myvariable вместо my_variable , затем в поле сообщения отображается пустая переменная. Если вы используете Option Explicit , эта ошибка невозможна, потому что вы получите сообщение об ошибке компиляции, указывающее на проблему.
Теперь, если вы добавите правильное объявление:
Вы получите сообщение об ошибке с указанием ошибки с myvariable :
-
Будьте осторожны, чтобы не пропустить имя массива при использовании оператора ReDim
-
Даже если оператор Option Explicit включен в модуль, будет создан новый массив
Dim arr() as Long
ReDim ar() 'creates new array "ar" — "ReDim ar()" acts like "Dim ar()"
Работа с массивами, а не с диапазонами
Часто достигается наилучшая производительность, позволяя максимально избегать использования Range . В этом примере мы читаем весь объект Range в массив, каждый квадрат в массиве, а затем возвращаем массив обратно в Range . Это позволяет получить доступ к Range только дважды, тогда как цикл будет обращаться к нему 20 раз для чтения / записи.
Дополнительные советы и информация с приуроченными примерами можно найти в статье Чарльза Уильямса «Эффективные VBA UDF» (часть 1) и других статьях в этой серии .
Используйте константы VB, если они доступны
могут быть использованы вместо
чтобы улучшить удобочитаемость.
Используйте Object Browser, чтобы найти доступные константы VB. Просмотр → Обозреватель объектов или F2 из редактора VB.
Введите класс для поиска
Использовать описательные имена переменных
Описательные имена и структура в коде помогут сделать комментарии ненужными
Это особенно полезно при копировании данных из одного места в другое, будь то ячейка, диапазон, рабочий лист или рабочая книга. Помогите себе, используя такие имена:
Если вы объявляете несколько переменных в одной строке, обязательно указывайте тип для каждой переменной:
Следующие будут объявлять только последнюю переменную, а первая останется Variant :
Обработка ошибок
Хорошая обработка ошибок не позволяет конечным пользователям видеть ошибки времени выполнения VBA и помогает разработчику легко диагностировать и исправлять ошибки.
Существует три основных метода обработки ошибок в VBA, два из которых следует избегать для распределенных программ, если это специально не требуется в коде.
По ошибке GoTo 0
Если в вашем коде не установлена ошибка, On Error GoTo 0 является обработчиком ошибок по умолчанию. В этом режиме любые ошибки времени выполнения запускают типичное сообщение об ошибке VBA, позволяющее либо закончить код, либо ввести режим debug , идентифицируя источник. При написании кода этот метод является самым простым и полезным, но его всегда следует избегать для кода, который распространяется среди конечных пользователей, поскольку этот метод очень непригляден и затруднен для понимания конечными пользователями.
On Error Resume Next VBA будет игнорировать любые ошибки, возникающие во время выполнения для всех строк, следующих за вызовом ошибки, до тех пор, пока обработчик ошибок не будет изменен. В очень конкретных случаях эта строка может быть полезна, но ее следует избегать за пределами этих случаев. Например, при запуске отдельной программы из макроса Excel вызов On Error Resume Next может быть полезен, если вы не уверены, открыта ли программа или нет:
Если бы мы не использовали GetObject вызов On Error Resume Next и приложение Powerpoint еще не было открыто, метод GetObject бы ошибку. Таким образом, для устранения двух экземпляров приложения необходимо было On Error Resume Next .
Примечание. Также рекомендуется сразу же сбросить обработчик ошибок, как только вам больше не понадобится On Error Resume Next вызова»
Вкл. Ошибка GoTo <строка>
Этот метод обработки ошибок рекомендуется для всего кода, который распространяется среди других пользователей. Это позволяет программисту точно контролировать, как VBA обрабатывает ошибку, отправив код в указанную строку. Тег можно заполнить любой строкой (включая числовые строки) и отправить код в соответствующую строку, за которой следует двоеточие. Несколько блоков обработки ошибок можно использовать, выполняя различные вызовы On Error GoTo <line> . Нижеприведенная подпрограмма демонстрирует синтаксис вызова On Error GoTo <line> .
Примечание. Важно, чтобы строка Exit Sub была помещена над первым обработчиком ошибок и перед каждым последующим обработчиком ошибок, чтобы предотвратить естественный переход кода в блок без вызываемой ошибки. Таким образом, лучше всего использовать функцию и читаемость для размещения обработчиков ошибок в конце блока кода.
Если вы выйдете из своего метода с кодом обработки ошибок, убедитесь, что вы очистили:
- Отменить все, что частично завершено
- Закрыть файлы
- Сбросить обновление экрана
- Сбросить режим расчета
- Сбросить события
- Сбросить указатель мыши
- Вызов метода выгрузки для экземпляров объектов, которые сохраняются после End Sub
- Сброс строки состояния
Документируйте свою работу
Хорошей практикой является документирование вашей работы для последующего использования, особенно если вы кодируете динамическую рабочую нагрузку. Хорошие комментарии должны объяснять, почему код что-то делает, а не то, что делает код.
Если ваш код настолько неясен, что он требует комментариев, чтобы объяснить, что он делает, подумайте о том, чтобы переписать его, чтобы быть более понятным, а не объяснять его с помощью комментариев. Например, вместо:
Уточнить код, который будет проще следовать, например:
Отключение свойств во время выполнения макроса
Лучше всего на любом языке программирования избегать преждевременной оптимизации. Однако, если тестирование показывает, что ваш код работает слишком медленно, вы можете получить некоторую скорость, отключив некоторые свойства приложения во время его запуска. Добавьте этот код в стандартный модуль:
И просто назовите его в начале и в конце макросов:
Хотя они могут в значительной степени рассматриваться как «усовершенствования» для обычных Public Sub процедур Public Sub , отключение обработки событий с помощью Application.EnableEvents = False должно считаться обязательным для макросов частного события Worksheet_Change и Workbook_SheetChange которые изменяют значения на одном или нескольких листах. Невозможность отключить триггеры событий заставит макрос события рекурсивно запускаться поверх себя, когда значение изменится и может привести к «замороженной» книге. Не забудьте снова включить события, прежде чем покинуть макрос события, возможно, с помощью обработчика ошибок «безопасного выхода».
Одно предостережение. Хотя отключение этих настроек улучшит время выполнения, они могут затруднить отладку приложения. Если код не работает надлежащим образом , закомментируйте SpeedUp True вызов , пока вы не выяснить проблему.
Это особенно важно, если вы пишете ячейки на листе, а затем читаете в вычисленных результатах из функций листа, поскольку xlCalculationManual позволяет xlCalculationManual книгу. Чтобы обойти это без отключения SpeedUp , вы можете включить Application.Calculate для выполнения расчета в определенных точках.
ПРИМЕЧАНИЕ. Поскольку это свойства самого Application , вам нужно убедиться, что они снова включены до того, как вы закончите макрос. Это делает особенно важным использование обработчиков ошибок и избежание множественных точек выхода (например, End или Unload Me ).
С обработкой ошибок:
Избегайте использования ActiveCell или ActiveSheet в Excel
Использование ActiveCell или ActiveSheet может быть источником ошибок , если (по любой причине) код выполняется в неправильном месте.
- Использование Active* может создавать проблемы в длинных макросах, если ваш пользователь скучает и нажимает на другой рабочий лист или открывает другую книгу.
- Это может создать проблемы, если ваш код открывается или создает другую книгу.
- Это может создать проблемы, если ваш код использует Sheets("MyOtherSheet").Select и вы забыли, какой лист вы были, прежде чем начинать читать или писать на него.
Никогда не допускайте рабочий лист
Даже когда вся ваша работа направлена на один рабочий лист, все же очень хорошая практика явно указывать рабочий лист в вашем коде. Эта привычка значительно облегчает расширение вашего кода позже или поднять части (или все) Sub или Function которые будут повторно использоваться где-то еще. Многие разработчики устанавливают привычку (re) использовать одно и то же имя локальной переменной для рабочего листа в своем коде, что делает повторное использование этого кода еще более простым.
Например, следующий код неоднозначен, но работает! — пока разработчик не активирует или не переключается на другой рабочий лист:
Если Sheet1 активен, ячейка A1 на Листе 1 будет заполнена текущей датой и временем. Но если пользователь по какой-либо причине меняет листы, тогда код обновит все текущие рабочие листы. Рабочий лист адресата неоднозначен.
Лучшая практика — всегда определять, какой лист, на который ссылается ваш код:
Вышеприведенный код ясен при определении как рабочей книги, так и рабочего листа. Хотя это может показаться излишним, создание хорошей привычки в отношении целевых ссылок избавит вас от будущих проблем.
Избегайте использования SELECT или ACTIVATE
Очень редко вы когда-либо захотите использовать Select или Activate в своем коде, но некоторые методы Excel требуют, чтобы рабочий лист или рабочая книга были активированы до того, как они будут работать должным образом.
Если вы только начинаете изучать VBA, вам часто предлагается записать ваши действия с помощью макросъемщика, а затем взглянуть на код. Например, я записал действия, предпринятые для ввода значения в ячейке D3 на Sheet2, и макрокоманда выглядит следующим образом:
Помните, однако, макрорекордер создает строку кода для КАЖДОГО из ваших (пользовательских) действий. Это включает в себя щелчок на вкладке рабочего листа, чтобы выбрать Sheet2 ( Sheets("Sheet2").Select ), щелкнув по ячейке D3 перед вводом значения ( Range("D3").Select ) и с помощью клавиши Enter (которая эффективно « выбрав «ячейку ниже текущей выбранной ячейки: Range("D4").Select ).
Существует несколько проблем с использованием. .Select здесь:
- Рабочий лист не всегда указывается. Это происходит, если вы не меняете рабочие листы во время записи и означает, что код даст разные результаты для разных активных рабочих листов.
- .Select() работает медленно. Даже если для параметра Application.ScreenUpdating установлено значение False , это необработанная операция, которая должна быть обработана.
- .Select() неуправляем. Если Application.ScreenUpdating остается равным True , Excel будет фактически выбирать ячейки, рабочий лист, форму . независимо от того, с чем вы работаете. Это стрессово для глаз и действительно неприятно смотреть.
- .Select() вызовет прослушиватели. Это уже немного продвинуто, но если не работать, будут запускаться такие функции, как Worksheet_SelectionChange() .
Когда вы кодируете в VBA, все действия «набрав» (т. Select Команды Select ) больше не нужны. Ваш код может быть сведен к одному оператору, чтобы поместить значение в ячейку:
(Пример BETTER выше показывает использование промежуточных переменных для разделения разных частей ссылки на ячейку. Пример GOOD всегда будет работать очень хорошо, но может быть очень громоздким в гораздо более длинных модулях кода и более сложным для отладки, если одна из ссылок неверна. )
** ПРИМЕЧАНИЕ. Макросъемщик делает много предположений о типе данных, которые вы вводите, в этом случае вводите строковое значение в качестве формулы для создания значения. Ваш код не должен делать этого и может просто назначить числовое значение непосредственно ячейке, как показано выше.
** Примечание 2: рекомендуемая практика , чтобы установить локальную переменную рабочую книгу ThisWorkbook вместо ActiveWorkbook (если явно не нужно). Причина заключается в том, что ваш макрос обычно должен / использовать ресурсы в любой книге, из которой возникает код VBA, и НЕ будет выглядеть за пределами этой книги — опять же, если вы явно не назовете свой код работать с другой книгой. Когда вы открываете несколько книг в Excel, ActiveWorkbook — это та, которая может отличаться от рабочей книги, просматриваемой в редакторе VBA . Итак, вы думаете, что работаете в одной книге, когда вы действительно ссылаетесь на другую. ThisWorkbook относится к книге, содержащей исполняемый код.
Всегда определяйте и устанавливайте ссылки на все книги и таблицы
При работе с несколькими открытыми рабочими книгами, каждая из которых может иметь несколько листов, наиболее безопасно определить и установить ссылку на все книги и таблицы.
Не полагайтесь на ActiveWorkbook или ActiveSheet поскольку они могут быть изменены пользователем.
В следующем примере кода показано , как скопировать диапазон от листа «Raw_Data» в книге «Data.xlsx» на листе «Refined_Data» в книге «Results.xlsx».
Эта процедура также демонстрирует, как копировать и вставлять, не используя метод Select .
Объект WorksheetFunction выполняется быстрее, чем эквивалент UDF
VBA компилируется во время выполнения, что оказывает огромное негативное влияние на его производительность, все встроенное будет быстрее, попробуйте использовать их.
В качестве примера я сравниваю функции SUM и COUNTIF, но вы можете использовать, если для чего-нибудь, что вы можете решить с помощью WorkSheetFunctions.
Первой попыткой для них было бы перебрать диапазон и обработать его ячейкой по ячейке (используя диапазон):
Одним из улучшений может быть сохранение значений диапазона в массиве и процесс, который:
Но вместо написания любого цикла вы можете использовать Application.Worksheetfunction что очень удобно для выполнения простых формул:
Или, для более сложных вычислений вы можете даже использовать Application.Evaluate :
И, наконец, работая над Subs 25 000 раз каждый, вот среднее (5 тестов) время в миллисекундах (конечно, это будет отличаться на каждом ПК, но по сравнению друг с другом они будут вести себя аналогичным образом):
- UseWorksheetFunction: 2156 мс
- UseArray: 2219 мс (+ 3%)
- UseEvaluate: 4693 мс (+ 118%)
- UseRange: 6530 мс (+ 203%)
Избегайте повторного назначения имен свойств или методов в качестве переменных
Обычно не считается «лучшей практикой» повторно назначать зарезервированные имена свойств или методов как имя (имена) ваших собственных процедур и переменных.
Плохая форма. В то время как следующий (строго говоря) законный, рабочий код повторное назначение метода Find, а также свойства Row , Column и Address могут вызвать проблемы / конфликты с неоднозначностью имени и просто путают в целом.
Хорошая форма. Все зарезервированные слова, переименованные в близкие, но уникальные аппроксимации оригиналов, избегали любых возможных конфликтов имен.
Хотя может наступить время, когда вы хотите намеренно переписать стандартный метод или свойство в соответствии со своими собственными спецификациями, эти ситуации немногочисленны и далеки друг от друга. По большей части избегайте повторного использования зарезервированных имен для ваших собственных конструкций.
Объявление переменных в VBA или одна неочевидная особенность языка, показывающая, читали ли вы манул или учились на практике
Всё, что написано ниже, относится к VBA, реализованному внутри Excel из комплекта Office 365 по состоянию на февраль 2021 года. Скорее всего, всё обстоит так же и в остальных версиях офиса, насколько помню — с 97.
Что такое переменные, зачем они нужны и прочие базовые принципы я пропущу, здесь всё достаточно очевидно(*) даже на уровне ощущений.
Но есть одна особенность, которая неочевидна, упомянута в мануле одной строкой, и в корне отличается от реализации в других диалектах VB — например, в .NET.
Во-первых, примем как должное, что код в VBA в любом (во всех!) модулях должен начинаться со строки
Это не обязательное требование, но оно сродни требованию включать поворотник при любом манёвре и пристёгиваться до начала движения: однажды оно спасёт вам жизнь, а для этого должно стать — даже не привычкой — рефлексом.
Не будем говорить про стиль написания кода — тут больше вопрос собственного удобства, но иногда хочется или необходимо объявить несколько переменных в одной строке
Простейшая задача: объявить в одной строке две строковые переменные — вызывает лютое желание написать
Эта строчка абсолютно корректна с точки зрения синтаксиса, будет работать почти всегда, однако, делает она совсем не то, что было задано. А именно, она объявляет одну строковую переменную и одну — нетипизированную.
Нетипизированные переменные, напомню, получают тот тип, который имеют записанные в них данные, и могут менять тип в процессе выполнения кода. Как любая мощная магия, они требуют понимания как оно работают и умения обращаться с ними.
По большому счёту, код с нетипизироанными переменными работает ровно так же, как и с типизированными. Отличие в том, что он делает не то, что вы задумали, а то, что понял интерпретатор из ваших косноязычных объяснений.
Пример кода, объясняющего происходящее:
Как видно, переменная S1 в начале выполнения кода вовсе не имеет типа (Empty), а потом меняет его несколько раз.
В то же время, S2 также принимает разные значения, при этом всегда оставаясь строковой. В её случае происходит неявное преобразование данных разных типов к строковому типу.
Данное поведение описано в документации по VBA https://docs.microsoft.com/ru-ru/office/vba/language/concept.
Хотя кто будет читать документацию! Особенно с раздела «объявление переменных». Особенно, если уже имеешь опыт программирования вообще и на похожем языке в частности.
Данная особенность VBA неочевидна. Более того, в VB для .NET данная конструкция ведёт себя противоположным образом: https://docs.microsoft.com/ru-ru/dotnet/visual-basic/program.
Резюмируя:
1. Option Explicit — желательна и рекомендуется.
2. При определении переменных нужно учитывать особенность VBA.
————————————————————
(*)Читать документацию нужно с самого начала, даже если кажется, что всё это знаешь.