Access実践入門 TOPへ
 ■ マイクロソフトアクセス、伝票入力−2(伝票入力の画面操作)
メインフォームの各イベント(フォーム全体)

まず、フォーム全体の各イベントの内容を説明します。

・[開く時]
 Select Case inpmode
  Case 0
     Me.削除.Visible = False
  Case 1
     Me.削除.Visible = True
 End Select

 hick = DLookup("登録締切日付", "ta会社情報", "ID =1")

ここでは、新規登録の時は、削除ボタン使用不可です。
登録締切日付を変数hickに代入しています
hickは、このフォームのモジュールの先頭に宣言してあります。


・[読み込み時]
 If inpmode = 0 Then
  Me!伝票番号 = DLookup("伝票番号", "ta会社情報", "ID =1")
 End If

新規登録の時は、伝票番号に会社情報の伝票番号が入ります。


・[キークリック時]
 Select Case KeyCode
  Case &H21, &H22
  KeyCode = 0
 End Select

ここでは、PageUpとPageDownキーを無視する設定です。
[キーイベント取得]を「はい」にしておかないといけません

・[エラー時]
 Response = DATA_ERRCONTINUE

  If DataErr = 3101 Then
   MsgBox "得意先番号を入力してください。", , ""
   DoCmd.CancelEvent
   DoCmd.GoToControl "得意先番号"
   Exit Sub
  End If

得意先番号を入力しないで、サブフォームにマウスで移動しようとしたときに、
「フィールド"得意先番号"とキーが一致・・・・」のようなエラーを出します。
その対処方法が見つからないので、このようにしています。
そのような場合、エラーメッセージでヘルプボタンを押すと、エラー番号が解ります。
今回3101番ですので、上のように書いて、とにかく得意先番号のコントロールに戻します。
このように、エラー番号毎に、処理方法を変えることができます。

メインフォームの各イベント(コントロール毎)

・----[請求日][フォーカス喪失時]----

 If IsNull([請求日]) Then
  Exit Sub
 End If

 If Len([請求日]) <> 11 Then
  MsgBox "年は4桁、月は2桁、日は2桁の入力です。", , ""
  DoCmd.CancelEvent
  Exit Sub
 End If

 If IsDate([請求日]) = 0 Then
  MsgBox "この日付の入力は間違っています。", , ""
  DoCmd.CancelEvent
  Exit Sub
 End If

 If DateValue([請求日]) <= hick Then
  MsgBox ("締切日以前のデータは入力できません...")
  DoCmd.CancelEvent
  Exit Sub
 End If

 [請求日付] = DateValue([請求日])

請求日に何も入ってないときは、すぐに出ます。ここで値を要求すると、戻るボタンで戻れなくなりますから・・・
請求日の桁数チェック、日付のチェック、締切日との比較をしています。
すべてOKの場合のみ、請求日付に日付型を代入します。


・----[伝票番号][フォーカス喪失時]----

 If IsNull([伝票番号]) Then
  伝票番号 = 0
 End If

数値入力なので何も入ってない場合は、ゼロを代入。


・----[得意検索][クリック時](得意先検索ボタン)----

 kdck = 1
 DoCmd.OpenForm "fo得意先検索指定"

kdckの値で区別して、伝票と入金で得意先の検索が出来るようにしています。
詳しくは後述します。


・----[明細サブ][フォーカス取得時](サブフォーム)----

 If IsNull([請求日]) Then
  MsgBox "請求日を力して下さい。"
  DoCmd.CancelEvent
  DoCmd.GoToControl "請求日"
  Exit Sub
 End If

 If IsNull([得意先番号]) Then
  MsgBox "得意コードを力して下さい。"
  DoCmd.CancelEvent
  DoCmd.GoToControl "得意先番号"
  Exit Sub
 End If

明細を入力する前に、請求日と得意先番号が入力されているかどうか調べています。


・----[戻る][クリック時](戻るボタン)----

 DoCmd.Close

フォームを閉じています。


