2
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

事前バインディングと実行時バインディングでWithの挙動が変わる事例

Last updated at Posted at 2018-08-29

VBAのWithステートメントにオブジェクトを指定したときの話です。

指定したオブジェクトが事前バインディングされている場合、実行時バインディングされている場合、で挙動が変わる事例があったため、備忘録として残します。

確認環境

Windows 10 Pro 64bit
Microsoft Excel 2016 64bit

サンプル

動作としては、一時ファイルを作成、TextStreamとして開き、その後削除するコードです。

事前バインディングの場合

TextStreamを明示的にClose()していませんが、End Withのステートメント実行時に参照が解放され、ファイルを削除できます。

実行にはMicrosoft Scripting Runtimeの参照設定が必要です。

EarlyBinding
'require Microsoft Scripting Runtime
Private Sub SampleEarlyBinding()
    Dim fso As Scripting.FileSystemObject
    Set fso = VBA.CreateObject("Scripting.FileSystemObject")
    
    Dim tempFilePath As String
    tempFilePath = fso.BuildPath(VBA.Environ$("TEMP"), fso.GetTempName())
    
    With fso.CreateTextFile(tempFilePath)
        'ファイルを開いているので削除できない
        'Call fso.DeleteFile(tempFilePath, Force:=True)
    End With
    
    '事前バインディングなら削除できる
    Call fso.DeleteFile(tempFilePath, Force:=True)
    
End Sub

実行時バインディングの場合

基本的には先ほどのコードのfsoの型宣言をObjectに変更しただけです。

このコードを実行すると、コメントアウトされていない
Call fso.DeleteFile(tempFilePath, Force:=True)
の行でエラーが発生します(ファイルへの参照を解放できていない)。

この時、このプロシージャ内で参照を解放する方法はなさそうです。
プロシージャを抜ければ問題なく削除できるようになります(参照が解放される)。

LateBinding
Private Sub SampleLateBinding()
    Dim fso As Object 'As Scripting.FileSystemObject
    Set fso = VBA.CreateObject("Scripting.FileSystemObject")
    
    Dim tempFilePath As String
    tempFilePath = fso.BuildPath(VBA.Environ$("TEMP"), fso.GetTempName())
    
    With fso.CreateTextFile(tempFilePath)
        'ファイルを開いているので削除できない
        'Call fso.DeleteFile(tempFilePath, Force:=True)
    End With
    
    '遅延バインディングではエラーになる
    Call fso.DeleteFile(tempFilePath, Force:=True)
    
    '手動削除用(デバッグ時にCtrl+F9で実行行を変更可能)
    Call VBA.Shell("explorer.exe /select," & tempFilePath, vbNormalFocus)
    
End Sub

image.png

参考:Withを使用しない場合

実行時バインディングでも、以下のように一行で記述した場合は問題なく参照を解放できます。
Call fso.CreateTextFile(tempFilePath).Write("Hello!")

NoUseWith
Private Sub NoUseWith()
    Dim fso As Object 'As Scripting.FileSystemObject
    Set fso = VBA.CreateObject("Scripting.FileSystemObject")
    
    Dim tempFilePath As String
    tempFilePath = fso.BuildPath(VBA.Environ$("TEMP"), fso.GetTempName())
    
    Call fso.CreateTextFile(tempFilePath).Write("Hello!")
    Stop 'BreakPoint ファイル存在確認用
    Call fso.DeleteFile(tempFilePath, Force:=True)
End Sub
2
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?