マスター・メンテナンスと伝票入力処理

Access 2000 で学ぶ業務アプリケーション開発―経理システムを作ってみよう―
第3回
マスター・メンテナンスと
伝票入力処理
金宏 和實
経理システムを題材に,Access 2000による業務アプリケーシ
ョンの開発に必要な知識やテクニックを学んでいこう,という
同じフィールドを主キーとする
テーブルのメンテナンス
この連載。今回で第 3回です。第 1回では,経理システムに必
要なテーブルを紹介しマスター・テーブルを作成しました(表
1)
。第 2回では,マスター・メンテナンス処理について説明し
科目マスター(M_科目,表 2)は勘定科目の名前やプロパ
ました。前回までの内容を含むmdbファイルは,本誌 Webサイ
ティを記録するテーブル,科目残高マスター(M_科目残高,
ト(http://software.nikkeibp.co.jp/)からダウンロードできます。
表 3)は各科目の残高を記録するテーブルです。どちらも主キ
ところで,第 1回でマスター・テーブルの関連図を紹介して
ーは科目 CD(科目コード)で,この二つのテーブルの情報を
おきながら,テーブル間のリレーションシップ* 1 をまだ作成し
使って,貸借対照表や損益計算書を作成するわけです。
「わざ
ていません。続けて読んでいる読者の方は「どうしてRDB(リ
わざテーブルを二つに分けることないのに」と思うかもしれま
レーショナル・データベース)なのにリレーションシップを定
せんが,実際の企業では貸借対照表や損益計算書を支店や部
義しないのだ。こいつ本当はデータベースがわかってないんじ
門ごとに作成します。科目残高と科目は分けておいたほうが便
ゃないか?」と疑念を抱かれているかもしれませんね。実は筆
利でしょう。ただし二つのテーブルに分けたことで,システム
者,トリガー* 2 の使えないAccessのmdbファイルでは,リレー
を作る側からするとやや面倒な問題が発生します。どういうこ
ションシップはあまり役に立たないと考えています。その理由
とか分かりますか?
を説明するのは後のお楽しみ。まずは,科目マスターと科目残
科目マスターに新しい科目を登録し,続いてその科目の残高
高マスターの関係について考えてみましょう。
を科目残高マスターに登録する処理を考えてみましょう。科目
マスターをメンテナンスする画面(F_科目 _保守)は
前回作成しましたね(図 1)
。ユーザーは,新しい
表 1●経理システムで作成するマスター・テーブル
名前
テーブル名
目的
科目マスター
M_ 科目
科目の定義や属性を格納
ます。しかし,科目マスターと科目残高マスターは
相手先マスター
M_ 相手先
相手先コードと名称を格納
別々のテーブルです。科目残高マスターを保守する
摘要マスター
M_ 摘要
摘要コードと名称を格納
画面を開いても,新しい科目 CDが表示されるわけ
消費税率マスター
M_ 消費税率
消費税率や適用開始日などを格納
ではありません。ユーザーは,科目マスターの保守
基本情報マスター
M_ 基本情報
会社名や年度情報などを格納
の後に,もう一度,新しい科目 CDを入力しなけれ
科目残高マスター
M_ 科目残高
科目別の残高情報を格納
相手先別残高マスター
M_ 相手先別残高
相手先別科目別の残高情報を格納
金宏 和實 (かねひろ かずみ)
通産省の情報処理技術者資格が改定される。筆者は第一種の資格を持
っているものの,それほど恩恵にあずかった記憶はない。しかし人間
というのは欲深いもので,古い資格がなくなると聞くと未練が残る。
どうせだったら,第一種=ソフトウエア開発技術者と認定してくれれ
ばいいのに…。
「今,試験を受けて合格できる自信がある?」と問わ
れると,きっぱりとこう答えるしかない。
「ありません!」
166
H 2000 年 11 月号
「科目 CD」と「科目名」などのプロパティを入力し
ばならないわけです。このとき,
「再度,科目 CDを
入力してください」なんてユーザーに言えるでしょ
* 1 リレーションシップは,リレーショ
ナル・ データベース(RDB)におい
て,テーブルとテーブルの関係を定義
したもの。
* 2 トリガーはテーブルに対するイベン
ト(レコードの挿入/削除/変更)をひ
きがね(Trigger)として実行されるプ
ロ グ ラ ム 。 SQL Serverや Oracle,
MSDE( Microsoft Database Engine)
などで利用できるが,Accessの MDB
形式のデータベースでは使えない。
マスター・メンテナンスと伝 票 入 力 処 理
表 2●科目マスターのテーブル構造
うか。私がユーザーだったらそんなメッセージは見たくありま
NO
名称
データ型
サイズ
備考
せん。そこで,ユーザーが同じコードを 2度登録しなくても済
1
科目 CD
テキスト型
4
主キー
むように,科目マスターに登録された科目 CDを科目残高マス
2
科目名
テキスト型
20
ター(M_科目残高)に簡単に追加できるようにしたいと思い
3
BSPL 区分
数値型
長整数型
ます。
4
借方貸方区分
数値型
長整数型
まず,図 1のフォーム「F_科目 _保守」にボタンを追加しま
5
相手先有無
数値型
長整数型
しょう(図 2)
。このボタンが押されたら,科目 CDを科目残高
6
税計算区分
数値型
長整数型
マスターに追加するようにプログラミングします。科目残高マ
7
税区分
数値型
長整数型
スターの各金額項目のデフォルト値は 0に設定してあるので,
科目 CDを追加するだけで科目残高マスターに新しいレコード
表 3●科目残高マスターのテーブル構造
が作成できます。ただ,一つ注意すべきことがあります。シス
NO
名称
データ型
サイズ
備考
テム導入時なら科目マスターを登録し終わった時点でこのボタ
1
科目 CD
テキスト型
4
主キー
ンを押し,すべての科目 CDを科目残高マスターに追加すれば
2
前期末残高
通貨型
いいのですが,運用を開始した後で科目を追加した場合はどう
3
当月借方
通貨型
でしょう? 科目残高マスターに存在しない,つまり新しく追加
4
当月貸方
通貨型
した科目 CDだけを追加する必要がありますね。これは,なか
5
当年借方
通貨型
なか難しそうです。もちろん,グリグリとプログラムを書けば
6
当年貸方
通貨型
できないことはないでしょうが,レコードを全件なめるような
効率の悪い処理になってしまいそうです。でもご安心を。Access
には「不一致クエリー」ウィザードという機能があります。
不一致クエリー・ウィザードを使って,科目マスターに存在
するものの,科目残高マスターには存在しない科目 CDを選択
ワンポイント・レッスン
するクエリーを作りましょう。まず,不一致クエリー・ウィザ
不一致クエリーを知っていますか?
ードを起動して,
「M_科目」
「M_科目残高」の二つのテーブル
性格の不一致はずっと離婚原因の NO.1です。
「性格の不一
を選択し,どのフィールドの不一致を見るのかを設定します
致」――あまりにも抽象的な表現ですね。でも,Accessの不一
(図 4の(1))
。ここは当然「科目 CD」とします。表示するフィ
致クエリーはもっと明確で
す。二つのテーブルからそ
れぞれフィールドを持って
図 1●フォーム「F_ 科目 _保守」
。前回作成した画面
図 2●フォーム「F_ 科目 _保守」に新たにボタンを
追加
きて,値が一致しないレコ
ードを抜き出す。それが不
一 致 クエリーの機 能 です。
不一致クエリーは,Access
の「クエリーの新 規 作 成 」
で作成します(図 3)
。
H 2000 年 11 月号
167
Access 2000で学ぶ業務アプリケーション開発
― 経理システムを作ってみよう―
図 3●不一致クエリー・ウィザードを選択
ールドにも科
M_科目からM_科目残高に向けて矢印が伸びていて,M_科目
目 CD を選 択
残高の科目 CDの抽出条件が「Is Null」と記述されていること
します(2)。
がわかります(3)* 3。これが不一致クエリーの種明かしです。結
作成したクエ
合したら,相手がいなかった(Is Null)わけですね。ここまで
リーをデザイ
で不一致のレコードが検出できるクエリーができました。
ン・ビューで
でもこれだけでは,科目残高マスターに新しい科目 CDが追
表示させてみ
加されるわけではありません。この選択クエリーを追加クエリ
ましょう。
ーに変更し,M_科目の科目 CDをM_科目残高の科目 CDに追
加するように変更しましょう(4)* 4。こ
うして作成したクエリーの SQL * 5 文は
図 4●不一致クエリーを使って,科目残高マスターに科目 CD を追加するSQL(INSERT 文)を作成する
までの流れ
(5)のようになります。科目マスターと
科目残高マスターが LEFT JOIN(左外
部結合)* 6 されていますね。後は,図 2
で追加したボタンに,(5)の SQL文を実
行する処理を実装すればいいわけです。
で も ,SQL を 実 行 さ せ る に は VBA
(Visual Basic for Applications)のコード
をどう記述すればいいでしょうか。それ
(1)関連付けるフィールドをどちらも
科目 CD とする
を知るためには,ADO(ActiveX Data Ob(5)LEFT JOIN(左外部結合)を使った SQL 文
jects)* 7 について少し学んでおく必要が
図 5● Access のプログラムから見た ADO
の位置付け
Accessのプログラム
ADO
(2)表示するフィールドも科目 CD と
する
OLE DBプロバイダ
(4)M_ 科目の科目 CD を M_ 科目残高
の科目 CD に追加して,「追加ク
エリー」に変更
データベース
ADO:ActiveX Data Objects
* 3 Nullは0とも空白とも異なる値で,
(3)M_ 科目残高の科目 CD の抽出条件
が Is Null に注目
168
H 2000 年 11 月号
データが何も入っていないことを表
す。
* 4 追加クエリーに変更するには,右
クリックで[クエリーの種類]-[追加]を
選択する。
マスター・メンテナンスと伝 票 入 力 処 理
際にコードを書きながら覚えていきましょう。
あります。
ワンポイント・レッスン
まず,フォーム「F_ 科 目 _ 保 守 」のモジュール宣 言 部 に,
ADO の概要をつかむ
ADOオブジェクトを定義します(リスト 1)* 10。cn(Connec-
Visual Basic(VB)や VBAでデータベース・プログラミング
tion オ ブ ジ ェ ク ト )と rs(Recordset オ ブ ジ ェ ク ト ),cmd
を行う場合,ミドルウエアを利用するのが一般的です。Access
(Commandオブジェクト)のほか,SQL文を編集するための変
では,MDB 形式(拡張子 mdb)のデータベースに接続するミ
数 strSQLを定義しています。
Objects)* 8
続いて,科目残高マスターに科目 CDを追加する処理を,図
を 利 用 し て き ま し た 。 Access 2000で は DAOに 加 え , 米
2で追加したボタン(btn残高マスター)をクリックした時のイ
ドルウエアとして,これまで DAO(Data Access
Microsoftが推奨しているADO を新たに利用できます。
ベントに記述します(リスト2)
。コードの中身を説明しましょ
ADO は,OLE DBプロバイダを通してデータベースにアクセ
う。(1)でSQL文を組み立てています。クエリーのSQLビューに
スします(図 5)
。対象となるデータベースに合わせて,MDB
表示されたSQL文をコピーして編集すれば簡単です。(2)では現
Server用,Oracle用,ODBC * 9 データベース用など
在開いているAccessアプリケーションが持っている接続情報を
とOLE DBプロバイダを指定します。OLE DBプロバイダがデー
cnに渡しています。通常 ADOを使う場合は,
「データベースの
用,SQL
タベースの違いを吸収してくれるの
で,データベースに合わせてプログ
図 6● ADO のオブジェクトの階層構造
ラムを書 き換 える必 要 がないのが
ADOを使ったときの最大のメリット
データベースへの接続情報を保持
Connection
です。
ADOのオブジェクトを階層構造に
コレクション
Errors
すると図 6のようになります。ちょ
DAO と比 較 してみましょう。
データ・アクセスに関するエラー情報を保持
Error
っと見るとなかなか難しそうですが,
データソースに対して実行するコマンドを保持
Command
Connection オブジェクトは DAO の
WorkSpaceオブジェクト,Record-
コレクション
Parameters
setオブジェクトはそのままRecordParameter
setオブジェクト,Commandオブジ
パラメータ・クエリーのパラメータを保持
ェクトはDAOのExecuteメソッドを
オブジェクト化したもの――ちょっ
と乱暴ですが,こんなイメージでと
らえてみれば分かりやすくなると思
Recordset
テーブルから取得したレコードセット全体または
コマンドの実行によって返されたレコードを保持
Fields
います。DAOについて知識のない人
コレクション
Field
データの列情報を保持
は,こんなオブジェクトがあるんだ
な,と目を通すだけで結構です。実
*5
SQLは,1970年代に開発された, 合 ( INNER JOIN), 左 外 部 結 合
,右外部結合(RIGHT
リレーショナル・データベース(RDB) (LEFT JOIN)
JOIN)の 3 種 類 の結 合 方 法 がある。
を操作するための言語。現在は,ISO
等結合では,双方のテーブルから結
(国際標準化機構)や ANSI(米国規
合に指定したフィールドに同じ値を
格協会)が標準化している。
* 6 テーブルの結合(JOIN)には,等結
持つレコードが選択される。左(右)
外部結合では,片方のテーブルの全
レコードともう一方のテーブルの結
合されたレコードが選択される。
* 7 ADO(ActiveX Data Objects)は,
米 Microsoftが開発したデータ・アク
セス用コンポーネント。同社の提唱
する汎用データ・アクセス・インタ
フェース仕様 OLE DBをベースにして
いる。RDBだけでなく,スプレッド
シートや電子メールなどのデータ形
式も操作できる。
H 2000 年 11 月号
169
Access 2000で学ぶ業務アプリケーション開発
― 経理システムを作ってみよう―
場 所 」や「OLE DBプロバイダ」のコードを記 述 しますが,
目マスターには存在して,科目残高マスターに存在しない科目
MDBにリンクされているテーブルを扱う場合は,その必要があ
を登録できるようになりました。
りません。(3)でCommandオブジェクトを生成し,(4)でプロパ
ティをセットしています。cmd.CommandType = adCmdTextは,
リレーションシップを作成しなかった理由(ワケ)
次の行で CommandTextプロパティに渡す文字列の種類が SQL
さて,冒頭で「トリガーの使えないmdbファイルでは,リレ
文であることを示します。(5)でSQL文を実行します。これで科
ーションシップはあまり役に立たない」と言い切った理由を説
明しましょう。
リスト 1●フォーム「F_ 科目 _保守」のモジュール宣言部
Accessは,リレーショナル・データベースとしての機能をい
くつか実装しています。例えば,関連する二つのテーブルで,
Option Explicit
Const ctFormName_M = "F_ 科目 _ 保守"
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim cmd As ADODB.Command
Dim strSQL As String
一方にはレコードが存在するのに,もう一方のレコードを削除
しようとすると警告を発する「参照整合性」や,別のテーブル
の関連するレコードを同時に削除する「連鎖削除」などの機能
です。しかし,理論と実務の間には溝があります。科目マスタ
ーのレコード削除処理を考えてみましょう。
「科目残高マスタ
ーに存在する科目 CDは,科目マスターから削除しては
いけない」――これだけのルールなら参照整合性を設
リスト 2●科目残高マスターに科目 CD を追加するコード
定すれば十分です。しかし,経理の勘定科目の中には,
毎年必ず使う科目と特定の年度にだけ使う科目があり
Private Sub btn 残高マスター _Click()
If MsgBox("データを複写しますか", (vbYesNo + _
vbDefaultButton2 + vbExclamation), "複写") = _
vbNo Then
Exit Sub
End If
ます。
「過去に一度使ったけど,現在は必要ない」とい
う科目もあります。また一般的には,
「科目残高の金額
が0円だったら削除してもよい」が業務ルールと言えま
す。つまり,単純なリレーションシップの設定だけで
strSQL
strSQL
strSQL
strSQL
strSQL
=
=
=
=
=
"INSERT INTO M_ 科目残高 (科目 CD)"
strSQL & " SELECT M_ 科目.科目 CD"
strSQL & " FROM M_ 科目 LEFT JOIN M_ 科目残高"
strSQL & " ON M_ 科目.科目 CD = M_ 科目残高.科目 CD"
strSQL & " WHERE ((M_ 科目残高.科目 CD) Is Null)"
Set cn = Application.CurrentProject.Connection
Set cmd = New ADODB.Command
cmd.ActiveConnection = cn
cmd.CommandType = adCmdText
cmd.CommandText = strSQL
cmd.Execute
DAO( Data Access Objects) は ,
データベース処理プログラムJetエン
ジンを通して,主に Access形式(拡
張子 mdb)のファイルに接続するデ
ータ・アクセス用コンポーネント。
* 9 ODBC(Open Database Connectiv-
170
H 2000 年 11 月号
め今回の経理システムでは,リレーションシップを使
わず,アプリケーション・プログラムの中でデータ処
(2)
(3)
(4)
理を実装することにしたのです。
ではリレーションシップなしにどうやって削除処理
を実装すべきか。削除処理のプログラムを見ておきま
しょう。科目マスターで削除ボタンがクリックされた
(5)
ら,選択された科目の各金額が 0円であることを確認
して,科目マスターと科目残高マスターのレコードを
Set cmd = Nothing
cn.Close
Set cn = Nothing
MsgBox "複写しました。"
End Sub
*8
は現実のデータ処理を定義できないわけです。このた
(1)
削除するプログラムです(リスト3)
。(1)で,指定され
た科目 CDのレコードを科目残高マスターから削除する
SQL文を組み立てています。(2)でレコードセットを作
ity)は,ベンダー間でデータベース
の仕様が異なっていても,アプリケ
ーションからそれを意識せずに接続/
操作できるようにする API仕様。米
Microsoftが提唱し,事実上の業界標
準になっている。
* 10 フォーム「F_科目 _保守」をデザ
イン・ビューで開き,[表示]-[コード]
とすると,VBAのコード・エディタ
がオープンする。
*11 ロックタイプの既定値は,adLockReadOnly(読み取り専用)
。作成し
たレコードセットを更新するために
は,adLockOptimistic(共 有 的 ロッ
ク)か,adLockPessimistic(排 他 的
ロック)を指定する必要がある。共
有的ロックと排他的ロックの違いは
ロックをかけるタイミングであり,排
マスター・メンテナンスと伝 票 入 力 処 理
成します。削除する必要があるので,ロックタイ
プ* 11 に adLockOptimisticを指定しています。カー
ソルタイプ* 12 にはadOpenForwardOnlyを指定して
います。 (3)で各フィールドの金額を調べます。フ
ィールドに金額が入っていた場合,blnZflagにTrue
を代入します。(4)で,blnZflagが Trueのとき,金
額が入力されていることを表示し,blnKflagにFalse
(初期値は True)を代入します。(5)で金額がすべ
て0のときは科目残高マスターの該当レコードを削
除します。(6)でblnKflagがTrueの場合,科目マス
ターの該当レコードを削除します。
主キーに連番を
付ける方法について考える
ではいよいよ今回の目玉である,伝票入力処理
について考えてみましょう。仕訳伝票入力処理を
作成するには,仕訳伝票データを保存するテーブ
ルが必要です。連載の第 1回でも説明しましたが,
伝票のヘッダー情報は「T_仕訳」
,明細データは
「T_仕訳明細」というテーブルに保存します。
ここで,1枚の伝票をユニーク(一意)に識別す
るための主キー* 13「伝票番号」に注目してくださ
い。伝票番号を採番する方法はいろいろ考えられ
ます。まず,(1)「オートナンバー型* 14 を使う」方
法。この方法では,自動的に重複しない値(連番)
が伝票番号として振られます。伝票番号の採番を
Accessに任せられるので便利です。しかし,伝票
番号を人間がコントロールしにくい方法とも言え
ます。
リスト 3●科目マスターと科目残高マスターから科目 CD を削除するコード
Private Sub btn 削除 _Click()
Dim strMsg As String
Dim blnZflag As Boolean, blnKflag As Boolean
Dim i As Integer
If MsgBox("データを削除しますか", (vbYesNo + _
vbDefaultButton2 + vbInformation), "削除") = vbNo Then
Exit Sub
End If
Me.Undo
DoCmd.SetWarnings False
strSQL = "SELECT 前期末残高,当月借方,当月貸方,当年借方,当年貸方"
strSQL = strSQL & " FROM M_ 科目残高 "
strSQL = strSQL & " WHERE 科目 CD = " & "'" & [科目 CD] & "'"
Set cn = Application.CurrentProject.Connection
Set rs = New ADODB.Recordset
rs.Open strSQL, cn, adOpenForwardOnly, adLockOptimistic
blnZflag = False
blnKflag = True
If Not rs.BOF Then
For i = 0 To 4
If rs.Fields(i).Value <> 0 Then
blnZflag = True
End If
Next i
If blnZflag Then
strMsg = "科目の残高が入力されています。" & vbCrLf
strMsg = strMsg & "削除できません。"
MsgBox strMsg
blnKflag = False
Else
rs.Delete
End If
End If
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
If blnKflag Then
DoCmd.RunCommand acCmdDeleteRecord
End If
DoCmd.SetWarnings True
End Sub
(1)
(2)
(3)
(4)
(5)
(6)
次に(2)「仕訳伝票データの最大伝票番号に1を
足して伝票番号を採番する」方法。具体的には
AccessのDlookup関数* 15 で伝票番号の最大値を求め,プラス1
ション開 発 では使 えない点 です。複 数 のクライアントが,
する方法です。欠点は伝票データの件数が増えるとレスポンス
Dlookup関数で同時に伝票番号の最大値を取得して1を足すと,
が悪くなる点と,クライアント/サーバー(C/S)のアプリケー
同じ番号を採用してしまう可能性があるからです。
他的ロックはレコードの編集時点で
ロックを行い,共有的ロックは更新
時点でロックを行う。スタンドアロ
ンでは特に両者の違いに留意する必
要はない。
* 12 カーソルタイプは,レコードのス
クロール方法や,他のユーザーの行
った更新の参照可能範囲をコントー
ルする。adOpenForwardOnly(前方
スクロール・カーソル)
,adOpenStatic(静的カーソル)
,adOpenDynamic
(動的カーソル)
,adOpenKeyset(キ
ーセットカーソル)が指定できる。
* 13 主キーは,テーブルの行(レコー
ド)をユニークに判別するためのフ
ィールド。
* 14 オートナンバー型は,自動的に重
複 し な い 値 (連 番 )を 発 番 す る
Accessのデータ型。
H 2000 年 11 月号
171
Access 2000で学ぶ業務アプリケーション開発
― 経理システムを作ってみよう―
(3)は「採番用のテーブルに最新の伝票番号を記録し,プラ
ス1して伝票番号を採番する」方法。今回はこの方法を用いま
ワンポイント・レッスン
正規化と正規化崩し
す。この方法なら,将来アプリケーションをC/Sシステムにア
リレーショナル・データベース理論の中核に「正規化」があ
ップサイジングする時でも,ロジックを見直す必要はありませ
ります。正規化っていったい何でしょう? 詳細な説明は省い
ん。複数ユーザーがサーバーにアクセスしてきても,採番用の
てざくっと言ってしまうと,
「同じ内容のフィールドを,データ
レコードを早い者勝ちで握っちゃえばいいからです。
「今日は
ベース中のあちこちのテーブルにばらまかないこと」です。例
握るか?」なんてお父さん,ゴルフの話じゃありません。新し
えば,得意先マスターに得意先の名称を記憶する「得意先名」
い伝票番号の取得時に採番用テーブルのレコードを握る(ロッ
というフィールドがあるとします。伝票を印刷する時に便利だ
クする)ことにより,伝票番号が重複する危険性を排除できま
からという理由で,売上伝票テーブルにも「得意先名」フィー
ルドを持たせると,得意先名が変更になった時(得意先マスタ
す。
では,採番用のテーブルを見てみましょう(表 4)
。テーブル
ーの得意先名を修正した時)に売上伝票テーブルの得意先名
構造は,いたってシンプルです。例えば,伝票番号を年度ごと
も変更しなくてはなりません。これではデータの整合性を維持
の連番にしたい場合は,年度フィールドを追加し,主キーに設
するのが面倒ですよね。そこでテーブルを設計するときは「正
定します。月ごとに採番したい場合は年月フィールドを追加し
規化」をするわけです。
でも,いついかなるときも「正規化」しなければならない,
ます。今回の例は最も単純な例です。
というわけではありません。現実のシステム開発では,正規化
正規化はどこまでやるべきか
の結果,SQL 文が複雑になりすぎてパフォーマンスが出にくい
T_仕訳とT_仕訳明細を見てみましょう(表 5)
。T_仕訳(a)の
とか,プログラムが煩雑になりすぎるなどの弊害が指摘される
フィールドは伝票番号と伝票日付だけです。これもまた申し訳
からです。そこで,まずラフなテーブル構造のイメージを描い
ないくらいシンプルです。実際にアプリケーションを利用する
てから正規化に従ってムダなフィールドを排除していき,その
場面を想定すると,
「支店別や部門別に伝票を入力する」など
後で現実に合わせて,あえて重複するフィールドを追加する,
のケースが考えられますが,支店コードや部門コードのフィー
というのが一般的なテーブル設計です。これを「正規化崩し」
ルドを T_仕訳に追加することで対応できます。一方,T_仕訳
と呼びます。
明細(b)の伝票番号は,T_仕訳と結合するためのフィールドで
とはいえ,安易に正規化崩しを行うとデータベースの整合性
す。明細番号はオートナンバー型を指定し自動的に重複しない
を維持するために,本来なら必要のない処理を実装しなくては
値を発生させ,主キーに設定してあります。科目 CDから税額
ならなくなってしまいます。これでは本末転倒ですよね。正規
までは同じ項目を借方/貸方ごとに定義してあります。仕訳伝
化と正規化崩しのバランスをどうとるかは,設計者の腕の見せ
票では,借方/貸方を左右に並べて科目コード,相手先コード,
所と言えるでしょう。
金額などを入力していくからです。仕訳伝票のイメージと照ら
し合わせて理解してください* 16。
さて,テーブル「T_仕訳明細」を正規化理論に照らし合わ
せるとどうでしょうか? データベース設計の権威に添削しても
表 4● T_ 採番 _ 仕訳のテーブル構造
らったら,赤ペンで×,×,×となり,58点で不合格!かもし
NO
名称
データ型
サイズ
1
伝票番号
数値型
長整数型
備考
* 15 Dlookup関数は,指定したフィー
ルド「名前」の値を取得できる。
ルドの値を返す関数。
x = DLookup("名前", "顧客マスター",
"顧客 CD = 111")
とすれば,テーブル「顧客マスター」
で顧客 CDが111のレコードのフィー
* 16 2000年 9月号の本連載 181ページ,
172
H 2000 年 11 月号
図 3を参照。
れません。例えばT_仕訳明細は,摘要マスターと同じフィール
ド「摘要」を持っています。この目的は編集です。摘要マスタ
マスター・メンテナンスと伝 票 入 力 処 理
連結フォームの
抱える問題
ーに摘要 CDが「12」
,摘要が「新聞代」と登録されているとし
ます。仕訳伝票上では,摘要CDを入力し,表示された摘要「新
図 7 ● フォーム「F_ 仕 訳 伝 票 _ 一
覧」
聞代」を「11月分新聞代」のように編集します。仕訳伝票入力
仕訳伝票入力処理では二
時に必要になる摘要を,すべてマスター上に用意すると膨大な
つのフォームを作成します。
量になり,管理や検索が困難になります。摘要マスターには
一 つはテーブル「T_仕 訳」
「新聞代」だけを登録しておき,伝票入力時にはそれに「11月
の全 レコードをクエリー
分」を追加入力し T_仕訳明細テーブルの摘要フィールドに保
「Q_ 仕 訳 伝 票 _ 一 覧 」を経
存する方が便利な場合もあります。ですから,T_仕訳明細テー
由して連結する「F_仕訳伝
ブルに摘要フィールドが必要なのです。
票 _一覧」フォーム(図 7)
。
また,借方/貸方双方に「税計算区分」と「税区分」を持っ
もう一つはテーブル「T_仕
ています。税計算区分はその科目の金額にかかわる消費税を外
訳明細」のレコードと連結
税で計算するか,内税で計算するか,あるいは計算しないかを
する「F_ 仕 訳 明 細 _ 入 力 」
示すフィールド。税区分は消費税を起こす場合,
仮払消費税として起こすか仮受消費税として起こ
表 5● T_ 仕訳と T_ 仕訳明細のテーブル構造
すかを示すフィールドです。本来,科目マスター
(a)T_ 仕訳
に持っていればいいはずのこの二つの区分コード
をT_仕訳明細テーブルに持たせる理由は次の通り
です。
科目マスター上で事務用消耗品費という科目の
税区分が「外税」で登録されているとします。通
常の購入先は外税で消費税を計算するからです。
ところが,いつもの購入先以外から事務用品を購
入したら,内税の納品書が添付されていたとしま
す。この場合,電卓で外税に計算し直してから入
力しても構わないのですが,仕訳伝票入力フォー
ム上で「この明細だけ,内税」と切り替えること
ができれば便利ですよね。そこで明細入力時に税
計算方法を変更できるように,これらの区分をT_
仕訳明細テーブルに持たせたのです。また借方/
貸方の「相手先有無」は,その科目を相手先別に
NO
名称
データ型
サイズ
備考
1
伝票番号
数値型
長整数型
主キー
2
伝票日付
日付/時刻型
(b)T_ 仕訳明細
NO
名称
データ型
サイズ
備考
1
伝票番号
数値型
長整数型
インデックス(重複あり)
2
明細番号
オートナンバー型
長整数型
主キー
3
借方科目 CD
テキスト型
4
インデックス(重複あり)
4
借方相手先有無
数値型
長整数型
5
借方相手先 CD
数値型
長整数型
6
借方税計算区分
数値型
長整数型
7
借方税区分
数値型
長整数型
8
借方金額
数値型
通貨型
9
借方税額
数値型
通貨型
10
摘要 CD
数値型
長整数型
11
摘要
テキスト型
30
管理するか否かを示す項目ですが,テーブル「T_
12
貸方科目 CD
テキスト型
4
仕訳明細」に持たせておいた方が,プログラム作
13
貸方相手先有無
数値型
長整数型
成上都合が良いという理由で「正規化崩し」をや
14
貸方相手先 CD
数値型
長整数型
っています。
15
貸方税計算区分
数値型
長整数型
16
貸方税区分
数値型
長整数型
17
貸方金額
数値型
通貨型
18
貸方税額
数値型
通貨型
インデックス(重複あり)
インデックス(重複あり)
インデックス(重複あり)
H 2000 年 11 月号
173
Access 2000で学ぶ業務アプリケーション開発
マスター・メンテナンスと伝 票 入 力 処 理
― 経理システムを作ってみよう―
フォームです(図 8)
。
ワンポイント・レッスン
連結フォームはパフォーマンスに注意
せん。
ここで,連結フォームのRecordSource(レコードソース)を
絞り込む方法を整理しておきましょう。
1)フォームのフィルタ(Filter)を適用する方法
Accessの Form(フォーム)には,クエリーやテーブルをレ
フォームのFilterプロパティに条件式(SQLのWHERE条件の
コードソースとして持つ「連結フォーム」と,レコードに連結
WHERE句を除いたもの)を記述し,FilterOnプロパティをTrue
されていない「非連結フォーム」があります。集計処理やレポ
に設定します。例えば,フォームのオープン時にモジュールで
ート印刷用のフォームは,非連結フォームとして作成すること
FilterプロパティとFilterOnプロパティを設定し連結するレコー
が多いでしょう。
ドを絞り込むような使い方ができます。
マスター・メンテナンス処理では,マスター・テーブルの全
レコードをクエリーを通してフォームに連結させていますが,
2)WHERE条件(レコード選択条件)付きのSQL文をフォーム
のRecordSourceプロパティに指定する方法
これは各マスターの最大件数を数百件程度と想定しているから
フォームのオープン時などに,モジュールでRecordSourceプ
です。もし数千,数万件のレコードがあったら「フォームの動
ロパティ(レコードソース)に直接 SQL文を設定する指定する
きが鈍い」という致命的な問題が発生します。厳密に言います
方法です。
と,レコード数ではなくレコード数×フィールド数,つまり「タ
3)ADOを使用して作成した RecordSet(レコードセット)をフ
テ×ヨコ」の積が大きいと連結フォームの動きが遅くなります。
ォームのRecordSetプロパティに代入する方法
1 万件のレコードを連結したとしても,T_仕訳テーブルのよう
Access 2000からはADOを使って作成したRecordSetをフォー
にフィールドが二つしかなければ深刻な速度の低下は起こりま
ムに連 結 できるようになりました。SQL 文 を基 に作 成 した
せん。しかし,フィールド数が仮に50 個あったら大変です。フ
RecordSetをフォームのRecordSetプロパティに代入(Set)する
ォームに連結するレコードを絞り込む必要があります。
ことで,動的に連結するレコードを変更できます。
4)DAOを使ってフォームに連結しているクエリーの定義を書き
パフォーマンスを考慮すると,
「F_仕訳明細 _入力」フォー
ムに,テーブル「T_仕訳明細」全レコードを連結するわけには
換える方法
クエリー定義(QueryDef)オブジェクトが持つSQL文をモジ
いきません。F_仕訳伝票一覧でレコードを選択し,明細ボタ
ュール上で書き換える方法です。フォームのRecordSourceプロ
ンをクリックしたら選択された伝票番号を持つ明細レコードだ
パティなどを変更する必要がないので,分かりやすい方法です
けを,F_仕訳明細 _入力フォームに連結させたいと思います。
が,QueryDefオブジェクトは DAO固有のオブジェクトですの
また,新規伝票の入力時には,明細レコードが0件の状態でF_
で,DAOに参照設定する必要があります。
仕訳明細 _入力フォームが表示されるようにしなければなりま
仕訳伝票入力処理では,2)の「SQL文をフォームの RecordSourceプロパティに指定する方法」を採用することにします。
図 8●フォーム「F_ 仕訳明細 _入力」
シンプルで見た目に分かりやすい方法だからです。
☆ ☆ ☆
伝票入力処理の方向性が決まったところで,今回はおしまい
です。次回は,クラス・プログラミングの説明を交えながら,
仕訳伝票入力処理を完成させていきましょう。ではまた! A
174
H 2000 年 11 月号