プロが教える店舗&オフィスのセキュリティ対策術

改めての質問です。
下記において、Set Wb = Nothing の位置は、考え方として、どこが正しいのでしょうか?

Sub myTitle()
Dim Wb As Workbook
Dim Ws As Worksheet
If xxxxx Then
Set Wb = Workbooks(myName)
Wb.Protect Structure:=False, Windows:=False
Application.DisplayAlerts = False
For Each Ws In Wb.Worksheets
If Left(Ws.Name, 1) = "H" Then Ws.Delete
Next
Application.DisplayAlerts = True
Wb.Protect Structure:=True, Windows:=False
Set Wb = Nothing
Set Ws = Nothing
End If

'Set Wb = Nothing やはり、この位置でしょうか?
'Set Ws = Nothing やはり、この位置でしょうか?

End Sub

上記は、オブジェクトWb,Wsに値を入れているIf文の中で開放をしています。
しかし、解放の位置は、If文の外(Dimに対応した位置)で、与えるのが、正しいのでしょうか?

Newを使った場合とか、現実に値を入れた時に生成される話と、こんがらかっているのです。
宜しく、お願い致します。

A 回答 (3件)

#1の回答者です。



実は、ご質問というのは、かなり議論になりやすい内容なのです。混乱すると思って、大幅に割愛しました。
>>人に披露するとか、ネットで口性(くちさが)がない人間がいるならともかく、あまり細かく気にすることはないような気がします。

これに尽きます。

学校などで教えるVBAでは、「オブジェクトは必ず開放しなさい」といわれますが、本当は、一種の建前とか作法のようなものなのだろうと思います。作法だったらとやかくいう筋合いでもないけれども、多少、気にかけなくてはならないのは、いい加減にすると、トラブルを起こすものがあるということです。それは、外部参照で常駐してしまうもので、代表は、"InternetExplorer.Application" です。

基本的には、
Sub ~ End Sub の中で、オブジェクトを確保したものは、その中で終わります。つまり、End Sub とすれば、開放されてしまいます。例外はあります。モジュール変数やグローバル変数は、例外になります。

>Wsなんかは、Forループを抜けた段階で nothing になっています。
>(なぜだか、理解していませんが)。つまり、
>Set Ws=nothing
>の記述は不要ということ。

これは、For Each Ws In Wb.Worksheets ~ Next のNext で、Wsが、終わっているということです。
他にもWith Workbooks(myName) ~ End With で、End With で終わっています。

余計わからなくなるかもしれませんが、こちらを読んでみてください。

「Set a = Nothing」のお話
http://www.moug.net/tech/exvba/0150027.html

その中に、
「「Set a = Nothing」をして、早め早めにオブジェクトへの参照を解除することで効率化につながります。」

このような文章がありますが、見栄えを優先していたから、最初のご質問で、If xxxxx Then がなにをするかにもよりますが、10年前ぐらいは、その外に、Set Wb = Workbooks(myName)としたのが常識でしたが、それが変わりつつあると思います。

かえって、わかりにくくなったかもしれません。

P.S.
もし、余裕があるのでしたら、こちらも考えてみてください。
http://oshiete.goo.ne.jp/qa/9064013.html
ご質問者は、解決しないとしています。私も理由はわかりません。


今までの話の延長上にあるはずなのです。今度は、付帯するオブジェクトとは別に、マクロ自身にも64Kというメモリ枠があります。残念ながら、こちらは、ローカル・ウィンドウでは、見れません。そのマクロ自身のメモリ枠を越えたり、End やEnd Sub、エラー信号 などで、そのメモリを壊してしまえば、たぶん、マクロは中途で止まってしまうはずです。マクロが走る本線が終われば、それを載せているオブジェクトも運ばなくなって、開放してしまうと思うのです。
    • good
    • 0
この回答へのお礼

遅くなりましたが、ありがとうございます。
難しく、にわかには理解できていません。
別の問題で、また、ここに戻ってきたいと思います。
とにかく、ありがとうございました。

お礼日時:2015/09/30 19:07

こんにちは。


追伸の追伸です。

かなり難しい内容にしてしまいました。

>もし、余裕があるのでしたら、こちらも考えてみてください
解決策のひとつです。
たまたま、マクロを作っいたら、同じ現象が現れたので、その解決策を
http://oshiete.goo.ne.jp/qa/9073173.html
で書きましたが、OnTime メソッド使って、途切れたマクロの線路を補填してやればよいのです。
    • good
    • 0
この回答へのお礼

参考とさせていただきます。

お礼日時:2015/09/30 19:08

こんにちは。



人に披露するとか、ネットで口性(くちさが)がない人間がいるならともかく、あまり細かく気にすることはないような気がします。簡単に言えば、ループの終わった時点で、何が残っているかを見れば、一目瞭然です。
そうしたら、少なくともWs は残ってませんね。(ローカルウィンドウで確認してみてください)

Wb(ワークブック) は、If の中で、設定したものですから、If の中で処理するほうが、無駄が少ないかと思います。

そして、通常、オブジェクトを生成したら、その生成した順番と逆に開放していくのが通例です。ただ、それを間違えたところで、VBA内では支障が生ずるわけではありません。
    • good
    • 0
この回答へのお礼

ありがとうございます。
ローカルウィンドウ、これまで使っていませんでした。
助かります。
少なくとも、このローカルウィンドウで、残っているものは、
積極的に開放してやることが必要ということを理解しました。
今まで、Dimで定義した段階で、メモリが確保されると考えていました。

Wsなんかは、Forループを抜けた段階で nothing になっています。
(なぜだか、理解していませんが)。つまり、
Set Ws=nothing
の記述は不要ということ。

ありがとうございます。

お礼日時:2015/09/22 06:56

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!