適材適所

WindowsやPowerShellやネットワーク、IBMなどのシステム系の話やポイ活など気になったことも載せているブログです。

VBAでftp.exeを簡単に使うサンプル【Shell関数】

Windowsに標準装備されているftp.exeがVBAから使えると便利ですよね。

Windows PCだけではなく、他のOSとも簡単にファイル交換を行うことができます。

サーバーにデータを送ったり、サーバーからデータを受け取ったり・・・。

ftp.exeはコマンドライン上で対話的に使うこともできますが、

コマンドの内容をファイルに記述しておくとバッチ的に使うこともできます。

枯れ枯っれの技術であるftp。

そんなftpをVBAから簡単に使うサンプルの紹介です。

VBAからftpを簡単に扱うサンプル

ftpをバッチ的に使う場合は、コマンドを書いたテキストファイルをあらかじめ用意してあげる必要があります。

ftp -s:ファイルパス

とすると、ファイルに書かれたftpコマンドが実行されます。

次のサンプルでは、接続先のホスト名、ユーザー名、パスワード、そして処理コマンドを定数として用意しています。

環境に合わせてこれらの定数を編集するようにしてください。

 
Sub FTPSample()
    Const HOST As String = "host"
    Const USER As String = "username"
    Const PASS As String = "password"
    Const COMMAND As String = "get test.txt c:\test.txt"

    'ftpコマンド書き出し用ファイル作成前準備
    Dim ftpFile As String
    ftpFile = ThisWorkbook.Path & "\ftp.tmp"
    If Dir(ftpFile) <> "" Then
        Kill ftpFile
    End If
    
    'ftpコマンドの書き出し用変数
    Dim ftpTemplate As String
    ftpTemplate = _
      "open {host}" & Chr(10) & _
      "{user}" & Chr(10) & _
      "{password}" & Chr(10) & _
      "{command}" & Chr(10) & _
      "Quit"
    
    '各種パラメータを置換する
    Dim ftpString As String
    ftpString = Replace(ftpTemplate, "{host}", HOST)
    ftpString = Replace(ftpString, "{user}", USER)
    ftpString = Replace(ftpString, "{pass}", PASS)
    ftpString = Replace(ftpString, "{command}", COMMAND)
    
    'ftpコマンドの書き出し
    Open ftpFile For Output As #1
    Print #1, ftpString
    Close #1
    
    'ftpコマンドの実行。ここまで長かったが実際はこの1行だけ。
    Shell "ftp -s:" & ftpFile, vbNormalFocus
    
    'ftpの処理待ち。ここは環境に応じて待ち時間を指定する。
    'この例では10秒待機。
    Application.Wait Now() + TimeValue("00:00:10")
    
    '不要になったファイルの削除
    Kill ftpFile
    
End Sub

Shell関数

サンプルのキモはずばりShell関数です。

ftp.exeを実行するにはShell関数を呼び出します。

Shell関数は外部アプリケーションを起動することができる関数です。

オブジェクトブラウザーを見るとVBA.Interactionクラスに属していることが確認できます。

f:id:shinmai_papa:20211122213356p:plain

Shell関数は2つの引数を取ります。

第一引数は起動したいアプリケーションのパス、または実行したい命令文です。

ftp.exeを使う場合は、-s:ファイル名のオプションも一緒に指定します。

第二引数はVBA.VbAppWinStyleの列挙型になります。

f:id:shinmai_papa:20211122213400p:plain

省略値はvbMinimizedFocusです。

各値の意味はこうなっています。

定数 説明
vbHide 0 ウィンドウは非表示で、フォーカスは非表示ウィンドウに渡されます。 vbHide 定数は Macintosh プラットフォームでは適用されません。
vbNormalFocus 1 ウィンドウがフォーカスを持ち、元のサイズと位置に復元されます。
vbMinimizedFocus 2 ウィンドウがフォーカスを持ってアイコンとして表示されます。
vbMaximizedFocus 3 ウィンドウがフォーカスを持って最大化されます。
vbNormalNoFocus 4 ウィンドウは、最新のサイズと位置に復元されます。 現在アクティブなウィンドウはアクティブのままです。
vbMinimizedNoFocus 6 ウィンドウはアイコンとして表示されます。 現在アクティブなウィンドウはアクティブのままです。

戻り値は、成功した場合はプログラムのタスク ID を表す Variant (Double) の値を返し、失敗した場合は 0 を返します。

Shell 関数 (Visual Basic for Applications) | Microsoft Docs

Shell関数を省略せずに書くと

Shell関数ですが、Interactionクラスに所属してますので、もろもろ省略せずに書くと、

 
VBA.Interaction.Shell "ftp", VBA.VbAppWinStyle.vbMaximizedFocus

と書くことができます。

え?だから何・・・?

いえ・・特に意味はありません・・・。

なんとなく、他の関数と色合いが違う関数なので一応、Interactionクラスにいますよ~ということを強調する意味で書いてみました。

このInteractionクラスはDoevents関数やMsgBox関数などお馴染みの関数の他に、音を鳴らすBeep関数、文字列から命令を呼び出す関数のCallByName関数などのおもしろい関数がおります。

Shell関数の注意点

外部アプリケーションを起動することはできますが、起動したアプリは非同期的に実行されるので、そのアプリの終了を待つということはできません。

お手軽な反面、そういった制御はできないので、多用はせず、簡単な処理を実行する程度にとどめておくのが得策かと思います。

処理の同期を取りたいときはWscript.ShellのRunメソッドが簡単

詳しい解説は割愛しますが、Wscript.ShellのRunメソッドを使うと簡単に同期を取ることができます。

 
Sub wscriptshellRun()
   Dim wscriptShell As Object
   Set wscriptShell = CreateObject("WScript.Shell")
   wscriptShell.Run "ftp -s:ftp.txt", , True
   Set wscriptShell =Nothing
End Sub

いちいちWscript.Shellのオブジェクトを作る手間がありますが、確実に処理を待つことができるので絶対に同期をとって処理を進めたいときはこちらがおすすめです。

終わりに

VBAでftpを簡単に起動するサンプルを紹介してみました。

途中から完全にShell関数の解説になってしまいました。

あれ?これ、Shell関数の記事じゃね?

いえいえそんなことはありません。

ftpの記事です(;´∀`)。

というわけでここまでお読みいただき、ありがとうございました。