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関数で余分な文字を指定し、削除します。今回は「です。、さん」などを削除しています。これにより純粋な宛先名のみ取得することができます。