<HOME  <お願い事項   <Access2002 TOP   <Access97 TOP   <サイト内検索
 MS-Access2000超入門部屋--基本操作をさらに考える
   >00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 



さて、最後にこれが一番肝心なこと。
下のような式をいくら作ったところで、このまま何万年待っててもこの式の答えは出てきません。

そう、この式をいつ動かすのかということを考えます。

Me!テキストボックス名 = DMax("フィールド名","テーブル名") + 1

VBAのコードを書くときに一番肝心なことは「いつ動かすのか」ということを考えることです。
VBAがわかんない、なんかすごく難しいと言っている人の大半が、この感覚が理解できていない人。
決して構文がわからないということではないようです。

Accessは、「イベントドリブン型」といって、必ず、

ボタンをクリックしたとき とか
フォームを開いたとき とか
ふぉーむを閉じたとき とか
新しいレコードが発生する直前 とか

こういう「場面」に対してひとつふたつ処理を書くイメージになります。
つってもこんなの文字で理解しろってのが無理なお話ですよね。失敗したっていいから、とにかくいろいろやってみましょうよ。

今回はまず、「新しい伝票を入力するときに押すボタン」っていうのを考えてみました。
つまり、このボタンをクリックしたときだけ、新しい伝票の入力ができるようにしようと考えたわけです。
そしたら、このボタンをクリックしたときに、上の式が働くようにすればよいではないですか。ここまで考えがまとまれば後は簡単っすよ。

わたしはこんな画面にしたので↓「次の入力」のボタンね。こいつのプロパティを出します。あ、当然、デザインビューの状態ですよ。

イベントプロパティの一覧の中から「クリック時」というやつを探して、右端の[...]ボタン(ビルドボタン)をクリックしましょう。
え?ビルドボタンなんかない?「クリック時」ってとこクリックしなきゃ出てこないですよ。カーソル置いてください。そうしたら右端にボタンがふたつ出てくるでしょう?


「コードビルダ」を選んで、VBAのエディタを開きます。

Private Sub コマンド12_Click()

って書いてありますよね。ここで拒絶反応起こさないでくださいよ。

よく見れば、「コマンド12をクリックしたときの、このフォームの中だけのプログラム」っていう意味じゃないです?そうですよね。
だから後からボタンの名前とか変えちゃうとややっこしいことになっちゃうんですよ。
今日は「コマンド12」のまま変えませんからね。後で変えちゃダメですよ。

Private SubとEnd Subの間に、コマンド12をクリックしたときに動いてもらいたいことを書けばいいんです。

まず、新規レコードの入力状態になってもらいたいので、

DoCmd.GoToRecord , , acNewRec

で、次に伝票番号を代入する式を、

Me![伝票番号] = DMax("伝票番号", "売上明細") + 1

と入力します。処理は2行ですね。できればここからコピーしないで入力してみてくださいね。
その方が絶対、理解が深まりますって。ほんとほんと。

テキストボックスの名前を[ ]カギカッコで囲ってるのは・・・前にお話しましたっけ。
フィールド名とかフォーム名とか、既に存在するものの名前、っていうことですよね。
こういうのは皆さんもう大丈夫ですよね。


さあ、できたかな。テストです。
エディタのウィンドウを閉じ、フォームを保存してから、改めてフォームビューを開きましょう。
1行目が表示されてますね。

んで、この状態で、「次の入力ボタン」(コマンド12)をクリックしてみましょう。
さて、どうなるかな・・・。

と、一番大きな番号がついたはずなんですけど・・・。どうでしょう?つきました?
まさか、ぜんぜん意味がわからないとか、そういうことはないですよね・・・??
いろんな仕組みが重なり合ってひとつの「伝票番号の自動採番」という仕組みを作ってますから、ややっこしいと思います。
でもこの仕組みって結構役に立つと思うんで、あまり難しく考えず、基本的なトコしっかり押さえちゃってください。

余談ですが、この方法だと、「売上明細テーブル」の中に1件でもデータが入っていて、「伝票番号の中で一番大きい数」を探すことができる状態になってることがポイントです。1件もレコードが入ってない状態だと、「伝票番号の中で一番大きい数」というのをDMax関数が探してこれない可能性が大です。
その場合は、「もし1件もなかったら」という、例外処理に備えた処理を考えないといけないんですけど・・・そいつはまた別の機会にしましょう。とにかく、1件でもなんかダミーの伝票入力をしておいてからテストしてみてください。


