[最初に表示するアドレス帳] を変更するスクリプト

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


勤務先で、入社してきた社員のPC設定をしております。
その中のひとつで、アドレス帳の「最初に表示するアドレス一覧」をあるアドレス一覧を自動選択が出来るようにしたいのですが、可能でしょうか。
また、「送信時に名前を確認するアドレス一覧の順番」の変更も出来ると嬉しいのですが・・


残念ながら Outlook Object Model では、[最初に表示するアドレス一覧] や [送信時に名前を確認するアドレス一覧の順番] の設定を変更することはできません。しかし、これらの設定はレジストリの MAPI プロファイルに格納されていますので、これを変更するようなスクリプトを作れば可能です。

というわけで作ったスクリプトは以下の通りです。冒頭の DEFAULT_AB_NAME で最初に表示したいアドレス一覧の名前を指定し、拡張子を vbs として保存して実行します。設定がバイナリ データとして保存されているので、ちょっと複雑になってしまいました。

' ここをトリプルクリックでスクリプト全体を選択できます。
Option Explicit
Const DEFAULT_AB_NAME = "連絡先" ' 最初に表示させたいアドレス帳の名前を指定します。
' 定数定義
Const HKEY_CURRENT_USER = &H80000001
Const MAPI_PROFILE_KEY = "Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles"
Const MAPI_SERVICES_KEY = "9207f3e0a3b11019908b08002b2a56c2"
Const PR_AB_PROVIDERS = "01023d01"
Const PR_AB_DEFAULT_DIR = "01023d06"
Const PR_AB_SEARCH_PATH = "11023d05"
Const PR_SERVICE_NAME = "001f3d09"
Const MAPI_EMS_KEY = "13dbb0c8aa05101a9bb000aa002fc45a"
Const PR_HMVCOL_ENTRYID = "110265e0"
Const PR_HMVCOL_DISPLAY_NAMES = "101f65e4"
Const CONTAB_PREFIX = "00000000FE42AA0A18C71A10E8850B651C2400000300000003000000"
Const PR_CONTAB_UID = "01026601"
Const PR_CONTAB_FOLDER_ENTRYIDS = "11026620"
Const PR_CONTAB_DISPLAY_NAMES = "101f6629"
Const PT_BINARY = &H102
Const PT_UNICODE = &H1F
' 変数宣言
Dim objReg
Dim strKey
Dim strDefaultProfile
Dim strProfileKey
Dim strServicesKey
Dim abyAddrBookUIDs
Dim iCount
Dim strServiceKey
Dim strServiceName
Dim abyData
Dim strDefaultEID
Dim strDefaultEIDSP
Dim abyEntryID()
Dim astrEntryIDs
Dim iStart
Dim i, j
' レジストリにアクセスするための WMI の StdRegProv オブジェクトを取得します。
Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
' 既定の MAPI プロファイルの名前を取得します。
objReg.GetStringValue HKEY_CURRENT_USER, MAPI_PROFILE_KEY, "DefaultProfile", strDefaultProfile
' プロファイルの名前からキーの文字列を生成します。
strProfileKey = MAPI_PROFILE_KEY & "\" & strDefaultProfile & "\"
strServicesKey = strProfileKey & MAPI_SERVICES_KEY
' アドレス帳プロバイダの ID の一覧を取得します。
objReg.GetBinaryValue HKEY_CURRENT_USER, strServicesKey, PR_AB_PROVIDERS, abyAddrBookUIDs
' アドレス帳プロバイダの ID ごとに指定されたアドレス帳を検索します。
iCount = (UBound(abyAddrBookUIDs) + 1) / 16
For i = 0 To iCount - 1
    strServiceKey = ""
    ' 16 バイトのバイナリ データを文字列に変換します。
    For j = 0 To 15
        strServiceKey = strServiceKey & Right("0" & Hex(abyAddrBookUIDs(i * 16 + j)), 2)
    Next
    ' アドレス帳プロバイダの名前を取得します。
    objReg.GetBinaryValue HKEY_CURRENT_USER, strProfileKey & strServiceKey, PR_SERVICE_NAME, abyData
    strServiceName = BinaryToUnicodeString(abyData, 0, UBound(abyData))
    ' サービスごとに情報の取得を行ないます。
    If strServiceName = "MSEMS" Then
        ' MSEMS は Exchange のグローバル アドレス一覧です。
        strDefaultEID = FindInGAL(objReg, strProfileKey & MAPI_EMS_KEY, DEFAULT_AB_NAME)
        strDefaultEIDSP = Left(strDefaultEID, 58) & "00"
    ElseIf strServiceName = "CONTAB" Then
        ' CONTAB は Outlook アドレス帳です。
        strDefaultEID = FindInCONTAB(objReg, strProfileKey & strServiceKey, DEFAULT_AB_NAME)
        strDefaultEIDSP = strDefaultEID
    End If
    ' アドレス帳が見つかったらループを抜けます。
    If strDefaultEID <> "" Then Exit For
