[Excel]VBAでOutlookの連絡先を取得(インポート)する

VBAは外部のライブラリを参照する事によって、そのアプリケーションには無い機能を利用することができます。今回はExcelOutlookの連絡先データを取得するコードを紹介します。

参考にするコード

検索してみたところ、公式にそのまま利用できそうなコードがありました。

マクロを実行すると、コード内で指定したフィールド(連絡先データ)が出力されます。連絡先「勤務先」欄の入力有無によって出力するデータが分岐するようです。

出力するフィールドを変更する場合、次の箇所を書き換えます。

基コードの設定箇所(抜粋)

'フィールド名設定
 With wsSheet
    .Range("A1").CurrentRegion.Clear
    .Cells(1, 1).Value = "Company / Private Person" 'ここの文字列がフィールド名になる
    .Cells(1, 2).Value = "Street Address"
    .Cells(1, 3).Value = "Postal Code"
    .Cells(1, 4).Value = "City"
    .Cells(1, 5).Value = "Contact Person"
    .Cells(1, 6).Value = "Email"

'フィールドの指定
With olItem
    If InStr(olItem.CompanyName, strDummy) > 0 Then
            Cells(lnContactCount, 1).Value = .CompanyName 'ContactItemプロパティ名で指定する
            Cells(lnContactCount, 2).Value = .BusinessAddressStreet
            Cells(lnContactCount, 3).Value = .BusinessAddressPostalCode
            Cells(lnContactCount, 4).Value = .BusinessAddressCity
            Cells(lnContactCount, 5).Value = .FullName
            Cells(lnContactCount, 6).Value = .Email1Address
    Else
            Cells(lnContactCount, 1) = .FullName
            Cells(lnContactCount, 2) = .HomeAddressStreet
            Cells(lnContactCount, 3) = .HomeAddressPostalCode
            Cells(lnContactCount, 4) = .HomeAddressCity
            Cells(lnContactCount, 5) = .FullName
            Cells(lnContactCount, 6) = .Email1Address
    End If

フィールド名は好きな名前を付けて下さい(名前、メールアドレス等)。ContactItemオブジェクトのプロパティ名は公式にまとめがあったので、確認を兼ねて一覧表にしました。

次の表から出力したいフィールドのプロパティ名を探してコードを書き換えて下さい。

ContactItemオブジェクトのプロパティ名 一覧

連絡先でよく使うフィールドとそのプロパティ名

名前関連

フィールド名プロパティ名
LastName
FirstName
勤務先CompanyName
フリガナ (姓)YomiLastName
フリガナ (名)YomiFirstName
フリガナ (勤務先名)YomiCompanyName
部署Department
役職JobTitle
表題FileAs

インターネット

フィールド名プロパティ名
メールEmail1Address
電子メール 表示名Email1DisplayName
Web ページWebPage
IM アドレスIMAddress

電話

フィールド名プロパティ名
秘書の電話AssistantTelephoneNumber
勤務先電話BusinessTelephoneNumber
勤務先電話2Business2TelephoneNumber
勤務先 FAXBusinessFaxNumber
コールバックCallbackTelephoneNumber
自動車電話CarTelephoneNumber
勤務先代表電話CompanyMainTelephoneNumber
自宅電話HomeTelephoneNumber
自宅電話 2Home2TelephoneNumber
自宅 FAXHomeFaxNumber
ISDNISDNNumber
携帯電話MobileTelephoneNumber
その他の FAXOtherFaxNumber
その他の電話OtherTelephoneNumber
ポケットベルPagerNumber
通常の電話PrimaryTelephoneNumber
無線電話RadioTelephoneNumber
テレックスTelexNumber
TTY/TDDTTYTDDTelephoneNumber

住所

フィールド名プロパティ名
郵便番号 (勤務先)BusinessAddressPostalCode
都道府県 (勤務先)BusinessAddressState
市区町村 (勤務先)BusinessAddressCity
番地 (勤務先)BusinessAddressStreet
国/地域 (勤務先)BusinessAddressCountry
郵便番号 (自宅)HomeAddressPostalCode
都道府県 (自宅)HomeAddressState
市区町村 (自宅)HomeAddressCity
番地 (自宅)HomeAddressStreet
国/地域 (自宅)HomeAddressCountry
郵便番号 (その他)OtherAddressPostalCode
都道府県 (その他)OtherAddressState
市区町村 (その他)OtherAddressCity
番地 (その他)OtherAddressStreet
国/地域 (その他)OtherAddressCountry
郵便番号 (郵送先)MailingAddressPostalCode
都道府県 (郵送先)MailingAddressState
市区町村 (郵送先)MailingAddressCity
番地 (郵送先)MailingAddressStreet
国/地域 (郵送先)MailingAddressCountry

