<HOME  <お願い事項   <Access2002 TOP   <Access97 TOP   <サイト内検索
 MS-Access2000--VBAの小屋>例外と戦う
   1 2 3 4 5 6



んでは、ついでに・・・。
同じような発想で、「生年月日から今日現在の年齢」を計算させてみましょうか。

新しいFunctionプロシージャを追加しましょう。名前はなんでもいいですよ。


基本的には、↓これだけで出せると思うんですけどね・・・。

あ、今回はいちおう、「年齢」を出すので、まあ、3万歳の人はいないだろうけど、Integer型を指定してみました。
NenreiというFunctionプロシージャで出した答えは、Integer型、という意味です。書き方、挑戦してみてください。

これだけだったら、何もプロシージャ作らなくても、DateDiff関数を直接クエリに書いちゃえばいいんですけど、とりあえず試してみましょうか。

はあ、なんか答え出てますけど・・・。

多分、誕生日がいつであったとしても、「その年のはじめ」にひとつ年を取るような計算のされ方になってると思います。「年」の部分だけで比較してますからね。ここんとこはみなさん、オッケーですよね。

年齢なので、「年」の部分だけで計算すればいいんですけど、10月1日生まれの人は、9月30日まで20歳で、10月1日になったら21歳になるんですよね。だから、「今日」が9月30日であるか10月1日であるか・・・つまり、生年月日の「月日」の部分と、今日の「月日」の部分を比較しないと、ほんとに正確な年齢を把握することはできないのです。
多分、今の状態だと、誕生日を迎えようが迎えまいが、年が明けると1つ年齢が増えてしまってるんじゃないかと思います。いろんな誕生日入力して、試してみてください。

正確な年齢、といっても、10も20も違ってしまうわけではなくて、1歳だけですけどね。
要するに、その年の誕生日がくるまで、DateDiff("yyyy",[生年月日],Date())で取ってきた年齢から1引いておけばよいわけです。

 If 生年月日の「月日」 より 今日の「月日」 の方が小さかったらまだ誕生日前だから
   DateDiff("yyyy",[生年月日],Date())-1
 それ以外は
   DateDiff("yyyy",[生年月日],Date())
 というわけです。

という感じの条件判断をしてやればいいわけですね。
あとは、「生年月日の「月日」 より 今日の「月日」 の方が小さかったらまだ誕生日前だから」これをどう書けばいいか、というところなんですけど・・・。
皆さんご存知とは思いますが、Windowsの日付時刻というのは、2000/10/01と書いてあったとしても、これは10桁の数値や文字ではないのです。内部的には「1900年1月1日から今日は何日目?」という数値が入ってまして、35021とか、そういう値なんです。それを日付時刻の書式で、2000/10/01って見せてるだけなのです。だから、「右端から5桁分取り出して10/01の部分だけ比較」っていっても、Accessにはわかりません。実際には2000/10/01っていう値が入ってるわけじゃないから。
年/月/日(正確にはこの後時間と分と秒も続く)が全部そろって、ワンセットなのです。

なので、超めんどくさいんですけど、けっこうめんどくさいことをしないといけません(汗)
今日、と、その人の誕生日を比較するためには、「年」の部分をそろえないといけないですよね。
1687年10月22日生まれの人の生年月日は、1687/10/22です。今日が2000/10/21だとすると、このふたつの日付を比較して、「10/22より前か後か」を知りたいんですけどね。このままだと、年月日全部セットで見てしまいます。1687/10/22は、内部的には-77500です。2000/10/21は36820なので、比較しても意味がありません。
なんとか、1687/10/22の10/22の部分だけ取り出して、2000/10/21と比較する方法はないもんでしょうか。

要するに、1687/10/22を、今年の/10/22って置き換えて考えてやれば、比較できますよね。

ここで、サーカスみたいなことをやります。
Nenreiプロシージャの引数(Umare)に代入された生年月日を、年、月、日の3つにばらして、年の部分だけ、今年の「年」にすりかえて、また年月日くっつけて日付時刻型の値に戻します。

いろんなやり方があるんですけど・・・ポイントとしては、年月日と一時的にバラバラにしますけど、最終的には日付時刻型の値に戻す、ということです。
Format関数とか使って一時的にバラバラに取り出すと、ほんとに2000/10/22っていう文字フィールドになっちゃう可能性大ですよね。そうすると結局、「今日」と比較できなくなっちゃいます。今度は「データ型が違う」ってことになっちゃいますしね。

データ型が及ぼす影響・・・特に、Windows上でうまいことプログラミングしていくためには、「日付時刻型」フィールドとうまく付き合っていかないとならないです。ぜんぜんわかんない。。。なんかこういうの苦手だ・・・という方もいらっしゃると思いますが、これも、できればゆっくり時間をかけて慣れていってください。
せっかくだから、応用できるようにしていきたいですよね。がんばりましょう。

バラバラの年と月と日をくっつけて日付を作る関数があるんです。DateSerial関数っていいます。ご存知かな。

DateSerial(年を表わす数字,月を表わす数字,日を表わす数字)