Next
' [最初に表示するアドレス一覧] に設定します。
ReDim abyEntryID(Len(strDefaultEID) / 2 - 1)
For i = 0 To Len(strDefaultEID) / 2 - 1
    abyEntryID(i) = CInt("&H" & Mid(strDefaultEID, i * 2 + 1, 2))
Next
objReg.SetBinaryValue HKEY_CURRENT_USER, strServicesKey, PR_AB_DEFAULT_DIR, abyEntryID
' [送信時に名前を確認するアドレス一覧の順番] を入れ替えます。
objReg.GetBinaryValue HKEY_CURRENT_USER, strServicesKey, PR_AB_SEARCH_PATH, abyData
astrEntryIDs = BinaryToMultiValue(abyData, PT_BINARY)
For i = 1 To UBound(astrEntryIDs)
    If astrEntryIDs(i) = strDefaultEIDSP Then
        For j = i To 1 Step -1
            astrEntryIDs(j) = astrEntryIDs(j - 1)
        Next
        astrEntryIDs(0) = strDefaultEIDSP
        Exit For
    End If
Next
' PR_AB_SEARCH_PATH を再構成します。
iStart = 4 + (UBound(astrEntryIDs) + 1) * 8
For i = 0 To UBound(astrEntryIDs)
    abyData(i * 8 + 4) = CByte(Len(astrEntryIDs(i)) / 2)
    abyData(i * 8 + 8) = CByte(iStart Mod &H100)
    abyData(i * 8 + 9) = CByte(Int(iStart / &H100))
    For j = 0 To Len(astrEntryIDs(i)) / 2 - 1
        abyData(iStart + j) = CByte("&H" & Mid(astrEntryIDs(i), j * 2 + 1, 2))
    Next
    iStart = iStart + j
    While iStart Mod 4 > 0
        abyData(iStart) = 0
        iStart = iStart + 1
    Wend
Next
' [送信時に名前を確認するアドレス一覧の順番] を設定します。
objReg.SetBinaryValue HKEY_CURRENT_USER, strServicesKey, PR_AB_SEARCH_PATH, abyData
'   グローバル アドレス一覧から既定とするアドレス帳を検索する関数です。
Function FindInGAL(objReg, strEMSKey, strDefaultName)
    Dim abyData
    Dim astrEntryIDs
    Dim astrNames
    Dim i
    ' 名前の一覧を取得します。
    objReg.GetBinaryValue HKEY_CURRENT_USER, strEMSKey, PR_HMVCOL_DISPLAY_NAMES, abyData
    astrNames = BinaryToMultiValue(abyData, PT_UNICODE)
    For i = 0 To UBound(astrNames)
        ' 一覧に設定したいアドレス帳の名前があるか確認します。
        If astrNames(i) = strDefaultName Then
            ' 一致したら EntryID の一覧を取得します。
            objReg.GetBinaryValue HKEY_CURRENT_USER, strEMSKey, PR_HMVCOL_ENTRYID, abyData
            astrEntryIDs = BinaryToMultiValue(abyData, PT_BINARY)
            FindInGAL = astrEntryIDs(i)
            Exit Function
        End If
    Next
    FindInGAL = ""
