業務効率化

OutlookVBA:本文から宛先抽出関数

Outlookで選択したメールの宛先を抽出するマクロ関数です。選択したメールの親フォルダに応じて送信者と受信者を判定し、適切な宛先名を抽出します。また、DearとFromをキーワードに英語の場合は「Eng 名前」として抽出することでその後の処理で活用できます。

記事の内容

・コード

・ポイント機能

コード

➤コードはこちら
Option Explicit


Function fChkParentFolder(olMail As MailItem)
    Dim olFolder As Folder
    Dim parentFolder As Object ' Parent は Object 型として扱う必要がある場合あり
    Dim folderPath As String
    
    ' Outlook アプリケーションのインスタンスを取得
    'Set olApp = Outlook.Application
    'Set olNamespace = olApp.GetNamespace("MAPI")
      
        ' 選択メールのフォルダを取得
        Set olFolder = olMail.Parent

        ' 現在のフォルダ名を取得
        folderPath = olFolder.Name
        
        ' 親フォルダを取得(ルートフォルダまで再帰的に)
        Set parentFolder = olFolder
        Do While Not parentFolder.Parent Is Nothing
            Set parentFolder = parentFolder.Parent
            If TypeOf parentFolder Is Outlook.Folder Then ' 型を確認してキャスト
                folderPath = parentFolder.Name & "\" & folderPath ' フォルダパスを構築
            Else
                Exit Do
            End If
        Loop

        If InStr(1, folderPath, "受信", vbTextCompare) > 0 Then
            fChkParentFolder = "MSender"
        ElseIf InStr(1, folderPath, "送信", vbTextCompare) > 0 Then
            fChkParentFolder = "MReceiver"
        Else ' 受信ボックスか送信済みボックス以外の場合は受信ボックスの処理
            fChkParentFolder = "MSender"
        End If
        
        Call fExtractNameInMail(fChkParentFolder, Mailbody)
  
End Function


Function fExtractNameInMail(MSenderOrMReceiver As String, Mailbody As Variant) As String
    Dim olApp As Outlook.Application
    Dim olMail As Outlook.MailItem
    Dim olSelection As Selection
    Dim bodyText As String
    Dim MailSender As String
    Dim lines As Variant
    Dim namefrom As String
    Dim KeywordsArray() As Variant
    
    
    bodyText = Mailbody
    
    ' 本文を改行ごとに分割
    lines = Split(bodyText, vbCrLf)
    

     
    ' 先頭3行を結合(4行)
    Dim i As Integer
    For i = LBound(lines) To Application.WorksheetFunction.Min(UBound(lines), 4)
        If i >= 0 Then
            namefrom = namefrom & " " & lines(i)
            If InStr(1, namefrom, "です", vbTextCompare) Then
                namefrom = Trim(namefrom)
                Exit For
            ElseIf InStr(1, namefrom, "from", vbTextCompare) Then
                namefrom = Trim(namefrom)
                i = 100
                Exit For
            End If
        End If
    Next i
     
     '’’’’’’’’’’’’’’’’’’’’’’’’’' 英語メールの場合’’’’’’’’’’’’’’’’’’’’’’’’’
     
    If i = 100 And InStr(1, MSenderOrMReceiver, "MSender", vbTextCompare) > 0 Then
        fExtractNameInMail = "EngName " & Mid(namefrom, InStr(1, namefrom, "from", vbTextCompare) + 5)
        Exit Function
    ElseIf InStr(1, namefrom, "Dear", vbTextCompare) > 0 And InStr(1, namefrom, "from", vbTextCompare) > 0 Then
        fExtractNameInMail = "EngName " & " " & Mid(namefrom, InStr(1, namefrom, "Dear", vbTextCompare) + 5, InStr(1, namefrom, "san", vbTextCompare) - (InStr(1, namefrom, "Dear", vbTextCompare) + 5))
        Exit Function
    ElseIf InStr(1, namefrom, "Dear", vbTextCompare) > 0 Then 'And InStr(1, namefrom, "san", vbTextCompare) > 0 Then
    ' 送信者に送りたいときで、from送信者のような記載もない場合の名前抽出は未実装
        fExtractNameInMail = "EngName "
        Exit Function
    ElseIf InStr(1, namefrom, "san", vbTextCompare) > 0 Or InStr(1, namefrom, "Dear", vbTextCompare) > 0 Then
        fExtractNameInMail = "EngName "
        Exit Function
    End If

    
    Dim TrimedNamefrom As String
    
    KeywordsArray = Array(" ", " ", "、", vbCrLf, vbLf, vbCr, vbTab)
    TrimedNamefrom = namefrom

    TrimedNamefrom = Removekeywords(TrimedNamefrom, KeywordsArray)
    
    TrimedNamefrom = CompareToExtract(MSenderOrMReceiver, namefrom, TrimedNamefrom)
    Debug.Print TrimedNamefrom
    
    KeywordsArray = Array("です。", "です", "。", "、", "さん")
    'Debug.Print Removekeywords(TrimedNamefrom, KeywordsArray)
    TrimedNamefrom = Removekeywords(Trim(TrimedNamefrom), KeywordsArray)
    If InStr(1, MSenderOrMReceiver, "MSender", vbTextCompare) > 0 Then
        TrimedNamefrom = Mid(TrimedNamefrom, InStrRev(TrimedNamefrom, " ", , vbTextCompare) + 1)
    End If
    fExtractNameInMail = Trim(TrimedNamefrom)
    'MsgBox fExtractNameInMail