・----[削除][クリック時](削除ボタン)----

 delmode = 7
 DoCmd.OpenForm "fo削除選択"

delmodeの値で区分して削除します。


・----[登録][フォーカス取得時](登録ボタン)----

 If IsNull([請求日]) Then
  MsgBox "日付を入力してください"
  DoCmd.CancelEvent
  DoCmd.GoToControl "請求日"
  Exit Sub
 End If

 If IsNull([得意先番号]) Then
  MsgBox "得意先を入力してください"
  DoCmd.CancelEvent
  DoCmd.GoToControl "得意先番号"
  Exit Sub
 End If

 If DSum("金額", "to請求明細") = 0 Then
  MsgBox "明細を入力してください"
  DoCmd.CancelEvent
  DoCmd.GoToControl "明細サブ"
 End If

請求日、得意先番号、明細に入力があるかどうか調べています。


・----[登録][クリック時](登録ボタン)----

 Me!税抜計 = DSum("金額", "to請求明細")
 Me!消費税計 = DSum("消費税", "to請求明細")

 Select Case inpmode
   Case 0:
     DoCmd.RunMacro "ma伝票.新規登録"
   Case 1:
     DoCmd.RunMacro "ma伝票.編集登録"
 End Select

「to請求」に必要な[税抜計]と[消費税計]の値を計算してコントロールにコピーしています。
マクロでの登録へ処理を移します。

メインフォームの各コントロール

・[得意検索]
得意先の検索ボタンです。
入金からも同じような検索がありますので、共通して使えるようにしています。
指定画面の「fo得意先検索指定」
検索結果を一覧表示する「fo得意先検索一覧」
この一覧表の[転記]ボタンがクリックされた時に、入金か伝票かを区別して、得意先番号のコントロールに検索結果の番号が代入されるようにしています。

・[摘要]
コンボボックスになっています。
過去の伝票で入力されている全ての摘要文が参照できるようになっています。

サブフォームのイベントと各コントロール

・フォーム全体のイベント
[キークリック時]にメインフォームと同じ処理が有ります

[更新前処理]に次のような処理があります
 If (IsNull(Me!商品番号) Or Me!商品番号 = "") And (Me!金額 <> 0 Or Me!消費税 <> 0) Then
  MsgBox ("商品番号を入力して下さい")
  DoCmd.CancelEvent
  DoCmd.GoToControl "商品番号"
 End If

ここでは、商品番号に何も入れないで、金額や消費税に数値が入らないようにしています。商品別集計と売上合計が矛盾しないためです。
商品番号無しで、商品名のところを使って文字を入力することはできます。

・各コントロールのイベント

----[行管理][クリック時](行番号の右のボタン)----
 SendKeys "{ESC}", True

 gy = Me![行番号]
 DoCmd.RunMacro "ma伝票行管理.行管理選択"

まだレコードが更新されていない行(入力途中の行)の場合はモジュールで、エラーが出るのでESCキーを送って編集前に戻してから行管理に移ります
gyに行番号を代入して、マクロの行管理を呼び出します。

ここで挿入と削除のモジュールの説明をします。



−挿入−den_ins()

Public Function den_ins()

 1 Dim dbs As Database
 2 Dim rst_1 As Recordset

 3 Dim gyou As Integer

 4 Set dbs = CurrentDb
 5 Set rst_1 = dbs.OpenRecordset("to請求明細", dbOpenTable)

 6  rst_1.Index = "行番号"
 7  rst_1.MoveLast
 8  If (IsNull(rst_1!商品番号) Or rst_1!商品番号 = "") And (IsNull(rst_1!商品名) Or rst_1!商品名 = "") And rst_1!数量 = 0 And rst_1!単価 = 0 And rst_1!金額 = 0 Then
 9   rst_1.Edit
10   rst_1!行番号 = gmax + 1
11   rst_1.Update
12   rst_1.MoveLast
13   rst_1.Move -1
14  Else
15   MsgBox ("これ以上行を増やせません")
16   rst_1.Close
17   Exit Function
18  End If