その他

フィールド名プロパティ名
事業所OfficeLocation
職業Profession
上司ManagerName
秘書AssistantName
ニックネームNickName
敬称 (Dr,Mrs)Title
敬称 (殿,様)Suffix
配偶者/パートナーSpouse
誕生日Birthday
記念日Anniversary

連結して値を返すプロパティ名

各フィールドを連結して値を返すプロパティもいくつか存在します。連絡先の「表題」に用意されているパターンもこれらのプロパティを使用しているのでしょう。

次のサンプルを例に表にしました。

  • 姓…煉獄(英字:Rengoku)
  • 名…杏寿郎(英字:Kyoujyurou)
  • 勤務先…鬼殺隊(英字:Demon Slayer)
  • 敬称…殿(英字:Dr.)

名前関連

連結するフィールド名プロパティ名サンプルの表示結果
姓,名LastFirstNoSpace煉獄杏寿郎
姓 [ ] 名LastFirstSpaceOnly煉獄 杏寿郎
姓,名 [ ] 敬称LastFirstNoSpaceAndSuffix煉獄杏寿郎 殿
姓,名 [↓] 勤務先LastFirstNoSpaceCompany煉獄 杏寿郎
鬼殺隊
姓 [ ] 名 [↓] 勤務先LastFirstSpaceOnlyCompany煉獄 杏寿郎
鬼殺隊
勤務先 [↓] 姓,名CompanyLastFirstNoSpace鬼殺隊
煉獄杏寿郎
勤務先 [ ] 姓[↓]名CompanyLastFirstSpaceOnly鬼殺隊
煉獄 杏寿郎

英字の名前や英字の敬称(Dr,Mrs)を付与している場合、以下のプロパティを使用します。

連結するフィールド名プロパティ名サンプルの表示結果
英字敬称 [ ] 名 [ ] 姓 [ ]FullName ※Dr. Kyoujyurou Rengoku
姓 [ ] 名(英字)LastNameAndFirstNameRengoku, Kyoujyurou
姓 [ ] 名 [↓] 勤務先(英字)FullNameAndCompanyRengoku, Kyoujyurou
Demon Slayer
勤務先 [↓] 姓 [ ] 名(英字)CompanyAndFullNameDemon Slayer
Rengoku, Kyoujyurou

FullName は日本語でも値を返します。 英字の敬称(Dr,Mrs) を付与していなければ、結果は「 姓 [ ] 名 [ ] 敬称 」になるので LastFirstNoSpaceAndSuffix 「 姓名 [ ] 敬称 」とは空白1個分の違いがあります。

住所関連

住所のフィールドを連結するプロパティもあります。

連結するフィールド名プロパティ名
勤務先:郵便番号 [↓] 都道府県,市区町村,番地BusinessAddress
自宅:           ↑HomeAddress
その他:          ↑OtherAddress
郵送先:          ↑MailingAddress

その他

アドレス帳の [ 名前 ]Subject

アドレス帳の「名前」欄は、これまでに紹介したプロパティでは表示できません。仕様は「日本語だと 姓,名,敬称、英字だと 名,姓(敬称抜き)」みたいな感じです(多分)。

アドレス帳「名前」フィールドを出力する場合はSubjectプロパティを使用して下さい。日本語のみの場合はFullNameでも代用できます。

基コードの説明は以上です。

コードを変更する

コードの次の点を変更します。

  • ハイパーリンクは不要なので削除
  • 出力の条件分岐も不要なので削除
  • シートの指定をシート名からオブジェクト名に変更
  • フィールド名とフィールドの指定以外はコードを書き換えなくてもいいようにする
  • データを配列に格納してまとめて出力する(処理時間短縮)
  • アドレス帳と同じデータを出力する

4番目は、例えば出力するデータ項目を増やす場合、基コードの.Cells(1, 6).Value = “Email”Cells(lnContactCount, 6).Value = .Email1Addressをコピペしてフィールド名とプロパティ名を新たに指定、「6」を「7」に変更する、といった作業が必要になります。

この作業をまるっと無くすのが目的です。

アドレス帳インポート

