【Access】VBAのSet Nothingは必要?書かないとどうなる?

VBAでオブジェクトを使い終わった後Set Nothingを書くべきか迷ったことはありませんか?

Accessではこの書き方をめぐって意見が分かれることがあります。

この記事ではSet Nothingの必要性と書かない場合の影響について解説します。

この記事で分かること
  • VBAのSet Nothingが何をする命令か
  • Set Nothingが必要な場合と不要な場合
  • 書かない場合の影響や注意点
  • ループ内などでの正しい使い方と落とし穴
目次

VBAのSet Nothingって何?

Set Nothingオブジェクト変数の参照を解除する命令のことです。

例えば次のようなVBAがあるとします。

Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("T顧客")
  • rsはレコードセットを指す変数
  • Setでオブジェクトを割り当てることを意味します

VBAでオブジェクト変数を使い終わった後に次のように書くことがあります。

Set rs = Nothing

Set Nothingの意味

  • 変数rsが指しているオブジェクトとの関連を切る
  • VBAのメモリ上のオブジェクト参照を開放する

変数を「箱」、オブジェクトを「物」と考えるとイメージしやすいです。

箱(変数)に物(オブジェクト)が入っていて、Set Nothingでその物を手放すイメージです。

Set Nothingの必要性

実はSet Nothingは記述しなくても問題ない場合がほとんどです。

VBAはガーベージコレクションという不要になったオブジェクトを自動で回収する仕組みを持っています。

つまり、VBAを閉じると自動的にメモリは解放されるようになっています。

じゃあ書く必要ないじゃん!

そう思ったかもしれませんが、実務では状況に応じて書いた方が安全なケースもあります。

書いた方がいいケース

外部アプリケーションや外部リソースを扱う場合

ExcelオブジェクトやADO接続などAccess外部のリソースを扱う場合は明示的に解放することが重要です。

Dim xlApp As Excel.Application
Set xlApp = New Excel.Application

xlApp.Visible = True
xlApp.Workbooks.Add

xlApp.Quit
Set xlApp = Nothing
  • Quitで終了させてからSet Nothingで解放する
  • 書かないとプロセスが残る・ファイルがロックされたままになることがある

複数オブジェクトを連続で使用する場合

ADOやDAOのRecordset、Connectionオブジェクトを複数生成する場合も同様です。

Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset

Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=DB.accdb;"

Set rs = New ADODB.Recordset
rs.Open "SELECT * FROM T顧客", cn

rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing

外部リソースを明示的に開放することで接続が残らず安定動作します

書かなくてもいいケース

単発で短時間処理が完結するオブジェクト

フォームを開いたときに1回だけレコードセットを開く簡単な処理で閉じる場合は、Set Nothingを書かなくてもVBAが自動的に解放してくれます。

Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("T顧客")

MsgBox rs.RecordCount

rs.Close
' Set rs = Nothing は省略してもOK

注意点と落とし穴

オブジェクトを閉じずにNothingは意味がない

オブジェクトはCloseQuitなどで終了させてからSet Nothingを行う必要があります。

NGな例

Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("T顧客")

' 間違った例:Closeしていない
Set rs = Nothing

正しい例

Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("T顧客")

rs.Close ' まず閉じる
Set rs = Nothing ' 参照を解放

ポイント

DAO/ADOレコードセットやExcelオブジェクトなど、外部リソースを使う場合は必ず終了メソッドを呼ぶこと。

ループ内でSet Nothingを書きすぎない

大量データの処理などでループ内に毎回Set Nothingを書くと処理が遅くなる場合があります。

NGな例

Dim i As Long
Dim rs As DAO.Recordset

For i = 1 To 1000
    Set rs = CurrentDb.OpenRecordset("T顧客")
    
    ' データ処理
    
    ' 毎回書くとオーバーヘッドになる
    rs.Close
    Set rs = Nothing
Next i

正しい例

Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("T顧客")

Dim i As Long
For i = 1 To 1000
    ' データ処理
Next i

' ループ外でまとめて解放
rs.Close
Set rs = Nothing

ポイント

ループ内ではオブジェクトの生成・破棄を最小限にする。

まとめ

今回はSet Nothingの必要性と書かない場合の影響について解説しました。

オブジェクトの操作は難しく感じる方も多く正しい使い方を理解するのは少し難易度が高いテーマです。

しかし、状況に応じてSet Nothingを書く・書かないを判断できれば次のようなメリットがあります。

  • 外部リソースを安全に扱える
  • 長時間稼働するVBAでも安定性が向上する
  • 不要なメモリやプロセスの残留を防げる

少し意識するだけでワンランク上のVBAを構築することができます。

コメント

コメントする

コメントは日本語で入力してください。(スパム対策)

CAPTCHA

目次