Moving files to a subfolder based on partial filename with VBA

SAMyMAS

New Member
Joined
Nov 2, 2022
Messages
3
Office Version
  1. 2019
Platform
  1. Windows
Hello There,

I have been trying to move over 300+ pdf files to subfolders, which partially match filenames. The file names format is as follow:

Definition, PN 123456, SN unique
Definition(may change), PN 657634(may change), SN unique(always different)

Their pattern is Two Commas following by PN and SN: ..., PN ..., SN ...

The folder names are: PN 123456 SN unique.

The example:

filenames

VALVE AFT SAFETY, PN 81155B010101, SN 00515
CABIN PRESSURIZATION MODULE, PN 92147A020103, SN 00501
AIR CYCLE MACHINE, PN 820906-3, SN 2010010011
AIR CYCLE MACHINE, PN 820906-3, SN 2010010014
TEMP REDUCTION SWITCH, PN 820907-2, SN 0414


folder names

PN 81155B010101 SN 00515
PN 92147A020103 SN 00501
PN 820906-3 SN 2010010011
PN 820906-3 SN 2010010014
PN 820907-2 SN 0414

The folders are subdirectories, second level.


I tried the information that, was kindly provided by @BNR bnr.455560 here

The below code run as Macro - does nothing.

VBA Code:
Public Function Return_SubDirectory_Name(FileName As String) As String
    
    'define a string array
    Dim Splitter() As String
    
    ' check if we have a filename with a length > 0  - i.e. no empty filenames
    If Len(FileName) > 0 Then
        ' let's assume the filename is "Definition, PN 123456, SN unique.pdf"
        ' Split creates a string array with the ", " as the break point - notice the space before and after the "-" character
        ' element 0 in the array will hold "Definition"
        ' element 2 in the array will hold "SN inique.pdf
        Splitter = Split(FileName, ", ", 2)
        
        ' test to make sure the array has JUST two elements
        ' 1st element of ANY array starts with zero
        ' logic would need to be adjusted if file name was something like "02 - 12345 - 123.pdf" - as plsit function would create more elements
        If UBound(Splitter) = 1 Then
            
            ' now splitter (1) holds the value "PN 123456, SN unique.pdf"
            ' split out the ".pdf" or whatever file extention

            Splitter = Split(Splitter(1), ".")
            ' element (0) now just holds "PN 123456, SN unique" - this *SHOULD* be the sub directory or deal #
 
'Remove comma "," by replace it to ""
            Splitter = Replace(Splitter(0), ",", "")
            Return_SubDirectory_Name = CStr(Splitter(0))
            
            ' now exit the function
            Exit Function
        End If
        
        ' if above logic didn't work (maybe weird file name or whatever) - then drop out here with vbnullstring (empty) filename
        Return_SubDirectory_Name = vbNullString
    
    End If
    
End Function

Public Sub Check_Files(Search_Path As String)

    Dim File_Name As String
    Dim File_Type As String
    
    Dim strFileName As String
    Dim Deal_Name As String
    
    Dim Archive_Path As String
    Dim Target_Path As String
    
    Dim File_Count As Integer
    
    ' setup where the archive directory is - maybe a network location?
    ' I'll assume it is the same directory path as the work book - change the following path as required
    ' path should be in a format like "C:\Desktop\MyFiles" or something
    Archive_Path = ThisWorkbook.Path
    
    ' the search_path is handed into the function as an arguement
    ' checks the Search path - this path is where the file currently are - maybe different than where you want to archive them
    Confirm_Directory Search_Path
    
    ' changes excel's default directory path to the one you want to search
    ChDir Search_Path

    ' assumes .msg files, but could be .pdf files - make changes as needed
    File_Type = Search_Path & "*.pdf"

    ' identifies file name within the target directory
    strFileName = Dir(File_Type)
    
    ' cycles through each file within the search directory - will continue until the length of the strFileName = 0 (i.e. no files)
    Do While Len(strFileName) > 0
        
        ' get the sub directory or #deal name
        Deal_Name = Return_SubDirectory_Name(strFileName)
        
        ' test if we have a valid deal name (not a vbnullstring)
        If Len(Deal_Name) > 0 Then
        
            ' update the target_path - the target path will change as the different #deal name subdirectories within the archive path change
            Target_Path = Archive_Path & "\" & Deal_Name
        
            ' checks if THAT target archive path exists - makes one if it doesn't
            Confirm_Directory Target_Path
            
            ' copy required file to the target archive directory
            FileCopy Search_Path & "\" & strFileName, Target_Path & "\" & strFileName

            ' delete original copy from search directory
            Kill Search_Path & "\" & strFileName
        
            File_Count = File_Count + 1
        
        End If
        
        ' aquires the next filename in the search directory
        strFileName = Dir
        
    Loop

    Debug.Print "Moved " & File_Count & " file(s)"

