トップ > スキル : アプリケーション > VBA for Access > 応用編(データベースオブジェクト DAOとADO)
カレントレコードの追加
テーブルにレコードを追加するには、AddNewメソッドとUpdateメソッドを使用します。但し、レコードを追加できるのはテーブルタイプ、ダイナセットタイプのRecordsetオブジェクトになり、スナップショットタイプは読み取り専用なので追加はできません。
◆ AddNewメソッドとUpdateメソッド
レコードを追加する時は、まずAddNewメソッドを実行します。実行するとレコードセット内に新しいレコードが1件作成され、それを編集することになります。しかし、これは仮のレコードになり、実際の追加は行われていません。編集した内容を反映する時に、Updateメソッドを使用し、その際追加したレコードが保存されることになります。
【※ 追加される位置】
AddNewメソッドを使ってレコードが追加される位置は、Recordsetオブジェクトの種類によって異なります。
- テーブルタイプ(インデックスなし):Recordsetオブジェクトの最後に追加される
- テーブルタイプ(インデックスあり):インデックス情報に従って適切な位置に挿入される。
- ダイナセット:Recordsetオブジェクトの最後に追加される。
《 記述例 》
「T_商品リスト」テーブルのレコードセットの最後に1件レコードを追加するには、以下のように記述します。
Sub レコードの追加() Dim db As DAO.Database Dim rs As DAO.Recordset Dim txtId As String Dim varRet As Variant Dim curPrice As Variant Dim dataMsg As String Set db = CurrentDb() Set rs = db.OpenRecordset("T_商品リスト") txtId = InputBox("追加IDを入力してください。") If txtId = "" Then MsgBox "IDが空白です": Exit Sub varRet = InputBox("追加商品を入力してください。") If varRet = "" Then MsgBox "商品名が空白です": Exit Sub curPrice = InputBox("単価を入力してください") If curPrice = "" Then ←Null(空白)値はVariant型のみ使用可 MsgBox "単価が空白です" Exit Sub ElseIf IsNumeric(curPrice) = False Then ↑入力データが数値型に変換できるかチェック MsgBox "数値を入力してください。" Exit Sub End If dataMsg = "商品名" & varRet & "を追加します。" If MsgBox(dataMsg, vbCritical + vbOKOnly) = vbOK Then rs.AddNew rs!ID = txtId rs!商品名 = varRet rs!単価 = curPrice rs.Update End If rs.Close: Set rs = Nothing db.Close: Set db = Nothing End Sub
動作を確認すると、まずID番号の入力を促す入力ボックスが表示されます。IDを入力します。

次に商品名を入力します。

次に単価を入力します。

商品を追加する旨のメッセージが表示されます。

テーブルを確認するとテーブルの末尾に追加されたレコードが表示されています。

入力ボックスで処理を促す時に、ユーザは常に正しいデータを入力するとは限りません。数値のところを文字列にしたり、その逆もあります。また、入力せずに[OK]ボタンを押すと空白を入力することになります。そのような過ちがあった時に、それに対する処理もしっかりと対処できる記述も忘れないようにします。
カレントレコードの検索
レコードの検索のときは、Seekメソッド、Find系メソッドを使用します。テーブルセットタイプでは、Seekメソッドを使い、ダイナセットタイプとスナップショットタイプではFind系メソッドを使うように使い分けます。また、Seekメソッドを使う場合は、レコードセットにインデックスが設定されている必要がありますが、この方が高速で検索結果を表示できます。
◆ Seekメソッド
テーブルタイプのレコードセットの場合に利用します。テーブルに設定されているインデックスを使って検索するので、このメソッドを使用する前にIndexプロパティでカレントインデックスを作成する必要があります。
【書式】 オブジェクト変数.Seek 比較記号,キー1[,キー2][,キーn]
- 比較記号:文字列式の「<」、「<=」、「=」、「>=」、「>」のいずれかを指定
- キー1…キーn:RecordsetオブジェクトのIndexプロパティの値で指定された、カレントインデックスのフィールドに対応する1つ以上の値を指定
レコード検索をする時、該当するレコードの有無を判断するには、NoMatchプロパティを使います。
◆ NoMatchプロパティ
レコードが見つかった場合:False
レコードが見つからない場合:True
NoMatchプロパティがTrueの時、カレントレコードは未定義になりますので、この時にカレントレコードを参照するとエラーになります。
《 記述例 》
特定のID番号でレコードを検索するには、次のような記述をします。
Sub Seekで検索() Dim db As dao.Database Dim rs As dao.Recordset Dim seekData As Variant Set db = CurrentDb() Set rs = db.OpenRecordset("T_商品リスト") seekData = InputBox("検索するIDを入力してください", "検索ID") rs.Index = "ID" rs.Seek "=", seekData If Not rs.NoMatch Then seekData = "ID:" & rs!ID & vbNewLine seekData = seekData & "商品名:" & rs!商品名 & vbNewLine seekData = seekData & "単価:\" & rs!単価 Else seekData = "該当レコードなし" End If MsgBox seekData rs.Close: Set rs = Nothing db.Close: Set db = Nothing End Sub
動作を実行すると、まず検索するIDを入力するダイアログボックスが表示されます。検索したいIDを入力します。

該当したレコードをメッセージボックスで表示します。

