[Accessマクロ] 保存ボタンを押されたときのみレコードを確定させる機能を実装する
![[Accessマクロ] 保存ボタンを押されたときのみレコードを確定させる機能を実装する](https://ateitexe.com/wp-content/uploads/2018/10/181024eye.png)
Accessでテーブルのデータを変更した場合、保存ボタンを押すか、レコードを移動したりテーブルを閉じたりすると変更が保存されます。テーブルを元にフォームを作成した場合もこのルールと同じで、フォーム上でレコードを移動したりフォームを閉じることで、自動で変更が保存される仕様になっていますよね。これを、ボタンを用意して「勝手に保存させない」機能をマクロのみで実装してみます。
背景というか
この記事の内容は、2018/11/1発売の著書、Accessマクロ入門を執筆する前段階でサンプルを作ったときに、張り切りすぎて機能盛り盛りにしてしまい、ローカルじゃない変数とかも使って初学者向けにはふさわしくないね…、という話になってカットしたネタです。
もったいないのでブログに書きます! たしかにこれはVBAでやるほうが楽かな!? マクロでこんな需要ないかな!?!? でもマクロでもできるんだよ!!! という気持ちを込めて。
準備

テーブルを元にした連結フォームがあったとします。

ボタンを3つ設置します。まずは設置だけでマクロはあとで。

それとは別に非連結の「メニュー」フォームを作りボタンをつけて、そこからさっきのフォームが開くようにマクロを作ります。ポイントは、「ウィンドウモード」を「ダイアログ」にしておくことです。

こうしておくと、ボタンをクリックしてフォームが開くとき、Access内にタブで開くのではなく、図のようにポップアップで開き、このポップアップウィンドウが閉じるまで他のウィンドウの操作ができなくなります。
今回、フォームが開いたときに「一時変数」を作成し、閉じるときにその変数を削除する、という工程を作るので、「ダイアログ」にしておくと「開きっぱなし」状態を防げるので、ここは忘れずにやっておいてください。
フォームイベントへの実装

では、連結フォームにマクロを組みます。ボタンのクリックイベントは後にして、先にフォームに対するイベントマクロを、図のように3つ作りましょう。
読み込み時

フォームの読み込み時に「一時変数」を設定します。一時変数はマクロの枠を超えて全体で使える、VBAで言うPublicな変数です。ちなみに1つのマクロの中でしか使えないPrivateな変数は「ローカル変数」です。
デフォルトはFalseにしておいて、保存ボタンが押されたときだけTrueになる想定のフラグとして使います。
更新前処理

このイベントは「保存ボタンが押された時」「レコードを移動しようとした時」「フォームが閉じられようとしている時」、内容に変更がある場合は保存前にすべてここを通るので、ここへ細工をします。
一時変数であるonSave
フラグがFalseだったとき、すなわち「保存ボタンが押されていないのに更新されようとしている場合」は、「保存して続行するか」に対して「はい」「いいえ」の2択を要求するメッセージボックスを出力します。そしてそれが「いいえ」だった場合は更新をキャンセルします。
最後にonSave
フラグをFalseにしておきます。フラグを落としておかないと一度「保存」ボタンを押したらずっとTrueになったままになってしまうので。
メッセージボックスのボタンの種類や返り値を示す整数はこちらを参照してください
閉じる時

一時変数は自動で削除されないので、フォームが閉じると共に破棄します。
ボタンのクリックイベントへの実装

今度は、この3つのボタンに対してクリックイベントマクロを実装します。
「保存」ボタンクリック時

onSave
フラグをTrueにしてから保存コマンドを実行します。これによりこのボタンを押したときは「更新前処理」イベントを通ったときに「保存して続行するか」ウィンドウが出力されず、データは更新されます。
「戻す」ボタンクリック時

これは「Esc」キーを押しても同じ動きなので必須ではないのですが、ユーザーからしたらあったほうが便利かもしれません。レコードが編集中だった場合、変更前の状態に戻します。
「閉じる」ボタンクリック時

このマクロの肝は、「保存コマンドを実行」してからの「フォームを閉じる」アクションです。
編集中の状態で保存コマンドが実行されると「更新前処理」イベントを通り、「保存して続行するか」ウィンドウが出力されるのですが、そこで「はい」を押された場合は良いのですが、「いいえ」を押された場合はキャンセルとなり、このマクロの「保存コマンドを実行」するアクションが失敗することになります。
失敗するということは「エラーが発生する」ことになるのですが、エラーは[MacroError]
を使ってそのエラーNoを取得することができます。そして、エラーの発生がなかった場合は、このNoが0となります。これを利用して、エラーNoが0だったら「はい」を押された、という判定ができます。
エラーNoが0だったら、すなわち「はい」が押されて問題なくレコードの更新が済んだ場合のみ、このボタンの本来の機能である「ウィンドウを閉じる」アクションが実行される、という動きになっています。
ちなみに、そのままだと「いいえ」が押された場合に「保存に失敗しました」という旨のエラーメッセージが出力されてしまうので、それをスキップするために、冒頭で「エラーが起きてもメッセージを出さずに次へ進む」という宣言を入れておきます。
デフォルトの閉じるボタンを無効化

最後にもうひと手間、せっかくエラー処理などいろんなマクロを組んで「閉じる」処理をしてあるのに、フォーム自体の閉じるボタンで閉じられてしまうと意味がないので、こちらを無効化しておきます。
動作確認

では上書き保存していったん閉じてから、「メニュー」フォームのボタンをクリックして起動してみましょう。適当に値を変更すると、左上の部分が鉛筆マークになって編集中になります。
この状態で「保存」ボタンを押せば更新されますし、「戻る」ボタンを押せば変更前の状態に戻ります。

編集中の状態でレコードを移動したり、「閉じる」ボタンを押したりすると、このようなメッセージボックスが出力されます。「いいえ」を押すと、このメッセージが閉じてさきほどの編集中の状態に戻ります。「はい」を押すと、変更が保存され、移動なら移動、閉じるなら閉じるの動作が続行されます。
2件のコメント
このマクロを丁度探していました!
ありがとうございます。
Boxというクラウドサーバーを使っていると、レコードをちょっといじるだけで保存されてしまいます。
このマクロがあれば、そんなことはおこらないですね!
これをVBAに変換できれば、なお良いのですが。。。
ViViさん、コメントありがとうございます。
お役に立てて嬉しいのですが、この処理はおそらくVBAで実装している方のほうが多くて、それを敢えて「VBAではよくあるヤツだろうけどマクロのみでやるには?」という趣旨で書いた記事ですので、けっこう面倒くさいです…。
以下のように、VBAでの実装方法を提示してくださっている記事はたくさんありますので、お使いの環境に望ましいほうを選択していただければと思います。
コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)