次の方法で共有


Office Space: Microsoft Outlook の電子メール メッセージの件数をカウントする

Office Space

Office Space へようこそ。Office Space は、Microsoft® Office アプリケーションのスクリプト作成に関するヒントとテクニックを紹介するコラムです。毎週木曜日に新しいヒントを掲載します。過去のヒントについては、Office Space アーカイブを参照してください。Microsoft Office でのスクリプト作成について質問がある場合は、scripter@microsoft.com (英語のみ) までお送りください。すべての質問に回答することはできないかもしれませんが、可能な限り対応いたします。

Microsoft Outlook の電子メール メッセージの件数をカウントする

コンピュータの算術演算機能を最大限に活用しているユーザーは少数だと思いますが、コンピュータは "計算処理" に長けていることで有名です。この能力は、ユーザーが処理したい数値についても発揮されます。たとえば、Microsoft Outlook も、その一例です。Scripting Guys によく見られる行動ですが、廊下をうろうろすると、次のような嘆き声を耳にすることでしょう。

「10 月は 1 年のうちで最もミーティングが多くて、他の月の 2 倍の数のミーティングがあるような気がする。」

「私の得意先の大半は Fabrikam で働いていると思う。いや、Contoso かもしれない。実際のところ、はっきりとはわからないけど。」

「火曜日は憂鬱だ。理由はわからないけど、なぜか火曜日には大量のメールを受信するようだ。実際にメールの件数を数えたことはないけど、少なくとも私はそう感じている。」

このような状況には、コンピュータの能力を活かせると思います。

ご存知のように、Microsoft Outlook には情報を格納するための巨大な貯蔵庫があります。問題となるのは、この情報にアクセスする明確な方法がないことです。しかし、それはもう過去の話です。今週のコラムでは、Outlook フォルダ内にあるアイテムをカウントする単純明快な方法を紹介します。このサンプル スクリプトでは、1 日に受信した電子メールの件数をカウントします。1 日に受信した電子メールの件数を把握することは最重要事項ではないかもしれませんが、この基本的な考え方を理解すると、このサンプル スクリプトを応用して、次に示すような、さまざまな処理を行えるようになるという利点があります。

  • [送信済みアイテム] フォルダを調べて、1 日に送信した電子メールの件数をカウントする。

  • [受信トレイ] フォルダを調べて、差出人または件名ごとに電子メールの件数をカウントする。

  • [予定表] フォルダを調べて、週または月ごとの予定の件数をカウントする。

  • Outlook のすべてのフォルダを調べて、受信した電子メールの件数をカウントし、その受信日時を列挙する。

これは一例です。

今週のコラムでは、単純なスクリプトを紹介するにとどめます。受信トレイにあるすべてのメッセージを調べて、それらを 1 日ごとにカウントします (つまり、10 月 10 日に何件のメッセージを受信し、10 月 9 日に何件のメッセージを受信したか、などの情報を収集します)。ここでは、受信トレイにあるメッセージを処理していることに注意してください。10 月 10 日に受信した電子メール メッセージを削除したり、別のフォルダに移動した場合、このスクリプトではその電子メール メッセージをカウントすることはできません。このスクリプトは、受信トレイにあるメッセージについてのみ処理を行うことができます。

コードは次のようになります。

Const olFolderInbox = 6

Set objDictionary = CreateObject("Scripting.Dictionary")

Set objOutlook = CreateObject("Outlook.Application")
Set objNamespace = objOutlook.GetNamespace("MAPI")
Set objFolder = objNamespace.GetDefaultFolder(olFolderInbox)

Set colItems = objFolder.Items

For Each objItem in colItems
    strDate = FormatDateTime(objItem.SentOn, vbShortDate)
    If objDictionary.Exists(strDate) Then
        objDictionary.Item(strDate) = objDictionary.Item(strDate) + 1
    Else
        objDictionary.Add strDate, "1"
    End If
Next

colKeys = objDictionary.Keys

For Each strKey in colKeys
    Wscript.Echo strKey, objDictionary.Item(strKey)
Next

それでは、このスクリプトはどのように動作するのでしょうか。このスクリプトの始まりは単純です。まず、olFolderInbox という名前の定数を定義し、値を 6 に設定します。この定数を使用して、どの Outlook フォルダを処理するかをスクリプトに指示します。次に、Dictionary オブジェクトのインスタンスを作成します。このオブジェクトは、1 日に受信した電子メール メッセージの件数をカウントするのに使用します。

Dictionary オブジェクトが、キーと項目の組み合わせを追跡するのに適した方法なのかを疑問に思う人もいるでしょう。Dictionary オブジェクトには、一連のキー (日付など) と対応する一連の項目 (ある特定の日に受信した電子メール メッセージの件数など) を渡します。大部分において、Dictionary オブジェクトは単なる配列ですが、1 つの特典があります。このオブジェクトでは、特定のキーの存在の有無を迅速かつ簡単に確認できます。たとえば、10/10/2005 のような日付がある場合、Exists メソッドを使用して、Dictionary オブジェクトに、この名前のキーが存在しているかどうかを確認できます。これに対して、普通の配列の場合は、配列に格納されているすべての値をループ処理で確認し、10/10/2005 に一致する値があるかどうかを確認する必要があります。また、それ以降の日付についても、同様の処理を行う必要があります。

Dictionary オブジェクトのおおまかな概要を紹介しましたが、このコラムを読み進めると、このオブジェクトがどのように機能するかについての理解を深めることができます。また、Dictionary オブジェクトについての概略的な背景情報を入手するには、「Microsoft Windows 2000 Scripting Guide」のこちらのセクション (英語) を参照してください。