Seekメソッドはインデックスを設定しておく必要があります。ここでは、「T_商品リスト」テーブルのIDフィールドは主キーとして設定していますので、自動的にインデックスは作成されています。
もし、商品名で検索するのであれば、あらかじめテーブルにてフィールドプロパティでインデックスを有効にしておく必要があります。

◆ Find系メソッド
ダイナセットタイプ、スナップショットタイプのレコードセットでは、Find系メソッドを使います。これらメソッドはカレントインデックスの指定は必要ありません。Find系メソッドには以下のような種類があります。
種類 | 機能 |
FindFirst | Recordsetオブジェクトの先頭から末尾のレコードに向かって検索。 |
FindLast | Recordsetオブジェクトの末尾から先頭のレコードに向かって検索。 |
FindNext | Recordsetオブジェクトのカレントレコードから末尾のレコードに向かって検索。 |
FindPrevious | Recordsetオブジェクトのカレントレコードから先頭のレコードに向かって検索。 |
これらのメソッドは、開いているRecordsetオブジェクトにレコードが対象となります。
フォーム上で商品に関するレコードを検索できるものを作成します。
図のように非連結テキストボックスと非連結コンボボックス、コマンドボタンを配置してフォームを割く瀬瑛しておきます。それぞれのコントロール名は、ラベルの標題と同じにしています。コンボボックスの名前は「商品名検索」、コマンドボタンは「検索」とします。

また、コンボボックスには、「T_商品リスト」テーブルから、商品名を表示されるように[データ]タブの[値集合ソース]と[値集合タイプ]、[連結列]プロパティに図のような設定を行います。

[検索]コマンドボタンのプロパティシートを開き、[イベント]タブの[クリック時]プロパティを「イベントプロシージャ」にして、右端のビルドボタンをクリックします。

VBEウィンドウに切り替わり、「Private Sub 検索_Click()」プロシージャのひな型が表示されます。

《 記述例 》
商品名で検索して、その商品のレコードを表示するには、SubとEnd Subの中に次のようなコードを記述します。
Private Sub 検索_Click() Dim db As DAO.Database Dim rs As DAO.Recordset Dim findData As String Set db = CurrentDb() Set rs = db.OpenRecordset("T_商品リスト", dbOpenDynaset) findData = "商品名='" & Me!商品名検索 & "'" rs.FindFirst findData If Not rs.NoMatch Then With Me .ID = rs!ID .商品名 = rs!商品名 .単価 = rs!単価 End With End If rs.Close: Set rs = Nothing db.Close: Set db = Nothing End Sub
動作を確認します。
「F_商品検索」フォームを開き、コンボボックスの一覧から任意の商品名を選択します。

[検索]ボタンをクリックすると、指定した商品名のレコードが表示されます。

【検索条件の留意点】
検索条件がテキスト型、数値型によって記述方法が変わります。
- テキスト型の場合
- findData = "商品名='" & Me!商品名検索 & "'"
- 数値型の場合
- findData = "ID=" & Me!ID検索
テキスト型は文字列の前後をシングルクォーテーション(')で囲む必要があります。数値型のような数字であれば、囲む必要はありません。
もし、記述を間違えると、以下のようなエラーメッセージが表示されます。

カレントレコードの削除
テーブルからレコードを削除するにはDeleteメソッドを使用します。但し、レコードを削除できるのはテーブルタイプ、ダイナセットタイプのRecordsetオブジェクトになり、スナップショットタイプは読み取り専用なので削除はできません。
削除されるレコードは、カレントレコードのみなので、全レコードを削除するには繰り返し処理(Do Loopステートメントなど)を利用してカレントレコードを移動させて削除します。
また、レコードを削除する際には警告メッセージは表示されなく、削除されたレコードは復元できません。削除する際は、If文などを利用してユーザに削除の確認をさせてから実行するようにします。
◆ Deleteメソッド
削除の対象となるレコードは、Recordsetオブジェクトで読み込まれているレコードセット内のカレントレコードになります。そのレコードに対してDeleteメソッドを実行すると、そのレコードが削除されます。
《 記述例 》
IDを指定してレコードを削除するには、次のような記述をします。
Sub レコード削除() Dim db As DAO.Database Dim rs As DAO.Recordset Dim delId As String Dim delOK As Integer Set db = CurrentDb() Set rs = db.OpenRecordset("T_商品リスト", dbOpenDynaset) delId = InputBox("削除するIDを入力してください", "レコード削除") rs.FindFirst "ID =" & delId If rs.NoMatch = False Then delOK = MsgBox("ID" & delId & "を削除しますか?", vbOKCancel + vbCritical) If delOK = vbOK Then rs.Delete Else Exit Sub End If End If rs.Close: Set rs = Nothing db.Close: Set db = Nothing End Sub
動作確認では、先ほど追加した[ID]が「12」のLANケーブルのレコードを削除しています。
削除するレコードのID番号を促す入力ボックスが表示されます。

削除するかどうかを再確認させているメッセージを表示します。

テーブルから[ID]の「12」が削除されていることが確認できます。

テーブルを開いた状態で削除を実行すると、削除したレコード箇所には「#Deleted」と表示されますが、一旦テーブルを閉じてから再び開くとその表示はなくなり、削除していしたレコードがないことが確認できます。