web-dev-qa-db-ja.com

Excel VBA変数を強制終了するか、何も設定しないのはいつですか?

私は過去2年間にわたってExcel VBAを教えてきましたが、コードセグメントの最後で変数を破棄することが適切な場合があるという考えがあります。たとえば、 Ron de BruinがExcelをHTMLに転送するためのコード

Function SaveContentToHTML (Rng as Range)

        Dim FileForHTMLStorage As Object
        Dim TextStreamOfHTML As Object
        Dim TemporaryFileLocation As String
        Dim TemporaryWorkbook As Workbook

...

        TemporaryWorkbook.Close savechanges:=False
        Kill TemporaryFileLocation
        Set TextStreamOfHTML = Nothing
        Set FileForHTMLStorage = Nothing
        Set TemporaryWorkbook = Nothing

End Function

私はこれをいくつか検索しましたが、それを行う方法を超えてほとんど何も見つかりませんでした、そして1つのフォーラムの投稿で ローカル変数をクリアする必要がないというステートメント 、それらはEnd Sub。上記のコードに基づいて、End Function、または他の状況では遭遇していません。

だから私の質問はこれに要約します:

  • 変数のクリーンアップのタイミングと理由を説明するWeb上のどこかにありますが、見つけられませんでしたか?

そして、ここで誰かが説明できない場合は...

  • Excel VBAの変数クリーンアップが必要なのはいつですか?
  • より具体的には...サブルーチンよりも長くメモリにロードされたままの特定の変数の使用(パブリック変数?関数定義変数?)があります。
29

VB6/VBAは、決定論的アプローチを使用してオブジェクトを破棄します。各オブジェクトには、それ自体への参照の数が格納されます。数がゼロに達すると、オブジェクトは破棄されます。

オブジェクト変数は、スコープから外れたときにクリーンアップ(Nothingに設定)されることが保証されています。これにより、それぞれのオブジェクトの参照カウンターが減少します。手動による対策は不要です。

明示的なクリーンアップが必要な場合は2つだけです。

  1. 変数がスコープ外になる前にオブジェクトを破棄したい場合(たとえば、プロシージャの実行に時間がかかり、オブジェクトがリソースを保持しているため、できるだけ早くオブジェクトを破棄して、資源)。

  2. 2つ以上のオブジェクト間に循環参照がある場合。

    objectAobjectBへの参照を保存し、objectBobjectAへの参照を保存する場合、明示的にチェーンを解除しない限り、2つのオブジェクトは破棄されません。設定objectA.ReferenceToB = Nothing または objectB.ReferenceToA = Nothing

表示するコードスニペットが間違っています。手動でクリーンアップする必要はありません。 より正確なコードの誤った感覚 が得られるため、手動でクリーンアップすることは有害です。

クラスレベルで変数を使用している場合、クラスインスタンスが破棄されると、変数は消去/破棄されます。必要に応じて、より早く破棄できます(アイテム1.)。

モジュールレベルで変数を使用している場合、プログラムが終了すると(または、VBAの場合はVBAプロジェクトがリセットされると)、変数は消去/破棄されます。必要に応じて、より早く破棄できます(アイテム1.)。

変数のアクセスレベル(パブリック対プライベート)は、そのライフタイムに影響しません。

46
GSerg

VBAは、 参照カウント で実装されるガベージコレクターを使用します。

特定のオブジェクトへの複数の参照が存在する場合があります(たとえば、Dim aw = ActiveWorkbookは、アクティブなワークブックへの新しい参照を作成します)。したがって、ガベージコレクターは、他の参照がないことが明らかな場合にのみオブジェクトをクリーンアップします。 Nothingに設定することは、参照カウントを減少させる明示的な方法です。スコープを終了すると、カウントは暗黙的に減らされます。

厳密に言えば、最新のExcelバージョン(2010以降)ではNothingに設定する必要はありませんが、古いバージョンのExcelには問題がありました(回避策は明示的に設定することでした)

3
SheetJS

データが自動的にクリーンアップされず、最終的に「メモリ不足」エラーが発生する状況が少なくとも1つあります。私が持っていたユーザーフォームで:

Public mainPicture As StdPicture
...
mainPicture = LoadPicture(PAGE_FILE)

UserFormが破棄されたとき(Unload MemainPictureにロードされたデータに割り当てられたメモリは、割り当て解除されていませんでした。明示的に追加する必要がありました

mainPicture = Nothing

終了イベントで。

0
Tomasz