End Function


Function Removekeywords(text As String, removewords As Variant) As String
    Dim patterns As Variant
    Dim i As Integer

    ' 削除する文字列のリスト
    patterns = removewords
    
    ' 配列をループして置換
    For i = LBound(patterns) To UBound(patterns)
        text = Replace(text, patterns(i), "")
    Next i
    
    ' 結果を返す
    Removekeywords = text
End Function


Function CompareToExtract(MSenderOrMReceiver As String, original As String, trimmed As String) As String
    Dim i As Long
    Dim lengthOriginal As Long
    Dim lengthTrimmed As Long
    
    ' 元の文字列と削除後の文字列の長さを取得
    lengthOriginal = Len(original)
    lengthTrimmed = Len(trimmed)
    
    ' 短い方の長さまで比較
    For i = 1 To Application.WorksheetFunction.Min(lengthOriginal, lengthTrimmed)
        ' 先頭から異なる文字が見つかった場合
        If Mid(original, i, 1) <> Mid(trimmed, i, 1) Then
            If InStr(1, MSenderOrMReceiver, "MSender", vbTextCompare) > 0 Then
                ' その位置から文末までの文字列を削除
                CompareToExtract = Mid(original, i)
                Exit Function
            ElseIf InStr(1, MSenderOrMReceiver, "MReceiver", vbTextCompare) > 0 Then
                ' 先頭からその位置までの文字列を削除
                CompareToExtract = Left(original, i)
                Exit Function
            Else
                ' 先頭からその位置までの文字列を削除
                CompareToExtract = Mid(original, i)
                Exit Function
            End If
        End If
    Next i
    
    ' 異なる部分が見つからない場合
    CompareToExtract = original
End Function





ポイント機能

・選択メールの親フォルダ:ParentFolderの取得

・選択メールのボックスに応じた宛先抽出

ParentFolderの取得

Outlookのメールはそれぞれに対してウィンドウズファイルと同じようにパスの情報があります。そのルートフォルダになる場所に今回使用する受信ボックスと、送信済みボックスの二つの場所があります。今回は送信済みメールに返信するのであれば、メールの宛先を宛先とし、受信ボックスメールに返信するのであれば、メール送信者を宛先にします

そこで、parentFolder変数に選択したメールの親フォルダを親フォルダがなくなるまでDo whileで継続します。そうして得られるパスには、受信ボックスと、送信済みフォルダの文字が入ったパスになります。

これを利用し、選択したメールが受信か送信済みボックスどちらか判定に使います。Instrで単純に一部ワードを検索し含まれているか判定します。

受信ボックスならMSender、送信済みボックスならMReceiver、それ以外はMSenderとして関数に代入します。これを宛先抽出関数で使用します。

選択メールのボックスに応じた宛先抽出

宛先抽出関数ではいくつかの関数を使用します。必要なのは、MSenderかMReceiverかと、選択したメールの本文です。まず、全体文を改行ごとに配列化します。

そして、メール冒頭から検索し、「です」という文字がある行まで抽出します。今回の抽出関数は「○○さん ●●です」か「Dear ○○ san, from ●●」のような和英文頭を持つメールを前提にしています。です/from行を取得することで宛先と送信者が含まれた一行を得られるというわけです。

まず英語のメールであるか判断処理をします。Dear,Fromというキーワードが入っていれば、英文のメールであると判断し、宛先となる部分を抜き出します。MSenderorReceiverがSenderであれば、送信者に送るということなので、From以降の●●を宛先として、「Eng ●●」の形で変数に格納します。これにより、後々Eng を削除し宛先のみを抽出します。

もし上記の英語要処理に当てはまらない場合は日本語の文と見なします。「○○さん ●●です」の文から、○○、●●を抽出するために元の文章と調整した文章を用意します。後者は、空欄や句読点を取り除いたものです。Removekeywords関数で指定したKeywordsArrayに入った値をすべて削除します。

二つの文章および、MSenderorMReceiverを引数に、CompareToExtraxt関数を実行します。関数では、二つの文字の先頭および中部から文字を比較し、異なる箇所があった時点でその場所を抜き出します。「○○さん ●●です」から「○○さん●●です」になり、空欄の箇所が抜出のポイントとなります。

その後取得した値をさらに形成します。上記のままだと敬称等がついており、名前だけの抽出ができていません。そこで再度RemoveKeywords関数で余分な文字を指定し、削除します。今回は「です。、さん」などを削除しています。これにより純粋な宛先名のみ取得することができます。

-業務効率化