End Function
'   Outlook アドレス帳から既定とするアドレス帳を検索する関数です。
Function FindInCONTAB(objReg, strCONTABKey, strDefaultName)
    Dim abyData
    Dim astrEntryIDs
    Dim astrNames
    Dim strUID
    Dim i
    Dim j
    ' サービスの UID を取得します。
    objReg.GetBinaryValue HKEY_CURRENT_USER, strCONTABKey, PR_CONTAB_UID, abyData
    For j = 0 To UBound(abyData)
        strUID = strUID & Right("0" & Hex(abyData(j)), 2)
    Next
    ' 名前の一覧を取得します。
    objReg.GetBinaryValue HKEY_CURRENT_USER, strCONTABKey, PR_CONTAB_DISPLAY_NAMES, abyData
    astrNames = BinaryToMultiValue(abyData, PT_UNICODE)
    For i = 0 To UBound(astrNames)
        ' 一覧に設定したいアドレス帳の名前があるか確認します。
        If astrNames(i) = strDefaultName Then
            ' 一致したら EntryID の一覧を取得します。
            objReg.GetBinaryValue HKEY_CURRENT_USER, strCONTABKey, PR_CONTAB_FOLDER_ENTRYIDS, abyData
            astrEntryIDs = BinaryToMultiValue(abyData, PT_BINARY)
            FindInCONTAB = CONTAB_PREFIX & strUID & astrEntryIDs(i)
            Exit Function
        End If
    Next
    FindInCONTAB = ""
End Function
'   バイナリ データを Multi-Value のデータに変換する関数です。
Function BinaryToMultiValue(abyData, iType)
    Dim cValues
    Dim iStart
    Dim iLen
    Dim i
    Dim j
    Dim astrData()
    ' 格納されているデータの数を取得します。
    cValues = abyData(0)
    ReDim astrData(cValues - 1)
    For i = 0 To cValues - 1
        If iType = PT_BINARY Then
            ' データの長さとデータの開始位置を取得します。
            iLen = abyData(i * 8 + 4) + abyData(i * 8 + 5) * &H100
            iStart = abyData(i * 8 + 8) + abyData(i * 8 + 9) * &H100
            ' データを文字列に変換します。
            For j = 0 To iLen - 1
                astrData(i) = astrData(i) & Right("0" & Hex(abyData(iStart + j)), 2)
            Next
        Else
            ' データの開始位置を取得します。
            iStart = abyData(i * 4 + 4)
            ' 文字列の終端を検索します。
            For iLen = 0 To UBound(abyData) - iStart Step 2
                If abyData(iStart + iLen) = 0 And abyData(iStart + iLen + 1) = 0 Then
                    Exit For
                End If
            Next
            ' データを文字列に変換します。
            astrData(i) = BinaryToUnicodeString(abyData, iStart, iLen + 1)
        End If
    Next
    BinaryToMultiValue = astrData
End Function
'   バイナリ データを Unicode 文字列に変換する関数です。
Function BinaryToUnicodeString(abyData, iStart, iLen)
    Dim strUnicode
    Dim i
    strUnicode = ""
    ' 2 バイトごとに Unicode 文字に変換します。
    ' 最初のバイトが下位バイト、次のバイトが上位バイトになります。
    For i = iStart To iStart + iLen - 1 Step 2
        strUnicode = strUnicode & ChrW(abyData(i) + abyData(i + 1) * &H100)
    Next
    ' 文字列の中に NULL がある場合は取り除きます。
    BinaryToUnicodeString = Replace(strUnicode, Chr(0), "")
End Function

 

Outlook Object Model で本文の編集のために Word の機能を呼びだすマクロ

Outlook 2007 はメッセージの表示や編集に Word 2007 のコンポーネントを使用しています。そして、Outlook Object Model からも、Inspector オブジェクトの WordEditor プロパティを使って Word の機能を呼びだすことができます。以下は、メッセージの作成の際、カーソル位置に任意の文字列を赤い太字の 20 pt のフォントで入力するサンプルです。

' ここをトリプルクリックでマクロ全体を選択できます。
Sub EnterText()
    Dim objDoc ' As Word.Document
    On Error Resume Next
    Set objDoc = Application.ActiveInspector.WordEditor
    With objDoc.Windows(1).Selection
        .Font.Bold = -1
        .Font.Color = &HFF
        .Font.Size = 20
        .TypeText "挿入する文字列"
    End With
    Set objDoc = Nothing
End Sub

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

