从多个子文件夹复制文件的VBA宏

时间:2016-02-08 01:29:13

标签: vba

我有一个VBA,用于根据图像名称将图像从一个文件夹复制到另一个文件夹。您可以检查附加工作中的宏。代码是:

Option Explicit

Sub CopyFiles()
    Dim iRow As Integer         ' ROW COUNTER.
    Dim sSourcePath As String
    Dim sDestinationPath As String
    Dim sFileType As String

    Dim bContinue As Boolean

    bContinue = True
    iRow = 2

    ' THE SOURCE AND DESTINATION FOLDER WITH PATH.
    sSourcePath = "C:\Users\nhatc_000\Desktop\01010101\"
    sDestinationPath = "C:\Users\nhatc_000\Desktop\02020202\"

    sFileType = ".jpg"      ' TRY WITH OTHER FILE TYPES LIKE ".pdf".

    ' LOOP THROUGH COLUMN "A" TO PICK THE FILES.
    While bContinue

        If Len(Range("A" & CStr(iRow)).Value) = 0 Then    ' DO NOTHING IF THE COLUMN IS BLANK.
            MsgBox "Images have been moved. Thank you!" ' DONE.
            bContinue = False
        Else
            ' CHECK IF FILES EXISTS.

            If Len(Dir(sSourcePath & Range("A" & CStr(iRow)).Value & sFileType)) = 0 Then
                Range("B" & CStr(iRow)).Value = "Does Not Exists"
                Range("B" & CStr(iRow)).Font.Bold = True
            Else
                Range("B" & CStr(iRow)).Value = "On Hand"
                Range("B" & CStr(iRow)).Font.Bold = False

                If Trim(sDestinationPath) <> "" Then
                    Dim objFSO
                    Set objFSO = CreateObject("scripting.filesystemobject")

                    ' CHECK IF DESTINATION FOLDER EXISTS.
                    If objFSO.FolderExists(sDestinationPath) = False Then
                        MsgBox sDestinationPath & " Does Not Exists"
                        Exit Sub
                    End If

                    '*****
                    ' HERE I HAVE INCLUDED TWO DIFFERENT METHODS.
                    ' I HAVE COMMENTED THE SECOND METHOD. TO THE SEE THE RESULT OF THE
                    ' SECOND METHOD, UNCOMMENT IT AND COMMENT THE FIRST METHOD.

                    ' METHOD 1) - USING "CopyFile" METHOD TO COPY THE FILES.
                    objFSO.CopyFile Source:=sSourcePath & Range("A" & CStr(iRow)).Value & _
                        sFileType, Destination:=sDestinationPath

                    ' METHOD 2) - USING "MoveFile" METHOD TO PERMANENTLY MOVE THE FILES.
                    'objFSO.MoveFile Source:=sSourcePath & Range("B" & CStr(iRow)).Value & _
                        sFileType, Destination:=sDestinationPath
                    '*****
                End If
            End If
        End If

       iRow = iRow + 1      ' INCREMENT ROW COUNTER.
    Wend
End Sub

但是,我需要在此代码中添加两项内容:

  1. 当我输入要复制的文件的名称时,我也想复制 具有相同名称的文件PLUS扩展名 _01 / _02 /.../_ 07 if 那些存在。
  2. 我希望宏不仅可以查看指定的文件夹内部,还可以查看 子文件夹内的子文件夹和子文件夹内的子文件夹 等
  3. 有人可以帮忙吗? 谢谢!

1 个答案:

答案 0 :(得分:0)

你需要的是一些Recursive Subs来根据Range值找到所有类似的文件名。

