【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 = NothingSet 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 = NothingQuitで終了させてから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は意味がない
オブジェクトはCloseやQuitなどで終了させてから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を構築することができます。
コメント