Ошибка переменная не определена vba

Пользовательское соглашение

Политика конфиденциальности

© Николай Павлов, Planetaexcel, 2006-2023
info@planetaexcel.ru


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

Техническая поддержка сайта

ООО «Планета Эксел»

ИНН 7735603520


ОГРН 1147746834949
        ИП Павлов Николай Владимирович
        ИНН 633015842586
        ОГРНИП 310633031600071 

Хитрости »

1 Май 2011              52120 просмотров


Option Explicit — начинающие программировать в Visual Basic могут увидеть данную строку в чужом коде, либо случайно в своем. Хотя кто-то может быть уже знает, что это и зачем и использует данное объявление намеренно. Я же постараюсь максимально подробно описать смысл этой строки и её полезность для кода в первую очередь для тех, кто еще не знает для чего она.

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

Собственно что же делает эта строка? А делает она следующее: она принуждает Вас объявлять переменные(если не знаете смысл объявления переменных — читайте здесь). Если какая-либо переменная внутри выполняемой процедуры не объявлена — Вы увидите такое вот сообщение:

рис.1

так же редактор VBA выделит ту переменную, которая не объявлена. Первое время это может раздражать. Да и вообще: зачем это? Вы и без всех этих объявлений неплохо жили. А вот зачем

  • во-первых: объявление переменных считается хорошим тоном при программировании
  • во-вторых: правильное присвоение типов недурно экономит память
  • ну и в-третьих(я бы даже сказал в главных): это помогает избежать неявных ошибок кода при несовпадении типов данных

А теперь перейдем к сути и попробуем разобраться в чем же польза от использования Option Explicit. Ниже приведен простой код:

Sub Check_Variables()
    Dim a As String
    a = "Привет от www.excel-vba.ru"
    MsgBox а, vbInformation
End Sub

Выполните данный код без строки Option Explicit. Какое значение выдаст MsgBox? Ничего. Что за странность? Ведь явно видно, что переменной присвоено значение текста. Ничего больше не происходит. Но переменная все равно пуста. Мистика…А теперь запишите первой строкой в модуле Option Explicit:

Option Explicit
Sub Check_Variables()
    Dim a As String
    a = "Привет от www.excel-vba.ru"
    MsgBox а, vbInformation
End Sub

Запустите код. И что же видите? Видите сообщение, показанное на рис.1 и выделенную переменную «а», в последней строке. Что это означает? Это означает, что переменная «а» у нас не объявлена. А все потому, что первой строкой (Dim a As String) я объявил переменную на английском языке, а в последней строке я записал её на русском. А для кода это разные символы. Если разглядеть логику работы VBA — первую «а» он видит как переменную с присвоенным типом String. И ей мы задаем значение «Привет от www.excel-vba.ru». А вторую…Вторую он не находит в объявленных переменных, не находит в функциях и сам инициализирует её как новую переменную с типом данных Variant. И, что вполне логично, со значением Empty, т.е. ничего, т.к. этой переменной мы никаких значений не присваивали.

Еще один классический пример, когда Option Explicit спасет от лишних мозговых штурмов. Имеем простую функцию пользователя(UDF), которая берет указанную дату и возвращает её в заранее заданном формате в текстовом виде:

Function GetDateAsText(Optional ByVal Дата As Date)
    If Дата = 0 Then
        Дата = Date
    End If
    GetDataAsText = Format(Дата, "DD MMMM YYYY")
End Function

Хоть функция и короткая, но даже в ней не сразу порой бросается в глаза опечатка(представим, если функция в реальности строк на 200). В итоге чаще всего автор функции не понимает, почему при записи её на листе она возвращает не дату вида «21 мая 2016», а 0 и начинает пошагово выполнять функцию, искать ошибки в логике кода и т.д. Но если поставить в начало модуля Option Explicit, то при первом же выполнении этой функции VBA подсветит нам «GetDataAsText = «, указывая тем самым, что GetDataAsText в чем-то отличается от заданного имени функции — GetDateAsText. Банальная опечатка: GetDataAsText — GetDateAsText.


А теперь представьте себе, что Вы написали кучу длинного кода, строк на 100 или более. Конечно, Option Explicit Вы не используете. И вот Вы тестируете код, но он работает как-то не так…Где-то что-то неверно выполняется. И Вы начинаете пошагово ковыряться в листинге и искать ошибку…А ведь все может быть и проще: где-то в коде Вы могли банально опечататься и присвоить таким образом значение переменной, на которую Вы и не рассчитывали. А если использовать Option Explicit, то такая опечатка будет сразу обнаружена еще до выполнения кода и, что немаловажно — подсвечена. Так что Вам даже не придется её искать, а останется лишь исправить ошибку.

Так же эта строка поможет избежать неявных ошибок и в других ситуациях. В частности, при обращении к другим приложениями(Word, Outlook и т.д.). Например, в Excel применяются именованные константы для многих задач. Одна из распространенных — поиск последней ячейки в столбце: llast = Cells(Rows.Count, 1).End(xlUp).Row
здесь xlUp является именованной константой, значение которой равно числу: -4162. В других приложениях такой же подход. Это избавляет от необходимости помнить на память все значения констант и обращаться к ним при помощи intellisense. Но действуют эти константы исключительно внутри своего приложения(можете обратить внимание, у Excel константы начинаются с xl, а у Word — с wd). И т.к. объявлены эти константы в других приложениях — Excel про них не знает(как и другие приложения не знают про константы Excel). Для примера возьмем простой и рабочий код замены в Word:

    Dim wdDoc As Object
    Set wdDoc = objWordApp.ActiveDocument
    With wdDoc.Range.Find
        .Text = "привет"
        .Replacement.Text = "привет"
        .wrap = wdFindContinue
        .Execute Replace:=wdReplaceAll
    End With

Где wdFindContinue для Word-а равно 1, а wdReplaceAll = 2. Но это происходит только при выполнении изнутри самого Word-а(или при раннем связывании через ToolsReferences. Подробнее про это можно почитать в статье: Как из Excel обратиться к другому приложению).

Если же скопировать и выполнять данный код из Excel, то работать он будет не так как задумали. Дело в том, что Вы считаете, что Excel работает с обозначенными константами(wdFindContinue, wdReplaceAll) наравне с Word-ом. Но Excel на самом деле про них ничего не знает. И если директива Option Explicit будет отключена, то Excel просто назначает им значение по умолчанию — Empty. Которое преобразуется в 0. А это совсем иной поиск получается, т.к. должны быть значения 1 и 2. А если бы Option Explicit была включена, то Excel выделил бы их и указал, что они не объявлены. И тогда можно было бы сделать либо так:

    Dim wdDoc As Object
    Const wdFindContinue As Long = 1
    Const wdReplaceAll As Long = 2
    Set wdDoc = objWordApp.ActiveDocument
    With wdDoc.Range.Find
        .Text = "привет"
        .Replacement.Text = "привет"
        .wrap = wdFindContinue
        .Execute Replace:=wdReplaceAll
    End With

либо так(что удобнее, на мой взгляд):

    Dim wdDoc As Object
    Set wdDoc = objWordApp.ActiveDocument
    With wdDoc.Range.Find
        .Text = "привет"
        .Replacement.Text = "привет"
        .wrap = 1
        .Execute Replace:=2
    End With

Так что думаю, не стоит недооценивать значимость строки Option Explicit при написании кодов. В довершение хотелось бы Вас обрадовать, что вписывание данной строки в начало каждого модуля можно сделать автоматическим: поставить в опциях редактора галочку: ToolsOptions-вкладка EditorRequire Variable Declaration. Теперь во всех новых созданных модулях строка Option Explicit будет создаваться самим редактором VBA автоматически. К сожалению, в уже имеющихся модулях Вам придется проставить данную строку самим вручную. Но это того стоит, поверьте.

Так же см.:
Что такое переменная и как правильно её объявить?


Статья помогла? Поделись ссылкой с друзьями!

  Плейлист   Видеоуроки


Поиск по меткам



Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика

Хитрости »

1 Май 2011              50924 просмотров


Option Explicit — начинающие программировать в Visual Basic могут увидеть данную строку в чужом коде, либо случайно в своем. Хотя кто-то может быть уже знает, что это и зачем и использует данное объявление намеренно. Я же постараюсь максимально подробно описать смысл этой строки и её полезность для кода в первую очередь для тех, кто еще не знает для чего она.

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

Собственно что же делает эта строка? А делает она следующее: она принуждает Вас объявлять переменные(если не знаете смысл объявления переменных — читайте здесь). Если какая-либо переменная внутри выполняемой процедуры не объявлена — Вы увидите такое вот сообщение:

рис.1

так же редактор VBA выделит ту переменную, которая не объявлена. Первое время это может раздражать. Да и вообще: зачем это? Вы и без всех этих объявлений неплохо жили. А вот зачем

  • во-первых: объявление переменных считается хорошим тоном при программировании
  • во-вторых: правильное присвоение типов недурно экономит память
  • ну и в-третьих(я бы даже сказал в главных): это помогает избежать неявных ошибок кода при несовпадении типов данных

А теперь перейдем к сути и попробуем разобраться в чем же польза от использования Option Explicit. Ниже приведен простой код:

Sub Check_Variables()
    Dim a As String
    a = "Привет от www.excel-vba.ru"
    MsgBox а, vbInformation
End Sub

Выполните данный код без строки Option Explicit. Какое значение выдаст MsgBox? Ничего. Что за странность? Ведь явно видно, что переменной присвоено значение текста. Ничего больше не происходит. Но переменная все равно пуста. Мистика…А теперь запишите первой строкой в модуле Option Explicit:

Option Explicit
Sub Check_Variables()
    Dim a As String
    a = "Привет от www.excel-vba.ru"
    MsgBox а, vbInformation
End Sub

Запустите код. И что же видите? Видите сообщение, показанное на рис.1 и выделенную переменную «а», в последней строке. Что это означает? Это означает, что переменная «а» у нас не объявлена. А все потому, что первой строкой (Dim a As String) я объявил переменную на английском языке, а в последней строке я записал её на русском. А для кода это разные символы. Если разглядеть логику работы VBA — первую «а» он видит как переменную с присвоенным типом String. И ей мы задаем значение «Привет от www.excel-vba.ru». А вторую…Вторую он не находит в объявленных переменных, не находит в функциях и сам инициализирует её как новую переменную с типом данных Variant. И, что вполне логично, со значением Empty, т.е. ничего, т.к. этой переменной мы никаких значений не присваивали.

Еще один классический пример, когда Option Explicit спасет от лишних мозговых штурмов. Имеем простую функцию пользователя(UDF), которая берет указанную дату и возвращает её в заранее заданном формате в текстовом виде:

Function GetDateAsText(Optional ByVal Дата As Date)
    If Дата = 0 Then
        Дата = Date
    End If
    GetDataAsText = Format(Дата, "DD MMMM YYYY")
End Function

Хоть функция и короткая, но даже в ней не сразу порой бросается в глаза опечатка(представим, если функция в реальности строк на 200). В итоге чаще всего автор функции не понимает, почему при записи её на листе она возвращает не дату вида «21 мая 2016», а 0 и начинает пошагово выполнять функцию, искать ошибки в логике кода и т.д. Но если поставить в начало модуля Option Explicit, то при первом же выполнении этой функции VBA подсветит нам «GetDataAsText = «, указывая тем самым, что GetDataAsText в чем-то отличается от заданного имени функции — GetDateAsText. Банальная опечатка: GetDataAsText — GetDateAsText.


А теперь представьте себе, что Вы написали кучу длинного кода, строк на 100 или более. Конечно, Option Explicit Вы не используете. И вот Вы тестируете код, но он работает как-то не так…Где-то что-то неверно выполняется. И Вы начинаете пошагово ковыряться в листинге и искать ошибку…А ведь все может быть и проще: где-то в коде Вы могли банально опечататься и присвоить таким образом значение переменной, на которую Вы и не рассчитывали. А если использовать Option Explicit, то такая опечатка будет сразу обнаружена еще до выполнения кода и, что немаловажно — подсвечена. Так что Вам даже не придется её искать, а останется лишь исправить ошибку.

Так же эта строка поможет избежать неявных ошибок и в других ситуациях. В частности, при обращении к другим приложениями(Word, Outlook и т.д.). Например, в Excel применяются именованные константы для многих задач. Одна из распространенных — поиск последней ячейки в столбце: llast = Cells(Rows.Count, 1).End(xlUp).Row
здесь xlUp является именованной константой, значение которой равно числу: -4162. В других приложениях такой же подход. Это избавляет от необходимости помнить на память все значения констант и обращаться к ним при помощи intellisense. Но действуют эти константы исключительно внутри своего приложения(можете обратить внимание, у Excel константы начинаются с xl, а у Word — с wd). И т.к. объявлены эти константы в других приложениях — Excel про них не знает(как и другие приложения не знают про константы Excel). Для примера возьмем простой и рабочий код замены в Word:

    Dim wdDoc As Object
    Set wdDoc = objWordApp.ActiveDocument
    With wdDoc.Range.Find
        .Text = "привет"
        .Replacement.Text = "привет"
        .wrap = wdFindContinue
        .Execute Replace:=wdReplaceAll
    End With

Где wdFindContinue для Word-а равно 1, а wdReplaceAll = 2. Но это происходит только при выполнении изнутри самого Word-а(или при раннем связывании через ToolsReferences. Подробнее про это можно почитать в статье: Как из Excel обратиться к другому приложению).

Если же скопировать и выполнять данный код из Excel, то работать он будет не так как задумали. Дело в том, что Вы считаете, что Excel работает с обозначенными константами(wdFindContinue, wdReplaceAll) наравне с Word-ом. Но Excel на самом деле про них ничего не знает. И если директива Option Explicit будет отключена, то Excel просто назначает им значение по умолчанию — Empty. Которое преобразуется в 0. А это совсем иной поиск получается, т.к. должны быть значения 1 и 2. А если бы Option Explicit была включена, то Excel выделил бы их и указал, что они не объявлены. И тогда можно было бы сделать либо так:

    Dim wdDoc As Object
    Const wdFindContinue As Long = 1
    Const wdReplaceAll As Long = 2
    Set wdDoc = objWordApp.ActiveDocument
    With wdDoc.Range.Find
        .Text = "привет"
        .Replacement.Text = "привет"
        .wrap = wdFindContinue
        .Execute Replace:=wdReplaceAll
    End With

либо так(что удобнее, на мой взгляд):

    Dim wdDoc As Object
    Set wdDoc = objWordApp.ActiveDocument
    With wdDoc.Range.Find
        .Text = "привет"
        .Replacement.Text = "привет"
        .wrap = 1
        .Execute Replace:=2
    End With

Так что думаю, не стоит недооценивать значимость строки Option Explicit при написании кодов. В довершение хотелось бы Вас обрадовать, что вписывание данной строки в начало каждого модуля можно сделать автоматическим: поставить в опциях редактора галочку: ToolsOptions-вкладка EditorRequire Variable Declaration. Теперь во всех новых созданных модулях строка Option Explicit будет создаваться самим редактором VBA автоматически. К сожалению, в уже имеющихся модулях Вам придется проставить данную строку самим вручную. Но это того стоит, поверьте.

Так же см.:
Что такое переменная и как правильно её объявить?


Статья помогла? Поделись ссылкой с друзьями!

  Плейлист   Видеоуроки


Поиск по меткам

Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика

Hi I develop the first time using VBA (Was using vb.net etc. before).
I always get the error

Variable is not defined

when running the code.
On calling the method writeHeaders the program always quits.

Some help would be highly appreciated, this thing drives me nuts atm.

Option Explicit

Sub exportToAPplus()

    Dim applusImport As Workbook
    Set applusImport = createFile
    writeHeaders applusImport
End Sub

