135

Using VBA, how can I:

  1. test whether a file exists, and if so,
  2. delete it?
ZygD
  • 22,092
  • 39
  • 79
  • 102
inglesp
  • 3,299
  • 9
  • 32
  • 30

9 Answers9

207

1.) Check here. Basically do this:

Function FileExists(ByVal FileToTest As String) As Boolean
   FileExists = (Dir(FileToTest) <> "")
End Function

I'll leave it to you to figure out the various error handling needed but these are among the error handling things I'd be considering:

  • Check for an empty string being passed.
  • Check for a string containing characters illegal in a file name/path

2.) How To Delete a File. Look at this. Basically use the Kill command but you need to allow for the possibility of a file being read-only. Here's a function for you:

Sub DeleteFile(ByVal FileToDelete As String)
   If FileExists(FileToDelete) Then 'See above          
      ' First remove readonly attribute, if set
      SetAttr FileToDelete, vbNormal          
      ' Then delete the file
      Kill FileToDelete
   End If
End Sub

Again, I'll leave the error handling to you and again these are the things I'd consider:

  • Should this behave differently for a directory vs. a file? Should a user have to explicitly have to indicate they want to delete a directory?

  • Do you want the code to automatically reset the read-only attribute or should the user be given some sort of indication that the read-only attribute is set?


EDIT: Marking this answer as community wiki so anyone can modify it if need be.

Max Makhrov
  • 17,309
  • 5
  • 55
  • 81
Onorio Catenacci
  • 14,928
  • 14
  • 81
  • 132
60

An alternative way to code Brettski's answer, with which I otherwise agree entirely, might be

With New FileSystemObject
    If .FileExists(yourFilePath) Then
        .DeleteFile yourFilepath
    End If
End With

Same effect but fewer (well, none at all) variable declarations.

The FileSystemObject is a really useful tool and well worth getting friendly with. Apart from anything else, for text file writing it can actually sometimes be faster than the legacy alternative, which may surprise a few people. (In my experience at least, YMMV).

Mike Woodhouse
  • 51,832
  • 12
  • 88
  • 127
  • 7
    Using this syntax without declaring a file scripting object, must add reference for Microsoft Scripting Runtime, else: Dim fs As New Scripting.FileSystemObject – pghcpa Mar 04 '15 at 05:13
  • 6
    you also need to reference the scripting library. see here: http://stackoverflow.com/questions/3233203/how-do-i-use-filesystemobject-in-vba – ekkis May 14 '15 at 00:06
  • Since there's no variable to set to Nothing, is there a risk the FileSystemObject will remain in memory, causing a leak or other issue? – johny why Sep 23 '16 at 22:10
  • No, it will be discarded after the "End With". Since it is not assigned to a variable the effect is similar to the object having been assigned to a variable that has been set to "Nothing". – TCN Jan 01 '17 at 04:09
17

I'll probably get flamed for this, but what is the point of testing for existence if you are just going to delete it? One of my major pet peeves is an app throwing an error dialog with something like "Could not delete file, it does not exist!"

On Error Resume Next
aFile = "c:\file_to_delete.txt"
Kill aFile
On Error Goto 0
return Len(Dir$(aFile)) > 0 ' Make sure it actually got deleted.

If the file doesn't exist in the first place, mission accomplished!

JohnFx
  • 34,542
  • 18
  • 104
  • 162
  • 4
    You raise a good point but, like most things, I think it would depend on context and sometimes simply having a "File Exists" function is handy apart from deletion. – Onorio Catenacci Sep 16 '08 at 11:11
  • 3
    +1: maybe the user of the application wants to be asked before removing a file: for instance, using `ActiveWorkbook.SaveCopyAs` is not able to overwrite, so you first have to remove existing file with same filename. – Joël Nov 07 '13 at 14:38
  • but you should never use `On Error Resume Next`, or so i've been told :D Of course, that's ridiculous advice, and your answer is correct. – johny why Sep 23 '16 at 17:08
  • The `Len(dir(...))` part isn't SOLELY to check for existence. It is also **checking if the file is HIDDEN** because a hidden file will return an empty string even if it exists (and you won't be able to delete it): `Dir(hiddenFile) = ""`. Hence, the part `SetAttr FileToDelete, vbNormal`eloquently takes care of this for you. – elektrykalAJ Feb 07 '19 at 00:37
13

The following can be used to test for the existence of a file, and then to delete it.

Dim aFile As String
aFile = "c:\file_to_delete.txt"
If Len(Dir$(aFile)) > 0 Then
     Kill aFile
End If 
Rich Adams
  • 26,096
  • 4
  • 39
  • 62
  • 3
    I know this question and response are old, just thought I'd add that using Len() to test strings (and functions that return strings) seems to be faster than literal string comparisons in VBA. – JimmyPena Nov 18 '11 at 16:52
  • 9
    The reason that `Len()` (and `LenB()`, which is even faster) are faster than string comparison is that in memory, VB strings are preceded by their length. Len/LenB just pull the length from that memory location, they don't have to iterate through the string to know its length. On the other hand, using string comparison has much more work to do. Additionally, avoid using `""` in VB as it always allocates a new string. Use `vbNullString` instead as it is a constant and does not uses more memory. – Renaud Bompuis Nov 12 '14 at 02:25
8

In VB its normally Dir to find the directory of the file. If it's not blank then it exists and then use Kill to get rid of the file.

test = Dir(Filename)
If Not test = "" Then
    Kill (Filename)
End If
ZygD
  • 22,092
  • 39
  • 79
  • 102
Leo Moore
  • 2,118
  • 2
  • 19
  • 21
6

set a reference to the Scripting.Runtime library and then use the FileSystemObject:

Dim fso as New FileSystemObject, aFile as File

if (fso.FileExists("PathToFile")) then
    aFile = fso.GetFile("PathToFile")
    aFile.Delete
End if
Brettski
  • 19,351
  • 15
  • 74
  • 97
  • 1
    I use FileSystemObject method too, as Kill is unable to delete files/folders with diacritis – mauek unak Oct 21 '15 at 14:35
  • This is method I use.. Someone who implements this wants to use error checking and DisplayAlerts = false. (The file won't delete if it's in use, so must have error trap) – Gregg Burns Oct 25 '19 at 19:39
4

Here's a tip: are you re-using the file name, or planning to do something that requires the deletion immediately?

No?

You can get VBA to fire the command DEL "C:\TEMP\scratchpad.txt" /F from the command prompt asynchronously using VBA.Shell:

Shell "DEL " & chr(34) & strPath & chr(34) & " /F ", vbHide

Note the double-quotes (ASCII character 34) around the filename: I'm assuming that you've got a network path, or a long file name containing spaces.

If it's a big file, or it's on a slow network connection, fire-and-forget is the way to go. Of course, you never get to see if this worked or not; but you resume your VBA immediately, and there are times when this is better than waiting for the network.

Nigel Heffernan
  • 4,636
  • 37
  • 41
2

You can set a reference to the Scripting.Runtime library and then use the FileSystemObject. It has a DeleteFile method and a FileExists method.

See the MSDN article here.

Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
0

A shorter version of the first solution that worked for me:

Sub DeleteFile(ByVal FileToDelete As String)
   If (Dir(FileToDelete) <> "") Then
      ' First remove readonly attribute, if set
      SetAttr FileToDelete, vbNormal
      ' Then delete the file
      Kill FileToDelete
   End If
End Sub
Claudio
  • 21
  • 4