ACCESS VBAでFTP接続に関する処理サンプル

こちらの記事では ACCESS VBAでのFTP接続に関する処理サンプルを掲載しています。

Windows APIのwininet.dllを利用する事で、FTPでのファイルアップロードやダウンロード等が一通り行えます。サンプルには呼び出す側のソースはありませんので別途作成が必要です。

以下に掲載するサンプルソースは標準モジュールに書き込んで、フォームの各処理から呼び出して利用します。

主な処理は下記の目次の通りになります。

 

sponsor link

必須)WindowsAPI、グローバル変数、定数の宣言

いずれの処理を使う場合もこの部分の記載は必須です。

FTP_HOST,FTP_USER,FTP_DIRは環境に合わせて修正が必要です。

32bitバージョンAccessの場合はPrivate Declare PtrSafe の部分から PtrSafe を削除します。

Option Compare Database
Option Explicit

Private Declare PtrSafe Function InternetOpen _
    Lib "wininet.dll" Alias "InternetOpenA" _
    (ByVal lpszAgent As String, ByVal dwAccessType As Long, _
     ByVal lpszProxyName As String, ByVal lpszProxyBypass As String, _
     ByVal dwFlags As Long) As Long
Private Declare PtrSafe Function InternetConnect Lib _
    "wininet.dll" Alias "InternetConnectA" _
    (ByVal hInternetSession As Long, ByVal lpszServerName As String, _
     ByVal nServerPort As Integer, ByVal lpszUsername As String, _
     ByVal lpszPassword As String, ByVal dwService As Long, _
     ByVal dwFlags As Long, ByVal dwContext As Long) As Long
Public Declare PtrSafe Function FtpSetCurrentDirectory _
    Lib "wininet.dll" Alias "FtpSetCurrentDirectoryA" _
    (ByVal hFtpSession As Long, ByVal lpszDirectory As String) As Long
Private Declare PtrSafe Function FtpPutFile _
    Lib "wininet.dll" Alias "FtpPutFileA" _
    (ByVal hFtpSession As Long, ByRef lpszLocalFile As Byte, _
     ByRef lpszNewRemoteFile As Byte, ByVal dwFlags As Long, _
     ByVal dwContext As Long) As Long
Public Declare PtrSafe Function FtpGetFile _
    Lib "wininet.dll" Alias "FtpGetFileA" _
    (ByVal hFtpSession As Long, ByVal lpszRemoteFile As String, _
     ByVal lpszNewFile As String, ByVal fFailIfExists As Long, _
     ByVal dwFlagsAndAttributes As Long, ByVal dwFlags As Long, _
     ByVal dwContext As Long) As Long
Public Declare PtrSafe Function FtpDeleteFile _
    Lib "wininet.dll" Alias "FtpDeleteFileA" _
    (ByVal hConnect As Long, ByVal lpszFileName As String) As Long
Private Declare PtrSafe Function InternetCloseHandle _
    Lib "wininet.dll" _
    (ByVal hInet As Long) As Long
Private Declare PtrSafe Function FtpFindFirstFile Lib "wininet.dll" Alias "FtpFindFirstFileA" _
    (ByVal hFtpSession As Long, _
    ByVal lpszSearchFile As String, _
    lpFindFileData As WIN32_FIND_DATA, _
    ByVal dwFlags As Long, _
    ByVal dwContent As Long) As Long
Private Declare PtrSafe Function InternetFindNextFile Lib "wininet.dll" Alias "InternetFindNextFileA" _
    (ByVal lngFind As Long, lpvFindData As WIN32_FIND_DATA) As Long
        
Private Const FILE_ATTRIBUTE_DIRECTORY = &H10
Private Const FILE_ATTRIBUTE_NORMAL = &H80
Private Const INTERNET_FLAG_RELOAD = &H80000000
Private Const INTERNET_OPEN_TYPE_PRECONFIG = 0
Private Const INTERNET_DEFAULT_FTP_PORT = 21
Private Const INTERNET_SERVICE_FTP = 1&
Private Const FTP_TRANSFER_TYPE_ASCII = &H1
Private Const FTP_TRANSFER_TYPE_BINARY = &H2

'以下3つの定数は環境に応じて設定してください。
Private Const FTP_HOST As String = "*****.ne.jp" 'FTPホスト
Private Const FTP_USER As String = "*****"       'FTPアカウント
Private Const FTP_DIR As String = "/ftp/dir"     'FTPサーバ上の参照先ディレクトリパス

Private Const MAX_PATH      As Long = 260&
Private Type FILETIME
    dwLowDateTime   As Long
    dwHighDateTime  As Long