Function createFile() As Workbook

    Dim dateiName As String
    dateiName = Application.GetSaveAsFilename()
    If dateiName <> "Falsch" And dateiName <> "False" Then
        Dim applusImport As Workbook
        dateiName = dateiName + "xlsx"
        Set applusImport = Workbooks.Add
        Application.DisplayAlerts = False
        applusImport.SaveAs dateiName, FileFormat:=xlOpenXMLWorkbook
        Application.DisplayAlerts = True
        Set createFile = applusImport
    Else
        MsgBox ("Sie haben keinen Dateinamen ausgewählt, es wurde nichts 
        gespeichert.")
    End If

End Function

Sub writeHeaders(applusImport As Workbook)
    Dim headers() As Variant
    headers() = Array("DATUM", "AUFTRAG", "PERSONAL", "KSTR", "INNENAUFTRAG", "POSITION", "AG", "KAPAST", "MASCHINENGRUPPE", "START", "ENDE", "DAUER", "BESCHREIBUNG")
    Application.ScreenUpdating = False
    For i = LBound(headers()) To UBound(headers()) Step 1
        .Cells(1, 1 + i).Value = headers(i)
    Next i
    applusImport.Save
    Application.ScreenUpdating = True
End Sub

Hi I develop the first time using VBA (Was using vb.net etc. before).
I always get the error

Variable is not defined

when running the code.
On calling the method writeHeaders the program always quits.

Some help would be highly appreciated, this thing drives me nuts atm.

Option Explicit

Sub exportToAPplus()

    Dim applusImport As Workbook
    Set applusImport = createFile
    writeHeaders applusImport
End Sub

Function createFile() As Workbook

    Dim dateiName As String
    dateiName = Application.GetSaveAsFilename()
    If dateiName <> "Falsch" And dateiName <> "False" Then
        Dim applusImport As Workbook
        dateiName = dateiName + "xlsx"
        Set applusImport = Workbooks.Add
        Application.DisplayAlerts = False
        applusImport.SaveAs dateiName, FileFormat:=xlOpenXMLWorkbook
        Application.DisplayAlerts = True
        Set createFile = applusImport
    Else
        MsgBox ("Sie haben keinen Dateinamen ausgewählt, es wurde nichts 
        gespeichert.")
    End If

End Function

Sub writeHeaders(applusImport As Workbook)
    Dim headers() As Variant
    headers() = Array("DATUM", "AUFTRAG", "PERSONAL", "KSTR", "INNENAUFTRAG", "POSITION", "AG", "KAPAST", "MASCHINENGRUPPE", "START", "ENDE", "DAUER", "BESCHREIBUNG")
    Application.ScreenUpdating = False
    For i = LBound(headers()) To UBound(headers()) Step 1
        .Cells(1, 1 + i).Value = headers(i)
    Next i
    applusImport.Save
    Application.ScreenUpdating = True
End Sub

ГЛАВНАЯ

ТРЕНИНГИ

   Быстрый старт
   Расширенный Excel
   Мастер Формул
   Прогнозирование
   Визуализация
   Макросы на VBA

КНИГИ

   Готовые решения
   Мастер Формул
   Скульптор данных

ВИДЕОУРОКИ

ПРИЕМЫ

   Бизнес-анализ
   Выпадающие списки
   Даты и время
   Диаграммы
   Диапазоны
   Дубликаты
   Защита данных
   Интернет, email
   Книги, листы
   Макросы
   Сводные таблицы
   Текст
   Форматирование
   Функции
   Всякое

PLEX

   Коротко
   Подробно
   Версии
   Вопрос-Ответ
   Скачать
   Купить

ПРОЕКТЫ

ОНЛАЙН-КУРСЫ

ФОРУМ

   Excel
   Работа
   PLEX

© Николай Павлов, Planetaexcel, 2006-2022
info@planetaexcel.ru


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

Техническая поддержка сайта

ООО «Планета Эксел»

ИНН 7735603520


ОГРН 1147746834949
        ИП Павлов Николай Владимирович
        ИНН 633015842586
        ОГРНИП 310633031600071 

На чтение 25 мин. Просмотров 11k.

VBA Dim

Алан Перлис

Постоянная одного человека — переменная другого

Эта статья содержит полное руководство по работе с переменными и использованию VBA Dim.

Первый раздел содержит краткое руководство по использованию оператора
Dim, включая примеры и формат оператора Dim.

Остальная часть поста содержит наиболее полное руководство, которое вы
найдете в VBA Dim Statement.

Если вы заинтересованы в объявлении параметров, вы можете прочитать о
них здесь.

Содержание

  1. Краткое руководство по использованию VBA Dim Statement
  2. Полезные ссылки 
  3. Что такое VBA Dim Statement?
  4. Формат VBA Dim Statement
  5. Как использовать Dim с несколькими переменными
  6. Где я должен поместить Dim Statement?
  7. Использование Dim в циклах
  8. Могу ли я использовать Dim для присвоения значения?
  9. Dim действительно требуется?
  10. Использование Dim с Basic Variables
  11. Использование Dim с Variants
  12. Использование Dim с Objects
  13. Использование Dim с Arrays
  14. Устранение неполадок ошибок  Dim
  15. Локальные и глобальные переменные
  16. Заключение

Краткое руководство по использованию VBA Dim Statement

Описание Формат Пример
Базовая
переменная
Dim [имя
переменной] 
As [Тип]
Dim count As Long
Dim amount 
As Currency
Dim name As String
Dim visible 
As Boolean
Фиксированная
строка
Dim [имя
переменной] 
As String *[размер]
Dim s As String * 4
Dim t As String * 10
Вариант Dim [имя
переменной] 
As Variant
Dim [имя
переменной]
Dim var As Variant
Dim var
Объект
использует
Dim и New
Dim [имя
переменной] 
As New [тип объекта]
Dim coll As New 
Collection
Dim coll As New 
Class1
Объект
использует
Dim и New
Dim [имя
переменной] 
As [тип объекта]
Set [имя
переменной] = New [тип объекта]
Dim coll As Collection
Set coll = New 
Collection
Dim coll As Class1
Set coll = New Class1
Статический
массив
Dim [имя
переменной]
([первый] 
To [последний] ) 
As[Тип]
Dim arr(1 To 6) 
As Long
Динамический
массив
Dim [имя
переменной]() 
As [Тип]
ReDim [имя
переменной]
([первый] 
To [последний])
Dim arr() As Long
ReDim arr(1 To 6)
Внешняя
библиотека
(Раннее
связывание) *
Dim [имя
переменной] 
As New [пункт]
Dim dict 
As New Dictionary
Внешняя
библиотека
(Раннее
связывание с
использованием
Set) *
Dim [имя
переменной] 
As [пункт]
Set [имя
переменной] = 
New [пункт]
Dim dict As Dictionary
Set dict = 
New Dictonary 
Внешняя
библиотека
(Позднее
связывание)
Dim [имя
переменной] 
As Object
Set [имя
переменной] = CreateObject
(«[библиотека]»)
Dim dict As Object
Set dict = CreateObject(«Scripting.
Dictionary»)

* Примечание. Для раннего связывания необходимо добавить
справочный файл с помощью меню «Инструменты» -> «Ссылки». Смотрите здесь,
как добавить ссылку на Dictonary.

Полезные ссылки 

  • Объявление параметров в подпрограмме или функции
  • Использование объектов в VBA
  • Массивы VBA
  • Коллекции VBA
  • Словарь VBA
  • VBA Workbook
  • VBA Worksheet

Что такое VBA Dim Statement?

Ключевое слово Dim — это сокращение от Dimension. Он
используется для объявления переменных в VBA.

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

Существует четыре типа Dim Statement. Все они очень похожи по синтаксису.

Вот они:

  1. Basic variable
  2. Variant
  3. Object
  4. Array

Ниже приводится краткое описание каждого типа

  1. Basic variable — этот тип переменной содержит одно значение. Это такие типы, как Long, String, Date, Double, Currency.
  2. Variant — VBA решает во время выполнения, какой тип будет использоваться. Вы должны избегать вариантов, где это возможно, но в некоторых случаях требуется их использование.
  3. Object — это переменная, которая может иметь несколько методов (то есть подпрограмм / функций) и несколько свойств (то есть значений). Есть 3 вида:
    Объекты Excel, такие как объекты Workbook, Worksheet и Range.
    Пользовательские объекты, созданные с использованием модулей классов.
    Внешние библиотеки, такие как Словарь.
  4. Array — это группа переменных или объектов.

В следующем разделе мы рассмотрим формат оператора VBA Dim с
некоторыми примерами каждого из них.

В последующих разделах мы рассмотрим каждый тип более
подробно.

Формат VBA Dim Statement

Формат выражения Dim показан ниже.

' 1. BASIC VARIABLE
' Объявление основной переменной
Dim [Имя переменной] As [тип]

' Объявление фиксированной строки
Dim [Имя переменной] As String * [размер]

' 2. VARIANT
Dim [Имя переменной] As Variant
Dim [Имя переменной]

' 3. OBJECT
' Объявление объекта
Dim [Имя переменной] As [тип]

' Объявление и создание объекта
Dim [Имя переменной] As New [тип]

' Объявление объекта с использованием позднего связывания
Dim [Имя переменной] As Object

' 4. ARRAY
' Объявление статического массива
Dim [Имя переменной](first To last) As [тип]

' Объявление динамического массива
Dim [Имя переменной]() As [тип]
Ниже приведены примеры использования различных форматов.
Sub Primeri()

    ' 1. BASIC VARIABLE
    ' Объявление основной переменной
    Dim name As String
    Dim count As Long
    Dim amount As Currency
    Dim eventdate As Date
    
    ' Объявление фиксированной строки
    Dim userid As String * 8
    
    ' 2. VARIANT
    Dim var As Variant
    Dim var
    
    ' 3. OBJECT
    ' Объявление объекта
    Dim sh As Worksheet
    Dim wk As Workbook
    Dim rg As Range
    
    ' Объявление и создание объекта
    Dim coll1 As New Collection
    Dim o1 As New Class1
    
    ' Объявление объекта - создайте объект ниже, используя Set
    Dim coll2 As Collection
    Dim o2 As Class1
    
    Set coll2 = New Collection
    Set o2 = New Class1
    
    ' 	Объявление и присвоение с использованием позднего связывания
    Dim dict As Object
    Set dict = CreateObject("Scripting.Dictionary")
    
    ' 4. ARRAY
    ' Объявление статического массива
    Dim arrScores(1 To 5) As Long
    Dim arrCountries(0 To 9) As String
    
    ' Объявление динамического массива - установите размер ниже, используя ReDim
    Dim arrMarks() As Long
    Dim arrNames() As String
    
    ReDim arrMarks(1 To 10) As Long
    ReDim arrNames(1 To 10) As String

End Sub

Мы рассмотрим эти различные типы операторов Dim в следующих
разделах.

Как использовать Dim с несколькими переменными

Мы можем объявить несколько переменных в одном выражении Dim.

Dim name As String, age As Long, count As Long

Если мы опускаем тип, то VBA автоматически устанавливает тип как Variant. Мы увидим больше
о Variant позже.

' Сумма является вариантом
Dim amount As Variant

' Сумма является вариантом
Dim amount

' Адрес это вариант - имя это строка
Dim name As String, address

' имя - это вариант, адрес – строка
Dim name, address As String

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

Dim wk As Workbook, marks As Count, name As String

Вы можете поместить столько переменных, сколько захотите, в
одном выражении Dim, но
для удобства чтения рекомендуется оставить его равным 3 или 4.

Где я должен поместить Dim Statement?

Оператор Dim может быть помещен в любое место кода. Тем не менее, он должен предшествовать любой строке, где используется переменная.

Если переменная используется перед оператором Dim, вы получите ошибку
«переменная не определена»

Dim statements

Когда дело доходит до позиционирования ваших Dim утверждений, вы можете сделать это двумя основными способами. Вы можете разместить все свои Dim заявления в верхней части процедуры.

Sub DimVverh()

    ' Размещение всех Dim statements наверху
    Dim count As Long, name As String, i As Long
    Dim wk As Workbook, sh As Worksheet, rg As Range
    
    Set wk = Workbooks.Open("C:ДокументыОтчет.xlsx")
    Set sh = wk.Worksheets(1)
    Set rg = sh.Range("A1:A10")
    
    For i = 1 To rg.Rows.count
        count = rg.Value
        Debug.Print count
    Next i
  
End Sub

ИЛИ вы можете объявить переменные непосредственно перед их
использованием:

Sub DimIsp()

    Dim wk As Workbook
    Set wk = Workbooks.Open("C:ДокументыОтчет.xlsx")
    
    Dim sh As Worksheet
    Set sh = wk.Worksheets(1)
    
    Dim rg As Range
    Set rg = sh.Range("A1:A10")
    
    Dim i As Long, count As Long, name As String
    For i = 1 To rg.Rows.count
        count = rg.Value
        name = rg.Offset(0, 1).Value
        Debug.Print name, count
    Next i
  
End Sub

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

Использование Dim в циклах

Помещение оператора Dim в цикл не влияет на переменную.

Когда VBA запускает Sub (или Function), первым делом он
создает все переменные, которые были объявлены в выражениях Dim.

Следующие 2 фрагмента кода практически одинаковы. Во-первых,
переменная Count объявляется перед циклом. Во втором он объявлен в цикле.

Sub CountPeredCiklom()

    Dim count As Long

    Dim i As Long
    For i = 1 To 3
        count = count + 1
    Next i
    
    ' значение счета будет 3
    Debug.Print count

End Sub
Sub CountPosleCikla()

    Dim i As Long
    For i = 1 To 3
        Dim count As Long
        count = count + 1
    Next i
    
    ' значение счета будет 3
    Debug.Print count

End Sub

Код будет вести себя точно так же, потому что VBA создаст переменные при
входе в подпрограмму.

Могу ли я использовать Dim для присвоения значения?

В таких языках, как C ++, C # и Java, мы можем объявлять и назначать переменные в одной строке:

' C++
int i = 6
String name = "Иван"

Мы не можем сделать это в VBA. Мы можем использовать оператор двоеточия для размещения
объявлений и назначения строк в одной строке.

Dim count As Long: count = 6

Мы не объявляем и не присваиваем в одной строке VBA. Что мы
делаем, это помещаем эти две строки (ниже) в одну строку в редакторе. Что
касается VBA, это две отдельные строки, как здесь:

Dim count As Long
count = 6

Здесь мы помещаем 3 строки кода в одну строку редактора,
используя двоеточие:

count = 1: count = 2: Set wk = ThisWorkbook

Нет никаких преимуществ или недостатков в назначении и
объявлении в одной строке редактора. Все сводится к личным предпочтениям.

Dim действительно требуется?

Ответ в том, что это не обязательно. VBA не требует от вас
использовать Dim Statement.

Однако не использовать оператор Dim — плохая практика и
может привести к множеству проблем.

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

Это может привести к таким проблемам, как

  1. Все переменные являются вариантами (проблемы с
    этим см. В разделе «Варианты»).
  2. Некоторые переменные ошибки останутся
    незамеченными.

Из-за этих проблем рекомендуется сделать использование Dim
обязательным в нашем коде. Мы делаем это с помощью оператора Option Explicit.

Option Explicit

 Мы можем сделать Dim
обязательным в модуле, набрав «Option Explicit» в верхней части модуля.

Мы можем сделать это автоматически в каждом новом модуле,
выбрав Tools-> Options из меню и отметив флажок «Требовать декларацию
переменной». Затем, когда вы вставите новый модуль, «Option Explicit» будет
автоматически добавлен в начало.

VBA Require Variable Declaration

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

Ошибки Переменной

В приведенном ниже коде мы используем переменную Total без использования оператора Dim.

Sub BezDim()

    Total = 6
    
    Total = Total + 1
    
    Debug.Print Total

End Sub

Если мы случайно написали Total неправильно, VBA сочтет это
новой переменной.

В приведенном ниже коде мы неправильно написали переменную Total как Totall.

Sub BezDimOshibki()

    Total = 6
    
    ' Первый Total - это ошибка
    Totall = Total + 1
    
    ' напечатает 6 вместо 7
    Debug.Print Total

End Sub

VBA не обнаружит ошибок в коде, и будет напечатано неверное
значение.

Давайте добавим Option Explicit и попробуйте приведенный
выше код снова

Option Explicit 

Sub BezDimOshibki()

    Total = 6
    
    ' Первый Total - это ошибка
    Totall = Total + 1
    
    ' Напечатает 6 вместо 7
    Debug.Print Total

End Sub

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

Когда мы добавим оператор Dim для Total
и запустим код, мы получим ошибку, сообщающую, что опечатка Totall не была определена.

variable not defined 2

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

Ошибка в ключевом слове

Вот второй пример, который более тонкий.

Когда следующий код выполняется, он должен изменить шрифт в
ячейке A1 на синий.

Однако, когда код запускается, ничего не происходит.

Sub ZadatCvet()

    Sheet1.Range("A1").Font.Color = rgblue

End Sub

Ошибка здесь в том, что rgblue должен быть rgbBlue. Если вы
добавите Option Explicit в модуль, появится ошибка «переменная не определена».
Это значительно облегчает решение проблемы.

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

Использование Dim с Basic Variables

VBA имеет те же основные типы переменных, которые
используются в электронной таблице Excel.

Вы можете увидеть список всех типов переменных VBA здесь.

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

Тип Хранение Диапазон Описание
Boolean 2 байта ИСТИНА или ЛОЖЬ Эта переменная
может быть
ИСТИНА или
ЛОЖЬ.
Long 4 байта от -2,147,483,648
до 2,147,483,647
Long — это
сокращение от
Long Integer.
Используйте это
вместо
типа Integer *
Currency 8 байт от -1,79769313486231E308
до -4,94065645841247E-324
для отрицательных
значений;
от 4.94065645841247E-324
до 1.79769313486232E308
для положительных
значений
Аналогично
Double,
но имеет
только 4
знака после
запятой
Double 8 байт от -922,337,203,685,477.5808
до 922,337,203,685,477.5807
Date 8 байт С 1 января 100
по 31 декабря 9999
String меняется От 0 до примерно
2 миллиардов
Содержит
текст

* Первоначально мы использовали бы тип Long вместо Integer,
потому что Integer был 16-разрядным, и поэтому диапазон был от -32 768 до 32
767, что довольно мало для многих случаев использования целых чисел.

Однако в 32-битной (или выше) системе целое число автоматически
преобразуется в длинное. Поскольку Windows была 32-битной начиная с Windows 95
NT, нет смысла использовать Integer.

В двух словах, всегда используйте Long для целочисленного
типа в VBA.

Фиксированный тип строки

В VBA есть один необычный тип базовой переменной, с которым
вы, возможно, не знакомы.

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

Sub TipStroki()

    Dim s As String
    
    ' s is "Иван Петров"
    s = "John Smith"
    
    ' s is "Игорь"
    s = "Tom"

End Sub

Фиксированная строка никогда не изменяется. Эта строка
всегда будет иметь одинаковый размер независимо от того, что вы ей назначаете

вот несколько примеров:

Sub FiksStroka()
    
    Dim s As String * 4
    
    ' s is "Иван"
    s = "Иван Перов"
    
    ' s = "Игорь "
    s = "Игорь"

End Sub

Использование Dim с Variants

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

Мы объявляем варианты следующим образом

' Оба варианта
Dim count
Dim count As Variant
Это звучит как отличная идея в теории. Больше не нужно беспокоиться о типе переменной
Sub IspVariants()
    
    Dim count As Variant
        
    count = 7
    
    count = "Иван"
    
    count = #12/1/2018#

End Sub

Однако использование вариантов является плохой практикой, и
вот почему:

  1. VBA
    не будет замечать неправильных ошибок типа (т. Е. Несоответствие данных).
  2. Вы не можете получить доступ к Intellisense.
  3. VBA
    угадывает лучший тип, и это может быть не то, что вы хотите.

Тип ошибки

Ошибки твои друзья!

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

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

Например. Представьте, что у нас есть лист оценок учеников.
Если кто-то случайно (или намеренно) заменит метку на текст, данные будут
недействительными.

Если мы используем вариант для хранения меток, то ошибки не
возникнет

Sub MarksVariant()
    
    Dim marks As Variant
    
    Dim i As Long
    For i = 1 To 10
        
        ' Прочитайте отметку
        mark = Sheet1.Range("A" & i).Value
        
    Next

End Sub

Это не хорошо, потому что в ваших данных есть ошибка, а вы
не знаете об этом.

Если вы зададите переменную Long, VBA сообщит вам об ошибке
«Несоответствие типов», если значения являются текстовыми.

Sub MarksLong()
    
    Dim mark As Long
    
    Dim i As Long
    For i = 1 To 10
        
        ' Прочитайте отметку
        mark = Sheet1.Range("A" & i).Value
        
    Next

End Sub

Доступ к Intellisense

Intellisense — удивительная особенность VBA. Он дает вам
доступные параметры в зависимости от типа, который вы создали.

Представьте, что вы объявляете переменную листа, используя
Dim

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

Вы можете увидеть Intellisense на скриншоте ниже

VBA Intellisense

Если вы используете Variant как тип, то Intellisense будет
недоступен

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

Использование Dim с Objects

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

Есть 3 типа объектов:

  1. Объекты Excel
  2. Объекты модуля класса
  3. Внешние объекты библиотеки

Примечание. Объект VBA Collection используется аналогично тому, как мы используем объект Class Module. Мы используем новое, чтобы создать его.

Давайте посмотрим на каждый из них по очереди.

Объекты Excel

Объекты Excel, такие как Рабочая книга, Рабочий лист,
Диапазон и т. Д., Не используют Новый, поскольку они автоматически создаются
Excel. Смотрите, «когда New не требуется».

При создании или открытии книги Excel автоматически создает
связанный объект.

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

Sub OtkrWorkbook()
    
    Dim wk As Workbook
    Set wk = Workbooks.Open("C:ДокументыОтчет.xlsx")

End Sub

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

Sub DobavSheet()
    
    Dim sh As Worksheet
    Set sh = ThisWorkbook.Worksheets.Add

End Sub

Нам не нужно использовать ключевое слово New для этих объектов Excel.

Мы просто присваиваем переменную функции, которая либо
создает новый объект, либо дает нам доступ к существующему.

Вот несколько примеров назначения переменных Workbook, Worksheet и range

Sub DimWorkbook()
    
    Dim wk As Workbook
    
    ' назначить wk новой книге
    Set wk = Workbooks.Add
    
    ' назначить wk первой открытой книге
    Set wk = Workbooks(1)
    
    ' назначить wk рабочей книге Отчет.xlsx
    Set wk = Workbooks("Отчет.xlsx")
    
    ' назначить wk активной книге
    Set wk = ActiveWorkbook
    
End Sub
Sub DimWorksheet()
    
    Dim sh As Worksheet
    
    ' Назначить sh на новый лист
    Set sh = ThisWorkbook.Worksheets.Add
    
    ' Назначьте sh на крайний левый лист
    Set sh = ThisWorkbook.Worksheets(1)
    
    ' Назначьте sh на лист под названием «Клиенты»
    Set sh = ThisWorkbook.Worksheets("Клиенты")
    
    ' Присвойте sh активному листу
    Set sh = ActiveSheet

End Sub
Sub DimRange()

    ' Получить рабочий лист клиента
    Dim sh As Worksheet
    Set sh = ThisWorkbook.Worksheets("Клиенты")
    
    ' Объявите переменную диапазона
    Dim rg As Range
    
    ' Присвойте rg диапазону A1
    Set rg = sh.Range("A1")
    
    ' Назначьте rg в диапазоне от B4 до F10
    Set rg = sh.Range("B4:F10")
    
    ' Присвойте rg диапазону E1
    Set rg = sh.Cells(1, 5)
    
End Sub

Если вы хотите узнать больше об этих объектах, вы можете ознакомиться со следующими статьями: Workbook VBA, Worksheet VBA и Cell и Range VBA.

Использование Dim с Class Module Objects

В VBA мы используем Class Modules для создания наших собственных пользовательских объектов. Вы можете прочитать все о Class Modules здесь.

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

Мы можем сделать это в операторе Dim или в операторе Set.

Следующий код создает объект, используя ключевое слово New в выражении Dim:

' Объявить и создать
Dim o As New class1
Dim coll As New Collection

Использование New в выражении Dim означает, что каждый раз
при запуске нашего кода будет создаваться ровно один объект.

Использование Set дает нам больше гибкости. Мы можем создать
много объектов из одной переменной. Мы также можем создать объект на основе
условия.

Этот следующий код показывает, как мы создаем объект Class Module, используя Set. (Чтобы создать модуль класса, перейдите в окно проекта, щелкните правой кнопкой мыши соответствующую книгу и выберите «Вставить модуль класса». Подробнее см. «Создание Simple Class Module».)

' Объявить только
Dim o As Class1

' Создать с помощью Set
Set o = New Class1

Давайте посмотрим на пример использования Set. В приведенном ниже коде мы хотим
прочитать диапазон данных. Мы создаем объект только в том случае, если значение
больше 50.

Мы используем Set для создания объекта Class1. Это потому, что количество нужных нам объектов зависит от
количества значений более 50.

Sub IspSet()
    
    ' Объявите переменную объекта Class1
    Dim o As Class1
    
    ' Читать диапазон
    Dim i As Long
    For i = 1 To 10
        If Sheet1.Range("A" & i).Value > 50 Then

            ' Создать объект, если условие выполнено
            Set o = New Class1
            
        End If
    Next i

End Sub

Я сохранил этот пример простым для ясности. В реальной версии этого кода мы бы заполнили объект Class Module данными и добавили его в структуру данных, такую как Collection или Dictionary.

Вот пример реальной версии, основанной на данных ниже:

dim sample data

' Class Module - clsStudent
Public Name As String
Public Subject As String

' Стандартный модуль
Sub ChitatBalli()

    ' Создать коллекцию для хранения объектов
    Dim coll As New Collection
    
    ' Current Region получает соседние данные
    Dim rg As Range
    Set rg = Sheet1.Range("A1").CurrentRegion
    
    Dim i As Long, oStudent As clsStudent
    For i = 2 To rg.Rows.Count
        
        ' Проверьте значение
        If rg.Cells(i, 1).Value > 50 Then
            ' Создать новый объект
            Set oStudent = New clsStudent
            
            ' Читать данные на объект студента
            oStudent.Name = rg.Cells(i, 2).Value
            oStudent.Subject = rg.Cells(i, 3).Value
            
            ' добавить объект в коллекцию
            coll.Add oStudent
            
        End If
        
    Next i
    
    ' Распечатайте данные в Immediate Window, чтобы проверить их
    Dim oData As clsStudent
    For Each oData In coll
        Debug.Print oData.Name & " studies " & oData.Subject
    Next oData

End Sub

Чтобы узнать больше о Set вы можете заглянуть сюда.

Объекты из внешней библиотеки

Действительно полезная часть VBA — это то, как у нас есть
доступ к внешним библиотекам. Это открывает целый новый мир тому, что мы можем
сделать.

Примерами являются библиотеки Access, Outlook и Word,
которые позволяют нам взаимодействовать с этими приложениями.

Мы можем использовать библиотеки для различных типов
структур данных, таких как Словарь, Массив, Стек и Очередь.

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

Мы можем создать эти объекты двумя способами:

  1. Раннее связывание
  2. Позднее связывание

Давайте посмотрим на это по очереди.

Раннее связывание

Раннее связывание означает, что мы добавляем справочный
файл. Как только этот файл добавлен, мы можем рассматривать объект как объект
модуля класса.

Мы добавляем ссылку, используя Tools-> Reference, а затем
проверяем соответствующий файл в списке.

Например, чтобы использовать словарь, мы ставим флажок
«Microsoft Scripting Runtime»

vba references dialog

Как только мы добавим ссылку, мы можем использовать словарь
как объект модуля класса

Sub RanSvyaz()

    ' Используйте только Dim
    Dim dict1 As New Dictionary
    
    ' Используйте Dim и Set
    Dim dict2 As Dictionary
    Set dict2 = New Dictionary

End Sub

Преимущество раннего связывания заключается в том, что у нас
есть доступ к Intellisense. Недостатком является то, что это может вызвать
конфликтные проблемы на других компьютерах.

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

Позднее связывание

Позднее связывание означает, что мы создаем объект во время
выполнения.

Мы объявляем переменную как тип «Объект». Затем мы
используем CreateObject для создания объекта.

Sub PozdSvyaz()

    Dim dict As Object
    Set dict = CreateObject("Scripting.Dictionary")
    
End Sub

Использование Dim с Arrays

В VBA есть два типа массивов:

  1. Статический — размер массива задается в
    операторе Dim и не может изменяться.
  2. Динамический — размер массива не указан в
    выражении Dim. Это устанавливается позже с помощью оператора ReDim
' Статический массив

' Магазины 7 длинных - от 0 до 6
Dim arrLong(0 To 6) As Long

' Магазины 7 длинных - от 0 до 6
Dim arrLong(6) As String

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

Мы объявляем динамический массив, используя инструкцию Dim,
и устанавливаем размер позже, используя ReDim.

' Динамический массив

' Объявите переменную
Dim arrLong() As Long

' Установить размер
ReDim arrLong(0 To 6) As Long

Использование ReDim

Большая разница между Dim и ReDim
заключается в том, что мы можем использовать переменную в выражении ReDim. В операторе Dim размер должен быть
постоянным значением.

Sub IspSet()

    ' Объявите переменную
    Dim arrLong() As Long
    
    ' Спросите пользователя о размере
    Dim size As Long
    size = InputBox("Пожалуйста, введите размер массива.", Default:=1)
    
    ' Установите размер на основе пользовательского ввода
    ReDim arrLong(0 To size) As Long

End Sub

На самом деле мы можем использовать оператор Redim без
предварительного использования оператора Dim.

В первом примере вы можете видеть, что мы используем Dim:

Sub IspDimReDim()

    ' Использование Dim
    Dim arr() As String

    ReDim arr(1 To 5) As String
    
    arr(1) = "Яблоко"
    arr(5) = "Апельсин"
    
End Sub

Во втором примере мы не используем Dim:

Sub IspTolkoReDim ()

    ' Использование только ReDim
    ReDim arr(1 To 5) As String
    
    arr(1) = "Яблоко"
    arr(5) = "Апельсин"
    
End Sub

Преимущество состоит в том, что вам не нужно тусклое
утверждение. Недостатком является то, что это может сбить с толку тех, кто
читает ваш код. В любом случае это не имеет большого значения.

Вы можете использовать ключевое слово Preserve с ReDim для сохранения существующих данных при изменении размера массива. Вы можете прочитать больше об этом здесь.

Вы можете найти все, что вам нужно знать о массивах в VBA здесь.

Устранение неполадок ошибок  Dim

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

Ошибка Тип Причина
Массив уже
рассчитан
Компиляция Использование
Redim для
статического
массива.
Ожидаемый:
идентификатор
Синтаксис Использование
зарезервированного слова в качестве
имени переменной.
Ожидаемый:
новый тип имени
Синтаксис Тип отсутствует в
выражении Dim.
Переменная объекта или переменная
блока не
установлена
Время выполнения New не был
использован для
создания объекта.
Переменная объекта или переменная
блока
не установлена
Время выполнения Set не использовался для назначения
переменной объекта.
Пользовательский
тип не определен
Компиляция Тип не распознан.
Это может
произойти, если
ссылочный файл не добавлен в меню
«Инструменты->
Ссылка» или имя
модуля класса
написано
неправильно.
Недопустимый
оператор вне блока
Type
Компиляция Имя переменной
отсутствует в
выражении Dim
Переменная
не определена
Компиляция Переменная
используется перед Dim-строкой.

Локальные и глобальные переменные

Когда мы используем Dim в процедуре (то есть подпрограмме или функции), она считается
локальной. Это означает, что это доступно только с этой процедурой.

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

В приведенном ниже коде мы объявили count как глобальную переменную:

' Глобальная
Dim count As Long
Sub UseCount1()
    count = 6
End Sub
Sub UseCount2()
    count = 4
End Sub

Что произойдет, если у нас будет глобальная переменная и
локальная переменная с одинаковым именем?

На самом деле это не вызывает ошибку. VBA дает приоритет локальной декларации.

' Глобальная
Dim count As Long

Sub UseCount()
    ' Локальная
    Dim count As Long
    
    ' Относится к локальному счету
    count = 6
    
End Sub

Подобная ситуация может привести только к проблемам, так как
трудно отследить, какой счет используется.

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

Важно знать и понимать глобальные переменные как вы,
поскольку вы можете встретить их в существующем коде.

Dim против Private

В VBA есть ключевое слово Private.

Если мы используем ключевое слово Private с переменной или
подфункцией / функцией, то этот элемент доступен только в текущем модуле.

Использование Dim и Private для переменной дает тот же
результат

' Доступно во всем этом модуле
Private priCount As Long
Dim dimCount As Long

Sub UseCount()

    ' Доступно только в этом разделе
    Private priName As String
    Dim dimName As String
    
End Sub

В VBA принято использовать Private для глобальных переменных
и Dim для локальных

' Доступно во всем этом модуле
Private priCount As Long

Sub UseCount()
    ' Только локальный
    Dim dimName As String
    
End Sub

Local OnlyThere
в VBA есть 2 других
типа объявлений, которые называются Public и Global.

Ниже приводится краткое изложение всех 4 типов:

  1. Dim
    — используется для объявления локальных переменных, т. Е. В процедурах.
  2. Private
    — используется для объявления глобальных переменных и процедур. Эти переменные
    доступны только для текущего модуля.
  3. Public
    — используется для объявления глобальных переменных и процедур. Эти переменные
    доступны во всех модулях.
  4. Global
    — старая и устаревшая версия Public.
    Может использоваться только в стандартных модулях. Он существует только для обратной
    совместимости.

Заключение

На этом мы заканчиваем статью о VBA Dim Statement. Если у вас есть
какие-либо вопросы или мысли, пожалуйста, дайте мне знать в комментариях ниже.

При выполнении макросов Excel могут возникнуть ошибки, которые в VBA делят на три категории:

  • Ошибки компиляции
  • Ошибки выполнения
  • Логические ошибки (баги)

Далее мы поговорим о каждом из трёх типов ошибок VBA подробно.

Содержание

  1. Ошибки компиляции
  2. Ошибки выполнения
  3. Перехват ошибок выполнения
  4. Логические ошибки

Ошибки компиляции

Компилятор VBA рассматривает ошибки компиляции как недопустимые и выделяет их в коде ещё до того, как дело дойдёт до запуска макроса.

Если при написании кода допущена синтаксическая ошибка, то редактор VBA сигнализирует об этом немедленно: либо при помощи окна с сообщением, либо выделяя ошибку красным цветом, в зависимости от статуса режима Auto Syntax Check.

Примечание: При включённом режиме Auto Syntax Check каждый раз, при появлении в редакторе Visual Basic во введённом коде синтаксической ошибки, будет показано соответствующее сообщение. Если же этот режим выключен, то редактор VBA продолжит сообщать о синтаксических ошибках, просто выделяя их красным цветом. Опцию Auto Syntax Check можно включить/выключить в меню Tools > Options редактора Visual Basic.

В некоторых случаях ошибка компиляции может быть обнаружена при выполнении компиляции кода, непосредственно перед тем, как макрос будет выполнен. Обычно ошибку компиляции несложно обнаружить и исправить, потому что компилятор VBA даёт информацию о характере и причине ошибки.

Ошибки в Excel VBA

Например, сообщение «Compile error: Variable not defined» при попытке запустить выполнение кода VBA говорит о том, что происходит попытка использовать или обратиться к переменной, которая не была объявлена для текущей области (такая ошибка может возникнуть только если используется Option Explicit).

Ошибки выполнения

Ошибки выполнения возникают в процессе выполнения кода и приводят к остановке выполнения программы. Этот тип ошибок VBA, как правило, также не сложно обнаружить и исправить, так как сообщается информация о характере ошибки и место в коде, где произошла остановка.

Примером такой ошибки может служить попытка выполнить деление на ноль. В результате будет показано сообщение «Run-time error ’11’: Division by zero«.

Ошибки в Excel VBA

В зависимости от структуры проекта VBA, может быть предложено выполнить отладку кода (как показано на рисунке ниже). В этом случае при нажатии на кнопку Debug (в окне сообщения о необходимости отладки) будет выделена цветом строка кода, которая стала причиной ошибки VBA.

Ошибки в Excel VBA

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

В случае если код сложнее, чем в нашем примере, то, чтобы получить больше информации о причине возникновения ошибки VBA, можно проверить значения используемых переменных. В редакторе VBA для этого достаточно навести указатель мыши на имя переменной, или можно открыть окно отслеживания локальных переменных (в меню редактора View > Locals Window).

Коды различных ошибок выполнения расшифрованы на сайте Microsoft Support (на английском). Наиболее часто встречающиеся ошибки VBA перечислены в этой таблице:

5 Недопустимый вызов процедуры (Invalid procedure call)
7 Недостаточно памяти (Out of memory)
9 Индекс вне заданного диапазона (Subscript out of range)

Эта ошибка возникает при попытке обратиться к элементу массива за пределами заданного размера массива – например, если объявлен массив с индексами от 1 до 10, а мы пытаемся обратиться к элементу этого же массива с индексом 11.

11 Деление на ноль (Division by zero)
13 Несоответствие типа (Type mismatch)

Эта ошибка возникает при попытке присвоить переменной значение не соответствующего типа – например, объявлена переменная i типа Integer, и происходит попытка присвоить ей значение строкового типа.

53 Файл не найден (File not found)

Иногда возникает при попытке открыть не существующий файл.

Перехват ошибок выполнения

Не все ошибки выполнения бывают вызваны недочётами в коде. Например, ошибки VBA не удастся избежать, если для работы макроса необходимо открыть файл с данными, а этого файла не существует. В таких случаях признаком профессионализма будет перехват ошибок и написание кода VBA, который будет выполняться при их возникновении. Таким образом, вместо неприятных сбоев будет происходить изящное завершение работы макроса.

Для того, чтобы помочь справиться с возникающими ошибками, VBA предоставляет разработчику операторы On Error и Resume. Эти операторы отслеживают ошибки и направляют выполнение макроса в специальный раздел кода VBA, в котором происходит обработка ошибки. После выполнения кода обработки ошибки, работа программы может быть продолжена с того места, где возникла ошибка, или макрос может быть остановлен полностью. Далее это показано на примере.

'Процедура Sub присваивает переменным Val1 и Val2 значения,
'хранящиеся в ячейках A1 и B1 рабочей книги Data.xlsx расположенной в каталоге C:Documents and Settings

Sub Set_Values(Val1 As Double, Val2 As Double)

   Dim DataWorkbook As Workbook

   On Error GoTo ErrorHandling

      'Открываем рабочую книгу с данными

      Set DataWorkbook = Workbooks.Open("C:Documents and SettingsData")

      'Присваиваем переменным Val1 и Val2 данные из рабочей книги DataWorkbook

      Val1 = Sheets("Лист1").Cells(1, 1)
      Val2 = Sheets("Лист1").Cells(1, 2)

      DataWorkbook.Close

   Exit Sub

ErrorHandling:

   'Если файл не найден, предлагаем пользователю разместить его в
   'нужном месте и продолжить работу

   MsgBox "Рабочая книга не найдена! " & _
      "Пожалуйста добавьте книгу Data.xlsx в каталог C:Documents and Settings и нажмите OK."

   Resume

End Sub

В этом коде производится попытка открыть файл Excel с именем Data. Если файл не найден, то пользователю будет предложено поместить этот файл в нужную папку. После того, как пользователь сделает это и нажмёт ОК, выполнение кода продолжится, и попытка открыть этот файл повторится. При желании вместо попытки открыть нужный файл, выполнение процедуры Sub может быть прервано в этом месте при помощи команды Exit Sub.

Логические ошибки

Логические ошибки (или баги) возникают в процессе выполнения кода VBA, но позволяют ему выполняться до самого завершения. Правда в результате могут выполняться не те действия, которые ожидалось, и может быть получен неверный результат. Такие ошибки обнаружить и исправить труднее всего, так как компилятор VBA их не распознаёт и не может указать на них так, как это происходит с ошибками компиляции и выполнения.

Например, при создании макроса в процедуре случайно были просуммированы не те переменные, которые требовалось просуммировать. Результат будет ошибочным, но макрос будет продолжать выполняться до завершения.

Редактор Excel VBA предоставляет набор инструментов отладки, которые помогут найти и исправить логические ошибки в коде VBA. В данной статье мы не будем рассматривать подробно эти инструменты. Любознательный пользователь может найти обзор инструментов отладки VBA на сайте Microsoft Help & Support (на английском).

Оцените качество статьи. Нам важно ваше мнение:

Работа с переменными

Автор Дмитрий Якушев На чтение25 мин. Просмотров271

Алан Перлис

Постоянная одного человека — переменная другого

Эта статья содержит полное руководство по работе с переменными и использованию VBA Dim.

Первый раздел содержит краткое руководство по использованию оператора Dim, включая примеры и формат оператора Dim.

Остальная часть поста содержит наиболее полное руководство, которое вы найдете в VBA Dim Statement.

Если вы заинтересованы в объявлении параметров, вы можете прочитать о них здесь.

Содержание

  1. Краткое руководство по использованию VBA Dim Statement
  2. Полезные ссылки 
  3. Что такое VBA Dim Statement?
  4. Формат VBA Dim Statement
  5. Как использовать Dim с несколькими переменными
  6. Где я должен поместить Dim Statement?
  7. Использование Dim в циклах
  8. Могу ли я использовать Dim для присвоения значения?
  9. Dim действительно требуется?
  10. Option Explicit
  11. Ошибки Переменной
  12. Ошибка в ключевом слове
  13. Использование Dim с Basic Variables
  14. Фиксированный тип строки
  15. Использование Dim с Variants
  16. Тип ошибки
  17. Доступ к Intellisense
  18. Использование Dim с Objects
  19. Объекты Excel
  20. Использование Dim с Class Module Objects
  21. Объекты из внешней библиотеки
  22. Раннее связывание
  23. Позднее связывание
  24. Использование Dim с Arrays
  25. Использование ReDim
  26. Устранение неполадок ошибок  Dim
  27. Локальные и глобальные переменные
  28. Dim против Private
  29. Заключение

Краткое руководство по использованию VBA Dim Statement

Описание

Формат

Пример

Базовая
переменная

Dim [имя
переменной] 
As [Тип]

Dim count As Long
Dim amount 
As Currency
Dim name As String
Dim visible 
As Boolean

Фиксированная
строка

Dim [имя
переменной] 
As String *[размер]

Dim s As String * 4
Dim t As String * 10

Вариант

Dim [имя
переменной] 
As Variant
Dim [имя
переменной]

Dim var As Variant
Dim var

Объект
использует
Dim и New

Dim [имя
переменной] 
As New [тип объекта]

Dim coll As New 
Collection
Dim coll As New 
Class1

Объект
использует
Dim и New

Dim [имя
переменной] 
As [тип объекта]
Set [имя
переменной] = 
New [тип объекта]

Dim coll As Collection
Set coll = New 
Collection
Dim coll As Class1
Set coll = New Class1

Статический
массив

Dim [имя
переменной]
([первый] 
To [последний] ) 
As[Тип]

Dim arr(1 To 6) 
As Long

Динамический
массив

Dim [имя
переменной]() 
As [Тип]
ReDim [имя
переменной]
([первый] 
To [последний])

Dim arr() As Long
ReDim arr(1 To 6)

Внешняя
библиотека
(Раннее
связывание) *

Dim [имя
переменной] 
As New [пункт]

Dim dict 
As New Dictionary

Внешняя
библиотека
(Раннее
связывание с
использованием
Set) *

Dim [имя
переменной] 
As [пункт]
Set [имя
переменной] = 
New [пункт]

Dim dict As Dictionary
Set dict = 
New Dictonary 

Внешняя
библиотека
(Позднее
связывание)

Dim [имя
переменной] 
As Object
Set [имя
переменной] = CreateObject
(«[библиотека]»)

Dim dict As Object
Set dict = CreateObject(«Scripting.
Dictionary»)

* Примечание. Для раннего связывания необходимо добавить справочный файл с помощью меню «Инструменты» -> «Ссылки». Смотрите здесь, как добавить ссылку на Dictonary.

Полезные ссылки 

  • Объявление параметров в подпрограмме или функции
  • Использование объектов в VBA
  • Массивы VBA
  • Коллекции VBA
  • Словарь VBA
  • VBA Workbook
  • VBA Worksheet

Что такое VBA Dim Statement?

Ключевое слово Dim — это сокращение от Dimension. Он используется для объявления переменных в VBA.

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

Существует четыре типа Dim Statement. Все они очень похожи по синтаксису.

Вот они:

  1. Basic variable
  2. Variant
  3. Object
  4. Array

Ниже приводится краткое описание каждого типа

  1. Basic variable — этот тип переменной содержит одно значение. Это такие типы, как Long, String, Date, Double, Currency.
  2. Variant — VBA решает во время выполнения, какой тип будет использоваться. Вы должны избегать вариантов, где это возможно, но в некоторых случаях требуется их использование.
  3. Object — это переменная, которая может иметь несколько методов (то есть подпрограмм / функций) и несколько свойств (то есть значений). Есть 3 вида:
    Объекты Excel, такие как объекты Workbook, Worksheet и Range.
    Пользовательские объекты, созданные с использованием модулей классов.
    Внешние библиотеки, такие как Словарь.
  4. Array — это группа переменных или объектов.

В следующем разделе мы рассмотрим формат оператора VBA Dim с некоторыми примерами каждого из них.

В последующих разделах мы рассмотрим каждый тип более подробно.

Формат VBA Dim Statement

Формат выражения Dim показан ниже.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

‘ 1. BASIC VARIABLE

‘ Объявление основной переменной

Dim [Имя переменной] As [тип]

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

Dim [Имя переменной] As String * [размер]

‘ 2. VARIANT

Dim [Имя переменной] As Variant

Dim [Имя переменной]

‘ 3. OBJECT

‘ Объявление объекта

Dim [Имя переменной] As [тип]

‘ Объявление и создание объекта

Dim [Имя переменной] As New [тип]

‘ Объявление объекта с использованием позднего связывания

Dim [Имя переменной] As Object

‘ 4. ARRAY

‘ Объявление статического массива

Dim [Имя переменной](first To last) As [тип]

‘ Объявление динамического массива

Dim [Имя переменной]() As [тип]

Ниже приведены примеры использования различных форматов.

Sub Primeri()

    ‘ 1. BASIC VARIABLE

    ‘ Объявление основной переменной

    Dim name As String

    Dim count As Long

    Dim amount As Currency

    Dim eventdate As Date

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

    Dim userid As String * 8

    ‘ 2. VARIANT

    Dim var As Variant

    Dim var

    ‘ 3. OBJECT

    ‘ Объявление объекта

    Dim sh As Worksheet

    Dim wk As Workbook

    Dim rg As Range

    ‘ Объявление и создание объекта

    Dim coll1 As New Collection

    Dim o1 As New Class1

    ‘ Объявление объекта — создайте объект ниже, используя Set

    Dim coll2 As Collection

    Dim o2 As Class1

    Set coll2 = New Collection

    Set o2 = New Class1

    ‘   Объявление и присвоение с использованием позднего связывания

    Dim dict As Object

    Set dict = CreateObject(«Scripting.Dictionary»)

    ‘ 4. ARRAY

    ‘ Объявление статического массива

    Dim arrScores(1 To 5) As Long

    Dim arrCountries(0 To 9) As String

    ‘ Объявление динамического массива — установите размер ниже, используя ReDim

    Dim arrMarks() As Long

    Dim arrNames() As String

    ReDim arrMarks(1 To 10) As Long

    ReDim arrNames(1 To 10) As String

End Sub

Мы рассмотрим эти различные типы операторов Dim в следующих разделах.

Как использовать Dim с несколькими переменными

Мы можем объявить несколько переменных в одном выражении Dim.

1

Dim name As String, age As Long, count As Long

Если мы опускаем тип, то VBA автоматически устанавливает тип как Variant. Мы увидим больше о Variant позже.

1

2

3

4

5

6

7

8

9

10

11

‘ Сумма является вариантом

Dim amount As Variant

‘ Сумма является вариантом

Dim amount

‘ Адрес это вариант — имя это строка

Dim name As String, address

‘ имя — это вариант, адрес – строка

Dim name, address As String

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

1

Dim wk As Workbook, marks As Count, name As String

Вы можете поместить столько переменных, сколько захотите, в одном выражении Dim, но для удобства чтения рекомендуется оставить его равным 3 или 4.

Где я должен поместить Dim Statement?

Оператор Dim может быть помещен в любое место кода. Тем не менее, он должен предшествовать любой строке, где используется переменная.

Если переменная используется перед оператором Dim, вы получите ошибку «переменная не определена»

Когда дело доходит до позиционирования ваших Dim утверждений, вы можете сделать это двумя основными способами. Вы можете разместить все свои Dim заявления в верхней части процедуры.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

Sub DimVverh()

    ‘ Размещение всех Dim statements наверху

    Dim count As Long, name As String, i As Long

    Dim wk As Workbook, sh As Worksheet, rg As Range

    Set wk = Workbooks.Open(«C:ДокументыОтчет.xlsx»)

    Set sh = wk.Worksheets(1)

    Set rg = sh.Range(«A1:A10»)

    For i = 1 To rg.Rows.count

        count = rg.Value

        Debug.Print count

    Next i

End Sub

ИЛИ вы можете объявить переменные непосредственно перед их использованием:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

Sub DimIsp()

    Dim wk As Workbook

    Set wk = Workbooks.Open(«C:ДокументыОтчет.xlsx»)

    Dim sh As Worksheet

    Set sh = wk.Worksheets(1)

    Dim rg As Range

    Set rg = sh.Range(«A1:A10»)

    Dim i As Long, count As Long, name As String

    For i = 1 To rg.Rows.count

        count = rg.Value

        name = rg.Offset(0, 1).Value

        Debug.Print name, count

    Next i

End Sub

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

Использование Dim в циклах

Помещение оператора Dim в цикл не влияет на переменную.

Когда VBA запускает Sub (или Function), первым делом он создает все переменные, которые были объявлены в выражениях Dim.

Следующие 2 фрагмента кода практически одинаковы. Во-первых, переменная Count объявляется перед циклом. Во втором он объявлен в цикле.

1

2

3

4

5

6

7

8

9

10

11

12

13

Sub CountPeredCiklom()

    Dim count As Long

    Dim i As Long

    For i = 1 To 3

        count = count + 1

    Next i

    ‘ значение счета будет 3

    Debug.Print count

End Sub

1

2

3

4

5

6

7

8

9

10

11

12

Sub CountPosleCikla()

    Dim i As Long

    For i = 1 To 3

        Dim count As Long

        count = count + 1

    Next i

    ‘ значение счета будет 3

    Debug.Print count

End Sub

Код будет вести себя точно так же, потому что VBA создаст переменные при входе в подпрограмму.

Могу ли я использовать Dim для присвоения значения?

В таких языках, как C ++, C # и Java, мы можем объявлять и назначать переменные в одной строке:

1

2

3

‘ C++

int i = 6

String name = «Иван»

Мы не можем сделать это в VBA. Мы можем использовать оператор двоеточия для размещения объявлений и назначения строк в одной строке.

1

Dim count As Long: count = 6

Мы не объявляем и не присваиваем в одной строке VBA. Что мы делаем, это помещаем эти две строки (ниже) в одну строку в редакторе. Что касается VBA, это две отдельные строки, как здесь:

1

2

Dim count As Long

count = 6

Здесь мы помещаем 3 строки кода в одну строку редактора, используя двоеточие:

1

count = 1: count = 2: Set wk = ThisWorkbook

Нет никаких преимуществ или недостатков в назначении и объявлении в одной строке редактора. Все сводится к личным предпочтениям.

Dim действительно требуется?

Ответ в том, что это не обязательно. VBA не требует от вас использовать Dim Statement.

Однако не использовать оператор Dim — плохая практика и может привести к множеству проблем.

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

Это может привести к таким проблемам, как

  1. Все переменные являются вариантами (проблемы с этим см. В разделе «Варианты»).
  2. Некоторые переменные ошибки останутся незамеченными.

Из-за этих проблем рекомендуется сделать использование Dim обязательным в нашем коде. Мы делаем это с помощью оператора Option Explicit.

Option Explicit

 Мы можем сделать Dim обязательным в модуле, набрав «Option Explicit» в верхней части модуля.

Мы можем сделать это автоматически в каждом новом модуле, выбрав Tools-> Options из меню и отметив флажок «Требовать декларацию переменной». Затем, когда вы вставите новый модуль, «Option Explicit» будет автоматически добавлен в начало.

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

Ошибки Переменной

В приведенном ниже коде мы используем переменную Total без использования оператора Dim.

1

2

3

4

5

6

7

8

9

Sub BezDim()

    Total = 6

    Total = Total + 1

    Debug.Print Total

End Sub

Если мы случайно написали Total неправильно, VBA сочтет это новой переменной.

В приведенном ниже коде мы неправильно написали переменную Total как Totall.

1

2

3

4

5

6

7

8

9

10

11

Sub BezDimOshibki()

    Total = 6

    ‘ Первый Total — это ошибка

    Totall = Total + 1

    ‘ напечатает 6 вместо 7

    Debug.Print Total

End Sub

VBA не обнаружит ошибок в коде, и будет напечатано неверное значение.

Давайте добавим Option Explicit и попробуйте приведенный выше код снова

1

2

3

4

5

6

7

8

9

10

11

12

13

Option Explicit

Sub BezDimOshibki()

    Total = 6

    ‘ Первый Total — это ошибка

    Totall = Total + 1

    ‘ Напечатает 6 вместо 7

    Debug.Print Total

End Sub

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

Когда мы добавим оператор Dim для Total и запустим код, мы получим ошибку, сообщающую, что опечатка Totall не была определена.

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

Ошибка в ключевом слове

Вот второй пример, который более тонкий.

Когда следующий код выполняется, он должен изменить шрифт в ячейке A1 на синий.

Однако, когда код запускается, ничего не происходит.

1

2

3

4

5

Sub ZadatCvet()

    Sheet1.Range(«A1»).Font.Color = rgblue

End Sub

Ошибка здесь в том, что rgblue должен быть rgbBlue. Если вы добавите Option Explicit в модуль, появится ошибка «переменная не определена». Это значительно облегчает решение проблемы.

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

Использование Dim с Basic Variables

VBA имеет те же основные типы переменных, которые используются в электронной таблице Excel.

Вы можете увидеть список всех типов переменных VBA здесь .

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

Тип

Хранение

Диапазон

Описание

Boolean

2 байта

ИСТИНА или ЛОЖЬ

Эта переменная
может быть
ИСТИНА или
ЛОЖЬ.

Long

4 байта

от -2,147,483,648
до 2,147,483,647

Long — это
сокращение от
Long Integer.
Используйте это
вместо
типа Integer *

Currency

8 байт

от -1,79769313486231E308
до -4,94065645841247E-324
для отрицательных
значений;
от 4.94065645841247E-324
до 1.79769313486232E308
для положительных
значений

Аналогично
Double,
но имеет
только 4
знака после
запятой

Double

8 байт

от -922,337,203,685,477.5808
до 922,337,203,685,477.5807

Date

8 байт

С 1 января 100
по 31 декабря 9999

String

меняется

От 0 до примерно
2 миллиардов

Содержит
текст

* Первоначально мы использовали бы тип Long вместо Integer, потому что Integer был 16-разрядным, и поэтому диапазон был от -32 768 до 32 767, что довольно мало для многих случаев использования целых чисел.

Однако в 32-битной (или выше) системе целое число автоматически преобразуется в длинное. Поскольку Windows была 32-битной начиная с Windows 95 NT, нет смысла использовать Integer.

В двух словах, всегда используйте Long для целочисленного типа в VBA.

Фиксированный тип строки

В VBA есть один необычный тип базовой переменной, с которым вы, возможно, не знакомы.

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

1

2

3

4

5

6

7

8

9

10

11

Sub TipStroki()

    Dim s As String

    ‘ s is «Иван Петров»

    s = «John Smith»

    ‘ s is «Игорь»

    s = «Tom»

End Sub

Фиксированная строка никогда не изменяется. Эта строка всегда будет иметь одинаковый размер независимо от того, что вы ей назначаете

вот несколько примеров:

1

2

3

4

5

6

7

8

9

10

11

Sub FiksStroka()

    Dim s As String * 4

    ‘ s is «Иван»

    s = «Иван Перов»

    ‘ s = «Игорь «

    s = «Игорь»

End Sub

Использование Dim с Variants

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

Мы объявляем варианты следующим образом

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

‘ Оба варианта

Dim count

Dim count As Variant

Это звучит как отличная идея в теории. Больше не нужно беспокоиться о типе переменной

Sub IspVariants()

    Dim count As Variant

    count = 7

    count = «Иван»

    count = #12/1/2018#

End Sub

Однако использование вариантов является плохой практикой, и вот почему:

  1. VBA не будет замечать неправильных ошибок типа (т. Е. Несоответствие данных).
  2. Вы не можете получить доступ к Intellisense.
  3. VBA угадывает лучший тип, и это может быть не то, что вы хотите.

Тип ошибки

Ошибки твои друзья!

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

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

Например. Представьте, что у нас есть лист оценок учеников. Если кто-то случайно (или намеренно) заменит метку на текст, данные будут недействительными.

Если мы используем вариант для хранения меток, то ошибки не возникнет

1

2

3

4

5

6

7

8

9

10

11

12

13

Sub MarksVariant()

    Dim marks As Variant

    Dim i As Long

    For i = 1 To 10

        ‘ Прочитайте отметку

        mark = Sheet1.Range(«A» &amp; i).Value

    Next

End Sub

Это не хорошо, потому что в ваших данных есть ошибка, а вы не знаете об этом.

Если вы зададите переменную Long, VBA сообщит вам об ошибке «Несоответствие типов», если значения являются текстовыми.

1

2

3

4

5

6

7

8

9

10

11

12

13

Sub MarksLong()

    Dim mark As Long

    Dim i As Long

    For i = 1 To 10

        ‘ Прочитайте отметку

        mark = Sheet1.Range(«A» &amp; i).Value

    Next

End Sub

Доступ к Intellisense

Intellisense — удивительная особенность VBA. Он дает вам доступные параметры в зависимости от типа, который вы создали.

Представьте, что вы объявляете переменную листа, используя Dim

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

Вы можете увидеть Intellisense на скриншоте ниже

Если вы используете Variant как тип, то Intellisense будет недоступен

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

Использование Dim с Objects

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

Есть 3 типа объектов:

  1. Объекты Excel
  2. Объекты модуля класса
  3. Внешние объекты библиотеки

Примечание. Объект VBA Collection используется аналогично тому, как мы используем объект Class Module. Мы используем новое, чтобы создать его.

Давайте посмотрим на каждый из них по очереди.

Объекты Excel

Объекты Excel, такие как Рабочая книга, Рабочий лист, Диапазон и т. Д., Не используют Новый, поскольку они автоматически создаются Excel. Смотрите, «когда New не требуется».

При создании или открытии книги Excel автоматически создает связанный объект.

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

1

2

3

4

5

6

Sub OtkrWorkbook()

    Dim wk As Workbook

    Set wk = Workbooks.Open(«C:ДокументыОтчет.xlsx»)

End Sub

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

1

2

3

4

5

6

Sub DobavSheet()

    Dim sh As Worksheet

    Set sh = ThisWorkbook.Worksheets.Add

End Sub

Нам не нужно использовать ключевое слово New для этих объектов Excel.

Мы просто присваиваем переменную функции, которая либо создает новый объект, либо дает нам доступ к существующему.

Вот несколько примеров назначения переменных Workbook, Worksheet и range

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

Sub DimWorkbook()

    Dim wk As Workbook

    ‘ назначить wk новой книге

    Set wk = Workbooks.Add

    ‘ назначить wk первой открытой книге

    Set wk = Workbooks(1)

    ‘ назначить wk рабочей книге Отчет.xlsx

    Set wk = Workbooks(«Отчет.xlsx»)

    ‘ назначить wk активной книге

    Set wk = ActiveWorkbook

End Sub

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

Sub DimWorksheet()

    Dim sh As Worksheet

    ‘ Назначить sh на новый лист

    Set sh = ThisWorkbook.Worksheets.Add

    ‘ Назначьте sh на крайний левый лист

    Set sh = ThisWorkbook.Worksheets(1)

    ‘ Назначьте sh на лист под названием «Клиенты»

    Set sh = ThisWorkbook.Worksheets(«Клиенты»)

    ‘ Присвойте sh активному листу

    Set sh = ActiveSheet

End Sub

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

Sub DimRange()

    ‘ Получить рабочий лист клиента

    Dim sh As Worksheet

    Set sh = ThisWorkbook.Worksheets(«Клиенты»)

    ‘ Объявите переменную диапазона

    Dim rg As Range

    ‘ Присвойте rg диапазону A1

    Set rg = sh.Range(«A1»)

    ‘ Назначьте rg в диапазоне от B4 до F10

    Set rg = sh.Range(«B4:F10»)

    ‘ Присвойте rg диапазону E1

    Set rg = sh.Cells(1, 5)

End Sub

Если вы хотите узнать больше об этих объектах, вы можете ознакомиться со следующими статьями: Workbook VBA , Worksheet VBA и Cell и Range VBA .

Использование Dim с Class Module Objects

В VBA мы используем Class Modules для создания наших собственных пользовательских объектов. Вы можете прочитать все о Class Modules здесь .

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

Мы можем сделать это в операторе Dim или в операторе Set.

Следующий код создает объект, используя ключевое слово New в выражении Dim:

1

2

3

‘ Объявить и создать

Dim o As New class1

Dim coll As New Collection

Использование New в выражении Dim означает, что каждый раз при запуске нашего кода будет создаваться ровно один объект.

Использование Set дает нам больше гибкости. Мы можем создать много объектов из одной переменной. Мы также можем создать объект на основе условия.

Этот следующий код показывает, как мы создаем объект Class Module, используя Set. (Чтобы создать модуль класса, перейдите в окно проекта, щелкните правой кнопкой мыши соответствующую книгу и выберите «Вставить модуль класса». Подробнее см. «Создание Simple Class Module ».)

1

2

3

4

5

‘ Объявить только

Dim o As Class1

‘ Создать с помощью Set

Set o = New Class1

Давайте посмотрим на пример использования Set. В приведенном ниже коде мы хотим прочитать диапазон данных. Мы создаем объект только в том случае, если значение больше 50.

Мы используем Set для создания объекта Class1. Это потому, что количество нужных нам объектов зависит от количества значений более 50.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

Sub IspSet()

    ‘ Объявите переменную объекта Class1

    Dim o As Class1

    ‘ Читать диапазон

    Dim i As Long

    For i = 1 To 10

        If Sheet1.Range(«A» &amp; i).Value > 50 Then

            ‘ Создать объект, если условие выполнено

            Set o = New Class1

        End If

    Next i

End Sub

Я сохранил этот пример простым для ясности. В реальной версии этого кода мы бы заполнили объект Class Module данными и добавили его в структуру данных, такую как Collection или Dictionary.

Вот пример реальной версии, основанной на данных ниже:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

‘ Class Module — clsStudent

Public Name As String

Public Subject As String

‘ Стандартный модуль

Sub ChitatBalli()

    ‘ Создать коллекцию для хранения объектов

    Dim coll As New Collection

    ‘ Current Region получает соседние данные

    Dim rg As Range

    Set rg = Sheet1.Range(«A1»).CurrentRegion

    Dim i As Long, oStudent As clsStudent

    For i = 2 To rg.Rows.Count

        ‘ Проверьте значение

        If rg.Cells(i, 1).Value > 50 Then

            ‘ Создать новый объект

            Set oStudent = New clsStudent

            ‘ Читать данные на объект студента

            oStudent.Name = rg.Cells(i, 2).Value

            oStudent.Subject = rg.Cells(i, 3).Value

            ‘ добавить объект в коллекцию

            coll.Add oStudent

        End If

    Next i

    ‘ Распечатайте данные в Immediate Window, чтобы проверить их

    Dim oData As clsStudent

    For Each oData In coll

        Debug.Print oData.Name &amp; » studies « &amp; oData.Subject

    Next oData

End Sub

Чтобы узнать больше о Set вы можете заглянуть сюда.

Объекты из внешней библиотеки

Действительно полезная часть VBA — это то, как у нас есть доступ к внешним библиотекам. Это открывает целый новый мир тому, что мы можем сделать.

Примерами являются библиотеки Access, Outlook и Word, которые позволяют нам взаимодействовать с этими приложениями.

Мы можем использовать библиотеки для различных типов структур данных, таких как Словарь, Массив, Стек и Очередь.

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

Мы можем создать эти объекты двумя способами:

  1. Раннее связывание
  2. Позднее связывание

Давайте посмотрим на это по очереди.

Раннее связывание

Раннее связывание означает, что мы добавляем справочный файл. Как только этот файл добавлен, мы можем рассматривать объект как объект модуля класса.

Мы добавляем ссылку, используя Tools-> Reference, а затем проверяем соответствующий файл в списке.

Например, чтобы использовать словарь, мы ставим флажок «Microsoft Scripting Runtime»

Как только мы добавим ссылку, мы можем использовать словарь как объект модуля класса

1

2

3

4

5

6

7

8

9

10

Sub RanSvyaz()

    ‘ Используйте только Dim

    Dim dict1 As New Dictionary

    ‘ Используйте Dim и Set

    Dim dict2 As Dictionary

    Set dict2 = New Dictionary

End Sub

Преимущество раннего связывания заключается в том, что у нас есть доступ к Intellisense. Недостатком является то, что это может вызвать конфликтные проблемы на других компьютерах.

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

Позднее связывание

Позднее связывание означает, что мы создаем объект во время выполнения.

Мы объявляем переменную как тип «Объект». Затем мы используем CreateObject для создания объекта.

1

2

3

4

5

6

Sub PozdSvyaz()

    Dim dict As Object

    Set dict = CreateObject(«Scripting.Dictionary»)

End Sub

Использование Dim с Arrays

В VBA есть два типа массивов:

  1. Статический — размер массива задается в операторе Dim и не может изменяться.
  2. Динамический — размер массива не указан в выражении Dim. Это устанавливается позже с помощью оператора ReDim

1

2

3

4

5

6

7

‘ Статический массив

‘ Магазины 7 длинных — от 0 до 6

Dim arrLong(0 To 6) As Long

‘ Магазины 7 длинных — от 0 до 6

Dim arrLong(6) As String

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

Мы объявляем динамический массив, используя инструкцию Dim, и устанавливаем размер позже, используя ReDim.

1

2

3

4

5

6

7

‘ Динамический массив

‘ Объявите переменную

Dim arrLong() As Long

‘ Установить размер

ReDim arrLong(0 To 6) As Long

Использование ReDim

Большая разница между Dim и ReDim заключается в том, что мы можем использовать переменную в выражении ReDim. В операторе Dim размер должен быть постоянным значением.

1

2

3

4

5

6

7

8

9

10

11

12

13

Sub IspSet()

    ‘ Объявите переменную

    Dim arrLong() As Long

    ‘ Спросите пользователя о размере

    Dim size As Long

    size = InputBox(«Пожалуйста, введите размер массива.», Default:=1)

    ‘ Установите размер на основе пользовательского ввода

    ReDim arrLong(0 To size) As Long

End Sub

На самом деле мы можем использовать оператор Redim без предварительного использования оператора Dim.

В первом примере вы можете видеть, что мы используем Dim:

1

2

3

4

5

6

7

8

9

10

11

Sub IspDimReDim()

    ‘ Использование Dim

    Dim arr() As String

    ReDim arr(1 To 5) As String

    arr(1) = «Яблоко»

    arr(5) = «Апельсин»

End Sub

Во втором примере мы не используем Dim:

1

2

3

4

5

6

7

8

9

Sub IspTolkoReDim ()

    ‘ Использование только ReDim

    ReDim arr(1 To 5) As String

    arr(1) = «Яблоко»

    arr(5) = «Апельсин»

End Sub

Преимущество состоит в том, что вам не нужно тусклое утверждение. Недостатком является то, что это может сбить с толку тех, кто читает ваш код. В любом случае это не имеет большого значения.

Вы можете использовать ключевое слово Preserve с ReDim для сохранения существующих данных при изменении размера массива. Вы можете прочитать больше об этом здесь .

Вы можете найти все, что вам нужно знать о массивах в VBA здесь .

Устранение неполадок ошибок  Dim

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

Ошибка

Тип

Причина

Массив уже
рассчитан

Компиляция

Использование
Redim для
статического
массива.

Ожидаемый:
идентификатор

Синтаксис

Использование
зарезервированного слова в качестве
имени переменной.

Ожидаемый:
новый тип имени

Синтаксис

Тип отсутствует в
выражении Dim.

Переменная объекта или переменная
блока не
установлена

Время выполнения

New не был
использован для
создания объекта.

Переменная объекта или переменная
блока
не установлена

Время выполнения

Set не использовался для назначения
переменной объекта.

Пользовательский
тип не определен

Компиляция

Тип не распознан.
Это может
произойти, если
ссылочный файл не добавлен в меню
«Инструменты->
Ссылка» или имя
модуля класса
написано
неправильно.

Недопустимый
оператор вне блока
Type

Компиляция

Имя переменной
отсутствует в
выражении Dim

Переменная
не определена

Компиляция

Переменная
используется перед Dim-строкой.

Локальные и глобальные переменные

Когда мы используем Dim в процедуре (то есть подпрограмме или функции), она считается локальной. Это означает, что это доступно только с этой процедурой.

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

В приведенном ниже коде мы объявили count как глобальную переменную:

1

2

3

4

5

6

7

8

‘ Глобальная

Dim count As Long

Sub UseCount1()

    count = 6

End Sub

Sub UseCount2()

    count = 4

End Sub

Что произойдет, если у нас будет глобальная переменная и локальная переменная с одинаковым именем?

На самом деле это не вызывает ошибку. VBA дает приоритет локальной декларации.

1

2

3

4

5

6

7

8

9

10

11

‘ Глобальная

Dim count As Long

Sub UseCount()

    ‘ Локальная

    Dim count As Long

    ‘ Относится к локальному счету

    count = 6

End Sub

Подобная ситуация может привести только к проблемам, так как трудно отследить, какой счет используется.

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

Важно знать и понимать глобальные переменные как вы, поскольку вы можете встретить их в существующем коде.

Dim против Private

В VBA есть ключевое слово Private.

Если мы используем ключевое слово Private с переменной или подфункцией / функцией, то этот элемент доступен только в текущем модуле.

Использование Dim и Private для переменной дает тот же результат

1

2

3

4

5

6

7

8

9

10

11

‘ Доступно во всем этом модуле

Private priCount As Long

Dim dimCount As Long

Sub UseCount()

    ‘ Доступно только в этом разделе

    Private priName As String

    Dim dimName As String

End Sub

В VBA принято использовать Private для глобальных переменных и Dim для локальных

1

2

3

4

5

6

7

8

‘ Доступно во всем этом модуле

Private priCount As Long

Sub UseCount()

    ‘ Только локальный

    Dim dimName As String

End Sub

Local OnlyThere в VBA есть 2 других типа объявлений, которые называются Public и Global.

Ниже приводится краткое изложение всех 4 типов:

  1. Dim — используется для объявления локальных переменных, т. Е. В процедурах.
  2. Private — используется для объявления глобальных переменных и процедур. Эти переменные доступны только для текущего модуля.
  3. Public — используется для объявления глобальных переменных и процедур. Эти переменные доступны во всех модулях.
  4. Global — старая и устаревшая версия Public. Может использоваться только в стандартных модулях. Он существует только для обратной совместимости.

Заключение

На этом мы заканчиваем статью о VBA Dim Statement. Если у вас есть какие-либо вопросы или мысли, пожалуйста, дайте мне знать в комментариях ниже.

Источник

5.4. Преимущества объявления переменных

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

Необъявленные переменные могут вызывать трудно диагностируемые ошибки. Например, рассмотрим такой код (листинг 5.2.):

txt_CompanyName = "Типография"
MsgBox (txt_CompanyName)


Листинг
5.2.
Пример работы с переменной

Как вы думаете, что получится при его исполнении? Очевидно, должно вывестись окно сообщения с текстом «Типография». Но это далеко не факт. По внешнему виду переменных можно предположить, что их имена написаны латинскими буквами. Предположим, что в строке, где мы присваиваем переменной значение «Типография», это так и есть. А во второй строке мы ошиблись — и вместо латинской написали русскую букву «С» (они и на клавиатуре занимают одну клавишу, а внешне различить их просто невозможно). Как результат – совершенно непонятная ошибка – все выглядит правильно, а работать не хочет.

Если бы редактор кода не давал нам пользоваться необъявленными переменными — подобного рода ошибки были бы пресечены на корню. Чтобы заставить редактор автоматически требовать объявление переменных, можно поступить одним из двух способов. Первый — вставить в раздел объявлений модуля (то есть — вне кода процедур и обработчиков событий) команду Option Explicit. Второй — включить запрещение работы с необъявленными переменными в настройках редактора. Для этого выполните команду главного меню Tools • Options (Инструменты • Опции) и в появившемся диалоговом окне на вкладке Editor (Редактор) включите параметр Require Variable Declaration (Требовать объявление переменных ).

5.5. Объявляем переменные: Dim и Static

05-02-Dim и Static.docm — пример к п. 5.5.

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

Рассмотрим пример. Объявление переменной с именем num_MyAge типа Byte выглядит так (листинг 5.3.):

Dim num_MyAge As Byte
num_MyAge = 23


Листинг
5.3.
Объявление переменной и работа с ней

Этот код можно перевести так: «Объявить переменную типа Byte с именем num_MyAge и сделать ее доступной в модуле, в котором она объявлена». Второй строкой мы присваиваем переменной число 23.

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

Обратите внимание на то, что если вы присваиваете значение строковой переменной — передаваемое ей значение должно быть заключено в кавычки. При присваивании значений даты соответствующим переменным, эти значения должны быть заключены в значки #. Например, так (листинг 5.4.):

Dim str_MyName as String
Dim date_MyBirthDate as Date
str_MyName = "Alexander"
date_MyBirthDate = #January 1, 2007#


Листинг
5.4.
Работа с переменными типа String и Date

Помимо ключевого слова Dim могут использоваться и другие слова. В частности, нам будет полезна команда Staticпеременная, объявленная с использованием этой команды, будет хранить свое значение между вызовами процедуры, область ее видимости аналогична переменной, объявленной с Dim. Такую переменную можно использовать для накопления каких-либо значений.

Рассмотрим пример. Создайте новый документ Microsoft Word, добавьте в него две кнопки. В обработчике события Click одной из них с именем cmd_Dim, на которой будет написано Dim, напишите такой код (листинг 5.5.)

Dim num_Counter As Integer
num_Counter = num_Counter + 1
MsgBox (num_Counter)


Листинг
5.5.
Обработчик события Click кнопки cmd_Dim

Здесь мы сначала объявляем переменную типа Integer, потом присваиваем этой переменной ее же значение, увеличенное на 1, а дальше — выводим переменную в окне сообщения.

Сколько бы вы не нажимали на эту кнопку — всякий раз в окне сообщения будет выводиться единица. Ведь каждый раз, когда запускается обработчик, все происходит как бы в первый раз — информация об изменениях переменной не сохраняется при выходе из обработчика.

Вторую кнопку назовите cmd_Static, подпишите ее как Static, и в обработчик нажатия добавьте следующее (листинг 5.6.):

Static num_Counter As Integer
num_Counter = num_Counter + 1
MsgBox (num_Counter)


Листинг
5.6.
Обработчик события Click кнопки cmd_Static

Единственное отличие этого текста от предыдущего — ключевое слово Static вместо Dim. Но благодаря такому объявлению, переменная хранит свое значение между запусками обработчика. Попробуйте несколько раз нажимать на кнопку Static — каждый раз вы будете видеть в окне сообщения число, увеличенное на 1.

5.6. Арифметические операторы и работа с числовыми переменными

05-03-Операторы, конкатенация.docm — пример к пп. 5.6.-5.7.

Операторы — это команды, которые используются в VBA для работы с данными. Если вы программировали когда-нибудь, например, на Basic’e или на каком-нибудь другом языке, вам уже знакомы основные операторы. Ну а если вы раньше не сталкивались с операторами в программировании, то уж со школьным курсом математики вы сталкивались точно. Большинство операторов VBA действуют точно так же, как знакомые всем арифметические операторы. В табл. 5.3. вы можете видеть описание арифметических операторов, применимых в VBA

Таблица
5.3.
Арифметические операторы VBA

Оператор Описание
+ Сложение. Например, в результате вычисления выражения 4+3 получится 7.
Вычитание.
* Умножение
/ Деление
^ Возведение в степень, 5^2 равняется 25
Целочисленное деление. От результата деления отбрасывается дробная часть. Например, 10 3 равняется 3.
mod Деление по модулю. Возвращает остаток от деления. Например, 10 mod 3 равняется 1

В VBA применяется тот же порядок обработки выражений, который принят в математике. Например, результат вычисления 2*3+7 равняется 13-ти. Так же, в математических выражениях могут использоваться круглые скобки. Однако, круглые скобки могут встретиться вам не только в математических выражениях. Скобки, как вы могли заметить из примеров, которые мы рассматривали выше, часто употребляются при вызове функций VBA, при работе с объектами и т.д.

Если снова вернуться к математике, нельзя не заметить, что редкая математическая запись обходится без знака =. Этот знак используется в VBA в нескольких ролях.

Во-первых, это оператор присваивания. Вы уже сталкивались с ним, когда присваивали какие-то значения свойствам элементов управления или переменным. Например, такая запись: num_a = 10 + 2 означает: «Присвоить переменной num_a результат сложения чисел 10 и 2 » или, проще, «а равно 10+2». Вторая роль оператора = заключается в том, что он используется в командах сравнения выражений — о них мы поговорим в следующей главе.

5.7. Конкатенация

Несколько ролей и у оператора +. Во-первых — это арифметический оператор сложения. А во-вторых — оператор конкатенации строк. Конкатенация — это нечто вроде «склеивания» строк. В качестве оператора конкатенации можно использовать и оператор &. Считается, что & использовать предпочтительнее так как он в любом случае обрабатывает операнды как строковые данные.

Давайте рассмотрим пример, который охватывает арифметические операции и конкатенацию строк.

Напишем программу, которая запрашивает имя пользователя и два числа, после чего выводит такой текст в окне сообщения (если имя введено как «Александр», первое число 2, второе – 21): «Здравствуйте, Александр. Вы ввели числа 2 и 21, их сумма равняется 23.»

Добавим кнопку в документ Microsoft Word, назовем ее cmd_Experiments, надпишем ее как Работа с операторами.

Теперь решим, какие переменные нам нужны.

Для имени пользователя это переменная типа String. Дадим ей имя str_UserName. Для чисел нам понадобится пара переменных одного из числовых типов.

Какие числа введет пользователь? Этого мы не знаем. Конечно, можно ограничить ввод проверками, но это дела будущих примеров. Предполагается, что пользователь может ввести практически любое число — целое или дробное, положительное или отрицательное. Поэтому воспользуемся типом Double. Назовем пару числовых переменных num_First и num_Second.

Создадим отдельную переменную того же типа Double для хранения суммы введенных значений – назовем ее num_Summ.

В условии нашей задачи присутствует требование вывести все введенные данные в строку, скомбинировав с определенными словами. Нам понадобится переменная типа String для хранения этой строки. Назовем ее str_Result.

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

Вы уже знакомы с функцией InputBox, которая выводит окно для ввода данных пользователем. Как вы могли убедиться, InputBox отлично справляется со вводом строковых значений. А как насчет чисел? Можем ли мы написать что-то вроде:

num_First = InputBox("Введите первое число")

Вполне можем.

Пожалуй, сейчас для вас самое сложное — это построить строку вывода, однако пользуйтесь следующими правилами и вы всегда будете правильно и быстро строить подобные строки.

Во-первых — помните, что все, что вы хотите вывести в виде неизменного текста, должно быть включено в кавычки, а имена переменных, наоборот, пишутся без кавычек. Во-вторых — используйте оператор & при «склеивании» отдельных частей строки или оператор + и функцию Str (о ней вы прочтете ниже), которая конвертирует числовые переменные в строки. Так вы будете гарантированы от неожиданностей и ошибок.

Например, пусть в переменной str_UserName хранится имя пользователя «Александр», а переменная str_Result должна содержать результат вывода. Напишем код, помещающий в str_Result строку «Привет, Александр»:

str_Result = "Привет, " & str_UserName

Видите? Ничего сложного, правда?

Обратите внимание на то, как реагирует система на использование необъявленных переменных при добавленной в модуль команде Option Explicit (рис. 5.3.).

Реакция системы на необъявленную переменную

Рис.
5.3.
Реакция системы на необъявленную переменную

Здесь вместо str_UserName мы ошибочно использовали str_UserNane. Но благодаря Option Explicit появление необъявленных переменных воспринимается как ошибка. При попытке запуска программы мы видим сообщение об ошибке: «Variable not defined» — «Переменная не определена».

Однако вернемся к нашей задаче. Мы определились с особенностями работы наиболее сложных ее частей, в итоге у нас получилось следующее (листинг 5.7.):

Dim str_UserName As String
    Dim str_Result As String
    Dim num_First As Double
    Dim num_Second As Double
    Dim num_Summ As Double
    str_UserName = InputBox("Введите ваше имя")
    num_First = InputBox("Введите первое число")
    num_Second = InputBox("Введите второе число")
    num_Summ = num_First + num_Second
        str_Result = "Здравствуйте, " & str_UserName _
    & ". Вы ввели числа " & num_First & " и " & num_Second _
    & ". Их сумма равняется " & num_Summ
    MsgBox (str_Result)


Листинг
5.7.
Обработчик события Click кнопки cmd_Experiments

Обратите внимание на то, что строку сборки строки вывода str_Result мы разбили на несколько частей оператором переноса строки.

0 / 0 / 0

Регистрация: 18.06.2016

Сообщений: 5

1

Ошибка компиляции: переменная, не определена

29.06.2016, 16:08. Показов 1388. Ответов 1


Вылезает ошибка при запуске программы: «Ошибка компиляции: переменная, не определена», как решить проблему?

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Private Sub LoadMetalsParam()
ReDim MetalsParam(0 To 5, 0 To 3)
 
MetalsParam(0, 1) = 0.000000055
MetalsParam(1, 1) = 0.0041
MetalsParam(2, 1) = 0.0000045
MetalsParam(3, 1) = 3650
MetalsParam(4, 1) = 2560000#
MetalsParam(5, 1) = 0.81
 
MetalsParam(0, 2) = 0.0000000178
MetalsParam(1, 2) = 0.0038
MetalsParam(2, 2) = 0.0000165
MetalsParam(3, 2) = 1083
MetalsParam(4, 2) = 3430000#
MetalsParam(5, 2) = 0.78
 
MetalsParam(0, 3) = 0.0000001
MetalsParam(1, 3) = 0.0004
MetalsParam(2, 3) = 0.0000122
MetalsParam(3, 3) = 1914
MetalsParam(4, 3) = 3630000#
MetalsParam(5, 3) = 0.68
 
    With cboMetalsList
     .AddItem "Выберите металл", 0
     .AddItem "Вольфрам", 1
     .AddItem "Медь", 2
     .AddItem "Железо", 3
     
     .TopIndex = metalindex
     .ListIndex = metalindex
    End With
End Sub

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

0

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

Variable not defined

vblr6.chm1011191

vblr6.chm1011191

office

4d8fdcc2-e4a9-7eb5-e0d4-f7a8e47b7431

06/08/2017

high

Variable not defined

You use the Option Explicit statement to protect your modules from having undeclared variables and to eliminate the possibility of inadvertently creating new variables when typographical errors occur. This error has the following cause and solution:

  • You used an Option Explicit statement to require the explicit declaration of variables, but you used a variable without declaring it. Explicitly declare the variable, or change the spelling of the variable to match that of the intended variable.

For additional information, select the item in question and press F1 (in Windows) or HELP (on the Macintosh).

[!includeSupport and feedback]

Хитрости »

1 Май 2011              51046 просмотров


Option Explicit — начинающие программировать в Visual Basic могут увидеть данную строку в чужом коде, либо случайно в своем. Хотя кто-то может быть уже знает, что это и зачем и использует данное объявление намеренно. Я же постараюсь максимально подробно описать смысл этой строки и её полезность для кода в первую очередь для тех, кто еще не знает для чего она.

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

Собственно что же делает эта строка? А делает она следующее: она принуждает Вас объявлять переменные(если не знаете смысл объявления переменных — читайте здесь). Если какая-либо переменная внутри выполняемой процедуры не объявлена — Вы увидите такое вот сообщение:

рис.1

так же редактор VBA выделит ту переменную, которая не объявлена. Первое время это может раздражать. Да и вообще: зачем это? Вы и без всех этих объявлений неплохо жили. А вот зачем

  • во-первых: объявление переменных считается хорошим тоном при программировании
  • во-вторых: правильное присвоение типов недурно экономит память
  • ну и в-третьих(я бы даже сказал в главных): это помогает избежать неявных ошибок кода при несовпадении типов данных

А теперь перейдем к сути и попробуем разобраться в чем же польза от использования Option Explicit. Ниже приведен простой код:

Sub Check_Variables()
    Dim a As String
    a = "Привет от www.excel-vba.ru"
    MsgBox а, vbInformation
End Sub

Выполните данный код без строки Option Explicit. Какое значение выдаст MsgBox? Ничего. Что за странность? Ведь явно видно, что переменной присвоено значение текста. Ничего больше не происходит. Но переменная все равно пуста. Мистика…А теперь запишите первой строкой в модуле Option Explicit:

Option Explicit
Sub Check_Variables()
    Dim a As String
    a = "Привет от www.excel-vba.ru"
    MsgBox а, vbInformation
End Sub

Запустите код. И что же видите? Видите сообщение, показанное на рис.1 и выделенную переменную «а», в последней строке. Что это означает? Это означает, что переменная «а» у нас не объявлена. А все потому, что первой строкой (Dim a As String) я объявил переменную на английском языке, а в последней строке я записал её на русском. А для кода это разные символы. Если разглядеть логику работы VBA — первую «а» он видит как переменную с присвоенным типом String. И ей мы задаем значение «Привет от www.excel-vba.ru». А вторую…Вторую он не находит в объявленных переменных, не находит в функциях и сам инициализирует её как новую переменную с типом данных Variant. И, что вполне логично, со значением Empty, т.е. ничего, т.к. этой переменной мы никаких значений не присваивали.

Еще один классический пример, когда Option Explicit спасет от лишних мозговых штурмов. Имеем простую функцию пользователя(UDF), которая берет указанную дату и возвращает её в заранее заданном формате в текстовом виде:

Function GetDateAsText(Optional ByVal Дата As Date)
    If Дата = 0 Then
        Дата = Date
    End If
    GetDataAsText = Format(Дата, "DD MMMM YYYY")
End Function

Хоть функция и короткая, но даже в ней не сразу порой бросается в глаза опечатка(представим, если функция в реальности строк на 200). В итоге чаще всего автор функции не понимает, почему при записи её на листе она возвращает не дату вида «21 мая 2016», а 0 и начинает пошагово выполнять функцию, искать ошибки в логике кода и т.д. Но если поставить в начало модуля Option Explicit, то при первом же выполнении этой функции VBA подсветит нам «GetDataAsText = «, указывая тем самым, что GetDataAsText в чем-то отличается от заданного имени функции — GetDateAsText. Банальная опечатка: GetDataAsText — GetDateAsText.


А теперь представьте себе, что Вы написали кучу длинного кода, строк на 100 или более. Конечно, Option Explicit Вы не используете. И вот Вы тестируете код, но он работает как-то не так…Где-то что-то неверно выполняется. И Вы начинаете пошагово ковыряться в листинге и искать ошибку…А ведь все может быть и проще: где-то в коде Вы могли банально опечататься и присвоить таким образом значение переменной, на которую Вы и не рассчитывали. А если использовать Option Explicit, то такая опечатка будет сразу обнаружена еще до выполнения кода и, что немаловажно — подсвечена. Так что Вам даже не придется её искать, а останется лишь исправить ошибку.

Так же эта строка поможет избежать неявных ошибок и в других ситуациях. В частности, при обращении к другим приложениями(Word, Outlook и т.д.). Например, в Excel применяются именованные константы для многих задач. Одна из распространенных — поиск последней ячейки в столбце: llast = Cells(Rows.Count, 1).End(xlUp).Row
здесь xlUp является именованной константой, значение которой равно числу: -4162. В других приложениях такой же подход. Это избавляет от необходимости помнить на память все значения констант и обращаться к ним при помощи intellisense. Но действуют эти константы исключительно внутри своего приложения(можете обратить внимание, у Excel константы начинаются с xl, а у Word — с wd). И т.к. объявлены эти константы в других приложениях — Excel про них не знает(как и другие приложения не знают про константы Excel). Для примера возьмем простой и рабочий код замены в Word:

    Dim wdDoc As Object
    Set wdDoc = objWordApp.ActiveDocument
    With wdDoc.Range.Find
        .Text = "привет"
        .Replacement.Text = "привет"
        .wrap = wdFindContinue
        .Execute Replace:=wdReplaceAll
    End With

Где wdFindContinue для Word-а равно 1, а wdReplaceAll = 2. Но это происходит только при выполнении изнутри самого Word-а(или при раннем связывании через ToolsReferences. Подробнее про это можно почитать в статье: Как из Excel обратиться к другому приложению).

Если же скопировать и выполнять данный код из Excel, то работать он будет не так как задумали. Дело в том, что Вы считаете, что Excel работает с обозначенными константами(wdFindContinue, wdReplaceAll) наравне с Word-ом. Но Excel на самом деле про них ничего не знает. И если директива Option Explicit будет отключена, то Excel просто назначает им значение по умолчанию — Empty. Которое преобразуется в 0. А это совсем иной поиск получается, т.к. должны быть значения 1 и 2. А если бы Option Explicit была включена, то Excel выделил бы их и указал, что они не объявлены. И тогда можно было бы сделать либо так:

    Dim wdDoc As Object
    Const wdFindContinue As Long = 1
    Const wdReplaceAll As Long = 2
    Set wdDoc = objWordApp.ActiveDocument
    With wdDoc.Range.Find
        .Text = "привет"
        .Replacement.Text = "привет"
        .wrap = wdFindContinue
        .Execute Replace:=wdReplaceAll
    End With

либо так(что удобнее, на мой взгляд):

    Dim wdDoc As Object
    Set wdDoc = objWordApp.ActiveDocument
    With wdDoc.Range.Find
        .Text = "привет"
        .Replacement.Text = "привет"
        .wrap = 1
        .Execute Replace:=2
    End With

Так что думаю, не стоит недооценивать значимость строки Option Explicit при написании кодов. В довершение хотелось бы Вас обрадовать, что вписывание данной строки в начало каждого модуля можно сделать автоматическим: поставить в опциях редактора галочку: ToolsOptions-вкладка EditorRequire Variable Declaration. Теперь во всех новых созданных модулях строка Option Explicit будет создаваться самим редактором VBA автоматически. К сожалению, в уже имеющихся модулях Вам придется проставить данную строку самим вручную. Но это того стоит, поверьте.

Так же см.:
Что такое переменная и как правильно её объявить?


Статья помогла? Поделись ссылкой с друзьями!

  Плейлист   Видеоуроки


Поиск по меткам

Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика

 

nicex

Пользователь

Сообщений: 167
Регистрация: 26.07.2015

#1

12.07.2019 15:15:57

Добрый день!, выдает ошибку Compile error: variable not defined

Код
 For i = 1 To Cells(Rows.Count, "D").End(xlUp).Row

       If Cells(i, 7) = "TNK" Or Cells(i, 7) = "RST" Or Cells(i, 7) = "TY" Then Cells(i, 10) = "SS"
 Next



 Dim i As Long
 Dim iLastRow As Long
 iLastRow = Cells(Rows.Count, "B").End(xlUp).Row

  For i = iLastRow To 1 Step -1
    If Cells(i, 7) = 1 And Cells(i, 8) < 2500 Then Rows(i).ClearContents
  Next

Я поменял местаим части кода

Код
 Dim i As Long
 Dim iLastRow As Long
 iLastRow = Cells(Rows.Count, "D").End(xlUp).Row

   For i = iLastRow To 1 Step -1
  
        If Cells(i, 7) = "TNK" Or Cells(i, 7) = "RST" Or Cells(i, 7) = "TY" Then Cells(i, 10) = "SS"
   Next



 iLastRow = Cells(Rows.Count, "B").End(xlUp).Row

  For i = iLastRow To 1 Step -1
    If Cells(i, 7) = 1 And Cells(i, 8) < 2500 Then Rows(i).ClearContents
  Next

Подскажите корректно макрос будет работать ?

 

Nordheim

Пользователь

Сообщений: 3154
Регистрация: 18.04.2017

У вас таблица заполнена не полностью? почему в двух циклах последняя заполненная строка ищется по разным столбцам?

Изменено: Nordheim12.07.2019 15:25:00

«Все гениальное просто, а все простое гениально!!!»

 

nicex

Пользователь

Сообщений: 167
Регистрация: 26.07.2015

Nordheim, это только часть макроса

 

Sanja

Пользователь

Сообщений: 14837
Регистрация: 10.01.2013

#4

12.07.2019 15:42:43

Цитата
nicex написал: Подскажите корректно макрос будет работать ?

А самому попробовать?  

Согласие есть продукт при полном непротивлении сторон.

 

Nordheim

Пользователь

Сообщений: 3154
Регистрация: 18.04.2017

#5

12.07.2019 15:49:14

Цитата
nicex написал:
это только часть макроса

Я вижу, это не ответ на вопрос, если нужна последняя строка диапазона, то  я не вижу смысла в двух циклах,
да и Select Case , как по мне, в данном случае предпочтительней.

«Все гениальное просто, а все простое гениально!!!»

 

nicex

Пользователь

Сообщений: 167
Регистрация: 26.07.2015

Sanja, я попробовал, работает, но проблема проверить результат, опасаюсь что в макросе что то не корректно обрабатывается, поэтому хочу понять не приведет ли такая замена на обум к ошибкам

Nordheim, мои возможности только методом тыка адаптировать готовый код

 

Nordheim

Пользователь

Сообщений: 3154
Регистрация: 18.04.2017

#7

12.07.2019 16:02:16

Цитата
nicex написал:
мои возможности только методом тыка адаптировать готовый код

Вы не знаете как ответить на вопрос

Цитата
Nordheim написал:
почему в двух циклах последняя заполненная строка ищется по разным столбцам?

или не хотите, меня не интересовало полный это макрос или часть, я это и так вижу.

Цитата
nicex написал:
мои возможности только методом тыка адаптировать готовый код

про ваши методы я так же не спрашивал. Вопрос тут в таком случае такой, а вы уверены что код вообще работает правильно, коли вы не знаете почему определение последней заполненной строки производится по разным столбцам?

«Все гениальное просто, а все простое гениально!!!»

 

nicex

Пользователь

Сообщений: 167
Регистрация: 26.07.2015

Nordheim, я объединил два разных макроса. перед второй частью макроса :

////// iLastRow = Cells(Rows.Count, «B»).End(xlUp).Row

 For i = iLastRow To 1 Step -1
   If Cells(i, 7) = 1 And Cells(i, 8) < 2500 Then Rows(i).ClearContents
 Next /////

происходит перестановка колонок и еще какие то замены и тп и тд

 

Sanja

Пользователь

Сообщений: 14837
Регистрация: 10.01.2013

Ошибка исчезла? Значит решение задачи, вынесенной в название Темы получено. Все остальное ЭТОЙ темы не касается.
Вы сначала разберитесь, что Вы хотите от этого макроса, а уже потом задавайте вопросы, конкретные, в других темах

Согласие есть продукт при полном непротивлении сторон.

 

Jack Famous

Пользователь

Сообщений: 10490
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

#10

12.07.2019 16:41:01

Цитата
nicex: Compile error: variable not defined

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

инструкцию

Прикрепленные файлы

  • 1.png (8.23 КБ)

Изменено: Jack Famous12.07.2019 16:41:33

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

 

nicex

Пользователь

Сообщений: 167
Регистрация: 26.07.2015

Jack Famous, спасибо

Sanja, как изменить тему на: Я поменял местаим части кода будет ли корректно макрос работать ?

 

vikttur

Пользователь

Сообщений: 47199
Регистрация: 15.09.2012

Такая ошибка может возникнуть в тысячах разных кодов.
Как назовем тему, пмощники?

 
название темы:

что значит сообщение Compile error: variable not defined при попытке выполнить макрос?

ответ:

в сообщении все сказано: Ошибка компилятора: неопределенная переменная!
эта  значит что в начале модуля есть инструкция Option Explicit которая требует обьявления ЛЮБОЙ переменной прежде, чем она будет использована в коде

решение:

1. удалите строку Option Explicit
или
2.напишите Option Explicit Off
или
3. обьявите перменную (Din переменная as…) раньше, чем обращаетесь к ней где-либо в коде
удачи!

Программисты — это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!

 

RAN

Пользователь

Сообщений: 7081
Регистрация: 21.12.2012

Вить, коды-то разные, причина одна.
И название ничем не хуже

этого

, или

этого

 

vikttur

Пользователь

Сообщений: 47199
Регистрация: 15.09.2012

Андрей, одна в Курилке, по второй более-менее понятно по названию.
А по этой… Вчитываться во все темы нет возможности, вижу обсуждение кода… поэтому и спрашиваю — как переименовать. Если не надо — оставим.

 

Dima S

Пользователь

Сообщений: 2063
Регистрация: 01.01.1970

#16

13.07.2019 01:53:01

Цитата
Ігор Гончаренко написал:
(Din переменная as…)

Dim

  • Remove From My Forums
  • Question

  • Hi,

    very old code with many-many colons….

    ' COMPILE:  Variable not defined......>vbCrLf<.................FALSE /Compile Error !!!
    ' COMPILE:  Variable not defined......>gkxPAC_NAME_SHRT<.......TRUE
    Option Compare Database
    Option Explicit
    '--------------------------------
    'Private Const gkxPAC_NAME_SHRT = ""
    'Private Const gkxPACAppMainVersion = ""
    'Private Function APP_QUIT(Optional cMsg$ = "")
    'On Error GoTo xPAC_CHYBA
    'Dim lc__proc_meno$, lc__proc_ErrUSR$, ln__proc_err&
    'lc__proc_meno$ = "APP_QUIT"
    'If Len(cMsg) > 0 Then MsgBox cMsg & vbCrLf & String(50, "-") & vbCrLf & gkxPAC_NAME_SHRT & " " & gkxPACAppMainVersion, vbExclamation + vbSystemModal, gkxPAC_NAME_SHRT & ", " & lc__proc_meno
    'LBL_EXIT:
    'Application.Quit
    'xPAC_KONIEC:
    'Exit Function
    'xPAC_CHYBA:
    'MsgBox "Err: " & Err.Number & "," & Err.Description & vbCrLf & String(50, "-") & vbCrLf & gkxPAC_NAME_SHRT & " " & gkxPACAppMainVersion, vbCritical + vbSystemModal, gkxPAC_NAME_SHRT & ", " & lc__proc_meno & ", E" & "rr" & "or !"
    'Resume LBL_EXIT
    'End Function
    '--------------------------------
    ' COMPILE:  Variable not defined......>vbCrLf<.................FALSE /Compile Error !!!
    ' COMPILE:  Variable not defined......>gkxPAC_NAME_SHRT<.......TRUE
    Private Function APP_QUIT(Optional cMsg$ = ""): On Error GoTo xPAC_CHYBA: Dim lc__proc_meno$, lc__proc_ErrUSR$, ln__proc_err&: lc__proc_meno$ = "APP_QUIT": If Len(cMsg) > 0 Then MsgBox cMsg & vbCrLf & String(50, "-") & vbCrLf & gkxPAC_NAME_SHRT & " " & gkxPACAppMainVersion, vbExclamation + vbSystemModal, gkxPAC_NAME_SHRT & ", " & lc__proc_meno
    LBL_EXIT: Application.Quit
    xPAC_KONIEC: Exit Function
    xPAC_CHYBA: MsgBox "Err: " & Err.Number & "," & Err.Description & vbCrLf & String(50, "-") & vbCrLf & gkxPAC_NAME_SHRT & " " & gkxPACAppMainVersion, vbCritical + vbSystemModal, gkxPAC_NAME_SHRT & ", " & lc__proc_meno & ", E" & "rr" & "or !": Resume LBL_EXIT
    End Function

    dBase,FoxPro,MS Access 2003,(2010=Not rec.),Office 2010+ACC.2013 ,Symbian C++, AC.2013.SystemResource.GetCurrentFreeSize=?

Answers

  • Hi PACALA_BA,

    >> the main  point is NOT „Variable not defined“

    Did you mean that you could make your code work, and you are wondering why the Selected undefined variable is wrong if you did not define the gkxPAC_NAME_SHRT?

    I have made a test with your code, and I could reproduce your issue. If I test with the code below, the error message with the selected is correct.

    Option Compare Database
    Option Explicit
    '--------------------------------
    'Private Const gkxPAC_NAME_SHRT = ""
    'Private Const gkxPACAppMainVersion = ""
    'Private Function APP_QUIT(Optional cMsg$ = "")
    'On Error GoTo xPAC_CHYBA
    'Dim lc__proc_meno$, lc__proc_ErrUSR$, ln__proc_err&
    'lc__proc_meno$ = "APP_QUIT"
    'If Len(cMsg) > 0 Then MsgBox cMsg & vbCrLf & String(50, "-") & vbCrLf & gkxPAC_NAME_SHRT & " " & gkxPACAppMainVersion, vbExclamation + vbSystemModal, gkxPAC_NAME_SHRT & ", " & lc__proc_meno
    'LBL_EXIT:
    'Application.Quit
    'xPAC_KONIEC:
    'Exit Function
    'xPAC_CHYBA:
    'MsgBox "Err: " & Err.Number & "," & Err.Description & vbCrLf & String(50, "-") & vbCrLf & gkxPAC_NAME_SHRT & " " & gkxPACAppMainVersion, vbCritical + vbSystemModal, gkxPAC_NAME_SHRT & ", " & lc__proc_meno & ", E" & "rr" & "or !"
    'Resume LBL_EXIT
    'End Function
    '--------------------------------
    ' COMPILE:  Variable not defined......>vbCrLf<.................FALSE /Compile Error !!!
    ' COMPILE:  Variable not defined......>gkxPAC_NAME_SHRT<.......TRUE
    'Private Function APP_QUIT(Optional cMsg$ = ""): On Error GoTo xPAC_CHYBA: Dim lc__proc_meno$, lc__proc_ErrUSR$, ln__proc_err&: lc__proc_meno$ = "APP_QUIT": If Len(cMsg) > 0 Then MsgBox cMsg & vbCrLf & String(50, "-") & vbCrLf & gkxPAC_NAME_SHRT & " " & gkxPACAppMainVersion, vbExclamation + vbSystemModal, gkxPAC_NAME_SHRT & ", " & lc__proc_meno
    'LBL_EXIT: Application.Quit
    'xPAC_KONIEC: Exit Function
    'xPAC_CHYBA: MsgBox "Err: " & Err.Number & "," & Err.Description & vbCrLf & String(50, "-") & vbCrLf & gkxPAC_NAME_SHRT & " " & gkxPACAppMainVersion, vbCritical + vbSystemModal, gkxPAC_NAME_SHRT & ", " & lc__proc_meno & ", E" & "rr" & "or !": Resume LBL_EXIT
    'End Function
    Private Function test()
        MsgBox "Hello" & vbCrLf & undefinedVariable
    End Function

    To be honesty, I do not know why this happened, I used the Editor for developer, but I did not know the details achievement of it.

    I suggest you define all the variable you will use in the code, write the correct code.

    Best Regards,

    Edward


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.

    Click
    HERE to participate the survey.

    • Marked as answer by

      Tuesday, August 25, 2015 1:10 PM

При выполнении макросов Excel могут возникнуть ошибки, которые в VBA делят на три категории:

  • Ошибки компиляции
  • Ошибки выполнения
  • Логические ошибки (баги)

Далее мы поговорим о каждом из трёх типов ошибок VBA подробно.

Содержание

  1. Ошибки компиляции
  2. Ошибки выполнения
  3. Перехват ошибок выполнения
  4. Логические ошибки

Ошибки компиляции

Компилятор VBA рассматривает ошибки компиляции как недопустимые и выделяет их в коде ещё до того, как дело дойдёт до запуска макроса.

Если при написании кода допущена синтаксическая ошибка, то редактор VBA сигнализирует об этом немедленно: либо при помощи окна с сообщением, либо выделяя ошибку красным цветом, в зависимости от статуса режима Auto Syntax Check.

Примечание: При включённом режиме Auto Syntax Check каждый раз, при появлении в редакторе Visual Basic во введённом коде синтаксической ошибки, будет показано соответствующее сообщение. Если же этот режим выключен, то редактор VBA продолжит сообщать о синтаксических ошибках, просто выделяя их красным цветом. Опцию Auto Syntax Check можно включить/выключить в меню Tools > Options редактора Visual Basic.

В некоторых случаях ошибка компиляции может быть обнаружена при выполнении компиляции кода, непосредственно перед тем, как макрос будет выполнен. Обычно ошибку компиляции несложно обнаружить и исправить, потому что компилятор VBA даёт информацию о характере и причине ошибки.

Ошибки в Excel VBA

Например, сообщение «Compile error: Variable not defined» при попытке запустить выполнение кода VBA говорит о том, что происходит попытка использовать или обратиться к переменной, которая не была объявлена для текущей области (такая ошибка может возникнуть только если используется Option Explicit).

Ошибки выполнения

Ошибки выполнения возникают в процессе выполнения кода и приводят к остановке выполнения программы. Этот тип ошибок VBA, как правило, также не сложно обнаружить и исправить, так как сообщается информация о характере ошибки и место в коде, где произошла остановка.

Примером такой ошибки может служить попытка выполнить деление на ноль. В результате будет показано сообщение «Run-time error ’11’: Division by zero«.

Ошибки в Excel VBA

В зависимости от структуры проекта VBA, может быть предложено выполнить отладку кода (как показано на рисунке ниже). В этом случае при нажатии на кнопку Debug (в окне сообщения о необходимости отладки) будет выделена цветом строка кода, которая стала причиной ошибки VBA.

Ошибки в Excel VBA

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

В случае если код сложнее, чем в нашем примере, то, чтобы получить больше информации о причине возникновения ошибки VBA, можно проверить значения используемых переменных. В редакторе VBA для этого достаточно навести указатель мыши на имя переменной, или можно открыть окно отслеживания локальных переменных (в меню редактора View > Locals Window).

Коды различных ошибок выполнения расшифрованы на сайте Microsoft Support (на английском). Наиболее часто встречающиеся ошибки VBA перечислены в этой таблице:

5 Недопустимый вызов процедуры (Invalid procedure call)
7 Недостаточно памяти (Out of memory)
9 Индекс вне заданного диапазона (Subscript out of range)

Эта ошибка возникает при попытке обратиться к элементу массива за пределами заданного размера массива – например, если объявлен массив с индексами от 1 до 10, а мы пытаемся обратиться к элементу этого же массива с индексом 11.

11 Деление на ноль (Division by zero)
13 Несоответствие типа (Type mismatch)

Эта ошибка возникает при попытке присвоить переменной значение не соответствующего типа – например, объявлена переменная i типа Integer, и происходит попытка присвоить ей значение строкового типа.

53 Файл не найден (File not found)

Иногда возникает при попытке открыть не существующий файл.

Перехват ошибок выполнения

Не все ошибки выполнения бывают вызваны недочётами в коде. Например, ошибки VBA не удастся избежать, если для работы макроса необходимо открыть файл с данными, а этого файла не существует. В таких случаях признаком профессионализма будет перехват ошибок и написание кода VBA, который будет выполняться при их возникновении. Таким образом, вместо неприятных сбоев будет происходить изящное завершение работы макроса.

Для того, чтобы помочь справиться с возникающими ошибками, VBA предоставляет разработчику операторы On Error и Resume. Эти операторы отслеживают ошибки и направляют выполнение макроса в специальный раздел кода VBA, в котором происходит обработка ошибки. После выполнения кода обработки ошибки, работа программы может быть продолжена с того места, где возникла ошибка, или макрос может быть остановлен полностью. Далее это показано на примере.

'Процедура Sub присваивает переменным Val1 и Val2 значения,
'хранящиеся в ячейках A1 и B1 рабочей книги Data.xlsx расположенной в каталоге C:Documents and Settings

Sub Set_Values(Val1 As Double, Val2 As Double)

   Dim DataWorkbook As Workbook

   On Error GoTo ErrorHandling

      'Открываем рабочую книгу с данными

      Set DataWorkbook = Workbooks.Open("C:Documents and SettingsData")

      'Присваиваем переменным Val1 и Val2 данные из рабочей книги DataWorkbook

      Val1 = Sheets("Лист1").Cells(1, 1)
      Val2 = Sheets("Лист1").Cells(1, 2)

      DataWorkbook.Close

   Exit Sub

ErrorHandling:

   'Если файл не найден, предлагаем пользователю разместить его в
   'нужном месте и продолжить работу

   MsgBox "Рабочая книга не найдена! " & _
      "Пожалуйста добавьте книгу Data.xlsx в каталог C:Documents and Settings и нажмите OK."

   Resume

End Sub

В этом коде производится попытка открыть файл Excel с именем Data. Если файл не найден, то пользователю будет предложено поместить этот файл в нужную папку. После того, как пользователь сделает это и нажмёт ОК, выполнение кода продолжится, и попытка открыть этот файл повторится. При желании вместо попытки открыть нужный файл, выполнение процедуры Sub может быть прервано в этом месте при помощи команды Exit Sub.

Логические ошибки

Логические ошибки (или баги) возникают в процессе выполнения кода VBA, но позволяют ему выполняться до самого завершения. Правда в результате могут выполняться не те действия, которые ожидалось, и может быть получен неверный результат. Такие ошибки обнаружить и исправить труднее всего, так как компилятор VBA их не распознаёт и не может указать на них так, как это происходит с ошибками компиляции и выполнения.

Например, при создании макроса в процедуре случайно были просуммированы не те переменные, которые требовалось просуммировать. Результат будет ошибочным, но макрос будет продолжать выполняться до завершения.

Редактор Excel VBA предоставляет набор инструментов отладки, которые помогут найти и исправить логические ошибки в коде VBA. В данной статье мы не будем рассматривать подробно эти инструменты. Любознательный пользователь может найти обзор инструментов отладки VBA на сайте Microsoft Help & Support (на английском).

Оцените качество статьи. Нам важно ваше мнение:

0 / 0 / 1

Регистрация: 23.10.2012

Сообщений: 135

1

04.01.2013, 00:34. Показов 17035. Ответов 3


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

Миниатюры

Ошибка типизации данных (Variable not defined)
 

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

0

Dragokas

Эксперт WindowsАвтор FAQ

17955 / 7592 / 889

Регистрация: 25.12.2011

Сообщений: 11,323

Записей в блоге: 17

04.01.2013, 00:47

2

Уберите в самом верху кода обязательную декларацию переменных:

Visual Basic
1
option explicit

или задавайте типизацию с помощью команды Dim
без указания типа возле каждой переменной.

0

Казанский

15131 / 6405 / 1730

Регистрация: 24.09.2011

Сообщений: 9,999

04.01.2013, 01:18

3

Лучший ответ Сообщение было отмечено как решение

Решение

При чем тут типизация? Просто переменная не объявлена. Обявите ее сразу после заголовка процедуры

Visual Basic
1
Dim i%

, а в процедуре можете называть ее просто i без указания типа.
Option Explicit не рекомендую убирать, эта опция позволяет обнаруживать необъявленные переменные (в результате опечаток) и тем самым экономит время и нервы

6

dev.Free

Заблокирован

04.01.2013, 16:55

4

Казанский, И в правду тебе нет цены !

0

  • #2

Welcome to the Forum!

Does you new workbook have sheets with codenames Sheet7 and Sheet9?

  • #3

MAybe this

Rich (BB code):

Option Explicit
Dim rx, cx, cxDeliverable, cxLoc, rxCode, rz, czDeliverable, czLoc, czCode, czSubtotal As Integer
Dim shx, shz As Worksheet

Sub Matrix2DB()

Set shx = Sheets("Sheet7")
Set shz = Sheets("Sheet9")

cxDeliverable = 1
cxLoc = 2
rxCode = 7
rz = 1
czDeliverable = 1
czLoc = 2
czCode = 3
czSubtotal = 4

For rx = 9 To 613
For cx = 3 To 54
If shx.Cells(rx, cx) > 0 Then
shz.Cells(rz, czDeliverable) = shx.Cells(rx, cxDeliverable)
shz.Cells(rz, czLoc) = shx.Cells(rx, cxLoc)
shz.Cells(rz, czCode) = shx.Cells(rxCode, cx)
shz.Cells(rz, czSubtotal) = shx.Cells(rx, cx)
rz = rz + 1
End If
Next cx
Next rx

End Sub
  • #4

sweet jesus it looks like that worked. thankyou stephencrump and Michael m.

I renamed the relevant sheets to «sheet 7» and «sheet 9» as suggested, saved, re-opened and re-ran the macro and she seems to be up and running.

May I ask if anyone knows why it initially suggested my «sub» needed to be declared as a variable ???

  • #5

Because you have Option Explicit (good coding practice!) execution won’t proceed with an undefined variable.

So execution stops at the first line Sub Matrix2DB() which will show yellow.

However, the first offending undefined variable should also be highlighted?

  • #6

@jalberthenet, you might also want to review how you declare your variables.

As you have it currently written

rx, cx, cxDeliverable, cxLoc, rxCode, rz, czDeliverable, czLoc, czCode and shx are all declared as Variant in VBA, which I don’t think is what you intended.

In VBA if you omit the As Type clause in a variable declaration then it is declared as Variant, Variant is the default type.

  • #7

Ah MARK858 has beaten me to the punch, but just to add,

The way you’re declaring your variables only the last one is being declared as the type you define as an integer or worksheet. To see this run this simple code which shows the variable type (
click here for a list of variable types and their associated number) from this:

Code:

MsgBox VarType(rx)
MsgBox TypeName(czSubtotal)

rx is actually a variant variable — the most expensive type of variable. You need «As Integer» after each of the other nine variables in that row (assuming you want them all to be integers).

Regards,

Robert

  • Ошибка переменная документа не указана word
  • Ошибка переменная документа не указана docvariable
  • Ошибка перекрытие отчетов сводных таблиц не допускается что делать
  • Ошибка перекомпиляции яндекс контест
  • Ошибка перекодирования невозможно сопоставить размер кадра