SyntaxHighlighter

2016年2月13日土曜日

Outlook 2010 で外部エディタでメールを編集するマクロ

Outlook 2010 で外部エディタでメールを編集するマクロ

メーラーとして Outlook 2010 を使う場合に、メールを外部のテキストエディタで編集するマクロを作りました。
GitHub で External Editor for Outlook 2010 として公開していますので、よければお使いください。

概要

Outlook 2010 では、メールの編集画面として、 Word のような独自の編集画面が用意されています。
他のメーラーと比べて特に劣っているわけではないと思いますが、私はテキストエディタの方が使いなれているので、できれば編集は好きなエディタでやりたいです。

そこで、外部テキストエディタでメールを編集できる VBA マクロを作ってみました。

マクロの仕組み

このマクロは、 Using Vim as an External Editor with Outlook のマクロを元に、種々の変更を加えて作りました。

下記のような動作になっています。

  1. 現在アクティブなメールエディタの本文を、指定されたディレクトリの下に一時ファイルとして保存する。
  2. そのファイルを引数として、外部のエディタを CreateProcess API で実行する。
  3. SetTimer API で、定期的にエディタのプロセスが終了したかどうかをチェックする。
  4. プロセスが終了したら、一時ファイルの内容をメールエディタの本文に反映させる。

元のマクロと大きく異なる部分は、上記の 3 の SetTimer で待つ部分です。

元のマクロでは、 DoEvents を呼びながらプロセスの終了を待ち続けていたのですが、この実装では、なぜか Outlook 側で他のフォルダを開くことができません。
理由はよく分かりませんが、 Outlook 2010 では、 VBA のプロシージャを抜けるまではフォルダの切り替えができないようです。
そのため、 SetTimer API で待ってみることにしました。

素朴な疑問

いつも疑問に思うのですが、 Microsoft の技術者は Outlook を使っているのでしょうか。

Outlook は一般ユーザー向けには悪くないと思いますが、あまりプログラマーに好まれるものではないように思います。
マクロ言語の VBA は、プログラミング言語として洗練されているとは言い難く、 Outlook 自体のメール仕分けも正規表現が使えないなど、プログラマが不満を持ちそうなポイントが多くあるように感じます。

誰か Microsoft の内情を知っていたら教えてください。

7 件のコメント:

  1. 今晩は。
    私も、好きなエディタを使いたいと思っていたので、さっそくマクロを使わせて頂きました。 ありがとうございます。
    エディタにEmacsを使う設定をしましたが、文章を記載してOutlookに戻りますと、フォントが変わってしまいます。
    Emacsのフォントを変更しても、Outlookに戻ったあとはいつも同じフォントになってしまいます。
    外部エディタに元のフォントと引き継ぎ、編集後もフォントをKeepすることは可能でしょうか?
    可能でしたら、方法を教えて頂けると嬉しいです。
    よろしくお願い致します。

    返信削除
    返信
    1. ご利用ありがとうございます。

      > 外部エディタに元のフォントと引き継ぎ、編集後もフォントをKeepすることは可能でしょうか?
      こちらは、残念ながらサポートしていません。

      このマクロは、原則として Outlook 側が「HTML 形式」ではなく「テキスト形式」でメールを編集することを想定しています。
      そのため、フォント情報が Outlook とエディタ間でやり取りされることは想定していないです。

      削除
  2. そうですかぁ。 Orz

    ありがとうございました。

    返信削除
  3. 大変便利なマクロのご提供ありがとうございます。

    長い間会社のメールで愛用させていただいて参りましたが、先日Office2013からOffice365に変更させられて、同様にインストールして利用しようとしたら、エディタでメール文が開いたあとにSaveMailInfo()の最終行で、「実行時エラー'5':プロシージャの呼び出し、または引数が不正です」となりました。

    # この行をコメントアウトするとエラーは回避できるものの、エディタで編集したものがOutlookのメールエディタに渡りませんでした。

    この関数内で利用している変数の値を確認すると、InfoのItem 1~3には文字列"procHandle","filename","mailItem"が設定され、MailInfoの中の「RetentionPolicyName」だけがと表示されている以外は、それっぽい値が設定されていました。

    ExternalEditorを引き続き利用させていただきたいのですが、VBAに疎いため、何かヒントとなる改修方法をご教示頂けましたら幸甚です。

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

    返信削除
  4. 五月雨となり失礼いたします。

    以下のようなQ&AをStackOverflowで見つけました。

    Office365のアップグレード以降VBAでMailItem.Sendが機能しない
    https://stackoverflow.com/questions/50369434/mailitem-send-in-vba-not-functioning-since-office-365-upgrade

    もしかして、Regeditで「\HKEY_CURRENT_USER\Software\Policies\Microsoft\Office\16.0\Outlook\Security」キーを追加して、何らかのDWORD値を設定する必要が生じていますでしょうか?

    Outlook2007の電子メールセキュリティ設定に関する管理者向けの情報
    https://docs.microsoft.com/en-za/outlook/troubleshoot/security/information-about-email-security-settings

    返信削除
  5. 自己レスです。

    上記解決方法を見つけましたので記載しておきます。

    https://teratail.com/questions/236493

    修正前: gMailInfo.Add procHandle, info
    修正後: gMailInfo.Add CStr(procHandle), info

    返信削除
  6. はじめまして。vimユーザです。
    このマクロ、外国の方が出している類似品よりかなり使いやすくて感動しました。


    一点だけ、LoadTempFileToMail関数の最終行の
     mailItem.body=body
    の部分が、htmlの書式を破壊してしまうのをどうにかしたいと思いましたので、次のように置き替えました。ご参考までに共有させていただきます。
     修正前:mailItem.body=body
     修正後:putAsWordEditor mailItem.GetInspector, body


    ※putAsWordEditor関数の中身
    Private Sub putAsWordEditor(ins As Object, body As String)
    'htmlを崩さずにテキストを貼り付ける。
    'mailItemのbodyを直接書き換えるのではなく、outlookのeditorに編集を任せる。
    'outlookのエディタオブジェクトを呼び出す。
    Dim objDoc As Object
    Set objDoc = ins.WordEditor
    '「Ctrl+a → backspace → ctrl+home で 全選択削除→貼り付け→行頭移動」 と同等の操作を実行
    With objDoc.Application.Selection
    .WholeStory
    .Delete Unit:=1, Count:=1
    .TypeText body
    .HomeKey Unit:=6
    End With
    End Sub

    返信削除