【MS Access】配列の代わりに作ったRecordsetがコンボボックスのアイテムに表示できない

MS Access
スポンサーリンク

以前も上手くいかなくて、別の方法で代用したんですが、今回できる方法を見つけたので、ブログに残しておきます。

 

Accessのコンボボックスにレコードセットを代入する

この操作自体はよくある話で、通常はCombboxオブジェクトのRecordsetプロパティに、Setを使ってレコードセットを代入してあげれば済みます。
ただ、以前VBScriptの記事で書いた、「配列の代わりにレコードセットを使う」

【VBScript】配列の代わりにレコードセットを使う方法
今回はVBScriptの配列の代わりにレコードセットを使用する方法を紹介します。 VBScriptの配列は使いづらい ...

のように、Recordsetオブジェクトを生成して、AddNewで行追加して、行の値をセットし、Updateしたレコードセットをコンボボックスに代入しようとすると、実行時にエラーにはならないが、コンボボックスのアイテムに何も表示されないという現象が起こります。

その際のサンプルコードは以下です。

Sub Set_CombItem()

    Dim rs As ADODB.Recordset
    
        Set rs = New ADODB.Recordset
        
        rs.Fields.Append "列1", adInteger
        rs.Fields.Append "列2", adVarChar, 50
        
        rs.Open
        
        rs.AddNew
            rs("列1").Value = 1
            rs("列2").Value = "あいうえお"
        rs.Update

        rs.AddNew
            rs("列1").Value = 2
            rs("列2").Value = "かきくけこ"
        rs.Update

        rs.AddNew
            rs("列1").Value = 3
            rs("列2").Value = "さしすせそ"
        rs.Update

		Set Me.cmb_コンボボックス.Recordset = rs
		Me.cmb_コンボボックス.Requery
		
		rs.Close
		
		Set rs = Nothing
End Sub

また、コンボボックスの表示は以下の画像のように、複数行アイテムは存在はしているのに、値は空の状態で開きます…。

なんですかねぇ、これ…。

ネットで調べてもなかなか原因がわからず、途方に暮れましたが、ようやく理由が判明しました。

 

対策1 RecordsetオブジェクトのUpdateBatchメソッドを実行

どうもRecordsetオブジェクトのUpdateメソッドだけではレコードセットの実体のデータとして反映されていなかった模様??

データベースのトランザクション管理で未コミット状態のようなものみたいです。

で、コンボボックスにレコードセットを代入する前にRecordsetオブジェクトのUpdateBatchメソッドを実行することで、未コミット状態のレコードセットがコミットされて実体のデータになり、コンボボックスに代入して表示出来るようになります。

以下がサンプルコードです。

Sub Set_CombItem()

    Dim rs As ADODB.Recordset
    
        Set rs = New ADODB.Recordset
        
        rs.Fields.Append "列1", adInteger
        rs.Fields.Append "列2", adVarChar, 50
        
        rs.Open
        
        rs.AddNew
            rs("列1").Value = 1
            rs("列2").Value = "あいうえお"
        rs.Update

        rs.AddNew
            rs("列1").Value = 2
            rs("列2").Value = "かきくけこ"
        rs.Update

        rs.AddNew
            rs("列1").Value = 3
            rs("列2").Value = "さしすせそ"
        rs.Update
		
		'以下の一行を追加
		rs.UpdateBatch
		
		Set Me.cmb_コンボボックス.Recordset = rs
		Me.cmb_コンボボックス.Requery
		
		rs.Close
		
		Set rs = Nothing
End Sub

 

対策2 RecordsetオブジェクトのOpen時にLockTypeをadLockOptimisticで指定する

対策1の対応をとらない場合に、この対策2の対応でもコンボボックスにレコードセットを代入して表示出来るようになります。

このadLockOptimisticの詳細はMicrosoftのページを参照してください。

LockTypeEnum

こちらもデータベースのトランザクション管理における、未コミット前の行の参照を許す処理と同様の状態になり、この様にOpenしたレコードセットであれば、コンボボックスに代入しても行が表示できます。

サンプルコードは以下です。

Sub Set_CombItem()

    Dim rs As ADODB.Recordset
    
        Set rs = New ADODB.Recordset
        
        rs.Fields.Append "列1", adInteger
        rs.Fields.Append "列2", adVarChar, 50
        
        '以下の一行を変更
        rs.Open , , , adLockOptimistic
        
        rs.AddNew
            rs("列1").Value = 1
            rs("列2").Value = "あいうえお"
        rs.Update

        rs.AddNew
            rs("列1").Value = 2
            rs("列2").Value = "かきくけこ"
        rs.Update

        rs.AddNew
            rs("列1").Value = 3
            rs("列2").Value = "さしすせそ"
        rs.Update
		
		Set Me.cmb_コンボボックス.Recordset = rs
		Me.cmb_コンボボックス.Requery
		
		rs.Close
		
		Set rs = Nothing
End Sub

対策1と対策2を比較した場合、大して重要ではないですが、未コミット前の状態をわざわざ参照してコンボボックスに表示させる必要性は無いので、対策1にように、いったんレコードセットを確定してコンボボックスにセットするのが望ましいとは思います。

もっと他に良い対応があるかも知れませんが、まぁ取り敢えずレコードセットをコンボボックスに無事セットできたため、良しとしましょう。

ではでは、皆さまごきげんよう。