web-dev-qa-db-ja.com

VBAを使用してComboBoxにRecordsetを設定する方法

専門家の交換 および teck republic で、combobox.recordsetプロパティを使用してAccessフォームにコンボボックスを設定する方法についての資料がいくつかあります。

これらのコントロールには通常、コントロールの「rowsource」プロパティに「SELECT *」文字列が入力され、アプリのクライアント側で使用可能なテーブルまたはクエリを参照します。サーバー側のデータをコンボボックスに表示する必要がある場合は、一時的なローカルテーブルを作成し、要求されたレコードをインポートします。これは、特に大きなテーブルでは時間がかかります。

レコードセットを使用してコンボボックスコントロールにデータを入力できると、ユーザーはサーバー側からデータを直接表示できます。

前の2つの例に触発されて、次のようにコードを記述しました。

Dim rsPersonne as ADODB.recordset
Set rsPersonne = New ADODB.Recordset

Set rsPersonne.ActiveConnection = connexionActive
rsPersonne.CursorType = adOpenDynamic
rsPersonne.LockType = adLockPessimistic
rsPersonne.CursorLocation = adUseClient

rsPersonne.Open "SELECT id_Personne, nomPersonne FROM Tbl_Personne"

fc().Controls("id_Personne").Recordset = rsPersonne

どこ:

  • connexionActive:私のデータベースサーバーへの永続的なADO接続です
  • fc():現在/アクティブなフォームです
  • コントロール( "id_Personne"):会社のスタッフリストを入力するためのコンボボックスコントロールです
  • 2003年のアクセスバージョン

残念ながら、それは機能しません!

デバッグモードでは、要求された列とデータを使用してレコードセットが適切に作成され、コンボボックスコントロールに適切に関連付けられていることを確認できます。残念ながら、フォームを表示すると、レコードがない空のコンボボックスが表示され続けます。どんな助けでも大歓迎です。

編集:

このレコードセットプロパティは、標準のコントロールオブジェクトではなく、特定のコンボボックスオブジェクトで実際に使用できます。数日前に、このプロパティを発見して非常に驚きました。コンボボックスのコールバック関数を使用するか、コンボボックスの「addItem」メソッドをリストに入力しようとしました。これらはすべて時間がかかります。

8

トリックを見つけました...コンボボックスコントロールの「rowSourceType」プロパティを「Table/List」に設定する必要があります。表示は問題ありませんが、メモリに別の問題があります。これらのADOレコードセットをフォームで使用しているため、フォームを参照するたびにAccessのメモリ使用量が増加しています。参照を停止するかフォームを閉じることによってメモリが解放されず、MSAccessが不安定になります。この問題を解決できない場合は質問を開きます

3

行ソースを受け入れるコントロールをレコードセットに設定するには、次のようにします。

Set recordset = currentDb.OpenRecordset("SELECT * FROM TABLE", dbOpenSnapshot)
Set control.recordset = recordset

DAOレコードセットで確実に動作しますが、ADOレコードセットを使用する本当の理由がないため、試したことはありません。

このようにすると、単純な再クエリはデータを更新するために機能しません。setステートメントを繰り返す必要があります。

5
Lance S

すでに述べたように、コンボボックスにクエリ結果を表示するには、RowSourceTypeを「Table/List」(フランス語の場合は「Table /Requête」)にする必要があります。

レコードセット(rsPersonne)を閉じずに開くと、メモリの問題が発生します。フォームを閉じる/アンロードするときにそれらを閉じる必要があります(ただし、レコードセットはフォームではなく関数で宣言されているため、スコープの問題が発生します)。

Accessの組み込みクエリクリエーターを使用してクエリを作成して保存し、同じクエリをコンボボックスのRowSourceにプラグインすることもできます。このようにして、クエリはAccess内で検証およびコンパイルされます。

5
Marcand

recordsetプロパティを使用する良い方法、そのヒントに感謝します!

パトリック、あなたがあなたのページに示した方法には大きな欠点があります(私もそれを自分で試しました):値リストは32 KBしかありません、この制限を超えると関数はエラーをスローします。コールバックメソッドには、非常に低速であり、エントリごとに1回呼び出されるため、長いリストでは使用できないという大きな欠点があります。レコードセットメソッドの使用は非常にうまく機能します。 SQL文字列が32KB(WHERE ID IN(x、x、x、x、x ...)の多くのインデックス値)より長いため、これが必要でした。

このアイデアを使用してレコードセットをコンボボックスに設定する簡単な関数を次に示します。

' Fills a combobox with the result of a recordset.
'
' Works with any length of recordset results (up to 10000 in ADP)
' Useful if strSQL is longer than 32767 characters
'
' Author: Christian Coppes
' Date: 16.09.2009
'
Public Sub fnADOComboboxSetRS(cmb As ComboBox, strSQL As String)
    Dim rs As ADODB.Recordset
    Dim lngCount As Long

   On Error GoTo fnADOComboboxSetRS_Error

    Set rs = fnADOSelectCommon(strSQL, adLockReadOnly, adOpenForwardOnly)

    If Not rs Is Nothing Then
        If Not (rs.EOF And rs.BOF) Then
            Set cmb.Recordset = rs
            ' enforces the combobox to load completely
            lngCount = cmb.ListCount
        End If
    End If

fnADOComboboxSetRS_Exit:
    If Not rs Is Nothing Then
        If rs.State = adStateOpen Then rs.Close
        Set rs = Nothing
    End If
    Exit Sub

fnADOComboboxSetRS_Error:
    Select Case Err
        Case Else
            fnErr "modODBC->fnADOComboboxSetRS", True
            Resume fnADOComboboxSetRS_Exit
    End Select
End Sub

(関数fnADOSelectCommonはADOレコードセットを開き、それを返します。関数fnErrは、エラーがある場合はエラーのあるメッセージボックスを表示します。)

この関数は開いているレコードセットを閉じるので、メモリに問題はありません。私はそれをテストしましたが、コンボボックスでフォームを閉じた後に解放されなかったメモリの増加は見られませんでした。

フォームのアンロードイベントで、さらに「Set rs = Me.Comboboxname.Recordset」を使用して、それを閉じることができます。これはメモリに関しては必要ありませんが、開いている接続を解放する方がよい場合があります(バックエンドデータベースサーバーで使用する場合)。

乾杯、

キリスト教徒

2
Bitsqueezer

コンボボックスコントロールには、レコードセットプロパティがありません。 RowSourceプロパティはありますが、AccessはそこにSQL文字列を期待しています。

RowSourceTypeを、ユーザー定義の「コールバック」関数の名前に変更できます。アクセスヘルプでは、RowSourceTypeに移動してF1キーを押すと、サンプルコードなどの詳細情報が表示されます。このタイプの関数は、使用可能なレポート、ドライブ文字、またはSQLクエリでは使用できないその他のデータのリストをユーザーに提供する場合に使用します。

サーバー側から直接データを使用することに関して、3番目の段落が何を意味するのかわかりません。むしろ、標準のクエリを使用することの問題が何であるかを理解していません。

0
Tony Toews

MS Accessでは問題ありませんが、VBではadodc(Jet 4.0)を使用して次のようなものを使用できます。

Private sub Form1_Load()
   with Adodc1
     .commandtype = adcmdtext
     .recordsource = "Select * from courses"
     .refresh

     while not .recordset.eof
           combo1.additem = .recordset.coursecode
           .recordset.movenext
     wend
   end with
End Sub
0
rexreponte