End Type
Private Type WIN32_FIND_DATA
    dwFileAttributes        As Long
    ftCreationTime          As FILETIME
    ftLastAccessTime        As FILETIME
    ftLastWriteTime         As FILETIME
    nFileSizeHigh           As Long
    nFileSizeLow            As Long
    dwReserved0             As Long
    dwReserved1             As Long
    cFileName               As String * MAX_PATH
    cAlternateFileName      As String * 14
End Type

Public AryFile() As String 'ファイル名一覧

 

 

FTPでファイル一覧を取得

FTPサーバー上のファイル一覧を取得する処理です。

取得結果はグローバル配列の AryFile() に格納されます。

'----------------------------------------------------------------------------
' Summary: FTPファイル一覧を取得
' Description. 取得結果はグローバル配列の AryFile() に格納されます.
' return boolean: True=ファイルあり,False=失敗orファイルなし
'----------------------------------------------------------------------------
Public Function GetFTPFileList() As Boolean
    On Error GoTo ErrorHandler
    Dim w32FindData As WIN32_FIND_DATA
    Dim lngInet As Long 'インターネットサービスのハンドル
    Dim lngFTP As Long 'FTPセッションのハンドル
    Dim lngRet As Long
    Dim lngFind As Long
    Dim lngCount As Long
    Dim result As Long
    Dim strPass As String
    Dim strFile As String
    GetFTPFileList = False
    '前回接続時のFTPパスワードを取得
    strPass = GetFTPPass
    lngInet = 0
    lngFTP = 0
    lngCount = -1
    Erase AryFile

    'インターネットサービスのハンドル取得
    lngInet = InternetOpen(vbNullString, INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0&)
    If (lngInet <> 0) Then 'ハンドル取得成功
OpenFTP:
        'FTPサーバーに接続
        lngFTP = InternetConnect(lngInet, FTP_HOST, _
                                  INTERNET_DEFAULT_FTP_PORT, _
                                  FTP_USER, strPass, _
                                  INTERNET_SERVICE_FTP, 0&, 0&)
        If lngFTP <> 0 Then
            Call UpdateFTPPass(strPass) 'FTPパス更新
            'FTPサーバカレントディレクトリを変更
            result = FtpSetCurrentDirectory(lngFTP, FTP_DIR)
            If (result <> 0) Then
                'CSVファイルのみを対象にする場合は"*.csv"と指定
                lngFind = FtpFindFirstFile(lngFTP, "*", w32FindData, INTERNET_FLAG_RELOAD, 0)
                If (lngFind = 0) Then
                    MsgBox "FTPサーバ上にファイルがありません。"
                Else
                    Do
                   strFile = Trim(Left(w32FindData.cFileName, InStr(w32FindData.cFileName, vbNullChar) - 1))
                        lngCount = lngCount + 1
                        ReDim Preserve AryFile(lngCount)
                        AryFile(lngCount) = strFile
                    '次のファイル名を取得
                    Loop Until InternetFindNextFile(lngFind, w32FindData) = 0 
                    GetFTPFileList = True
                End If
            Else
                MsgBox "ディレクトリ取得に失敗しました。"
            End If
        Else
            strPass = InputBox("FTP接続に失敗しました。" & vbNewLine & "パスワードを入力してください。", "FTPサーバ接続", strPass)
            If StrPtr(strPass) <> 0 Then
                GoTo OpenFTP 'リトライ
            End If
        End If
    Else
        MsgBox "FTP接続に失敗しました。"
    End If

    GoTo Finally
    
ErrorHandler:
    MsgBox "[No:" & Err.Number & "]" & Err.Description, vbCritical, "エラーが発生しました。"

Finally:
    'FTPセッションクローズ
    If (lngFTP <> 0) Then InternetCloseHandle lngFTP
    'インターネットサービスクローズ
    If (lngInet <> 0) Then InternetCloseHandle lngInet
End Function

 

 

FTPでファイルをダウンロード

FTPサーバー上のファイルをダウンロードする処理です。

上記に記載している、FTPファイル一覧を取得する処理、GetFTPFileList関数で取得したファイル名のいずれかと、保存先ファイル名のフルパスを指定します。

