Access 2000 で学ぶ業務アプリケーション開発―経理システムを作ってみよう― 第6回 複雑な計算式を DB 化するテクニック ― 元帳と決算帳票の作成 ― 金宏 和實 今回は経理システムのかなめである「元帳(総勘定元帳と補 助元帳) 」と「決算帳票(貸借対照表と損益計算書) 」を作成 します(図 1) 。前回作成した月次集計処理 * 1 というバッチ処 当月末残高 = 前月までの残高 + 当月の借方発生額 理で出力した元帳データ(T̲元帳)と,科目ごとに月単位の -当月の貸方発生額 (貸方残の科目の場合) 発生額を集計した科目残高マスター(M̲科目残高)を基に, これらのレポートを作成していきます。ただし,貸借対照表や 当月末残高 = 前月までの残高-当月の借方発生額 損益計算書の計算は後述するように複雑です。下手に計算式プ + 当月の貸方発生額 ログラムを実装してしまうと,後でメンテナンスするのが面倒 という計算式を使います。当月末残高から残高試算表を作成し になります。そこで今回は「計算式そのものをメンテナンス可 たら,貸借のバランスが正しいかどうかをチェックして,損益 能なデータとして定義する」というテクニックを紹介しましょ 計算書と貸借対照表を仕上げるわけです。これら一連の作業を う。経理システムに限らず,さまざまな業務処理で応用できる コンピュータ化する一番のメリットは,残高試算表で試算する 必要がなくなることでしょう。総勘定元帳から一気に損益計算 アイデアなので,ぜひマスターしてください。 書と貸借対照表を作れるようになるのですから。 まずは総勘定元帳を作成する それでは,総勘定元帳レポートを発行するフォームを見てみ 総勘定元帳は,各科目の金額が当月にどのように動いたか ましょう(図 2) 。レポート発行用フォームでは,科目 CD(コ (増減したか)を表す明細表です。手書きで経理処理をしてい ード)を指定して印刷できるようにテキストボックスを配置し たころは,まず仕訳伝票を起票し,総勘定元帳の該当する科目 ています。また,科目名表示用のテキストボックス(txt科目 のページに発生額を書きこんでいました。科目には借方残,貸 名)と科目検索フォーム* 2 を開くためのコマンドボタン(btn 方残のいずれかで科目の残高を計算するという属性があるので, 科目検索)も配置しています。科目 CDが入力された場合は, (借方残の科目の場合) その科目の元帳だけを印刷し,何も入力されなければ,すべて 図 1●今回は経理システムで最も重要な帳票を作成する 仕訳伝票 仕訳チェックリスト 第4回 第5回 金宏 和實 (かねひろ かずみ) 筆者には 3 人の子供がいます。長男は「こうしろうの Mindstorms日記」の宏志郎,次男は和也。筆者のペンネー ムには2 人の名前が1文字ずつ入っています。でも,実は長 女の名前が入っていません。彼女の名前は「ほのか」 。どう やってペンネームに入れればいいでしょう? 金宏マルほ和實 にしようかな(^^; 216 H 2001 年 2 月号 図 2●総勘定元帳レポートを印刷す るフォーム 総勘定元帳 貸借対照表 補助元帳 損益計算書 集計処理 今回作成する部分 * 1 第 5回までの月次集計処理を含 むデータベース(kei.mdb と kei̲dt.mdb)は 本 誌 Web サ イ ト (http://software.nikkeibp.co.jp/)でダ ウンロードできます。 複雑な計算式を DB 化するテクニック 図 3●総勘定元帳レポートのサンプル Office 2000 SR-1 は適用しましたか? ところでみなさん,前回作成した仕訳チェックリストはうま く印刷できましたか? ページ設定で横方向に設定しても,デー タベースの最適化を行うと縦方向になってしまって,困られた 方はいらっしゃいませんでしたか? 実は初期のAccess2000には「データベースの最適化を行うと, ページ設 定 が既 定 値 に戻 る」(http://www.microsoft.com/ JAPAN/support/kb/articles/J049/8/41.htm)というバグがありま した。この問題は,Office 2000 Service Release 1(SR-1)で解消 されています。もし,まだ SR-1を適用されていなければ,ぜひ インストールすることをオススメします。 の科目の元帳を印刷します。 総勘定元帳レポートを見てみましょう(図 3) 。このレポート で重要なのは,どう金額が動いたかが見えることです。例えば 前月末残高は,科目残高マスターの各フィールドから次の計算 式で算出します。 (借方残の科目の場合) 表 1● W̲ 元帳のテーブル構造 NO 名称 データ型 サイズ 備考 1 科目 CD テキスト型 4 主キー 2 科目名 テキスト型 20 3 前月末残高 通貨型 4 借方貸方区分 数値型 長整数型 前月末残高 = 前期末残高 + 当年借方-当年貸方 (貸方残の科目の場合) 前月末残高 = 前期末残高-当年借方 + 当年貸方 借方残か貸方残かは,科目マスターの借方貸方区分(0:借方, ートのデータを計算し,それをプリントするようにプログラム するには,複雑なクエリー処理を記述するなど結構面倒な手間 が必要です。 1:貸方)で判断し,明細部は元帳テーブル(T̲元帳)から印 業務アプリケーション開発では,処理効率はもちろん,開発 刷して借方/貸方の発生額を合計します。当月の残高は前月末 効率の向上も重要なテーマです。アプリケーションのライフ・ 残高と上記の合計から求めます。 サイクルはどんどん短くなっているので,簡単にプログラミン さて以上のことから,総勘定元帳レポートを作成するには, 1)元帳データ(T̲ 元帳)からデータをセレクトする 2)科目残高マスター(M̲科目残高)から前月末残高を計算す る の2点が必要なことがわかったと思います。 グできて,かつほかの人にもメンテナンスしやすいようなシス テムを作ることを忘れてはいけません。 そこで今回は,元帳データと科目残高マスターから一気にレ ポートを作成するのではなく,いったん計算用のワークテーブ ルを作って計算結果を保存して,レポートを出力する方法を紹 介しましょう。この方法なら,ワークテーブルをレポートのレ ワンポイント・レッスン ワークテーブルを使ってメンテナンスを容易にする コードソースとすればいいので,レポート作成そのものはぐっ と簡単になります。 ここまで読んだ皆さんの多くは「元帳データと科目残高マス ターさえあれば,直接レポートを作成するのは簡単だな」と思 総勘定元帳レポートを作成するためのワークテーブルは,科 ったかもしれません。しかし実は二つのテーブルから直接レポ 目残高マスターの計算結果を保存する「W̲元帳」 (表 1)と, * 2 科目検索フォームの使い方は, 2000年 12月号の本連載を参照。 H 2001 年 2 月号 217 Access 2000で学ぶ業務アプリケーション開発 ― 経理システムを作ってみよう― 元帳テーブルからデータのセレクトを行う「W̲元帳明細」 (表 は,W̲元帳と同様にWHERE条件でレコードをセレクトして出 2)の二つです。W̲元帳は,科目残高マスターと科目マスター 力します。こうしてW̲元帳とW̲元帳明細ができたら,それら を等結合* 3 で結合したレコードセットから,科目 CD,科目名, を等結合してクエリー「Q̲総勘定元帳」を作成します(図 4) 。 借方貸方区分を取り出して作成します。科目名を取り出すの これで,総勘定元帳レポートのレコードソースができました。 は,印刷用のクエリーが複雑になるのを避けるためです。また 肝心の総勘定元帳レポートをデザインビューで見てみましょう 同時に,前述した計算式に従って前月末残高も出力します。印 刷フォームで科目 CDが指定された場合,W̲元帳は1レコード (図 5) 。 総勘定元帳での並べ替えは,科目 CD,伝票日付,伝票番号, だけになります。一方,W̲元帳明細は,T̲元帳から各項目を 明細番号の昇順に設定し,グループ化 * 4 は科目 CDに設定しま 取り出して作成します。フォームで科目 CDが指定された場合 す。図 5を見て, 「あれっ?」と思った方がいたらうれしいので すが,科目の前月末残高が,科目 CDが変わったら出力される 表 2● W̲ 元帳明細のテーブル構造 科目 CDヘッダーではなく,ページヘッダーに配置されている NO 名称 データ型 サイズ 備考 のがわかりますか? もちろんこれは,間違ったわけではなく, 1 元帳キー オートナンバー型 長整数型 主キー レポートを見やすくするための工夫です。科目 CDヘッダーに 2 科目 CD テキスト型 4 ある改ページのプロパティを「カレント・セクションの前」* 5 3 相手先 CD 数値型 長整数型 に指定して,科目 CDが変わるたびに改ページが行われるよう 4 伝票日付 日付/時刻型 5 伝票番号 数値型 長整数型 同じように扱えるわけです。科目 CDフッターでは借方,貸方 6 明細番号 数値型 長整数型 の金額をそれぞれSUM関数 * 6 で集計しています。 7 摘要 テキスト型 30 8 相手科目 CD テキスト型 4 9 借方金額 通貨型 10 貸方金額 通貨型 に設定していますので,ページヘッダーも科目 CDヘッダーと 科目 CDフッターとページヘッダーには,非連結 * 7 のテキス トボックスが合わせて三つ配置されています。これらのテキス トボックスの値は,標準モジュールではなく,レポートのクラ 図 5●「総勘定元帳レポート」をデザインビューで開いたところ 図 4●クエリー「Q̲ 総勘定元帳」 * 3 テーブルの結合(JOIN)には, 等結合(INNER JOIN) ,左外部結合 (LEFT JOIN) ,右外部結合(RIGHT JOIN)の 3 種 類 の結 合 方 法 がある。 等結合では,双方のテーブルから結 合に指定したフィールドに同じ値を 218 H 2001 年 2 月号 持つレコードが選択される。左(右) 外部結合では,片方のテーブルの全 レコードともう一方のテーブルの結 合されたレコードが選択される。 * 4 グループ化の詳細は 2001年 1月 号の本連載を参照。 * 5 改ページのプロパティには「 (改 ページを)しない」/カレント・セク ションの前」/「カレント・セクショ ンの後」 , 「カレント・セクションの 前後」の四つの選択肢がある。 * 6 SUM関数は,引数として与えら れたフィールドの値の合計を算出す る関数。 * 7 データベースのテーブルなどか ら直 接 データを取 得 しない場 合 を 「非連結」と呼ぶ。 複雑な計算式を DB 化するテクニック リスト 1●総勘定元帳レポートのクラス・オブジェクトのコード ス・オブジェクト* 8(この場合はReport̲総勘定元帳) で設定します(リスト 1) 。(1)のページヘッダー・フォ ーマット時の処理では,Dlookup関数 * 9 を使って基本 情報マスター(M̲基本情報)の月次締日を取得して います。(2)の科目 CDフッターのフォーマット処理で は,非表示でレポートに配置した借方貸方区分テキス トボックスの値に従って,当月末残高(借方残高/貸 方残高)を計算しています。Dlookup関数による値の 取得は,レポートのクラス・オブジェクトに記述せず に,テキストボックスのコントロールソースに設定す ることもできますが,クラス・オブジェクトに書いた 方が見やすいでしょう。この例のように,クラス・オ ブジェクトを使ってデータの取得や計算を行えば,レ ポートのレコードソースを準備する標準モジュールや フォーム・モジュールの処理をシンプルにすることが できます。 Option Compare Database Option Explicit Private Sub ページヘッダー _Format(Cancel As Integer, _ FormatCount As Integer) [月次締日] = DLookup("月次締日", "M_ 基本情報", _ "基本情報キー =1") End Sub (1) Private Sub 科目 CD フッター _Format(Cancel As Integer, _ FormatCount As Integer) If [借方貸方区分] = 借方貸方区分 _ 借方 Then [借方残高] = [前月末残高] + [借方金額合計] _ - [貸方金額合計] [貸方残高] = "" Else [借方残高] = "" [貸方残高] = [前月末残高] + [貸方金額合計] _ - [借方金額合計] End If End Sub (2) 集計情報や計算式の情報を テーブルに持たせる しかし単純に 総勘定元帳の処理はできました。次はいよいよ経理システム 「利益」と言っても, 開発後半戦のメイン・イベント,損益計算書と貸借対照表の 実 際 には売 上 総 利 作成です。まず損益計算書レポートのイメージをながめながら, 益 ,営 業 利 益 ,経 どんな仕組みが必要なのかを考えていきましょう(図 6) 。 常 利 益 ,税 引 前 当 図 6を見ると,まず階層構造になっていることに気が付きま 期 利 益 ,当 期 利 益 すね。売上高は商品売上高からサービス売上高までの四つの科 と五つのカテゴリに 目で構成されています。それぞれの当月発生/今期累計の金額 分かれ,それぞれ表 は科目残高マスターから求め,売上高にはその合計を印刷しま 3のように計算方法 す。注意してほしいのは,製品売上高やサービス売上高は科目 が異なります。それ マスターに登録されている科目ですが,売上高は単なる集計用 に企業は「生き物」 の項目にすぎない,ということです。 ですから,科 目 は 売上原価は期首商品棚卸高以下の三つの科目の計算結果で 図 6●損益計算書レポートのサンプル 追 加 されたり使 わ す。売上高から売上原価を引いた値が売上総利益になります。 れなくなったりします。計算式をプログラムの中にコードとし つまり損益計算書というのは,その名の通り,収益−費用=利 て持たせると, 「もう科目の追加はできません」とか「変更で 益(当期利益)を求めるための帳票なのです。 きません」などというように,メンテナンス上の問題が発生す * 8 Access 2000のソースコードは, Accessクラス・オブジェクト(フォ ームやレポートのソースコード) ,標 準モジュール,クラス・モジュール の三つに分けて記述できる。 * 9 DLookupは選択条件を指定して, テーブルやクエリーから特定のレコ ードのフィールドを取得するために 使用する。DLookup("取得したいフィ ールド名", "テーブルやクエリー名"," 検索条件式")のように使う。 H 2001 年 2 月号 219 Access 2000で学ぶ業務アプリケーション開発 ― 経理システムを作ってみよう― る可能性があります。 す。例えば上に空白行を 1行作りたい場合は,この値を 2に設 そこで,冒頭に紹介したように今回のシステムでは,これら 定します。一方,集計レベルは計算の順序を指定します。集計 の集計情報や計算式を,テーブルにレコードとして持たせるこ レベルが0の場合は,科目残高マスターからの金額の集計を意 とにします。損 味します。集計範囲開始と集計範囲終了には集計すべき科目 益計算書計算定 CDを範囲指定します。集計レベル1〜 Nのレコードは,集計値 表 3●損益計算書に印字する各「利益」とその計算 方法 分類 項目 A 売上高 a 売上原価 1 計算式 売上総利益 b 2 A− a 販売費および一般管理費 営業利益 C 営業外収益 c 営業外費用 3 1− b 特別収益 d 特別損失 4 5 減算 CDにマイナス要素のPLCDを記入します。集計レベルの1 義)を見てくだ 〜 Nは計算の順序を示します。このようにして,集計レベルの さ い ( 表 4 )。 順に計算をしていけば損益計算書の階層構造に対応でき,つじ PLCD(損 益 コ つまのあった計算ができるのです。このテーブルをメンテナン ード)はこのテ スするフォームを作成しておけば,ユーザーが容易に計算定義 ーブルの主キー を変更することができるでしょう。 ワンポイント・レッスン でのレコードの 2+ C− c 税引前当期利益 e の計算を意味します。加算 CDにプラス要素のPLCDを記入し, で,テーブル内 経常利益 D 義 マ ス タ ー (M̲PL 計 算 定 3+ D− d 法人税等 当期利益 4− e 位置を示します。 計算式をテーブルに保存するメリット 印刷名称は損益 損益計算書計算定義マスターにデータを登録する作業は,実 計算書の区分欄 は結構面倒です。しかし,プログラム中にコード番号を埋め込 に印刷する名称 んで, 特別計算 で ,改 行 数 は 1 る必要がないので,イレギュラーな処理のない構造的なプログ を既定値としま ラミングが可能になります。 なんてコメントを付けて計算処理を作成す 表 4●損益計算書計算定義マスター(M̲PL 計算定義)の例 PLCD 改行数 集計レベル 0001 (営業損益) 1 0 0002 売上高 1 0 5001 0003 商品売上高 1 0 5001 0004 商品卸売上高 1 0 5004 5004 0005 製品売上高 1 0 5002 5002 0006 サービス売上高 1 0 5003 5003 0007 売上原価 2 1 0008 期首商品棚卸高 1 0 5110 5110 0009 当期商品仕入高 1 0 5100 5100 0010 期末商品棚卸高 1 0 5120 5120 0012 売上総利益 2 2 0020 販売費及び一般管理費 2 0 5200 5600 0021 役員報酬 1 0 5200 5200 0022 給与手当 1 0 5210 5210 0023 雑給 1 0 5220 5220 0024 賞与 1 0 5230 5230 220 印刷名称 H 2001 年 2 月号 集計範囲開始 集計範囲終了 加算 CD1 今期累計 当月発生 ¥0 ¥0 5004 ¥2,120,000 ¥2,120,000 5001 ¥120,000 ¥120,000 ¥2,000,000 ¥2,000,000 ¥500,000 ¥500,000 ¥500,000 ¥500,000 ¥1,620,000 ¥1,620,000 ¥66,667 ¥66,667 0008 0002 加算 CD2 0009 減算 CD1 0010 0007 複雑な計算式を DB 化するテクニック 実はこのテクニッ クは,15 年前に筆者 図 7●損益計算書レポートを印刷するフォ ーム が COBOL プログラ 補助元帳(相手先別元帳)を作るには 元帳データには,本文で説明している総勘定元帳のほかに, マだった時代に考え 補助元帳(相手先別元帳)があります。これは,総勘定元帳を たものです。決算書 科目 CDと相手先 CDをキーとして相手先別に分類した帳票で の計算の仕方として す。科目マスター(M̲科目)で, 「相手先有り」に設定されて は,例えば科目コー いる科目が対象となります。フォームやモジュールの構造は総 ド 3000 から 3999 ま では売上高の科目で, 4000から 4999までが販売費および一般管理費などとルールを 勘定元帳レポートと同じですが,科目残高マスターではなく, 相手先別残高マスターを使う点と,科目 CDと相手先 CDでグル ーピングを行う点だけが異なります。ぜひ,総勘定元帳レポー トを例に,ご自分でプログラミングしてみてください。 決めておいて集計し,それ以降の計算はプログラム内に計算方 法をコードとして持つ方法が考えられます。自社のシステム開 発なら科目コードの体系そのものはそんなに変化しないので, リスト 2●フォーム「F̲ 損益計算書」の一部 これも良い方法でしょう。しかし,もしその経理システムをほ かの企業が使うとしたら,その企業の科目コードを経理システ ム規定のコード体系に合わせてもらわなくてはいけません。筆 者の経験から言うと,科目のコード付けルールは業種や企業規 模で結構異なります。今回の方法なら,企業が従来から使って いる科目コードをそのまま適用させることができます。 複数の関数に処理を分散する Private Sub btn計算実行 _Click() Dim intRet As Integer Dim intMaxN As Integer Dim i As Integer If Not 項目設定([txt 期間終了日]) Then Exit Sub End If DoCmd.Hourglass (True) それでは損益計算書計算定義マスター(M̲PL計算定義)を 使って,損益計算書を作成する手順を解説していきましょう。 まず,印刷処理をキックするフォームからです(図 7) 。 このフォームには,計算実行,プレビュー,印刷,終了の四 つのボタンを配置します。フォームのロード時には,プレビュ ー,印刷ボタンのEnabledプロパティをFalse(使用不可)に設 定し,計算実行ボタンがクリックされて計算処理が完了した時 点で,Enabledプロパティを True(使用可)にします。計算処 理に少し時間がかかるからです。期間開始日,終了日,会社名 などのテキストボックスには基本情報マスター(M̲基本情報) のフィールドを表示しています。 計算実行ボタンが押された時の処理を見てみましょう(リス intMaxN = 損益計算 _ 集計レベル _ 最大値取得() intRet = 損益計算 _ 科目集計 _ 削除() intRet = 損益計算 _ 科目集計 _ 残高() intRet = 損益計算 _ 計算定義 _ クリヤ() intRet = 損益計算 _ 計算定義 _ 集計() For i = 1 To intMaxN intRet = 損益計算 _ 計算定義 _ 計算(i) Next i intRet = 損益計算 _ 損益 _ 削除() intRet = 損益計算 _ 損益 _ 出力() (1) (2) (3) (4) (5) MsgBox "集計しました。" DoCmd.Hourglass (False) btn プレビュー.Enabled = True btn 印刷.Enabled = True End Sub ト 2) 。ポイントは,ほとんどの計算処理を複数の関数(Func- H 2001 年 2 月号 221 Access 2000で学ぶ業務アプリケーション開発 ― 経理システムを作ってみよう― tion)に分散していることです。概略は, 計算 ̲計算定義 ̲クリヤ( )で,レベル0のレコードすべてについ (1)M̲PL計算定義の集計レベルの最大値を取得 てフィールド「今期累計」と「当月発生」をクリアします。そ (2)科目残高マスターの科目 CDごとに,今期累計と当月発生を して,損益計算 ̲計算定義 ̲集計( )関数を使って,(2)で作成し 集計 た W̲科目集計を選択・集計し,M̲PL計算定義の今期累計, (3)集計レベル0 の科目ごとに今期累計と当月発生を集計 当月発生フィールドに結果を格納します(図 9) 。 (4)集計レベル1 から最大値までの科目について,今期累計と当 集計レベルに応じて損益を計算 月発生を計算 (5)損益計算書印刷用のワークテーブルにデータを出力 リスト2の(4)は,集計レベル1から最大値(intMaxN)までの 計算処理です。For i = 1 To intMaxNが集計レベル1〜 Nに対応 という手順になります。 まず最初の(1)の処理で,M̲PL計算定義から集計レベルの最 大値(intMaxN)を取得します。リスト 2にはありませんが, SELECT MAX(集計レベル) AS 最大値 FROM M̲PL計算定義 というSQL文 * 10 を使っています。 しています。損益計算 ̲計算定義 ̲計算(i)のコードを見てみま しょう(リスト3) 。 まず,M̲PL計算定義で集計レベルが変数 iのレコードをセレ クトしてレコードセットを作成します(リスト3の(1)) 。次に, (2)では,W̲科目集計というワークテーブルに,科目残高マ その時点の集計レベルよりも小さい値の集計レベルを持つデー スターの金額を集計します。事前に,損益計算 ̲科目集計 ̲削 タをセレクトして,レコードセットを作成します(2)。このレコ 除( )で W̲科目集計の全レコードを削除しておき,損益計算 ̲ ードセット(rs1)が集計対象になります。rsレコードセットの 科 目 集 計 ̲残 高 ( ) 加算 CD,減算 CD(それぞれ 1〜 10まで登録可)で rs1レコー で,今 期 累 計 と当 ドセットから対象のレコードをFind * 12 して(3),今期累計と当 月 発 生 を格 納 しま 月発生を加算もしくは減算していきます。i=1の計算が終了し す(図 8)* 11。 た時点のM̲PL計算定義は,例えば図 10のようになっています。 図 8●リスト2の(2)の処理を実行後のワーク テーブル「W̲ 科目集計」 続 いて(3)は, 集計レベル1の売上原価が計算されていることがわかりますか? M̲PL計算定義で集 このようにして集計レベルの最大値まで計算を繰り返すと当期 計レベルが0の科目 利益が求まり,損益計算書ができあがるのです。 の処 理 です。こち 計算実行ボタンクリック時処理のラストは,またしてもワー らも事 前 に,損 益 図 9●リスト 2の(3)の処理を実行後のテーブル「M̲PL 計算定義」 * 10 MAX関数はSQLの集計関数で, 指定されたフィールドの最大値を返 す。 * 11 損益計算 ̲科目集計 ̲残高( )で は,科目残高マスターと科目マスタ ーを等結合してセレクトする SQL文 222 H 2001 年 2 月号 を基にレコードセットを作成し,科 目マスターのBSPL区分と借方貸方区 分に応じて,今期累計と当月発生分 を集計している。 *12 Findはレコードセットから,指 定した条件を満たす行を検索するメ 図 10 ●リスト2の(4)で,i=1 について実行後のテーブル「M̲PL 計算 定義」 。集計レベル 1の売上原価が計算されている ソッド。ADO(ActiveX Data Objects) には DAO(Data Access Objects)の ように FindFirstなどのメソッドがな い。そこでリスト3では,Findを実行 する前に,MoveFirstでポインタの位 置をレコードセットの先頭に移動さ せている。 複雑な計算式を DB 化するテクニック リスト 3●損益計算 ̲計算定義 ̲ 計算( )のコード Function 損益計算 _計算定義 _計算(level As Integer) Dim strSQL As String '計算レベルでM_PL計算定義をSELECT Dim strSQL2 As String Dim j As Long strSQL = 損益計算 _SQL_定義計算(level) strSQL2 = 損益計算 _SQL_定義計算 2(level) (1) (2) Set cn = Application.CurrentProject.Connection Set rs = New ADODB.Recordset Set rs1 = New ADODB.Recordset rs.Open strSQL, cn, adOpenDynamic, adLockOptimistic rs1.Open strSQL2, cn, adOpenDynamic, adLockReadOnly cn.BeginTrans Do While Not (rs.EOF) For j = 1 To 10 If Trim(rs.Fields(j) & "") <> "" Then rs1.MoveFirst rs1.Find "PLCD = '" & rs.Fields(j) & "'" If Not rs1.EOF Then rs![今期累計] = Nz(rs![今期累計], 0) _ + Nz(rs1![今期累計], 0) rs![当月発生] = Nz(rs![当月発生], 0) _ + Nz(rs1![当月発生], 0) Else MsgBox "加算コード = " & rs.Fields(j) _ & "が見つかりません" End If End If Next j For j = 11 To 20 If Trim(rs.Fields(j) & "") <> "" Then rs1.MoveFirst rs1.Find "PLCD = '" & rs.Fields(j) & "'" If Not rs1.EOF Then rs![今期累計] = Nz(rs![今期累計], 0) _ - Nz(rs1![今期累計], 0) rs![当月発生] = Nz(rs![当月発生], 0) _ - Nz(rs1![当月発生], 0) Else MsgBox "減算コード = " & rs.Fields(j) _ & "が見つかりません" End If End If Next j rs.Update rs.MoveNext Loop cn.CommitTrans rs.Close rs1.Close Set rs = Nothing Set rs1 = Nothing cn.Close Set cn = Nothing End Function Private Function 損益計算 _SQL_定義計算(level As Integer) _ As String Dim strSQL As String Dim strWHERE As String strWHERE = " WHERE 集計レベル = " & level (3) (3) (1) strSQL = "SELECT PLCD, 加算 CD1, 加算 CD2, 加算 CD3," strSQL = strSQL & "加算 CD4, 加算 CD5, 加算 CD6, 加算 CD7," strSQL = strSQL & "加算 CD8, 加算 CD9, 加算 CD10," strSQL = strSQL & "減算 CD1, 減算 CD2, 減算 CD3, 減算 CD4," strSQL = strSQL & "減算 CD5, 減算 CD6, 減算 CD7," strSQL = strSQL & "減算 CD8, 減算 CD9, 減算 CD10," strSQL = strSQL & "今期累計, 当月発生" strSQL = strSQL & " FROM M_PL計算定義" strSQL = strSQL & strWHERE strSQL = strSQL & " order by PLCD" 損益計算 _SQL_定義計算 = strSQL End Function Private Function 損益計算 _SQL_定義計算 2(level As Integer) _ As String Dim strSQL As String Dim strWHERE As String strWHERE = " WHERE 集計レベル < " & level strSQL strSQL strSQL strSQL strSQL = = = = = "SELECT PLCD," strSQL & "今期累計, 当月発生" strSQL & " FROM M_PL計算定義" strSQL & strWHERE strSQL & " order by PLCD" (2) 損益計算 _SQL_定義計算 2 = strSQL End Function H 2001 年 2 月号 223 Access 2000で学ぶ業務アプリケーション開発 複雑な計算式を DB 化するテクニック ― 経理システムを作ってみよう― クテーブル(W̲損益)への出力処理です(リスト2の(5)) 。こ ドウに出力した値をレビューした方が効率的なことがあるので こでは,M̲PL計算定義からSELECT文でPLCD,印刷名称,改 す。しかし,このデバッグ用のコードを完全に削除しないでリ 行数,今期累計,当月発生のフィールドを選択し,レコードセ リースしてしまったら…。こんなうっかりミスを防ぐために古 ットを作成して W̲損益に出力しています。なぜ,こんなこと くから使われているテクニックを紹介します。 をしているのかと言うと,改行数に応じて空白のレコードを付 加して出力するためです。Accessのレポート上で改行をコント ロールするのは困難だからです。具体的には次のように, Do While Not (rs.EOF) If rs![改行数] > 1 Then For j = rs![改行数] To 2 Step - 1 まず標準モジュールにグローバル定数を宣言します。 Public Const ctDEBUG = True デバッグのための処理は, if ctDEBUG then Debug.print 変数名 end if rs1.AddNew のように ctDEBUGが真の時のみ実行するように,必ず IF 文で rs1.Update くくります。そしてプログラム完成後,ユーザーに使ってもら Next j End If rs1.AddNew rs1![印刷名称] = rs![印刷名称] うときに,標準モジュールの定数宣言の部分を, Public Const ctDEBUG = False のように書き換えます。 こうすれば,プログラムのあちこちにデバッグ用のコードを rs1![今期累計] = Nz(rs![今期累計], 0) 埋め込んでいたとしても,ctDEBUGの値を修正するだけで,す rs1![当月発生] = Nz(rs![当月発生], 0) べてオフにできます。 rs1.Update rs.MoveNext 一つの目的/一つの関数 今回のソースコード,特にリスト2を見て, 「処理を小分けに Loop 改行数が1より大きい場合に,改行数に応じて空白行を出力し しすぎではないか」と思われた方もいたかもしれません。確か ています。このようにして作成した W̲損益をレコードソース に個々の関数の機能を増やせば,関数の数を減らせるかもしれ にして,損益計算書レポートを作成します。 ません。ですが筆者は「一つの関数が,一つの目的のみを果た ワンポイント・レッスン 古典的なデバッグ・テクニック 変数の値を表示する「msgbox 変数名」のようなコードや, す」ように作成することを心がけています。プログラムをわか りやすいものにしたいからです。 筆者も20代のころは難しいプログラムを作ることに快感を感 じていました。複雑なロジックのプログラムを作成し一発で動 変 数 の値 の推 移 をイミディエイト・ ウィンドウに出 力 する いた時なんか,ひとり悦に入っていました。しかし,業務用ア 「Debug.print 変数名」などのコードを,プログラムの中に入れ プリケーションも工業生産物の一つです。いかに製造工程を簡 ることがあります。デバッグや実行後にどこで処理がおかしく 略化するか――これもソフトウエア開発者の腕の見せ所です。 なったかを見つけるための措置です。もちろん,Accessの開発 誌面の都合で説明できませんでしたが,貸借対照表も損益計算 環境にあるウォッチ式やブレークポイントを使ってデバッグす 書と同じ要領で作成します。詳細はmdbファイルをダウンロー ることも可能ですが,複雑な処理ではイミディエイト・ウィン ドしてお確かめください。ではまた! 224 H 2001 年 2 月号 A
© Copyright 2024 Paperzz