VBAでの一般的な削除処理はゴミ箱に移動せず完全削除される
VBAにはファイル削除の方法としていくつかあります。
- VBA標準のKillステートメント(一番簡単)
- FileSystemObjectのDeleteFileメソッド
- FileオブジェクトのDeleteメソッド
- Shell32ライブラリのShellオブジェクトのMoveHereメソッド
- Win32APIのDeleteFile関数
これらの方法で実行すると、いずれの場合もファイルが完全に削除されます。ゴミ箱には行きません。マウス操作でファイルを削除した場合の「完全に削除しますか」→「はい」の状態です。
VBAで処理をする場合、いらないファイルを消すというのは本当に要らないから消すことが一般的なため、ゴミ箱に一時的に残しておく必要はまずないですが、人が操作したときと同じようにゴミ箱に残しておきたい場合には上記の方法では困ります。
そこで、以下ではマウス操作の削除のようにゴミ箱に移動させる方法を紹介します。
VBAでゴミ箱に移動させる方法
VBAでゴミ箱に移動させるにはWin32APIのSHFileOperation関数を利用します。Win32APIについては「VBAでWin32APIを使う方法と定義一式」をご参照ください。
後述のサンプルコードに全部書いていますのでダウンロードは不要ですが、当ページで利用しているWin32APIの定数、構造体、関数の定義が書かれているWin32API_PrtSafe.TXTもダウンロードできるようにしています。
Declare PtrSafe Function SHFileOperation Lib “shell32.dll” Alias “SHFileOperationA” (lpFileOp As SHFILEOPSTRUCT) As Long
引数にはSHFILEOPSTRUCT構造体を指定します。
1 2 3 4 5 6 7 8 9 10 |
Type SHFILEOPSTRUCT hwnd As LongPtr wFunc As Long pFrom As String pTo As String fFlags As Integer fAnyOperationsAborted As Long hNameMappings As LongPtr lpszProgressTitle As String ' only used if FOF_SIMPLEPROGRESS End Type |
SHFileOperation関数は、Windowsでのマウスやキーボードを使ったファイル操作を行った場合と同様の動作を行うことが出来ます。
上で挙げたファイル削除方法は、ファイルが完全に削除されますが、SHFileOperation関数ではゴミ箱に移動させる削除が可能になります。
ただし以下の制約があります。
ネットワークドライブのファイル削除はゴミ箱に行かず完全削除される
ここではSHFileOperation関数でのごみ箱への移動方法を主に書いていますが、コピーや移動などの操作の場合も、Windowsの制約がSHFileOperation関数の挙動に引き継がれます。
例えば、Windowsでのファイルの削除は、Cドライブなどのローカルディスクにある場合とネットワークドライブにある場合とでは挙動が異なり、ローカルディスクの場合はゴミ箱への移動が可能ですが、ネットワークドライブの場合はゴミ箱を経由できずに完全削除しかできません。これはSHFileOperation関数を使った場合も同様です。
エクスプローラーを使って、ネットワークドライブ上のファイルを削除しようとすると、右クリックで削除した場合は「完全に削除しますか?」と聞かれ、「はい」を押すとゴミ箱に行かず削除されます。また、エクスプローラの削除メニューの「ゴミ箱に移動」はグレーアウトしており利用できません。これが、ローカルディスクであればゴミ箱への移動が可能になります。
一応、ネットワーク上のファイルをゴミ箱での削除を行うようにすることは可能ですが、ネットーワークドライブ側の共有設定だったり特殊なアプリを使う必要があったりと、設定のここをいじればOK、みたいな話ではありません。
そのため、以下のコードではローカルディスク上のファイルを削除した場合にゴミ箱に行きますが、ネットワークドライブ上のファイルを削除した場合はゴミ箱に行かず完全削除になります。
コード
SHFileOperation関数を利用するにはSHFileOperation関数自体のDeclare宣言と、SHFILEOPSTRUCT構造体の定義が必要です。
サンプルコードのSHFileOperation関数自体のDeclare宣言と、SHFILEOPSTRUCT構造体の定義はWin32API_PrtSafe.TXTの内容をそのまま引用しています。
SHFILEOPSTRUCT構造体には8つの変数がありますが、ゴミ箱への削除の場合はコードの通り4つを設定すればOKです。
定数もWin32API_PrtSafe.TXTの内容をそのまま引用していますが、使わない定数は無くても構いません。具体的には、FO_DELETE、FOF_ALLOWUNDO、FOF_NOCONFIRMATIONの3つのConstが書いてあればOKです。
利用している定数の説明ですが、定数FO_DELETEはファイルやフォルダの削除を行う際に指定します。注意点としてPで始まるPO_DELETEがありますが、こちらを使うとエラーになります。実行してもファイルが削除されずエラー87が発生する場合は、FO_DELETEではなく間違ってPO_DELETEを指定していないか確認してください。
FOF_ALLOWUNDOは取消情報の保持を許可します。ファイル削除の場合は、ゴミ箱への移動を行い、ゴミ箱から元に戻すことを意味します。
FOF_NOCONFIRMATIONはダイアログのボタンを「はい」を押した状態として扱います。ファイル削除の場合にFOF_NOCONFIRMATIONが無く、FOF_ALLOWUNDOしか指定されていない場合は、ファイルを削除することを確認するダイアログが表示されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
Const FO_MOVE = &H1 Const FO_COPY = &H2 Const FO_DELETE = &H3 Const FO_RENAME = &H4 Const FOF_MULTIDESTFILES = &H1 Const FOF_CONFIRMMOUSE = &H2 Const FOF_SILENT = &H4 ' don't create progress/report Const FOF_RENAMEONCOLLISION = &H8 Const FOF_NOCONFIRMATION = &H10 ' Don't prompt the user. Const FOF_WANTMAPPINGHANDLE = &H20 ' Fill in SHFILEOPSTRUCT.hNameMappings ' Must be freed using SHFreeNameMappings Const FOF_ALLOWUNDO = &H40 Const FOF_FILESONLY = &H80 ' on *.*, do only files Const FOF_SIMPLEPROGRESS = &H100 ' means don't show names of files Const FOF_NOCONFIRMMKDIR = &H200 ' don't confirm making any needed dirs Const PO_DELETE = &H13 ' printer is being deleted Const PO_RENAME = &H14 ' printer is being renamed Const PO_PORTCHANGE = &H20 ' port this printer connected to is being changed ' if this id is set, the strings received by ' the copyhook are a doubly-null terminated ' list of strings. The first is the printer ' name and the second is the printer port. Const PO_REN_PORT = &H34 ' PO_RENAME and PO_PORTCHANGE at same time. Type SHFILEOPSTRUCT hwnd As LongPtr wFunc As Long pFrom As String pTo As String fFlags As Integer fAnyOperationsAborted As Long hNameMappings As LongPtr lpszProgressTitle As String ' only used if FOF_SIMPLEPROGRESS End Type Declare PtrSafe Function SHFileOperation Lib "shell32.dll" Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long Sub SHFileOperationTest() Dim sPath As String '// ファイルパス Dim t As SHFILEOPSTRUCT '// ファイル操作構造体 Dim ret As Long '// 処理結果 '// 削除対象ファイルパスを設定 sPath = "C:\abc\abc.txt" '// 構造体設定 t.hwnd = Application.hwnd '// ウインドウハンドル t.wFunc = FO_DELETE '// 処理:削除 t.pFrom = sPath '// 処理対象:ファイルパス t.fFlags = FOF_ALLOWUNDO + FOF_NOCONFIRMATION '// ゴミ箱 '// ファイルをゴミ箱へ移動 ret = SHFileOperation(t) '// 削除失敗時 If ret <> 0 Then Debug.Print ret End If End Sub |