Outlook 2007 用予定表印刷アシスタントの出力ファイルをカスタマイズする方法

これまで 2 回ほど紹介している Outlook 2007 用の予定表印刷アシスタントですが、ある程度カスタマイズが可能なものの、細かいところでカスタマイズできないものがあります。例えば、文字の色やフォントが定義済みのものしか使えなかったり、フォントのサイズを変更することができません。しかし、作成した予定表のファイルの内容をテキスト エディタで編集し、文字の色やフォントをカスタマイズすることが可能です。今回は予定表印刷アシスタントのファイルのカスタマイズ方法について概要を説明します。

では、サンプルとして「年 (メモ欄つき) 01」の出力をカスタマイズしてみます。このテンプレートでは、土曜日と日曜日が同じ色となっていますが、一般的には土曜日は青で日曜日は赤ではないでしょうか? また、予定表のスタイルで [標準] 以外を選択すると、土日が非常に見づらくなってしまいます。そこで、[標準の色] を選択した際に、土曜日が青、日曜日が赤で印刷されるようカスタマイズします。手順は以下の通りです。

  1. Outlook 2007 用予定表印刷アシスタントを起動します。
  2. [ビュー テンプレート] で [年テンプレート] の [年 (メモ欄つき) 01] を選択します。
  3. 色やフォント、予定表のスタイルなど、必要に応じて設定します。
  4. [ファイル]-[名前をつけて保存] でファイルを保存します。
  5. Outlook 2007 用予定表印刷アシスタントを終了します。
  6. 4. で保存したファイルの拡張子を .zip に変更します。
  7. 圧縮フォルダとなったファイルをダブルクリックして展開し、Cal\Templates\Template1 にある Content.xml ファイルをデスクトップなどの別のフォルダにコピーします。
  8. Content.xml ファイルをメモ帳などのテキスト エディタで開きます。
  9. 下記の記述が 2 箇所あるので、それを以下の通り変更します。

    変更前:

    <ConditionalFormat Condition="DayOfWeek eq ‘sun’" Foreground="style!WeekendColor" ForegroundHighlight="style!WeekendColor"/>
    <ConditionalFormat Condition="DayOfWeek eq ‘sat’" Foreground="style!WeekendColor" ForegroundHighlight="style!WeekendColor"/>

    変更後:

    <ConditionalFormat Condition="DayOfWeek eq ‘sun’" Foreground="Red" ForegroundHighlight="Red"/>
    <ConditionalFormat Condition="DayOfWeek eq ‘sat’" Foreground="Blue" ForegroundHighlight="Blue"/>

  10. 変更したファイルを上書き保存します。
  11. Content.xml ファイルを圧縮フォルダの元のパスに上書き保存します。
  12. 4. のファイルの拡張子を .zip から .calx に戻します。
  13. 4. のファイルをダブルクリックで開きます。

なお、色の指定方法は "Red" や "Blue" などのほか、”#CC0000” のように 16 進数で指定することもできます。また、文字の大きさを変えたい場合には、FontSize = "7pt" というような指定の数値を増減させます。

現在の日時をカスタマイズした書式でメールの編集時に挿入する方法

Outlook 2007 では [挿入] リボンの [日付と時刻] から書式を選んで本文に挿入することができますが、用意されている書式以外の書式で挿入したいということもあると思います。

そのような場合には、挿入した後で [フィールドの編集] により書式を変更し、クイック パーツとして登録することで、カスタマイズした書式の日時を簡単に挿入できるようになります。

以下は、「2009/07/01 09:01」というような書式の日時を登録する手順です。

  1. Outlook 2007 で新規のメッセージ作成画面を表示します。
  2. 本文をクリックします。
  3. [挿入] リボンの [日付と時刻] をクリックします。
  4. [自動的に更新する] をオンにします。
  5. [OK] をクリックします。(表示形式で何が選択されていても構いません。)
  6. 挿入された日時を右クリックし、[フィールドの編集] をクリックします。
  7. [日付の書式] に 「yyyy/MM/dd HH:mm」と入力し、[OK] をクリックします。
  8. 日付と時刻を範囲選択します。
  9. [挿入] リボンの [クイック パーツ] をクリックし、[選択範囲をクイック パーツ ギャラリーに保存] をクリックします。
  10. [名前] に "日時" など適切なものを入力し、[OK] をクリックします。

