Access実践入門 TOPへ
 ■ マイクロソフトアクセス、伝票入力−1(伝票入力のデータ操作)
テーブル

・データを2つに分ける
伝票データは「ta請求」と「ta請求明細」の2つのデータを用意しています。
「ta請求」は、伝票の合計金額を保存します。
請求一覧表は、このデータだけで作成できます。


「ta請求明細」は、伝票の明細を保存します。
明細を必要とする、請求書、元帳等で、必要です。


・実際の入力には、作業データを使う。
伝票入力画面では、「ta請求」「ta請求明細」は直接使いません。
作業テーブルを使って編集し、データのチェックをした後、登録することになります。
明細データは何行入力されるか、わかりませんし、直接データを編集していて、データにトラブルが発生すると困りますので。
「to請求」と「to請求明細」が作業用のテーブルです。


伝票一覧画面

マスター登録と同じような構成です。
一覧表が、日付の降順に表示されて、新規登録ボタンで新規の伝票、編集ボタンで、入力済み伝票の編集画面へと移ります。
納品書ボタンは、後述します。
検索、初期画面は、伝票が多くなってきた時に、日付と得意先で抽出出来るようにしています。

伝票入力画面

「fo伝票入力」のデザインを見てください。
単票入力になっています。
下に、サブフォームが貼ってあります。
日付とか、得意先の情報をメインのフォームで登録して、明細データを、下のサブフォームで入力します。

サブフォームは大変便利な機能です。
別のフォームですから、レコードソースも別になりますので、サブフォームを使えば、1つのフォームでいろんなテーブルのデータを編集する事ができます。


・伝票入力の流れ

「新規登録」の場合は、「to請求明細」に空白行を20行作り、それをレコードソースにして、編集し、登録ボタンが押されたら、入力された行数だけ「ta請求」と「ta請求明細」にデータが追加されます。

「編集」の場合は、「to請求明細」に明細データがコピーされて、20行に足りない行数だけ空白行を作り、それをレコードソースにして、編集し、登録ボタンが押されたら、「ta請求」と「ta請求明細」に入力された行数だけ追加されます。その後、元の「ta請求」と「ta請求明細」が削除されます。

新規登録の前処理

伝票一覧表で、[新規登録]ボタンがクリックされると、マクロ「ma伝票」の「新規入力」が呼び出されます。
「ma伝票」のデザインを見てください。

まず、削除クエリー「quto削除請求」と「quto削除請求明細」で、作業テーブルを空にします。
次にモジュール「den_1()」が呼び出されます。
「to請求明細」に20行の空データを作ります。

モジュール「Module」の「den_1()」を説明します

Public Function den_1()

 1 Dim dbs As Database
 2 Dim rst_1 As Recordset
 3 Dim i As Integer

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

 6  i = 1
 7  Do Until i = gmax + 1
 8    rst_1.AddNew
 9    rst_1!行番号 = i
10    rst_1!商品番号 = ""
11    rst_1!商品名 = ""
12    rst_1!数量 = 0
13    rst_1!単位 = ""
14    rst_1!単価 = 0
15    rst_1!金額 = 0
16    rst_1!消費税 = 0
17    rst_1!明細摘要 = ""
18    rst_1.Update
19    i = i + 1
20  Loop

21  rst_1.Close

22  inpmode = 0

End Function

1〜3行目は、変数の宣言です。
3行目のiには1〜20までの行番号が入ります。

4,5行目はテーブルを空けるためのお決まりの形です

6行目で、iの初期値を1にしています。
7行目のgmaxは、モジュールの先頭でプログラム全体から参照できる変数として宣言しています。その値は、「fo伝票一覧」の「読み込み時」に20を代入しています。
Do Until i = gmax + 1は iの値が20+1、すなわち21になるまで、20行目のLoopまでの処理を繰り返すという命令です。20で通過して、19行目で21になった時に、21行目に進みます。
8〜18行目では、数値項目には、ゼロを文字列項目には、""(ダブルクォーテーション2つで空のデータ)を代入しています。
19行目で1レコード追加しています。
20行目で、iを1つ増やしています。
9行目の行番号だけは、1〜20の数字が入ります。
22行目で入力モードを新規の0にしています。

