• ベストアンサー

【Excel VBA】 WorksheetやRangeオブジェクトとして宣言した変数の開放は必要でしょうか?

こんばんは。 プロシージャレベルで宣言したWorksheetやRangeなどのオブジェクト変数に対し、 プロシージャを終了する直前に、 Set ○=Nothing を実行して、変数(オブジェクトへの参照)を開放する処理を習慣的行っていました。 これは、絶対に必要な処理なのでしょうか? 開放しないことで不具合が出るケースとはどういう場合なのでしょうか? どなたか、ご教示いただけないでしょうか。 よろしくお願いいたします。 <例> Sub test()   Dim Ws1 As Worksheet      Set Ws1 = Worksheets("Sheet1")   '処理内容      Set Ws1 = Nothing End Sub 尚、CreateObject関数で作成したオブジェクトへの参照などではなく、 あくまでもWorksheetやRangeなどの話です。

質問者が選んだベストアンサー

  • ベストアンサー
  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.2

プロシージャレベルの Worksheet や Range オブジェクトでは、 プロシージャの終了とともに自動開放されますから、 Nothing に よる開放処理は必須ではありません。 長く VBA を使っておりますが、省略したからといって不具合が発生 したケースも経験ありません。 ただ、プログラムを書く姿勢として、   自分で使ったモノは、自分で開放する とあるべきではないかと考えます。 VBA においてはマナーみたいなものですね。されど、これは私個人 だけの考えではなく、過去から積み上がった先人プログラマーの 経験側でもあります。 例えば、VBA のこのような言語仕様に慣れきった人、つまり開放 するということが習慣として身についていない人が、メモリ操作や 画像処理など高度な処理を書くようになった場合、必須の開放処理 が抜け落ちたプログラムを平気で書いてしまい、後々メモリリーク に悩むはめになったりしがちです。 言語仕様として、「必須ではない」とはいえ、きちんと開放処理を 記述した方が良いでしょう。 注意が必要なのは、オートメーションを使ったプログラムの場合は、 例えプロシージャレベルであっても開放必須です。これを怠ると #1 でお話がでてますが、いわゆるゾンビプロセスが残るという事態 になります。また、 > プロシージャレベルで宣言したWorksheetやRangeなどの... と限定されているのでお分かりかと思いますが、グローバル等の 広域変数の場合も、誤動作防止、余計なメモリ消費を抑えるため 適所で開放処理が必須になります。 余談になりますが、#1 補足欄のソースは私ならこう書きます。 ご参考までに。 Sub test()   On Error Goto Err_   Dim Ws1 As Worksheet   Set Ws1 = Worksheets("Sheet1")   '処理内容    Bye_:   Set Ws1 = Nothing   Exit Sub Err_:   'エラー処理   Resume Bye_ End Sub

ka_na_de
質問者

お礼

KenKen_SP様、大変丁寧なご回答ありがとうございました。 すっきり納得できました。 必須ではないが、行うべきだということですね。 最後のソースを含め大変参考になりました。 またお世話になる事があると思いますが、 その際はよろしくお願いいたします。

その他の回答 (1)

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.1

Nothingは必要であると思ってます。 VBAのつくりが悪くて、何度かNothingを通る前に強制終了させてたらフリーズ。 タスクマネージャでプロセスみたら、EXCELの残ったままのプロセスが・・・。(ゾンビプロセス?) なので、「おまじないかも?」とは思いつつも実行してます。

ka_na_de
質問者

お礼

bin-chan様 ご回答ありがとうございました。 今までどおり、変数の開放を習慣化しようと思います。 以下、備忘録として利用させていただく事をお許しください。 Sub test()   On Error Goto Err_   Dim Ws1 As Worksheet   Set Ws1 = Worksheets("Sheet1")   '処理内容    Bye_:   Set Ws1 = Nothing   Exit Sub Err_:   MsgBox Err.Description, vbCritical   Resume Bye_ End Sub

ka_na_de
質問者

補足

ご回答ありがとうございます。 途中でエラーが発生した場合のことを考えて ということですね。 それでは、以下のような処理をしたほうが 良いのでしょうか? (Exit Subの前では、あえてNothingしてません) <例> Sub test()   On Error Goto Err   Dim Ws1 As Worksheet      Set Ws1 = Worksheets("Sheet1")   '処理内容      Exit Sub Err:    Set Ws1 = Nothing End Sub

関連するQ&A