データシート上の複数のレコードを一括して変更前の状態に復元するお手本

図4-6-1 作業明細の複数レコードを一括して復元するサンプルデータベース
このサンプルデータベースは、データシート上の複数レコードを一括して変更前の状態に復元します。データシート上のシングルレコードを変更前の状態に戻すには、メニューから復元のアイコン
をクリックします。ところが、データシート上の複数のレコードを変更前の状態に復元するアイコンは、用意されていません。このサンプルデータベースでは、DBEngineのトランザクション機能を使用することにより、複数のレコードを変更前の状態に復元します。複数のレコードを一括して復元する機能は、受注伝票入力、見積書入力などメイン/サブフォームを使用したアプリに適用すると効果があります。
サンプルデータベース(CH4-6.mdb)では、以下のノウハウを習得することができます。
◆ トランザクションを一括してコミット/ロールバックする方法
◆ メイン/サブフォームでサブフォームに表示されるレコードをアプリ独自で絞り込む行う方法
● データシート上の複数レコードを一括して変更前の状態に復元するフォームを作成するには
1 Access を起動して作業フォルダに、新規データベース CH4-6.mdbを作成します。
2 ファイルメニューから外部データの取り込み、インポートをクリックします。インポートのダイアログが表示されたら、CH4-6.mdbを選択してインポートボタンをクリックします。オブジェクトのインポートダイアログが表示されたら、テーブルタブをクリックしてすべて選択のボタンをクリックします。同様の手順で、クエリ、フォーム、モジュールタブをクリックしたらすべて選択をクリックして、最後にOKボタンをクリックしてインポート処理を完了させます。

図4-6-2 CH4-6.mdbからテーブル、クエリ、フォーム、モジュールの全てのオブジェクトをインポートする
3 データベースウィンドウからクエリ
をクリックしたら、qryWorkOrderDetailsを選択してデザインボタンをクリックして開きます。フィールドWoIDの抽出条件に[Forms]![frmWorkOrder]![WoID]を設定します。サブフォームのWoIDの抽出条件に、にメインフォームのWoIDを設定することにより、サブフォームにはメインフォームに関連したレコードのみ表示されます。

図4-6-3 サブフォームのレコードソースに抽出条件を設定してメイン/サブフォームを連動させる
4 データベースウィンドウからフォーム
をクリックしたら、frmWorkOrderをデザインモードで開きます。コンボボックスのスタッフIDの右側に、作業明細を一括復元するコマンドボタンを作成します。コマンドボタンのプロパティを表示させたら、標題に”作業明細の一括復元”を設定して、コントロールの名前を”cmdUnDoWODetails”に書き替えます。
次に、フォームフッターにラベルを作成して標題にコマンドボタンの説明を入力します。
表4-6-1 コマンドボタン/ラベルのプロパティ
|
コントロールの種類 |
プロパティ |
値 |
|
コマンドボタン |
名前 |
cmdUnDoWODetails |
|
標題 |
作業明細の一括復元 |
|
|
ラベル |
標題 |
作業明細の出勤/退勤時間を変更してから一括復元のボタンをクリックすると複数のレコードが変更前に復元されます |

