【问题标题】:Upload file via FTP from Excel VBA通过 FTP 从 Excel VBA 上传文件
【发布时间】:2011-12-05 23:10:32
【问题描述】:

需要从 Excel VBA 将文件 (file.txt) 上传到服务器 (ftp.server.com)。 (不一定是 FTP,只需要能够将文件放在那里并取回即可,并且我在 GoDaddy 共享主机上有一个服务器)

我尝试的是运行这个脚本:

ftp -s:script.txt

script.txt:

open ftp.server.com
USER
PASS
lcd c:\
put file.txt
disconnect
bye

我得到的错误是:

425 无法打开到端口 53637 的数据连接:连接超时

Google 告诉我需要进入被动模式,但命令行 ftp.exe 客户端不允许这样做。

我有比 FTP 更简单的替代方法,还是有更好的方法通过 VBA 上传文件(无需命令行解决方法)?

我正在考虑使用 DROPBOX(但我真的不想在所有需要该程序的工作站上安装该程序)。

【问题讨论】:

    标签: excel vba ftp


    【解决方案1】:

    http://winscp.net 是免费的,可编写脚本,支持被动模式,绝对是优秀的。

    【讨论】:

    • 我不明白为什么这是公认的答案?这家伙在 excel 中要求 VBA,而不是桌面软件!对于桌面 FileZilla 是最好和最常用的,适用于所有平台:Windows、Linux、Mac:filezilla-project.org
    • @NikolayIvanov:“Filezilla 是最好的”是一个非常主观的观点。 AFAIK,FZ 不可编写脚本,这使得它在许多情况下都无法使用。这是事实:-)
    • @NikolayIvanov:“那个家伙”——正如你所说——可能比你更了解答案。我的建议正好满足了他的需求。
    • @NikolayIvanov 我同意你的观点,这个答案不应该被接受
    【解决方案2】:

    Diego,我已经成功使用下面的代码多年了。该代码从主机获取文件,但我确信可以对其进行修改以将文件放在那里。

    'Start Code
    Set FSO = CreateObject("scripting.filesystemobject")
    
    '**************************************************************************************    '***        Create FTP Action File & Initiate FTP File Transfer
    '**************************************************************************************    VREDET = filename1 'Variable holding name of file to get
    
    F = "C:\Volume\Temp\FTPScript.txt" 'creates the file that holds the FTP commands
    
    Open F For Output As #1
    Print #1, "open ftp.server" 'replace ftp.server with the server address
    Print #1, ID 'login id here
    Print #1, PW 'login password here
    Print #1, "cd " & " Folder1" 'Directory of file location
    Print #1, "cd " & " Folder2" 'Sub-Directory of file location
    Print #1, "ascii"
    Print #1, "prompt"
    'Get the file from the host and save it to the specified directory and filename
    Print #1, "get " & VREDET; " C:\some\directory\" & another-filename & ".CSV"
    Print #1, "disconnect" 'disconnect the session
    Print #1, "bye"
    Print #1, "exit"
    Close #1
    
    'identify folder where ftp resides and execute the FTPScript.txt file
    'vbHide - hides the FTP session
    
    If FSO.FolderExists("C:\Windows\System32") = False Then
        Shell "C:\WINNT\system32\ftp.exe -s:C:\Volume\Temp\FTPScript.txt", vbHide
    Else
        Shell "C:\WINDOWS\system32\ftp.exe -s:C:\Volume\Temp\FTPScript.txt", vbHide
    End If
    'end code
    

    【讨论】:

    • 本机 windows FTP 不支持被动模式,当你需要它时,这是一个很好的选择。
    • thnx @Jeremy,但我真的需要被动模式
    【解决方案3】:

    上面的脚本很棒,我使用以下命令上传文件以及将输出记录到文件中,这在调试时很有用,这是一个常见的误解,即 windows ftp 不能执行被动模式,进入被动模式的命令是 "quote pasv"(我已将其添加到脚本中

    Sub FtpFileto()
        Set FSO = CreateObject("scripting.filesystemobject")
        F = "C:\FTPScript.txt"
        ' Create the ftpscript to be run
    
        Open F For Output As #1
        Print #1, "open ftp.server.com" 'replace ftp.server with the server address
        Print #1, "ID" 'login id here
        Print #1, "PWD" 'login password here
        Print #1, "quote pasv" ' passive mode ftp if needed
        Print #1, "cd " & " /dir" 'Directory of file location
        Print #1, "cd " & " subdir" 'Sub-Directory of file location
        Print #1, "ascii"
        Print #1, "prompt"
        'Put the file from the host and save it to the specified directory and filename
        Print #1, "put " & VREDET; """C:\file1.csv"""; ""
        Print #1, "put " & VREDET; """C:\file2.csv"""; ""
        Print #1, "put " & VREDET; """C:\file3.csv"""; ""
        Print #1, "disconnect" 'disconnect the session
        Print #1, "bye"
        Print #1, "exit"
        Close #1
        'Now for the command to upload to the ftpsite and log it to a text file
        ' the trick is to use the standard command shell which allows logging
    
        Shell "cmd /c C:\WINDOWS\system32\ftp.exe -i -s:C:\FTPScript.txt > c:\ftpuploadlog.txt", vbHide
    
        End Sub
    

    【讨论】:

    【解决方案4】:

    如果您无法使用 Windows ftp.exe(特别是因为 it does not support the passive mode 和 TLS/SSL),您可以使用另一个命令行 FTP 客户端。

    例如要使用WinSCP scripting 上传文件,请使用:

    Call Shell( _
        "C:\path\WinSCP.com /log=C:\path\excel.log /command " & _
        """open ftp://user:password@example.com/"" " & _
        """put C:\path\file.txt /path/"" " & _
        """exit""")
    

    为了便于阅读,上面运行了这些 WinSCP 命令:

    open ftp://user:password@example.com/
    put C:\path\file.txt /path/
    exit
    

    您可以将命令放入脚本文件并使用/script= command-line parameter 运行脚本,类似于ftp -s:,而不是/command


    请参阅Converting Windows FTP script to WinSCP script 的指南。

    您甚至可以拥有WinSCP GUI generate the FTP upload script


    WinSCP 默认为被动模式。

    你也可以使用FTPS (TLS/SSL):

    open ftpes://user:password@example.com/
    

    您也可以使用 VBA 代码中的WinSCP .NET assembly via COM


    (我是 WinSCP 的作者)

    【讨论】:

    【解决方案5】:

    经过大量研究,我找到了一种无需任何 .ocx 文件 Internet 控制文件即可将文件上传到 FTP 位置的方法。这对我有用....

     Declare PtrSafe Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" ( _
            ByVal hInternetSession As Long, ByVal sServerName As String, _
            ByVal nServerPort As Integer, ByVal sUserName As String, _
            ByVal sPassword As String, ByVal lService As Long, _
            ByVal lFlags As Long, ByVal lContext As Long) As Long
        Declare PtrSafe Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" ( _
            ByVal sAgent As String, ByVal lAccessType As Long, _
            ByVal sProxyName As String, _
            ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
        Declare PtrSafe Function FtpSetCurrentDirectory Lib "wininet.dll" Alias _
         "FtpSetCurrentDirectoryA" (ByVal hFtpSession As Long, _
            ByVal lpszDirectory As String) As Boolean
        Declare PtrSafe Function FtpPutFile Lib "wininet.dll" Alias "FtpPutFileA" ( _
            ByVal hConnect As Long, _
            ByVal lpszLocalFile As String, _
            ByVal lpszNewRemoteFile As String, _
            ByVal dwFlags As Long, _
            ByRef dwContext As Long) As Boolean
    
    Sub simpleFtpFileUpload()
    
        Dim ftp, FTP_PORT, user, password, loc_file, remote_file, ftp_folder As Variant
        ftp_folder = "/EXPORT"
        loc_file = ThisWorkbook.Path & "\readme.txt"
        remote_file = ftp_folder & "/readme.txt"
        FTP_PORT = "2221"
        user = "ajay"
        password = "ajay"
        ftp = "192.168.1.110"
    
        Internet_OK = InternetOpen("", 1, "", "", 0)
        If Internet_OK Then
            FTP_OK = InternetConnect(Internet_OK, ftp, FTP_PORT, user, password, 1, 0, 0) ' INTERNET_DEFAULT_FTP_PORT or port no
            If FtpSetCurrentDirectory(FTP_OK, "/") Then
                Success = FtpPutFile(FTP_OK, loc_file, remote_file, FTP_TRANSFER_TYPE_BINARY, 0)
            End If
        End If
        If Success Then
            Debug.Print "ftp success ;)"
            MsgBox "ftp success ;)"
        Else
            Debug.Print "ftp failure :("
            MsgBox "ftp failure :("
        End If
    End Sub
    

    请根据您的需要更改值

        ftp_folder = "/EXPORT"
        loc_file = ThisWorkbook.Path & "\readme.txt"
        remote_file = ftp_folder & "/readme.txt"
        FTP_PORT = "2221"
        user = "ajay"
        password = "ajay"
        ftp = "192.168.1.110"
    

    【讨论】:

      【解决方案6】:

      我也无法使用命令提示符使被动模式工作,但我发现资源管理器工作得更快更有效。

      我已经在另一个子程序中指定了可以改变的地方:

      strFileName = "file.txt"
      strMyFile = "C:\path\file.txt"
      strFTP = "ftp.server.com"
      strUser = "ID"
      strPW = "PWD"
      strSubfolder = "/subfolder"
      

      以及我找到并修改为我使用的代码:

      Sub cmdFTPviaExplorer()
      
          Set oShell = CreateObject("Shell.Application")
          Set objFSO = CreateObject("Scripting.FileSystemObject")
      
          Const copyType = 16
      
          strFTP = "ftp://" & strUser & ":" & strPW & "@" & strFTP & strSubfolder
      
          Set objFTP = oShell.Namespace(strFTP)
      
          'Upload single file
          If objFSO.FileExists(strMyFile) Then
              Set objFile = objFSO.getFile(strMyFile)
              strParent = objFile.ParentFolder
              Set objFolder = oShell.Namespace(strParent)
              Set objItem = objFolder.ParseName(objFile.Name)
              objFTP.CopyHere objItem, copyType
          End If
      
          'Pop-up message box
          MsgBox strFileName & " file created and uploaded"
      
      End Sub
      

      【讨论】:

        猜你喜欢
        • 2012-04-26
        • 2013-03-24
        • 1970-01-01
        • 1970-01-01
        • 2018-01-05
        • 2012-02-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多