19  Do Until rst_1!行番号 < gy
20   gyou = rst_1!行番号 + 1
21   rst_1.Edit
22   rst_1!行番号 = gyou
23   rst_1.Update
24   rst_1.Move -1
25   If gyou = 2 Then
26     Exit Do
27   End If
28  Loop

29  rst_1.MoveLast
30  rst_1.Edit
31  rst_1!行番号 = gy
32  rst_1!商品番号 = ""
33  rst_1!商品名 = ""
34  rst_1!数量 = 0
35  rst_1!単位 = ""
36  rst_1!単価 = 0
37  rst_1!金額 = 0
38  rst_1!消費税 = 0
39  rst_1!明細摘要 = ""
40  rst_1.Update
41  rst_1.Close

42 DoCmd.ShowAllRecords
43 DoCmd.GoToControl "明細サブ"
44 DoCmd.GoToRecord , , acGoTo, gy

End Function

6行目で、行番号をインデックスに指定しています
7行目で最後の行にレコードを移動します(ここでは20行目)。
8行目からは、
最後の行にデータが入力されていない場合は、9〜13行目を処理します。
9行目で、編集モードの指定
10行目で、行番号20を21にします。
11行目で、レコードを上書き保存します。
12行目で、最後のレコードに移動します
13行目で、1つ前のレコードに移動します。(19行目で待つ)

最後の行にデータが入力されている場合は、15〜17行目を処理します。
15行目で、「増やせません」というメッセージの表示
16行目で、レコードセットを閉じます。
17行目で、プロシージャから出ます。

19行目からは、挿入処理です
今19行目に居ますから、そこから下に下がっていきながら、行番号を1つプラスしたものに変更していきます。
25〜27行目は、1行目で挿入処理をされた場合のエラー回避処理で、ループから出ています。

29行目からは、行番号を21と登録しているレコードを空のデータを代入して、挿入された行を作って、レコードを上書き保存しています。
42行目で、全レコードの表示
43行目で、明細サブにコントロールを移動(念のため)
44行目で、レコードの挿入した行に移動しています



−削除−den_ins()

Public Function den_del()

 1 Dim dbs As Database
 2 Dim rst_1 As Recordset

 3 Dim gyou As Integer

 4 Set dbs = CurrentDb
 5 Set rst_1 = dbs.OpenRecordset("to請求明細", dbOpenTable)

 6  rst_1.Index = "行番号"
 7  rst_1.Seek "=", gy
 8  rst_1.Edit
 9  rst_1!行番号 = gmax + 1
10  rst_1.Update
11  rst_1.MoveNext

12  Do Until rst_1!行番号 = gmax + 1
13   gyou = rst_1!行番号 - 1
14   rst_1.Edit
15   rst_1!行番号 = gyou
16   rst_1.Update
17   rst_1.MoveNext
18  Loop

19   rst_1.Edit
20   rst_1!行番号 = gmax
21   rst_1!商品番号 = ""
22   rst_1!商品名 = ""
23   rst_1!数量 = 0
24   rst_1!単位 = ""
25   rst_1!単価 = 0
26   rst_1!金額 = 0
27   rst_1!消費税 = 0
28   rst_1!明細摘要 = ""
29   rst_1.Update
30   rst_1.Close

31 DoCmd.ShowAllRecords
32 DoCmd.GoToControl "明細サブ"
33 DoCmd.GoToRecord , , acGoTo, gy

End Function


6行目で、行番号をインデックスに指定しています
7行目でボタンが押された行にSeek(検索移動)でレコード移動します(念のため)
8〜10行目は削除される行の行番号を21にして上書き保存します。
11行目で、次のレコードに移動しています。
12〜18行目は、ループで20今いるレコードから20行目までの行番号をマイナス1しています。
19〜29行目で、今行番号21にレコードが移動しているはずですから、ここを行番号20として、空データを書き込んでいます。
30行目で、レコードセットを閉じます。

31行目で、全レコードの表示
32行目で、明細サブにコントロールを移動(念のため)
33行目で、レコードの挿入した行に移動しています