Access95によるアプリケーション開発

はじめに
 Microsoft Access95はもっとも低価格なリレーショナル・データベースです。本来は、エンドユーザ向けのものですが、極めて高機能なためソフトハウスでは本格的なアプリケーション開発用として用いられます。書店に行けばAccess95に関する多くの書籍を見ることができますが、その多くは入門書・リファレンスでありこれからアプリケーションを開発する参考にしようとする人にとって有効ではありません。そこで、入門編ではAccess95での開発のノウハウを、実践編では、実際に簡単なアプリケーションを作りながらAccess95での開発を勉強します。

★☆★ 目次 ★☆★

プログラムデザイン
  Access95の得意/不得意
  データとプログラムでMDBを分割
  オブジェクトの命名規則
  横並びのデータ(OCCURS)は不得意
  入力画面からの更新ロジック
  システムテーブルを参照する

プログラミング
  フォームの項目でテーブルを更新する
  フォームの入力フィールドのNullチェックは?
  フォームで右クリックを無効にする
  四捨五入の関数は無い!
  レポートで空行を作る方法は?
  レポートでの値を累積する方法は?
  MDB最適化を簡単にする方法
  Access95起動時のコマンド引数
  クエリーでの技
  指定した年月の最終日を求める方法は?  /NEW 1998.10.30/

その他
  ネットワークで利用する場合の注意
  ダイアルアップを起動する方法  /NEW/
  AccessのレポートをFAX送信する  /NEW 1998.10.30/
  アプリケーションでアタッチを自動的に行う  /NEW/

アプリケーション開発テクニック

Access95の得意/不得意

 現在、我々システム開発者がAccess95を使ってアプリケーションを開発するメリットとしては以下のような理由があげられます。

 (1)基本的にエンドユーザ指向のデータベースなので、リレーショナルデータベースとしては取り扱いが容易。

 (2)フォーム/クエリー/マクロだけでもかなりのプログラムが容易に構築できる。

 (2)VBA(Viual Basic for Applications)を使えば、さらに高度なユーザーインターフェースを構築できる。

 (3)またVBAはVisualBasic系の言語なので、WindowsのAPIやOCX等など高度な機能が使用できる。

 (4)レポート機能(帳票)が優れている。但し、得意・不得意な帳票が存在する。

 (5)Microsoft SQL-Serverとの親和性が高いため、アップグレードが容易。

 Access95にはこのようなメリットがありますが、だからといってどんなシステムでもAccess95で作るのが良いわけではありません。例えば、大勢のユーザが利用するような高度なC/Sシステムには向きません。また、速度優先の場合もAccess95は不利でしょう。逆に、スタンドアロンまたは数人で利用するシステムで、ある程度までの規模ならAccess95は十分に実用的なデータベースではないでしょうか。


データとプログラムでMDBを分割

 Access95では、テーブル/クエリー/フォームなど全てのオブジェクトがMDBという名の1つのファイルに納められます。この方式は、個人ユースで使うソフトを開発するには都合が良いのですが、客先に納めるのが目的のアプリケーション開発では不都合が生じます。例えば、納品後にバグ対応やアップグレードで複数のオブジェクトを入れ替えたい場合、1オブジェクトづつ納品してあるMDBにエクスポートするのは時間がかかるうえに入れ替え忘れなど間違いを起こしやすいでしょう。また、テーブル等の頻繁にアクセスするオブジェクトとフォーム/クエリーなどのプログラムを混在させておくと、最悪の場合システム全体を破損してしまいます。

 そこで、ビジネスシステムを作る場合は、テーブルだけをもったTBL.MDBとそれ以外の(アプリケーション部分)OBJ.MDBに分割した構成にするのが一般的です。


オブジェクトの命名規則

 アプリケーション開発の最初のポイントは、Access95で使用する各オブジェクトの名称をどうするかです。Access95ではオブジェクト名に漢字が使えるなど便利になっていますが、そのため最初に統一しておかないと後で収拾つかなくなります。特に、多人数での大規模システムは注意が必要です。

