トップ > スキル : アプリケーション > VBA for Access > 応用編(データベースオブジェクト DAOとADO)

VBA_Access

DAO

カレントレコードの追加

テーブルにレコードを追加するには、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」と表示されますが、一旦テーブルを閉じてから再び開くとその表示はなくなり、削除していしたレコードがないことが確認できます。