'----------------------------------------------------------------------------
' Summary: FTPダウンロード
' Discription:GetFTPFileList関数で取得したファイル名のいずれかと、保存先ファイル名のフルパスを指定します。
' param strFrom:ダウンロードするファイル名
' param strTo:ダウンロード後の保存先ファイルのフルパス
' return boolean: True=成功,False=失敗
'----------------------------------------------------------------------------
Public Function FtpDownload(ByVal strFrom As String, ByVal strTo As String) As Boolean
    On Error GoTo ErrorHandler

    Dim lngInet As Long
    Dim lngFTP As Long
    Dim lngRet As Long
    Dim strPass As String
    Dim strFile As String
    FtpDownload = False
    '前回接続時のFTPパスワードを取得
    strPass = GetFTPPass
    lngInet = 0
    lngFTP = 0

    'FTPをオープン
    lngInet = InternetOpen(vbNullString, INTERNET_OPEN_TYPE_PRECONFIG, _
                            vbNullString, vbNullString, 0&)
    If lngInet <> 0 Then
OpenFTP:
        'FTPサーバ接続
        lngFTP = InternetConnect(lngInet, FTP_HOST, _
                                  INTERNET_DEFAULT_FTP_PORT, _
                                  FTP_USER, strPass, _
                                  INTERNET_SERVICE_FTP, 0&, 0&)
        If lngFTP <> 0 Then
            'FTP接続成功
            Call UpdateFTPPass(strPass) 'FTPパス更新
            'ダウンロード先ファイルがあったら削除
            If Len(Dir(strTo)) > 0 Then Kill strTo
            'ダウンロード元ディレクトリへ移動
            FtpSetCurrentDirectory lngFTP, FTP_DIR
            'バイナリモードFTP_TRANSFER_TYPE_BINRYでダウンロード
            'ASCIIの場合はFTP_TRANSFER_TYPE_ASCIIを指定
            lngRet = FtpGetFile(lngFTP, strFrom, strTo, _
                                 1&, FILE_ATTRIBUTE_NORMAL, _
                                 FTP_TRANSFER_TYPE_BINARY, 0&)
            If lngRet <> 0 Then FtpDownload = True
        Else
            strPass = InputBox("FTP接続に失敗しました。" & vbNewLine & "パスワードを入力してください。", "FTPサーバ接続", strPass)
            If StrPtr(strPass) <> 0 Then
                GoTo OpenFTP 'リトライ
            End If
        End If
    End If
    
    GoTo Finally

ErrorHandler:
    MsgBox "[No:" & Err.Number & "]" & Err.Description, vbCritical, "エラーが発生しました。"

Finally:
    'FTPセッションクローズ
    If (lngFTP <> 0) Then InternetCloseHandle lngFTP
    'インターネットサービスクローズ
    If (lngInet <> 0) Then InternetCloseHandle lngInet
End Function

 

 

FTPでファイルをアップロード

FTPでアップロードする処理です。

'----------------------------------------------------------------------------
' Summary: FTPアップロード
' param strFrom:アップロード元ローカルファイルのフルパス
' param strTo:アップロード先に配置する時のファイル名
'----------------------------------------------------------------------------
Public Function FtpUpload(ByVal strFrom As String _
        , Optional ByVal strTo As String)
    On Error GoTo ErrorHandler
    
    Dim strPass As String
    Dim abytFrom() As Byte
    Dim abytTo() As Byte
    Dim lngInet As Long
    Dim lngFTP As Long
    Dim lngRet As Long
    lngInet = 0
    lngFTP = 0
    
    '前回接続時のFTPパスワードを取得
    strPass = GetFTPPass
    'インターネットサービスのハンドル取得
    lngInet = InternetOpen(vbNullString, INTERNET_OPEN_TYPE_PRECONFIG, _
                            vbNullString, vbNullString, 0&)
      
    If lngInet <> 0 Then
OpenFTP:
        'FTPサーバ接続
        lngFTP = InternetConnect(lngInet, FTP_HOST, _
                  INTERNET_DEFAULT_FTP_PORT, _
                  FTP_USER, strPass, _
                  INTERNET_SERVICE_FTP, 0&, 0&)
      
        If lngFTP <> 0 Then
            Call UpdateFTPPass(strPass) 'FTPパス更新
            'アップロード先ディレクトリへ移動
            FtpSetCurrentDirectory lngFTP, FTP_DIR
            'ファイル名をUnicodeからシステムの規定コードに変換
            abytFrom = StrConv((strFrom & vbNullChar), vbFromUnicode)
            abytTo = StrConv((strTo & vbNullChar), vbFromUnicode)
            'バイナリモードFTP_TRANSFER_TYPE_BINRYでアップロード
            'ASCIIの場合はFTP_TRANSFER_TYPE_ASCIIを指定
            lngRet = FtpPutFile(lngFTP, abytFrom(0), abytTo(0), _
                                  FTP_TRANSFER_TYPE_BINARY, 0&)
            If lngRet <> 0 Then
                'FTPアップロード成功
                MsgBox "ファイルのアップロードが完了しました。", vbOKOnly + vbInformation
            Else
                MsgBox "FTPアップロードに失敗しました。"
            End If
        Else
            strPass = InputBox("FTP接続に失敗しました。" & vbNewLine & "パスワードを入力してください。", "FTPサーバ接続", strPass)
            If StrPtr(strPass) <> 0 Then
                GoTo OpenFTP 'リトライ
            End If        
        End If
    Else
        MsgBox "FTP接続に失敗しました。"
    End If
    
    GoTo Finally
    