End Sub

Public Sub Confirm_Directory(This_Path As String)
    ' used to test for directory locations
    ' will make sub directories if required
    
    Dim Splitter() As String
    Dim Test_Path As String
    
    If Dir(This_Path, vbDirectory) <> vbNullString Then
    
        Splitter = Split(This_Path, "\")
        
        For I = LBound(Splitter) To UBound(Splitter)
            If I = 0 Then
                Test_Path = Splitter(0)
            Else
                Test_Path = Test_Path & "\" & Splitter(I)
            End If
            
ReTest:
            If Dir(Test_Path, vbDirectory) = vbNullString Then
                'Debug.Print "'" & Test_Path & "' does not exist"
                MkDir Test_Path
                'Debug.Print "Making ' " & Test_Path & "'"
                GoTo ReTest
            Else
                'Debug.Print "'" & Test_Path & "' exists"
            End If
        Next I
    End If
    

End Sub
Sub Sort_files_2_folders_()

End Sub
 

Excel Facts

VLOOKUP to Left?
Use =VLOOKUP(A2,CHOOSE({1,2},$Z$1:$Z$99,$Y$1:$Y$99),2,False) to lookup Y values to left of Z values.
The initial my attempt was to match the filename's last part after ‘SN’ to the one after ‘SN’ of the folder. The current submitted code has been adjusted to matchup the fully folder name. Since it will also suit to my purpose. I was trying to make it works.
 
Upvote 0
It's not totally clear where the subfolders are in relation to the PDF files. I've assumed they are subfolders of the folder containing the PDF files. You must change the PDFsFolder string where indicated to the folder path containing the PDF files.

VBA Code:
Public Sub Move_PDF_Files()

    Dim PDFsFolder As String
    Dim destFolder As String
    Dim FSO As Object 'Scripting.FileSystemObject
    Dim FSfile As Object 'Scripting.File
   
    PDFsFolder = "C:\path\to\PDF files\"    'CHANGE THIS
    
    Set FSO = CreateObject("Scripting.FileSystemObject") 'New Scripting.FileSystemObject
    
    For Each FSfile In FSO.GetFolder(PDFsFolder).Files
        
        If LCase(FSfile.Name) Like "*.pdf" Then
            
            destFolder = Get_Folder(FSfile.Name)
            
            If destFolder <> "" Then
                destFolder = FSfile.ParentFolder & "\" & destFolder & "\"
                If FSO.FolderExists(destFolder) Then
                    FSO.CopyFile FSfile.Path, destFolder, True
                    FSfile.Delete
                Else
                    MsgBox "Destination folder doesn't exist" & vbCrLf & vbCrLf & _
                           "File: " & FSfile.Name & vbCrLf & vbCrLf & _
                           "Folder: " & destFolder, vbExclamation
                End If
                
            End If
            
        End If
        
    Next
    
End Sub


Private Function Get_Folder(fileName As String) As String

    'Parse file name in expected format and return folder name
    'Example: fileName "xxxxxx, PN yyyyyy, SN zzzzzz.pdf", returns "PN yyyyyy SN zzzzzz"

    Dim parts1 As Variant, parts2 As Variant
    Dim folder As String
    
    Get_Folder = ""
    parts1 = Split(fileName, ", PN ", Compare:=vbTextCompare)
    If UBound(parts1) > 0 Then
        parts2 = Split(parts1(1), ",")
        If UBound(parts2) > 0 Then folder = "PN " & parts2(0)
        parts2 = Split(parts1(1), ", SN ", Compare:=vbTextCompare)
        If UBound(parts2) > 0 Then Get_Folder = folder & " SN " & Split(parts2(1), ".")(0)
    End If
    
End Function
 
Upvote 0
Solution
It's not totally clear where the subfolders are in relation to the PDF files. I've assumed they are subfolders of the folder containing the PDF files. You must change the PDFsFolder string where indicated to the folder path containing the PDF files.
Thank you John for the provided code. It works perfectly. There is one thing, the destination folders are not subfolders of the PDF files.
The subfolders' ParentFolder has another folders (subdirectories, level 1), which in turn contain the destination folders (subdirectories, level 2) are located in the different location to PDF files. i.e. ParentFolder > subdirectories > destination folders.
How to change the destFolder to ParentFolder location.

Could you tell me the 'logic' of this code, please. So I could understand how it works and be able to tweak it if needed.


Kind Regards
 
Upvote 0
There is one thing, the destination folders are not subfolders of the PDF files.
The subfolders' ParentFolder has another folders (subdirectories, level 1), which in turn contain the destination folders (subdirectories, level 2) are located in the different location to PDF files. i.e. ParentFolder > subdirectories > destination folders.
How to change the destFolder to ParentFolder location.
OK, I understand that the destination folders are not subfolders of the folder containing the PDF files, so the code will need changing.

But your clarification is not completely clear. Are you saying that the destination folders are in this structure:

Parent folder > A single specific subfolder > Destination folders

Examples:
C:\parent\subfolder1\PN 81155B010101 SN 00515\
C:\parent\subfolder1\PN 92147A020103 SN 00501\
C:\parent\subfolder1\PN 820906-3 SN 2010010011\

Or are they in this structure:

Parent folder > Many subfolders > Destination folders

Examples:
C:\parent\subfolder1\PN 81155B010101 SN 00515\
C:\parent\subfolder2\PN 92147A020103 SN 00501\
C:\parent\subfolder2\PN 820906-3 SN 2010010011\

If the former then the code can be easily changed to specify the "C:\parent\subfolder1\" path to the destination folder. However, the latter needs more code to look in all the 'Many subfolders' for the correct destination folder which matches the "PN yyyyyy SN zzzzz" string extracted from the PDF file name.

Could you tell me the 'logic' of this code, please. So I could understand how it works and be able to tweak it if needed.
It loops through all files in the PDFsFolder, the If LCase(FSfile.Name) Like "*.pdf" Then checks that the file name matches the wildcard *.pdf file specification and if so calls Get_Folder to parse the file name and extract the "PN yyyyyy SN zzzzz" string. It then checks whether the "PN yyyyyy SN zzzzz" destination folder exists and if so copies the PDF there and deletes it from its original location, otherwise it displays the warning message.
 
Upvote 0
John_w i have some questions specific to this thread but i see it is kinda old. I do not see where the path to the new folder is defined.
Ex) My folder with pdfs is on my C:\drive and that is being identified in your example as the PDFSFolder. My destfolders (plural) are not on my C:\drive. I just don't see where to define those pathways in your example. Could you provide that example please?
 
Upvote 0
I do not see where the path to the new folder is defined.

The new folder is a subfolder of the folder containing the PDF file to be moved. This new folder is based on the file name of the PDF and is generated by the Get_Folder function in the above code. An example is given in the comments:

VBA Code:
    'Parse file name in expected format and return folder name
    'Example: fileName "xxxxxx, PN yyyyyy, SN zzzzzz.pdf", returns "PN yyyyyy SN zzzzzz"
 
Upvote 0
Ok. I am following i think. In this thread he is just moving files from a folder to a subfolder of the original folder right?
In my situation there will be no duplicated as i already have a date and time stamp in the name, so no need to parse names. I just need to move the files from a folder on C drive to subfolders on a different drive.
(This is kind of related to another thread i have going so i am not trying to duplicate post or anything. I just thought this thread was most relevant to what i am trying to accomplish and that maybe this solution was possibly adaptable to my needs. I can post that link if needed/proper etiquette.)
 
Upvote 0
Thank you very much for that clarification.
That doesn't really suit my needs at all. hahahaha i will keep searching.
Thanks again
 
Upvote 0

Forum statistics

Threads
1,214,942
Messages
6,122,366
Members
449,080
Latest member
Armadillos

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top