ちょっとエンジニアらしいことを書いてみる。
VBAではExcelシート上の文字列を探すことがよくある。たとえば下のシートで、“Name”が“John”セルオブジェクトを取りたいとしよう。
方法はいろいろあると思うが、僕がVBAでよく使う方法は2種類。
1.Findメソッドを使用する。
2.WorksheetFunctionのMatch関数を使用する。
1はVBAに標準搭載されているFindメソッドを使用して、直接、対象のセルオブジェクトを取ってくる方法である。
2はExcelのセル関数を使用し、対象のセルが何番目にあるかを取得する方法だ。
僕は次のように書く。
細かいことはいろいろあるが、パッと見てわかることはFindを使う方が簡潔に書ける。それはFindメソッドが対象セルオブジェクトを直接取ってこれるからだ。一方Match関数はRangeオブジェクトの何番目に該当セルがあるかというインデックスを取得する。したがって、後からセルの移動を行う必要がある。
一見すると、Findを使用した方が良い気がするが、もちろん欠点もある。今回のシートでは“Emi”を探す時だ。Findメソッドはwhatの引数に渡した文字列を検索するが、環境によっては“Emiri”を取ってきてしまう場合がある。これは省略した引数のLookAtがxlPartになっているときだ。LookAtはFindメソッドのxlPart(部分一致)、xlWhole(完全一致)を指定することができるが、省略してもよい。しかし省略したとき、使われる引数は前回使用した引数になる(らしい)。これはかなり重要である。これを避けるためには毎回、引数を指定しないといけないが、正直めんどくさい。この部分だけは部分一致で、こちらの部分は完全一致にしようとすると、別の部分で使っていた引数を指定しなかった部分がどちらの検索をするか不明になる。怖い怖い…。
Match関数は3つ目の引数を0にすると完全一致になる。これは絶対に使わなければいけない引数である(ちなみに0以外は1:検査値以下の最大値、-1:検査値以上の最小値)。したがってこちらの方が安心して使うことができる。しかし、上記のとおりこちらは、渡す引数が面倒であり、直接セルオブジェクトを参照できない。
やはりどちらの方法も一長一短である。
僕は検索範囲が狭い時や検査値が明らかに1つしか指さないときにFindメソッドを使用して、同じ系列が並んでいる場合(今回のName列)はMatch関数を使用している。
この問題はVBAを使い始めた当初、悩まされた問題だ。これからVBAを使い始める人もきっと同じ問題を抱えると思うので、参考にしてもらえたら幸いである。
後記
新しい関数やメソッドを使用するとき、このようなブログや解説サイトを参考にさせてもらっているが、思っていたよりすごいと感じた。今回取り上げたFindとMatchはVBAを使っている人ならだれでも知っているような簡単なことだが、いざ文章で説明しようと思うと難しい。僕は学生時代の経験から教えることは得意だと思っていたが、改めてその難しさを感じた。読みやすい文章、わかりやすい文章はきっと役に立つので、書くことにも重きをおきたいと思う。