和風スパゲティのレシピ

日本語でコーディングするExcelVBA

Killステートメントに*が渡ると一括削除が実行される

知らずに落ちると抜け出せなくなるVBAの落とし穴です。

  • Killステートメントを実行したら関係のないファイルも削除された
  • ファイル名を半角に変換した際、Killステートメントが暴発する
  • 環境依存文字を用いたファイルの削除が安定しない

あたりにお悩みの方は、この落とし穴に落ちていないかご確認ください。

Killステートメント(DeleteFile)のワイルドカード仕様

Killステートメントには「ワイルドカード*」いわゆる「あいまい検索」機能があり、
例えば以下のコードで「フォルダ内の一括削除」が実行できます。

Kill "C:\Users\wfsp\Desktop\○○\*"

 
この仕様はFileSystemObjectのDeleteFileメソッドでも同様で、
知って使う分には非常に強力な機能になります。

「PDFだけを削除する」なんてのも一瞬ですからね。

Kill "C:\Users\wfsp\Desktop\○○\*.pdf"

 
しかしこの仕様、意図せず発動した場合には、
消してほしくないファイルも静かに削除していく凶悪なメソッドと化します。


何よりもまずはこの仕様を知っておくことが危険回避の第一歩ですので、
Kill/DeleteFile共にワイルドカードを受け取ることを知っておきましょう。
 

罠にはまりやすいポイント

Dir関数の結果でなく引数をKillに渡してしまう

偶発的にワイルドカードが渡る例としてよくあるのは、
Dir関数に渡す文字列を誤って渡してしまうパターンです。

「ファイルが存在したら消す」をDir関数で実装する際、
「見つかったファイル名」ではなく「検索対象ファイル名」を渡してしまう
ミスに注意しましょう。

全角→半角変換の結果意図せずワイルドカードが混じる

ワイルドカードに使われる「*」「?」などの文字は、
そのままではファイル名に使用できません。

よって通常ファイル名を取得してKillに渡す場合は、
ワイルドカードが偶発することを心配する必要はありません。
※ ファイル名やフォルダ名に「*」が入ることはない


しかし、全角の「*」はファイル名に使用することができるため、
ファイル名の全半角/大小文字を統一する処理をしていると、
稀にこれらの文字がFileSystem系の処理に混じることがあります。


よりによってKillにわたってしまうことは稀と思いますが、
一応頭の片隅に入れておくと、いつか命拾いするかもしれません。

Dir関数の結果がUnicode文字だった場合に「?」を返す

Dir関数はUnicode文字(環境依存文字)に対応していないため、
それらの文字が混じると「?」に変換して表示します。

この「?」はワイルドカードとして「何らかの1文字」という意味を持つため、
この結果をそのままKillに渡すと予期せぬファイルを削除することがあります。


前述の「引数を渡すミス」と同じく、
DirとKillの併用を行う場合は十分注意して下さい。

ワイルドカードの機能をOFFにする方法

Killステートメントのワイルドカード機能を切って、
「絶対にひとつのファイルだけを削除する」機能が欲しいときがあります。

しかしながらKill/DeleteFile共にこの機能を切ることはできないため、
FileSystemObjectの機能全体を使って以下のように実装します。

Public FSO As New FileSystemObject

Sub 指定した1ファイルだけを削除する()

    Dim 削除するファイルパス As String
    削除するファイルパス = "C:\Users\wfsp\Desktop\○○.pdf"
    
    ' 削除ファイルが存在するかチェック
    If FSO.FileExists(削除するファイルパス) Then
        
        ' 削除ファイルが存在すればFileオブジェクトをSet
        Dim 削除ファイル As File
        Set 削除ファイル = FSO.GetFile(削除するファイルパス)
        
        ' FileオブジェクトのDeleteメソッドでファイルを削除
        削除ファイル.Delete
        
    End If

End Sub

 
FileSystemObjectの「Fileオブジェクト」を取得して、
その「Deleteメソッド」を利用してファイルを削除するコードです。


FileSystemObject全体の仕様を理解していないと難しいコードですが、
このコードを利用すればかなり安全なファイル削除が実行できます。

複雑なファイル管理の中でファイル削除を実行する場合は、
このコードでの実行を検討してください。


以下のように汎用関数化するのもおすすめです。

Public FSO As New FileSystemObject

Function 指定した1ファイルを削除する(削除ファイルパス As String) As Boolean
    
    ' 削除ファイルが存在するかチェック
    If FSO.FileExists(削除するファイルパス) Then
        
        ' 削除ファイルが存在すればFileオブジェクトをSet
        Dim 削除ファイル As File
        Set 削除ファイル = FSO.GetFile(削除するファイルパス)
        
        ' FileオブジェクトのDeleteメソッドでファイルを削除
        On Error Resume Next
        削除ファイル.Delete
        
        ' 削除の成否を返す
        If Err.Number = 0 Then 指定した1ファイルを削除する = True
        
    End If
    
End Function