2011年10月13日木曜日

64ビット版OfficeでURLエンコード処理ができない?に対する返信3

一応、最終回です。
前々回では既存手法のまとめを、前回はその改変を試みました。
今回はさらに一歩進んで、ワンライナーに挑戦してみます。

ここまで、64bit 版 Office ユーザーは URL エンコードのために JScript スクリプトエンジンをいかに叩けばよいか、という方向で何となくお送りしてきました。しかし、おそらくこの方向性の延長線上には、必ず浮かぶであろう疑問が待ち構えています。

URL エンコードを提供しているライブラリって、JScript だけじゃないし、Windows のスクリプトって、WSH だけじゃないよね?

ですよねー。
というわけで、そろそろ .NET Framework と Windows PowerShell に行きましょうか。

今回のお題は、64bit 版 Office (今のところ Office 2010 のみ) が前提です。ということは、かなりの確率で .NET Framework と Windows PowerShell を使える環境であることが期待できます。
Microsoft Office 2010 のシステム要件を見ると Windows XP SP3 以降となっていますが、Win XP には 32bit のみとの但し書きが付いていますから、64bit に関しては実質 Vista 以降ということになります。Vista だと PowerShell が入っていない環境もあるかもしれませんが、Windows 7 になるともう OS 標準搭載ですから、使用に当たっての問題は無くなります。
とりあえず、今回は PowerShell が使える環境を前提として、話を進めます。

というわけで、コードです。

Option Explicit

Public Sub Sample()
  MsgBox EncodeURLx64("東京都千代田区")
End Sub

Public Function EncodeURLx64(ByRef str As String) As String
    Dim cmd As String

    cmd = "powershell.exe -Command ""[Uri]::EscapeUriString('" & str & "')"""
    EncodeURLx64 = CreateObject("WScript.Shell").Exec(cmd).StdOut.ReadLine
End Function

PowerShell 経由で .NET Framework Uri クラスの Uri.EscapeUriString メソッドを呼んでいます。[System.Web.HttpUtility]::UrlEncode とかでもいいかもしれません。私は PowerShell も .NET もよく知らないので、この辺 適当です。

見てお分かりのように、可読性のためコマンド文字列を変数に外出ししているので数行ありますが、実行は Exec 一発なのでワンライナー可です。

64bit Office を所有していないため、検証は VBS でやります。
以下、VBS 用の検証コードとその結果です。

MsgBox EncodeURLx64("東京都千代田区")

Function EncodeURLx64(str)
    Dim cmd

    cmd = "powershell.exe -Command ""[Uri]::EscapeUriString('" & str & "')"""
    EncodeURLx64 = CreateObject("WScript.Shell").Exec(cmd).StdOut.ReadLine
End Function


残念ながら、PowerShell のコンソール画面が一瞬表示されます。PowerShell 2.0 には WindowStyle 引数が追加されたのですが、Hidden を指定しても一瞬は見えてしまうようです (ので、指定を外しました)。あと大雑把な体感ですが、PowerShell~.NET Framework の呼び出しは WSH~JScript よりも明らかに遅く感じました。
もちろん利点もあります。VBA から .NET Framework の豊富な機能に簡易的にアクセスできること、そして PowerShell がコマンド文字列を受け取れるので スクリプトファイルを出力しなくても済む点などは、嬉しい特徴だと思います。

お約束ですが、コードはあくまで実験用です。エラーハンドリングや、引用符のエスケープなど、プロダクトなら当然必要な処理を割愛しておりますので、ご注意ください。

というわけで、自分が持ってもいない 64bit 版 Office のためのネタを、三回に渡ってお送りしてしまいましたが、いかがでしたでしょうか。
他にもいろいろなアプローチがあると思います。自分の用途に合わせた工夫をしたら、ぜひあなたも URL エンコード部門にエントリしてみてください!

4 件のコメント:

  1. Uri.EscapeUriString メソッド(でなくてもいいんですけど)を、PowerShellを介さずにVBAから呼べないだろうか(●゚ェ゚)

    返信削除
  2. 諦めた凹○コテッ
    UriクラスがあるSystem.dllには参照設定できないし、System.tlbにはなぜかUriクラスがないし。HttpServerUtilityクラス(System.Web.dll)も同様。

    返信削除
  3. こんにちは。

    HPやブログを取り上げていただいたきぬあさです。

    アクセスログを辿ってくると、なんとYU-TANGさんのブログ。
    しかもこんなマイナー(?)な話題を取り上げていただいているとは!


    > 素直に考えると VBScript ファイルじゃなく JScript ファイルでいいんじゃないか。

    そういえばそうですね!(^^)
    すっかり失念していました。
    ブログの記事は随分回り道していたなぁ~(^^;

    > というわけで、そろそろ .NET Framework と Windows PowerShell に行きましょうか。

    これは素晴らしいですね!
    思いつきもしませんでした。
    応用範囲も広くて便利そうです。


    この話題で、自分一人ではここまで発想を広げることが出来ませんでしたので、こうしてYU-TANGさんに取り上げていただいてとても嬉しいです。
    極めつけはこれ↓

    "「URL エンコード処理ていどは、簡単なんだから自前で組めばいいじゃん」は禁句とします。あくまで外部ライブラリの褌を借りて、自分の手を汚さず (?) 処理させるのが江戸前の粋というもの。"

    たしかにこの程度の処理であれば「自分で組んじゃえばいいじゃん!」という話になるのですが(私も最初はそう思っていました)、そうせずに如何に自分で組まずに処理するか、というところに主眼を置いたのが私のHPやブログの記事ですので、同様の視点でYU-TANGさんが記事を書いてくださったのがとても嬉しく、とても楽しませていただきました(*^^*)


    正攻法ではなく、もしかしたら余計な回り道になるかもしれないけれども「あれ?こういう風に処理することもできるんだ!」的な話題、大好きです。



    #実は午前中にもコメントを書かせていただいたのですが、上手く投稿出来ていないようでした(T^T)
    #今回は上手く投稿できますように…。

    返信削除
  4. @きぬあささん
    Google スパムフィルタに引っかかっていました。失礼しました。ウチは読者少ないんで、そもそもスパムコメント付いたことは無いんですが、本物のコメントがスパム扱いされたのはこれで二度目です。つまり、誤検知しかしたことがないフィルタなんですけど、フィルタを無効にする方法が分からない(無い?)んです。引っ越そうかな…。

    返信削除