以前も上手くいかなくて、別の方法で代用したんですが、今回できる方法を見つけたので、ブログに残しておきます。
Accessのコンボボックスにレコードセットを代入する
この操作自体はよくある話で、通常はCombboxオブジェクトのRecordsetプロパティに、Setを使ってレコードセットを代入してあげれば済みます。
ただ、以前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にように、いったんレコードセットを確定してコンボボックスにセットするのが望ましいとは思います。
もっと他に良い対応があるかも知れませんが、まぁ取り敢えずレコードセットをコンボボックスに無事セットできたため、良しとしましょう。
ではでは、皆さまごきげんよう。