オブジェクト命名規則の1案
プリフィックス 用途
M_ マスタテーブル(社員マスタ/商品マスタ/勘定科目マスタ...)
T_ トランザクションテーブル(売上伝票/売上伝票明細/給与明細...)
W_ ワークテーブル(作業用の一時テーブル)
Q_ クエリー(選択クエリー/更新クエリー/削除クエリー等でさらに細分化する場合もあります。)
R_ レポート
F_ フォーム/マクロ(※マクロは、フォーム毎に作成し名称を合わせておいた方がわかりやすいでしょう。)

 ※オブジェクト名の中に"()"は使わないほうが無難です。また、末尾に半角数字(1,2,3,...)を付けると、インポートのとき同名のオブジェクトが存在するときAccess95が自動的に付ける名前と区別がつきにくくなります。

横並びのデータ(OCCURS)は不得意

 例えば月ごとの集計データなどのもちかたをCOBOL系のSEが設計すると横並び(OCCURS)にすることが多いのですが、Acces95はこれが苦手です。クエリーではテーブルの横方向(レコードの中)の計算より縦方向の計算のほうが断然得意です。そこでこの横並びのデータを処理するとき、結果として横方向で欲しい場合も、まずVBAで一旦縦並びのデータに変換してからクエリー等を使うようにします。縦並びのデータを横向きに変換するのは、クロス集計クエリー等を使えば簡単にできます。しかし、Access95で開発を行う予定ならば、最初から横並びのテーブル構造は設計しない方が良いでしょう。

横に並ぶデータ
1月 2月 3月 ・・・ 12月
売上データ 450,000 380,000 750,000 ・・・ 520,000

縦に並ぶデータ
売上データ
1月450,000
2月380,000
3月750,000
・・・・・・
7月520,000

入力画面からの更新ロジック

 Access95のフォームウイザードではテーブル直結のフォームを作りますが、この方式ではユーザーが入力した画面を全てキャンセルすることができないことになります。そこで、ワークテーブルとクエリーを使って以下のような更新ロジックにすると便利です。

フォームを開く
  @削除クエリーでワークテーブルをクリア。
  A処理対象レコードをトランザクションから抽出してワークテーブルに追加。

閉じるボタン
  @登録=OKなら、クエリーでワークテーブルの内容をトランザクションに転記したあとフォームを閉じる。
  A登録=NOなら、そのままフォームを閉じる。


システムオブジェクトを参照する
 Access95は自身のオブジェクトの管理もMDBの中のテーブルで行っています。これらはAccess95のインストール直後は非表示となっていますが、「ツール」−「オプション」の設定を変更するだけで見えるようになります。何種類かのシステムオブジェクトが存在しますが、その中でも「MSysObject」はオブジェクト一覧レポートの作成などに便利です。また、アタッチ等の情報もこのテーブルで管理されているようです。


フォームの項目でテーブルを更新する

 アプリケーションを開発しているとき、更新クエリーを使って開いているフォームの項目をテーブルに反映させたい場合があります。通常、Access95で以下のような更新クエリーを作ることになりますが、このままではテーブルへの更新はできません。Access95ではフォーム上の項目のデータ型はVariant型のため、テーブルへ更新する時の型変換がうまくいかないからです。

フォーム:見積入力
クエリー:Q_見積入力単票_更新
テーブル:T_見積明細

フィールド ID
品名
単価
数量
テーブル T_見積明細 T_見積明細 T_見積明細 T_見積明細
レコードの更新   Forms![見積入力]![品名] Forms![見積入力]![単価] Forms![見積入力]![数量]
抽出条件 Forms![見積入力]![ID]      

 そこで、以下のようにクエリーのパラメータで更新する各項目のデータ型を、更新対象テーブルの項目に合わせて指定するとテーブルへの更新が上手く行くようになります。(※数字タイプの時、整数/長整数/倍精度浮動小数点など正確に指定しないと更新できません。)

Forms![見積入力]![ID] テキスト型
Forms![見積入力]![品名] テキスト型
Forms![見積入力]![単価] 通貨型
Forms![見積入力]![数量] 倍精度浮動小数点


