Excel / 移動特定檔案到特定資料夾

同樣是來自網友的提問:

如何用Excel VBA將資料夾內的特定檔案移動到特定資料夾

我的思路是

1.先取得資料夾內的檔案

這有2種方式

1種是直接打在試算表內

再用程式去讀取儲存格

但是檔案多就沒效率

所以第2種是用FileSystemObject 物件建立Folder物件

再來取得資料夾內的所有 File 物件

可以參考微軟的線上說明

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Sub ShowFileList(folderspec)
    Dim fs, f, f1, fc, s
    Set fs = CreateObject("Scripting.FileSystemObject")
    Set f = fs.GetFolder(folderspec)
    Set fc = f.Files
    For Each f1 in fc
        s = s & f1.name 
        s = s &  vbCrLf
    Next
    MsgBox s
End Sub

 

2.找出特定的檔案

由於不是每個檔案都要移動,而是特定副檔名的檔案

因此,可以用 File 物件的name屬性來取得檔案名稱

再用Split() 以 . 來分割完整檔案名稱

這樣得到的陣列的第1個值就是檔案名稱

第2個值則是副檔名

ps.用File 物件的type屬性,回傳的是Microsoft Excel 工作表

再用判斷式,符合的才進行操作

ps.如果不是所有相同副檔名都要移動??

如果檔案名稱是有規則的就可以依照規則來取出檔案

不然最好還是事前排除不要的檔案

 

3.判斷式:符合的檔案移動到特定資料夾

特定的資料夾名稱可以自訂

例如:根據檔案名稱

ps.如果只是要部份的檔案名稱

假如名稱是有規則的,例如:123-XXX .xlsx 456-XXX.xlsx

這樣就可以用Split() 來分割檔案名稱,取出要的部分再組成

如果沒有規則的話,就自己找規則…

 

4.之後再用一個判斷式:資料夾是否存在

如果資料夾已經存在就執行移動檔案的指令

假如不存在,則先建立資料夾,再執行移動檔案的指令

這邊移動檔案的指令式利用shell函數執行CMD(也就是DOS)的move指令

move [{/y|-y}] [<source>] [<target>]

Chr(32)是為了產生空格

 

完整程式碼如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Public Sub 移動特定檔案到特定資料夾2()
    Dim oFSO As Object
    Dim oFolder As Object
    Dim oFile As Object
    Dim xlsx As Variant
    Dim filePath As String
    Dim oldPath As String
    Dim newPath As String
   
    
    filePath = ThisWorkbook.Path
    Debug.Print filePath

    ' 建立 FileSystemObject 物件
    Set oFSO = CreateObject("Scripting.FileSystemObject")

    ' 建立目錄物件
    Set oFolder = oFSO.GetFolder(filePath & "\")


    ' 以迴圈列出所有檔案
     For Each oFile In oFolder.Files
        
        xlsx = Split(oFile.Name, ".")   '用.來分割完整檔案名稱
        
        Debug.Print xlsx(1)             'xlsx(0)檔案名稱 xlsx(1)副檔名
        
        If xlsx(1) = "xlsx" Then        '只取副檔名為xlsx的檔案
            
            oldPath = oFile.Path
            newPath = ThisWorkbook.Path & "\" & xlsx(0) & "-資料夾"        '自訂目標資料夾路徑
                
            If Dir(newPath, vbDirectory) <> "" Then                            '判斷資料夾是否存在
            
                Debug.Print "cmd.exe /c move /Y " & Chr(32) & oldPath & Chr(32) & newPath
            
                Shell "cmd.exe /c move /Y " & Chr(32) & oldPath & Chr(32) & newPath     '執行cmd的move
            Else
                MkDir newPath                                                   '不存在則建立
                Debug.Print "cmd.exe /c move /Y " & Chr(32) & oldPath & Chr(32) & newPath
            
                Shell "cmd.exe /c move /Y " & Chr(32) & oldPath & Chr(32) & newPath     '執行cmd的move
            End If

        End If

     Next oFile
      
End Sub

 

後記

看程序名稱可以知道還有第1個版本

在第1個版本中,我是先將讀取到的檔案資料

分別寫入試算表中

再用迴圈分別讀取儲存格來執行shell函數

好處是可以判斷資料是否正確

缺點就是多餘了點

不過這是順著原本的思路一路修改來的

仔細看程式碼

其實用了兩種方式來操作檔案系統

1種是FileSystemObject

另1種是shell執行cmd指令

而FileSystemObject本身就有移動檔案的MoveFile方法

因此程式碼可以如下修改

	If xlsx(1) = "xlsx" Then        '只取副檔名為xlsx的檔案
        
            oldPath = oFile.Path
            newPath = ThisWorkbook.Path & "\" & xlsx(0) & "-資料夾"        '自訂目標資料夾路徑
            If Dir(newPath, vbDirectory) <> "" Then                            '判斷資料夾是否存在
        
                'Debug.Print "cmd.exe /c move /Y " & Chr(32) & oldPath & Chr(32) & newPath
            
                'Shell "cmd.exe /c move /Y " & Chr(32) & oldPath & Chr(32) & newPath     '執行cmd的move
                
                oFSO.MoveFile oldPath, newPath & "\"
                
            Else
                MkDir newPath                                                   '不存在則建立
                'Debug.Print "cmd.exe /c move /Y " & Chr(32) & oldPath & Chr(32) & newPath
            
                'Shell "cmd.exe /c move /Y " & Chr(32) & oldPath & Chr(32) & newPath     '執行cmd的move
                
                oFSO.MoveFile oldPath, newPath & "\"
                
            End If

        End If

 

當然,也可以都用shell+cmd的方式

只是會比較麻煩,至少我目前想到的方法…