ACCESS 特定レコードを抽出してフラグを立てる方法
ACCESSのフォームで特定レコードの抽出を行う処理は非常によく行われます。
さらにその抽出したレコードにフラグを立てて、別の処理に利用する場合も多々あります。
しかし、抽出したレコードにフラグを立てる処理は、少し作成が難しいのです。
今回は、ACCESSのフォームで特定レコードの抽出を行い、さらにフラグを立てる機能をご紹介します。
こんにちは。
はこにわガジェット (@hakoniwagadget) です。
ACCESSを使った売上管理、顧客管理などのデータベース開発を行っています。
ACCESSは使いこなすために少しスキルが必要なものの、うまく活用すればExcelよりも業務の効率化が図れます。
この記事ではACCESSで実際に作成したフォームやレポートを、その作成方法と共にご紹介していきます。
完成形
では最初に完成形を示します。
こちらは請求書を一括発行するためのフォームです。
請求対象の売上伝票が一覧表示されており、請求するものには右側の「請求」チェックを入れます。
上段の顧客名を選択すると、対象のレコードのみを抽出し、さらに請求フラグへのチェックを自動で行うようになっています。
フォームの作成
では、実際の作成方法を見ていきましょう。
フォームを作成する前に、フォームのレコードソースとなるテーブルを準備します。
今回はレコードソースとして「TRN_売上」というテーブルを準備しました。
売上情報がレコードとして保管されています。
これをもとに一覧表型のフォームを作成しています。
フォームをデザインビューで見るとこんな感じです。
中央の詳細セクションがレコードを表示する箇所になっています。
今回は、顧客名を更新した際にレコードの抽出とフラグ更新の処理が行われるようになっています。
そのため、フォームヘッダーにあるコンボボックス「顧客ID指定」の更新後処理にイベントプロシージャを設定しています。
VBAプログラミング
では、「顧客ID指定」の更新後処理に設定してあるVBAのプロシージャをご紹介します。
2つのプロシージャに分かれており、一つはフォームに設定していあるクラスモジュール、もう一つは共通で利用できる標準モジュールに作ってあります。
まず、クラスモジュール側のプロシージャがこちらです。
Private Sub 顧客ID指定_AfterUpdate()
Me.Filter = "顧客ID = " & Me!顧客ID指定
Me.FilterOn = True
Me.OrderBy = "処理日 DESC"
Me.OrderByOn = True
Call seikyu_flag(Me.Filter)
DoCmd.Requery
End Sub
そして、標準モジュール側のプロシージャがこちらです。
このプロシージャはクラスモジュール側のプロシージャから呼び出されます。
Dim cnn As ADODB.Connection
Dim rst1 As ADODB.Recordset
Public Sub seikyu_flag(filter_txt As String)
'フラグクリア
DoCmd.SetWarnings False
DoCmd.OpenQuery "UPD_請求フラグクリア"
DoCmd.SetWarnings True
'フラグ付与
'変数にADOオブジェクトを代入
Set cnn = CurrentProject.Connection
Set rst1 = New ADODB.Recordset
rst1.CursorLocation = adUseClient
'レコードセットを取得
rst1.Open "TRN_売上", cnn, adOpenKeyset, adLockOptimistic
rst1.Filter = filter_txt
'請求対象がない場合は処理終了
If rst1.RecordCount = 0 Then
Exit Sub
End If
rst1.MoveFirst
Do Until rst1.EOF
rst1!請求 = True
rst1.Update
rst1.MoveNext
Loop
'終了処理
rst1.Close: Set rst1 = Nothing
cnn.Close: Set cnn = Nothing
End Sub
開発方針
ACCESSでテーブルのレコードを自動更新する方法は2つあります。
1.更新クエリを使う
2.VBAでADOを使う
今回は2.VBAでADOを使う方法を採用しています。
基本的には更新クエリの方がVBAのコードを記述しなくてよいので簡単です。
ですので、更新クエリで対応できる場合はそちらを選択した方が良いでしょう。
しかし、更新クエリの場合はあらかじめレコードの抽出条件を設定してクエリを作っておく必要があります。
今回のようにレコードの抽出条件が動的に変化する場合はVBAでADOを使った方が対応しやすくなります。
今回は抽出条件をフォームで指定しているのが顧客ID指定コンボボックス一つなので、更新クエリでも作ろうと思えば作れます。
そちらに興味がある方は下記の記事でクエリの抽出条件でフォームを参照させる方法を載せておりますのでご覧ください。
クラスモジュール
さて、コードの解説に戻ります。
クラスモジュール側のプロシージャから解説していきます。
最初の
Me.Filter = "顧客ID = " & Me!顧客ID指定
Me.FilterOn = True
Me.OrderBy = "処理日 DESC"
Me.OrderByOn = True
の部分は、顧客ID指定コンボボックスで指定した値に基づいて、フォームに表示するレコードの抽出を行っています。
Filterプロパティを使って、顧客IDが顧客ID指定コンボボックスと同一のレコードのみが表示されます。
そしてその後に
Call seikyu_flag(Me.Filter)
でもう一つのプロシージャであるseikyu_flagを呼び出しています。
この際、()内には引数として先ほど設定したFilter文を格納しています。
標準モジュール
次に、呼び出された標準モジュールの内容を解説します。
このモジュールではADOを使って、レコードソースである「TRN_売上」の請求フラグを更新しています。
最初に、既に設定されている請求フラグをクリアします。
'フラグクリア
DoCmd.SetWarnings False
DoCmd.OpenQuery "UPD_請求フラグクリア"
DoCmd.SetWarnings True
ここでは、UPD_請求フラグクリアというクエリを実行してフラグをクリアしています。
UPD請求フラグクリアのクエリをデザインビューで見ると以下のようになっています。
TRN_売上テーブルの「請求」フィールドをFalseに更新する更新クエリです。
これを、DoCmd.OpenQueryでVBAから実行しています。
この際、クエリ実行の確認メッセージが出てしまうので、DoCmd.SetWarningsを使ってアラート表示が一時的に出ないようにしています。
次に記載しているこの部分はADOの設定ですね。
'変数にADOオブジェクトを代入
Set cnn = CurrentProject.Connection
Set rst1 = New ADODB.Recordset
rst1.CursorLocation = adUseClient
'レコードセットを取得
rst1.Open "TRN_売上", cnn, adOpenKeyset, adLockOptimistic
rst1というレコードセットに「TRN_売上」テーブルをセットしています。
その後、
rst1.Filter = filter_txt
で「TRN_売上」テーブルに引数で指定したfilter_txt、つまりフォーム側で設定したMe.Filterの抽出条件を設定してレコードを抽出します。
次に記載している
'請求対象がない場合は処理終了
If rst1.RecordCount = 0 Then
Exit Sub
End If
はエラー回避ルーチンです。
ADOでレコードセットを使って更新処理などを行う際は、対象レコードがないとエラーになってしまう場合があります。
そのため、RecordCountを使ってレコード数が0の場合はプロシージャを中断する処理を毎回入れておくとよいでしょう。
そしていよいよ以下でループ処理を使って請求フラグを「True」に更新しています。
Do Until rst1.EOF
rst1!請求 = True
rst1.Update
rst1.MoveNext
Loop
最初にfilter_txtを使ってレコードセットを抽出していますので、フォームで表示されたレコードだけにフラグを付けることができる、というわけです。
これでフォームで指定したレコードのみを更新することができました。
以上、特定レコードを抽出してフラグを立てる方法をご紹介しました。
ACCESSを使いこなせば、業務の効率化や自動化が実現できます。
しかし、自分でACCESSを学ぶには時間がない、難しそうで不安、という方も多いでしょう。
そんな時は、ACCESS開発歴20年以上、過去に100以上のACCESSデータベースを開発してきた私(@hakoniwagadget)にお任せください。
ACCESSの新規開発、既存のACCESSの修正、ACCESSの操作レッスンなど様々なサービスをご提供しています。
ご興味のある方は下記のサービス一覧をご覧ください。
最後までお読みいただき、ありがとうございました。