って使います。

あと、とある日付から、年の部分だけ取り出す関数にYaer関数、月の部分だけ取り出すやつにMonth関数、日の部分だけ取り出す関数にDay関数というのがありますんで、これをうまく活用しましょう。

なんか変数 = DateSerial(Year(Date), Month(生年月日にあたる日付), Day(生年月日にあたる日付))

これで、1687/10/22が、変数の中で2000/10/22になりますから、今日の日付と比較して、誕生日が過ぎてるか過ぎてないか、確認できるってわけです。
うわははは。イヤでしょう。めんどうなんですよ。ひとつプロシージャ作るっていうのも・・・。


じゃ、いきますよん。

まず、引数は「生年月日」が入ってきますから、Date型を指定しましょう。

でもって、バラバラにしてくっつけた日付を入れる変数を、日付時刻型で宣言しておきます。AAAAとか、なんかそんな名前で適当に作ってください。
これで、AAAAには、今年のその人の誕生日が入ってくるはずですよね。

AAAAと今日の日付を比較することで、誕生日が過ぎたのかまだなのか、知ることができます。

まだだったら、1引いときます。不等号の向き、気をつけてくださいね。

完成したら、コンパイルして確認してから、Module1を保存しておきましょう。
じゃ、クエリでおためしです。


年齢、出ますか?生年月日、いろいろ入力してみたりして、確かめてみてくださいね。
誕生日が過ぎたら、ひとつ歳を取ってますか?


さて・・・。
VBAを使う、ってことの意味、つかんでいただけましたでしょうか。

たまに、「こういうことは、VBAを使えばできるんでしょうか?」なんて感じのご質問いただいたりするんですけど、「できるできない」の問題ではないのです。「やろうと思えばできる、思いつかなければできない」という世界。決まったやり方もありませんし、多分、10人いれば10通りの書き方があると思います。
こんな、年齢もとめたり勤続年数求めたりするなんてことは、それそのものは、そんなに頻繁に必要な知識ではありません。
お話したいのは、「VBAを使ってプロシージャを作るということの雰囲気」をつかんでいただきたい、ってことなんです。
だから、ここでは、コードを丸写しコピーするのではなくて、1行1行、関数ひとつひとつ、書き方、意味、活用の仕方を見ていっていただきたいなと思います。

↓「こういうプロシージャ作ったんですけど、なんかエラーになるんです・・・」

どうしてエラーになるか、みなさん、おわかりになりますか?

エラーはこういうのが出ました。

なんでエラーになるのか、このコードのどこが悪いのか、ということを考える前に、このプロシージャ、どういう処理をするプロシージャだか、まずそこを考えてみてください。
人が作ったコード丸写ししただけだと、多分、こういう壁にぶち当たっちゃうんじゃないかな、って、ちょっと心配です。

上のプロシージャ、何をしているんだと思います?

これ、わかんない、って方は、多分いらっしゃらないと思いますけど・・・。
Seikyu_Hakkoっていう名前の、別のプロシージャを呼び出し(Call)しています。
でも、このデータベースの中に、Seikyu_Hakkoなんていう名前のプロシージャが見当たらないので、「SubまたはFunctionが定義されていません」っていうエラーになって止まるんです。

・・・なぜないかって?作ってないからじゃないでしょうか・・・。
つまりですね・・・「おーい、田中、田中はいないのか?ったく、しょうがないヤツだな。呼ばれたらちゃんと出てこいよ」「うちのクラスに田中なんてやつ、いないよ」
ってことですね。

ここまでいろいろ作ってみて、これの意味がわからない、って方はいらっしゃらないと思いますんで大変バカバカしいお話ですが、VBAそのものを、どういうものかよくわかってない人からすると、「なんでエラーになっちゃうんだろう・・・本のとおりに書いてるのに・・・」って途方にくれちゃうんじゃないでしょうか。
こんなことのないように、小さなプロシージャをいくつも作ってみて、とにかくデータベースの中でプロシージャというものがどういう存在なのか、身体で覚えちゃうってのがポイントだと思いますよ。

すべてにおいて言えることは・・・テーブルやフォームなど、Accessの中の構造や各オブジェクトの役割、プロパティ、あらかじめ用意されている関数などについて、ひとつでも多く知っておくことです。今までご覧いただいてきたのだって、コードそのものの書き方、っていうより、どこで、どういう関数を使って、なんて感じのお話が多かったでしょう?で、最終的にそういうの全部ひっくるめて、「VBA」っていうものになるわけです。
プロシージャそのものの「書き方」「エディタの使い方」等々に少し慣れてきたら、関数ハンドブックとかプロパティ一覧みたいな書籍をひとつ、手元に置いておかれるといいと思います。あるいは、ヘルプの「VisualBasicの概念」の章にある関数やプロパティの一覧を片っ端から読んでいくとか。
とにかく、すぐ役にたたなくても、知っていることはひとつでも多い方が勝ち、って世界ですよ<VBAって。

決して、「VBA」という単語だけ一人歩きさせないで下さいね。