«Переменная объекта или переменная блока не установлена» ошибка времени выполнения в VB6 - PullRequest
2 голосов
/ 30 июля 2009

У меня проблема с VB6. У меня есть форма с несколькими объектами ComboBox. Я хочу заполнить ComboBox через функцию, которая принимает SQL-запрос в качестве параметра. Итак, код выглядит так

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, чтобы эта функция работала? Это вообще возможно?

Заранее спасибо!

Ответы [ 5 ]

7 голосов
/ 30 июля 2009

Ваш код выражает уверенность в том, что идентификатор FillComboBoxFromMDB получил ссылку на комбинированный список в левой части назначения в процедуре теста.

Это не тот случай, когда функция будет выполняться первой, когда 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
2 голосов
/ 31 июля 2009

Что проблема с работой с элементами управления vb6, они могут быть созданы только в форме. Какая уродская чушь! О, да, вы можете зарегистрировать DLL, в которой находятся элементы управления. Удачи с этим! Я столкнулся с этим с сокетом tcp / ip.

Моим решением было создание интерфейса SocketDriver. Создайте форму и поместите сокет в форму. Сделайте форму невидимой. Реализуйте интерфейс SocketDriver в форме. Теперь вы можете передать SocketDriver.

Мне нравится ответ Энтони, за исключением того, что я создал бы интерфейс с именем 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

Используя интерфейс, вы можете разделить задачи. Ваш доступ к данным ничего не знает о формах или элементах управления, а ваши сотрудники и элементы управления не знают, откуда поступили эти данные, поскольку зависимость находится на интерфейсе

1 голос
/ 10 ноября 2011

Я столкнулся с той же проблемой в vb6 и нашел решение тоже.

Причиной проблемы была

моя хранимая процедура имела несколько операторов выбора.

Решение: я использовал SET NOCOUNT ON в начале хранимой процедуры и SET NOCOUNT OFF непосредственно перед последним оператором выбора (вывода).

1 голос
/ 30 июля 2009

У вас есть функция, которая утверждает, что ее тип возвращаемого значения равен 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, а не Function). В теле подпрограммы, где у вас есть

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

вместо

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

для действия с ComboBox, переданным в подпрограмму.

1 голос
/ 30 июля 2009

В: Для чего задан FillComboBoxFromMDB перед вызовом AddItem?
A: Ничего, поэтому вы получаете ошибку

Попробуйте определить переменную наподобие

Dim Value as ComboBox

Затем вызывается AddItem для этого

Value.AddItem(...)

тогда в конце функции есть

FillComboBoxFromMDB = Value

Или как другой ответ, если вы не хотите использовать тип возвращаемого значения, как вы пытались использовать.

...