これにより、[挿入]-[クイック パーツ]-[日時] で現在の日時を指定した書式で挿入することができるようになります。

Outlook 2003 でメッセージの受信者の部署名により送信チェックを行なうマクロ

以前、メッセージの受信者の Exchange のプロパティを取得するマクロという記事で、Outlook 2007 用の受信者の部署名チェックを行なうマクロを紹介しました。しかし、ご要望をいただいた方は Outlook 2003 をお使いということであったため、今回は Outlook 2003 でも使えるマクロを紹介します。

まず、Outlook 2003 においては GetExchangeUser というメソッドが使用できないため、グローバル アドレス一覧の部署名などの情報を取得するには CDO 1.21 を使用する必要があります。しかし、この方法を用いた場合、アドレス帳へのアクセスの際に警告ダイアログが毎回表示されてしまい、これを防ぐにはパブリック フォルダ上に Security Settings のフォームを発行するなど、Exchange 管理者の手を借りる必要があります。

そこで、グローバル アドレス一覧のうち、同じ部署に所属するユーザーだけを Outlook の連絡先にコピーし、連絡先から部書名の取得を行なうようなマクロにしました。このマクロを使用するには、事前にグローバル アドレス一覧で同じ部署に所属するユーザーを右クリックし、[連絡先フォルダに追加] で Outlook の連絡先に追加してください。

' ここをトリプルクリックでマクロ全体を選択できます。
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
    Const MY_DEPARTMENT = "IT Department" ' 自分の部署名を指定します。
    Dim objRecip As Recipient
    Dim objContact As ContactItem
    Dim strExternal As String
'
    If Item.MessageClass Like "IPM.TaskRequest*" Then
        Set Item = Item.GetAssociatedTask(False)
    End If
'
    strExternal = ""
    For Each objRecip In Item.Recipients
        Set objContact = FindContactByAddress(objRecip.Address)
        If objContact Is Nothing Then
            strExternal = strExternal & objRecip.Name & ";"
        Else
            If objContact.Department <> MY_DEPARTMENT Then
                strExternal = strExternal & objRecip.Name & ";"
            End If
        End If
    Next
'
    If strExternal <> "" Then
        If MsgBox("あて先に他部署の受信者が含まれています。送信してよろしいですか?" & vbLf & _
        "受信者名:" & strExternal, vbYesNo, "受信者の確認") = vbNo Then
            Cancel = True
        End If
    End If
End Sub
'
Private Function FindContactByAddress(strAddress As String)
    Dim objContacts
    Dim objContact
    Set objContacts = Application.Session.GetDefaultFolder(olFolderContacts)
    Set objContact = objContacts.Items.Find("[Email1Address] = '" & strAddress _
        & "' or [Email2Address] = '" & strAddress _
        & "' or [Email3Address] = '" & strAddress & "'")
    Set FindContactByAddress = objContact
End Function

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

カスタム フォームで作成したアイテムを To Do バーから開くと標準のフォームになる理由と回避策

仕事フォームをカスタマイズしてオリジナルのフォームを作成し、仕事フォルダに発行しておくことで、標準のフォームにない情報を管理することができるようになりますが、このようなフォームを To Do バーで開くと、カスタマイズされていないフォームで開いてしまうことがあります。不具合のように思えるかもしれませんが、これは Outlook がフォームを選択する仕様によって発生する現象です。

Outlook はアイテムを開くときに使用するフォームをメッセージ クラスというプロパティによって判断しています。例えば、メッセージ アイテムであれば IPM.Note、予定アイテムであれば IPM.Appointment、仕事アイテムであれば IPM.Task というメッセージ クラスになっており、Outlook はそのメッセージ クラスに応じて表示するフォームを選択します。

そして、カスタム フォームを作成した場合、そのフォームはオリジナルのフォームのメッセージ クラスに独自の名前を付与したものとなります。例えば、仕事アイテムをカスタマイズした場合には IPM.Task.Custom という具合です。これにより、標準のフォームとカスタム フォームが区別されたり、単にメッセージ クラスを書き換えるだけで、すでに保存したアイテムをカスタム フォームに変更するということが可能になっています。

