年、月、日の階層構造のフォルダーを作成してアイテムを移動するマクロ

コメントにて以下のご要望をいただきました。


お世話になります。今回初めてコメントをさせていただきます。Outlook2010、Outlook2013の環境で、決まった差出人のメールを、受信トレイ配下に階層深くチェックした後に、移動させたいのですが、その時にフォルダが存在しない時は、作成してメールを移動させたいのですが、1回目は階層深くフォルダを作成し、移動することはできるようになったのですが、翌日、同じマクロを実行すると、最階層の下にフォルダをまた、階層深く作成してしまって、どうにかして、最階層だけ作成して、メールを移動するようにしたいのですが、よくわからないのです。ご教授いただけると助かります。
受信トレイから→チェック済→年度→月→日に移動させたいのです。翌日は新しい日のフォルダが月の下に作成されて、メールが移動される。月が変わったら、新しく月と日のフォルダを作成して、日のフォルダにメールが移動される。年度が変わったら、年度、月、日のフォルダが作成され、新しい日のフォルダにメールが移動されるようにしたいのです。マクロVBAを作成した経験がなく、非常に困っております。どなたかご教授いただけると助かります。よろしくお願いいたします。


フォルダーが存在するかどうかを確認し、存在しない場合だけ作成するようにすれば、ご要望の動作は満たせるでしょう。
以下のようなマクロで実現できます。

' ここをトリプルクリックでマクロ全体を選択できます。
Public Sub MoveByDate()
    Dim objItem As MailItem
    Dim dt As Date
    Dim fldInbox As Folder
    Dim fldChecked As Folder
    Dim fldYear As Folder
    Dim fldMonth As Folder
    Dim fldDay As Folder
    ' 現在開いているか選択しているアイテムを取得
    If TypeName(Application.ActiveWindow) = "Inspector" Then
        Set objItem = ActiveInspector.CurrentItem
    Else
        Set objItem = ActiveExplorer.Selection(1)
    End If
    '
    Set fldInbox = Session.GetDefaultFolder(olFolderInbox)
    Set fldChecked = GetOrCreateFolder(fldInbox, "チェック済み")
    dt = Now ' 今日の日付でフォルダーを作成
    ' フォルダをアイテムの受信日時により作成する場合は下記の記述を使用
    ' dt = objItem.ReceivedTime
    Set fldYear = GetOrCreateFolder(fldChecked, Year(dt))
    Set fldMonth = GetOrCreateFolder(fldYear, Month(dt))
    Set fldDay = GetOrCreateFolder(fldMonth, Day(dt))
    '
    objItem.Move fldDay
End Sub
'
Private Function GetOrCreateFolder(fldParent As Folder, strName As String)
    On Error Resume Next
    Dim fldSub As Folder
    For Each fldSub In fldParent.Folders
        If fldSub.Name = strName Then
            Set GetOrCreateFolder = fldSub
            Exit Function
        End If
    Next
    Set fldSub = fldParent.Folders.Add(strName)
    Set GetOrCreateFolder = fldSub
End Function

マクロの登録方法やメニューへの追加について

HTML 形式の本文に文字列を追加する方法

コメントにて以下のご質問をいただきました。


いつも参考にさせて戴いております。今回初めて質問致します。
HTML形式で図が含まれているメールに対して
mailItem の reply メソッドを行うと図が保持されますが、本文に何かを追記しようとすると図が失われます。
保持する方法はありますでしょうか。
(Outlook 2010 or 2013, VBA はExcel から起動)
ex) objReply.body = “test” + objReply.body –> 図がなくなる


MailItem オブジェクトの Body プロパティはテキスト形式の本文を参照あるいは設定するためのプロパティです。
そのため、このプロパティに文字列を設定すると、メッセージ形式が自動的にテキスト形式に変換され、HTML の書式や図は失われてしまいます。

HTML 形式のメールの本文は HTMLBody プロパティを使って参照や設定を行います。
ただし、本文の先頭に文字列を追加する際に、以下のようにしてしまうと想定外の動作をする場合があります。

objReply.HTMLBody = "test" & objReply.HTMLBody