で、ココまで理解がオッケーなら一段落。
多分ここまで来たら、「00005っていう感じで、アマタにゼロをつけるにはどうしたらいいの?」とか「Z-0004って感じで文字をつけたいんだけど」とか、「200006−0001って感じで、年と月を表す数字も頭につけたいんだけど・・・」とか、いろいろイメージが湧くと思います。
でも、基本は上の通り。上の仕組みが理解できてないうちは、やらない方がいいと思いますよ。こっちはすべて応用編ですね。


いちおう、上の仕組みをご理解いただいたと仮定して・・・。応用例を書いてみますね。参考にしてください。

「00005っていう感じで、アマタにゼロをつけるにはどうしたらいいの?」

ってのは、今の状態ではできません。
まず、「売上明細テーブル」の「伝票番号」のデータ型を「テキスト型」にしないとダメです。なんでダメかは、多分何となくご理解いただけると思うんですけど・・・。
とにかく、いったんこのフォーム閉じて、売上明細のテーブルのデザイン画面開いて、伝票番号のフィールドのデータ型をテキスト型にして、保存しなおします。
多分、エラーにはならないと思いますけど・・・ほんとは、途中でフィールドのデータ型変えるのって、あんましよくないんですよね。

で、テーブルは閉じて、もう一回フォームを開いて、コマンド12のクリック時のイベントのコードを見直します。ビルドボタンですよビルドボタン。クリック時の[...]ボタン。
DMAX関数にもう一工夫くわえます。
ゼロが・・・というより、つまり、桁をそろえるってイメージになりますね。例えば000005なら、全部で6桁。で、先行部分にゼロを入れるってことになります。
そういうときはFormat関数ってのが便利なんです。これも便利な関数なので、ヘルプを見て押さえておいてください。

Format(DMax("伝票番号", "売上明細") + 1,"000000")

ゼロの分だけ、先行ゼロが入ります。複雑そうに見えますけど、対応するカッコを探して、それぞれがFomat関数用のカッコ、DMax用のカッコであることを確認してください。書き方に。ちゃんと規則性がありますよね。

「Z-0004って感じで文字をつけたいんだけど」とか、「200006−0001って感じで、年と月を表す数字も頭につけたいんだけど・・・」・・・となると、難易度がまた少し上がりますね。これも、何か関数などをうまく工夫したらできるかな、と、そんな感じでとららえていただいて、ご自身でいろいろ研究なさってみてください。


後はちょっとだけ細かいことを・・・。
こうなると「伝票番号」を新しく入力する必要はなくなるわけで、というか、入力できるようになってるとかえってややこしいことになるんで、カーソルを「売上日」のトコまで飛ばしちゃおうかなと思いますけど、いかがでしょう。

それには、GotoControlっていうアクションを使いましたね。挑戦してみてください。
まあ、この辺はお好みですが・・・。

じゃ、試してみますか?どうでしょう。「次の入力」ボタンをクリックすると、カーソル、というか、入力できるような状態(フォーカスって呼びます)が「売上日」のトコに移動してます?


さて、これからわたしたちは「例外処理」と戦っていかなければなりません。

すなわち、今、続けて2回「次の入力ボタン」をクリックしたらどうなるか、ってことです。

フォームを閉じて、テーブルの中身を開いてみてください。

あれ・・・社員番号も売上も入力されてない・・・って、してませんよね。6番目の伝票入力したときって。伝票入力が不完全でも、こうしてレコードはできちゃうわけです。
今の状態だと、「次の入力ボタン」をクリックするたびに、あるいはただ「次の入力ボタン」をクリックしただけでフォームを閉じたりしても、どんどんこんな感じで「空回りレコード」が増えていってしまうはずです。これは今の状態ではしょうがないですよね?Accessのバグじゃないですよ。まだわたしたちの配慮が足りないんです。それは・・・わかりますよね。

