40過ぎてやっとVBAを使い始めた素人の備忘録です。
VBAをやっていると避けては通れないのは「分岐」ですよね。
今回はおじさんがやっと「Case」の使い方がわかったというお話です。
Contents
分岐には「If」と「Case」があるけど…。
分岐といえば誰しも最初に学ぶのは「If」だと思います。
しかしIfだと常に2択をして進めるので、処理が増えてくるとやたらと「ElseIf」が多くなったり入れ子が増えたりします。
そうなると書いたコードが非常に読みにくくなってしまいますよね。
というわけでいっぺんに処理できると噂の「Case」を使うことを考えるようになります。
しかしこの「Case」、書いてみたはいいけど全然思うように動かないことが多すぎませんか?
私の場合はどうにもうまく動かすことができずCaseを諦め、逃げて逃げて数年間読みにくいIFでやりくりしてきました。
「Case」について調べると最初に陥る罠。
コードの読みにくさに限界を感じたおじさん、意を決してCaseについて調べてみることにしました。
すると大抵の場合最初に出てくるのはこんなコードです。
Select Case 変数
Case 1
処理1
Case 2
処理2
Case 3
処理3
End Select
これを見ると「なるほどこれは確かにElseIfを使っていちいち書くよりも簡単」と思って実際に使おうとするとどうにもうまく動かないんですよね。
それもそのはず、この形だと応用が効かなさすぎてちょっと変わったことをやろうとするとエラーで止まるか何もせずにスルーして終わります。
具体的には「”~を含む”の処理ができない」のが一番のネックですね。
変数と完全一致する場合の分岐だけが必要なわけではないので結局「これは使えん。何だこのゴミ!」とブチギレてCaseを諦めてしまうのです。
スポンサーリンク
何とかして使いたいので色々調べてみた。
この問題に当たったとき、何とかならんものかとCaseについて基礎から調べてみたところなとなくCaseの概念がわかってきました。
Select Case A
Case B
処理B
Case C
処理C
End Select
上記のような構文があった場合、Aの部分は必ずしも変数にする必要はないようです。
どうやらCase文の基本は、「”Select Case”に続くものが、その後に出てくる”Case”の後に続くものと一致した場合にその処理を行う」に過ぎないということのようですね。
そうなってくると「Case文で”~を含む”場合の処理ができない」という問題の中身が見えてきます。
例えば、
Dim H As String
'午前指定はA1セルに「0812」を記載
H = "午前中"
Select Case H
Case Like "*午前*"
Range("A1") = "'0812"
End Select
これでは「Like」の主語(?)が抜け落ちているため、書いている時点で構文エラーの警告が出ます。
下記だとどうでしょうか?
Dim H As String
'午前指定はA1セルに「0812」を記載
H = "午前中"
Select Case H
Case H Like "*午前*"
Range("A1") = "'0812"
End Select
変数である「H」が重複している違和感があるにせよ、構文エラーもなくパッと見は動いてくれそうな気もしますよね?
しかしこれだとマクロを走らせても特に何もすることなく終了してしまいます。
というのも、最初の「Select Case」に続く「H」は「午前中」という文字列ですが、次のCaseに続く節である「H Like “*午前*”」は”True”か”False”を返す構文です。
つまり、その結果である「True」が「H」の中身である「午前中」との比較対象になるからなんです。
人間の感覚では同じように感じてしまいますが、VBA的には全くの別物として認識されますので後の処理は行ってくれません。
ではどうすれば同じものと認識されるかというと答えはシンプルで、「Select Case」の後を変数「H」ではなく「True」に変えてやればいいんですね。
Dim H As String
'午前指定はA1セルに「0812」を記載
H = "午前中"
Select Case True
Case H Like "*午前*"
Range("A1") = "'0812"
End Select
これでちゃんと結果が出力されます。
パターンが増えた場合はどうでしょうか?
Dim H As String
'時間指定に応じた4桁数字をA1セルに記入
H = "AM必着"
Select Case True
Case H Like "*午前*", H Like "*AM*"
Range("A1") = "'0812"
Case H Like "*14*16*"
Range("A1") = "'1416"
Case H Like "*16*18*"
Range("A1") = "'1618"
Case H Like "*18*20*"
Range("A1") = "'1820"
Case H Like "*19*21*"
Range("A1") = "'1921"
End Select
大丈夫そうです。
午前中以外も試してみましたが問題なく出力してくれました。
1つ気をつけなければいけないことは、カンマを使ってOr条件を追加する場合は条件を最初から記述しなければいけないということです。
Case H Like "*午前*", "*AM*"
みたいな書き方だと後に書いた方は「*AM*」そのものが比較対象となってしまい、Trueを返さないのでご注意下さい。
これで完璧!と浮かれたおじさんが気づいた現実。
これでうまいことCase文が動いてくれたのでめでたしめでたしとなったわけですが、その直後おじさんはあることに気がついてしまいます。
Dim H As String
'時間指定に応じた4桁数字をA1セルに記入
H = "AM必着"
If H Like "*午前*" Or H Like "*AM*" Then
Range("A1") = "'0812"
ElseIf H Like "*14*16*" Then
Range("A1") = "'1416"
ElseIf H Like "*16*18*" Then
Range("A1") = "'1618"
ElseIf H Like "*18*20*" Then
Range("A1") = "'1820"
ElseIf H Like "*19*21*" Then
Range("A1") = "'1921"
End If
これは上に書いたCase文をIf分に変えてみたものです。
構成もほとんど一緒です。う~ん。
Caseの使い方を覚えて浮かれていた直後でしたが、Caseに過大な期待を寄せてもしょうがないんだなと感じた次第でございますよ。
スポンサーリンク
Case文についての素人視点まとめ。
- Case文での「~を含む」という条件設定にはTrueを使う。
- そうなると「If、ElseIf」と構造的に変わりはなくなる。
- 使えるようにはなったけど劇的に何かが変わるわけではなさそう。
- Ifの入れ子になったときの視認性は少し上がりそう?
- Thenを打ち込まなくていいのは少し楽?
私の中でのCaseに対する現時点での評価はこんな感じです。
これから先詳しくなっていけば評価は変わってくるかもしれません。
いずれにぜよ、Case文が動かなくて困っている人は、
「”Select Case”に続くものが、その後に出てくる”Case”の後に続くものと一致した場合にその処理を行う」
という原則を考えながら書いていけば動くようにはなると思います。
私と同じように「Case動かないじゃん!ゴミかよ!」と憤っていた方の一助になれば幸いでございますよ。
以上です!