HTMLBody プロパティは HTML のタグを含んだ HTML 本文全体を取得するのですが、その先頭には <HEAD> タグで囲まれた CSS の定義などが存在します。
それらの定義の前に文字列を追加してしまうと、適切な処理ができなくなる可能性があるのです。

そのため、HTML 本文の先頭に文字列を追加する場合、本文の開始を意味する BODY タグを検出し、その後ろに文字列を追加する必要があります。
以下は、HTML 本文の先頭に文字列を追加するサブルーチンの例です。

' ここをトリプルクリックでマクロ全体を選択できます。
Public Sub InsertStringToHTMLBody(objItem As MailItem, strText As String)
    Dim i As Long
    ' body タグの開始を検索
    i = InStr(LCase(objItem.HTMLBody), "<body")
    ' body タグの終了を検索
    i = InStr(i, objItem.HTMLBody, ">")
    ' body タグの終了位置に文字列を挿入
    objItem.HTMLBody = Left(objItem.HTMLBody, i) & strText & Mid(objItem.HTMLBody, i + 1)
    Debug.Print objItem.HTMLBody
End Sub

Outlook 2016/2013/2010 の累積的な修正プログラム 2017 年 5 月分がリリース

5/2 に Outlook 2016、Outlook 2013 および Outlook 2010 の累積的な修正プログラムがリリースされました。以下は各製品のそれぞれの KB へのリンクです。

Office 2016

Outlook 2016 の修正

2017、5 月 2日が Outlook 2016 (KB3191883) の更新します。
20 件の不具合修正が行われています。

Office 2013

Outlook 2013 の修正

May 2, 2017, update for Outlook 2013 (KB3191889)
3 件の不具合修正が行われています。

Office 2010

Outlook 2010 の修正

2017、5 月 2日は、Outlook 2010 (KB3191906) の更新します。
1 件の不具合修正が行われています。

前の月に受信したメールのうち、特定のキーワードを含むメールをサブフォルダーも含めてカウントするマクロ

前の月に受信したメールのうち、特定のキーワードを含むメールをカウントするマクロのコメントにて以下のご要望をいただきました。


コメント失礼します。
このマクロを試させて頂き、動作を確認させて頂きました。
これは既定フォルダのみ検索したカウント数であると思います。
そうであれば1点機能を追加したいのですが、作り方がわからずご教示頂けましたら幸いです。
<内容>
受信トレイ内にあるすべてのサブフォルダにアクセスし、キーワードカウントをしたいです。
Outlook2013を使用しています。


すべてのサブフォルダーについて処理をする場合は、再帰という方法を使用します。
マクロは以下のようになります。

' ここをトリプルクリックでマクロ全体を選択できます。
Public Sub FindMailByKeywordLastMonthRecursive()
    On Error Resume Next
    ' 検索するキーワードを指定
    Const SEARCH_KEY = "test"
    ' レポートを作成するファイルのフルパスを指定
    Const REPORT_FILE = "c:\temp\report.txt"
    Dim dtStart As Date
    Dim dtEnd As Date
    Dim strFilter As String
    Dim cntItems As Integer
    Dim strReport As String
    ' 前月を表す日付範囲を算出
    dtEnd = Year(Now) & "/" & Month(Now) & "/1"
    dtStart = DateAdd("m", -1, dtEnd)
    ' 日付範囲でフィルタリング
    strFilter = "[受信日時] >= #" & dtStart & "# AND [受信日時] <  #" & dtEnd & "#"
    cntItems = 0
    ' 検索実行
    strReport = FindMailRecursive(Session.GetDefaultFolder(olFolderInbox), strFilter, SEARCH_KEY, cntItems)
    ' レポート作成
    Open REPORT_FILE For Output As #1
    Print #1, SEARCH_KEY & "を含むメールの件数:", cntItems
    Print #1, strReport
    Close #1
    ' レポートをメモ帳で表示
    Shell "notepad.exe " & REPORT_FILE
