この特集のトップページへ
Chapter 7:プレゼンテーション層の構築

7.4.6 顧客の検索
●[検索]ボタンが押されたときの処理

○[検索]ボタンが押されたときの処理
 さて,これらを踏まえて,[検索]ボタンが押されたときの処理を実装する。Fig.7-37にも示したように,[検索]ボタンにはBTN_SEARCHという名前を設定してあるので,[検索]ボタンが押されたときのプロシージャはBTN_SEARCH_Clickプロシージャになる。実際にこの処理を実装したものが,List 7-34である。

 List 7-34はやや長いプログラムではあるが,さして難しい処理をしているわけではない。先頭から順に処理を説明してゆこう。

 まず,10行目〜14行目において,ユーザーがCOMBO_SEARCHFIELDコンボボックスにおいて何番目の項目を選択したのかを取得する。10行目にあるように,ユーザーが選択した項目はCOMBO_SEARCHFIELDコンボボックスのListIndexプロパティを使って取得できる。ListIndexプロパティの値が-1であれば,ユーザーはどの項目も選択していない。その場合には,11〜14行目にあるようにエラーメッセージを表示し,以降の処理は何もしないようにしてある。

 16〜20行目の部分は,ユーザーが選択した項目がDGrid_Customerデータグリッドが保持するADODB.Recordsetオブジェクトのどのフィールド名に相当するのかを調べている箇所である。先に,COMBO_SEARCHFIELDコンボボックスに列名を格納するときに,その列に対応するのが何番目のColumnオブジェクトであるかの番号をItemDataプロパティに格納しておいた(List 7-31Fig.7-38を参照)。そのため,17行目にあるようにCOMBO_SEARCHFIELDコンボボックスのItemDataプロパティを参照することで,ユーザーが選択した項目がDGrid_Customerデータグリッドの何番目のColumnオブジェクトに相当するのかを調べることができる。17行目では,この値をsearchfield変数に格納するようにしてある。18行目では,DGrid_Customerデータグリッドの第searchfield番目のColumnオブジェクトのDataFieldプロパティを取得することで,COMBO_SEARCHFIELDコンボボックスでユーザーが選択した列名に対応するフィールド名を取得している。これによって,たとえば,ユーザーが“顧客名”を選択したときには“NAME”,“顧客番号”を選択したときには“ID”といった具合に,列名に対応するフィールド名を示す文字列がfieldname変数に格納される。

 22〜29行目は検索方向を取得している箇所である。Fig.7-37で示したように,ユーザーはOPT_UPラジオボタンかOPT_Downラジオボタンのいずれかを選択することで,それぞれ上方向検索または下方向検索を選択できるようになっている。ここでは,ユーザーがOPT_UPラジオボタンを選択しているのであればorder変数にadSearchBackward(先頭方向に向かう検索)を,そうでなければadSearchForward(末尾方向に向かう検索)をそれぞれ格納するような処理にした。

 38〜75行目が,型の種類によって検索の方法を判別している箇所である。まず,38行目でフィールドのTypeプロパティを参照し,どのような型であるのかを調べる。これにより,文字列であれば39〜43行目の処理が,日付であれば44〜64行目の処理が,数値であれば65〜74行目の処理が,それぞれ実行される。

 値の型が文字列であったときの処理(39〜43行目)では,FindStr変数にlike演算子を使った検索条件を指定する。そして,値の型が日付であったときの処理(44〜64行目)では,値を#で括った検索条件を指定している。また,このとき,時刻が指定されていないときには,dataFlag変数の内容をTrueに設定するようにした。このdataFlag変数は後続の処理で使う。値の型が数値であったときの処理(65〜74行目)では,値を=演算子で指定するような検索条件をFindStr変数に格納している。

 83〜100行目が,実際にFindメソッドを使って検索する処理である。dataFlag変数の内容がFalseである場合には84〜91行目が,そうでない場合には93〜99行目が実行される。dataFlag変数の内容は,先の38〜75行目の処理において,値の型が日付で,かつユーザーが時刻を入力せずに日付のみしか入力しなかった場合にのみ,Trueとなるように設定している。すなわち,日付以外の場合には84〜91行目が,日付の場合には93〜99行目が実行されることになる。

 84〜91行目の処理は,単純なFindメソッドの呼び出しである。一方の93〜99行目の処理では,ループ処理によるFindメソッドの呼び出しになっている。すでに「○フィールドが日付の場合」で説明したように,日付を=演算子で検索してしまうと,時刻まで合致したものしか検索の対象にならないからである。そのためここでは,まず>=演算子を使ってその日付以上のレコードを検索し,その見つかったレコードのフィールドの値が翌日の午前0時よりも小さいことを確認することで,日付部分のみが一致するレコードを検索している。

 なお,81行目では,On Error Resume Nextステートメントを使い,実行時エラーがあってもそれを無視するように指定している。これは,ユーザーが入力した内容をそのままFindメソッドの引数に渡すとエラーが発生する可能性があるためである。たとえば,ユーザーが顧客名の列を検索しようとし,かつ,“ソフト'バンク”と入力したとしよう。このとき,Findメソッドの第1引数の内容は,次のようになる。

