新・闘わないプログラマ No.393

UNC


久しぶりにExcelのマクロを使って簡単なプログラムをつくることになりました。マクロを動かしたら、「ファイルを開く」ダイアログボックスを表示してExcelのブックを選択させて、でもってそれを開いて、ちょっとした集計をおこなって印刷する、という簡単なものです。
まあ、Excelじゃなくても集計までは何でやってもよかったのですが、最終的な印刷物の整形をやるのに、ExcelならどのPCにも入っているしそれが一番楽かな、と思いExcelを選択したわけです。ユーザは「あまりややこしいことはやりたくない」とのことだったので、マクロの入っているファイルを開いて、あとは集計対象のファイルを選択すれば印刷まで自動的にやってくれるようにしようか、ということで作り始めました。

集計から印刷までは、Excelにある「マクロ記録」の機能を駆使して、それで出来たマクロに手を入れてやれば、ほとんど問題もなくあっという間にできてしまいました。まあ、各PCやユーザによって異なっているであろうExcelの初期設定、たとえばデフォルトのフォント名やサイズといったものに依存しないようにするところがちょっとばかり厄介でしたが、それもなんとかこなして集計以降の部分は数時間で出来上がったのですが……。
問題は「ファイルを開く」の部分です。あのダイアログボックスはどうやって表示するんだろうか、といろいろ調べてみたところ、ApplicationオブジェクトのGetOpenFilenameメソッドを使えばいいらしいことが判明しました。これでファイル名を取得して、Openメソッドでブックを開けばいいようです。さっそく次のようなコードを書いて試してみました。

    fn = Application.GetOpenFilename
    Workbooks.Open Filename:=fn

ダイアログボックスに目的の拡張子のファイルだけを表示するために引数を書いたり、あとはエラーのハンドリングをしたり、とか細かいことは後回しにすれば、とりあえずこれで動きます。でも、最初に表示するディレクトリはどうやって決めればいいのでしょうか。今回のマクロは、ある特定のディレクトリ決めうちで、そこにあるファイルを開きたいのですが、GetOpenFilenameメソッドには、最初に開くディレクトリを決めるような引数は見当たりません。
こういう場合には、たぶんカレントドライブとカレントディレクトリを変更すればいいんだろう、ということで、以下のようにしてみました。

    ChDrive "D:"
    ChDir "D:\data"
    fn = Application.GetOpenFilename
    Workbooks.Open Filename:=fn

やはりそうで、これでうまく行きました。どのディレクトリを開くか、というのは初期設定でマクロを入れるブックのシート内に置くことにしました。そこを書き換えれば別のところが最初に開くような感じです。
という感じでマクロをでっちあげて、ユーザに使ってもらうことにしたのですが……ここで問題が発生。最初に開くディレクトリはファイルサーバにしたい、という要望が出たのです。まあ、それもそうで、集計元のデータはサーバで作っているので、そこに置いてあるのは自然なのですね。
さて、Windowsのファイルサーバに対するアクセスは、通常次のような形でやります。

  1. サーバの共有名に対してローカルのドライブ名を割り当てる。
  2. サーバ名と共有名からなるUNCを使い直接アクセスする。

UNC(Universal Naming Convention)というのは、“\\server1\share2\data3”のようもので、サーバ(server1)の共有名(share2)のディレクトリ(data3)の……というのを表記したパス名のことです。
ユーザによってドライブの割り当ては異なっているので、今回作ったマクロでは1番目の方法は取れません。必然的に2番目の方法になります。そこで、UNCで記述されているパスで「ファイルを開く」ダイアログボックスを表示するように、マクロのほうを変更しようとしました。しかし……UNCには「カレントドライブ」という概念がありません。ということはたぶん、chdriveはしないでchdirだけすればいいんだろう、と勝手に判断して、

    ChDir "\\server1\share2\data3"
    fn = Application.GetOpenFilename
    Workbooks.Open Filename:=fn

と、してみたのですが、うまく行きません。カレントドライブがもとのままなので、そのカレントドライブのカレントディレクトリが開いてしまいます。ううむ。そもそも、はるか昔のDOSのころからの慣わしで、

というやっかいな仕様が、UNCのような「ドライブ」という概念の無いパス名と相容れないわけですね。UNIXのようなすっきりした考え方だったらよかったのですが。結局のところどうすればいいのか、いろいろと調べてみたところ、カレントディレクトリをUNCのパスにしてGetOpenFilenameを使う、という方法は不可能らしい、という結論に達しました。APIを使うとか、もっと面倒な方法をとればなんとかできなくはないようですが、そこまで時間をかけてまで作るような仕事でもありません。しかし、なんでこんなありがちなことが簡単にできないんでしょう。
仕方が無いので、マクロの中で共有名に対してドライブを割り当てて、それからファイルを開いて……最後にドライブ割り当てを解除する、という力技を用いることにしました。ううむ、なんかいまいち美しくないというか、非常に気に入らない手法なのですが、まあこんなんで何日もかけるわけにはいかない、ということで、はっきり言って手抜きです。でも、なんかくやしい。

[前へ] [次へ]

[Home] [戻る]


mailto:lepton@amy.hi-ho.ne.jp