Get file names from folder and subfolder function change - excel

i have this code below to get files names from a specific folder and it works great. i like how is transposes the file names it works really well with how i do my work.
what i want to change is to have it also return the file names with in the subfolders to. but carry on transposing it accrss my work sheet.
Thank you.
Function GetFileNames6(ByVal FolderPath As String) As Variant
Dim Result As Variant
Dim i As Integer
Dim MyFile As Object
Dim MyFSO As Object
Dim myFolder As Object
Dim MyFiles As Object
Set MyFSO = CreateObject("Scripting.FileSystemObject")
Set myFolder = MyFSO.GetFolder(FolderPath)
Set MyFiles = myFolder.Files
ReDim Result(1 To MyFiles.Count)
i = 1
o = 1
For Each MyFile In MyFiles
Result(i) = MyFile.name & " " & MyFile.DateCreated
i = i + 1
Next MyFile
GetFileNames6 = Result
End Function

Return File Names From All Folders and Subfolders
Issues
Files containing 'non-standard' characters like e.g. žćčšđ will be returned by the ArrFilePaths function using the WScript Host but will not be found by the FileSystemObject object (nor the Dir function) hence the complications in the GetFileNames6function. If you have such characters in your file- or folder names, you can ask another question.
I've used something like Dim Arr() As String: Arr = Split("") to get an 'empty' string array in both functions. Not sure if that's the ideal way since I've never seen it done before.
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Tests the 'GetFileNames6' function.
' Calls: GetFileNames6
' ArrFilePaths
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub GetFileNames6TEST()
Const FolderPath As String = "C:\Test\"
Dim NamesDates() As String: NamesDates = GetFileNames6(FolderPath)
If UBound(NamesDates) = -1 Then
Debug.Print "No files found."
Exit Sub
End If
Debug.Print Join(NamesDates, vbLf)
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns a zero-based string array containing the concatenated
' names and dates ('DateCreated') from a given zero-based string
' array containing file paths.
' Calls: ArrFilePaths.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function GetFileNames6( _
ByVal FolderPath As String, _
Optional ByVal Delimiter As String = " ") _
As String()
Const ProcName As String = "GetFileNames6"
On Error GoTo ClearError
' Ensuring that a string array is passed if an error occurs.
GetFileNames6 = Split("") ' LB = 0 , UB = -1
Dim FilePaths() As String: FilePaths = ArrFilePaths(FolderPath)
'Debug.Print Join(FilePaths, vbLf)
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
Dim fsoFile As Object
Dim n As Long ' Files Count
Dim fCount As Long ' Found Files Count
For n = 0 To UBound(FilePaths)
If fso.FileExists(FilePaths(n)) Then
Set fsoFile = fso.GetFile(FilePaths(n))
FilePaths(fCount) = fsoFile.Name & Delimiter & fsoFile.DateCreated
fCount = fCount + 1
Else ' happens if not 'standard characters' (character map?)
Debug.Print "Not found: " & FilePaths(n)
End If
Next n
If fCount < n Then
ReDim Preserve FilePaths(0 To fCount - 1)
'Debug.Print Join(FilePaths, vbLf)
Debug.Print "Initially found files: " & n
Debug.Print "Finally found files: " & fCount
End If
GetFileNames6 = FilePaths
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "' Run-time error '" _
& Err.Number & "':" & vbLf & " " & Err.Description
Resume ProcExit
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns the file paths of the files in a folder in an array.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function ArrFilePaths( _
ByVal FolderPath As String, _
Optional ByVal FilePattern As String = "*.*", _
Optional ByVal DirSwitches As String = "/s/b/a-d") _
As String()
Const ProcName As String = "ArrFilePaths"
On Error GoTo ClearError
' Ensuring that a string array is passed if an error occurs.
ArrFilePaths = Split("") ' LB = 0 , UB = -1
Dim pSep As String: pSep = Application.PathSeparator
If Right(FolderPath, 1) <> pSep Then FolderPath = FolderPath & pSep
Dim ExecString As String ' '%comspec%' or 'cmd.exe' ?
ExecString = "%comspec% /c Dir """ _
& FolderPath & FilePattern & """ " & DirSwitches
Dim Arr() As String: Arr = Split(CreateObject("WScript.Shell") _
.Exec(ExecString).StdOut.ReadAll, vbCrLf)
If UBound(Arr) > 0 Then
ReDim Preserve Arr(0 To UBound(Arr) - 1)
End If
ArrFilePaths = Arr
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "' Run-time error '" _
& Err.Number & "':" & vbLf & " " & Err.Description
Resume ProcExit
End Function

Related

to move files from one folder to another using VBA

I have a code which can transfer the Excel files from one folder to another but i would like to update the code so that it can move all the files (.xml, .txt, .pdf, etc.) from one folder to another.
Sub MoveFiles()
Dim sourceFolderPath As String, destinationFolderPath As String
Dim FSO As Object, sourceFolder As Object, file As Object
Dim fileName As String, sourceFilePath As String, destinationFilePath As String
Application.ScreenUpdating = False
sourceFolderPath = "E:\Source"
destinationFolderPath = "E:\Destination"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set sourceFolder = FSO.GetFolder(sourceFolderPath)
For Each file In sourceFolder.Files
fileName = file.Name
If InStr(fileName, ".xlsx") Then ' Only xlsx files will be moved
sourceFilePath = file.Path
destinationFilePath = destinationFolderPath & "\" & fileName
FSO.MoveFile Source:=sourceFilePath, Destination:=destinationFilePath
End If ' If InStr(sourceFileName, ".xlsx") Then' Only xlsx files will be moved
Next
'Don't need set file to nothing because it is initialized in for each loop
'and after this loop is automatically set to Nothing
Set sourceFolder = Nothing
Set FSO = Nothing
End Sub
can you please help
Move Files Using MoveFile
You would get greater control of things by using CopyFile and DeleteFile instead of MoveFile.
Using Dir, FileCopy, and Kill, instead of the FileSystemObject object and its methods, would make it simpler and also faster.
Option Explicit
Sub MoveFilesTEST()
Const sFolderPath As String = "E:\Source"
Const dFolderPath As String = "E:\Destination"
Const FilePattern As String = "*.*"
MoveFiles sFolderPath, dFolderPath, FilePattern
End Sub
Sub MoveFiles( _
ByVal SourceFolderPath As String, _
ByVal DestinationFolderPath As String, _
Optional ByVal FilePattern As String = "*.*")
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FolderExists(SourceFolderPath) Then
MsgBox "The source folder path '" & SourceFolderPath _
& "' doesn't exist.", vbCritical
Exit Sub
End If
If Not fso.FolderExists(DestinationFolderPath) Then
MsgBox "The destination folder path '" & DestinationFolderPath _
& "' doesn't exist.", vbCritical
Exit Sub
End If
Dim apSep As String: apSep = Application.PathSeparator
Dim sPath As String: sPath = SourceFolderPath
If Left(sPath, 1) <> apSep Then sPath = sPath & apSep
Dim sFolder As Object: Set sFolder = fso.GetFolder(sPath)
If sFolder.Files.Count = 0 Then
MsgBox "There are no files in the source folder '" & sPath & "'.", _
vbExclamation
Exit Sub
End If
Dim dPath As String: dPath = DestinationFolderPath
If Left(dPath, 1) <> apSep Then dPath = dPath & apSep
Dim dFolder As Object: Set dFolder = fso.GetFolder(dPath)
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim sFile As Object
Dim dFilePath As String
Dim ErrNum As Long
Dim MovedCount As Long
Dim NotMovedCount As Long
For Each sFile In sFolder.Files
dFilePath = dPath & sFile.Name
If fso.FileExists(dFilePath) Then
dict(sFile.Path) = Empty
NotMovedCount = NotMovedCount + 1
Else
On Error Resume Next
fso.MoveFile sFile.Path, dFilePath
ErrNum = Err.Number
' e.g. 'Run-time error '70': Permission denied' e.g.
' when the file is open in Excel
On Error GoTo 0
If ErrNum = 0 Then
MovedCount = MovedCount + 1
Else
dict(sFile.Path) = Empty
NotMovedCount = NotMovedCount + 1
End If
End If
Next sFile
Dim Msg As String
Msg = "Files moved: " & MovedCount & "(" & NotMovedCount + MovedCount & ")"
If NotMovedCount > 0 Then
Msg = Msg & vbLf & "Files not moved:" & NotMovedCount & "(" _
& NotMovedCount + MovedCount & ")" & vbLf & vbLf _
& "The following files were not moved:" & vbLf _
& Join(dict.keys, vbLf)
End If
MsgBox Msg, IIf(NotMovedCount = 0, vbInformation, vbCritical)
End Sub

Move files from multiple folders to a single folder

I am trying to consolidate Excel files from different folders to a single folder. Within each folder there is a single Excel file.
Sub move_data()
Dim FSO As Object
Dim FromPath As String
Dim ToPath As String
Dim Fdate As Date
Dim FileInFromFolder As Object
MkDir "C:\User\TEST\"
FromPath = "C:\User\MainFolder\"
ToPath = "C:\User\TEST\"
Set FSO = CreateObject("scripting.filesystemobject")
If FSO.FolderExists(FromPath) = False Then
MsgBox FromPath & " doesn't exist"
Exit Sub
End If
For Each FileInFromFolder In FSO.GetFolder(FromPath).Files
FileInFromFolder.Move ToPath
Next FileInFromFolder
End Sub
The code is unable to get the files from the subfolder within the folder (as shown in the image).
The area I am looking to change is 'FromPath', if it is possible to include a wildcard to specify the subfolders?
Multiple Folders, One Excel file per Folder
Move Files From Multiple Folders to Single Folder (FileSystemObject)
Sub MoveFiles()
Const FromPath As String = "C:\MainFolder\"
Const ToPath As String = "C:\Test\"
Const LCaseExtensionPattern As String = "xls*"
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FolderExists(FromPath) Then
MsgBox "The folder '" & FromPath & "' doesn't exist.", vbCritical
Exit Sub
End If
If Not fso.FolderExists(ToPath) Then MkDir ToPath
Dim SubFolderPaths() As String: SubFolderPaths = ArrSubFolderPaths(FromPath)
Dim fsoFile As Object
Dim NotMoved() As String
Dim n As Long
Dim mCount As Long
Dim nmCount As Long
For n = 0 To UBound(SubFolderPaths)
For Each fsoFile In fso.GetFolder(SubFolderPaths(n)).Files
If LCase(fso.GetExtensionName(fsoFile)) _
Like LCaseExtensionPattern Then
If Not fso.FileExists(ToPath & fsoFile.Name) Then
mCount = mCount + 1
fsoFile.Move ToPath
Else
nmCount = nmCount + 1
ReDim Preserve NotMoved(1 To nmCount)
NotMoved(nmCount) = fsoFile.Path
End If
End If
Next fsoFile
Next n
Dim MsgString As String
MsgString = "Files moved: " & mCount & "(" & mCount + nmCount & ")"
If nmCount > 0 Then
MsgString = MsgString & vbLf & vbLf & "Files not moved: " & mCount _
& "(" & mCount + nmCount & "):" & vbLf & vbLf & Join(NotMoved, vbLf)
End If
MsgBox MsgString, vbInformation
End Sub
Function ArrSubFolderPaths( _
ByVal InitialFolderPath As String, _
Optional ByVal ExcludeInitialFolderPath As Boolean = False) _
As String()
Const ProcName As String = "ArrSubFolderPaths"
On Error GoTo ClearError
' Ensure that a string array is passed if an error occurs.
Dim Arr() As String: Arr = Split("") ' LB = 0 , UB = -1
' Locate the trailing path separator.
Dim pSep As String: pSep = Application.PathSeparator
If Right(InitialFolderPath, 1) <> pSep Then
InitialFolderPath = InitialFolderPath & pSep
End If
' Add the initial folder path to a new collection.
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
Dim coll As Collection: Set coll = New Collection
coll.Add fso.GetFolder(InitialFolderPath)
' Add the initial folder path (or don't) to the result.
Dim n As Long
If ExcludeInitialFolderPath Then ' don't add
n = -1
Else ' add
ReDim Preserve Arr(0 To 0): Arr(0) = coll(1)
End If
Dim fsoFolder As Object
Dim fsoSubFolder As Object
Do While coll.Count > 0
Set fsoFolder = coll(1)
coll.Remove 1
For Each fsoSubFolder In fsoFolder.SubFolders
coll.Add fsoSubFolder
n = n + 1: ReDim Preserve Arr(0 To n): Arr(n) = fsoSubFolder
Next fsoSubFolder
Loop
ArrSubFolderPaths = Arr
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "' Run-time error '" _
& Err.Number & "':" & vbLf & " " & Err.Description
Resume ProcExit
End Function
This is simple to achieve if you adopt recursive procedure.
Sub Starter()
Call FilesMover("C:\User\MainFolder\", "C:\User\TEST\")
End Sub
Sub FilesMover(FromPath As String, DestinationPath As String)
Dim fso As object
Set fso = CreateObject("scripting.filesystemobject")
Dim f As File
Dim d As Folder
' first move the files in the folder
For Each f In fso.GetFolder(FromPath).Files
f.Move DestinationPath
Next f
' then check the subfolders
For Each d In fso.GetFolder(FromPath).SubFolders
Call FilesMover(d.Path, DestinationPath)
Next d
End Sub

Loop through files in a given folder, check cell content in CLOSED files to identify template and add said files to array

I'm mainly trying to work off of the solution in this thread How to loop through all sheets in all workbooks within a folder.
This is the code responsible for filling the array
'Fill the array(myFiles)with the list of Excel files in the folder
Fnum = 0
Do While FilesInPath <> ""
Fnum = Fnum + 1
ReDim Preserve MyFiles(1 To Fnum)
MyFiles(Fnum) = FilesInPath
FilesInPath = Dir()
Loop
If I understand it correctly, it should loop through all files in a given folder and retrieve every excel file in it.
Based on this thread ExecuteExcel4Macro to get value from closed workbook ExecuteExcel4Macro(string) should allow to check/retrieve the content of a given cell in a closed workbook of which I already have its name and its sheet's name.
I want to check the value of a cell (so I can identify whether the file is based on a template which I would like to work on) so it gets added to the array in the first.
I would like to integrate the solution to check cell content into the loop I pasted above.
Option Explicit
Sub Sample()
Dim wbPath As String, wbName As String
Dim wsName As String, cellRef As String
Dim Ret As String
'wbPath = "C:\Documents and Settings\Siddharth Rout\Desktop\"
wbPath = "C:\Users\my.name\Desktop\"
wbName = "QOS DGL stuff.xls"
wsName = "ACL"
cellRef = "C3"
Ret = "'" & wbPath & "[" & wbName & "]" & _
wsName & "'!" & Range(cellRef).Address(True, True, -4150)
MsgBox ExecuteExcel4Macro(Ret)
End Sub
Check Cell in Closed Files (ExecuteExcel4Macro)
Option Explicit
Sub ProcessFiles()
Dim sFolderPath As String
sFolderPath = Environ("USERPROFILE") & "\OneDrive\Documents\Test\"
Const sExtensionPattern As String = "*.xls*"
Const swsName As String = "ACL"
Const sCellAddress As String = "C3"
Const sString As String = "Yes"
Dim sFileName As String: sFileName = Dir(sFolderPath & sExtensionPattern)
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim cString As String
Do While Len(sFileName) > 0
cString = GetCellString(sFolderPath, sFileName, swsName, sCellAddress)
If StrComp(cString, sString, vbTextCompare) = 0 Then
' You could process the files here without writing them
' to a data structure...
dict(sFolderPath & sFileName) = Empty
End If
sFileName = Dir
Loop
If dict.Count = 0 Then Exit Sub
Debug.Print Join(dict.Keys, vbLf)
' ' ... or loop through the dictionary ...
' Dim Key As Variant
' For Each Key In dict.Keys
' ' Continue
' 'Debug.Print Key
'
' Next Key
'
' ' ... or write the values from the dictionary to an array
' ' and loop through the array.
' Dim MyFiles As Variant: MyFiles = dict.Keys
'
' Dim n As Long
'
' For n = 0 To UBound(MyFiles)
' ' Continue
' 'Debug.Print MyFiles(n)
' Next n
End Sub
Function GetCellString( _
ByVal wbPath As String, _
ByVal wbName As String, _
ByVal wsName As String, _
ByVal CellAddress As String) _
As String
Const ProcName As String = "GetCellString"
On Error GoTo ClearError
Dim ee4mString As String
ee4mString = "'" & wbPath & "[" & wbName & "]" & _
wsName & "'!" & Range(CellAddress).Address(ReferenceStyle:=xlR1C1)
GetCellString = ExecuteExcel4Macro(ee4mString)
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
Resume ProcExit
End Function

Copy, rename and validate success of multiple files and paths in excel

Solution Template SetUp
Been scratching around for the last 5 days here and across the net to find something that works for multiple files. Many a late night/early hours of the morning unsuccessfully piecing together/coding to get a result. Thanks in advance.
The following code is from get-digital-help.com/copyrename-a-file-excel-vba written by Oscar
It works for 1 file, Ive got 8,000 files to do across a deep folder structure so but I'd really like each row to look at a source path, source file name, destination path and destination file:
For each row:
Column A list the source path
Column B lists the source file name
Column C lists to destination path
Column D lists the new file name
Column E writes "Success" or "Fail" validation.
if file name already exists in destination, then "Fail"
If source file doesn't exist, then "Fail"
Nice to have/completely optional!!! :)
Check if source file column A&B exists, = True or False in column F. Where True, then proceed with copy and rename.
If destination file already exist, the fail and column F = duplicate
Leave first row to put in column header names.
Sub CopyRenameFile()
'Dimension variables and declare data types
Dim src As String, dst As String, fl As String
Dim rfl As String
'Save source directory specified in cell A2 to variable src
src = Range("A2")
'Save destination directory specified in cell C2 to variable dst
dst = Range("C2")
'Save file name specified in cell B2 to variable fl
fl = Range("B2")
'Save new file name specified in cell D2 to variable rfl
rfl = Range("D2")
'Enable error handling
On Error Resume Next
'Copy file based on variables src and fl to destination folder based on variable dst and name file based on value in rfl
FileCopy src & "\" & fl, dst & "\" & rfl
'Check if an error has occurred
If Err.Number <> 0 Then
'Show error using message box
MsgBox "Copy error: " & src & "\" & rfl
End If
'Disable error handling
On Error GoTo 0
End Sub
Copy Files Using a File List
This solution consists of three procedures. You run only the first: copyRenameFile. The other two, getOffsetColumn and writeOffsetRange are being called by the first, when necessary.
It is best tested with a new workbook. Insert a module and copy the code into it. Now open your original workbook and copy certain values to e.g. Sheet1 of the new workbook. Since the code is written for Thisworkbook (the workbook containing this code), the original workbook will be safe (will not be written to).
First adjust the values in the constants sections (titled Worksheet and Other). Then test the empty worksheet. Then test with one folder in column A then with more and slowly continue testing with other columns. Possible errors should be suppressed and their messages (descriptions) should appear in VBE's Immediate window (CTRL+G).
As a byproduct of this investigation, I've also added the createFolders function to create folders in one case when MkDir 'cannot', and two procedures to test it.
The Code
Option Explicit
Sub copyRenameFile()
' Initialize error handling.
Const ProcName As String = "copyRenameFile"
On Error GoTo clearError ' Turn on error trapping.
' Worksheet
Const wsName As String = "Sheet1" ' Worksheet Name
Const FirstRow As Long = 2 ' First Row Number
Const LastRowCol As Variant = "A" ' Last Row Column Index
Dim srcCols As Variant ' Source Columns Array
srcCols = VBA.Array("A", "B", "C", "D")
Dim tgtCols As Variant ' Target Columns Array
tgtCols = VBA.Array("E", "F")
' Other
Dim filMsg() As Variant ' File Messages
filMsg = VBA.Array("Fail", "Success")
Dim folMsg() As Variant ' Folder Messages
folMsg = VBA.Array(False, True, "Duplicate")
Dim PathDelimiter As String
PathDelimiter = Application.PathSeparator
Dim wb As Workbook
Set wb = ThisWorkbook ' 'Thisworkbook' is the workbook containing this code.
' Define Last Row Column Range ('rng').
Dim ws As Worksheet
Set ws = wb.Worksheets(wsName)
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, LastRowCol).End(xlUp).Row
If LastRow < FirstRow Then
GoTo FirstRowBelowLastRow
End If
Dim rng As Range
Set rng = ws.Range(ws.Cells(FirstRow, LastRowCol), _
ws.Cells(LastRow, LastRowCol))
' Write Source Column Ranges to Source Jagged Array ('Source').
Dim ubcS As Long
ubcS = UBound(srcCols)
Dim Source As Variant
ReDim Source(0 To ubcS)
Dim Data As Variant
Dim j As Long
For j = 0 To ubcS
getOffsetColumn Data, srcCols(j), rng
Source(j) = Data
Next j
' Define Target Jagged Array ('Target').
Dim ubcT As Long
ubcT = UBound(tgtCols)
Dim ubs As Long
ubs = UBound(Source(0))
Dim Target As Variant
ReDim Target(0 To ubcT)
ReDim Data(1 To ubs, 1 To 1)
For j = 0 To ubcT
Target(j) = Data
Next j
' Declare additional variables for the For Next loop.
Dim i As Long
Dim Copied As Long
Dim srcPath As String
Dim tgtPath As String
' Loop through rows of arrays of Source Jagged Array, check folders,
' check files and finally copy if condition is met. At the same time
' write results to arrays of Target Jagged Array.
' The condition to copy is met when source file exists,
' and target file does not.
For i = 1 To ubs
' Folders
srcPath = Source(0)(i, 1)
If Dir(srcPath, vbDirectory) = "" Then
' Source Folder and Source File do not exist.
Target(0)(i, 1) = filMsg(0)
Target(1)(i, 1) = folMsg(0)
GoTo NextRow
End If
' Source Folder exists.
tgtPath = Source(1)(i, 1)
If Dir(tgtPath, vbDirectory) = "" Then
' Target Folder and Target File do not exist.
Target(0)(i, 1) = filMsg(0)
Target(1)(i, 1) = folMsg(0)
GoTo NextRow
End If
' Source Folder and Target Folder exist.
' Files
srcPath = srcPath & PathDelimiter & Source(2)(i, 1)
If Dir(srcPath) = "" Then
' Source File does not exist.
Target(0)(i, 1) = filMsg(0)
Target(1)(i, 1) = folMsg(0)
GoTo NextRow
End If
' Source File exists.
tgtPath = tgtPath & PathDelimiter & Source(3)(i, 1)
If Dir(tgtPath) <> "" Then
' Target File exists.
Target(0)(i, 1) = filMsg(0)
Target(1)(i, 1) = folMsg(2)
GoTo NextRow
End If
' Source File exists and Target File does not.
Target(0)(i, 1) = filMsg(1)
Target(1)(i, 1) = folMsg(1)
' Copy
FileCopy srcPath, tgtPath
' Count files copied.
Copied = Copied + 1
NextRow:
Next i
' Write values (results) from arrays of Target Jagged Array
' to Target Columns.
For j = 0 To ubcT
writeOffsetRange Target(j), tgtCols(j), rng
Next j
' Inform user.
MsgBox "Copied " & Copied & " files.", vbInformation, "Success"
ProcExit:
Exit Sub
FirstRowBelowLastRow:
Debug.Print "'" & ProcName & "': First row below last row."
GoTo ProcExit
clearError:
Debug.Print "'" & ProcName & "': " & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
On Error GoTo 0 ' Turn off error trapping.
GoTo ProcExit
End Sub
Sub getOffsetColumn(ByRef Data As Variant, _
OffsetColumnIndex As Variant, _
ColumnRange As Range)
' Initialize error handling.
Const ProcName As String = "getOffsetColumn"
On Error GoTo clearError ' Turn on error trapping.
Data = Empty
If ColumnRange Is Nothing Then
GoTo NoRange
End If
Dim ws As Worksheet
Set ws = ColumnRange.Worksheet
If ColumnRange.Rows.Count > 1 Then
Data = ColumnRange.Offset(, ws.Columns(OffsetColumnIndex).Column _
- ColumnRange.Column) _
.Value
Else
ReDim Data(1 To 1, 1 To 1)
Data(1, 1) = ColumnRange.Offset(, ws.Columns(OffsetColumnIndex) _
.Column _
- ColumnRange.Column) _
.Value
End If
ProcExit:
Exit Sub
NoRange:
Debug.Print "'" & ProcName & "': No Range."
GoTo ProcExit
clearError:
Debug.Print "'" & ProcName & "': " & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
On Error GoTo 0 ' Turn off error trapping.
GoTo ProcExit
End Sub
Sub writeOffsetRange(Data As Variant, _
OffsetColumnIndex As Variant, _
ColumnRange As Range)
' Initialize error handling.
Const ProcName As String = "writeOffsetColumn"
On Error GoTo clearError ' Turn on error trapping.
If ColumnRange Is Nothing Then
GoTo NoRange
End If
Dim ws As Worksheet
Set ws = ColumnRange.Worksheet
ColumnRange.Offset(, ws.Columns(OffsetColumnIndex).Column _
- ColumnRange.Column).Value = Data
ProcExit:
Exit Sub
NoRange:
Debug.Print "'" & ProcName & "': No Range."
GoTo ProcExit
clearError:
Debug.Print "'" & ProcName & "': " & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
On Error GoTo 0 ' Turn off error trapping.
GoTo ProcExit
End Sub
The Byproduct
' e.g. "C:\Test" is an existing folder, "C:\Test\Test1" is not.
' When you want to create the folder "C:\Test\Test1\Test2", 'MkDir' will return
' "Run-time error '76': Path Not found", because "C:\Test\Test1" does not exist.
' The 'createFolders' function remedies this by creating as many folders
' as needed. In the previous example it first creates "C:\Test\Test1" and
' only then creates "C:\Test\Test1\Test2" in it.
' The function returns 'True' if the folder previously existed or now exists.
' The function returns 'False' if 'PathString' is invalid.
Function createFolders(PathString As String) As Boolean
' Initialize error handling.
Const ProcName As String = "createFolders"
On Error GoTo clearError ' Turn on error trapping.
' Split Path String ('PathString') by System Path Separator ('Delimiter')
' into 1D zero-based Folders Array 'Folders()'.
Dim Delimiter As String
Delimiter = Application.PathSeparator
Dim Folders() As String
Folders = Split(PathString, Delimiter)
' Define Last Subscript ('LastSS') to be considered, because Path String
' could be ending with a System Path Separator.
Dim LastSS As Long
LastSS = UBound(Folders)
If Folders(LastSS) = "" Then
LastSS = LastSS - 1
End If
' Using Folders Array, write paths to Paths Array ('Paths()').
Dim Paths() As String
ReDim Paths(0 To LastSS)
Paths(0) = Folders(0)
Dim j As Long
If LastSS > 0 Then
For j = 1 To LastSS
Paths(j) = Paths(j - 1) & Delimiter & Folders(j)
Next j
End If
' Create each folder if it does not exist.
For j = 0 To LastSS
If Dir(Paths(j), vbDirectory) = "" Then
MkDir Paths(j)
End If
Next j
' Write result.
createFolders = True
ProcExit:
Exit Function
clearError:
Debug.Print "'" & ProcName & "': " & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
On Error GoTo 0 ' Turn off error trapping.
GoTo ProcExit
End Function
Sub testCreateFolders()
Const PathString As String = "C:\Test\Test1\Test2"
Dim Result As Boolean
Result = createFolders(PathString)
If Result Then
MsgBox "If the path previously didn't exist, now it certainly does."
Else
MsgBox "The supplied path is invalid."
End If
End Sub
Sub testMkDir()
Const PathString As String = "C:\Test\Test1\Test2"
MkDir PathString
End Sub

How do you use MATCH in a loop?

I keep getting an error in the below code and its likely incorrect syntax.
I have tried replacing this line
IsInArray(pdfname, arNames(i)) = True
with this
Application.worksheetfunction.match(pdfname, arNames(i)) = True
but its not working.
Sub OpenPdf()
On Error GoTo OpenPdf_Error
Dim pdfname As String
Dim pdf
Const sPath = "S:\RA QUOTES 2019"
Dim FName As String
Dim arNames() As String
Dim myCount As Integer
Dim i As Integer
FName = Dir("S:\RA QUOTES 2019\*.pdf*")
Do Until FName = ""
myCount = myCount + 1
ReDim Preserve arNames(1 To myCount)
arNames(myCount) = FName
FName = Dir
Loop
pdfname = Application.InputBox("Enter the pdf you are looking for")
pdfname = "PLQ" & pdfname
For i = 1 To UBound(arNames)
If IsInArray(pdfname, arNames(i)) = True Then
ThisWorkbook.FollowHyperlink sPath & arNames(i)
End If
Next i
On Error GoTo 0
Exit Sub
OpenPdf_Error:
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure OpenPdf"
End Sub
This will work for an exact match using a dictionary (a collection data type which has the .Exists property which allows you to check if a key within the dictionary exists without looping through everytime).
Option Explicit
Sub OpenPdf()
Dim pdfname As String
Dim DictPDF As New Scripting.Dictionary 'Needs Microsoft Scripting Runtime
Const sPath = "S:\RA QUOTES 2019\"
Dim FName As String
Dim i As Integer
FName = Dir(sPath & "*.pdf*")
Do While FName <> vbNullString
'add the name into the dictionary
DictPDF.Add Left(LCase(pdfname), 7), 1 'Left will get the first 7 characters from the left to the name
FName = Dir
Loop
pdfname = Application.InputBox("Enter the pdf you are looking for")
pdfname = LCase("PLQ" & pdfname)
'Check if the name is in the dictionary I used LCase because dictionaries are case sensitive,
'so everything in low case to avoid problems.
If DictPDF.Exists(pdfname) Then
ThisWorkbook.FollowHyperlink sPath & DictPDF(pdfname)
Else
MsgBox pdfname & " was not found."
End If
End Sub
Sub OpenPdf()
On Error GoTo OpenPdf_Error
Dim pdfname As String
Dim pdf
Const sPath = "S:\RA QUOTES 2019\"
Dim FName As String
Dim arNames() As String
Dim myCount As Integer
Dim i As Integer
FName = Dir("S:\RA QUOTES 2019\*.pdf*")
Do Until FName = ""
myCount = myCount + 1
ReDim Preserve arNames(1 To myCount)
arNames(myCount) = FName
FName = Dir
Loop
pdfname = Application.InputBox("Enter the pdf you are looking for")
pdfname = "PLQ" & pdfname
For i = 1 To UBound(arNames)
If InStr(1, arNames(i), pdfname, vbTextCompare) Then
MsgBox (arNames(i))
ThisWorkbook.FollowHyperlink sPath & arNames(i)
End If
Next i
On Error GoTo 0
Exit Sub
OpenPdf_Error:
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure
OpenPdf"
End Sub

Resources