フォームの入力フィールドのNullチェックは?

 フォームの項目データ型は、テーブル等が直結の場合はその元になっているデータ型であり非連結の場合はVariantのようです。そのため、VBAから非連結の入力フィールドのNullチェックを簡単にIsNull()だけで判断することができません。以下のように複合条件で判断するしかないようです。

If IsNull(Forms![画面名]![フィールド名]) = False Or IsEmpty(Forms![画面名]![フィールド名]) Then
  フィールドは空で無い
Else
  フィールドは空
Endif

※逆に、フィールドは空であるかを判断することはできません。
※フィールドに、1個以上のスペースが存在していても空と判断されます。

フォームで右クリックを無効にする

 Access95の右クリックはショートカットメニューとなっており使い慣れると便利なのですが、パソコンに詳しくはないエンドユーザが我々の作成したアプリケーションを使うきに誤動作の原因となります。そんなとき、フォームのプロパティで『ショートカットメニュー』を『いいえ』にするだけで右クリックを無効にすることができます。


四捨五入の関数は無い!

 Access95には四捨五入の関数が存在しません。四捨五入の関数が欲しい場合は、ユーザー関数を作る必要があります。この件については、Microsoft社のホームページに記載されサンプルもありますので、そちらを参照して下さい。


レポートで空行を作る方法は?

 Access95で罫線で囲んだ帳票で罫線で空行を印刷するのはかなり難易度の高いと考えられます。実際にクエリーを単純にレコードソースとするなら空行を印刷することができません。そこで、レポートイメージ(1枚分)そのままのワークテーブルを用意して、モジュールで更新をかけていくのが一番簡単ではないでしょうか。


レポートで値の累積をする方法は?

 Access95のクエリーで累計をとるのはかなり難しいようです。実は、レポートで累計を出したいだけならプロパティを使うだけで可能なのです。 詳細行のフィールドのプロパティ「集計実行」を「グループ全体」または「全体」とすると、そのフィールドは指定した範囲で累計されていきます。


MDB最適化を簡単にする方法

 Access95のMDB(データベース)は放っておくとどんどん大きくなっていきます。そのためAccess95には最適化という機能が用意されていますが、これはメニューから操作するもので、しかも開いているMDB自身を最適化することができません。一般ユーザーが使用するアプリケーションを開発した時、この最適化をどうするかが問題になります。一番簡単なのは、Access95を起動するとき最適化モードを指定できるのでこれをショートカットに登録しておくことです。

【書式】
C:\MSOFFICE\Access\MSACCESS.EXE 最適化元データベース名/Compact 最適化先データベース名


Access95起動時のコマンド引数

 Access95は起動時につけた任意のコマンド引数を関数で取得しVBAで使用することができます。例えば、この機能を使えばC/Sシステムを作成するときクライアントAPとサーバーAPを1つのMDBに用意しておきコマンド引数の切り替えだけで、どちらかに対応したメニューを開くようなことが可能となります。

  【サーバーとして起動】
  C:\MSOFFICE\Access\MSACCESS.EXE /Cmd "S"
  【クライアントとして起動】
  C:\MSOFFICE\Access\MSACCESS.EXE /Cmd "C"

  【モジュール】
  if Command = "S" then
    Docmd.OpenForm "メインメニュー(サーバー)"
  Else
    Docmd.OpenForm "メインメニュー(クライアント)"
  End If


クエリーでの技

 例えば、以下のようなテーブルを考えてみましょう。このとき画面(フォーム)から指定された1項目(ハード、ソフト、パーツ、書籍)のどれかを販売しているショップをクエリーで抽出しようとすると、QBEの抽出条件のところにかなり複雑な式を入れるか複数のクエリーを組み合わせるなど困難なものになります。
M_SHOP
店名ハードソフトパーツ書籍
A商店YesYesNoNo
B商店YesNoYesNo
C商店YesYesNoYes
D商店YesYesYesNo

 このような場合、発想を変えるだけで簡単なクエリーにしてしまうことができます。具体的には、抽出条件に式を書くのではなく、項目の方に式を書きターゲットとなる項目を特定してしまうのです。抽出条件は、選ばれた項目がYesであることだけを判定すれば良いことになります。この方式は、データがあまり多くないとき、選択する項目が1種類に限定できるときに使うことができます。