さて、どこまで説明しましたっけ。そうでした。スクリプトについて説明していたところでした。Dictionary オブジェクトを作成した後、次の 3 行のコードで、Outlook.Application オブジェクトのインスタンスを作成し、MAPI 名前空間にバインドして、受信トレイ フォルダを開きます。

Set objOutlook = CreateObject("Outlook.Application")
Set objNamespace = objOutlook.GetNamespace("MAPI")
Set objFolder = objNamespace.GetDefaultFolder(olFolderInbox)

この処理により、次のコード行を呼び出して、受信トレイにあるすべてのアイテムを取得できるようになります。

Set colItems = objFolder.Items

おもしろいのはここからです。

もちろん、ここまでも十分におもしろかったと思いますが、ここからは、さらにおもしろくなります。

まず、For Each ループを設定して、受信トレイにあるアイテムのコレクション (メール メッセージなど) を調べます。では、次の行に移りましょう。

strDate = FormatDateTime(objItem.SentOn, vbShortDate)

電子メール メッセージの SentOn プロパティは、メッセージの受信日時を表します。このスクリプトで処理対象となるのは日付のみです。ここで必要な情報は、2005 年 10 月 10 日に何件の電子メールを受信したかという情報で、メッセージの受信時刻は不要な情報です。そのため、FormatDateTime 関数を使用し、この関数に SentOn プロパティの値と VBScript の定数 vbShortDate を渡します。この関数では、どのような処理が行われるのでしょうか。この関数では、SentOn プロパティ値が保持している時刻の形式を 10/10/2005 1:47 PM から 10/10/2005 に変換します。そして、この変換後の値を strDate という名前の変数に格納します。

これで Dictionary オブジェクトを使用する準備が整いました。まず、Exists メソッドを使用して、Dictionary オブジェクトが、strDate 変数の値と一致するキー (たとえば、10/10/2005 など) を保持しているかどうかを判断します。

If objDictionary.Exists(strDate) Then

Exists メソッドから False が返された場合、一致するキーは存在しません。この場合、Else ステートメントで、次のコード行が実行されます。

objDictionary.Add strDate, "1"

ここでは、Dictionary オブジェクトに対して Add メソッドを呼び出して、変数 strDate と 1 という 2 つのパラメータを渡します (この変数を渡すことにより、変数 strDate の値と一致するキーを追加することになります)。では、なぜ 1 を渡すのでしょうか。これは 2005 年 10 月 10 日に受信したメッセージとして最初に検出されたメッセージを示し、キーと項目の組み合わせの項目部分を使用して、1 日に受信したメッセージの合計件数を追跡します。今のところ、2005 年 10 月 10 日のキーが作成されていないので、最初に受信したメッセージとして 1 を設定します。

しかし、Exists メソッドから True が返された場合はどうなるのでしょうか。このような場合は、変数 strDate の値と一致するキーが Dictionary オブジェクトに存在していることになります (言い忘れましたが、Dictionary オブジェクト内でキーは一意である必要があります)。つまり、2005 年 10 月 10 日に受信したメッセージが少なくとも 1 件は検出されており、そのことが Dictionary オブジェクトに記録されています。2005 年 10 月 10 日に受信した別のメッセージが検出されたことになるので、次のコード行を使用して、この日に受信したメッセージの件数を 1 増やします。

objDictionary.Item(strDate) = objDictionary.Item(strDate) + 1

ここで行っているのは、特定のキーを持つ項目にバインドして、1 を加算しているだけです。とても簡単ですよね。

処理は以上です。ループに戻り、受信トレイにある後続のメッセージについても同じ処理を繰り返します。

1 日ごとに受信したメールの件数をカウントしたら、次のコード ブロックを使用して結果を返します。

colKeys = objDictionary.Keys

For Each strKey in colKeys
    Wscript.Echo strKey, objDictionary.Item(strKey)
Next

これも非常に基本的な処理で、Dictionary オブジェクトの一連のキーを処理しているだけです。コレクション内のキーごとに、キーと項目の両方の値を返します (ここでは、キーは日付、項目はその日に受信したメッセージの件数になります)。この処理の結果、次のような出力が返されます。

10/6/2005 2
10/7/2005 2
10/8/2005 5
10/9/2005 21
10/10/2005 1
10/11/2005 1
10/12/2005 4

ご覧のとおり、何故か 10 月 9 日は特に忙しい日だったようです。来年の 10 月 9 日はお休みを取ろうと思います。私たちが忘れていたら、お知らせください。

既に述べたように、このスクリプトはリアルタイムでは動作しません。電子メールを受信するたびに、受信したメールの件数が逐次更新されることはありません (それは可能でしょうか。不可能ではありませんが、少なくとも、今週のコラムで紹介した処理よりは複雑な処理が必要になるでしょう)。このスクリプトでは、単に、受信トレイにあるすべての電子メール メッセージをカウントするだけです。電子メールを読んだ後に削除してしまった場合、このスクリプトでは、その電子メール メッセージはカウントされません。しかし、マイクロソフト社内で見かけるような状態の受信トレイをお持ちの場合 (受信トレイに数万件ものメッセージが溜まっている場合)、このスクリプトが役に立つかもしれません (編集者注 : 2001 年 5 月 18 日に Scripting Guys 宛てに送信された 24 件のメッセージを探しています)。

これで、世界第 3 位のクランチである "コンピュータ (number-crunching)" についての紹介は以上です (ちなみに第 1 位と第 2 は、ネスレ クランチと Captain Crunch です)。