Access実践入門 TOPへ
 ■ マイクロソフトアクセス、単票入力フォーム
単票入力フォームとは
フォームには、帳票フォームと単票フォームの2種類あります。
ここでは、単票フォームを使った入力を説明します。
単票フォームは、1ページの画面が1つのレコードになっていて基本的にはウィンドが閉じたら、1レコード登録される仕組みになっています。
細かい入力チェック、複雑な入力画面が作成可能です。

入力の仕組み
ここで紹介している住所録の処理は、まず入力済みデータを一覧表で表示して、変更する場合は一覧から呼び出して修正し、新しく登録する場合は、新規登録で白紙のフォームにデータを登録し、一覧表に戻るという形をとっています。

まず、「fo住所録一覧表」のデザインを見てください。
何もない所をクリックしますフォーム全体のプロパティを見てください。
前に紹介した、帳票ホームと同じです。
違うところは、レコードソースがクエリーになっています。
ここで、フォームのレコードソースとなる選択クエリー「qu住所録一覧表番号順」を見てみます。
今、開いているフォーム「fo住所録一覧表」を閉じてください。もし、登録の確認画面が出たら、いいえを選んでください。

では、クエリー「qu住所録一覧表番号順」のデザインを見てください。



クエリーの作り方は前回説明したとおりです。
「ta住所録」の項目は全部下に落としています。1つずつ落とさなくても、まず一番上の住所録番号をクリックして、最後のめもの項目をスライドさせて見えるようにして、SHIFTキーを押しながら、めもをクリックすると全項目が選択できますので、それを下に落とすと全部落ちます。
次に「ta勤務先」の勤務先名を下のメモの上に落とすとめもの前に入ってきます。
最後に、住所録番号の並び替えの欄でその列の右端をクリックするとコンボボックスが出ますので、昇順を選べば、出来上がりです。

練習してみてください。いろいろ試した後、クエリーを閉じるときに「いいえ」を選択すれば、変更は保存されませんので、クエリーが変わってしまうことはありません。
このクエリーは抽出条件のない全レコードが住所録番号順に並んだ一覧表です。

それでは、このクエリーをデザインではなく、開くボタンで開いてみましょう。
すると、住所録番号順に一覧表になって表示されます。ここでデータを編集しても編集できます。
プログラムの作者が編集したい項目だけのクエリーを開けて、データの保守作業をすることはよくあります。
ただ、入力の規則、桁数のチェックなど一切できませんから、データ構造を知らない人にクエリー画面で入力させるのは危険です。

では、クエリー「qu住所録一覧表番号順」を閉じてください。


フォームの「fo住所録入力」の説明をします。
このフォームは変更のための編集用として、新規登録のための入力用として、2つの使い方をしなければいけません。新規登録の画面では、削除ボタンは必要ありません。
かといって、それぞれのために似たようなフォームを2つ作るのは効率が悪いです。
ここでは、新規登録中なのか、編集中なのかの区分を、変数としておぼえさせています。

フォームのデザインを見る前に、データベースウインドからモジュールを選んで、そこのある、Moduleのデザインを開いてみてください。その中の一番上に、
Public inpmode As Integerというのがあります。
これは、このプログラムのどこからでも参照できる、整数が入る、inpmodeという変数を使いますよ、という宣言です。



このように使うのだと、覚えてください、そして、その変数の使い方は、これから説明する「fo住所録入力」で出てきますので、それの真似をして使ってください。
全てを理解しなくても、使い方を真似すればプログラムは作れますので。

もう一度、「fo住所録一覧表」のデザインを見てください。
「新規登録」ボタンのプロパティで[クリック時]のイベントプロシージャを開いてみてください

inpmode = 0
DoCmd.OpenForm "fo住所録入力", acNormal, , , acFormAdd

1行目で、先程宣言している、変数に0を代入しています。
その後、「fo住所録入力」のフォームを開いています。
ここでは、フォーム名の後に、カンマでいろいろつないで書いてあります。
最後のacFormAddは、[データモード]が追加であることを示しています。

だんだん難しくなってきましたが、ここであまり悩まないでください。何度も言いますが、自分のプログラムを新規に作る場合、入力画面は、この「fo住所録入力」をコピー張り付けで使うわけですから、このコードもすでに書かれているわけで、上のコードのfo住所録入力をたとえば、fo顧客入力に変更するだけで、すぐ使えるのです。したがって、, , , acFormAddのことで難しいなぁ〜と悩む必要はありません。プログラムが作れるようになってからゆっくり悩んでください。サンプルを確認したり、コピーしてプログラムを作っていうちに徐々に理解できるようになります。
最初から出てきた項目全てを理解しながら進むことは無駄な事ですし、このサイトの目的に反します。

それでは、今開いている、プロシージャのウィンドを閉じて、Visual Basicのウィンドも閉じて、戻ってください。

