Dir関数の注意点


Dir関数は、引数に指定したファイルが存在するときファイル名を返し、存在しないときは空欄を返す関数です。たとえば次のように使います。

Sub Sample1()
    Dim buf As String
    buf = Dir("C:\Work\Sample.txt")
    If buf = "" Then
        MsgBox "存在しません"
    Else
        MsgBox "存在します"
    End If
End Sub

上記のコードは、C:\Work\Sample.txtが存在するかどうかを調べます。また、Dir関数の引数にはワイルドカードを使えます。次のコードは、C:\Workフォルダに存在するすべての「.txt」ファイルを調べます。

Sub Sample2()
    Dim buf As String, msg As String
    buf = Dir("C:\Work\*.txt")
    Do While buf <> ""
        msg = msg & buf & vbCrLf
        buf = Dir()
    Loop
    MsgBox msg
End Sub

それほど使い方も難しくなく、どちらかと言えば基本的な関数に分類されるDir関数ですが、思わぬ特徴があります。それは、3文字の拡張子が前方一致で判定されるということです。実際に試してみましょう。次のコードは、C:\Workフォルダに「123.htm」と「1234.html」の2つのファイルを作成します。

Sub Sample3()
    Open "C:\Work\123.htm" For Append As #1
        Print #1, Now
    Close #1
    Open "C:\Work\1234.html" For Append As #1
        Print #1, Now
    Close #1
End Sub

拡張子が「htm」と「html」のように異なっている点に留意してください。さて、この状態で次のコードを実行するとどうなるでしょう。Dir関数の引数に指定するのは「*.htm」です。

Sub Sample4()
    Dim buf As String, msg As String
    buf = Dir("C:\Work\*.htm")
    Do While buf <> ""
        msg = msg & buf & vbCrLf
        buf = Dir()
    Loop
    MsgBox msg
End Sub

この現象は、Dir関数の引数に3文字の拡張子を指定したときに発生します。

存在するファイル Dir("*.htm") Dir("*.ht") Dir("*.html")
123.htm 該当する 該当しない 該当しない
123.html 該当する 該当しない 該当する
123.htmlxxx 該当する 該当しない 該当しない

もちろん、「htm」と「html」といったよく使われる拡張子だからというわけではありません。「xyz」と「xyzz」といった意味のない拡張子でも発生します。この現象に気をつけなければならないのは、Excel 2007が発売された後です。ご存じのようにExcel 2007では標準のファイル形式がXMLに変更され、拡張子が「xlsx」や「xlsm」と4文字になります。Excel 2003以前に作成した「xls」もExcel 2007で読み込めることから、発売以降はハードディスク内に「xls」と「xlsx」のブックが混在すると予想されます。旧形式のブックだけを操作したいとき Dir("*.xls") のように指定すると Dir("*.xls*") と同じ意味になり、Dir関数は「xlsx」や「xlsm」も返してきます。

もう少し詳しい話をしましょう。

この現象はVBAの不具合ではありません。試しにDOS窓で「dir *.htm」を実行すると、同じように拡張子「html」のファイルも表示されます。

これはWindows NTからの仕様で、3文字より長い拡張子では、先頭の3文字を拡張子と認識します。一般的にはDOS窓のコマンドラインで問題になりますが、このようにVBAのDir関数でも影響が出ます。

Windowsの設定を変更して、4文字以上の拡張子を3文字に切りつめないようにするには、次のようにレジストリを変更します。

レジストリの変更は十分に注意して行ってください。
できればバックアップを取ってから編集することをお勧めします。
レジストリをバックアップする方法がわからない人は、レジストリを編集しない方がいいでしょう。
  1. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem を開きます
  2. Win95TruncatedExtensions の値を 0 に変更します(標準は 1 です)
  3. Windowsを再起動します

これで4文字以上の拡張子が3文字に切りつめられなくなります。ただし、切りつめられなくなるのはレジストリを変更した後に作成したファイルです。レジストリを変更する前に作成したファイルは、レジストリを変更した後でも拡張子が3文字に切りつめられます。

上記Sub Sample3()で作成した「123.htm」と「1234.html」を削除してから、再度Sub Sample3()を実行します。今度はDOS窓のdirと、Sub Sample4()は次のように拡張子「htm」のファイルだけを返します。