Board logo

標題: [發問] vba 讀取 ftp 裡面的檔案清單 [打印本頁]

作者: warhead    時間: 2020-11-2 09:58     標題: vba 讀取 ftp 裡面的檔案清單

我需要常常到公司的ftp抓取資料回來處理,
所以想要利用vba去看看有哪些檔案是更新過的,
在抓回來處理,就不用每一個資料夾都進去看。

但ftp有帳號密碼,無法使用一般dir的方式去尋找,
網路上找不到相關的資料(也可能是我找錯方向),
是否有前輩可以提點一下我該如何做到,或是從哪個方向下手呢?
作者: cody    時間: 2020-11-4 16:18

本帖最後由 cody 於 2020-11-4 16:27 編輯

回復 1# warhead


用 windows 內建 ftp.exe 讀取 Script 的方式
一般是將 ftp comment 做成文字檔, 再用 ftp.exe 去讀取執行
將結果存成文字檔後, 再讀入excel
作者: Joforn    時間: 2020-11-5 23:32

本帖最後由 Joforn 於 2020-11-5 23:33 編輯
  1. Private Function FTPFolder(ByVal Url As String, _
  2.     Optional ByVal UserName As String, _
  3.     Optional ByVal PassWord As String, _
  4.     Optional ByVal Port As Integer) As Object
  5.   Dim objShell  As Object
  6.   
  7.   If Len(Url) Then
  8.     If Len(UserName) Then Url = UserName & ":" & PassWord & "@" & Url
  9.     If Port > 0 Then Url = Url & ":" & Port
  10.     Set objShell = CreateObject("Shell.Application")
  11.     Set FTPFolder = objShell.Namespace("FTP://" & Url)
  12.   End If
  13. End Function

  14. Sub Test()
  15.   Dim objFolder As Object
  16.   Dim objItem   As Object
  17.   
  18.   Set objFolder = FTPFolder("0.0.0.0", "username", "password")
  19.   If Not (objFolder Is Nothing) Then
  20.     For Each objItem In objFolder.Items
  21.       Debug.Print "Name=""" & objItem.Name & """ Size=" & objFolder.GetDetailsOf(objItem, 1) & " ModifyDate=" & objFolder.GetDetailsOf(objItem, 3)
  22.     Next
  23.   End If
  24. End Sub
複製代碼

作者: warhead    時間: 2020-11-9 14:41

回復 2# cody


    好的,我在找時間研究看看ftp的comment,謝謝
作者: warhead    時間: 2020-11-9 14:44

回復 3# Joforn


    這方法可行,感激不盡....
   
    另外在提問一個問題,如果裡面還有資料夾,我是將全部資料夾抓出來,
    在一個一個資料夾進去檢查是否有新的檔案嗎?
    或是有其他方式可行?
作者: Joforn    時間: 2020-11-9 19:50

回復 5# warhead
遞歸查找和對比所有文件。
作者: warhead    時間: 2020-11-10 10:18

回復 6# Joforn
  1.     Private Function FTPFolder(ByVal Url As String, _
  2.     Optional ByVal UserName As String, _
  3.     Optional ByVal PassWord As String, _
  4.     Optional ByVal Port As Integer) As Object
  5.   Dim objShell  As Object
  6.   
  7.   If Len(Url) Then
  8.     If Len(UserName) Then Url = UserName & ":" & PassWord & "@" & Url
  9.     If Port > 0 Then Url = Url & ":" & Port
  10.     Set objShell = CreateObject("Shell.Application")
  11.     Set FTPFolder = objShell.Namespace("FTP://" & Url)
  12.   End If
  13. End Function

  14. Sub test()
  15.   Dim objFolder As Object
  16.   Dim objItem   As Object
  17.   Dim selectFolder
  18.   
  19.   Set objFolder = FTPFolder("118.163.50.55/firmware_software_version_files/", "xxxxx", "xxxx")
  20.   
  21.   If Not (objFolder Is Nothing) Then
  22.    
  23.     selectFolder = objFolder
  24.    
  25.     Call 列出檔案清單(selectFolder)
  26. End If
  27. End Sub

  28. Sub 列出檔案清單(ByVal theDir As String)
  29.     Dim pt As Range
  30.                
  31.     Set pt = Sheet1.Range("a2")
  32.     Call 設定標題(1)
  33.                
  34.     If Len(Dir(theDir, vbDirectory)) > 0 Then
  35.         If (GetAttr(theDir) And vbDirectory) = vbDirectory Then
  36.             Call FileIOUtility.RetrivalFileList(theDir, pt, 0)
  37.         End If
  38.     End If
  39.    
  40.     pt.Worksheet.Columns("A:B").AutoFit
  41. End Su

  42. Function RetrivalFileList(ByVal strDir As String, ByRef myRange As Range, ByRef depth As Integer)
  43.     Dim thePath As String
  44.     Dim strSdir As String
  45.     Dim theDirs As Scripting.Folders
  46.     Dim theDir As Scripting.Folder
  47.     Dim theFile As Scripting.File
  48.     Dim myFso As Scripting.FileSystemObject
  49.     Dim subFolderCount As Integer
  50.    
  51.     Set myFso = New Scripting.FileSystemObject
  52.     If Right(strDir, 1) <> "" Then strDir = strDir & ""
  53.     thePath = thePath & strDir
  54.         
  55.     '列出第一層根目錄的檔案
  56.     If depth = 0 Then
  57.             For Each theFile In myFso.GetFolder(strDir).Files
  58.                 myRange = theFile.Path
  59.                 myRange.Next = theFile.Size
  60.                 myRange.Next.Next = theFile.DateLastModified
  61.                 Set myRange = myRange.Offset(1, 0)
  62.             Next
  63.             depth = 1
  64.     End If
  65.         
  66.     '尋找所有子目錄的檔案
  67.     Set theDirs = myFso.GetFolder(strDir).SubFolders
  68.     For Each theDir In theDirs
  69.         For Each theFile In theDir.Files
  70.             myRange = theFile.Path
  71.             myRange.Next = theFile.Size
  72.             myRange.Next.Next = theFile.DateLastModified
  73.             Set myRange = myRange.Offset(1, 0)
  74.         Next
  75.         RetrivalFileList strDir:=theDir.Path, myRange:=myRange, depth:=depth
  76.     Next
  77.     Set myFso = Nothing
  78. End Function

  79.   
複製代碼
我將檔案路徑丟給selectFolder,會出問題


但如果我給selectFolder 的路徑是電腦本機的卻可以執行,


selectFolder 完整的FTP路徑也會出錯,


是因為FTP查詢的方式跟本機的不一樣嗎??
作者: Joforn    時間: 2020-11-11 00:25

回復 7# warhead
用的是Shell32就不要去混用FSO了,直接用Shell32查找吧。
  1. Option Explicit

  2. Public Property Get FTPSearch(ByVal FTPUrl As String, _
  3.         Optional ByVal UserName As String, _
  4.         Optional ByVal PassWord As String, _
  5.         Optional ByVal Port As Integer) As Collection
  6.                            
  7.   Dim objShell  As Object, objFolder As Object
  8.   
  9.   On Error Resume Next
  10.   
  11.   If Len(FTPUrl) Then
  12.     If Len(UserName) Then FTPUrl = UserName & ":" & PassWord & "@" & FTPUrl
  13.     If Port > 0 Then FTPUrl = FTPUrl & ":" & Port
  14.     Set objShell = CreateObject("Shell.Application")
  15.     Set objFolder = objShell.Namespace("FTP://" & FTPUrl)
  16.   End If
  17.   FTPSearchWithShell FTPSearch, objFolder
  18. End Property

  19. Private Sub FTPSearchWithShell(ByRef Searched As Collection, ByVal Folder As Object)
  20.   Dim FolderItem  As FolderItem
  21.   Dim subSearch   As New Collection
  22.   
  23.   On Error GoTo ErrorLOOP
  24.   
  25.   If Searched Is Nothing Then Set Searched = New Collection
  26.   
  27.   If Folder.Items.Count > 0 Then
  28.     Set subSearch = New Collection
  29.     For Each FolderItem In Folder.Items
  30.       With FolderItem
  31.         If .IsFolder Then
  32.           Set Folder = .GetFolder
  33.           If Folder.Items.Count Then subSearch.Add Folder
  34.         ElseIf .IsBrowsable Then
  35.           Searched.Add .Path
  36.         End If
  37.       End With
  38.     Next FolderItem
  39.    
  40.     For Each Folder In subSearch
  41.       FTPSearchWithShell Searched, Folder
  42.       DoEvents
  43.     Next Folder
  44.   End If
  45. EXITFunction:
  46.   On Error Resume Next
  47.   Exit Sub
  48. ErrorLOOP:
  49.   Err.Clear
  50.   Resume EXITFunction
  51. End Sub

  52. Sub Test()
  53.   Dim Files As Collection
  54.   Dim I     As Long

  55.   Set Files = FTPSearch("118.163.50.55/firmware_software_version_files/", "xxxxx", "xxxx")
  56.   For I = 1 To Files.Count
  57.     Debug.Print Files.Item(I)
  58.   Next I
  59. End Sub
複製代碼

作者: ML089    時間: 2020-11-11 14:17

回復 8# Joforn


這VBA執行OK,可是中文檔案名稱回傳變成亂碼,請問這要如何修正,感恩

第一個VBA執行中文檔案名稱回傳正常
作者: warhead    時間: 2020-11-11 15:33

回復 8# Joforn


    程式可執行,但超出我功力太多,需要時間慢慢消化,謝謝。
作者: Joforn    時間: 2020-11-12 00:07

回復  Joforn


這VBA執行OK,可是中文檔案名稱回傳變成亂碼,請問這要如何修正,感恩

第一個VBA執行 ...
ML089 發表於 2020-11-11 14:17


.Path返回的并不是亂碼,而是將文字進行了Url編碼,可以通過Url解碼得到原字符串,也可以用下面的方式直接返回文字格式。
  1. Public Property Get FTPSearch(ByVal FTPUrl As String, _
  2.         Optional ByVal UserName As String, _
  3.         Optional ByVal PassWord As String, _
  4.         Optional ByVal Port As Integer) As Collection
  5.                            
  6.   Dim objShell  As Object, objFolder As Object
  7.   
  8.   On Error Resume Next
  9.   
  10.   If Len(FTPUrl) Then
  11.     If Len(UserName) Then FTPUrl = UserName & ":" & PassWord & "@" & FTPUrl
  12.     If Port > 0 Then FTPUrl = FTPUrl & ":" & Port
  13.     Set objShell = CreateObject("Shell.Application")
  14.     Set objFolder = objShell.Namespace("FTP://" & FTPUrl)
  15.   End If
  16.   Set FTPSearch = New Collection
  17.   If objFolder Is Nothing Then Exit Function
  18.   
  19.   With objFolder
  20.     If .ParentFolder.Self.IsFolder Then
  21.       If .ParentFolder.ParseName(.Self.Name) Is Nothing Then
  22.         Debug.Print "Error:Invalid Path!"
  23.       ElseIf objFolder.Self.IsBrowsable Then
  24.         Debug.Print "Error:Invalid Parameter!"
  25.       ElseIf objFolder.Self.IsFolder Then
  26.         Debug.Print "Start search files in path..."
  27.         With objFolder
  28.           FTPSearchWithShell FTPSearch, .ParentFolder.ParseName(.Self.Name).GetFolder
  29.         End With
  30.         Debug.Print "Files search completed."
  31.       End If
  32.     ElseIf objFolder.Self.IsFolder Then
  33.       Debug.Print "Start search files in path..."
  34.       With objFolder
  35.         FTPSearchWithShell FTPSearch, objFolder
  36.       End With
  37.       Debug.Print "Files search completed."
  38.     End If
  39.   End With
  40. End Property

  41. Private Sub FTPSearchWithShell(ByVal Searched As Collection, ByVal Folder As Object, Optional ByVal strPath As String)
  42.   Dim FolderItem  As Object
  43.   Dim objFolder   As Object
  44.   Dim subSearch   As New Collection
  45.   
  46.   On Error Resume Next
  47.   
  48.   If Len(strPath) = 0 Then
  49.     Set objFolder = Folder
  50.     Do While (objFolder.ParentFolder.Self.IsFolder)
  51.       strPath = objFolder.Self.Name & "/" & strPath
  52.       Set objFolder = objFolder.ParentFolder
  53.     Loop
  54.     strPath = objFolder.Self.Path & strPath
  55.   End If
  56.   
  57.   If Folder.Items.Count > 0 Then
  58.     Set subSearch = New Collection
  59.     For Each FolderItem In Folder.Items
  60.       With FolderItem
  61.         If .IsFolder Then
  62.           Set Folder = .GetFolder
  63.           If Folder.Items.Count Then subSearch.Add Folder
  64.         ElseIf .IsBrowsable Then
  65.           Searched.Add strPath & .Name
  66.         End If
  67.       End With
  68.     Next FolderItem
  69.    
  70.     For Each Folder In subSearch
  71.       FTPSearchWithShell Searched, Folder
  72.       DoEvents
  73.     Next Folder
  74.   End If
  75. End Sub

  76. Sub Test()
  77.   Dim Files As Collection
  78.   Dim I     As Long
  79.   
  80.   Set Files = FTPSearch("118.163.50.55/firmware_software_version_files/", "xxxxx", "xxxx")
  81.   For I = 1 To Files.Count
  82.     Debug.Print Files.Item(I)
  83.   Next I
  84. End Sub
複製代碼

作者: ML089    時間: 2020-11-12 00:34

回復 11# Joforn

感謝,中文檔名可以正常顯示




歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)