次に、[詳細]に中にある、「編集」ボタンのプロパティで[クリック時]のイベントプロシージャを開いてみてください

inpmode = 1
DoCmd.OpenForm "fo住所録入力", , , , acFormEdit, , Me.住所録番号

1行目で、先程宣言している、変数に1を代入しています。
その後、「fo住所録入力」のフォームを開いています。
ここでのも、フォーム名の後に、カンマでいろいろつないで書いてあります。
acFormEditは、[データモード]が編集であることを示しています。
次の[ウィンドウモード]は省略されていて、その次にMe.住所録番号とあります。
マクロには[ウィンドウモード]の次の引数は無いはずです。
Visual Basicでのみ使えるモードなのです。開いた後、自分のフォームの住所録番号のコントロールに移動しなさいというような意味です。このように、マクロとプロシージャで違う場合もあります。


それでは、すべて閉じて、データベースウィンドに戻り、「fo住所録入力」のデザインを開いてみてください。


何もない所をクリックしますフォーム全体のプロパティを見てください。
[規定のビュー]が「単票フォーム」なっています。
[Tabキー移動]が「カレントレコード」になっています。これは帳票入力と違って、最後の項目を通過した後、次のレコードに行かせないためにこうしています。
その他のプロパティについては説明しませんが、単票入力を使うときは、このフォームをコピーして使っていただければ、他のプロパティを修正する必要はありません。

帳票フォームとの違いはここだけです。

それでは、その下の方にある、[開く時]に、イベントプロシージャが書いてあります、それを右端の"..."のボタンで開いてみてください。

  1 Select Case inpmode
  2 Case 0
  3  Me.RecordSource = "qu住所録一覧表番号順"
  4  Me.削除.Visible = False
  5 Case 1
  6  Me.RecordSource = "qu住所録編集"
  7  Me.削除.Visible = True
  8  Me.住所録番号.Locked = True
  9 End Select

Visual Basicで、条件分岐に使う Select Case文が使われています。
文法について、詳しくは説明しません。こんなかんじで使うらしい、だけでいいです。
変数 impmode が0の時1の時の処理が書いてあります。
3行目と4行目は0の時、すなわち新規登録時です。
Me.RecordSource とな何でしょう。
マクロをプロシージャで書くと英語になるように、フォーム全体のプロパティをプロシージャで書くと英語になります。
フォーム全体のプロパティの[レコードソース]が「qu住所録一覧表番号順」ですよという意味です。フォームを開くときに自分のレコードソースをデザイン画面で設定しているレコードソース以外のものに変更できるわけです。
4行目で、このフォームの削除ボタンのプロパティのVisible(可視)をFalse(いいえ)にしています。これで、新規登録時には、削除ボタンが無い(見えない)状態でフォームが開くわけです
Me.で、フォーム全体、Me.○○.でフォームの中のコントロールにたいして処理を記述できます。

6から8行目は、一覧表から、編集ボタンから呼び出された場合です。
レコードソースは「qu住所録編集」です、このクエリーでは、抽出条件に一覧表の住所録番号が設定してありますのでそれに該当するデータをレコードソースにしますので、編集ボタンがクリックされた行のデータが表示される結果となります。
7行目で、削除ボタンのプロパティのVisible(可視)をTrue(はい)にしています。
8行目で、住所録番号を変更されては困るので、プロパティのLocked(編集ロック)をTrue(はい)にしています。


同じくフォーム全体のプロパティの中のさらに下の方にある、[キークリック時]に、イベントプロシージャが書いてあります、それを右端の"..."のボタンで開いてみてください。


これは、単票フォームでPageUpキーとPageDownキーが押されると、レコードが移動してしまうため、2つのキーを押されても無視するように書いているものです。
[キークリック時]のプロシージャを機能させるためには、その少ししたにある、[キーボートイベント取得を]「はい」にしておかなければいけません。
この2つをセットにして、単票フォームには必ず付けると覚えてください。

フォー全体に関しての、プロシージャはこの2つです。


次に、フォームに貼ってあるコントロールを見てみます。
まず、住所録番号のプロパティの[フォーカス喪失時]のプロシージャを見てください。
[フォーカス喪失時]とは、今居るコントロールからTABキー等で次のコントロールにカーソルが移動する直前のことです。

 1 If inpmode = 0 Then
 2  If IsNull(Me.住所録番号) Then
 3   Exit Sub
 4  Else
 5   If Len(Me.住所録番号) <> 5 Then
 6     MsgBox ("数字5桁で入力して下さい。")
 7     DoCmd.CancelEvent
 8   End If
 9   If DCount("住所録番号", "ta住所録", "[住所録番号]='" & Me.住所録番号 & "'") <> 0 Then
10   MsgBox ("この番号は使用済みです。")
11   DoCmd.CancelEvent
12   End If
13  End If
14 End If

