“オブジェクト変数またはWithブロック変数が設定されていません” VB6のランタイムエラー

StackOverflow https://stackoverflow.com/questions/1206526

  •  05-07-2019
  •  | 
  •  

質問

VB6に問題があります。いくつかのComboBoxオブジェクトを含むフォームがあります。パラメーターとしてSQLクエリを受け取る関数を介してComboBoxesを設定したいと思います。したがって、コードは次のようになります

Private Function FillComboBoxFromMDB(ByVal sDBName As String, _
                                     ByVal sSQL As String) As ComboBox
    '/*
    ' * Execute SQL in MDB and fill the ComboBox with the results
    ' * Returns filled ComboBox
    ' */
    Dim DB As Database
    Dim DBRecordset As Recordset

    On Error GoTo FillComboBoxFromMDB_ErrHandler

    Set DB = OpenDatabase(sDBName, False, False)

    If Not DB Is Nothing Then
        Set DBRecordset = DB.OpenRecordset(sSQL)
        If Not DBRecordset Is Nothing Then
            If DBRecordset.RecordCount > 0 Then
                Call FillComboBoxFromMDB.AddItem(DBRecordset.Fields(0).Value)
                ' ^^ This row gives the "Object variable or With block variable not set"
            End If
        Else
            Call WriteLog("Unable to execute " & sSQL)
        End If
        DB.Close
    Else
        Call WriteLog("Unable to open " & sDBName)
    End If

    Exit Function
FillComboBoxFromMDB_ErrHandler:
    Call WriteLog("FillComboBoxFromMDB() error: " & Err.Number & " " & Err.Description)
End Function

このような関数を呼び出します。

Private Function Test()
    ' Fill the combobox
    frmMyForm.cmbMyCombo = FillComboBoxFromMDB("Database.mdb", _
                                               "SELECT MyTable.MyText FROM MyTable")
End Function

したがって、基本的にこれはインスタンス化に帰着することを理解していますが、オンラインでそれについて有用なものは見つかりませんでした。 Newキーワードは、VB.Netで機能するようには機能しません。関数が機能するようにFillComboBoxFromMDBコンボボックスをインスタンス化するにはどうすればよいですか?可能ですか?

事前に感謝します!

役に立ちましたか?

解決

コードは、 FillComboBoxFromMDB という識別子が、Testプロシージャの割り当ての左側にあるコンボボックスへの参照を取得したという信念を表しています。

関数が最初に実行されるのは、FillCombBoxFromMDBがNothingで、結果を左側に割り当てようとする(および失敗する)場合ではありません。

コンボボックスをパラメーターとして渡す必要があります。

Private Sub FillComboBoxFromMDB(ByVal sDBName As String, _
                                     ByVal sSQL As String, ByVal cbo As ComboBox)
    '/*
    ' * Execute SQL in MDB and fill the ComboBox with the results
    ' * Returns filled ComboBox
    ' */
    Dim DB As Database
    Dim DBRecordset As Recordset

    On Error GoTo FillComboBoxFromMDB_ErrHandler

    Set DB = OpenDatabase(sDBName, False, False)

    If Not DB Is Nothing Then
        Set DBRecordset = DB.OpenRecordset(sSQL)
        If Not DBRecordset Is Nothing Then
            If DBRecordset.RecordCount > 0 Then
                Call cbo.AddItem(DBRecordset.Fields(0).Value)
                ' ^^ This row gives the "Object variable or With block variable not set"
            End If
        Else
            Call WriteLog("Unable to execute " & sSQL)
        End If
        DB.Close
    Else
        Call WriteLog("Unable to open " & sDBName)
    End If

    Exit Sub
FillComboBoxFromMDB_ErrHandler:
    Call WriteLog("FillComboBoxFromMDB() error: " & Err.Number & " " & Err.Description)
End Sub

次のように呼び出します:-

 Private Function Test()
 ' Fill the combobox
 Call FillComboBoxFromMDB("Database.mdb", _
                          "SELECT MyTable.MyText FROM MyTable", _
                          frmMyForm.cmbMyCombo ) 
 End Function

他のヒント

vb6フォームコントロールの操作に関する問題は、フォームでのみインスタンス化できることです。なんて馬鹿げた!そうそう、コントロールが存在するDLLを登録できます。楽しんでください! tcp / ipソケットでこれに遭遇しました。

私の解決策は、SocketDriverインターフェースを作成することでした。フォームを作成し、フォームにソケットを配置します。フォームを非表示にします。フォームにSocketDriverインターフェイスを実装します。これでSocketDriverを渡すことができます。

Anthonyの回答が好きですが、1つのメソッドで「DataFiller」という名前のインターフェイスを作成したことを除きます。

Public Sub AddItem(item As String)
End Sub

フォームに実装します。

Public Sub AddItem(item As String)
   cmbMyCombo.AddItem(item)
End Sub

署名を使用する

Private Sub FillComboBoxFromMDB(ByVal sDBName As String, _
                                 ByVal sSQL As String, ByVal injectWith As DataFiller)
   'yada yada code

   injectWith.AddItem(DBRecordset.Fields(0).Value)

   'yada yada code

End Sub

Private Function Test()
   ' Fill the combobox
   FillComboBoxFromMDB("Database.mdb", _
                                           "SELECT MyTable.MyText FROM MyTable", frmMyForm)
End Function

インターフェースを使用することで、懸念事項を分離できます。データアクセスはフォームやコントロールについては何も知りません。また、依存関係がインターフェイスにあるため、データがどこから来たのかをfromやコントロールは知りません

Q:AddItemを呼び出す前にFillComboBoxFromMDBは何に設定されますか?
A:何もありません。だからエラーが発生します

次のような変数を定義してみてください

Dim Value as ComboBox

そして、この上でAddItemを呼び出す

Value.AddItem(...)

関数の最後にある

FillComboBoxFromMDB = Value

または、使用しようとしているような戻り値の型を使用したくない場合の別の回答として。

戻り値の型が ComboBox であると主張する関数がありますが、実際に戻り値を設定した場所はどこにもありません。戻り値は決して設定されないため、 Nothing になります。したがって、アクセスするとエラーになります。

提供するユースケースから、既存のコンボボックスで動作するヘルパーサブルーチンが欲しいと思います。したがって、次のように呼び出します。

' Fill the combobox
FillComboBoxFromMDB(frmMyForm.cmbMyCombo, _
                    "Database.mdb", _
                    "SELECT MyTable.MyText FROM MyTable")

およびサブルーチン自体には次のようなシグネチャがあります:

Private Sub FillComboBoxFromMDB(ByVal cbo As ComboBox、_                                 ByVal sDBName As String、_                                 ByVal sSQL As String)

関数ではなく、 Sub であることに注意してください)。サブルーチンの本文内で、

 Call FillComboBoxFromMDB.AddItem(DBRecordset.Fields(0).Value)

代わりに持っている

 cbo.AddItem(DBRecordset.Fields(0).Value)

サブルーチンに渡された ComboBox に作用します。

vb6で同じ問題に直面し、解決策も見つかりました。

問題の背後にある理由は、

私のストアドプロシージャには複数の選択ステートメントがありました。

解決策:ストアドプロシージャの開始時に SET NOCOUNT ON を使用し、最終選択(出力)ステートメントの直前に SET NOCOUNT OFF を使用しました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top