問題は、カスタム フォームが特定のフォルダに発行されていた場合です。カスタム フォームを [アクション] メニューから開くには、そのフォームをフォルダに対して発行しますが、この場合には他のフォルダに同じメッセージ クラスのアイテムがあっても、そのカスタム フォームで開かれることはありません。例えば、Folder A と Folder B に同じ IPM.Task.Custom というメッセージ クラスのアイテムがあった場合、Folder A のアイテムは Folder A に発行されたフォームで開かれ、Folder B のアイテムは Folder B に発行されたフォームで開かれることになります。そして、もし Folder B にフォームが発行されていなければ、そのアイテムは標準のフォームで開かれるのです。つまり、To Do バーで開くとカスタム フォームが標準のフォームになってしまうのは、To Do バー自体が元のフォルダとは別のフォルダであり、そこに対してカスタム フォームが発行されていないためなのです。

では、To Do バーにカスタム フォームを発行すればよいのかというと、そうではありません。To Do バーは検索フォルダの一つなのですが、検索フォルダに対してはフォームを発行することができないのです。そのため、カスタム フォームをフォルダではなく [個人用フォーム ライブラリ] に発行します。
個人用フォーム ライブラリはその名の通り個人がフォームを管理するためのライブラリで、ここに発行したフォームはその人がアクセスできるフォルダに対して使用することが可能となります。また、その人が開いたアイテムのメッセージ クラスのカスタム フォームがフォルダに対して発行されていなかった場合、個人用フォーム ライブラリのフォームが使用されます。
ただし、フォルダに関連付けがされていないため、[アクション] メニューには表示されません。したがって、[アクション] メニューから開く必要があり、かつ To Do バーからも開く必要がある場合は、フォルダと個人用フォーム ライブラリの両方にまったく同じフォームを発行してください。

なお、以下の手順で発行済みのフォームを個人用フォーム ライブラリにコピーすることができます。フォームを更新して発行した場合は、この手順を再度実行して個人用フォーム ライブラリのフォームも更新する必要があります。

  1. [ツール]-[オプション] をクリックします。
  2. [その他] の [詳細オプション] をクリックします。
  3. [ユーザー設定フォーム] をクリックします。
  4. [フォームの管理] をクリックします。
  5. 左側の [設定] をクリックします。
  6. [フォルダ フォーム ライブラリ] を選択し、フォームを発行したフォルダをクリックして [OK] をクリックします。
  7. 右側の [設定] をクリックします。
  8. [フォーム ライブラリ] を選択し、ドロップ ダウンから [個人用フォーム] を選択して [OK] をクリックします。
  9. 左側のフォームの一覧でコピーしたいフォームの名前をクリックし、[コピー] をクリックします。
  10. [閉じる] をクリックします。
  11. すべてのダイアログを [OK] をクリックして閉じます。

Outlook 2007 および Outlook 2003 の累積的な修正プログラムがリリース

7/1 (米国時間 6/30) に Outlook 2007 および Outlook 2003 の累積的な修正プログラム (以下、CU) がリリースされました。
以下はそれぞれの CU の KB へのリンクです。

970944 Outlook 2007 修正プログラム パッケージ (Outlook.msp): 2009 年 6 月 30 日
20 弱の不具合が修正されており、その中には SP2 適用後に発生するものもあるようです。SP2 を適用している場合はこちらも適用したほうがよいでしょう。

972574 Outlook 2007 修正プログラム パッケージ (Oms.msp、Outlook.msp): 2009 年 6 月 30 日
以前公開した全角のプロファイル名を使用していると SP2 適用後にハングアップするという不具合の修正です。なお、修正されたファイルの一覧を見ると上の 970944 で修正されているものと同じですので、970944 を適用するならこちらの適用は不要です。

971786 Outlook 2007 修正プログラム パッケージ (Outlook-ja-jp.msp): 2009 年 6 月 30 日
テキスト形式のメッセージで改行を削除するという機能が正しく動作しないという不具合が修正されています。これは日本語環境にのみ適用できる CU です。