Visual Basicで、条件分岐に使う If Else文が使われています。
1行目は、変数がゼロ(新規登録)の時は2行目に、それ以外は、一番外のEnd Ifの飛びます。If とEnd If は必ず対になっています、Else は無い場合もあります
2行目は、住所録番号に何も入力されなかった場合は、3行目へ、それ以外は、4行目へ分岐します
3行目は、このプロシージャから出ます。
4行目のElseは2行目のIfに対するElseです、5行目に移ります。
5行目では、入力された住所録番号の長さが5桁かどうか調べます、5桁の場合は、9行目に、5桁でない場合は、6行目に移ります。
6行目は、小さいウィンドを開けて、メッセージを表示します。
7行目は、次の項目へ移動しようとしているのをキャンセルします。(つまり住所録番号にとどまらせる)
8行目は、5行目の If に対する、End If です。
9行目は、「ta住所録」の中に、今入力されたデータと一致するレコードが何個あるか調べています。ゼロでない場合は、10行目に、それ以外は、12行目の移ります。
10行目は、小さいウィンドを開けて、メッセージを表示します。
11行目は、次の項目へ移動しようとしているのをキャンセルします。
12行目は、9行目の If に対する、End If です。
13行目は、2行目の If に対する、End If です。
14行目は、1行目の If に対する、End If です。

この一連のコードは、単票入力画面の新規入力で使うものとして、まとめてコピーして使ってください。


次に区分のプロパティを見てください。
初めて出てきた、コントロール(コンボボックス)です。


「ta区分」のデータを参照して、その中のデータを貼り付けるコントロールです。
[値集合タイプ]:テーブルを参照しますので、テーブル/クエリーになります。
[値集合ソース]:ここでは、テーブル名が入ります。(「ta区分」)
[列数]:「ta区分」は、フィールドが1つしかないので、1です。
[列見出し]:ここはいいえでいいでしょう。
[列幅]:区分名がわかるような幅を設定します。
[連結列]:ここはいつも1です。
[リスト行数]:スクロールしないで一度に見せるウィンドの行数です
[リスト幅]:ここでは、1列ですが、列幅の合計の数字になります。
[入力チェック]:ここが[はい]の場合は、参照する「ta区分」以外のデータを入力することができません、ここでは、リレーションシップが登録されているので、[はい]にしておきます。
[自動拡張]:ここはいいえにしておきましょう。
ここでは、簡単な説明で終わりますが、別の場所でもコンボボックスは使っているので、違いを比べてみてください。

次に生年月日和暦のプロパティを見てください
コンボボックスです。


ここでは、[値集合ソース]がクエリーになっています。
参照画面が開いたときに明治から順番に並ぶようにするためです。
和暦番号に並び替えを設定しています。


[列数]:2になっています。
[列幅]:セミコロンで、つないで書きます。ただし右側の番号は見せたくないのでゼロです。


次に生年月日のプロパティを見てください
[定型入力]を使っています。

ウイザードで作ることができますが、日付の入力は、ここをコピーして使ってください。

このコントロールの[フォーカス喪失時]に次のようなイベントプロシージャが書いてあります。

If IsNull([生年月日]) Then
 Else
 If Len([生年月日]) <> 9 Then
  MsgBox ("年は2桁、月は2桁、日は2桁の入力です。")
  DoCmd.CancelEvent
  Exit Sub
 End If
End If

ここでは桁数をチェックしています。
このように書くと、覚えてください。

次に生年月日日付のプロパティを見てください
[可視]:が「いいえ」になっています。
このコントロールは、入力者には見せません。


次に性別のプロパティを見てください
コンボボックスです。

[値集合タイプ]が値リストになっています。
こうすると、直接選択項目があたい集合ソースにセミコロンでつないで、記述できます。
入力チェックを、いいえにしておくと、値集合ソース以外の文字も入力できます。
ここでは、値集合ソース以外の入力は許していませんが、項目の内容によっては、入力チェックをいいえにして、使ってください。


次に勤務先番号のプロパティを見てください
コンボボックスです。


[入力チェック]ここでは、リレーションシップが登録されているので、[はい]にしておきます。


次に勤務先名のプロパティを見てください
[使用可能]:が「いいえ」、[編集ロック]:が「はい」になっています。
選ばれた番号に対する勤務先名を確認のために表示するだけで、編集させてはいけません。

以上で、詳細の中にあるコントロールは終わりです。

次にフォームフッターの戻るボタンのプロパティを見てください
[クリック時]にイベントプロシージャが書いてあります。

 1 SendKeys "{ESC}", True
 2 DoCmd.Close
 3 If inpmode = 0 Then
 4  Form_fo住所録一覧表.RecordSource = "qu住所録一覧表番号順"
 5  DoCmd.ShowAllRecords
 6 End If