Public Sub Import_Contacts()
    Dim olApp As Object, olNamespace As Object, olFolder As Object, olConItems As Object, olItem As Object
    Dim fieldNameAry() As Variant, contactItemsAry() As Variant
    Dim conItemNum As Long, lnContactCount As Long, i As Long, k As Long

    Application.ScreenUpdating = False
    Set olApp = CreateObject("Outlook.Application")

    With wsAddress 'ワークシートのオブジェクト名を変更して下さい
        .Range("A1").CurrentRegion.Clear
        fieldNameAry = Array("名前", "表示名", "電子メールアドレス") '好きなフィールド名に書き換え
        For i = 0 To UBound(fieldNameAry)
            .Cells(1, i + 1).Value = fieldNameAry(i)
        Next i
        conItemNum = UBound(fieldNameAry) + 1
        With .Range("A1").Resize(1, conItemNum)
            .Font.Bold = True
            .Font.ColorIndex = 10
            .Font.Size = 11
        End With

        Set olNamespace = olApp.GetNamespace("MAPI")
        Set olFolder = olNamespace.GetDefaultFolder(10)
        Set olConItems = olFolder.Items

        lnContactCount = 0

        ReDim itemsCntAry(olFolder.Items.Count, conItemNum)

        For Each olItem In olConItems
            With olItem
                contactItemsAry = Array(.Subject, .Email1DisplayName, .Email1Address) 'ContactItemプロパティ
            End With
            If TypeName(olItem) = "ContactItem" Then
                For k = 0 To UBound(contactItemsAry)
                    itemsCntAry(lnContactCount, k) = contactItemsAry(k)
                Next k
                lnContactCount = lnContactCount + 1
            End If
        Next olItem

        .Range("A2").Resize(olFolder.Items.Count, conItemNum) = itemsCntAry

        Set olItem = Nothing
        Set olConItems = Nothing
        Set olFolder = Nothing
        Set olNamespace = Nothing
        Set olApp = Nothing

        .Range("A2", .Cells(2, conItemNum).End(xlDown)).Sort key1:=.Range("A2"), order1:=xlAscending
        .Range(.Columns(1), .Columns(conItemNum)).EntireColumn.AutoFit
    End With
    Application.ScreenUpdating = True
    MsgBox "アドレス帳をインポートしました", vbInformation
End Sub

出力するデータを変更する場合、11行目の配列にフィールド名を、32行目の配列にフィールドのプロパティ名を指定します。9行目のワークシートのオブジェクト名変更も必須です。

変更箇所

参照設定なしで外部ライブラリを使用する

  • 2行目…宣言を変更
  • 7行目…CreateObject関数でOutlook.Applicationを指定

あえて参照設定なしのコードにしています。可能なら参照設定推奨です。

この記事で参照設定について紹介しているので時間が取れる方は読んでみて下さい。

参照設定とCreateObject

エクセルVBAでは、外部ライブラリ(エクセル外のオブジェクト)を参照する事によりエクセルには無い機能を利用する事ができます。方法は2つあって「参照設定」と「CreateObject関数」です。 [adcode] 参照設定 […]

シートをオブジェクト名で指定

  • 9行目…シートをオブジェクト名で指定

シートのオブジェクト名をsheet1から変更します(サンプルコードはwsAddress)。ワークシートのプロパティからオブジェクト名を変更してください。

Setや宣言を省けるし、シート名を変更されてもエラーが出ません。

フィールド名指定処理変更

  • 3行目…配列宣言
  • 11行目…配列の要素指定(フィールド名)
  • 12~14行目…配列に格納されたフィールド名をA1セルから順に、横方向に出力する
  • 15行目…配列の要素数(16行目のResizeに必要)
  • 16行目…書式を変更する範囲を指定(A1セルから要素数分Resizeで範囲指定)

フィールド名を指定する処理を変更しています。基コードはフィールド数を変更すると.Cells(r, c).Value = の部分もフィールド数に合わせて編集する必要があります。

このコードであれば、配列の中身を変更すればその他の部分は書き換えが不要です。

処理時間短縮

  • 28行目…配列宣言(行:フィールド件数、列:フィールド数)
  • 35~37行目…出力するデータを配列に格納
  • 42行目…配列をシートに出力(宣言した要素と同じ範囲をResizeで指定)

フィールドを出力する処理を変更しています。基コードはデータをひとつずつ出力する処理ですが、配列に一度格納し、まとめて出力する事で処理時間を短縮しています。

フィールド指定処理変更

  • 3行目…配列宣言
  • 32行目…配列の要素指定(フィールド)
  • 36行目…フィールドを配列(処理時間短縮用)に格納
  • 50~51行目…ソート処理の範囲指定

フィールド名同様、配列の中身以外はコード書き換えが不要になります。

既知の不具合

フィールド名数 < フィールド数 だとエラーが出ます。フィールド名数とフィールド数は合わせて下さい。

あとがき

思った通りの動きで満足なのですが、コードの可読性は悪いです。基コードは非常に読みやすいので、その辺りを考えてのコードなのかも知れません。そんなコードが書けるのはいつの日になる事やら。

それでは最後までご高覧いただき、ありがとうございました。