在这里,我将使用以下代码通过以下几个步骤来实现此目标:

  1. 对于每个Range值(存储为Dictionary中的Key),找到所有文件名(与Dictionary中的Item完全相似)。将每个发现加入&#34; |&#34; (非法文件名字符)。
  2. 在源路径
  3. 中的所有文件和子文件夹之后处理词典项目
  4. 对于键字典中的每个项目,查看目标文件夹中的现有文件。追加&#34; (ⅰ)&#34;目标文件名(如果已存在)。
  5. 将目标文件复制到目标文件夹。
  6. 复制时,会返回

  7. 遇到第一个空单元时停止循环

  8. 注意:代码未经过测试,只编译正常

    Option Explicit
    
        ' THE SOURCE AND DESTINATION FOLDER WITH PATH.
    Private Const sSourcePath = "C:\Users\nhatc_000\Desktop\01010101\"
    Private Const sDestinationPath = "C:\Users\nhatc_000\Desktop\02020202\"
    Private Const sFileType = "jpg"        ' TRY WITH OTHER FILE TYPES LIKE ".pdf".
    Private Const DIV = "|" ' A character that's not legal file name
    
    Private objFSO As Object, objDict As Object
    
    Sub CopyFilesAlike()
        Dim lRow As Long, sName As String
        Set objFSO = CreateObject("Scripting.FileSystemObject")
        If Not objFSO.FolderExists(sSourcePath) Then
            MsgBox "Source folder not found!" & vbCrLf & sSourcePath, vbCritical + vbOKOnly
            GoTo I_AM_DONE
        End If
        If Not objFSO.FolderExists(sDestinationPath) Then
            MsgBox "Destination folder not found!" & vbCrLf & sDestinationPath, vbCritical + vbOKOnly
            GoTo I_AM_DONE
        End If
        ' Proceed when both Source and Destination folders found
        Set objDict = CreateObject("Scripting.Dictionary")
        lRow = 2
        Do Until IsEmpty(Cells(lRow, "A")) ' Stop on first empty cell in Column A from lRow
            ' Get Main file name to look up
            sName = Cells(lRow, "A").Value
            ' Look for files (exact and alikes from sub folders) to add to dictionary
            LookForFilesAlike sName, objFSO.GetFolder(sSourcePath)
            ' Copy files
            If objDict.Count = 0 Then
                Cells(lRow, "B").Value = "No files found."
            Else
                Cells(lRow, "B").Value = objDict.Count & " filenames(s) found." & vbLf & CopyFiles
            End If
            ' Clear the Dictionary for next Name
            objDict.RemoveAll
            ' Increment row counter
            lRow = lRow + 1
        Loop
        Set objDict = Nothing
    
    I_AM_DONE:
        Set objFSO = Nothing
    End Sub
    
    Private Sub LookForFilesAlike(ByVal sName As String, ByVal objFDR As Object)
        Dim oFile As Object, oFDR As Object
        ' Add files of current folder to dictionary if name matches
        For Each oFile In objFDR.Files
            If InStr(1, oFile.Name, sName, vbTextCompare) = 1 Then ' Names beginning with sName
                ' Check the extension to match
                If LCase(objFSO.GetExtensionName(oFile)) = LCase(sFileType) Then
                    If objDict.Exists(oFile.Name) Then
                        ' Append Path to existing entry
                        objDict.Item(oFile.Name) = objDict.Item(oFile.Name) & DIV & oFile.Path
                    Else
                        ' Add Key and current path
                        objDict.Add oFile.Name, oFile.Path
                    End If
                End If
            End If
        Next
        ' Recurse into each sub folder
        For Each oFDR In objFDR.SubFolders
            LookForFilesAlike sName, oFDR
        Next
    End Sub
    
    Private Function CopyFiles() As String
        Dim i As Long, oKeys As Variant, oItem As Variant, iRepeat As Integer, sName As String, sOut As String
        sOut = ""
        ' Process the items for each key in Dictionary
        Set oKeys = objDict.Keys ' <- Add "Set " before oKeys
        For i = 0 To objDict.Count
            For Each oItem In Split(objDict.Item(oKeys(i)), DIV)
                ' Determine the filename in destination path
                If objFSO.FileExists(sDestinationPath & objFSO.GetFileName(oItem)) Then
                    ' Same file name alreay found, try append " (i)"
                    iRepeat = 0
                    Do
                        iRepeat = iRepeat + 1
                        sName = objFSO.GetBaseName(oItem) & " (" & iRepeat & ")" & objFSO.GetExtensionName(oItem)
                    Loop While objFSO.FileExists(sDestinationPath & sName)
                    sName = sDestinationPath & sName
                Else
                    ' First file to be copied to destination folder
                    sName = sDestinationPath
                End If
                ' Copy the source file to destination file
                If Len(sOut) = 0 Then
                    sOut = oItem & DIV & sName
                Else
                    sOut = sOut & vbLf & oItem & DIV & sName
                End If
                objFSO.CopyFile oItem, sName
            Next
        Next
        CopyFiles = sOut
    End Function