【VBA】一瞬でExcelのスケジュールをOutlookの予定表へ登録/変更する方法

【追加】予定アイテム更新処理<高速版>

Excelから予定表の更新を行う処理に2~3分時間がかかってしまうとのご意見がありましたので、
処理方法を見直した高速版を公開します。

今までは予定アイテム全件のIDをチェックしていましたので、Outlook利用歴が長い方や密にスケジュールを入れている予定アイテム総数が多い方は処理時間がどうしてもかかってしまいます。

そこでIDをチェックする範囲を期間で絞り込み、予定アイテム数を少なくすることによって、処理を軽減させていきます。

タカヒロ
タカヒロ
多忙な方ほど処理時間が長くなってしまうということでエク短的に改善必須でしたね…

VBAは以下の通りとなります。

Sub Outlookの予定表へ登録する_高速版()

    'Outlook用の定義
    Dim olApp As Outlook.Application
    Dim olNamespace As Outlook.Namespace
    Dim olFolder As Folder
    Dim olConItems As Outlook.Items
    Dim olItem  As AppointmentItem
    Dim olItemBefor As AppointmentItem
    Dim checkFlg As Long
    
    '重複チェックフラグ初期値設定
    checkFlg = 0

    'Excel用の定義
    Dim wbBook As Workbook
    Dim wsSheet As Worksheet
    Dim lnContactCount As Long
    Dim i As Long
    
    '抽出期間の定義
    Dim strStart As String
    Dim strEnd As String
    Dim intKikan As Integer
    
    
    '対象予定表の抽出期間を月単位で指定します。
    '※抽出期間が短いと予定アイテムのチェックができず登録できない場合がありますので注意してください。
    intKikan = 12  '抽出期間を12か月にしています。
    
    strStart = Format(DateAdd("m", -intKikan, Date), "yyyy/mm/dd") '抽出するスケジュールの開始日を指定
    strEnd = Format(DateAdd("m", intKikan, Date), "yyyy/mm/dd") '抽出するスケジュールの終了日を指定
    
    
    'スクリーンの更新は行われません。
    Application.ScreenUpdating = False
    
    'Excelのブックとワークシートのオブジェクトを設定します。
    Set wbBook = ThisWorkbook
    Set wsSheet = wbBook.Worksheets(1)
    
    wsSheet.Activate
    
    'Outlookオブジェクトを設定し、MAPI名前空間を介してOutlookの予定表を取得します。
    Set olApp = New Outlook.Application
    Set olNamespace = olApp.GetNamespace("MAPI")
    Set olFolder = olNamespace.GetDefaultFolder(olFolderCalendar)
    Set olConItems = olFolder.Items

    'Restrictメソッドで期間指定して抽出するメールアイテムを絞り込む
    Set olConItems = olConItems.Restrict("[Start] >= '" & strStart & "' And [End] < '" & strEnd & "'")


    '取得結果を記述する行番号を指定します。2行目のセルから開始されることになります。
    lnContactCount = 2

    Dim rc As Integer
    rc = MsgBox("予定表へ登録しますか?", vbYesNo + vbQuestion, "確認")
    
    If rc = vbYes Then
    
        '予定表一覧の件数分繰り返す。
        For i = lnContactCount To Cells(1, 1).End(xlDown).Row
            Set olItem = olApp.CreateItem(olAppointmentItem)

            '重複チェック&更新処理
            For Each olItemBefor In olConItems
                If TypeName(olItemBefor) = "AppointmentItem" Then
                
                    'ExcelI列のEntryIDと登録されているEntryIDが一致していたら該当予定表を更新
                    If olItemBefor.EntryID = Cells(i, 9) Then
                    
                        '比較用に一時的に作成
                        With olItem
                            .Subject = Cells(i, 1)
                            .Start = Format(Cells(i, 3), "yyyy/mm/dd hh:mm:ss")
                            .End = Format(Cells(i, 4), "yyyy/mm/dd hh:mm:ss")
                        End With
    
                    
                        '重複フラグ1をセット
                         checkFlg = 1
                    
                        '登録されている予定表の件名と開始日時及び終了日時が一致していなかった場合のみ更新
                        '※更新の条件はご都合に応じて変更してください。この条件が無い場合はExcelの予定表すべて更新されますので、ご注意ください。
                        If olItemBefor.Subject = olItem.Subject And olItemBefor.Start = olItem.Start And olItemBefor.End = olItem.End Then
    
    
                        Else

                            '定期アイテムは除外します。
                            If Not olItemBefor.IsRecurring Then
                                 With olItemBefor
                                    .Subject = Cells(i, 1)
                                    .Location = Cells(i, 2)
                                    .Start = Format(Cells(i, 3), "yyyy/mm/dd hh:mm:ss")
                                    .End = Format(Cells(i, 4), "yyyy/mm/dd hh:mm:ss")
                                    .Body = Cells(i, 5)
                                    .RequiredAttendees = Cells(i, 6)
                                    .OptionalAttendees = Cells(i, 7)
                                    .Save
                                End With
                            End If
                        End If
                        
                        'Null out the variables.
                        Set olItem = Nothing
                        
                    End If
                End If
            Next
            'EntryIDが空である場合のみ新規登録をすることにしました。
            If checkFlg <> 1 And Cells(i, 9) = "" Then
                With olItem
                    .Subject = Cells(i, 1)
                    .Location = Cells(i, 2)
                    .Start = Format(Cells(i, 3), "yyyy/mm/dd hh:mm:ss")
                    .End = Format(Cells(i, 4), "yyyy/mm/dd hh:mm:ss")
                    .Body = Cells(i, 5)
                    .RequiredAttendees = Cells(i, 6)
                    .OptionalAttendees = Cells(i, 7)
                    .Save
               End With
    
               'ExcelI列へ発行されたEntryIDを書き込み
               Cells(i, 9) = olItem.EntryID
                
            End If
    
        
        '重複フラグリセット
        checkFlg = 0
    
    Next
    
    Else
        MsgBox "処理を中断します"
        Exit Sub
    End If
    
    'Null out the variables.
    Set olItem = Nothing
    Set olApp = Nothing
    Set wbBook = Nothing
    Set wsSheet = Nothing
    Set olNamespace = Nothing
    Set olFolder = Nothing
    Set olConItems = Nothing

            
    'Turn screen updating back on.
    Application.ScreenUpdating = True
    
    MsgBox "Outlook予定表の登録が完了しました!", vbInformation
    
