VBA - Trouble with Loop Structure for File Searching and Copying - vba

I'm trying to develop a macro on one of my spreadsheets that will take the value of Column B (2502-13892-33 for example), starting at Row 3, and search the source folder listed in column A for that file (using Wildcards before and after the value in column B. Once it finds that file, it needs to use FileCopy to copy the file into the Destination Folder listed in Column C, but only after renaming the file in the form of "Column E"_"Original Filename (A252_2502-13892-33 for example).
I think I have worked out the code to make this work because when I tested it, it functioned exactly like I expected it to, found the file, copied it to the new destination with the PREFIX from column E and the underscore added to the filename. The problem is that it just stops after the first file, which leads me to believe something is wrong with the structure of my loop.
My code is as follows:
Sub MoveFiles()
Dim SourcePath As String
Dim DestPath As String
Dim PartNum As String
Dim PLISN As String
Dim LastRow As Long
Dim i As Long
Dim filename As String
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
For i = 3 To LastRow
PLISN = Cells(i, "E").Value
PartNum = Cells(i, "B").Value
If Right(Cells(i, "A").Value, 1) <> Application.PathSeparator Then
SourcePath = Cells(i, "A").Value & Application.PathSeparator
Else
SourcePath = Cells(i, "A").Value
End If
If Right(Cells(i, "C").Value, 1) <> Application.PathSeparator Then
DestPath = Cells(i, "C").Value & Application.PathSeparator
Else
DestPath = Cells(i, "C").Value
End If
If Dir$(SourcePath & "*" & PartNum & "*") = "" Then
Cells(i, "D").Value = "Source file does not exist."
ElseIf Dir$(DestPath & PLISN & "_" & "*" & PartNum & ".pdf") <> "" Then
Cells(i, "D").Value = "File already exists."
Else
filename = Dir$(SourcePath & "*" & PartNum & "*" & ".pdf")
'Copy the file
FileCopy SourcePath & filename, DestPath & PLISN & "_" & filename
Cells(i, "D").Value = "File Copied to new location"
End If
Next i
End Sub

I had accidentally left my DestinationPath blank for the 2nd and 3rd lines of the excel sheet. That was what was giving me just the "\" as the destination path. Seems to be working properly now.
As someone mentioned below in one of the comments, stepping through my code in the debugger was extremely helpful to solving this problem. My final code has some structural changes, in that I no longer have columns for SourcePath and DestPath, and instead use a folder dialog box to have the user select both of those.
The code for selecting my Source and Destination Folders:
Sub SourceFolder()
Dim lCount As Long
Dim rCount As Long
SourcePath = vbNullString
DestPath = vbNullString
With Application.FileDialog(msoFileDialogFolderPicker)
.InitialFileName = OpenAt
.Title = "Source Path"
.Show
For lCount = 1 To .SelectedItems.Count
SourcePath = .SelectedItems(lCount)
MsgBox (SourcePath)
Next lCount
End With
With Application.FileDialog(msoFileDialogFolderPicker)
.InitialFileName = OpenAt
.Title = "Destination Path"
.Show
For rCount = 1 To .SelectedItems.Count
DestPath = .SelectedItems(rCount)
MsgBox (DestPath)
Next rCount
End With
End Sub
The code for actually going out to the SourcePath, searching for the filename located in Column A (including with wildcards before and after), copying it to the DestinationPath, and renaming it with ColumnB's Value, followed by an underscore, and then ColumnA's Value is as follows:
Option Explicit
Public SourcePath As String
Public DestPath As String
Dim PartNum As String
Dim PLISN As String
Sub MoveFiles()
Dim LastRow As Long
Dim i As Long
Dim filename As String
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
For i = 3 To LastRow
PLISN = Cells(i, "B").Value
PartNum = Cells(i, "A").Value
If Right(SourcePath, 1) <> Application.PathSeparator Then
SourcePath = SourcePath & Application.PathSeparator
Else
SourcePath = SourcePath
End If
If Right(DestPath, 1) <> Application.PathSeparator Then
DestPath = DestPath & Application.PathSeparator
Else
DestPath = DestPath
End If
If Dir$(SourcePath & "*" & "*" & PartNum & "*") = "" Then
Cells(i, "C").Value = "Source file does not exist."
ElseIf Dir$(DestPath & PLISN & "_" & "*" & PartNum & "*" & ".pdf") <> "" Then
Cells(i, "C").Value = "File already exists."
Else
filename = Dir$(SourcePath & "*" & PartNum & "*" & ".pdf")
'Copy the file
FileCopy SourcePath & filename, DestPath & PLISN & "_" & filename
Cells(i, "C").Value = "File Copied to new location"
End If
Next i
End Sub