図4-6-4 一括復元のコマンドボタンをラベルに追加した例
5 メニューからコードのアイコン
をクリックして、フォームモジュールを開きます。フォームモジュールの全てのコードを削除します。CH4-6.mdbを開いたら、frmWorkOrderのフォームモジュールをコピーして貼り付けます。フォームモジュールのソースコードは、リスト4-6-1を参照してください。メインフォームのコードを置換することにより、サブフォームのトランザクション処理が可能になります。メインフォームを保存して閉じます。
6 データベースウィンドウからサブフォームsfrWorkOrderDetailsを選択したら、メニューからコードのアイコン
をクリックしてフォームモジュールを表示させます。フォームの全てのコードを削除したら、CH4-6.mdbのsfrWorkOrderDetailsのフォームモジュールをコピーして貼り付けます。尚、フォームモジュールのソースコードは、リスト4-6を参照してください。サブフォームを保存して閉じます。
7 メインフォームfrmWorkOrderをビューモードで開いたら、明細行の複数レコードを変更します。明細行を変更すると、作業明細の一括復元のコマンドボタンが使用可能状態になりますので、クリックして一括復元します。次に、明細行の複数レコードを選択したら、DELキーを押して削除します。一括復元のコマンドボタンをクリックして、削除したレコードが復元されるか確認します。
8 一括復元処理が正常に動作することを確認したらメインフォームを保存して、Access を終了させます。
Sub Form_Current()イベントの処理
このイベントは、カレントレコードが移動するとき実行されます。このイベントでは、サブフォームのトランザクション処理を可能にするための準備をします。
DBEngine.CreateWorkspaceでは、フォーム固有のWorkspaceを作成します。CreateWorkspaceメソッドには、3個の引数を指定します。
・ Name 新規に作成するWorkspaceオブジェクトの名前を指定します。
・ User 新規に作成するWorkspaceオブジェクトの所有者を指定します。
・ Password 新規に作成するWorkspaceオブジェクトのパスワードを指定します。
mws.OpenDatabase(CurrentDb.Name)では、新規に作成したWorkspaceにカレントデータベース(CH1-14.mdb)を開きます。mws(0).QueryDefs("qryWorkOrderDetails")では、クエリコレクションから引数で指定したクエリオブジェクトを取得します。qdf(0) =
Me.WoIDでは、qryWorkOrderDetailsのWoIDに抽出条件を設定しています。QueryDefのOpenRecordsetメソッドで、qryWorkOrderDetailsを開いたら、レコードセットオブジェクトをサブフォームsfrWorkOrderDetailsのRecordsetプロパティに設定します。これでサブフォームのデータシートには、メインフォームのWoIDと連動する作業明細が表示されます。WorkspaceのBeginTransメソッドで、トランザクション処理の開始を宣言したら、mfInTransにTrueをセットします。最後に、一括復元のコマンドボタンのEnabled(使用可能)プロパティをFalse(無効)に設定しておきます。このコマンドボタンは、サブフォームの明細行を更新/削除したときに有効になります。
Sub cmdUnDoWODetails_Click()イベントの処理
このイベントは、一括復元のコマンドボタンがクリックされたときに実行されます。このイベントでは、トランザクション処理が開始(BeginTransメソッドが実行)されているかどうか調べて、WorkspaceのRollbackメソッドで変更されたレコードをBegineTransメソッド発行直前まで戻します。mfInTransにFalseを設定したら、Sub Form_Currentを呼んでサブフォームのレコードを再表示します。
Sub Form_Unload()イベントの処理
このイベントは、フォームを閉じる処理が開始されたときに実行されます。このイベントでは、BeginTransメソッドが実行されているとき、WorkspaceのCommitTransメソッドでレコードを強制的にディスクに書き込んでトランザクションを完了させます。Set mws = Nothingでは、新規に作成したWorkspaceオブジェクトを解放します。
リスト4-6-1
|
Option Compare Database Option Explicit Private mws As DAO.Workspace Private mfInTrans As Boolean Private Sub cmdUnDoWODetails_Click() If mfInTrans Then Me.Painting = False mws.Rollback mfInTrans = False Me.cboStaffID.SetFocus Call Form_Current Me.Painting = True End If End Sub Private Sub Form_Current() Dim db As DAO.Database Dim qdf As DAO.QueryDef Dim rs As DAO.Recordset
If mfInTrans = True Then mws.CommitTrans End If
Set mws = Nothing Set db = Nothing Set qdf = Nothing Set rs = Nothing
Set mws = DBEngine.CreateWorkspace("mws", "Admin", "") Set db = mws.OpenDatabase(CurrentDb.Name) Set qdf = mws(0).QueryDefs("qryWorkOrderDetails") qdf(0) = Me.WoID Set rs = qdf.OpenRecordset Set Me.sfrWorkOrderDetails.Form.Recordset = rs
mws.BeginTrans mfInTrans = True Me.cmdUnDoWODetails.Enabled = False End Sub Private Sub Form_Unload(Cancel As Integer) If mfInTrans = True Then mws.CommitTrans End If Set mws = Nothing End Sub Private Sub Form_Open(Cancel As Integer) Call SetAppTitle_FS("UnDo Multiple Records (C) " _ & Year(Date) & " by Akio Kasai") End Sub |
Sub Form_AfterDelConfirm()イベントの処理
このイベントは、サブフォームのレコード削除を承認したときに実行されます。このイベントでは、メインフォームの一括復元コマンドボタンのEnabled(使用可能)プロパティをTrue(有効)に設定します。
Sub Form_BeforeUpdate()イベントの処理
このイベントは、サブフォームのレコードが更新されたときに実行されます。このイベントでは、サブフォームのWo.IDにメインフォームのWoIDを設定します。WoIDは、メインとサブフォームを関連付けるための主キーです。メインフォームに作成したサブフォームのリンク子フィールド/リンク親フィールドプロパティにWoIDを設定して、メインフォームと同じWorkspaceにサブフォームのレコードセットを開いたときは、Accessが自動的にサブフォームのWoIDを設定してくれます。ところが、サブフォームのレコードセットが、メインフォームと異なるWorkspaceで開かれているときは、サブフォームのWoIDをアプリ独自で設定する必要があります。尚、この処理は、サブフォームに新規レコードを追加するときのみ必要になります。
Sub Form_Dirty()イベントの処理
このイベントは、サブフォームのレコードが変更されたときに実行されます。このイベントでは、メインフォームの一括復元コマンドボタンのEnabled(使用可能)プロパティをTrue(有効)に設定します。
リスト4-6-2
|
Option Compare Database Option Explicit Private Sub Form_AfterDelConfirm(Status As Integer) Me.Parent.cmdUnDoWODetails.Enabled = True End Sub Private Sub Form_BeforeUpdate(Cancel As Integer) If IsNull(Me!WoID) Then Me.WoID = Me.Parent.WoID End If Call ReCalcHours End Sub Private Sub Form_Dirty(Cancel As Integer) Me.Parent.cmdUnDoWODetails.Enabled = True End Sub Private Sub 休憩時間_MouseDown( _ Button As Integer, Shift As Integer, _ X As Single, Y As Single) If Button = acRightButton Then Call PopUpTime_FS(Me.休憩時間) End If End Sub Private Sub 出勤時刻_MouseDown( _ Button As Integer, Shift As Integer, _ X As Single, Y As Single) If Button = acRightButton Then Call PopUpTime_FS(Me.出勤時刻) End If End Sub Private Sub 退勤時刻_MouseDown( _ Button As Integer, Shift As Integer, _ X As Single, Y As Single) If Button = acRightButton Then Call PopUpTime_FS(Me.退勤時刻) End If End Sub Private Sub ReCalcHours() 就労時間 = ElapsedHours_FS( _ TimeValue(ElapsedTime2_FS(出勤時刻, 退勤時刻)) _ - 休憩時間, 15) 残業時間 = IIf(就労時間 > 8, 就労時間 - 8, 0) End Sub |