ErrorHandler:
    MsgBox "[No:" & Err.Number & "]" & Err.Description, vbCritical, "エラーが発生しました。"

Finally:
    'FTPセッションクローズ
    If (lngFTP <> 0) Then InternetCloseHandle lngFTP
    'インターネットサービスクローズ
    If (lngInet <> 0) Then InternetCloseHandle lngInet
End Function

 

 

FTPサーバー上のファイルを削除

FTPサーバー上のファイルを削除する処理です。

削除するファイル名の指定が無い場合は全て削除します。

'----------------------------------------------------------------------------
' Summary: FTPサーバー上のファイルを削除
' Description. 削除ファイル名の指定が無い場合は全て削除.
' param strFile: 削除ファイル名
' return boolean: True=成功,False=失敗
'----------------------------------------------------------------------------
Public Function FtpDelete(Optional ByVal strFile As String = "") As Boolean
    On Error GoTo ErrorHandler
    Dim w32FindData As WIN32_FIND_DATA
    Dim lngInet As Long 'インターネットサービスのハンドル
    Dim lngFTP As Long 'FTPセッションのハンドル
    Dim lngRet As Long
    Dim lngFind As Long
    Dim result As Long
    Dim strPass As String
    FtpDelete = False
    '前回接続時のFTPパスワードを取得
    strPass = GetFTPPass
    lngInet = 0
    lngFTP = 0
    Erase AryFile

    'インターネットサービスのハンドル取得
    lngInet = InternetOpen(vbNullString, INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0&)
    If (lngInet <> 0) Then 'ハンドル取得成功
OpenFTP:
        'FTPサーバーに接続
        lngFTP = InternetConnect(lngInet, FTP_HOST, _
                  INTERNET_DEFAULT_FTP_PORT, _
                  FTP_USER, strPass, _
                  INTERNET_SERVICE_FTP, 0&, 0&)
        If lngFTP <> 0 Then
            Call UpdateFTPPass(strPass) 'FTPパス更新
            'FTPサーバカレントディレクトリを変更
            result = FtpSetCurrentDirectory(lngFTP, FTP_DIR)
                    
            If (result <> 0) Then 'ディレクトリ変更成功
                'csvファイルのみを対象とする場合は *.csv と指定
                lngFind = FtpFindFirstFile(lngFTP, "*", w32FindData, INTERNET_FLAG_RELOAD, 0)
                If (lngFind = 0) Then
                    'ファイルなし
                Else
                    If strFile = "" Then
                        Do
                            strFile = Left(w32FindData.cFileName, InStr(w32FindData.cFileName, vbNullChar) - 1)
                            result = FtpDeleteFile(lngFTP, strFile)
                        Loop Until InternetFindNextFile(lngFind, w32FindData) = 0 '次のファイル名を取得
                    Else
                        result = FtpDeleteFile(lngFTP, strFile)
                    End If
                End If
                If result Then FtpDelete = True
            Else
                MsgBox "ディレクトリの移動に失敗しました。" & Err.LastDllError
            End If
        Else
            strPass = InputBox("FTP接続に失敗しました。" & vbNewLine & "パスワードを入力してください。", "FTPサーバ接続", strPass)
            If StrPtr(strPass) <> 0 Then
                GoTo OpenFTP 'リトライ
            End If
        End If    
    Else
        MsgBox "FTP接続に失敗しました。"
    End If

    GoTo Finally
    
ErrorHandler:
    MsgBox "[No:" & Err.Number & "]" & Err.Description, vbCritical, "エラーが発生しました。"

Finally:
    'FTPセッションクローズ
    If (lngFTP <> 0) Then InternetCloseHandle lngFTP
    'インターネットサービスクローズ
    If (lngInet <> 0) Then InternetCloseHandle lngInet
End Function

 

 

FTPパスワードを取得

ローカルテーブルで管理するFTPパスワードを取得する処理です。

ローカルACCESSファイル内に T_FTP テーブルが自動的に作成されます。