End Sub
'
Private Function FindMailRecursive(fldRoot As Folder, strFilter As String, strKeyword As String, ByRef cntItems As Integer) As String
    On Error Resume Next
    Dim strReport As String
    Dim colItems As Items
    Dim objItem As Object
    Dim fldSub As Folder
    Debug.Print fldRoot.FolderPath
    ' フィルタ文字列で検索
    Set colItems = fldRoot.Items
    colItems.Restrict strFilter
    strReport = ""
    ' フィルタリングしたメールを確認
    For Each objItem In colItems
        ' 件名にキーワードを含む場合はカウンタとレポート追加
        If objItem Is MailItem Then
            If InStr(1, objItem.Subject, strKeyword, vbTextCompare) > 0 Then
                cntItems = cntItems + 1
                strReport = strReport & objItem.ReceivedTime & vbTab & objItem.Subject & vbCrLf
            End If
        End If
    Next
    ' レポートが存在する場合は先頭にフォルダーパスを追加
    If strReport <> "" Then
        strReport = "フォルダー:" & fldRoot.FolderPath & vbCrLf & strReport
    End If
    ' サブフォルダーについて再帰的に実行
    For Each fldSub In fldRoot.Folders
        strReport = strReport & FindMailRecursive(fldSub, strFilter, strKeyword, cntItems)
    Next
    '
    FindMailRecursive = strReport
End Function

マクロの登録方法やメニューへの追加について

メールの宛先に指定したアドレスを連絡先の名前に置き換えるマクロ

コメントにて以下のご要望をいただきました。


はじめまして。
いつもサイトを拝見させていただき、大変お世話になっております。
Outlook2013で連絡先の閲覧ウインドウで、名前の下にある4つのアイコンの中から一番右のメールのアイコンからメールを作成しようとすると、宛先にはメールアドレスが表示されます。この時にメールアドレスでなく、連絡先に登録してある表示名を宛先に表示する設定とかあるのでしょうか。新しい電子メールから作成した時と、送信済みアイテムの宛先が異なる名前で残ってしまうのが困っています。
宜しくお願い致します。


残念ながら閲覧ウィンドウのボタンで宛先に表示名を付けて追加する設定はありませんが、宛先がアドレスとなっている状態で以下のマクロを実行することでアドレス帳の名前に置き換えることができます。

' ここをトリプルクリックでマクロ全体を選択できます。
Public Sub ResolveWithContacts()
    Dim objMail As MailItem
    Dim objRecip As Recipient
    Dim objContact As ContactItem
    Dim objAddrList As AddressList
    Dim i As Integer
    Dim objAddrEntry As AddressEntry
    Dim bFound As Boolean
    Dim cRecips As Integer
    Dim colAddress() As String
    Dim colName() As String
    Dim colType() As Integer
    Dim strEntryID As String
    '
    Set objMail = ActiveInspector.CurrentItem
    objMail.Save
    objMail.Recipients.ResolveAll
    cRecips = objMail.Recipients.Count
    ReDim colAddress(cRecips) As String
    ReDim colName(cRecips) As String
    ReDim colType(cRecips) As Integer
    For i = cRecips To 1 Step -1
        Set objRecip = objMail.Recipients.Item(i)
        colAddress(i) = objRecip.Address
        colName(i) = objRecip.Name
        colType(i) = objRecip.Type
        objMail.Recipients.Remove i
    Next
    '
    For i = 1 To cRecips
        bFound = False
        For Each objAddrList In Session.AddressLists
            If objAddrList.AddressListType = olOutlookAddressList Then
                For Each objAddrEntry In objAddrList.AddressEntries
                    If objAddrEntry.Address = colAddress(i) Then
                        Set objRecip = objMail.Recipients.Add(colAddress(i))
                        Set objRecip.AddressEntry = objAddrEntry
                        objRecip.Type = colType(i)
                        Exit For
                    End If
                Next
                If Not objRecip Is Nothing Then
                    Exit For
                End If
            End If
        Next
        If objRecip Is Nothing Then
            If colName(i) <> colAddress(i) Then
                Set objRecip = objMail.Recipients.Add(colName(i) & " <" & colAddress(i) & ">")
            Else
                Set objRecip = objMail.Recipients.Add(colAddress(i))
            End If
            objRecip.Type = colType(i)
            objRecip.Resolve
        End If
    Next
    objMail.Close olSave
    objMail.Display
End Sub

マクロの登録方法やメニューへの追加について

Outlook 2016/2013/2010/ 2007 のセキュリティ修正プログラム 2017 年 4 月分がリリース

