World Financial Strategy

Outlook VBAでメール受信をトリガーとしてバッチファイルを実行する

Outlookでメール受信をしたときに、UiPathのRPA実行用バッチファイルを起動したい案件が発生しました。

RPAを実務で活用していると、こんなことがあるかもしれません。

なお、バッチファイルでUiPathのxamlファイルを開いてRPAを実行するには、下記の構文でバッチファイルを作成します。

call "UiRobot.exeのフルパス" /file:"実行対象XAMLファイルのフルパス"

詳細は下記リンクを参考にしてください。

さて、本題のメール受信をトリガーにしたバッチファイルの起動ですが、いろいろと調べたところ、メールの仕分けルールで「スクリプトを実行する」を選択する方法があるようでした。

仕分けルールの「スクリプトを実行する」は新しいOutlookではデフォルトでは選択できませんが、下記のリンクで紹介されているように、レジストリをいじることで選択できるようになるはずでした。

ただ、私の環境では、そこで紹介されている通りにレジストリを設定しても、本当にどうやってもダメでした。

いろいろと調べた結果、OutlookのVBAでApplication_NewMailExイベントを活用すれば、仕分けルールの設定は一切行うことなくVBAのみで、メール受信をトリガーにしたアクションが実現できることが分かりました。

ここではその手順を紹介します。

開発タブの表示

OutlookでVBAを利用するにあたり、まず「開発」タブを表示する必要があります。

「ファイル」→「オプション」→「リボンのユーザー設定」において「開発」にチェックを入れます。

実装

「開発」タブを表示したら、その中にある「Visual Basic」を開きます。

「ThisOutlookSession」に以下のコードをCopy&Pasteします。

Option Explicit

Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)

    '###################################
    '▼変数宣言・初期値セット
    '###################################
    Dim myNamespace As Outlook.NameSpace
    Dim objId As Object
    Dim ExitFlag As Boolean

    Set myNamespace = GetNamespace("MAPI")
    Set objId = myNamespace.GetItemFromID(EntryIDCollection)
    ExitFlag = False

    '###################################
    '▼メイン処理
    '▼
    '▼将来的に件名の特定の文字列とバッチファイルの組み合わせを増やしたい場合は、
    '▼Call ExeBatchFile(~~)からEnd Ifまでの段落を増やせばよい。
    '###################################
    Call ExeBatchFile(objId, "トリガーとしたいメールの件名1", "バッチファイルのフルパス1", ExitFlag)
    If ExitFlag = True Then
        Exit Sub
    End If

    Call ExeBatchFile(objId, "トリガーとしたいメールの件名2", "バッチファイルのフルパス2", ExitFlag)
    If ExitFlag = True Then
        Exit Sub
    End If

    Call ExeBatchFile(objId, "トリガーとしたいメールの件名3", "バッチファイルのフルパス3", ExitFlag)
    If ExitFlag = True Then
        Exit Sub
    End If
    
End Sub

Private Sub ExeBatchFile(o1 As Object, s1, s2 As Variant, ef As Boolean)
    '▼引数の片方でも文字列型以外の場合は処理終了
    If VarType(s1) <> vbString Or VarType(s2) <> vbString Then
        '▼呼び出し元を終了させるフラグをTrueに
        ef = True
        Exit Sub
    End If
    
    If InStr(o1.Subject, s1) Then
        '###################################
        '▼Runメソッドの第2引数リスト(省略時の値は1となる)
        '###################################
        Const vbHide = 0             'ウィンドウ・スタイル:非表示  ,アクティブ・ウィンドウ:そのまま(変わらない)
        Const vbNormalFocus = 1      'ウィンドウ・スタイル:通常サイズ,アクティブ・ウィンドウ:起動したアプリケーション
        Const vbMinimizedFocus = 2   'ウィンドウ・スタイル:最小化  ,アクティブ・ウィンドウ:起動したアプリケーション
        Const vbMaximizedFocus = 3   'ウィンドウ・スタイル:最大化  ,アクティブ・ウィンドウ:起動したアプリケーション
        Const vbNormalNoFocus = 4    'ウィンドウ・スタイル:通常サイズ,アクティブ・ウィンドウ:そのまま(変わらない)
        Const vbMinimizedNoFocus = 7 'ウィンドウ・スタイル:最小化  ,アクティブ・ウィンドウ:そのまま(変わらない)
 
        Dim objWShell
        Set objWShell = CreateObject("WScript.Shell")

        '###################################
        '▼Runメソッドの第3引数は省略時はFalse
        '▼
        '▼True : アプリケーションが終了するまでスクリプトが待機する(同期処理)
        '▼False: アプリケーションの終了を待たずにRunメソッドの次の行が実行される(非同期処理)
        '###################################
        objWShell.Run "cmd /c " & s2, vbMinimizedNoFocus, False
        
        Set objWShell = Nothing
        
        '▼受信トレイのメールを削除
        o1.Delete
        
        '▼削除済みアイテムに移す処理がサーバーに反映されてから次の処理に移るため待機
        'Outlook.Application.Wait (Now() + TimeValue("00:00:03")) --これではダメだった
        Call Sleep(3000)
        
        '▼削除済みアイテムに移したメールを即削除
        Session.GetDefaultFolder(olFolderDeletedItems).Items(Session.GetDefaultFolder(olFolderDeletedItems).Items.Count).Delete

        '▼呼び出し元を終了させるフラグをTrueに
        ef = True
    End If
End Sub

22, 27, 32行目の”トリガーとしたいメールの件名”, “バッチファイルのフルパス”は、それぞれ皆さんが実際に設定したい通りに変更してください。

貼り付け後のイメージはこんな感じです。

51~56行目は、バッチファイルをどんなウィンドウ・スタイルで、またアクティブ・ウィンドウをどのようにして実行するかのパラメータを変数に格納しています。

ご希望の実行の仕方を67行目のRunメソッドの第2引数で指定してあげます。

上記コードは私が今回実装したコードですが、今回はコマンドプロンプトの黒い画面がアクティブ・ウィンドウになって欲しくない上に邪魔なので、最小化かつアクティブ・ウィンドウにしないような設定にしてあります。

ただ、実はこれだけでは動きません。

76行目の「Call Sleep(3000)」のところを動かすためには、標準モジュールに下記のコードの追加が必要です。

「挿入(I)」→「標準モジュール(M)」を選択することで標準モジュールが挿入されます。

挿入した標準モジュールに下記のコードを追加してください。

#If Win64 Then
    Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
#Else
    Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

以下は貼り付け後の画面のイメージです。

こちらに関しては下記を参考にさせていただきました。

VBAで指定した秒数だけ処理を止める方法【Sleep関数(API)】|CATIAマクロの作成方法 LiCLOG 2020年5月18日閲覧。

感想

これで晴れて、RPA用PCのOutlookを起動しておくことで、任意のタイミングで任意のRPAを実行できる体制が整いました。

いろいろと業務の自動化に貢献するRPAですが、活用の幅が1つ広がりました。

WFS記事下レスポンシブ

シェアする

  • このエントリーをはてなブックマークに追加
トップへ戻る