その後、「fo伝票入力」を開いて、コントロールを[請求日]に移動して、新規の伝票入力の状態になります。

編集の前処理

伝票一覧表で、[編集]ボタンがクリックされると、マクロ「ma伝票」の「編集」が呼び出されます。
「ma伝票」のデザインを見てください。

まず、削除クエリー「quto削除請求」と「quto削除請求明細」で、作業テーブルを空にします。
次に、「quto追加請求」と「quto追加請求明細」で、一覧表で選ばれた、入力済みの「ta請求」と「ta請求明細」のデータを作業テーブルへコピーします。

次にモジュール「den_4()」が呼び出されます。
「to請求明細」が20行のデータになるように、足りない行数の空データを追加します。

モジュール「Module」の「den_4()」を説明します

Public Function den_4()

 1 Dim dbs As Database
 2 Dim rst_1 As Recordset

 3 Dim lastgy As Integer
 4 Dim t As Integer

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

 7  t = 0
 8  rst_1.Index = "行番号"
 9  rst_1.MoveLast
10  lastgy = rst_1!行番号

11  t = lastgy + 1
12   Do Until t = gmax + 1
13    rst_1.AddNew
14    rst_1!行番号 = t
15    rst_1!商品番号 = ""
16    rst_1!商品名 = ""
17    rst_1!数量 = 0
18    rst_1!単位 = ""
19    rst_1!単価 = 0
20    rst_1!金額 = 0
21    rst_1!消費税 = 0
22    rst_1!明細摘要 = ""
23    rst_1.Update
24    t = t + 1
25   Loop

26  rst_1.Close

27  inpmode = 1

End Function


1〜4行目は、変数の宣言です。
3行目のlastgyは入力済みデータの行数です。
4行目のtは空白行の行番号の数値が入ります。

5,6行目はテーブルを空けるためのお決まりの形です

7行目は、tの変数をゼロで初期化しています。
8行目は、開くテーブルのインデックスを指定しています。
「to請求明細」のデザインで、インデックスを表示してみてください、そこに登録されているインデックス名が、ここで使用できます。

9行目で、行番号をインデックスとした最後のレコードに移動しています。
10行目で、最後の行番号をlastgyに代入します。

11行目からは、新規の時と同じようにして、残りの20行の空データを追加しています。

27行目で入力モードを編集の1にしています。

その後、「fo伝票入力」を開いて、編集入力の状態になります。

伝票登録時の処理

伝票入力で[登録]ボタンが押されると、作業テーブルから「ta請求」と「ta請求明細」にデータを登録する処理をします。

「ma伝票」のデザインを見てください。
「新規登録」と「編集登録」があります。
違いは、編集登録の場合は、元のデータの削除処理が余分にあるだけです。

@閉じる(伝票入力フォームを閉じます)
Aクエリーを開く(「qu請求追加」)
Bプロシージャの実行(den_2()の実行)
Cプロシージャの実行(den_3()の実行)
Dクエリーを開く(「qu請求明細追加」)
Eクエリーを開く(「qu請求明細削除」)・・・編集登録のみ
Fクエリーを開く(「qu請求削除」)・・・編集登録のみ
Gプロシージャの実行(den_5()の実行)
H全レコードの表示


順番に説明します。

@でまず、「fo伝票入力」を閉じます。
Aで「to請求」から「ta請求」にデータを追加します。

Bのden_2の内容は、次のようになっています。

Public Function den_2()

 1 Dim dbs As Database
 2 Dim rst_1 As Recordset
 3 Dim rst_2 As Recordset

 4 Set dbs = CurrentDb
 5 Set rst_1 = dbs.OpenRecordset("qu請求最後", dbOpenDynaset)
 6 Set rst_2 = dbs.OpenRecordset("ta会社情報", dbOpenDynaset)

 7  rst_1.MoveFirst
 8  denid = rst_1!ID
 9  denban = rst_1!伝票番号

10  If inpmode = 0 Then
11  rst_2.Edit
12  rst_2!伝票番号 = denban + 1
13  rst_2.Update
14  End If

15 rst_1.Close
16 rst_2.Close

End Function