4/11 に Outlook 2016, 2013, 2010 および 2017 のセキュリティ修正プログラムがリリースされました。メールをプレビューしただけで攻撃される可能性のあるセキュリティ ホールなので、早めに適用したほうが良いでしょう。以下は各製品のそれぞれの KB へのリンクです。

Office 2016

Outlook 2016 のセキュリティ修正

Description of the security update for Outlook 2016: April 11, 2017 2 件のセキュリティ修正と 17 件の不具合修正が行われています。

Word 2016 の修正

April 4, 2017, update for Word 2016 (KB3178720) 1 件の Outlook 2016 に関する修正が行われています。

Office 2013

Outlook 2013 のセキュリティ修正

Description of the security update for Outlook 2013: April 11, 2017 2 件のセキュリティ修正と 5 件の不具合修正が行われています。

Office 2013 のセキュリティ修正

Description of the security update for Office 2013: April 11, 2017 1 件の Outlook 2013 に関するセキュリティ関連ではない修正が行われています。

Office 2010

Outlook 2010 の修正

Description of the security update for Outlook 2010: April 11, 2017 2 件のセキュリティ修正が行われています。

Office 2007

Outlook 2007 の修正

Description of the security update for Outlook 2007: April 11, 2017 2 件のセキュリティ修正が行われています。

選択したメッセージをまとめて一つのテキストファイルに保存するマクロ

コメントにて以下のご要望をいただきました。


win10(32bit)、outlook2016を使用しています。以下の操作を手作業でやっていますが、マクロで行うことは出来ますでしょうか。
・サブフォルダにある複数のメールを選択。(サブフォルダ内の全てのメールでも構いません。)
・選択した状態で「ファイル」「名前を付けて保存」をクリック。
・任意のフォルダを指定、「ファイルの種類(テキスト)」を選択、ファイル名は例えば「123.txt」として保存する。
(結果的に、複数のメールの内容が並んだ1つのテキストファイルが作成されます。)


現在表示中のフォルダーの選択したメールをテキストに保存するマクロは以下のようになります。
フォルダーのすべてのメールを保存したい場合は ActiveExplorer.SelectionActiveExplorer.CurrentFolder.Items としてください。

' ここをトリプルクリックでマクロ全体を選択できます。
Public Sub SaveSelectedAsText()
    On Error Resume Next
    Const TEXT_FILE = "c:\temp\messages.txt" ' 保存するファイル名を指定
    Dim objMail As MailItem
    Dim objAttach As Attachment
    Dim strAttach As String
    '
    Open TEXT_FILE For Output As #1
    For Each objMail In ActiveExplorer.Selection
        With objMail
            Print #1, "差出人:" & vbTab & .SenderName
            Print #1, "送信日時:" & vbTab & .SentOn
            If .To <> "" Then
                Print #1, "宛先:" & vbTab & .To
            End If
            If .CC <> "" Then
                Print #1, "CC:" & vbTab & .CC
            End If
            Print #1, "件名:" & vbTab & .Subject
            If .Attachments.Count > 0 Then
                strAttach = ""
                For Each objAttach In .Attachments
                    strAttach = strAttach & objAttach.FileName & "; "
                Next
                strAttach = Left(strAttach, Len(strAttach) - 2)
                Print #1, "添付ファイル: " & vbTab & strAttach
            End If
            If .Importance <> olImportanceNormal And .Sensitivity <> olNormal Then
                Print #1, ""
            End If
            If .Importance = olImportanceHigh Then
                Print #1, "重要度:" & vbTab & "高"
            End If
            If .Importance = olImportanceHigh Then
                Print #1, "重要度:" & vbTab & "低"
            End If
            If .Sensitivity = olConfidential Then
                Print #1, "秘密度:" & vbTab & "社外秘"
            End If
            If .Sensitivity = olPersonal Then
                Print #1, "秘密度:" & vbTab & "個人用"
            End If
            If .Sensitivity = olPrivate Then
                Print #1, "秘密度:" & vbTab & "親展"
            End If
            If .Categories <> "" Then
                Print #1, ""
                Print #1, "分類項目:" & vbTab & .Categories
            End If
            Print #1, ""
            Print #1, .Body
            Print #1, ""
        End With
    Next
    Close #1
End Sub

マクロの登録方法やメニューへの追加について