Хитрости »
1 Май 2011 51922 просмотров
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-а(или при раннем связывании через Tools –References. Подробнее про это можно почитать в статье: Как из 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 при написании кодов. В довершение хотелось бы Вас обрадовать, что вписывание данной строки в начало каждого модуля можно сделать автоматическим: поставить в опциях редактора галочку: Tools–Options-вкладка Editor–Require Variable Declaration. Теперь во всех новых созданных модулях строка Option Explicit будет создаваться самим редактором VBA автоматически. К сожалению, в уже имеющихся модулях Вам придется проставить данную строку самим вручную. Но это того стоит, поверьте.
Так же см.:
Что такое переменная и как правильно её объявить?
Статья помогла? Поделись ссылкой с друзьями!
Видеоуроки
Поиск по меткам
Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика
I am a long time avid Excel user but am just starting to learn VBA. I am using the following code but am getting an error when I try to run Sub test
:
Compile Error:Variable not defined
Can you help me figure out what is wrong?
Option Explicit
Function toFarenheit(degrees)
toFarenheit = (9 / 5) * degrees + 32
End Function
Function toCentigrade(degrees)
toCentigrade = (5 / 9) * degrees - 32
End Function
Sub test()
answer = toCentigrade(55)
MsgBox answer
End Sub
RubberDuck
11.8k4 gold badges50 silver badges95 bronze badges
asked Dec 29, 2014 at 19:43
You have Option Explicit
turn on which means you must declare your variables before using them.
In Sub test
, you are missing a declaration for answer
. Adding this should fix it:
Sub test()
Dim answer As Variant
answer = toCentigrade(55)
MsgBox answer
End Sub
Edit
Since you are new to VBA, you might want to consider typing both your variables and function returns. You don’t have to do this (and everything will be treated as a Variant
), but it is good practice.
If you type everything properly, your example would become:
Option Explicit
' Accept a double value and return a double type value.
Function toFarenheit(degrees As Double) As Double
toFarenheit = (9 / 5) * degrees + 32
End Function
Function toCentigrade(degrees As Double) As Double
toCentigrade = (5 / 9) * degrees - 32
End Function
Sub test()
' Variable type matches what the function will return.
Dim answer As Double
answer = toCentigrade(55)
MsgBox answer
End Sub
answered Dec 29, 2014 at 19:52
Jason FaulknerJason Faulkner
6,3382 gold badges27 silver badges33 bronze badges
3
I tested this to convert to farenheit
The function is as follows
Function ToFarenheit(Degrees As Double)
ToFarenheit = (9 / 5) * Degrees + 32
End Function
The sub is as follows
Sub TestFunction()
MsgBox ToFarenheit(0)
End Sub
answered Dec 29, 2014 at 19:52
1
nicex Пользователь Сообщений: 167 |
#1 12.07.2019 15:15:57 Добрый день!, выдает ошибку Compile error: variable not defined
Я поменял местаим части кода
Подскажите корректно макрос будет работать ? |
||||
Nordheim Пользователь Сообщений: 3154 |
У вас таблица заполнена не полностью? почему в двух циклах последняя заполненная строка ищется по разным столбцам? Изменено: Nordheim – 12.07.2019 15:25:00 “Все гениальное просто, а все простое гениально!!!” |
nicex Пользователь Сообщений: 167 |
Nordheim, это только часть макроса |
Sanja Пользователь Сообщений: 14849 |
#4 12.07.2019 15:42:43
А самому попробовать? Согласие есть продукт при полном непротивлении сторон. |
||
Nordheim Пользователь Сообщений: 3154 |
#5 12.07.2019 15:49:14
Я вижу, это не ответ на вопрос, если нужна последняя строка диапазона, то я не вижу смысла в двух циклах, “Все гениальное просто, а все простое гениально!!!” |
||
nicex Пользователь Сообщений: 167 |
Sanja, я попробовал, работает, но проблема проверить результат, опасаюсь что в макросе что то не корректно обрабатывается, поэтому хочу понять не приведет ли такая замена на обум к ошибкам Nordheim, мои возможности только методом тыка адаптировать готовый код |
Nordheim Пользователь Сообщений: 3154 |
#7 12.07.2019 16:02:16
Вы не знаете как ответить на вопрос
или не хотите, меня не интересовало полный это макрос или часть, я это и так вижу.
про ваши методы я так же не спрашивал. Вопрос тут в таком случае такой, а вы уверены что код вообще работает правильно, коли вы не знаете почему определение последней заполненной строки производится по разным столбцам? “Все гениальное просто, а все простое гениально!!!” |
||||||
nicex Пользователь Сообщений: 167 |
Nordheim, я объединил два разных макроса. перед второй частью макроса : ////// iLastRow = Cells(Rows.Count, “B”).End(xlUp).Row For i = iLastRow To 1 Step -1 происходит перестановка колонок и еще какие то замены и тп и тд |
Sanja Пользователь Сообщений: 14849 |
Ошибка исчезла? Значит решение задачи, вынесенной в название Темы получено. Все остальное ЭТОЙ темы не касается. Согласие есть продукт при полном непротивлении сторон. |
Jack Famous Пользователь Сообщений: 11000 OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome |
#10 12.07.2019 16:41:01
объявите переменную. Для того, чтобы в будущем этого избежать, прочтите инструкцию Прикрепленные файлы
Изменено: Jack Famous – 12.07.2019 16:41:33 Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄ |
||
nicex Пользователь Сообщений: 167 |
Jack Famous, спасибо Sanja, как изменить тему на: Я поменял местаим части кода будет ли корректно макрос работать ? |
vikttur Пользователь Сообщений: 47199 |
Такая ошибка может возникнуть в тысячах разных кодов. |
название темы:
что значит сообщение Compile error: variable not defined при попытке выполнить макрос? ответ: в сообщении все сказано: Ошибка компилятора: неопределенная переменная! решение: 1. удалите строку Option Explicit Программисты – это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете! |
|
RAN Пользователь Сообщений: 7132 |
Вить, коды-то разные, причина одна. этого , или этого |
vikttur Пользователь Сообщений: 47199 |
Андрей, одна в Курилке, по второй более-менее понятно по названию. |
Dima S Пользователь Сообщений: 2063 |
#16 13.07.2019 01:53:01
Dim |
||
Permalink
Cannot retrieve contributors at this time
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 |
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]
- 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
-
Marked as answer by