じゃあどうすればよいか・・・。
これにはいろいろな考え方があります。いちおう、伝票入力の目的を考えて、最良の方法を取るようにしましょう。ケースバイケースです。
今回は・・・どうかな。例えば、フォームを閉じるときとか、新規レコードを追加するときとかに、入力が完全かどうかのチェックをして、必要最低限の入力がなされていなかったらエラーメッセージを出してフォームを閉じさせないとか・・・。そんな仕組みを考えてみましょうか。これもひとつの手だと思いますよ。


Accessは基本的に「レコード単位」の保存をします。
Excelみたいにファイル全体単位で保存するんじゃないんで、レコードの入力をはじめた時点で、既にそのレコードはテーブルの中の一員になってるわけです。
テーブルとかフォームを閉じるときに保存されるわけじゃないんですよ。だから、ちゃんと入力の仕組みを作っておかないと、どんどんワケのわかんない空っぽレコードが増えちゃう可能性もあるんです。
慌てんぼさんが入力するときなんか可能性大ですよね。

新規入力レコードの場合や、レコードの内容を書き換えているとき、その操作をキャンセルすることができます。
フォームをUndoしてやればいいんですよ。アンドウ。一太郎っていうワープロソフトを使ってる人にはおなじみの単語でしょうか。
一個前の状態に戻るとか、そんなイメージですね。ESCキーを押してレコードの入力や更新を取り消すってイメージになります。

ただ、このアクションは、動かすタイミング(イベント)が結構難しいんで・・・。状況によりけりかもしれませんが。

まずは「フォームを閉じるとき、フォーム内の”社員番号”テキストボックスに入力があるかないか」をチェックする処理を考えてみましょう。でも、「閉じるとき」ってもうフォームは閉じちゃってますから、「社員番号」のテキストボックスの中身を見ろっていっても通じないと思うんですよね・・・。

そこで、「終わり」ボタンを作って、絶対これをクリックして終わってらうように仕組みを考えてみましょう

書き方は結構単純・・・ただし、「社員番号のテキストボックスが空っぽかそうでないか」という判断をさせないといけません。こういう時使うのがIf文です。

考え方としては、

if なんか判断させる式とか then

 
どうする

else

 
そうじゃなかったらどうする

end if

わざと汚い色を選んでいるわけじゃないんですが・・・とにかくこんな感じになります。
今回の場合は、まず判断させる式として、「社員番号のフィールドが空っぽだったら」という式を考えます。
空っぽってのがまた難しいんですが、まあ、何の入力もなされてない、っていう意味で、IsNullっていう関数を使ってみましょう。
何の入力もなされてない、っていう意味です。
<Null ブランクとはまたちょっと意味合いが違うんで、この辺が難しいトコなんですけどね。まあ、今回はこれでいけると思います。

if isnull(me![社員番号]) then

 
どうする

else

 
そうじゃなかったらどうする

end if

で、どうするか、なんですけど・・・とりあえずメッセージも何も出さずUndoしてみますか。
閉じるときだからそれでいいでしょう。社員番号入力してないんですからね。この伝票はなしんこってことじゃないかなーと思うんです。

if isnull(me![社員番号]) then

 
me.undo

else

 
そうじゃなかったらどうする

end if

で、あとは「そうじゃなかったら」ですけど、そうじゃなかったら何にもしないで閉じてもらってかまわないんで、elseはいらない、ってことで、


if isnull(me![社員番号]) then

 
me.undo

end if


これで完成。これがIf文です。そんなに難しいことはないでしょう。
難しいのはなんか判断させる式とかという部分です。
こいつはケースバイケースなんだから、その時考えればいいこと。If文の構造だけ頭に入れておけば、いろいろ応用が利くはずですよね。

後は、わかりやすいようにコメントをつけておくと良いと思います。説明みたいなやつですね。
半角のシングルコーテーション’から右側は、コードと見なさないということになってますから、変なエラーにならず無視されますので、なんかしら説明をつけるときは下のようにしてください。−−−−ってのは別に入れなくてもいいです。シングルコーテーションだけあれば、右側は何を入力していただいてもオッケイ。

で、最後に、(End Ifの次の行)

Docmd.Close

と入力して、完成です。フォームを閉じるアクションです。これがなくちゃ(笑)