End Sub

設定してもらいたい箇所は以下の数値の箇所です。

ここでは対象予定表の抽出期間を月単位で指定します。
intKikan = 12

サンプルでは抽出期間を12か月に設定しているという意味となり、
この場合、12か月前から12か月後の予定アイテムが対象となるわけです。

[抽出開始]<—-12か月間—->[現在]<—–12か月間—->[抽出終了]

これまではOutlookの予定アイテムがある期間分取得していましたので、

人によっては膨大な予定アイテム数になってしまうわけですが、

期間指定により期間外の予定アイテムは除外されるので、対象予定アイテム数が絞られるという仕組みになります。

タカヒロ
タカヒロ
こちらの環境で検証したところ、12か月指定で1分、6か月指定で数十秒、1か月指定だと一瞬で完了します。Outlook利用歴の長い方ほど効果がでると思います。

なお、期間を短くすればするほど比例して処理時間も短くなりますが、
その分更新漏れのリスクが生じますのでご注意ください。

【追加】予定表の公開方法を指定するVBA

読者の方から予定表の公開方法を指定する質問がありましたので、追記致します。

予定登録時に予定の公開方法を合わせて指定する場合は、
BusyStatusプロパティへ以下の値を指定することで対応可能です。

名前 説明
olBusy 2 予定あり
olFree 0 予定なし
olOutOfOffice 3 外出中
olTentative 1 仮の予定あり
olWorkingElsewhere 4 リモート

Excelシートへ値を指定し、VBAへ渡す場合は、
例えばL列を「予定の公開方法」とした場合は、
L1セルにタイトル名、L2以降に上記表の値の数字か名前を入力します。

VBA側では各オブジェクトへプロパティを指定する箇所に以下を追加します。

.BusyStatus = Cells(i, 12)

サンプルコード中では以下オブジェクトの2か所になります。

With olItemBefor
With olItem

実行してみましょう。

値を「外出中」の3に指定してみましたが、予定表をみますと…

はい、「予定の公開方法」が指定通りですね。

【追加】終日の予定を登録する

読者の方からのご要望により時間指定の予定以外に終日の予定の登録方法について記載いたしましたので、
終日の予定も併せて登録されたい方はこちらをご参照ください。

【VBA】Excel からOutlookへ終日の予定を登録する方法!複数日指定も!

 

さいごに

いかがでしょうか。
Outlookの操作は手作業が多いですからなるべく自動化して効率化を図りたいですね。

【VBA】ExcelからOutlookの追加した予定表へスケジュールを登録する

Excelの予定一覧から他人のOutlook予定表を登録、編集する方法

他人のOutlook予定表をExcelワークシートへ取り込む方法

【Excel VBA】先月、今月、翌月分のOutlook予定表データをワンクリックで取り込む



この記事の関連キーワード

こちらの記事の関連キーワード一覧です。クリックするとキーワードに関連する記事一覧が閲覧できます。







111 件のコメント

  • 予定表をデフォルトの予定表ではなく、新しく作成した別の予定表に入れることはできますか?

    • いつもご利用ありがとうございます。

      予定表をデフォルトの予定表ではなく、新しく作成した別の予定表を指定し登録する方法について
      以下の記事にまとめておりますので、ご参考いただきたくお願いいたします。
      https://extan.jp/?p=3341

    • ご指摘ありがとうございます。

      olItemBeforの宣言は入れるべきでした。大変失礼いたしました。
      掲載のコードも修正させていただきました。

      よろしくお願いいたします。

  • コメントを残す

    メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

    CAPTCHA ImageChange Image