スポンサーリンク
前回の記事の中で、Excel VBAでファイルやフォルダの属性を取得するGetAttrという関数を扱った。
今回は、このGetAttr関数と、そこで使うビット演算というものについて書いてみる。
頻繁に使うものではないし、ライトVBAユーザーが無理に押さえる必要もないと思うけどね。
GetAttr関数が返す結果
GetAttr関数は、
のように、括弧の中に文字列を入れて使う。
その結果は数値を返すのだけど、それがどれも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などの結果を返すことがあり、それを↓にソースコードとして書いてみた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
'フォルダなのでvbDirectory=16を返す Debug.Print GetAttr("D:\ダウンロード") '普通のファイルは、結果32(=vbArchive) Debug.Print GetAttr("D:\ダウンロード\普通のファイル.xlsx") '読み取り専用ファイルは、結果33 '(=32 + 1) '(=vbArchive + vbReadOnly) Debug.Print GetAttr("D:\ダウンロード\読み取り専用.xlsx") '隠しファイルは、結果34 '(=32 + 2) '(=vbArchive + vbHidden) Debug.Print GetAttr("D:\ダウンロード\隠しファイル.xlsx") '読み取り専用であり、隠し専用ファイルでもあるなら、結果35 '(=32 + 1 + 2) '(=vbArchive + vbReadOnly + vbHidden) Debug.Print GetAttr("D:\ダウンロード\読み取り専用・隠しファイル.xlsx") |
属性をビット演算で調べる
単一属性の確認
では、複数の属性を持つかもしれないファイル・フォルダについて
- これは(フォルダではなく)ファイルなのか
- このファイルは読み取り専用なのか
といった、特定の属性だけGetAttr関数で調べれば良い場合はどうするか。
その場合、ビット演算という特殊な考え方を用いて、またAnd演算子を通常とは異なる使い方をして、調べることになる。
普通、VBAのAnd演算子は
If num > 1 And num < 6 Then
のような感じで書いて、「num > 1 かつ num < 6」という条件を示すように用いる。
しかしGetAttr関数でビット演算を用いる場合、このAnd演算子の使い方では駄目だ。
つまり
のような書き方では駄目で、
というように、特殊な位置に() を付けなければビット演算にならず、不適切な結果を返してしまう。
どういう結果を示すかというのを、次のソースコードに、コメントを中心にして示す。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Dim str As String str = "D:\ダウンロード\普通のファイル.xlsx" 'GetAttr関数の結果は「読み取り専用ではありません」を返したい。 'GetAttr関数の前に括弧を付けずに、Andを使った場合 '結果は「読み取り専用です」を返してしまい不適切。 'これはAndが、通常と同じく「尚且つ」の用法で使われているから。 If GetAttr(str) And vbReadOnly = vbReadOnly Then Debug.Print "読み取り専用です" Else Debug.Print "読み取り専用ではありません" End If 'GetAttr関数の前に括弧を付けて、Andを使った場合 '結果は「読み取り専用ではありません」を返し、適切。 'これはAndが、通常と同じく「尚且つ」の用法で使われているから。 If (GetAttr(str) And vbReadOnly) = vbReadOnly Then Debug.Print "読み取り専用です" Else Debug.Print "読み取り専用ではありません" End If |
複数組み合わせ属性の確認
「読み取り専用で、尚且つ隠しファイルである」というように組み合わせ条件の真偽を調べたい場合は、
vbReadOnly + vbHidden
のように+演算子を付けて確認すれば良い。
サンプルのソースコードは次のような感じ。
1 2 3 4 5 6 7 8 9 10 |
'読み取り専用(vbReadOnly)かつ隠しファイル(vbHidden)の場合 Dim str As String str = "D:\ダウンロード\読み取り専用・隠しファイル.xlsx" If (GetAttr(str) And (vbReadOnly + vbHidden)) = (vbReadOnly + vbHidden) Then '結果はこちらが返る。 Debug.Print "読み取り専用かつ隠しファイルです" Else Debug.Print "・・・" End If |
ビット演算について、ちょっと詳しく
今回取り上げたビット演算について、ちょっと突っ込んだ説明を書いてみる。
結構マニアックな内容だと思うし、一般ユーザは読み飛ばせば良いだろう。
私も、正確に書ききれる自信はあまりない。
では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
ともなるし、また
ともなる。
そして、単なる通常のファイルは
vbArchive =
となる。
この両者の、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演算子を用いたビット演算に当てはめると次のようになる。
1 2 3 4 5 6 7 8 9 |
Dim str As String str = "D:\ダウンロード\読み取り専用・隠しファイル.xlsx" If (GetAttr(str) And vbArchive) = vbArchive Then '結果はこちらが返る。 Debug.Print "通常のファイルです" Else Debug.Print "・・・" End If |
読み取り専用・隠しファイルという属性が付随していても、このコードではvbArchive =25の重なる部分を問題にしているだけなので、結果もvbArchiveが返ることになる。
・・・と、書いてみたけど、恐らく多くの方はこんなの読んでもチンプンカンプンだろう。
私自身、書いてて頭が痛くなるばかりで、これ以上に分かりやすい書き方もできなくて、自分が理解できているのかも自信が無くなるばかりだ。
あまり深入りせず、GetAttrとAnd演算子をちょっと特別な組み合わせで使う方法で、ファイルやフォルダの属性を調べられるのだということだけ頭の片隅に入れておけば良いだろう。
スポンサーリンク