Доброго времени суток! Прошу описать применение функцию «Set» на доступном языке Особенно интересует когда обязательно объявлять: Спасибо заранее! P.S. буду рад любому Вашему ответу, даже короткому |
|
Для переменных текстового, числового и логического типов SET не применяется. Для ОБЪЕКТОВ необходимо использовать оператор SET |
|
KuklP Пользователь Сообщений: 14868 E-mail и реквизиты в профиле. |
Всегда желательно в конце процедуры: Я сам — дурнее всякого примера! … |
И вообще, вас что, на Гугле забанили? По VBA есть куча справочников — в каждом описано различие между SET и LET Цитата: В VBA существует два основных типа инструкций присваивания Let и Инструкция Set присваивает ссылку на объект переменной или свойству |
|
Alex_ST Пользователь Сообщений: 2746 На лицо ужасный, добрый внутри |
ИМХО, если переменная определена в процедуре (локальная), то время её жизни ограничено процедурой и по окончании процедуры (Exit Sub) все локальные переменные «умирают» и освобождают память. Поэтому Set «Переменная» = Nothing для локальных переменных делать не обязательно (конечно, если сама процедура не жутко жадная в смысле пожирания памяти) С уважением, Алексей (ИМХО: Excel-2003 — THE BEST!!!) |
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
{quote}{login=Alex_ST}{date=10.06.2010 11:29}{thema=}{post}Поэтому Set «Переменная» = Nothing для локальных переменных делать не обязательно (конечно, если сама процедура не жутко жадная в смысле пожирания памяти){/post}{/quote}Позвольте не согласиться. VBA редактор не такой уж продвинутый, как может показаться и он своими силами высвобождает память не всегда корректно. Он по идее должен все выгрузить, но такое происходит далеко не всегда. Лично я предпочитаю в большинстве случаев именно принудительно высвобождать память от подобных переменных, что и Вам советую. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
KuklP Пользователь Сообщений: 14868 E-mail и реквизиты в профиле. |
{quote}{login=Alex_ST}{date=10.06.2010 11:29}{thema=}{post}ИМХО, если переменная определена в процедуре (локальная), то время её жизни ограничено процедурой и по окончании процедуры (Exit Sub) все локальные переменные «умирают» и освобождают память. Поэтому Set «Переменная» = Nothing для локальных переменных делать не обязательно (конечно, если сама процедура не жутко жадная в смысле пожирания памяти){/post}{/quote} Я сам — дурнее всякого примера! … |
KuklP Пользователь Сообщений: 14868 E-mail и реквизиты в профиле. |
Ну вот, за Димой разве успеешь…. Могу только дополнить — не только в ВБА. ВБ5, ВБ6 тоже грешили этим. И сами разработчики рекомендовали делать ТАК явно. Я сам — дурнее всякого примера! … |
Alex_ST Пользователь Сообщений: 2746 На лицо ужасный, добрый внутри |
По поводу «правил хорошего тона» при программировании абсолютно с вами согласен. Это как ржавчина на кузове автомобиля: на скорость не влияет, но и самому смотреть противно, и похвастаться перед другими как-то стыдно… С уважением, Алексей (ИМХО: Excel-2003 — THE BEST!!!) |
EducatedFool, спасибо Вам за ответы, но зачем иронизировать или Вы не заметили «…на доступном языке»?! Спасибо Вам, Алексей, Дмитрий и Сергей! P.S. теперь все понятно и просто. |
|
KuklP Пользователь Сообщений: 14868 E-mail и реквизиты в профиле. |
Алекс, я покраснел прочитав: «к сожалению иногда грешат примерами без комментариев.» Правда, неудобно. Но я так и читаю чужой код. Не глядя на комменты. Самоучка — и так привык. С Вами абсолютно согласен(только вчера azam-у объяснял полезность комментов), но себя, боюсь, уже не исправлю:-( Я на этом форуме мнооооогому пытаюсь научиться. В первой строке списка доброта Юрий М, его умение общаться, не обижая других. Мне бы так. Ладно, что-то я совсем расчувствовался(это из мультика, не подумайте). Я сам — дурнее всякого примера! … |
слэн Пользователь Сообщений: 5192 |
зря вы на goto ополчились иногда без него никак.. коммменты, да, ленюсь писать, каюсь |
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
Я тоже не понимаю, чем GoTo не угодил. Да, плохо смотрится, когда таких переходов куча и они используются нецелесообразно. Но иногда ведь действительно нужен этот переход и если без него, то наоборот, код смотрится более неграмотно и загроможденно, потому что приходится выдумать обходные пути. И не помню, чтобы кто-то рекомендовал его не использовать. Вывод: не брезгуйте этим оператором — он бывает весьма полезен и не вреден в умеренных количествах. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
Мне лично комменты писать откровенно лень. Прописывать комменты бывает намного дольше, чем сами коды. Для себя я пишу с комментами, а в форум — лень…. P.S. Исправляться не собираюсь. Пока, во всяком случае. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
KuklP Пользователь Сообщений: 14868 E-mail и реквизиты в профиле. |
{quote}{login=слэн}{date=10.06.2010 12:52}{thema=}{post}зря вы на goto ополчились иногда без него никак.. http://khpi-iip.mipk.kharkiv.edu/library/extent/dijkstra/pp/ewd215.html почитайте(прям сейчас нашел, не умею, как Дима, доходчиво объяснять) Я сам — дурнее всякого примера! … |
Hugo Пользователь Сообщений: 23250 |
Но что-то есть в этом GoTo… В AutoIt с 3-й версии его вообще убрали, тоже мучался, так я и не понял, как сподручнее обходить, местами вообще придуманный алгоритм менять приходилось… |
KuklP Пользователь Сообщений: 14868 E-mail и реквизиты в профиле. |
{quote}{login=Hugo}{date=10.06.2010 02:04}{thema=}{post}Но что-то есть в этом GoTo… В AutoIt с 3-й версии его вообще убрали, тоже мучался, так я и не понял, как сподручнее обходить, местами вообще придуманный алгоритм менять приходилось…{/post}{/quote} Я сам — дурнее всякого примера! … |
слэн Пользователь Сообщений: 5192 |
вот пример когда никак: on error goto вот пример, когда как, но не красиво и yt’aatrnbdyj^ for i=1 to n можно, конечно, функцией оформить, с использованием exit function, но на вызов функции тратится время |
{quote}{login=слэн}{date=10.06.2010 02:12}{thema=}{post} http://forum.ixbt.com/topic.cgi?id=23:31044 |
|
KuklP Пользователь Сообщений: 14868 E-mail и реквизиты в профиле. |
Слэн(хочу Вас все же называть с большой буквы), плохой пример. Во всех примерах мэтров программирования goto используется только для определения ошибки, с последующим Exit Sub. То есть goto на выход. И я в жизни не встречал ситуаций, когда нельзя было избежать его. Поначалу(это еще в 2000 где-то), напрягало, помню. Зато сейчас даже в мыслях не бывает. Вот так мозги перестроились. Прсто блок стоит. Я сам — дурнее всякого примера! … |
KuklP Пользователь Сообщений: 14868 E-mail и реквизиты в профиле. |
{quote}{login=Казанский}{date=10.06.2010 02:17}{thema=Re: }{post}{quote}{login=слэн}{date=10.06.2010 02:12}{thema=}{post} http://forum.ixbt.com/topic.cgi?id=23:31044 {/post}{/quote} Я сам — дурнее всякого примера! … |
слэн Пользователь Сообщений: 5192 |
вообщето алгоритм можно записать так: Sub t() что короче, яснее и быстрее но я уже приводил на форуме множество раз алгоритмы, с использованием on error goto ( и в паре с ним ще и просто goto) — да, можно сделать по-другому, но так быстрее.. зачем же делать хуже, но без goto ? |
слэн Пользователь Сообщений: 5192 |
можно еще так: Sub t() |
KuklP Пользователь Сообщений: 14868 E-mail и реквизиты в профиле. |
Слэн, Вы читаете, что я пишу? Я сам — дурнее всякого примера! … |
KuklP Пользователь Сообщений: 14868 E-mail и реквизиты в профиле. |
В слове anser буква W пропущена, но это уже флуд. Если честно — боюсь, Диме позавчера спать не давали, оффтопили по полной. Чувствую, психанет и начнет стирать все без разбора. А главное по делу! Хотя этот топик флудом не считаю. Мы, как программеры, обсуждаем целесообразность применения оператора goto. Я сам — дурнее всякого примера! … |
Эммм…мммм…а хорошая тема получилось Спасибо и за «GoTo» |
|
Alex_ST Пользователь Сообщений: 2746 На лицо ужасный, добрый внутри |
Ну, я бы не был так категоричен, утверждая, что обсуждение целесообразности применения оператора goto в топике с названием «Описание применения «Set»» не является оффтопом… С уважением, Алексей (ИМХО: Excel-2003 — THE BEST!!!) |
Alex_ST Пользователь Сообщений: 2746 На лицо ужасный, добрый внутри |
Да… А топик-стартер-то, оказывается, ещё не спит, а тему-то просматривает… С уважением, Алексей (ИМХО: Excel-2003 — THE BEST!!!) |
слэн Пользователь Сообщений: 5192 |
<но я уже приводил на форуме множество раз алгоритмы, с использованием on error goto ( и в паре с ним еще и просто goto)> вот пример из моего решателя балды: (уж поверьте — оптимизировал-оптимизировал ) Sub fnd(ByVal s$) pos = InStr(1, s, «?») |
KuklP Пользователь Сообщений: 14868 E-mail и реквизиты в профиле. |
#30 10.06.2010 15:37:39 To Alex_ST: Ну вот. пришел поручик Ржевский и все опошлил:-) Я сам — дурнее всякого примера! … |
I always read that it is recommended to set objects to nothing, once I am done with them. But I normally use them only in functions inside forms.
Isn’t the reference lost and memory released when the function scope is left, regardless of setting objects to Nothing?
i.e. is it really necessary to do:
Set db = Nothing
Set record_set = Nothing
user692942
16.2k7 gold badges78 silver badges173 bronze badges
asked Feb 5, 2009 at 17:47
VB uses a so-called «reference counting» garbage collector.
Basically, the moment a variable goes out of scope, the reference counter on the referenced object is decremented. When you assign the object reference to another variable, the reference counter is incremented.
When the counter reaches zero, the object is ready for garbage collection. The object resources will be released as soon as this happens. A function local variable will most likely reference an object whose reference count never goes higher than 1, so object resources will be released when the function ends.
Setting a variable to Nothing
is the way to decrease the the reference counter explicitly.
For example, you read in a file, and set the file object variable to Nothing
right after the ReadAll()
call. The file handle will be released immediately, you can take your time process its contents.
If you don’t set to Nothing
, the file handle might be open longer than absolutely necessary.
If you are not in a «must unblock valuable resource» kind of situation, simply letting the variables go out of scope is okay.
answered Feb 5, 2009 at 18:22
TomalakTomalak
330k66 gold badges523 silver badges623 bronze badges
12
Garbage collection is rarely perfect. Even in .NET there are times where you are strongly encouraged to prompt the system to do garbage collection early.
For this reason, I explicitly both close and set to Nothing recordsets when I’m done with them.
answered Feb 5, 2009 at 18:16
BIBDBIBD
15k25 gold badges85 silver badges137 bronze badges
5
The very last line of the help topic for «Recordset.Close» in the Microsoft DAO help and the Access Developer Reference is this:
«An alternative to the Close method is
to set the value of an object variable
to Nothing (Set dbsTemp = Nothing).»
http://msdn.microsoft.com/en-us/library/bb243098.aspx
With that in mind, this article from the Microsoft Knowledge Base entitled «How to prevent database bloat after you use Data Access Objects (DAO)», tells you that you should explicitly close if you don’t want your databases to bloat. You’ll notice that the article is a little vague about the details; the «Cause» section is unclear, almost to the point of being gibberish.
http://support.microsoft.com/kb/289562
SYMPTOMS: A Microsoft Access database
has begun to bloat (or grow rapidly in
size) after you implement Data Access
Objects (DAO) to open a recordset.CAUSE: If you do not release a
recordset’s memory each time that you
loop through the recordset code, DAO
may recompile, using more memory and
increasing the size of the database.MORE INFORMATION: When you create a
Recordset (or a QueryDef) object in
code, explicitly close the object when
you are finished. Microsoft Access
automatically closes Recordset and
QueryDef objects under most
circumstances. However, if you
explicitly close the object in your
code, you can avoid occasional
instances when the object remains
open.
Finally, let me add that I have been working with Access databases for 15 years, and I almost always let my locally declared recordset variables go out of scope without explicitly using the Close method. I have not done any testing on it, but it does not seem to matter.
answered Feb 5, 2009 at 23:39
Shane MiskinShane Miskin
1,9132 gold badges22 silver badges30 bronze badges
When you are using ASP classic (server-side scripting), it is important to set all objects to nothing when you are through with them, because they do not go out of scope until the [virtual] server is shut down.
For this reason, all MS VB scripting examples always showed objects being closed and set to nothing. So that the script excerpts could be used in environments like ASP classic where the objects did not go out of scope.
There are, rarely, other situations where you wish to code long-running processes where the objects do not go out of scope, and you find yourself running out of physical memory if you do not explicitly release objects.
If you find yourself coding ASP classic, or running processes in global scope for some other reason, then yes, you should explicitly release objects.
answered Aug 9, 2016 at 12:36
daviddavid
2,4061 gold badge19 silver badges33 bronze badges
References are supposed to be cleaned up when the variable goes out of scope. Presumably this has improved with later versions of the software, but it was at one time not reliable. I believe that it remains a good practice to explicitly set variables to «Nothing.»
answered Feb 5, 2009 at 17:57
John MoJohn Mo
1,32610 silver badges14 bronze badges
I usually always put this at the end of my procedures, or call a «CloseRecordSet» sub with it in if I’m using module level ones:
Private Sub Rawr()
On Error GoTo ErrorHandler
'Procedural Code Here.
ExitPoint:
'Closes and Destroys RecordSet Objects.
If Not Recset Is Nothing Then
If Recset.State = 1 Then
Recset.Close
Conn.Close
End If
Set Recset = Nothing
Set Conn = Nothing
End If
Exit Sub
ErrorHandler:
'Error Handling / Reporting Here.
Resume ExitPoint
End Sub
That way however the procedure ends, (be it normally or due to an error) the objects are cleaned up and resources are free.
Doing it that way is quite safe in that it you can just slap it in and it will only do what is necessary in regards to closing, or destroying the recordset / connection object, incase it has already been closed (due to a runtime error or just closing it early as ya should, this just makes sure).
Its really not much hassle and its always best to clean up your objects when you’re finished with them to free up resources immediately regardless of what happens in the program.
answered May 26, 2010 at 15:15
3
Try this
If Not IsEmpty(vMyVariant) Then
Erase vMyVariant
vMyVariant = Empty
End If
answered Jan 24, 2013 at 7:51
Содержание
- Is there a need to set Objects to Nothing
- 7 Answers 7
- When should an Excel VBA variable be killed or set to Nothing?
- 3 Answers 3
- VBA: Set variable to «Empty» or «Missing»? Handling multiple optional arguments?
- 4 Answers 4
- VBA: Conditional — Is Nothing
- 3 Answers 3
- Do nothing in vba
- 8 Answers 8
- Related
- Hot Network Questions
- Subscribe to RSS
Is there a need to set Objects to Nothing
I always read that it is recommended to set objects to nothing, once I am done with them. But I normally use them only in functions inside forms.
Isn’t the reference lost and memory released when the function scope is left, regardless of setting objects to Nothing?
i.e. is it really necessary to do:
7 Answers 7
VB uses a so-called «reference counting» garbage collector.
Basically, the moment a variable goes out of scope, the reference counter on the referenced object is decremented. When you assign the object reference to another variable, the reference counter is incremented.
When the counter reaches zero, the object is ready for garbage collection. The object resources will be released as soon as this happens. A function local variable will most likely reference an object whose reference count never goes higher than 1, so object resources will be released when the function ends.
Setting a variable to Nothing is the way to decrease the the reference counter explicitly.
For example, you read in a file, and set the file object variable to Nothing right after the ReadAll() call. The file handle will be released immediately, you can take your time process its contents.
If you don’t set to Nothing , the file handle might be open longer than absolutely necessary.
If you are not in a «must unblock valuable resource» kind of situation, simply letting the variables go out of scope is okay.
Garbage collection is rarely perfect. Even in .NET there are times where you are strongly encouraged to prompt the system to do garbage collection early.
For this reason, I explicitly both close and set to Nothing recordsets when I’m done with them.
The very last line of the help topic for «Recordset.Close» in the Microsoft DAO help and the Access Developer Reference is this:
«An alternative to the Close method is to set the value of an object variable to Nothing (Set dbsTemp = Nothing).»
With that in mind, this article from the Microsoft Knowledge Base entitled «How to prevent database bloat after you use Data Access Objects (DAO)», tells you that you should explicitly close if you don’t want your databases to bloat. You’ll notice that the article is a little vague about the details; the «Cause» section is unclear, almost to the point of being gibberish.
SYMPTOMS: A Microsoft Access database has begun to bloat (or grow rapidly in size) after you implement Data Access Objects (DAO) to open a recordset.
CAUSE: If you do not release a recordset’s memory each time that you loop through the recordset code, DAO may recompile, using more memory and increasing the size of the database.
MORE INFORMATION: When you create a Recordset (or a QueryDef) object in code, explicitly close the object when you are finished. Microsoft Access automatically closes Recordset and QueryDef objects under most circumstances. However, if you explicitly close the object in your code, you can avoid occasional instances when the object remains open.
Finally, let me add that I have been working with Access databases for 15 years, and I almost always let my locally declared recordset variables go out of scope without explicitly using the Close method. I have not done any testing on it, but it does not seem to matter.
Источник
When should an Excel VBA variable be killed or set to Nothing?
I’ve been teaching myself Excel VBA over the last two years, and I have the idea that it is sometimes appropriate to dispose of variables at the end of a code segment. For example, I’ve seen it done in this bit adapted from Ron de Bruin’s code for transferring Excel to HTML:
I’ve done some searching on this and found very little beyond how to do it, and in one forum post a statement that no local variables need to be cleared, since they cease to exist at End Sub . I’m guessing, based on the code above, that may not be true at End Function , or in other circumstances I haven’t encountered.
So my question boils down to this:
- Is there somewhere on the web that explains the when and why for variable cleanup, and I just have not found it?
And if not can someone here please explain.
- When is variable cleanup for Excel VBA necessary and when it is not?
- And more specifically. Are there specific variable uses (public variables? Function-defined variables?) that remain loaded in memory for longer than subs do, and therefor could cause trouble if I don’t clean up after myself?
3 Answers 3
VB6/VBA uses deterministic approach to destoying objects. Each object stores number of references to itself. When the number reaches zero, the object is destroyed.
Object variables are guaranteed to be cleaned (set to Nothing ) when they go out of scope, this decrements the reference counters in their respective objects. No manual action required.
There are only two cases when you want an explicit cleanup:
When you want an object to be destroyed before its variable goes out of scope (e.g., your procedure is going to take long time to execute, and the object holds a resource, so you want to destroy the object as soon as possible to release the resource).
When you have a circular reference between two or more objects.
If objectA stores a references to objectB , and objectB stores a reference to objectA , the two objects will never get destroyed unless you brake the chain by explicitly setting objectA.ReferenceToB = Nothing or objectB.ReferenceToA = Nothing .
The code snippet you show is wrong. No manual cleanup is required. It is even harmful to do a manual cleanup, as it gives you a false sense of more correct code.
If you have a variable at a class level, it will be cleaned/destroyed when the class instance is destructed. You can destroy it earlier if you want (see item 1. ).
If you have a variable at a module level, it will be cleaned/destroyed when your program exits (or, in case of VBA, when the VBA project is reset). You can destroy it earlier if you want (see item 1. ).
Access level of a variable (public vs. private) does not affect its life time.
Источник
VBA: Set variable to «Empty» or «Missing»? Handling multiple optional arguments?
Is it possible, or desirable, to set objects/data to an «Empty» or «Missing» variant? I want to be able to conditionally pass optional arguments to a function. Sometimes I want to use an optional argument, sometimes I don’t.
In Python, you could easily pass through whichever optional arguments you wanted by using **kwdargs to unpack a dictionary or list into your function arguments. Is there something similar (or a way to hack it in VBA) so you can pass in Empty/Missing optional arguments?
In particular, I’m trying to use Application.Run with an arbitrary number of arguments.
EDIT:
I’m basically trying to do this:
Because the number of arguments changes for each function call, what is the acceptable way to make sure the right number of inputs are input into Application.Run?
The equivalent Python code would be
4 Answers 4
in VBA you use ParamArray to enter option inputs to functions.
There are two ways in which a routine can change the number of arguments that has to be provided to it:
- declare some of the trailing arguments as Optional
- declare the last argument as ParamArray
A single routine can use either or both.
An Optional parameter may have a strict type (e.g. Optional s As String ), but then it will be impossible to detect whether it was passed. If you don’t pass a value for such argument, the correct flavour of «blank» will be used, which is indistinguishable from passing that blank value manually.
So, having Public Sub Bob(Optional S As String) , you cannot detect from inside of Bob whether it was called as Bob or as Bob vbNullString .
An optional parameter may have a default value, which suffers from the same problem. So, having Public Sub Bob(Optional S As String = «Default Value») , you cannot detect if Bob was called as Bob or as Bob «Default Value» .
To be able to truly detect whether an optional parameter was passed, they have to be typed as Variant . Then a special function, IsMissing , can be used inside the routine to detect if a parameter was passed.
ParamArray can only be the last argument, and it allows an infinite* number of arguments to be passed starting from this position. All these arguments arrive packed in a single Variant array (no option for static typing here).
The IsMissing function does not work on the ParamArray argument (always returns False). The way to know how many arguments were passed is to compare UBound(args) with LBound(args) . Note that this only tells you how many argument «slots» were used, but some of them can be in fact missing!
Note that you cannot pass «missing» value for the trailing arguments of the ParamArray , i.e. this is illegal:
However, you can work around this using the trick described below.
An interesting use case that you touch in your question is preparing an array of all arguments in advance, passing it to the function, filling all the arguments «placeholders», but still expecting the function to detect that some of the arguments are missing (not passed).
Normally this is not possible, because if anything is passed (even «blank» values, such as Empty , Null , Nothing of vbNullString ), then it still counts as passed, and IsMissing() will return False .
Fortunately, the special Missing value is nothing but a specially constructed Variant , and even without knowing how to construct that value manually, we can trick the compiler to give it away:
Now, we can work around the inability to pass «missing» to the trailing «slots» of ParamArray :
Note, however, that this workaround will only work if you call BobArray directly. If you use Application.Run , it will not work because the Run method will discard any trailing «missing» arguments before passing them onto the called routine:
Further to @GSerg’s very comprehensive answer (I don’t have enough reputation just to comment), the ‘special’ value assigned to a Missing argument has the ‘appearance’ of being an Error value — it converts to «Error 448» (Named argument not found) using CStr() , and responds to IsError() as TRUE . However, an attempt to preset the argument using CvErr(448) before passing to a procedure (in the hope that it will be recognised as Missing) fails, perhaps because the value is ‘not quite’ the same as the Error value in some way.
@GSerg suggested a method of ‘recording’ the value actually passed by the compiler when an argument is missing and using that to preset a dummy argument prior to passing to the procedure needing to be fooled. This method, indeed, does work and I have simply extended @GSerg’s function to replace his error message (if it is inadvertently called with an argument) by a recursive call without an argument which ensures a successful outcome either way. Usage is simply to preset the dummy variable(s) before passing to a procedure (where it/they will then be treated as missing): Dummy_Var = Missing() .
Источник
VBA: Conditional — Is Nothing
There is an If condition in a VBA application as seen below:
When the code is run in debug mode, I found that the If condition returns a true even when My_Object has «No Variables».
Could somebody please explain this? I want My_Object.Compute to be executed only when My_Object exists.
3 Answers 3
Based on your comment to Issun:
Thanks for the explanation. In my case, The object is declared and created prior to the If condition. So, How do I use If condition to check for ? In other words, I do not want to execute My_Object.Compute if My_Object has
You need to check one of the properties of the object. Without telling us what the object is, we cannot help you.
I did test several common objects and found that an instantiated Collection with no items added shows in the watch window. If your object is indeed a collection, you can check for the condition using the .Count property:
It is also worth noting that if you declare any object As New then the Is Nothing check becomes useless. The reason is that when you declare an object As New then it gets created automatically when it is first called, even if the first time you call it is to see if it exists!
This does not seem to be the cause of your specific problem. But, since others may find this question through a Google search, I wanted to include it because it is a common beginner mistake.
Источник
Do nothing in vba
Is there an equivalent to python «pass» in VBA to simply do nothing in the code?
I get an error here that pass is not defined. Thanks.
8 Answers 8
just remove pass and re run the code. VBA will be happy to accept that I believe
Don’t include any statements:
Just leave it blank. You can also use a Select statement, it’s easier to read.
Write code that does what it says, and says what it does.
That’s all you need. An instruction that means «here’s some useless code» does not exist in VBA.
You want comments that say why, not what — a comment that says ‘do nothing is the exact opposite of that. Don’t write no-op code, it’s pure noise.
Assuming Python’s pass works like C#’s continue statement and skips to the next iteration, then the VBA equivalent is the one and only legitimate use of a GoTo jump:
This code shows an IF test that keeps searching unless it gets a match.
I coded in COBOL for many years and the equivalent ‘do nothing’ statement is NEXT SENTENCE .
In VBA, I find myself creating a dummy variable (sometimes a global) dim dummy as integer and then when I need that ‘do nothing’ action in an If..Then..Else I put in a line of code: dummy = 0 .
This is actually a legit question. I want to run a debug routine that stops when a certain critical value is, say, 8, i.e., set break point at x = 8 and then step through line by line. So the following construct is useful:
- Since you can’t put a break point on a comment, an actual statement is needed.
- You also can’t put a break point on the Case statements because that gets executed every time.
Obviously anything here is OK e.g., x=x , but it would be nice to have something formal like pass .
But I’ve been using x=x .
Most languages have a «null» or «empty» statement like Python’s pass . These statements have evolved because they are practically useful, and in some grammars, necessary. For example, as others have suggested, null statements can serve as side-effect free anchors for a debugger.
Note that if your use case is to set a conditional breakpoint, you may find Stop more useful, as in:
Hot Network Questions
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.3.20.43331
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.
Источник
-
#1
Hello all! This is a «best practice» sort of question for you fellow programmers out there.
Is it necessary to always set object variables to Nothing at the end of a procedure?
In a procedure where any sort of object variable is declared, I always make a habit of setting the object to nothing at the end of the procedure. An example:
Code:
Public Sub sampleProcedure()
Dim wks As Worksheet
Dim rng As Range
Dim dct As Scripting.Dictionary
Set wks = ThisWorkbook.Worksheets("Sheet1")
Set rng = wks.Range("A1")
set dct = New Scripting.Dictionary
'«BRILLIANT AUTOMATION PROGRAMMING HERE»
HANDLER_EXIT:
Set wks = Nothing
Set rng = Nothing
set dct = Nothing
Exit Sub
HANDLER_ERROR_SOMETHING1:
'«BRILLIANT ERROR HANDLING HERE»
HANDLER_ERROR_SOMETHING2:
'«BRILLIANT ERROR HANDLING HERE»
End Sub
I do this to make certain that the memory is being released for that particular variable. Doesn’t matter if it is a range, worksheet, collection, or some wild class object… I always set it to Nothing.
Am I being OCD or is this a valid concern?
Excel Joke
Why can’t spreadsheets drive cars? They crash too often!
-
#2
I think you only need to set variables declared as objects to nothing. This should be done in the reverse order of their setting (ie. the last object set should be the 1st object set to nothing). I’ll see if I can find a link to some real feedback. Also, your 1st error handler should exit sub before the next error handler routine. Dave
-
#3
VBA has its own garbage collector so I’m not really sure you are doing something strictly worthwhile (although it’s good practice for languages where this really matters). At worst it costs you the time to apply a few key strokes
shg
MrExcel MVP
-
#4
I think there are some corner cases where it’s necessary when you’ve done something so complicated that VBA’a reference counting fails, but in general, it’s unnecessary defensive programming that clutters your code. Variables of all types are destroyed when they go out of scope.
-
#5
I’m certain that there are situations that warrant such behavior, especially in cases where variable scope may exist outside the procedure. It’s good to know that it isn’t EXPLICITLY necessary, however. I’ll be happy to unclutter my programming.
A fine discussion, thank you all for sharing!
Also, good catch NdNoviceHlp. Fortunately this was fluff I threw up here to visualize my madness.
-
#7
That looked more like support for not setting objects to Nothing because then you avoid the possibility of orphaning them by doing it in the wrong sequence!
-
#8
Interesting. Maybe we could use a bit more learning if anyone else has a preference that they would like to share. I would prefer to ignore the whole business if it were possible. I’m guessing it’s not nb until your wb gets large…. which makes it hard to prove/disprove. Dave
shg
MrExcel MVP
-
#9
I’m certain that there are situations that warrant such behavior, especially in cases where variable scope may exist outside the procedure.
When variables are more broadly scoped, it is frequently for the very reason that you want them to persist.
I’d never say never, but have personally never had occasion to believe it was necessary or appropriate.
-
#10
Generally not necessary. If you look at my code you will see I do it anyway with most non-Excel objects, but not because I need to. I think the only exception I know of is DAO objects (and even that may be out of date). VBA is basically very good about «garbage collection» and, well, let’s face it, memory is cheap and plentiful these days.
Excel VBA — Empty, ZLS, Null, Nothing, Missing
————————————
Contents:
Empty
VarType Function
Null
Nothing
Missing
————————————
In excel vba we often refer to an Empty variable, ZLS (zero-length string) or null string or vbNullString, Null value, Missing Argument, or using the Nothing keyword with an object variable. It is important to differentiate and understand these terms and expressions while using them in your vba code. In this section, we will also understand using the VarType Function to determine the subtype of a variable, using the IsEmpty & IsNull Functions to check for Empty & Null values, and using the IsMissing Function to check whether optional arguments have been passed in the procedure or not.
Empty
When you declare a variable in your code using a Dim statement, you are setting aside sufficient memory for the variable (viz. 2 bytes for a Boolean or Integer variable, 4 bytes for a Long variable, and so on), and that the information being stored in the variable has an allowable range (of True or False for a Boolean variable, a whole number between -32,768 to 32,767 for an Integer variable, a whole number between -2,147,483,648 to 2,147,483,647 for a variable subtype of Long, and so on). You will receive a run-time error if trying to assign a string value to a variable declared as Integer.
While declaring a variable if you do not specify its data type, or if you do not declare a variable at all it will default to Variant data type that can hold any type of data (string, date, time, Boolean, or numeric values) & can automatically convert the values that it contains. However, the disadvantage is that this makes Excel reserve more memory than is required (at least 16 bytes), and could also result in mistyping a variable name and not knowing it viz. you might type rowNumbre instead of rowNumber.
When you run a macro, all variables are initialized to a default value. The initial default value: for a numeric variable is zero; for a variable length string it is a zero-length or empty string («»); a fixed length string is initialized with the ASCII code 0, or Chr(0); an object variable defaults to Nothing; a Variant variable is initialized to Empty. In numeric context, an Empty variable denotes a zero while in a string context an Empty variable is a zero-length string («») . A zero-length string («») is also referred to as a null string. However, it is advised to explicitly specify an initial value for a variable instead of relying on its default initial value.
Empty indicates that no beginning value has been assigned to a Variant variable ie. a variable which has not been initialized. An Empty variable is represented as 0 in a numeric context or a zero-length string («») in a string context. Empty is not the same as Null which indicates that a variable contains no valid data.
The Empty keyword indicates an uninitialized variable value. It is used as a Variant subtype. You can assign the Empty keyword to explicitly set a variable to Empty.
IsEmpty Function
Use the IsEmpty Function to check whether a variable has been initialized. The function returns a Boolean value — returns True for an uninitialized variable or if a variable is explicitly set to Empty, otherwise the function returns False. Syntax: IsEmpty(expression), where expression is a Variant variable which you want to check. See below example(s) where we use this function to check if a variant variable is empty.
Empty, Blank, ZLS (zero-length string), null string & vbNullString
ZLS means a zero-length string («»), is also referred to as a null string, and has a length of zero (0). For all practical purposes using vbNullString is equivalent to a zero-length string («») because VBA interprets both in a similar manner, though both are actually not the same — a ‘zero length string’ actually means creating a string with no characters, whereas vbNullString is a constant used for a null pointer meaning that no string is created and is also more efficient or faster to execute than ZLS. You can use «» or vbNullString alternatively in your code and both behave similarly. Note that there is no Blank keyword in vba, but we can refer to ‘blank cells‘ or «empty cells» in Excel spreadsheet. There are Excel worksheet functions for empty cells: (i) the COUNTA function counts the number of cells that are not empty, and also counts or includes a cell with empty text («») — also referrred to as empty string or zero length string — which is not counted as an empty cell; and (ii) the ISBLANK function returns True for an empty cell, and does not treat a zero-length string («») as a blank (empty cell) similarly as in COUNTA. Both the worksheet functions of ISBLANK and COUNTA distinguish between an empty cell and a cell containing a zero-length string (ie. «» as formula result).
VarType Function
Use the VarType Function to determine the subtype of a variable. Syntax: VarType(variable_name). The function returns an Integer indicating the variable’s subtype. The variable_name can be any variable except a user-defined data type (data type defined using the Type statement) variable. Examples of return values are: value 0 (VarType constant — vbEmpty, uninitialized / default), value 1 (VarType constant — vbNull, contains no valid data), value 2 (VarType constant — vbInteger, Integer), value 3 (VarType constant — vbLong, Long Integer), and so on. The VarType constants can be used anywhere in your code in place of the actual values.
Example — Empty variable:
Sub EmptyVar()
‘Empty variable
‘variable var1 has not been declared, hence it is a Variant data type:
‘returns 0, indicating variable subtype Empty:
MsgBox VarType(var1)
‘returns True, indicating variable subtype Empty:
MsgBox IsEmpty(var1)
‘returns False — is an Empty variable, not a Null variable — no beginning value has been assigned to a Variant variable:
MsgBox IsNull(var1)
‘Empty indicates a Variant variable for which you do not explicity specify an initial value, which by default gets initialized in VBA to a value that is represented as both a zero and a zero-length string.
‘returns both messages as below:
If var1 = 0 Then
MsgBox «Empty Variable represented as Zero»
End If
If var1 = «» Then
MsgBox «Empty Variable represented as a Zero-Length (Null) String»
End If
End Sub
Example — Testing for Empty:
Sub EmptyCheck()
‘testing for Empty
Dim var1 As Variant
‘variable not initialized — returns 0, indicating variable subtype Empty:
MsgBox VarType(var1)
‘returns True, indicating variable subtype Empty:
MsgBox IsEmpty(var1)
‘————
‘initialize the variable by specifying a string value:
var1 = «Hello»
‘returns 8, indicating variable subtype String:
MsgBox VarType(var1)
‘returns False, indicating variable is not Empty:
MsgBox IsEmpty(var1)
‘————
‘assign Empty keyword to set variable to Empty:
var1 = Empty
‘returns 0, indicating variable subtype Empty:
MsgBox VarType(var1)
‘returns True, indicating variable is Empty:
MsgBox IsEmpty(var1)
‘————
‘returns True for an empty worksheet cell, otherwise False:
MsgBox IsEmpty(ActiveCell)
End Sub
Example — Initialize a Variant variable:
Sub VarInitialized()
‘initialized variable
Dim var1 As Variant
‘variable has been initialized to a zero-length string («»):
var1 = «»
‘returns False, indicating variable is NOT Empty:
MsgBox IsEmpty(var1)
‘returns 8, indicating variable subtype String:
MsgBox VarType(var1)
‘returns — «Variable value is a Zero-Length String»
If var1 = «» Then
MsgBox «Variable value is a Zero-Length String»
Else
MsgBox «Variable value is NOT a Zero-Length String»
End If
‘returns — «Variable value is NOT Zero»
If var1 = 0 Then
MsgBox «Variable value is Zero»
Else
MsgBox «Variable value is NOT Zero»
End If
End Sub
Example — Check a zero-length string:
Sub CheckZLS()
‘check a zero-length string
Dim var1 As Variant
‘variable not initialized — returns 0, indicating variable subtype Empty — represented both as Zero (0) and a Zero-Length (Null) String:
MsgBox VarType(var1)
‘returns «True» for all If statements below:
If var1 = «» Then
MsgBox «True»
End If
If var1 = vbNullString Then
MsgBox «True»
End If
If Len(var1) = 0 Then
MsgBox «True»
End If
End Sub
Null
In VBA, Null keyword is used to indicate that a variable contains no valid data. A value indicating that a variable contains no valid data. Null is the result — (i) if you explicitly assign Null to a variable, or (ii) if you perform any operation between expressions that contain Null. The Null keyword is used as a Variant subtype ie. only a Variant variable can be Null, and and variable of any other subtype will give an error. Null is not the same as a zero-length string («»), and neither is Null the same as Empty, which indicates that a variable has not yet been initialized.
If you try to get the value of a Null variable or an expression that is Null, you will get an error of ‘Invalid use of Null’ (Run-time Error 94). You will need to ensure the variable contains a valid value. Refer Image 1.
IsNull Function
The IsNull Function returns a Boolean value — True for an expression that is Null (containing no valid data), or else False for an expression that contains valid data. Syntax: IsNull(expression). The expression argument is a variant that contains a numeric or string value, and is necessary to specify.
Example — Integer variable:
Sub VarInteger()
‘no beginning value assigned to a variable of subtype Integer
Dim intVar As Integer
‘returns False (intVar is not Null & neither is it Empty) — no beginning value has been assigned to a variable of subtype Integer:
MsgBox IsNull(intVar)
‘returns 2, indicating variable subtype Integer:
MsgBox VarType(intVar)
‘returns — «Variable value is Zero» (The initial default value for a numeric variable is zero)
If intVar = 0 Then
MsgBox «Variable value is Zero»
Else
MsgBox «Variable value is NOT Zero»
End If
End Sub
Example — Evaluate Empty / Null variable, use IsNull & VarType vba functions:
Sub EmptyNullVar()
‘evaluate Empty / Null variable, use IsNull & VarType vba functions.
Dim var1 As Variant
‘returns False, var1 is not Null but an Empty variable (no beginning value has been assigned to a Variant variable):
MsgBox IsNull(var1)
‘variable not initialized — returns 0, indicating variable subtype Empty:
MsgBox VarType(var1)
‘returns the message because var1 is an Empty variable:
If var1 = 0 And var1 = vbNullString Then
MsgBox «Empty Variable represented both as Zero (0) and a Zero-Length (Null) String»
End If
‘——————-
‘variable is initialized to a zero-length string («») or vbNullString:
var1 = vbNullString
‘returns False — var1 is not a Null variable:
MsgBox IsNull(var1)
‘returns 8, indicating variable subtype String:
MsgBox VarType(var1)
‘——————-
‘explicitly assigning Null to a variable:
var1 = Null
‘returns True, for a Null variable, containing no valid data:
MsgBox IsNull(var1)
‘returns 1, indicating variable subtype Null:
MsgBox VarType(var1)
‘——————-
‘explicitly assigning valid data to a variable:
var1 = 12
‘returns False, for a variable containing valid data:
MsgBox IsNull(var1)
‘returns 2, indicating variable subtype Integer:
MsgBox VarType(var1)
‘——————-
‘returns False, for an expression containing valid data:
MsgBox IsNull(«Hello»)
End Sub
Example — Check a Null variable:
Sub CheckNull()
‘check a Null variable
‘explicitly assigning Null to a variable:
var1 = Null
‘returns 1, indicating variable subtype Null:
MsgBox VarType(var1)
‘returns the message, indicating variable subtype Null:
If VarType(var1) = vbNull Then
MsgBox «Null variable»
End If
‘an expression containing Null also evaluates to Null:
var2 = Null + 2
‘returns 1, indicating variable subtype Null:
MsgBox VarType(var2)
End Sub
Example — Check worksheet cell for Empty, ZLS, Null:
Sub WorksheetCell_ZLS_Empty_Null()
‘check worksheet cell for Empty, ZLS, Null
Dim var1 As Variant
‘returns True:
MsgBox vbNullString = «»
‘In the case where ActiveCell is Blank:
‘returns True for a Blank cell:
MsgBox ActiveCell.Value = «»
MsgBox ActiveCell.Value = vbNullString
MsgBox ActiveCell.Value = 0
MsgBox IsEmpty(ActiveCell.Value)
‘assign Active Cell value to variable:
var1 = ActiveCell.Value
‘returns True:
MsgBox IsEmpty(var1)
MsgBox var1 = vbNullString
MsgBox var1 = «»
MsgBox var1 = 0
‘returns False:
MsgBox VarType(var1) = vbNull
‘returns 0, indicating variable subtype Empty:
MsgBox VarType(var1)
‘If you enter «» in the Active Cell ie. the active cell contains the value: =«»
‘returns True:
MsgBox ActiveCell.Value = «»
MsgBox ActiveCell.Value = vbNullString
‘returns False:
MsgBox ActiveCell.Value = 0
MsgBox IsEmpty(ActiveCell.Value)
End Sub
Nothing
Assigning the Nothing keyword to an object variable disassociates the variable from an actual object. Nothing is assigned to an object variable by using the Set statement. You can assign the same actual object to multiple object variables in vba code, and this association uses your system resources and memory. The system resources and memory get released only either after you assign Nothing to all object variables using the Set statement which disassociates these variables from the actual object, or when all object variables go out of scope and get destroyed. It is advisable to explicity set all object variables to Nothing at the end of your procedure or even earlier while running your code when you finish using them, and this will release memory allocated to these variables.
Determine if the object variable is initialized — use Is Nothing for objects: To check if an object has been assigned or set, use the Is keyword with Nothing, viz. If object_variable Is Nothing. For objects, you cannot test if an object_variable is equal to something, and using = instead of Is will give an error.
Example — Using the Nothing keyword with an object variable:
Sub ObjNothing()
‘using the Nothing keyword with an object variable
Dim objVar As Object
‘returns True, because you have not yet assigned an actual object to the object variable:
MsgBox objVar Is Nothing
Set objVar = ActiveSheet
‘returns False, because you have assigned an actual object (Sheet) to the object variable:
MsgBox objVar Is Nothing
Set objVar = Nothing
‘returns «Variable not associated with an actual object», because you have disassociated the object variable from an actual object:
If objVar Is Nothing Then
MsgBox «Variable not associated with an actual object»
Else
MsgBox «Actual object is assigned to an Object variable»
End If
End Sub
Missing
Passing Arguments to Procedures: When an external value is to be used by a procedure to perform an action, it is passed to the procedure by variables. These variables which are passed to a procedure are called arguments. An argument is the value supplied by the calling code to a procedure when it is called. When the set of parentheses, after the procedure name in the Sub or Function declaration statement, is empty, it is a case when the procedure does not receive arguments. However, when arguments are passed to a procedure from other procedures, then these are listed or declared between the parentheses.
Optional Arguments: Arguments can be specified as Optional by using the Optional keyword before the argument to its left. When you specify an argument as Optional, all other arguments following that argument to its right must
also be specified as Optional. Note that specifying the Optional keyword makes an argument optional otherwise the argument will be required.
Check if an argument is Missing, using the IsMissing function: The Optional argument should be (though not necessary) declared as Variant data type to enable use of the IsMissing function which works only when used with variables declared as Variant data type. The IsMissing function is used to determine whether the optional argument was passed in the procedure or not and then you can adjust your code accordingly without returning an error. If the Optional argument is not declared as Variant in which case the IsMissing function will not work, the Optional argument will be assigned the default value for its data type which is 0 for numeric data type variables (viz. Integer, Double, etc) and Nothing (a null reference) for String or Object data type variables.
IsMissing function: The IsMissing function is used to check whether optional Variant arguments have been passed in the procedure or not. Syntax: IsMissing(argname). The function returns a Boolean value — True if no value is passed for the optional argument, and False if a value has been passed for the optional argument. If the IsMissing function returns True for an argument, using the missing argument in the code will cause an error, and thus using this function will help in adjusting your code accordingly.
Example of using the IsMissing function to check if an argument is Missing:
Function FullName(strFirstName As String, Optional strSecondName As Variant) As String
‘The declaration of the procedure contains two arguments, the second argument is specified as Optional. Declaring the Optional argument as Variant data type will enable use of the IsMissing function.
‘The IsMissing function is used to determine whether the optional argument was passed in the procedure, and if not, you can adjust your code accordingly without returning an error.
If IsMissing(strSecondName) Then
FullName = strFirstName
Else
FullName = strFirstName & » « & strSecondName
End If
End Function
Sub GetName()
Dim strGivenName As String
strGivenName = InputBox(«Enter Given Name»)
‘specifying only the first argument & omitting the second argument which is optional:
MsgBox FullName(strGivenName)
End Sub