NAME like 'ソフト'バンク*'

 これでは,“'”の対応が正しくないため,Findメソッドは実行時エラーを発生する。つまり,文字列の閉じを示す“'”や日付の閉じを示す“#”など,Findメソッドの引数で特別な意味を持つ文字をユーザーが入力した場合,実行時エラーが発生するおそれがある。そこで,実行時エラーがあっても処理が停止しないように,On Error Resume Nextステートメントを使っているのである。


One Point! ただし,On Error Resume Nextステートメントでエラーを回避することは,一般にあまり好ましいものではない。本来ならば,ユーザーが入力した文字列に対してInStr関数などを使い,あらかじめ特殊な文字が含まれていないかどうかを調べたり,Replace関数を使って特殊な文字を置き換えたりする前段階処理を実行するほうが望ましい。なぜなら,Findメソッドの引数に不正な値を与えても特に問題となることはないが,場合によってはそれがセキュリティホールになるおそれもあるからである。今回はそのような事例を扱っていないが,たとえばユーザーからSQL文を入力させ,それをデータベースに送って処理するようなケースでは,ユーザーが不正なSQL文を入力することで,データベース内の特殊なストアドプロシージャを意図的に呼び出すことができる可能性を否定できない。今回のFindメソッドのように,ユーザーが不正な文字列を入力しても単なるエラーとしかなり得ない場合にはOn Error Resnme Nextステートメントを使ってもかまわないが,そうではなく,エラー以外の重大な問題が発生するおそれがあるときには,ユーザーの入力ミスをOn Error Resume Nextステートメントでトラップすることは避けなければならない。その場合,事前にしっかりと入力文字列をチェックすべきなのである。

 102〜112行目は,Findメソッドを呼び出した結果,BOFプロパティやEOFプロパティがTrueであるかどうかを調べているところである。BOFプロパティやEOFプロパティがTrueであるということは,Findメソッドを呼び出した結果,該当するレコードが見つからなかったということを意味する。そこで,MsgBox関数を使い,「指定された値は見つかりませんでした」と表示することにした。

 今回は,いかなる列でも検索できるような欲張った仕様にしてしまったために,少々処理が複雑になってしまった。しかし,Findメソッドを使えば,文字列の検索や数値の検索は比較的容易に実現できる。問題となるのは,日付の検索において時刻まで検索条件に含まれるため,例外的な処理を実装する必要があるという点のみである。


One Point! 実は,List 7-34の実装は使いやすさの点でやや問題がある。それは,Boolean型の検索処理である。顧客情報テーブルのDELETEDFLAGフィールドでは,削除ずみかそうでないかを示すフラグとしてBoolean型を用いている。List 7-34に示した実装では,Boolean型を数値として扱っているので,削除ずみでなければ0が,削除ずみであれば1が,それぞれ対応する。つまり,ユーザーは削除ずみの顧客を検索したいときには“1”という値を入力して検索しなければならない。これは,いかにもわかりづらい。今回はそこまで踏み込んで実装しないが,Boolean型を検索するときには,別途「はい」「いいえ」または「Yes」「No」を選択するようなわかりやすいユーザーインタフェースを用意したほうがよいだろう。
prevpg.gif Chapter 7 35/65 nextpg.gif