1行目は、キーボードから、ESCキーを押したとのと同じ処理をさせるコードです。
入力の途中で戻るボタンを押された場合、不完全なデータを登録されないために、このようにしています。単票フォームは閉じるときに、レコードが登録されますので、これは、必ず必要です。
後で説明しますが、登録ボタンでは、データのチェックをしていますから不完全なデータのままでは閉じられませんが、データを完全に登録しないと、前の画面に戻れないのでは、困りますので、このような、入力中でも、キャンセルして戻ることができるボタンを用意しています。

2行目は、自分自身のウィンドを閉じます。
3〜6行目では、もし新規登録中であれば、新しくデータが登録された可能性があるので、戻った一覧表のデータを更新するために、「全レコード表示」の命令をしています。
4行目は、検索を実行していた場合は、レコードソースが変更されているので、最初のレコードソースに戻しています。


次にフォームフッターの登録ボタンのプロパティを見てください
[フォーカス取得時]と[クリック時]にイベントプロシージャが書いてあります。
[フォーカス取得時]の方がイベントとしては早く発生します。
プログラムは[フォーカス取得時]を先に処理します。
[フォーカス取得時]のイベントプロシージャを見てください。

ここを、クリックしない限り、データを登録できないようなフォームの設計になっていますので、ここに大事なデータチェックを書いています。
上から順番に見ていきます

If IsNull([住所録番号]) Then
MsgBox ("住所録番号を入力して下さい。 ")
DoCmd.GoToControl "住所録番号"
Exit Sub
End If


If IsNull([区分名]) Then
MsgBox ("区分名を入力して下さい。")
DoCmd.GoToControl "区分名"
Exit Sub
End If


If IsNull([勤務先番号]) Then
MsgBox ("勤務先番号を入力して下さい。")
DoCmd.GoToControl "勤務先番号"
Exit Sub
End If

上の3項目は、リレーションシップで登録されていますから、必須入力です。
空白の場合は、それぞれのコントロールに戻して、入力をしてもらいます。
Exit Sub とは、このイベントプロシージャを抜けるということです。
プロシージャの下の評価をするまでもなく、入力してもらわなければ、先に進んでも無駄だからです。入力後、登録ボタンを再度クリックしてもらうことになります。


If IsNull([生年月日]) Then
Else
 If IsDate([生年月日和暦] & [生年月日]) = 0 Then
  MsgBox ("日付の入力が間違っています。")
  DoCmd.CancelEvent
  DoCmd.GoToControl "生年月日"
  Exit Sub
 End If

[生年月日日付] = DateValue([生年月日和暦] & [生年月日])
End If

生年月日は必須項目でないので、入力されていなければ、チェックする必要がないので、すぐにここのIf 文を抜けます。
IsDade() はかっこ内の文字列が日付型のデータに変換できるかどうか調べさせるために使っています。変換出来なかったら、ゼロが帰ってきます。
たとえば、大正18年01月01日と入力されたり、昭和50年15月45日と入力されたら、存在しない日付なので、値がゼロになり、生年月日にコントロールを戻して、再入力をしてもらいます。
正しい日付が入力された場合、DateValueで、日付型データに変換して、[日付年月日の]集計用のコントロールに値をコピーしています。

このイベントプロシージャの書いてある条件を全てクリアしたものだけが、次の[クリック時]のイベントプロシージャへと進むことができます。


[クリック時]のイベントプロシージャを見てください。

Select Case inpmode
Case 0
    DoCmd.Close
    DoCmd.OpenForm "fo住所録入力", acNormal, , , acFormAdd
Case 1
    DoCmd.Close
    Form_fo住所録一覧表.RecordSource = "qu住所録一覧表番号順"
    DoCmd.ShowAllRecords
End Select

ここでは、入力モードによって処理が別れます。
新規登録時は、自分自身を閉じて、データを登録させて、すぐに入力画面を、新規レコードモードで開きます。(連続で新規登録をするようになっている)
編集時には、自分自身を閉じて、データを登録させ、一覧表を番号順に並べるクエリーをレコードソースにして、全部のレコードを再表示させて、最新の一覧表にした状態で、次の処理を待ちます。


最後にフォームフッターの削除ボタンのプロパティを見てください
ここでは、[クリック時]にマクロを呼び出しています。
イベントプロシージャで書いてもいいのですが、別のウィンドが開きますし、特別な処理ですから、マクロに書いた方が、わかりやすいような気がします。

マクロでは、削除選択画面を開けて、削除する場合には、削除クエリーを実行しているだけです。
帳票のところで説明していますが、進物データが入力されているデータを削除しようとすると、Accessがエラーを出して、削除できません。
バージョン1.0では、このままにしていますが、次のバージョンで、進物データがあるので削除できませんというメッセージを表示させます。