Related

How can I delete a file based on cell value?

I'm having trouble deleting a file based on cell value.
I get an error message on the line with the Kill command below:
Kill path & r.Offset(1, -4) & "\" & r.Offset(1, -3)
Any ideas?
Sub INACTIVE_files()
Const path = "C:\Users\NikolouzosD\AppData\Local\Temp\vbakillfunction\"
Dim r As Range
Dim x As Integer
Set r = Cells(1, 5)
Do Until r = ""
If UCase(r.value) = "INACTIVE" Then
Kill path & r.Offset(1, -4) & "\" & r.Offset(1, -3)
End If
Set r = r.Offset(1, 0)
Loop
End Sub
The code starts from cell E1 and looks for INACTIVE files in the same column, until there's no more files to look for.
Then, it checks the folder name (Column A), combines it with the Cube (Column B)
and puts both of them in a path:
path = "C:\Users\NikolouzosD\AppData\Local\Temp\vbakillfunction\"
so for example:
for cell E2 which is INACTIVE, the path should be:
C:\Users\NikolouzosD\AppData\Local\Temp\vbakillfunction\WPO 17 02 04 3MMT All Periods\BG023104.txt
It then deletes the INACTIVE files (Cubes) from the appropriate folder.
Wrap your path in double quotes to avoid issues with spaces in filenames and folders.
Even better is to put the path in a string variable so you can debug it easily
Outside your loop:
Dim strPath As String
Inside your if block:
strPath = """" & path & r.Offset(1,-4) & "\" & r.Offset(1,-3) & """"
Debug.Print strPath ' Ctrl-G to view results
Kill strPath
EDIT - add a check for file before deleting
Under Tools | References
Add a reference to Windows Script Hosting
Then at top of sub code add
Dim fso as New FileSystemObject
Replace your Kill command with a check for existence
If fso.FileExists(strPath) Then
Kill strPath
Else
Msgbox "File Doesn't Exist: " & strPath
End If
UPDATED FOR CONTINUE TO NEXT FILE
Change loop to be:
Do Until r = ""
If UCase(r.value) = "INACTIVE" AND fso.FileExists(strPath) Then
Kill strPath
End If
Set r = r.Offset(1, 0)
Loop
It works!
I've commented out some parts of the code that were used for checking if a file exists.
Sub delete_INACTIVE_files()
Const path = "C:\Users\Dn\AppData\Local\Temp\vbakillfunction\"
Dim r As Range
Set r = Cells(1, 5)
Do Until r = ""
If UCase(r.Value) = "INACTIVE" Then
If Dir(path & r.Offset(0, -4) & "\" & r.Offset(0, -3) & ".txt") <> "" Then 'Does the file exist?
'MsgBox "file" & path & r.Offset(0, -4) & "\" & r.Offset(0, -3) & ".txt" & " exists"
Kill path & r.Offset(0, -4) & "\" & r.Offset(0, -3) & ".txt"
'Else
'MsgBox "file" & path & r.Offset(0, -4) & "\" & r.Offset(0, -3) & ".txt" & " not here"
End If
End If
Set r = r.Offset(1, 0)
Loop
End Sub

Getting folder path using msoFileDialogFolderPicker

I have a code which picks file from a SourcePath then renames it and saves in DestPath. The code is working fine with hardcoded folder path for SourcePath (SourcePath = "C:\Invoices\Raw invoices"). however, it's not able to capture and retain the folderpath with msoFileDialogFolderPicker function. The code is unable to find the file in sourcepath and gives error as programmed.
Here is the sample data.
Here is the code I am using.
Sub Rename_invoices()
Dim SourcePath As String, DestPath As String, Fname As String, NewFName As String
Dim i As Long
SourcePath = GetFolder("C:\")
DestPath = "C:\Dunning Temp\"
For i = 1 To Cells(Rows.Count, "A").End(xlUp).Row
If Not IsEmpty(Range("A" & i).Value) Then
NewFName = Range("B" & i).Value
'Search for the first file containing the string in column A
Fname = Dir(SourcePath & "*" & Range("A" & i).Value & "*")
If Fname <> vbNullString Then
FileCopy SourcePath & Fname, DestPath & NewFName
Else
MsgBox Range("A" & i).Value & " dosen't exist in the folder"
End If
End If
Next i
ActiveSheet.Close = False
End Sub
Function GetFolder(strPath As String) As String
Dim fldr As FileDialog
Dim sItem As String
Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
With fldr
.Title = "Select a Folder"
.AllowMultiSelect = False
.InitialFileName = strPath
If .Show <> -1 Then GoTo NextCode
sItem = .SelectedItems(1)
End With
NextCode:
GetFolder = sItem
Set fldr = Nothing
End Function
The path your GetFolder Function returns will not end with a backslash \. As is, the pathname argument you pass to Dir in Fname = Dir(SourcePath & "*" & Range("A" & i).Value & "*") will be incorrect.
So change SourcePath = GetFolder("C:\") to SourcePath = GetFolder("C:\") & "\", or add a trailing backslash within your GetFolder function.
As #Mistella pointed out, using Debug.Print would easily highlight this issue.

Rename files in folder vba

I have code to find a filename from column A and rename files as in column B in a source folder and then copy to a new folder.
The code is as below.
Sub Rename_Files()
Dim SourcePath, DestPath, Fname, NewFName
SourcePath = "C:\Invoices\"
DestPath = "C:\Invoices\Renamed\"
For i = 1 To 100
Fname = Range("A" & i).Value
NewFName = Range("B" & i).Value
If Not Dir(SourcePath & Fname, vbDirectory) = vbNullString Then
FileCopy SourcePath & Fname, DestPath & NewFName
Else
MsgBox (Fname & " Not Exists in Folder")
End If
Next i
End Sub
The problem is that The filenames in the source directory are long like 'INVOICEDUMP_OFND_4294819_ABC Corp.pdf' and hundreds of like this.
I want to find the file containing 4294819 (from column A) in the name and then replace the name with only 'INV 4294819.pdf' (as mentioned in column B).
Thanks
Unless my DOS skills are extremely rusty, you should be able to use
Sub Rename_Files()
Dim SourcePath As String, DestPath As String, Fname As String, NewFName As String
Dim i As Long
SourcePath = "C:\Invoices\"
DestPath = "C:\Invoices\Renamed\"
For i = 1 To 100
If Not IsEmpty(Range("A" & i).Value) Then
NewFName = Range("B" & i).Value
'Search for the first file containing the string in column A
Fname = Dir(SourcePath & "*" & Range("A" & i).Value & "*")
If Fname <> vbNullString Then
FileCopy SourcePath & Fname, DestPath & NewFName
Else
MsgBox Range("A" & i).Value & " Not Exists in Folder"
End If
End If
Next i
End Sub
This assumes that column A has entries such as 4294819 and that the corresponding entry in column B is something like INV 4294819.pdf.

Accessing files from external hard drive

I have files stored on a WD elements hard drive. On occasions I need to copy files from here onto my pc. When I tested the following macro using both the source and destination folders on the c: drive it works fine. However when I changed the source to the external drive (I:\history\june) it says the files do not exist. How can I access the external drive? Any guidance would be welcome.
Thanks, willi
Sub CopyFiles()
Dim iRow As Integer
Dim sSourcePath As String
Dim sDestinationPath As String
Dim sFileType As String
Dim bContinue As Boolean
bContinue = True
iRow = 2
sSourcePath = "C:\Users\admin\documents\Test1\"
sDestinationPath = "C:\Users\admin\documents\Test2\"
sFileType = ".pdf"
While bContinue
If Len(Range("B" & CStr(iRow)).Value) = 0 Then
MsgBox "Files Copied"
bContinue = False
Else
If Len(Dir(sSourcePath & Range("B" & CStr(iRow)).Value & sFileType)) = 0 Then
Range("C" & CStr(iRow)).Value = "File Does Not Exist"
Range("C" & CStr(iRow)).Font.Bold = True
Else
Range("C" & CStr(iRow)).Value = "File Copied"
Range("C" & CStr(iRow)).Font.Bold = False
If Trim(sDestinationPath) <> "" Then
Dim objFSO
Set objFSO = CreateObject("scripting.filesystemobject")
If objFSO.FolderExists(sDestinationPath) = False Then
MsgBox "The destination folder " & sDestinationPath & " Does Not Exists"
Exit Sub
End If
objFSO.CopyFile Source:=sSourcePath & Range("B" & CStr(iRow)).Value & _
sFileType, Destination:=sDestinationPath
End If
End If
End If
iRow = iRow + 1
Wend
End Sub

Excel copy from file to file macro not working

I have to copy data from multiple excel files named with numbers (1.xlsx, 2.xlsx, 3.xlsx, etc). I wrote this macro. It runs. But no copy happens, the main workbook in which I ran the macro remains empty.
Sub filecopy()
' The macro is running in the main file, which I saved as .xlsm
' This main.xlsm is in the same folder as the files from which I copy the data
Dim Filename As String, Pathname As String,xx as Double
Activesheet.Usedrange.Clear 'I delete the current contents of the sheet
Pathname = ActiveWorkbook.Path
Filename = Dir(Pathname & "*.xlsx")
xx = 1 'the first column where the contents of the first file goes
Do While Len(Filename) > 0
Cells(1, xx).Formula = "='[" & Filename & "]Sheet1'!A1"
Cells(2, xx).Formula = "='[" & Filename & "]Sheet1'!B2"
Cells(3, xx).Formula = "='[" & Filename & "]Sheet1'!C3"
xx = xx + 1 'next file next column
Filename = Dir()
Loop
ActiveSheet.UsedRange.Value = ActiveSheet.UsedRange.Value 'every formula goes to value
MsgBox "Work Complete", vbInformation
End Sub
There are 2 errors in your code:
1. \ is missing -> filename is empty
Replace Filename = Dir(Pathname & "*.xlsx") with Filename = Dir(Pathname & "\*.xlsx")
2. the formula is not correct -> not complete filename
Change your formulas e.g. Cells(1, xx).Formula = "='[" & Filename & "]Sheet1'!A1" with this Cells(1, xx).Formula = "='" & Pathname & "\[" & Filename & "]Sheet1'!A1"
What about a solution like this:
Pathname = ActiveWorkbook.Path 'Be sure is the rigth path
Filename = Dir(Pathname & "\*.xlsx") 'I've addedd a "\"
xx = 1
Do While Len(Filename) > 0
If Filename <> ThisWorkbook.Name Then
Set mFile = Workbooks.Open(Pathname & "\" & Filename)
Else
GoTo NextFile
End If
With mFile.ActiveSheet 'Use the sheet you need here
Cells(1, xx) = .Cells(1, 1).Value
Cells(2, xx) = .Cells(2, 1).Value
Cells(3, xx) = .Cells(3, 1).Value
End With
xx = xx + 1 'next file next column
Application.DisplayAlerts = False
mFile.Close savechanges:=False
Application.DisplayAlerts = True
Set mFile = Nothing
NextFile:
Filename = Dir()
Loop