項目 店名 比較項目:SWITCH( Myform![項目]="ハード",M_SHOP![ハード],Myform![項目]="ソフト",M_SHOP![ソフト],Myform![項目]="パーツ",M_SHOP![パーツ],Myform![項目]="書籍",M_SHOP![書籍])
抽出条件      Yes
※MyForm![項目]で指定された物を販売しているショップを抽出します。



指定した年月の末日を求める方法は?

 指定した年月の末日を求めるにはAccessの日付関数を組み合わせるだけで簡単にできます。 DateAdd関数は、年/月/日をそれぞれプラス・マイナスできるので、Format関数と組み合わせて 翌月の1日を求めます。次に、DateAddをもう一度使って日を−1すると末日が求められます。

 【例】
    Dim MyDate As String
    Dim EndDay As Date

    MyDate = 98/10/15
    EndDay = DateAdd("d",-1,DateAdd("m",1,DateValue(Format(MyDay,"yyyy/mm/01")))
    Msgbox("指定した年月の末日は " & EndDay & "です。"



ネットワークで利用する場合の注意
 WindowsNTやWindows95はネットワークOSでもあるので、複数のパソコンを繋いでファイル共有ができるようになります。この機能を使い、Access95で作成したアプリケーションは複数のパソコンから使うシステム(※1)にすることができます。その場合、プログラムであるOBJ.MDBは各クライアントに置き、データベース本体であるTBL.MDBだけをサーバーとなるパソコンに置いた方がネットワークの負荷、パフォーマンスの点から良いでしよう。しかし、このように手軽にネットワークシステムを構築できることから、落とし穴にはまることもあります。例えば、単純なAccess95で作ったシステムをネットワーク対応にした場合、たとえ2〜3人で使うような場合でもテーブルアクセスの競合が発生します。もちろんAccess95はクエリーやフォームで(※2)排他を制御できるようになっていますが、それは「他のユーザと競合している」旨のメッセージを出すだけでユーザまかせのものです。もし、複数テーブルをアクセスしている部分でこれが起きると、ユーザの操作しだいではデータの不整合をともなう危険な状態になるでしょう。このようなことから、たとえAccess95で作る場合でも、ネットワークシステムを構築する時は開発者は排他制御など十分注意していなければなりません。

※1:Access95はC/S型システムではなくファイル共有システムです。
※2:Access95はページ(2K)単位の排他となります。


ダイアルアップを起動する方法
只今、工事中です。


AccessのレポートをFAX送信する
 AccessのレポートをFAXで送信するという要求が時々ありますが、市販のパッケージ「信之助(株式会社コムユース)」 「まいとーく(NEC)」などを使う方法とWindows95に標準でついているMicrosoftFAXを使用する方法があります。 前者では各々のAPIなどを使ってアプリケーション側から高度な制御を行うことができます。後者の場合は起動時に アドレス帳が開いて相手先を選ぶ必要があるなど一部で手動操作が必要ですが、逆に簡単に作りこむことが可能です。 どちらを使うかは、プロジェクトでの必要性やスケジュール・工数などにもよりますが、ここではMicrosoftFAXでの 使用を説明します。

【操作】
 (1)Windows95/98にMicrosoftFAXをインストールします。
 (2)Accessのレポートのページ設定で、出力先のプリンタに「Microsoft FAX」を選択します。
 (3)通常どおりレポートを印刷すると、MicrosoftFAXの送信画面が開きますので相手先を入力してください。

※1:MicrosoftFAXは、WIndows98ではCD-ROMのToolsフォルダの中にあります。


アプリケーションでアタッチを自動的に行う
只今、工事中です。


(C)1997 NEO TAGAWA PROJECT

※当ページの著作権は、「NEO TAGAWA PROJECT」にあります。
※当ページを無断で転載することを禁止します。
※当ページを書籍等に転載する場合は事前にご連絡下さい。