970942 Word 2007 修正プログラム パッケージ (Word.msp、Wordconv.msp): 2009 年 6 月 30 日
Outlook 2007 がメールの表示・編集に使用している Word 2007 の修正です。Outlook に関するものとしてはハイパーリンクの全角文字が文字化けする場合があるというものと、リッチテキスト形式のメッセージが開けない場合があるというものです。

971366 Outlook 2003 修正プログラム パッケージ (Outlook.msp) の説明: 2009 年 6 月 30 日
Outlook 2003 の会議出席依頼に関する修正などです。延長サポートに入ってもこちらの CU は無償でダウンロードできるようです。

連絡先の保存の際に件名を自動設定する方法

コメントで以下のようなご要望をいただきました。


最近Outlook 2007の[連絡先の選択]画面で表示されるローカルの連絡先の表示順を変えようと思い調べていると、連絡先の[件名](ContactItem.Subject)を設定すればその順でソートされて表示されることがわかりました。ここに[会社名][部署名][姓][名]などをセットしておけば、[連絡先の選択]画面で同じ会社の人が並んで表示されるのでメールの送信先を選択し易くなります。
ところが、この[件名]フィールドは連絡先をOutlook 2007上でGUIから個別に編集して保存すると、都度[姓][名]の形式で上書きされてしまいます。
現在はOutlook起動時に全連絡先をマクロで書き直していますが、起動に余分な時間がかかりますしできれば連絡先を編集して保存するタイミングでフックできれば一つの連絡先だけを書き直せばよいので助かります。
連絡先の保存をフックする方法はあるのでしょうか?
またGUIでの保存だけをフックしたいのですが、フック処理関数の中でContactItem.Saveを使うと再帰的にフックされてしまうものでしょうか?


このようなご要望を満たす方法としては、連絡先のフォームをカスタマイズし、保存の際に呼び出される Item_Write イベントによって件名を設定するというものが考えられます。

連絡先のフォームをカスタマイズする手順は以下の通りです。

  1. [ツール]-[オプション]-[その他] の [詳細オプション] をクリックし、"[開発] タブをリボンに表示する" をオンにしてから、全てのダイアログを [OK] で閉じます。
  2. [ファイル]-[新規作成]-[連絡先] をクリックし、連絡先の新規作成ウィンドウを表示します。
  3. [開発] リボンの [このフォームのデザイン] をクリックします。
  4. フォームのカスタマイズ画面が表示されますので、[コードの表示] をクリックします。 なお、カスタマイズ画面に含まれるコントロールは変更しないように注意してください。
  5. [スクリプト エディタ] のウィンドウで以下のようなコードを入力します。

    ' ここをトリプルクリックでコード全体を選択できます。
    Function Item_Write()
        Item.Subject = Item.CompanyName & " " & Item.Department & " " & Item.LastName & " " & Item.FirstName
        ' 名前などの並び順を漢字のコード順ではなく、フリガナの順にしたい場合は、下記のコードのコメントを外します。
        ' Item.Subject = Item.YomiCompanyName & " " & Item.Department & " " & Item.YomiLastName & " " & Item.YomiFirstName
    End Function

  6. [スクリプト エディタ] のウィンドウを閉じます。
  7. [開発] リボンの [発行] をクリックし、[フォームの発行] をクリックします。
  8. [フォームの場所] で [Outlook フォルダ] を選択し、[詳細] をクリックして [連絡先] を選択します。(通常なら、連絡先が選択済みです。)
  9. 表示名に任意の名前 (たとえば、"SetSubject" など) を入力し、[発行] をクリックします。
  10. 新規作成のウィンドウを閉じます。
  11. [連絡先] フォルダを右クリックし、[プロパティ] をクリックします。
  12. [全般] タブの [このフォルダに投稿するときに使用するフォーム] で 8.で入力した名前を選択し、[OK] をクリックします。

これにより、新規に作成した連絡先のアイテムについては、そのアイテムの保存の際に自動的に件名に「会社名 部署名 姓 名」という文字列が設定されます。

また、すでに連絡先にあるアイテムでもこのフォームを使う場合には、以下のマクロを一度だけ実行します。

