ここ二週間ほど裏でアドレス帳を実装していましたが、trunkにマージしました。[Tool]-[Address Book]でどうぞ。まだ機能的に不十分なところがあると思いますので、こんな機能が欲しいという方はお早めに。
menus.xml, keymap.xml, toolbars.xmlが変更になっています。また、以前のToolAddressBookアクションはToolSelectAddressアクションに変更されていますのでご注意ください。
Exceptional C++ Styleが届きました。一緒に注文したHowl's Moving Castleも。両方とも350ページくらいなのですが、前者は10日もあれば読めそうなのに、後者は一ヶ月かかっても読みきれなそうな気配がするのはなぜ。しかし、Harry Potter and the Order of the Phoenixに比べたらはるかに薄いのです*1。
Outlookのドキュメントを見て最初に思いついたのはこれです。
var app = new ActiveXObject("Outlook.Application"); var ns = app.GetNameSpace("MAPI"); var entries = ns.AddressLists.Item(1).AddressEntries; for (n = 1; n <= entries.Count; ++n) { var entry = entries.Item(n); WScript.StdOut.WriteLine(entry.Name); WScript.StdOut.WriteLine(entry.Address); }
しかしこれは本当にアドレス帳としてアクセスしているようで、一つのエントリに複数のアドレスが設定されていると複数のエントリになってしまいますし、細かいプロパティにもアクセスできません。
MAPIFolder経由でアイテムを取るのが正しいようです。
set app = CreateObject("Outlook.Application") set ns = app.GetNameSpace("MAPI") set folder = ns.GetDefaultFolder(10) set items = folder.Items For n = 1 to items.Count set item = items.Item(n) itemType = TypeName(item) WScript.StdOut.WriteLine(itemType) If itemType = "ContactItem" Then WScript.StdOut.WriteLine(item.FullName) WScript.StdOut.WriteLine(item.Email1Address) ElseIf itemType = "DistListItem" Then WScript.StdOut.WriteLine(item.DLName) End If WScript.StdOut.WriteLine() Next
ちなみにGetDefaultFolderに渡している10はolFolderContactsの値です。なぜいきなりJScriptからVBScriptに変わったのかというと、TypeNameと同じ機能をJScriptから使う方法がわからなかったからです*2。
OOM経由でアドレス帳からメールアドレスにアクセスすると、毎回「プログラムが、Outlook 内に保存されている電子メール アドレスにアクセスしようとしています。よろしいですか?」というダイアログが出ます。Exchange環境の場合には管理者がこのダイアログを抑制することができるようですが、スタンドアロンの場合にはどうしようもないようです。
Outlook "Object Model Guard" Security Issues for Developersによると、これを回避する方法は、
だそうです。3番目と4番目は置いておくとしても、わざわざプラグインを作る気もしないし、MAPIを直接使うとOOMよりはるかに面倒だし悩みどころですね。OOM経由でもIDispatch経由のときだけブロックしてvtbl経由のときはブロックしないようにしてくれれば良かったのですけど。
MAPIでOutlookのアドレス帳にアクセスするなら、Accessing the Address Book Data Using MAPIが参考になりそうです。良く考えると、今もWABにアクセスするコードはMAPIでやっているのでログイン部分を除くとほとんど使い回しができそうです。