015 年の 12 月に Outlook でメッセージをプレビューしただけで悪意のあるコードを実行されてしまうという Word の脆弱性に対応するセキュリティ修正プログラムがリリースされましたが、それに関連して以下のブログの脆弱性が話題になっているようです。 OLEOutlook – bypass almost every Corporate security control with a point’n’click GUI このブログで記載されている脆弱性というのは、以下のような手順でメールを送信することにより、exe ファイルを意図せず実行させられるというものです。 この問題に対する対処方法としては、mso を危険な添付ファイルの拡張子としてブロックする設定を行うというものがあります。 ※ <ver> は Outlook のバージョン (2007 = 12.0、2010 = 14.0、2013 = 15.0、2016 = 16.0) 上記以外の設定方法については Outlook 2013 で添付ファイル設定を計画する をご覧ください。 HTML メールで OLE オブジェクトを埋め込んだ場合は拡張子が .mso となるので、上記の設定により OLE パッケージ オブジェクトが埋め込まれたとしても実行ができなくなります。 なお、上記のブログでは回避策として ShowOLEPackageObj というレジストリ設定を 0 にするというものが紹介されていますが、これは回避策とはなりません。 また、ShowOLEPackageObj は既定で 0 (= 表示しない) となっているため、通常はリッチテキスト形式で上記の手順を実行しても OLE パッケージ オブジェクトは表示すらされません。 メッセージ形式により OLE オブジェクトの動作や設定が変わり、ちょっとわかりにくいかと思いましたので、整理してみました。
(このとき、アイコンや名前を変更し、通常のファイルのように偽装できます。)
Outlook での拡張子による添付ファイルのブロック方法はいくつかありますが、ユーザー権限でできる方法は以下のレジストリ設定となります。 キー: HKEY_CURRENT_USER\Software\Microsoft\Office\<Ver>\Outlook\Security
名前: Level1Add
種類: REG_SZ
値: .mso
ただし、この設定を行うと、パッケージ オブジェクトだけでなく、Excel ワークシートや PowerPoint スライドなど他の OLE オブジェクトも実行できなくなります。
そのため、Excel ワークシートを埋め込んで返信時にフォームのように入力させたり、AllowInplaceOleActivation レジストリの設定により受信時の OLE オブジェクト実行を可能としているような場合には注意が必要です。
何故なら、ShowOLEPackageObj が有効なのはリッチテキスト形式で本文に OLE パッケージ オブジェクトが埋め込まれている場合であり、HTML 形式のメールには作用しないためです。
意図的に ShowOLEPackageObj を 1 と設定している場合に限り、既定の 0 に戻すことで上記のような手順による攻撃を防ぐことができるようになります。HTML 形式の場合
リッチテキスト形式の場合
2016年2月6日
HTML メールでの OLE パッケージ オブジェクトを制限する方法
2016年1月30日
予定表を定期的に ics ファイルに保存し、自動で特定のアドレスに送信するマクロ
コメントにて以下のご要望をいただきました。 ご質問】予定表を定期的にicsファイルに落とし、自動で特定のアドレスに送信する いつも参考にさせていただいております。 今回、どうしても欲しいマクロで、どこのサイトを探しても outlook2007使用 ・他の人と共有している予定表を、icsファイルに変換し、それを特定のアドレスに ・上記メールを決まった時間 or outlook起動時など定期的に自動で送信する そんな都合の良いマクロは作成可能でしょうか? 素人の為どの位ムチャな要望なのかも分かっておりません。 大変申し訳ありません、何卒ご教示ねがいます。 Outlook のオブジェクト モデルには、予定アイテム単体を iCal ファイルに保存するメソッドは用意されていますが、予定表全体を保存するメソッドはありません。 以下のマクロは、起動時に iCal ファイルを送信し、さらに仕事アイテムを使って 1 日おきに iCal ファイルを送信するマクロです。
当方、マクロは全くの素人のため、当サイトのマクロ
をそっくり使わせていただいており、非常に助かっております。
それらしい物が無かったため、要望させていただきます。
送信する
そのため、一つ一つのアイテムを iCal で保存し、それをまとめた iCal ファイルを作成するというような処理が必要となります。
また、定期的にマクロを実行する方法としては、マクロ実行用の仕事アイテムを用意し、そのアイテムのアラームが表示されるタイミングで処理を実行する、というようなものがあります。
件名や宛先などを適宜変更して使用してください。
なお、予定表に大量のアイテムがある場合にはマクロの実行に時間がかかったり、iCal ファイルのサイズが非常に大きくなったりする可能性があるのでご注意ください。 ' ここをトリプルクリックでマクロ全体を選択できます。
' 定期実行のためのタスクの件名
Const CALSEND_ITEM = "予定表自動送信タスク"
' iCal を送信するメールの件名
Const MSG_SUBJECT = "予定表送信"
' iCal を送信するメールの本文
Const MSG_BODY = "予定表を送信します"
' iCal を送信するメールの宛先
Const MSG_TO = "user1@example.com"
' iCal のローカル保存用ファイル名
Const ATT_FILE = "c:\temp\予定表.ics"
' iCal 作成の作業ファイル名
Const TEMP_FILE = "c:\temp\~temp~.ics"
'
' 起動時に自動実行されるルーチン
Private Sub Application_Startup()
Dim fldTask As Folder
Dim objTask As TaskItem
Set fldTask = Session.GetDefaultFolder(olFolderTasks)
' 自動送信タスクの検索
Set objTask = fldTask.Items.Find("[件名]='" & CALSEND_ITEM & "'")
If objTask Is Nothing Then
' 自動送信タスクが存在しなければ作成
Set objTask = fldTask.Items.Add
objTask.Subject = CALSEND_ITEM
End If
' 自動送信タスクのアラームを 1 日後に設定
objTask.ReminderTime = DateAdd("d", 1, Now)
objTask.ReminderSet = True
objTask.Save
' iCal 送信
SendMyCalendar
End Sub
'
' アラーム表示で実行されるルーチン
Private Sub Application_Reminder(ByVal Item As Object)
' 自動送信タスクだったら
If Item.Subject = CALSEND_ITEM Then
' 一時的にアラームをオフ
Item.ReminderSet = False
Item.Save
' 自動送信タスクのアラームを 1 日後に設定
Item.ReminderTime = DateAdd("d", 1, Now)
Item.ReminderSet = True
Item.Save
' iCal 送信
SendMyCalendar
End If
End Sub
'
' 予定表を iCal で送信するルーチン
Public Sub SendMyCalendar()
On Error Resume Next
' ADO の定数設定
Const adTypeText = 2
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
'
Dim fldCalendar As Folder
Dim oneAppt As AppointmentItem
Dim stmWrite 'As ADODB.Stream
Dim stmRead 'As ADODB.Stream
Dim strText As String
Dim binIcs As Variant
Dim msgSend As MailItem
' UTF-8 で iCal ファイルを作成するためのストリーム作成
Set stmWrite = CreateObject("ADODB.Stream")
With stmWrite
.Type = adTypeText
.Charset = "UTF-8"
.Open
' iCal のヘッダーを書き込み
.WriteText "BEGIN:VCALENDAR" & vbCrLf
.WriteText "PRODID:-//Microsoft Corporation//Outlook 12.0 MIMEDIR//EN" & vbCrLf
.WriteText "VERSION:2.0" & vbCrLf
.WriteText "METHOD:PUBLISH" & vbCrLf
.WriteText "X-WR-CALNAME:" & Session.CurrentUser & vbCrLf
End With
' 既定の予定表を取得
Set fldCalendar = Session.GetDefaultFolder(olFolderCalendar)
' すべての予定アイテムを処理
For Each oneAppt In fldCalendar.Items
Err.Clear
' 単一のアイテムを iCal として保存
oneAppt.SaveAs TEMP_FILE, olICal
If Err.Number = 0 Then
' iCal ファイルを UTF-8 として読み込む
Set stmRead = CreateObject("ADODB.Stream")
With stmRead
.Type = adTypeText
.Charset = "UTF-8"
.Open
.LoadFromFile TEMP_FILE
strText = .ReadText
.Close
End With
' iCal データのうち VEVENT の部分だけ抜きとり
strText = Mid(strText, InStr(strText, "BEGIN:VEVENT"))
strText = Left(strText, InStr(strText, "END:VCALENDAR") - 1)
' 送信用 iCal ファイルへ書き込み
stmWrite.WriteText strText ' adWriteChar
End If
DoEvents
Next
'
With stmWrite
' iCal ファイルの終わりを書き込み
.WriteText "END:VCALENDAR" & vbCrLf
' iCal ファイルの保存
.SaveToFile ATT_FILE, adSaveCreateOverWrite
.Close
End With
' iCal ファイルを添付してメールを送信
Set msgSend = CreateItem(olMailItem)
msgSend.Subject = MSG_SUBJECT
msgSend.Body = MSG_BODY
msgSend.To = MSG_TO
msgSend.Attachments.Add ATT_FILE
msgSend.Send
End Sub
2016年1月23日
宛先に応じて署名をクイックパーツから挿入するマクロ
コメントにて以下のご要望をいただきました。 お世話になっております。 さて過去にも “署名” について、いくつかご投稿されておりますが ‘ 署名の置き換え バージョン:OutLook2010 SP2 宛先により差し込む署名を変えるとなると、宛先と署名を紐づけるものが必要となります。
業務上 outlookを多用しており 作業の効率化を図るため
活用させていただいております。
署名を何パターンか登録し 送信先によって、差し込む署名を変えたいと考えております。
過去のサンプルを基に 構文を探しましたがわかりませんでした。
お手数ですが ご教授の程 宜しくお願いいたします。
また クイックパーツで登録した文章も 差し込む構文も合わせてご教授いただければ幸いです。
Set objWord = ActiveInspector.WordEditor
Set objSignature = objWord.Bookmarks(“_MailAutoSig”)
objSignature.Range.Text = ANOTHER_SIGNATURE
今回のマクロでは、宛先のアドレスに該当する連絡先を検索し、見つかった連絡先の分類項目の文字列を名前とするクイックパーツで署名を置き換えるというものにしてみました。
マクロは以下の通りです。' ここをトリプルクリックでマクロ全体を選択できます。
Public Sub ChangeSignatureByRecipients()
Dim objRecip As Recipient
Dim objContact As ContactItem
'
For Each objRecip In ActiveInspector.CurrentItem.Recipients
' 受信者のアドレスに該当する連絡先を検索
Set objContact = FindContactByAddress(objRecip.Address)
If Not objContact Is Nothing Then
' 連絡先の分類項目が設定されているか確認
If objContact.Categories <> "" Then
' 分類項目の文字列を名前とするクイックパーツの埋め込み
If ReplaceSignatureByQuickParts(objContact.Categories) Then
Exit For
End If
End If
End If
Next
End Sub
' アドレスから連絡先を検索する関数
Private Function FindContactByAddress(strAddress As String)
Dim objContacts 'As Folder
Dim objContact As ContactItem
'
Set objContacts = Session.GetDefaultFolder(olFolderContacts)
Set objContact = objContacts.Items.Find("[Email1Address] = '" & strAddress _
& "' or [Email2Address] = '" & strAddress _
& "' or [Email3Address] = '" & strAddress & "'")
Set FindContactByAddress = objContact
End Function
' 指定した名前のクイックパーツで署名を置き換える関数
Private Function ReplaceSignatureByQuickParts(strName As String)
On Error Resume Next
Dim oDoc As Object
Dim oWord As Object
Dim strTemp As String
Dim oParts As Object
Dim oSignature As Object
ReplaceSignatureByQuickParts = False
' 現在表示しているメールの Word コンポーネントを取得
Set oDoc = ActiveInspector.WordEditor
Set oWord = oDoc.Parent
' メールの標準テンプレートからクイックパーツを取得
strTemp = oWord.Options.DefaultFilePath(2) & "\NormalEmail.dotm"
Set oParts = oWord.templates(strTemp).BuildingBlockEntries(strName)
' クイックパーツが見つからなければ中断
If oParts Is Nothing Then Exit Function
' メールの署名をクイックパーツで置き換え
Set oSignature = oDoc.Bookmarks("_MailAutoSig")
oParts.Insert Where:=oSignature.Range, RichText:=True
ReplaceSignatureByQuickParts = True
End Function
2016年1月16日
Outlook 2016/2013/2010 の累積的な修正プログラム 2016 年 1 月分がリリース
1/12 に Office 2016、Office 2013 および Office 2010 の累積的な修正プログラム (以下、CU) がリリースされました。 Outlook 2016 (KB3114532) は、2016 年 1 月 12 日更新 Office 2016 (KB3114536) は、2016 年 1 月 12 日更新 January 12, 2016, update for Outlook 2013 (KB3114500) MS16-004: Description of the security update for Office 2013: January 12, 2016 2016 年 1 月 12 日は、Outlook 2010 (KB3114570) の更新します。 他の Office 製品の修正へのリンクは、以下の KB にまとめて記載されています。
以下は各製品のそれぞれの KB へのリンクです。Office 2016
Outlook 2016 の修正
Outlook 2016 の不具合が 2 件修正されています。Office 2016 共通コンポーネントの修正
Outlook 2016 関連の不具合が 1 件修正されています。 Office 2013
Outlook 2013 の修正
1 件の機能追加と 2 件の不具合修正が行われています。Office 2013 共通コンポーネントのセキュリティ修正
セキュリティに関するものではありませんが、Outlook 2013 がハングアップする不具合が修正されています。Office 2010
Outlook 2010 の修正
1 件の不具合修正が行われています。その他の修正
2016年1月9日
検索を連続して実行するマクロ
コメントにて以下のご要望をいただきました。 Outlook2010でメールを検索するときにいつも次のような使い方をしていますが、もう少し効率よくできないものかと思っています。 a) クイック検索でメール本文に”xyz”という文字列を含むメールを検索 Outlook では Explorer で次のメールを選択するという方法が用意されていないため完全に自動化はできなかったのですが、マクロを使用して以下のような手順にはできます。 上記を実現するマクロは以下のようになります。 SearchStart、SearchNext、SearchStop をクイック アクセス ツールバーに登録しておけばより便利になると思います。
下記手順のうちc)~f)をマクロで簡単にできないでしょうか?
あるいは、最悪、c)とd)の所だけでもショートカットキーで一発で検索ダイアログボックスが出せるようになるとうれしいのですが。
ご教示いただきたく、よろしくお願いいたします。
b) 検索で見つかった一番上のメールを選択
c) Ctrl+Gで「検索と置換」ダイアログボックスを表示
d) 「検索」タブに切り替えて”xyz”という文字列を検索
e) そのメールの最後まで検索したら、次のメールを選択
f) c)~e)を繰り返す
' ここをトリプルクリックでマクロ全体を選択できます。
Dim WithEvents myExplorer As Explorer
Dim mySearchWord As String
Dim myFind As Object
'
' 検索を開始するマクロ
Public Sub StartSearch()
mySearchWord = InputBox("検索文字列:")
Set myExplorer = ActiveExplorer
myExplorer.Search mySearchWord, olSearchScopeCurrentFolder
End Sub
'
' 次の文字列を検索するマクロ
Public Sub NextSearch()
If Not myFind Is Nothing Then
myFind.Execute
End If
End Sub
'
' 検索を終了するマクロ
Public Sub StopSearch()
myExplorer.ClearSearch
Set myExplorer = Nothing
Set myFind = Nothing
End Sub
'
' 検索結果のアイテムをクリックした際に発生するイベントで本文検索開始
Private Sub myExplorer_SelectionChange()
On Error Resume Next
Dim objWord As Object
If myExplorer.Selection.Count = 0 Then
Exit Sub
End If
Set objWord = myExplorer.Selection(1).GetInspector().WordEditor
DoEvents
Set myFind = objWord.Parent.Selection.Find
With myFind
.ClearFormatting
.Text = mySearchWord
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchByte = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = False
.MatchFuzzy = True
.Execute
End With
End Sub
'
' フォルダーが切り替わったら検索を終了させるための記述
Private Sub myExplorer_FolderSwitch()
StopSearch
End Sub
2015年12月26日
Outlook の予定表に「山の日」を含む 2016 年以降の祝日を追加するスクリプト
Outlook の予定表に 2013 年以降の祝日を追加するスクリプトのコメントにて以下のご質問をいただきました。 山の日が追加されたのですが、どうしたらよいでしょうか。 山の日は 2014 年に制定された新しい祝日なので、それ以前にリリースされた Outlook 2013 などの祝日情報には含まれていません。 スクリプトは以下の通りです。このスクリプトを AddHoliday.vbs という名前で保存し、ダブルクリックして実行すると、2013 年以降の祝日が Outlook の既定の予定表に追加されます。
Outlook 2016 の祝日情報には山の日が含まれていますが、すでに以前のバージョンでインポート済みであると、既存の祝日が重複してインポートされる動作となってしまいますので、祝日を追加するスクリプトを作りました。' - ここをトリプル クリックするとすべてのコードが選択できます。
'
Option Explicit
Const olFolderCalendars = 9
Const olAppointmentItem = 1
Const olFree = 0
Dim objOutlook
Dim objSession
Dim objCalendar
Dim colEvents
Dim objHoliday
Dim iYear
' Outlook アプリケーション オブジェクトの取得
Set objOutlook = CreateObject("Outlook.Application")
' Namespace オブジェクトの取得
Set objSession = objOutlook.GetNamespace("MAPI")
' 予定表フォルダの取得
Set objCalendar = objSession.GetDefaultFolder(olFolderCalendars)
Set colEvents = objCalendar.Items
' 予定表から 2016 年以降の祝日のみを取得
Set objHoliday = colEvents.Find("[分類項目] = '祝日' AND [開始日] >= '2015/12/31' AND [場所] = '日本'")
' 2016 年以降の祝日を削除
While Not objHoliday Is Nothing
objHoliday.Delete
Set objHoliday = colEvents.FindNext
Wend
'
' 2016 年から 2022 年までの祝日を追加
For iYear = 2016 to 2022
AddNormalHoliday "天皇誕生日", iYear, 12, 23
AddNormalHoliday "勤労感謝の日", iYear, 11, 23
AddNormalHoliday "文化の日", iYear, 11, 3
AddHappyMonday "体育の日", iYear, 10, 2
AddHappyMonday "敬老の日", iYear, 9, 3
AddNormalHoliday "山の日", iYear, 8, 11
AddHappyMonday "海の日", iYear, 7, 3
AddNormalHoliday "こどもの日", iYear, 5, 5
AddNormalHoliday "みどりの日", iYear, 5, 4
AddNormalHoliday "憲法記念日", iYear, 5, 3
AddNormalHoliday "昭和の日", iYear, 4, 29
AddNormalHoliday "建国記念の日", iYear, 2, 11
AddHappyMonday "成人の日", iYear, 1, 2
AddNormalHoliday "元日", iYear, 1, 1
Next
' 日付が一定でない祝日の追加
AddNormalHoliday "春分の日", 2016, 3, 20
AddNormalHoliday "春分の日", 2017, 3, 20
AddNormalHoliday "春分の日", 2018, 3, 21
AddNormalHoliday "春分の日", 2019, 3, 21
AddNormalHoliday "春分の日", 2020, 3, 20
AddNormalHoliday "春分の日", 2021, 3, 20
AddNormalHoliday "春分の日", 2022, 3, 21
AddNormalHoliday "秋分の日", 2016, 9, 22
AddNormalHoliday "秋分の日", 2017, 9, 23
AddNormalHoliday "秋分の日", 2018, 9, 23
AddNormalHoliday "秋分の日", 2019, 9, 23
AddNormalHoliday "秋分の日", 2020, 9, 22
AddNormalHoliday "秋分の日", 2021, 9, 23
AddNormalHoliday "秋分の日", 2022, 9, 23
'
' 振り替え休日を考慮しない祝日の追加
Sub AddHoliday( sName, dtDay )
Set objHoliday = objOutlook.CreateItem(olAppointmentItem)
objHoliday.Subject = sName
objHoliday.Start = dtDay
objHoliday.AllDayEvent = True
objHoliday.Categories = "祝日"
objHoliday.ReminderSet = False
objHoliday.BusyStatus = olFree
objHoliday.Location = "日本"
objHoliday.Save
Set objHoliday = Nothing
End Sub
'
' ハッピーマンデーの祝日の追加
Sub AddHappyMonday( sName, iYear, iMonth, iMonday )
Dim iWk
Dim iDay
Dim dtDay
iWk = Weekday(iYear & "/" & iMonth & "/1" )
If iWk <= 2 Then
iWk = iWk + 4
Else
iWk = iWk - 3
End If
iDay = 7 * iMonday - iWk
AddHoliday sName, iYear & "/" & iMonth & "/" & iDay & " 00:00 AM"
End Sub
'
' 通常 (振り替え休日あり) の祝日の追加
Sub AddNormalHoliday( sName, iYear, iMonth, iDay )
Dim iWk
Dim dtSub
Dim objHoliday
AddHoliday sName, iYear & "/" & iMonth & "/" & iDay & " 00:00 AM"
iWk = Weekday( iYear & "/" & iMonth & "/" & iDay )
If iWk = 1 Then
dtSub = CDate(iYear & "/" & iMonth & "/" & iDay)
Do ' 振替休日が国民の祝日だったら、翌日に繰り越し
dtSub = DateAdd("d", 1, dtSub)
Set objHoliday = colEvents.Find("[分類項目] = '祝日' AND [開始日] >= '" & _
dtSub & " 00:00 AM' AND [終了日] <= '" & DateAdd("d", dtSub, 1) & _
"' AND [場所] = '日本'")
Loop While Not objHoliday Is Nothing
AddHoliday "振替休日 (" & sName & ")", dtSub & " 00:00 AM"
End If
End Sub
2015年12月19日
Outlook 2010 の定例外の修正プログラムがリリース
12/16 に以下の通り Outlook 2010 の修正プログラムがリリースされました。 Outlook 2010 (KB3114560) は 2015 年 12 月 16 日更新 12 月の更新プログラムで発生していた Outlook がセーフモードでしか起動しないという不具合を修正したものです。
こちらは Windows Update では提供されないようなので、12 月の更新プログラムによる修正が直ちに必要という場合は、この修正プログラムを手動で適用する必要があります。
2015年12月12日
Outlook 2016/2013/2010 の累積的な修正プログラム 2015 年 12 月分がリリース
12/9 に Office 2016、Office 2013 および Office 2010 の累積的な修正プログラム (以下、CU) がリリースされました。 December 8, 2015, update for Outlook 2016 (KB3114387) December 8, 2015, update for Outlook 2016 (KB3101550) December 8, 2015, update for Office 2016 (KB3114391) December 8, 2015, update for Office 2016 (KB3114390) December 8, 2015, update for Office 2016 (KB3114381) December 8, 2015, update for Outlook 2013 (KB3114349) Office 2013 (KB3114333) は 2015 年 12 月 8 日更新 MS15-131: Description of the security update for Word 2013: December 8, 2015 Outlook 2010 (KB3114409) は 2015 年 12 月 8 日更新 Office 2010 (KB2760779) は 2015 年 12 月 8 日更新 他の Office 製品の修正へのリンクは、以下の KB にまとめて記載されています。
以下は各製品のそれぞれの KB へのリンクです。Office 2016
Outlook 2016 の修正
Outlook 2016 の不具合が 4 件修正されています。
Outlook 2016 のデータ損失防止ポリシー表示のコンポーネントの不具合が 2 件修正されています。Office 2016 共通コンポーネントの修正
Outlook 2016 に関する不具合が 1 件修正されています。
Outlook 2016 に関する不具合が 1 件修正されています。
Outlook 2016 に関する不具合が 1 件修正されています。Office 2013
Outlook 2013 の修正
1 件の機能追加と 12 件の不具合修正が行われています。Office 2013 共通コンポーネントの修正
Outlook 2013 に関する不具合が 3 件修正されています。Word 2013 のセキュリティ修正
セキュリティに関連するものではありませんが、Outlook 2013 に関する機能追加が 1 件行われています。
Office 2010
Outlook 2010 の修正
1 件の機能追加と 4 件の不具合修正が行われていますが、セーフモードでしか起動できなくなるという不具合があるため、現在はダウンロードできなくなっています。Exchange アドインの修正
1 件の不具合修正が行われています。その他の修正
2015年12月5日
メールのスレッドを保持してExcelにエクスポートするマクロ
コメントにて以下のご要望をいただきました。 スレッドを保ったまま、Excelへ書き出すマクロは生成できますか? Outlook のオブジェクト モデルには Conversation というオブジェクトがあり、スレッドに含まれるアイテムを取得することが可能です。
例えば、
相手のメールを抜き出し、日付、宛名、件名、本文、を一行でExcelへ抽出する際に、
そのメールに対する自分の返信があった場合は同じ行の本文の横のセルに自分の返信、更に相手からまた返信があった場合は、その横のセルに追加のようにやりとりが同じ行に追加されていく
その他のメールは別の行にみたいな方法をおしえていただけなでしょうか?
これを利用すると、特定のスレッドのメールだけ 1 行に出力できます。
なお、Conversation が使えない状況も考えられるため、その場合はメッセージ ヘッダーに含まれる Message-ID と In-Reply-To を使用してスレッドを認識するようにしてみました。
マクロは以下の通りです。 ' ここをトリプルクリックでマクロ全体を選択できます。
Public Sub ExportToExcelWithThread()
Dim appExcel 'As Excel.Application
Dim objBook 'As Excel.Workbook
Dim objSheet 'As Excel.Worksheet
Dim bConvOK As Boolean
Dim colItems As Items
Dim objItem 'As MailItem
Dim c As Integer
'
Set appExcel = CreateObject("Excel.Application")
Set objBook = appExcel.Workbooks.Add()
Set objSheet = objBook.Sheets(1)
With objSheet
.Cells(1, 1) = "スレッド情報"
.Cells(1, 2) = "日付"
.Cells(1, 3) = "宛先"
.Cells(1, 4) = "Cc"
.Cells(1, 5) = "差出人"
.Cells(1, 6) = "件名"
.Cells(1, 7) = "本文"
'
Set colItems = ActiveExplorer.CurrentFolder.Items
colItems.Sort "送信日時"
bConvOK = ActiveExplorer.CurrentFolder.Store.IsConversationEnabled
For Each objItem In colItems
If bConvOK Then
ExportThreadByConversation objItem, objSheet
Else
ExportThreadByMessageId objItem, objSheet
End If
Next
For c = 2 To .UsedRange.Columns.Count Step 6
.Cells(1, c) = "日付"
.Cells(1, c + 1) = "宛先"
.Cells(1, c + 2) = "Cc"
.Cells(1, c + 3) = "差出人"
.Cells(1, c + 4) = "件名"
.Cells(1, c + 5) = "本文"
Next
End With
'
appExcel.Visible = True
objBook.Windows(1).Visible = True
End Sub
'
Private Sub ExportThreadByConversation(objItem, objSheet)
Const PR_CONVERSATION_ID = "http://schemas.microsoft.com/mapi/proptag/0x30130102"
Dim strConvID As String
Dim r As Integer
Dim c As Integer
'
With objItem.PropertyAccessor
strConvID = .BinaryToString(.GetProperty(PR_CONVERSATION_ID))
End With
r = 2
While objSheet.Cells(r, 1) <> ""
If objSheet.Cells(r, 1) = strConvID Then
Exit Sub
End If
r = r + 1
Wend
objSheet.Cells(r, 1) = strConvID
c = 2
EnumConversation objItem.GetConversation().GetRootItems, objSheet, r, c
End Sub
'
Private Sub EnumConversation(colItems As SimpleItems, objSheet, r As Integer, c As Integer)
Dim objItem 'As MailItem
Dim conv As Conversation
Dim colSubItems As SimpleItems
For Each objItem In colItems
WriteCell objItem, objSheet, r, c
c = c + 6
Set conv = objItem.GetConversation()
Set colSubItems = conv.GetChildren(objItem)
If colSubItems.Count > 0 Then
EnumConversation colSubItems, objSheet, r, c
End If
Next
End Sub
'
Private Sub ExportThreadByMessageId(objItem As MailItem, objSheet)
Const PR_INTERNET_MESSAGE_ID = "http://schemas.microsoft.com/mapi/proptag/0x1035001e"
Const PR_IN_REPLY_TO_ID = "http://schemas.microsoft.com/mapi/proptag/0x1042001e"
Dim strMsgID As String
Dim strRepID As String
Dim r As Integer
Dim c As Integer
Dim bFound As Boolean
'
With objItem.PropertyAccessor
strMsgID = .GetProperty(PR_INTERNET_MESSAGE_ID)
strRepID = .GetProperty(PR_IN_REPLY_TO_ID)
End With
'
With objSheet
c = 2
If strRepID = "" Then
r = .UsedRange.Rows.Count + 1
Else
bFound = False
r = 2
While (Not bFound) And .Cells(r, 1) <> ""
If InStr(.Cells(r, 1), strRepID) > 0 Then
While .Cells(r, c) <> ""
c = c + 6
Wend
bFound = True
Else
r = r + 1
End If
Wend
End If
.Cells(r, 1) = .Cells(r, 1) & strMsgID
WriteCell objItem, objSheet, r, c
End With
End Sub
'
Private Sub WriteCell(objItem, objSheet, r As Integer, c As Integer)
With objSheet
.Cells(r, c) = objItem.SentOn
.Cells(r, c + 1) = objItem.To
.Cells(r, c + 2) = objItem.CC
.Cells(r, c + 3) = objItem.Sender
.Cells(r, c + 4) = objItem.Subject
.Cells(r, c + 5) = objItem.Body
End With
End Sub
2015年11月28日
特定のフォルダー以下のサブフォルダーの未読メールをまとめて管理する方法
コメントにて以下のご要望をいただきました。 Outlook2010で、部署名フォルダの下に各社員のフォルダをつくる等、階層構造を使って管理しております。 1) サブフォルダ以下の未読数を表示する機能。 2) フォルダ及びサブフォルダの未読を一括して既読にする機能。 もし方法がありましたら、教えていただければ大変助かります。 このようなご要望であれば、検索フォルダーでも実現可能でしょう。 このようにして作成した検索フォルダーには指定されたフォルダー以下のすべてのサブフォルダーの未読メールがリストアップされ、検索フォルダーの右の数字はすべてのサブフォルダーの未読メールの合計数となります。
その際、下記の2つを実行できたらと考えているのですが、そのようなスクリプトは作成可能でしょうか。
部署名フォルダにサブフォルダ(各社員)の未読数の合計を表示。
部署名フォルダを選択した際に、部署フォルダ及びサブフォルダ(各社員)の未読を一括して既読にできる機能。
既定の「未読メール」検索フォルダーはメールボックスのすべての未読メールが表示されますが、カスタマイズした検索フォルダーを作ることで特定のフォルダーの下のサブフォルダーすべての未読メールだけを検索することが可能です。
そのような検索フォルダーを作成する手順は以下の通りです。
また、検索フォルダーを右クリックし、[すべて開封済みにする] をクリックすれば、サブフォルダーのすべての未読メールを既読にすることもできます。