I have found one code snippet that successfully copies 1 file to one specific directory. However what I am trying to piece together is a way to copy one file into hundreds of subdirectories. I have also found code that recursively cycles through subfolders and allows you to take action upon the files in the subfolders. Surely there must be a mash up of these two codes that would allow me to copy the 1 file into numerous subdirectories.
If this is not possible I have working code for a command prompt.
Sub Copy_Certain_Files_In_Folder()
'This example copy all Excel files from FromPath to ToPath.
'Note: If the files in ToPath already exist it will overwrite
'existing files in this folder
Dim fso As Object
Dim FromPath As String
Dim ToPath As String
Dim FileExt As String
'FromPath = "C:\Users\Ron\Data" '<< Change
'ToPath = "C:\Users\Ron\Test" '<< Change
FileExt = "*.pdf" '<< Change
'You can use *.* for all files or *.doc for Word files
If Right(FromPath, 1) <> "\" Then
FromPath = FromPath & "\"
End If
Set fso = CreateObject("scripting.filesystemobject")
If fso.FolderExists(FromPath) = False Then
MsgBox FromPath & " doesn't exist"
Exit Sub
End If
If fso.FolderExists(ToPath) = False Then
MsgBox ToPath & " doesn't exist"
Exit Sub
End If
fso.CopyFile Source:=FromPath & FileExt, Destination:=ToPath
MsgBox "You can find the files from " & FromPath & " in " & ToPath
End Sub
Code that cycles through subfolders:
Dim FileSystem As Object
Dim HostFolder As String
HostFolder = "C:\"
Set FileSystem = CreateObject("Scripting.FileSystemObject")
DoFolder FileSystem.GetFolder(HostFolder)
Sub DoFolder(Folder)
Dim SubFolder
For Each SubFolder In Folder.SubFolders
DoFolder SubFolder
Next
Dim File
For Each File In Folder.Files
' Operate on each file
Next
End Sub
Any advice is welcome!
Try the following code:
'*****************************************************
' FUNCTION HEADER: Put_A_File_In_All_Subfolders
'
' Purpose: Looks for the specified file, and if it exists it
' puts the file in all subfolders of the target path.
'
' Inputs:
' blnFirstIteration: True / false for whether this is the first function call
' strFromPath As String: The path where the file to copy is located.
' strToPath As String: The path where the destination folder tree exists.
' strFileToCopy: The filename to copy.
'*****************************************************
Sub Put_A_File_In_All_Subfolders( _
blnFirstIteration As Boolean, _
strFromPath As String, _
strToPath As String, _
strFileToCopy As String)
Dim fso As Scripting.FileSystemObject
Set fso = New Scripting.FileSystemObject
Dim blnEverythingIsValid As Boolean
blnEverythingIsValid = True
'If this is the first run, check to make sure the initial file
'exists at that path, else throw error messages:
If blnFirstIteration Then
If Right(strFromPath, 1) <> "\" Then
strFromPath = strFromPath & "\"
End If
If fso.FolderExists(strFromPath) = False Then
MsgBox strFromPath & " doesn't exist"
blnEverythingIsValid = False
Else
If Not fso.FileExists(strFromPath & strFileToCopy) Then
MsgBox strFileToCopy & " doesn't exist in " & strFromPath
blnEverythingIsValid = False
End If
End If
If fso.FolderExists(strToPath) = False Then
MsgBox strToPath & " doesn't exist"
blnEverythingIsValid = False
End If
End If
If blnEverythingIsValid Then
If Right(strToPath, 1) <> "\" Then
strToPath = strToPath & "\"
End If
'Copy the file to the destination folder
fso.CopyFile (strFromPath & strFileToCopy), strToPath, True
'Run the sub recursively for each subfolder
Dim vntSubFolder As Variant
Dim currentFolder As Scripting.Folder
Set currentFolder = fso.GetFolder(strToPath)
'Check to see if there are subfolders
If currentFolder.SubFolders.Count > 0 Then
For Each vntSubFolder In currentFolder.SubFolders
'Dim fsoSubFolder As Scripting.Folder
'Set fsoSubFolder = currentFolder.SubFolders.item(vntSubFolder)
Dim strSubFolderPath As String
strSubFolderPath = vntSubFolder.Path
Put_A_File_In_All_Subfolders False, strFromPath, strSubFolderPath, strFileToCopy
Next vntSubFolder
End If
Else
Set fso = Nothing
Exit Sub
End If
Set fso = Nothing
End Sub
You can call it using:
Put_A_File_In_All_Subfolders True, "C:\PathWithFile\", "C:\RootDestinationFolder", "Filename.ext"
I mashed that up quickly, so please test before using widely...
Related
I found this code on another stack overflow post and it works well but the code prompts the user to select the file, can it be changed so that it automatically unzips all the files in the chosen directory?
Unzip folder with files to the chosen location
Sub Unzip()
Dim FSO As Object
Dim oApp As Object
Dim Fname As Variant
Dim FileNameFolder As Variant
Dim DefPath As String
Fname = Application.GetOpenFilename(filefilter:="Zip Files (*.zip), *.zip", _
MultiSelect:=False)
If Fname = False Then
'Do nothing
Else
'Destination folder
DefPath = "C:\test\" ' Change to your path / variable
If Right(DefPath, 1) <> "\" Then
DefPath = DefPath & "\"
End If
FileNameFolder = DefPath
' 'Delete all the files in the folder DefPath first if you want
' On Error Resume Next
' Kill DefPath & "*.*"
' On Error GoTo 0
'Extract the files into the Destination folder
Set oApp = CreateObject("Shell.Application")
oApp.Namespace(FileNameFolder).CopyHere oApp.Namespace(Fname).items
MsgBox "You find the files here: " & FileNameFolder
On Error Resume Next
Set FSO = CreateObject("scripting.filesystemobject")
FSO.deletefolder Environ("Temp") & "\Temporary Directory*", True
End If
End Sub
Now with an added loop as brax is great to point out that I can use this but still doesn't solve the issue of the user being prompted for which file to open
Sub Unzip5()
Dim FSO As Object
Dim oApp As Object
Dim Fname As Variant
Dim FileNameFolder As Variant
Dim DefPath As String
Dim StrFile As String
StrFile = Dir("Z:\G Thang\Excel & VBA\Extract\*.zip")
Do While Len(StrFile) > 0
Fname = Application.GetOpenFilename(filefilter:="Zip Files (*.zip), *.zip", _
MultiSelect:=False)
If Fname = False Then
'Do nothing
Else
'Destination folder
DefPath = "Z:\G Thang\Excel & VBA\Extract\" ' Change to your path / variable
If Right(DefPath, 1) <> "\" Then
DefPath = DefPath & "\"
End If
FileNameFolder = DefPath
' 'Delete all the files in the folder DefPath first if you want
' On Error Resume Next
' Kill DefPath & "*.*"
' On Error GoTo 0
'Extract the files into the Destination folder
Set oApp = CreateObject("Shell.Application")
oApp.Namespace(FileNameFolder).CopyHere oApp.Namespace(Fname).items
MsgBox "You find the files here: " & FileNameFolder
On Error Resume Next
Set FSO = CreateObject("scripting.filesystemobject")
FSO.deletefolder Environ("Temp") & "\Temporary Directory*", True
End If
Loop
End Sub
ok, I'm getting it! But my new code loops through the same file and keeps unzipping that one, maybe I can move it into another directory when I've finished unzipping it and then move onto the next one, i'll post the code below.
Sub Unzip99File()
Dim FSO As Object
Dim oApp As Object
Dim Fname As Variant
Dim FileNameFolder As Variant
Dim DefPath As String
Dim StrFile As String
StrFile = Dir("Z:\G Thang\Excel & VBA\Extract\*.zip")
'Fname = ("*.zip")
Do While Len(StrFile) > 0
Fname = ("*.zip")
If Fname = False Then 'Fname
'Do nothing
Else
'Destination folder
DefPath = "Z:\G Thang\Excel & VBA\Extract\" ' Change to your path / variable
' If Right(DefPath, 1) <> "\" Then
' DefPath = DefPath & "\"
' End If
FileNameFolder = DefPath
' 'Delete all the files in the folder DefPath first if you want
' On Error Resume Next
' Kill DefPath & "*.*"
' On Error GoTo 0
'Extract the files into the Destination folder
Set oApp = CreateObject("Shell.Application")
oApp.Namespace(FileNameFolder).CopyHere oApp.Namespace(DefPath & StrFile).items
On Error Resume Next
Set FSO = CreateObject("scripting.filesystemobject")
FSO.deletefolder Environ("Temp") & "\Temporary Directory*", True
End If
Loop
End Sub
I need to do the following:
Allow the user to select any number of files, in any format, and copy them to a new folder.
Create the destination folder if it doesn't exist. In this case, the folder name should be given by the content of the C2 & C3 cells (Range("C2").Value & Range("C3").Text & "\").
Private Sub CommandButton4_Click()
Dim strDirname As String
Dim strDefpath As String
Dim strPathname As String
Dim strFilename As String
Dim FSO
Dim sFile As FileDialog
Dim sSFolder As String
Dim sDFolder As String
strDirname = Range("C2").Value & Range("C3").Text
MkDir strDefpath & "\" & strDirname
strPathname = strDefpath & "\" & strDirname & "\" & strFilename
Set sFile = Application.FileDialog(msoFileDialogOpen)
sDFolder = strDirname & "\"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set FSO = New FileSystemObject
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
If Not .Show Then Exit Sub
Set xFolder = FSO.GetFolder(.SelectedItems(1))
For Each xFile In xFolder.Files
On Error Resume Next
xRow = Application.Match(xFile.Name, Range("A:A"), 0)
On Error GoTo 0
Next
End With
End Sub
I know the error is here...
Set xFolder = FSO.GetFolder(.SelectedItems(1))
...because I'm asking it to get a file, not a folder.
It is not very clear to me what you are trying to do but, if you intend to select a folder, you have to use it
Application.FileDialog (msoFileDialogFolderPicker)
instead of
Application.FileDialog (msoFileDialogFilePicker)
Your posted code shows so little resemblance to what you Q asks for, I've disregarded it.
This code follows the description. You may need to alter certain details to fully match your needs
Sub Demo()
Dim FilePicker As FileDialog
Dim DefaultPath As String
Dim DestinationFolderName As String
Dim SelectedFile As Variant
Dim DestinationFolder As Folder
Dim FSO As FileSystemObject
DefaultPath = "C:\Data" ' <~~ update to suit, or get it from somewhere else
' Validate Default Path
If Right$(DefaultPath, 1) <> Application.PathSeparator Then
DefaultPath = DefaultPath & Application.PathSeparator
End If
If Not FSO.FolderExists(DefaultPath) Then Exit Sub
' Get Destination Folder, add trailing \ if required
DestinationFolderName = Range("C2").Value & Range("C3").Value
If Right$(DestinationFolderName, 1) <> Application.PathSeparator Then
DestinationFolderName = DestinationFolderName & Application.PathSeparator
End If
Set FSO = New FileSystemObject
' Get reference to Destination folder, create it if required
If FSO.FolderExists(DefaultPath & DestinationFolderName) Then
Set DestinationFolder = FSO.GetFolder(DefaultPath & DestinationFolderName)
Else
Set DestinationFolder = FSO.CreateFolder(DefaultPath & DestinationFolderName)
End If
' File Selection Dialog
Set FilePicker = Application.FileDialog(msoFileDialogFilePicker)
With FilePicker
.AllowMultiSelect = True ' allow user to select multiple files
.InitialFileName = DefaultPath ' set initial folder for dialog
If .Show = False Then Exit Sub ' check if user cancels
For Each SelectedFile In .SelectedItems ' loop over selected files
If SelectedFile Like DefaultPath & "*" Then 'Optional: disallow browsing higher than default folder
FSO.CopyFile SelectedFile, DefaultPath & DestinationFolderName, True ' Copy file, overwrite is it exists
End If
Next
End With
End Sub
I want to copy specific file type(*.SLDDRW) from source to destination,in destination path we have lots of folders and sub-folders .in below code i am trying to walk on any sub folders but unfortunately it didn't work and didn't walk all sub-folders S.O can help me?
Sub copy_specific_files_in_folder()
Dim FSO As Object
Dim sourcePath As String
Dim destinationPath As String
Dim fileExtn As String
sourcePath = "C:\Users\6\"
destinationPath = "C:\Users\"
fileExtn = "*.SLDDRW"
If Right (sourcePath, 1) <> "\" Then
sourcePath = sourcePath & "\"
End If
Set FSO = CreateObject ("scripting.filesystemobject")
If FSO.FolderExists(sourcepath) = False Then
MsgBox sourcePath & " does not exist"
Exit Sub
End If
FSO.CopyFile Source:=sourcePath & fileExtn, Destination :=destinationPath
copy_files_from_subfolders
MsgBox "Your files have been copied from the sub-folders of " & sourcePath
End sub
sub copy_files_from_subfolders()
Dim FSO AS Object , fld As Object
Dim fsoFile As Object
Dim fsoFol As Object
sourcePath = "C:\Users\6\"
targetPath = "C:\Users\"
If Right (sourcePath , 1) <> "\" then sourcePath = sourcePath & "\"
Set FSO = createObject("Scripting.FileSystemObject")
Set fld = FSO.getFolder(sourcePath)
If FSO.FolderExists(fld) Then
For Each fsoFol In FSO.GetFolder(sourcePath).SubFolders
For Each fsoFile In fsoFol.Files
If Right (fsoFile, 6) = "sldprt" Then
fsoFile.Copy targetPath
End If
Next
Next
End If
Here's a function that will recursively search a folder and all subfolders for a specific extension and then copy found files to a specified destination:
Sub SearchFoldersAndCopy(ByVal arg_sFolderPath As String, _
ByVal arg_sDestinationFolder As String, _
ByVal arg_sExtension As String)
Dim oFSO As Object
Dim oFolder As Object
Dim oSubFolder As Object
Dim sTest As String
'Test if FolderPath exists
sTest = Dir(arg_sFolderPath, vbDirectory)
If Len(sTest) = 0 Then
MsgBox "Specified folder [" & arg_sFolderPath & "] doesn't exist. Please check spelling or create the directory."
Exit Sub
End If
'Test if Destination exists
sTest = Dir(arg_sDestinationFolder, vbDirectory)
If Len(sTest) = 0 Then
MsgBox "Specified destination [" & arg_sDestinationFolder & "] doesn't exist. Please check spelling or create the directory."
Exit Sub
End If
'FolderPath and Destination both exist, proceed with search and copy
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFolder = oFSO.GetFolder(arg_sFolderPath)
'Test if any files with the Extension exist in directory and copy if one or more found
sTest = Dir(oFolder.Path & Application.PathSeparator & "*." & arg_sExtension)
If Len(sTest) > 0 Then oFSO.copyfile oFolder.Path & Application.PathSeparator & "*." & arg_sExtension, arg_sDestinationFolder
'Recursively search subfolders
For Each oSubFolder In oFolder.SubFolders
SearchFoldersAndCopy oSubFolder.Path, arg_sDestinationFolder, arg_sExtension
Next oSubFolder
End Sub
Here's an example of how to call it:
Sub tgr()
Dim sStartFolder As String
Dim sDestination As String
Dim sExtension As String
sStartFolder = "C:\Test"
sDestination = "C:\Output\" '<-- The ending \ may be required on some systems
sExtension = "SLDDRW"
SearchFoldersAndCopy sStartFolder, sDestination, sExtension
End Sub
I have a function that works to search through the subfolders of a given directory and finds the file name I need. However, it only goes through one set of subfolders, finding the first one and then going through to the end of the subfolders. However, it then just stops. I have looked through various threads and tried different options but no joy.
I need it to then loop back to the root directory (say, sPath=C:\Windows) and look at the next subfolder, go through that whole directory, come back to the root folder, and so on until it finds the file it needs. I cannot seem to get that part to work, hoping someone here can help point out what I am missing. I am trying to keep this set at a higher level root folder rather than have to start lower in in the directory to get it to work. Here is the function:
Function recurse(sPath As String, strname As String, strName3 As String)
Dim FSO As New FileSystemObject
Dim myFolder As Scripting.Folder
Dim mySubFolder As Scripting.Folder
Dim myFile As Scripting.file
Dim strJDFile As String
Dim strDir As String
Dim strJDName As String
Set myFolder = FSO.GetFolder(sPath)
' strName = Range("a2").Offset(0, 3)
strName3 = Replace(strName3, "/", " ")
For Each mySubFolder In myFolder.SubFolders
Debug.Print " mySubFolder: " & mySubFolder
For Each myFile In mySubFolder.Files
If "*" & myFile.Name & "*" Like "*" & strName3 & "*" Then
strJDName = myFile.Name
strDir = mySubFolder & "\"
strJDFile = strDir & strJDName
recurse = strJDFile
Exit Function
Else
Debug.Print " myFile.name: " & myFile.Name
End If
Next
recurse = recurse(mySubFolder.Path, strname, strName3)
Next
End Function
Here is a routine you may be able to adapt to your use, if you are running Excel under Windows.
Pick a base folder using the Excel folder picker routine
Enter a file name mask (eg: Book1.xls*)
Uses the Dir command window command to check all the folders and subfolders for files that start with Book1.xls
The results of the command are written to a temporary file (which is deleted at the end of the macro)
There is a way to write it directly to a VBA variable, but I see too much screen flicker when I've done that.
The results are then collected into a vba array, and written to a worksheet, but you can do whatever you want with the results.
Option Explicit
'set references to
' Microsoft Scripting Runtime
' Windows Script Host Object model
Sub FindFile()
Dim WSH As WshShell, lErrCode As Long
Dim FSO As FileSystemObject, TS As TextStream
Dim sTemp As String
Dim sBasePath As String
Dim vFiles As Variant, vFullList() As String
Dim I As Long
Dim sFileName As String
sTemp = Environ("Temp") & "\FileList.txt"
'Select base folder
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
If .Show = -1 Then 'if OK is pressed
sBasePath = .SelectedItems(1)
Else
Exit Sub
End If
End With
'File name mask
sFileName = InputBox("Entire File Mask", "File Finder")
Set WSH = New WshShell
lErrCode = WSH.Run("CMD /c dir """ & sBasePath & "\*" & sFileName & """ /A-D /B /S > " & sTemp, xlHidden, True)
If Not lErrCode = 0 Then
MsgBox "Problem Reading Directory" & _
vbLf & "Error Code " & lErrCode
Exit Sub
End If
Set FSO = New FileSystemObject
Set TS = FSO.OpenTextFile(sTemp, ForReading, False, TristateFalse)
vFiles = Split(TS.ReadAll, vbLf)
TS.Close
FSO.DeleteFile sTemp
Set FSO = Nothing
Set WSH = Nothing
ReDim vFullList(1 To UBound(vFiles), 1 To 1)
For I = 1 To UBound(vFiles)
vFullList(I, 1) = vFiles(I)
Next I
Dim rDest As Range
Set rDest = Cells(1, 2).Resize(UBound(vFullList, 1), UBound(vFullList, 2))
With rDest
.EntireColumn.Clear
.Value = vFullList
.EntireColumn.AutoFit
End With
End Sub
I have created a VBA userform, by manipulating code i found from a website, for coworkers to transfer files from selected folder from one listbox to another folder in a second listbox. The folders that populate in the listboxes change daily. It works fine for both listboxes with fmSingleSelect but i cannot figure out how to run it properly with a fmMultiSelect property on the second listbox (Yes, i changed the property to fmMultiSelect on the second listbox).
It would save time to be able to multiselect the projects folder and run the transfers simultaneously.
Below is the code for single select and commented out some code i was working with for multiselect
Also an image is below code
Thanks
Private Sub CmdBtn_transfer_Click()
Dim FSO As Object
Dim FromPath As String
Dim ToPath As String
Dim FileExt As String
Dim Value As String
Dim i As Integer
FromPath = "C:\Users\us-lcn-dataprep03\Desktop\Production files\" & (Me.ListBox1) '<< Change
ToPath = "\\bego.hb\MED_PRODUCTION\USA_Datapreparation\" & (Me.ListBox2) '<< Change
' For i = 0 To ListBox2.Items.Count - 1
' If ListBox2.Items(i).Selected = True Then
' Val = ListBox2.Items(i).Value
' End If
'Next i
FileExt = "*.sli*" '<< Change
If Right(FromPath, 1) <> "\" Then
FromPath = FromPath & "\"
End If
Set FSO = CreateObject("scripting.filesystemobject")
If FSO.FolderExists(FromPath) = False Then
MsgBox FromPath & " doesn't exist"
Exit Sub
End If
If FSO.FolderExists(ToPath) = False Then
MsgBox ToPath & " doesn't exist"
Exit Sub
End If
FSO.CopyFile Source:=FromPath & FileExt, Destination:=ToPath
MsgBox "You can find the files from " & FromPath & " in " & ToPath
End Sub
Userform list boxes
The following code is a "minimal change" alteration to your code so that it should handle copying the files from one directory to multiple directories:
Private Sub CmdBtn_transfer_Click()
Dim FSO As Object
Dim FromPath As String
Dim ToPath As String
Dim FileExt As String
Dim Value As String
Dim i As Integer
FromPath = "C:\Users\us-lcn-dataprep03\Desktop\Production files\" & (Me.ListBox1) '<< Change
FileExt = "*.sli*" '<< Change
If Right(FromPath, 1) <> "\" Then
FromPath = FromPath & "\"
End If
Set FSO = CreateObject("scripting.filesystemobject")
If FSO.FolderExists(FromPath) = False Then
MsgBox FromPath & " doesn't exist"
Exit Sub
End If
For i = 0 To ListBox2.ListCount - 1
If ListBox2.Selected(i) Then
ToPath = "\\bego.hb\MED_PRODUCTION\USA_Datapreparation\" & (Me.ListBox2.List(i)) '<< Change
If Right(ToPath, 1) <> "\" Then
ToPath = ToPath & "\"
End If
If FSO.FolderExists(ToPath) = False Then
MsgBox ToPath & " doesn't exist"
Exit Sub
End If
FSO.CopyFile Source:=FromPath & FileExt, Destination:=ToPath
MsgBox "You can find the files from " & FromPath & " in " & ToPath
End If
Next i
End Sub
All I did was move your commented out code re looping through the selected items in ListBox2 so that it was wrapped around the parts of the code which are affected by the ToPath. (Note: The MsgBox is within the loop - you may wish to move it outside the loop but, if you do, you may want to make the message more generic - e.g. "Your files have been moved as requested".)
I also corrected some mistakes in your commented code:
ListBox2.Items.Count should be ListBox2.ListCount
ListBox2.Items(i).Selected should be ListBox2.Selected(i)
ListBox2.Items(i).Value should be ListBox2.List(i)