フォームでのデータチェック

* Amazon Access 関連書籍情報

表形式のフォームで、「登録」ボタン使ってデータの保存させたいんだけど。よくあるじゃん?汎用機とかでさ。
でもさぁ、Aceess のフォームって、なんでレコード移動しただけでデータ保存しちまうの?これじゃ関連チェックなんてできないじゃん。
まいったな~、非連結フォームにしてモジュールで更新するしかないの?


・・・・・そんなことはありませんよ。こういう方法はどうですか?Accessのフォームに連結されているテーブルまたはクエリーデータは、基本的に、フォームでの更新を RollBack することはできません。
モジュール内でトランザクションを作り、その中でDocmdを使ってレコード保存を行ったとしても、トランザクション内での更新とはみなされず、たとえRollBackしても更新を元には戻せません。
(実は、フォームのレコードセットの clone を作って、それでトランザクション処理をすれば可能です。Googleで検索したけど意外といいサンプルがないので機会があれば作ります)
ここでよく、非連結フォームを作り、モジュールでデータの読み込み、更新動作を行おうとする設計者もいますが、これは得策ではないとなぼは思います。


なぜなら、この方法では帳票フォームが作れませんし、そもそも論としてそんなことするなら最初っから全部 Visual Studio で作ればいいからです。コーディング方法や文法はほとんど同じですし(カット&ペーストで移植というわけにはいきませんが)、Windows Form の方が比べ物にならないぐらい起動がスムーズです。できあがった EXE ファイルの大きさが MSAccess.exe とは比べ物になりませんし、数々のアドイン類を読み込む時間もバカにはなりません。(ランタイムならある程度は省けるのかもしれませんが、経験上それほど速くなる気がしません)
Access の利点をいっさい生かせないフォームを、Accessを使って作る価値はまったくないのです。


みなさんわりとご存知ないので驚きますが、フォームの更新前処理はキャンセルできます
更新前処理イベントの引数 Cancel に True を代入することにより、フォームのレコード保存動作をさせなくすることができるのです。
更新前処理イベントですから、レコードの移動による保存(Access はレコード移動の操作手段がたくさんあるため、完全禁止するのが難しい)、メニューバーからの保存、登録ボタンを押した時の Docmd による保存、すべての場合に対応できます。
つまり、すべての項目チェックを更新前処理で行い、エラーだったらCancel = Trueと一行書けば、お望みの機能「保存前に全てチェックして、エラーがあれば保存をさせない」を実現できるのです。
さらに、チェックがすべて OK だったら、「更新しますか? はい、いいえ」等のメッセージボックスを出し、ユーザーに確認させることもできます。こうすれば、不意のレコード移動で意に沿わない保存をしてしまうこともありません。
方法はもうおわかりかと思いますが、ユーザーが「いいえ」を選んだら Cancel = Trueしてしまえばよいのです。


では、帳票形式のフォームの場合どうでしょう。別のレコードには簡単に移動してしまいますし、「登録」ボタンはフォームヘッダーやフッターに1つだけあるでしょうから、1画面分の修正作業が全部済んだところで登録を確定したい、という動作は一見不可能のように思えますね。
そこでなぼは、編集用のワークテーブルを使っています。修正するデータを全てワークテーブルにとりこんで、ワークテーブルのデータをフォームを通して修正し、登録ボタンで本物ファイルに変更を反映します。方法は、更新クエリーでも DAO を使っても ADO を使っても Execute メソッドでもいいでしょう。

「そ、そんなのダメだよ、だってレスポンス超落ちるでしょ??」と思いますか?ところが、そうでもないのです。
たいがいの帳票形式フォームでは、フォームヘッダーで検索条件を入力しますよね。ある程度条件を絞り込み、該当するデータに対してだけ編集作業をしたほうが効率がよいというものです。
そこでフォームは、単なる帳票フォームではなく、メインーサブフォーム形式にします。
検索条件を入力し、検索ボタンを押すまでサブフォームのVisibleをFalse(見えない状態)にしておき、ワークテーブルへの該当データ抽出が終了してからサブフォームを表示するようにします。
検索してデータを絞り込んで表示するのも、ワークテーブルに抽出して全件表示するのも、体感速度はそれほど違わないのです。


また、この方法は ODBC 経由でサーバーにリンクしているテーブルに対して更新を行う場合にはたいへん有効です。
ODBC リンクテーブルに対して直接データメンテナンスしようとした場合、ネットワーク負荷の影響をもろに受け、レコード移動もままならないような状態もしばしば起こります。…最近はインフラ事情もよくなってますから、そこはあんまり気にしなくてもいいと思いますが。
また、データを画面上で修正し、レコードセレクタがえんぴつマーク状態のまま(変更が確定されていない状態)でマシンの前を離れた場合、長時間そのレコード(正しくはページ)がロックされた状態になっているはずです。このような状態はレコードを共有するのが前提のサーバー・クライアントアプリケーションにとって決して好ましいとは言えません。
ワークテーブルを使う運用にした場合、データを読み込んでワークテーブルに書き込むときにロックするも、ワークテーブルから修正内容をサーバーに反映させるときだけロックするも、そもそもロックしないのも、開発者の自由です。
(レコードにロック制御の項目を設ける など論理的にロックするしくみを自分で構築できる ということです これは汎用機エンジニアの人は大得意のはず)


いいことばかり書いてきましたが、デメリットが無いわけではありません。
結局は更新処理のすべてをモジュールで制御する必要が出てきますので開発工数はそれ相当にかかりますし、ワークテーブルに対してレコードを追加・削除・更新を繰り返すわけですから、当然 MDB ファイルはすごい勢いで肥大化します。(ワークテーブルをほかの MDB に作るのもいいかも。でもそこまでやるなら Access じゃなくてもいいですよねぇ)
MDB を閉じる前にはワークテーブルのレコードを全て削除し、閉じた後は必ず最適化するようなしくみを忘れてはいけません。


ただ、常々述べている通り、どんなシステムでも最適化のしくみは必須ですから、よもやこれを怠る方はもういらっしゃらないでしょうが。