ExcelのVBAのFindメソッドで困ったエラーが発生!

このエントリーをはてなブックマークに追加

ExcelのVBAでの話になります。

RangeオブジェクトのFindメソッドを使用し、指定された値を所持するセルの行位置を取得する処理を組み入れた業務APを開発される際の注意喚起になります。

実際の業務APの内容をお見せすることは出来ないため、デフォルメ化したサンプルAPで説明させていただきます。

※サンプルExcelファイルのダウンロードはこちらからどうぞ。

<サンプルAP仕様>
シート「Sheet1」上の表より、指定された値を所持するセルを探索しその行位置を結果としてメッセージ表示する。

先ずは、シート「Sheet1」の内容になります。
excel_01_00_data

 

そして、当初開発時のソースコード(VBAマクロ)

Sub 一見問題のないように見える書き方()

 Dim l_Row As Long   '探し物の行位置

 With Sheets("Sheet1")

  '■探索範囲に存在する"くじら"を探索
  l_Row = .Range("A:A").Find("くじら").Row

  MsgBox "探し物の行は[" & Format(l_Row, "#,##0") & "]です。"

 End With

End Sub

 

これを実行すると正常に処理されます。
excel_01_01_ok1

 

しかし、下記のソースコードのように探索値を変更してみたところ・・・

Sub 問題が発生します()

 Dim l_Row As Long   '探し物の行位置
 
 With Sheets("Sheet1")

  '■探索範囲に存在しない"ことり"を探索
  l_Row = .Range("A:A").Find("ことり").Row

  MsgBox "探し物の行は[" & Format(l_Row, "#,##0") & "]です。"

 End With

End Sub

 

Findメソッドの実行行で、このように結果がエラーとなります。
excel_01_02_ng1

しかも、withブロック変数の設定が原因とのこと・・・・

見てのとおりwithブロックの書き方に間違いは見られない。

しかし、エラーはwithブロック変数・・・これは困りました。

 

諸々の情報収集と検証をしたところ、原因は本当につまらないことでした。

Findメソッドで条件該当するセルを探索することが出来ないにも関わらず、Rowプロパティを要求したため「Rowプロパティを返したいけど対象のセルがありませんよ!」というエラーだったようです。

つまり、下記のソースコードのようにオブジェクトとメソッドとプロパティの3連続ピリオド結合を止めて、正しく途中経過を判定すれば良いだけだったのです。

Sub 皆様このように書きましょう()

 Dim l_Range As Range   '探し物の結果セル

 With Sheets("Sheet1")

  '■探索範囲に存在しない"ことり"を探索
  Set l_Range = .Range("A:A").Find("ことり")

  '■探索結果を判定する。
  If (Not l_Range Is Nothing) Then
   MsgBox "探し物の行は[" & Format(l_Range.Row, "#,##0") & "]です。"
  Else
   MsgBox "探し物はありませんでした。"
  End If

 End With

End Sub

 

その結果は、このとおり正常に表示されました。
excel_01_03_ok2

 

ExcelのVBAコードを記述する場合、このようにオブジェクト.メソッド.プロパティのように連続したピリオドで結合し、ソースコードの記述を楽したいと思う心情は私も理解します。

しかし、お客様へ納品する業務APとしてVBAコードを記述する際は、このような楽をすべきではありません

今回の記事では、Findメソッドを例として記載しましたが、Findメソッド以外の他のメソッドの場合も考え方は同じです。

 

今回は、このFindメソッドの原因を究明するために、本来なら出さなくてもよいあぶら汗を約1時間も出しながら苦戦することになりました。

「作れば良い」「動けば良い」ではダメなのです。

「保守しやすいか?」「エラーが発生した場合、原因究明しやすいか?」を念頭に置いて、プログラマ諸君にはVBAコードを書いていただきたいものです。

 

(検索キーワード)
オブジェクト変数または With ブロック変数が設定されていません。