[Accessマクロ] 保存ボタンを押されたときのみレコードを確定させる機能を実装する
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だったら、すなわち「はい」が押されて問題なくレコードの更新が済んだ場合のみ、このボタンの本来の機能である「ウィンドウを閉じる」アクションが実行される、という動きになっています。
ちなみに、そのままだと「いいえ」が押された場合に「保存に失敗しました」という旨のエラーメッセージが出力されてしまうので、それをスキップするために、冒頭で「エラーが起きてもメッセージを出さずに次へ進む」という宣言を入れておきます。
デフォルトの閉じるボタンを無効化
最後にもうひと手間、せっかくエラー処理などいろんなマクロを組んで「閉じる」処理をしてあるのに、フォーム自体の閉じるボタンで閉じられてしまうと意味がないので、こちらを無効化しておきます。
動作確認
では上書き保存していったん閉じてから、「メニュー」フォームのボタンをクリックして起動してみましょう。適当に値を変更すると、左上の部分が鉛筆マークになって編集中になります。
この状態で「保存」ボタンを押せば更新されますし、「戻る」ボタンを押せば変更前の状態に戻ります。
編集中の状態でレコードを移動したり、「閉じる」ボタンを押したりすると、このようなメッセージボックスが出力されます。「いいえ」を押すと、このメッセージが閉じてさきほどの編集中の状態に戻ります。「はい」を押すと、変更が保存され、移動なら移動、閉じるなら閉じるの動作が続行されます。
5件のコメント
このマクロを丁度探していました!
ありがとうございます。
Boxというクラウドサーバーを使っていると、レコードをちょっといじるだけで保存されてしまいます。
このマクロがあれば、そんなことはおこらないですね!
これをVBAに変換できれば、なお良いのですが。。。
ViViさん、コメントありがとうございます。
お役に立てて嬉しいです! この処理はおそらくVBAで実装している方のほうが多くて、それを敢えて「VBAではよくあるヤツだろうけどマクロのみでやるには?」という趣旨で書いた記事ですので、けっこう面倒くさいのが難点ですね…。
以下のように、VBAでの実装方法を提示してくださっている記事はたくさんありますので、お使いの環境に望ましいほうを選択していただければと思います。
はじめまして。
私はAccess初心者なので、こちらのマクロがコマンド一つ一つに理由が説明されていてとても分かりやすいです。
ひとつ質問があるんですがよろしければ教えてください。
保存ボタンで、レコードの保存の他に追加クエリを実行したい場合は以下で良いんでしょうか。(カレントレコードを履歴テーブルに追加&カレントレコードの更新は単票入力で日時を代入(新規レコード更新はなし))
今考えてるのは、一行目にメッセージの設定の「いいえ」、「レコードの保存」の前に日時の各「値の代入」と「クエリを開く」を設置したら良いのかなと。
ただそうした場合、更新前処理の設置はどうするのか分からないんです。
ご都合がよろしければよろしくお願いいたします。
追記です。
突然の質問で大変失礼しました。
自分なりにあれこれやってみたら何とかできました。
更新前処理では、とにかく保存ボタン以外でレコードの保存をさせたくないので、TempVars!onSave=Falseの後に、メッセージボックスをOKオンリーにして「キャンセルします」→イベントの取り消し
保存ボタンでは、メッセージボックスを足し保存して良いかどうか、はいならレコードの保存の前に日時の値の代入と追加クエリを開くを追加
Elseでイベントの取り消し、最後にonSaveをFalse
(最初にメッセージの設定をいいえ)
閉じるボタンでは、レコードの保存を削除し、MacroError=0の後にメッセージボックスを足し、入力途中なら→閉じるかどうか、はいならレコードを元に戻す、閉じる
Elseでイベントの取り消し
マクロのプロの方から見たら滅茶苦茶かもしれませんが、初心者だとこんな感じになりました。
こうなるまで試して1週間はかかりましたが、このページが無かったら、保存させたくないやり方にいまだにたどり着けず四苦八苦していたことでしょう。
掲載していただいて本当にありがとうございました。
マクロ勉強中さん、コメントありがとうございます! ちょうど繁忙期にさしかかってしまってお返事が遅くなってしまい申し訳ありませんでした。そして、その間に自己解決されたとのことで、おめでとうございます! 滅茶苦茶なんてことは決してなくて、ご自身の力で理想の動きを作れたのであれば、なによりそれが一番です! だいぶ前に書いた記事ですが、熟読してくださって、1つ1つの動きを理解しながら頑張っていただけたのだろうなということが伝わってきて、こちらこそ本当に嬉しいです。読んでいただいて、ありがとうございます。
ご自身で作ったマクロは、のちのちメンテナンスもしやすいですし、「こうしてみよう」という仮説も立てやすくなりますし、いいことづくめです。ぜひまたいろいろ作ってみてくださいね。
コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)
YouTubeでQ&Aコンテンツを企画しています
運営しているYouTubeチャンネルで、ご相談やご質問を募集しています。動画のコメントやお問い合わせページからお気軽にご相談をお寄せください。