Excel VBA GetAttr関数とビット演算

Excel マクロ、VBA

スポンサーリンク

Excel VBA 空のフォルダを一括削除するマクロ

2020年4月25日

前回の記事の中で、Excel VBAでファイルやフォルダの属性を取得するGetAttrという関数を扱った。

今回は、このGetAttr関数と、そこで使うビット演算というものについて書いてみる。

頻繁に使うものではないし、ライトVBAユーザーが無理に押さえる必要もないと思うけどね。

GetAttr関数が返す結果

GetAttr関数は、

GetAttr( “D:\ダウンロード” )

のように、括弧の中に文字列を入れて使う。

その結果は数値を返すのだけど、それがどれも2のべき乗になっており、下記のようになる(正確には、Macのみ64もあるけど)。

定数 内容 2のべき乗
vbNormal 0 通常ファイル 0
vbReadOnly 1 読み取り専用ファイル 20
vbHidden 2 隠しファイル 21
vbSystem 4 システムファイル 22
vbDirectory 16 フォルダ 24
vbArchive 32 アーカイブ 25

組み合わせ属性の返り値

で、ファイルやフォルダの属性というものは、「読み取り専用ファイルでもあるし隠しファイルでもある」とかいう組み合わせ属性がありえる。

たとえば
C:\Program Files\Uninstall Information
というのは隠し属性のフォルダだけど、

GetAttr(“C:\Program Files\Uninstall Information”)

とすると、答えは18を返す。
これはフォルダ(=vbDirectory=16)であり且つ隠し(=vbHidden=2)だから、16+2=18ということだ。

ファイルについても、33などの結果を返すことがあり、それを↓にソースコードとして書いてみた。

属性をビット演算で調べる

単一属性の確認

では、複数の属性を持つかもしれないファイル・フォルダについて

  • これは(フォルダではなく)ファイルなのか
  • このファイルは読み取り専用なのか

といった、特定の属性だけGetAttr関数で調べれば良い場合はどうするか。

その場合、ビット演算という特殊な考え方を用いて、またAnd演算子を通常とは異なる使い方をして、調べることになる。

普通、VBAのAnd演算子は
If num > 1 And num < 6 Then
のような感じで書いて、「num > 1 かつ num < 6」という条件を示すように用いる。

しかしGetAttr関数でビット演算を用いる場合、このAnd演算子の使い方では駄目だ。
つまり

If GetAttr(str) And vbReadOnly = vbReadOnly Then

のような書き方では駄目で、

If (GetAttr(str) And vbReadOnly) = vbReadOnly Then

というように、特殊な位置に() を付けなければビット演算にならず、不適切な結果を返してしまう。

どういう結果を示すかというのを、次のソースコードに、コメントを中心にして示す。

複数組み合わせ属性の確認

「読み取り専用で、尚且つ隠しファイルである」というように組み合わせ条件の真偽を調べたい場合は、
vbReadOnly + vbHidden
のように+演算子を付けて確認すれば良い。

サンプルのソースコードは次のような感じ。

ビット演算について、ちょっと詳しく

今回取り上げたビット演算について、ちょっと突っ込んだ説明を書いてみる。
結構マニアックな内容だと思うし、一般ユーザは読み飛ばせば良いだろう。

私も、正確に書ききれる自信はあまりない。

ではGetAttr関数の返り値について、再掲。

定数 内容 2のべき乗
vbNormal 0 通常ファイル 0
vbReadOnly 1 読み取り専用ファイル 20
vbHidden 2 隠しファイル 21
vbSystem 4 システムファイル 22
vbDirectory 16 フォルダ 24
vbArchive 32 アーカイブ 25

「読み取り専用で、尚且つ隠しファイルであるファイル」を例にすると、その返り値は

vbArchive + vbReadOnly + vbHidden

となるが、これは

25 + 21 + 20

ともなるし、また

25×1 + 24×0 + 23×0 + 22×0 + 21×1 + 20×1

ともなる。

そして、単なる通常のファイルは

vbArchive =

25×1 + 24×0 + 23×0 + 22×0 + 21×0 + 20×0

となる。
この両者の、1 を掛けられる「2のべき乗」が、重なる部分を調べると次のようになる。2進法とかいうやつだけど。

2のべき乗 25 24 23 22 21 20
読み取り専用・隠しファイル 1 0 0 0 1 1
通常のファイルvbArchive  1 0 0 0 0 0
1が重なった部分を1に 1 0 0 0 0 0

重なる部分は、25=vbArchive の1箇所のみとなるわけだが、これを先述のAnd演算子を用いたビット演算に当てはめると次のようになる。

読み取り専用・隠しファイルという属性が付随していても、このコードではvbArchive =25の重なる部分を問題にしているだけなので、結果もvbArchiveが返ることになる。

・・・と、書いてみたけど、恐らく多くの方はこんなの読んでもチンプンカンプンだろう。
私自身、書いてて頭が痛くなるばかりで、これ以上に分かりやすい書き方もできなくて、自分が理解できているのかも自信が無くなるばかりだ。

あまり深入りせず、GetAttrとAnd演算子をちょっと特別な組み合わせで使う方法で、ファイルやフォルダの属性を調べられるのだということだけ頭の片隅に入れておけば良いだろう。

スポンサーリンク