' ここをトリプルクリックでマクロ全体を選択できます。
Public Sub ChangeMessageClassOfAllContacts()
    ' 置き換えるフォームのメッセージ クラスを指定します。
    Const NEW_MESSAGE_CLASS = "IPM.Contact.SetSubject"
    Dim fldContacts 'As MAPIFolder
    Dim objContact 'As ContactItem
    Set fldContacts = Session.GetDefaultFolder(olFolderContacts)
    For Each objContact In fldContacts.Items
        If objContact.MessageClass = "IPM.Contact" Then
            objContact.MessageClass = NEW_MESSAGE_CLASS
            objContact.Save
        End If
    Next
End Sub

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

Google Apps Sync for Microsoft Outlook をインストールすると Outlook の検索ができなくなる

先日、Google 社より Outlook のメールや予定表、連絡先と Google Apps のデータを同期するための Google Apps Sync for Microsoft Outlook というプラグインが発表されましたが、このツールをインストールすると Outlook 内のすべてのデータの検索ができなくなるという現象が発生するようです。

原因は Google Apps Sync がインストールの際に Windows Search の設定を勝手に変更し、Outlook の一切のデータを検索対象から除外するようにしてしまうためです。この設定はユーザー単位ではなくコンピュータ単位で行なわれるので、コンピュータを複数のユーザーで使っている場合には、誰かが Google Apps Sync をインストールすると、他のユーザーも Outlook のデータの検索ができなくなります。

この問題の回避策は Google Apps Sync のインストーラが行った以下のレジストリ設定の変更を元に戻すということになります。手順は以下の通りです。(最新版の Google Apps Sync をインストールしてからアンインストールをすることでも回避できます。)

  1. ファイル名を指定して実行により、REGEDIT を起動します。
  2. レジストリ キーの “HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Windows Search” まで移動します。
  3. PreventIndexingOutlook をダブルクリックします。
  4. 値を 0 にして [OK] をクリックします。
  5. REGEDIT を終了します。

レジストリの編集に自信がないという方のために、上記の設定を行なうファイルを用意しました。http://cid-9d7ea61ec7daa750.skydrive.live.com/self.aspx/%e5%85%ac%e9%96%8b/EnableSearchInOutlook.reg の [ダウンロード] をクリックして EnableSearchInOutlook.reg をローカル ディスクに保存し、それをダブル クリックして設定を適用してください。なお、この設定を適用するにはコンピュータの管理者権限が必要となります。

参考リンク:
Microsoft Office Outlook Team Blog – Google Apps Sync Disables Outlook Search
What’s different with Google Apps Sync for Microsoft Outlook

7/1 追記:
Google Apps Sync の不具合が修正されたようです。
http://googleenterprise.blogspot.com/2009/06/updates-to-google-apps-sync-for.html

メッセージの受信者の Exchange のプロパティを取得するマクロ

あしあと機能を使って以下のようなご質問を受けました。


メール誤送信を防ぐために Outlook で確認用のマクロを作っております。
Application_ItemSend のタイミングでチェックするものです。
入力されたメールアドレスをアドレス帳(Exchange)から検索し、
関係ある所属(指定した所属)であるかどうかを判定したいです。
どのようなコードを書けばよいでしょうか?


Outlook のバージョンが記載されていなかったので、Outlook 2007 であることを前提として説明します。

Outlook 2007 から、AddressEntry オブジェクトの GetExchangeUser メソッドにより、ExchangeUser オブジェクトが取得できるようになりました。このオブジェクトはメッセージの受信者などが Exchange Server のグローバル アドレス一覧に存在する場合に、Exchange ユーザーの詳細なプロパティを取得できるようにするものです。部署名は、ExchangeUser オブジェクトの Department プロパティに格納されています。

以下は、メッセージ送信の際に、メッセージの受信者の部署名をイミディエイト ウィンドウに表示するサンプルです。

' ここをトリプルクリックでマクロ全体を選択できます。
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
    Dim objRecp As Recipient
    Dim objExchUser As ExchangeUser
'
    If Item.MessageClass Like "IPM.TaskRequest*" Then
        Set Item = Item.GetAssociatedTask(False)
    End If
'
    For Each objRecp In Item.Recipients
        Set objExchUser = objRecp.AddressEntry.GetExchangeUser()
        If Not objExchUser Is Nothing Then
            Debug.Print objExchUser.Department
        End If
    Next
End Sub

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