2009-07-30 6 views
2

У меня проблема с VB6. У меня есть форма с несколькими объектами ComboBox. Я хочу заполнить ComboBoxes с помощью функции, которая принимает SQL-запрос в качестве параметра. Таким образом, код выглядит так:«Объектная переменная или с переменной блока не задана» ошибка времени выполнения в VB6

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 

Так что в основном я понимаю, что это сводится к созданию экземпляра, но я не нашел в нем ничего полезного в Интернете. Новое ключевое слово не работает, как работает в VB.Net. Как создать экземпляр выпадающего списка FillComboBoxFromMDB, чтобы функция работала? Возможно ли это?

Заранее благодарен!

+3

Поздравляем! Вы столкнулись с одним из двух сообщений об ошибках VB6! (Единственный другой - «нет метода« ~ »на объекте« ~ ».) –

+2

Не забывайте« Ошибка ActiveX 429 »:) – AakashM

+0

Ну, это один из самых забавных, да. Мне просто нравится получать эти старые проекты с 2000 года, чтобы добавить функции .... – Gert

ответ

7

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

Это не тот случай, когда функция будет выполняться сначала с FillCombBoxFromMDB, являющейся Nothing, когда она попытается (и не удастся) присвоить результат левой стороне.

Вам необходимо передать значение combobox в качестве параметра.

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 
+0

ОК, но это в основном побеждает идею наличия функции. Может также преобразовать его в Sub и передать combobox ByRef. – Gert

+1

Нет смысла иметь функцию, если вы ничего не можете сделать с ее возвращаемым значением. ComboBoxes в VB6 - это не то, что вы можете создавать и присваивать как другие значения.Как вы можете видеть, я уже преобразовал его в Sub – AnthonyWJones

+0

Да, я просто хотел узнать, был ли какой-то способ. У меня была догадка, что это не получится. Спасибо, что разобрался. – Gert

1

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

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

Dim Value as ComboBox 

Затем вызывающей AddItem на этом

Value.AddItem(...) 

затем в конце функции есть

FillComboBoxFromMDB = Value 

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

+0

К сожалению, это не работает. – Gert

+1

Это не будет работать как 'Dim Value As ComboBox' не создает экземпляр нового' ComboBox'. –

+0

Да, вот что я имел в виду. – Gert

1

У вас есть функция, которая утверждает, что ее тип возврата ComboBox, но я не вижу нигде, где вы когда-либо устанавливали возвращаемое значение. Поскольку возвращаемое значение никогда не устанавливается, оно будет Nothing, поэтому ваша ошибка при доступе к нему.

Из используемого варианта поставки, я думаю, что вам нужна вспомогательная подпрограмма, которая работает на существующих combobox.Таким образом, вы могли бы назвать это так:

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

и сама подпрограмма будет иметь подпись так:

Private Sub FillComboBoxFromMDB (ByVal СВО Как 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, который был передан в подпрограмму.

2

Что проблема с работой с элементами управления формой 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

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

Причиной этому вопросу был,

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

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