1〜3行目は、変数の宣言です。
4〜6行目はお決まりの形です。クエリーの場合は、dbOpenDynasetです。
dbOpenDynasetの場合は、インデックスの指定はありません、クエリーで順番をつけておきます。「qu請求最後」はIDの降順に並べてあります
「ta会社情報」はリンクテーブルなので, dbOpenTableで開くことはできません。

7行目で一番最初のレコードに移動しています。ここの一番最初のデータは、IDの最大値ですから、先程「qu請求追加」で登録されたレコードのはずです。
8行目でモジュールの先頭で宣言している、変数denidにID番号を代入します。
9行目では、同じくdenbanに伝票番号を代入しています。

10〜14行目は、新規登録の場合には、伝票番号に1をプラスして、会社情報の次回の伝票番号として、「ta会社情報」のレコードを更新しています。
「ts会社情報」はレコードが1つしかないので、編集(Edit)で上書き(Update)すれば、書き換えられます。



Cのden_3の内容は、次のようになっています。

Public Function den_3()

 1 Dim dbs As Database
 2 Dim rst_1 As Recordset, rst_2 As Recordset

 3 Dim gyou As Integer
 4 Dim i As Integer

 5 DoCmd.OpenQuery "quto削除請求明細登録"

 6 Set dbs = CurrentDb
 7 Set rst_1 = dbs.OpenRecordset("to請求明細", dbOpenTable)
 8 Set rst_2 = dbs.OpenRecordset("to請求明細登録", dbOpenTable)

 9  rst_1.Index = "行番号"
10  rst_1.MoveLast
11  Do Until rst_1.BOF
12   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
13    rst_1.MovePrevious
14   Else
15    gyou = rst_1!行番号
16    Exit Do
17   End If
18  Loop

19 rst_1.MoveFirst
20 For i = 1 To gyou
21 rst_2.AddNew
22 rst_2!伝番ID = denid
23 rst_2!行番号 = rst_1!行番号
24 rst_2!商品番号 = rst_1!商品番号
25 rst_2!商品名 = rst_1!商品名
26 rst_2!数量 = rst_1!数量
27 rst_2!単位 = rst_1!単位
28 rst_2!単価 = rst_1!単価
29 rst_2!金額 = rst_1!金額
30 rst_2!消費税 = rst_1!消費税
31 rst_2!明細摘要 = rst_1!明細摘要
32 rst_2.Update
33 rst_1.MoveNext
34 Next i

35 rst_1.Close
36 rst_2.Close

End Function

1〜4行目は、変数の宣言です。
5行目では、登録するための作業テーブル「to請求明細登録」の全レコードを削除する削除クエリーを実行しています。
「to請求明細登録」を通さないで、直接「ta請求明細」に書くこともできますが、ここでは作業テーブルをまず作って、追加クエリーで登録しています。

6〜8行目はお決まりの形です。
9〜18行目は、何行伝票入力されたかを調べています。
9行目で、インデックスを行番号にしています。
10行目で、行番号の最後のレコードに移動しています。
11行目は、レコードの先頭になるまで、17行目までの処理を繰り返すということになります。
実際は20行目から下に下がって見ていくことになります。
12行目の条件式は、何も入力されていない場合は、13行目に行って、1つ前のレコードに移動します。もしデータが入力されていれば、15行目に行って、gyouに行番号を代入して、16行目で、ループ(繰り返しの構文)から抜けます。
Exit Doは先頭の1行目まで移動しないで、ループから抜けるという命令です。

19行目からは、1行目から今見つけた最後の行までの、明細データを「to請求明細登録」に行数分だけコピー(追加)しています。


Dでは、作業テーブル「to請求明細登録」を「ta請求明細」に追加クエリーで追加しています。

EとFは編集登録の場合のみです。
呼び出す前のデータを削除しています。
明細から先に削除しないと、リレーションのエラーが出て、削除できません。


Gのden_5の内容は、次のようになっています。

Public Function den_5()

Form_fo伝票一覧.RecordSource = "qu伝票一覧"

End Function

データに変更がありましたし、検索等でレコードソースが変わっているかもしれませんので、最初のレコードソースに戻しておきます。

Hで全レコードの表示で、全てのレコードを表示しておきます