テーブルの存在チェックに ADO Extライブラリを 利用しているため、予め下記手順でADO Extライブラリを追加してください。

Visual Basic Editorのメニュー [ツール] ⇒ [参照設定] より『Microsoft ADO Ext. 6.0 for DDL and Security』を追加。

'----------------------------------------------------------------------------
' Summary:FTPパスワードを取得
' ※暗号化してないので、利用者が複数なら暗号化するか都度入力する方向に。
'----------------------------------------------------------------------------
Private Function GetFTPPass() As String
    On Error GoTo ErrorHandler
    
    Dim sql As String
    Dim cn As ADODB.Connection
    Set cn = CurrentProject.Connection
    Dim rs As ADODB.Recordset
    Set rs = cn.OpenSchema(adSchemaTables)
    
    'T_FTPテーブル存在チェック
    Dim isExist As Boolean
    Do Until rs.EOF
        If rs!TABLE_NAME = "T_FTP" Then
            isExist = True
            Exit Do
        End If
        rs.MoveNext
    Loop
    rs.Close

    If isExist = False Then
        'T_FTPテーブル作成
        Dim cat As New ADOX.Catalog
        cat.ActiveConnection = cn
        Dim tbl As New ADOX.Table
        tbl.Name = "T_FTP"
        Set tbl.ParentCatalog = cat
        tbl.Columns.Append "FTP_USER", adVarWChar
        tbl.Columns.Append "FTP_PASS", adVarWChar
        cat.Tables.Append tbl
        Set cat = Nothing
        cn.Execute "CREATE INDEX index1 ON T_FTP (FTP_USER);"
    End If

    sql = "SELECT * FROM T_FTP WHERE T_FTP.FTP_USER='" & FTP_USER & "'"
    rs.Open sql, cn, adOpenStatic, adLockReadOnly
    If rs.RecordCount = 1 Then
        GetFTPPass = rs!FTP_PASS
    Else
        GetFTPPass = ""
    End If
    
    GoTo Finally
    
ErrorHandler:
    GetFTPPass = ""
    MsgBox "[No:" & Err.Number & "]" & Err.Description, vbCritical, "エラーが発生しました。"
    
Finally:
    If Not cn Is Nothing Then
        If cn.State = adStateOpen Then cn.Close
        Set cn = Nothing
    End If
End Function

 

 

FTPパスワードを更新

ローカルテーブルで管理するFTPパスワードを更新する処理です。

'----------------------------------------------------------------------------
' Summary:FTPパスワードを更新
' ※暗号化していないので、利用者が複数なら暗号化するか都度入力する方向に。
' param strPass 新FTPパスワード
'----------------------------------------------------------------------------
Private Function UpdateFTPPass(ByVal strPass As String) As String
    On Error GoTo ErrorHandler
    
    Dim sql As String
    Dim rs As New ADODB.Recordset
    Dim cn As ADODB.Connection
    Set cn = CurrentProject.Connection
    
    sql = "SELECT * FROM T_FTP" & _
    " WHERE T_FTP.FTP_USER='" & FTP_USER & "'"
    
    rs.CursorLocation = adUseClient
    rs.Open sql, cn, adOpenDynamic, adLockOptimistic
    cn.BeginTrans
    
    If rs.RecordCount = 1 Then
        rs.Update "FTP_PASS", strPass
    Else
        '新規登録
        sql = "INSERT INTO T_FTP (FTP_USER, FTP_PASS)"
        sql = sql & " VALUES ("
        sql = sql & "'" & FTP_USER & "'"
        sql = sql & ",'" & strPass & "'"
        sql = sql & ")"
        cn.Execute sql
    End If
    cn.CommitTrans
    
    GoTo Finally
    
ErrorHandler:
    MsgBox "[No:" & Err.Number & "]" & Err.Description, vbCritical, "エラーが発生しました。"
    
Finally:
    If Not cn Is Nothing Then
        If cn.State = adStateOpen Then cn.Close
        Set cn = Nothing
    End If
End Function

FTP接続時のパスワードをローカルテーブルで管理するようにしています、FTP接続が失敗した場合はパスワードの再入力を促してきます。正常に接続できた場合は、新しいパスワードをテーブルに保存します。この機能が不要な場合はパスワードの取得( GetFTPPass )と更新関数( UpdateFTPPass )の呼び出し箇所を修正してパスワード直接指定に変更してください。

パスワード保存機能を利用する場合は T_FTP テーブルが作成されている必要があります。T_FTPテーブルは「FTPパスワードを取得」の処理部分で自動作成されるようになっています。

タイトルとURLをコピーしました