“Variável Object ou com variável bloco não definida” erro de execução em VB6

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

  •  05-07-2019
  •  | 
  •  

Pergunta

Eu tenho um problema com VB6. Eu tenho um formulário com vários objetos ComboBox nele. Desejo preencher os ComboBoxes através de uma função que leva uma consulta SQL como um parâmetro. Então os olhares código como este

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

Eu chamo a função como esta.

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

Então, basicamente, eu entendo que isso se resume a instanciação, mas eu não encontrei nada de útil sobre isso online. A nova palavra-chave não funciona como ele funciona em VB.Net. Como faço para instanciar o combobox FillComboBoxFromMDB para que a função vai funcionar? Será que é mesmo possível?

Agradecemos antecipadamente!

Foi útil?

Solução

código Você expressa a crença de que o FillComboBoxFromMDB identificador adquiriu uma referência para a caixa de combinação no lado esquerdo da atribuição no procedimento de teste.

Este não é o caso, a função será executada pela primeira vez com FillCombBoxFromMDB sendo nada, uma vez que ele iria tentar (e falhar) para atribuir o resultado para o lado esquerdo.

Você precisa passar o combobox como parâmetro.

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

chamá-lo assim: -

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

Outras dicas

Que o problema de trabalhar com controles de formulário VB6, que só pode ser instanciado em um formulário. O que freakin' merda! Oh sim, você pode registrar o DLL que os controles residem. Divirta-se com isso! Corri para isso com o TCP / IP socket.

A minha solução foi criar uma interface SocketDriver. Crie um formulário e colocar o soquete no formulário. Tornar o formulário invisível. Implementar a interface SocketDriver no formulário. Agora você pode passar o SocketDriver redor.

Eu gosto de resposta de Anthony, exceto que eu teria criado uma interface chamada 'DataFiller' com um método.

Public Sub AddItem(item As String)
End Sub

Em seguida, implemente em sua forma.

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

Agora uso Assinatura

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

Ao usar a interface que você pode ter alguma separação de interesses. Seu acesso a dados não sabe nada sobre formulários ou controles e seus froms e controles não sabe onde os dados vieram porque a dependência é em uma interface

Q: O que há de FillComboBoxFromMDB conjunto para antes de chamar AddItem
A: Nada, é por isso que você obter o erro

Tente definir uma variável como

Dim Value as ComboBox

Em seguida, chamar o AddItem nesta

Value.AddItem(...)

, em seguida, no final da função Com

FillComboBoxFromMDB = Value

Ou, como a outra resposta, se você não quiser usar um tipo de retorno que você estava tentando usar.

Você tem uma função que afirma que seu tipo de retorno é ComboBox, mas eu não posso ver em qualquer lugar onde você nunca realmente definir o valor de retorno. Uma vez que o valor de retorno não está definido, será Nothing, daí o seu erro quando você acessá-lo.

A partir do caso de uso que você fornecer, eu acho que você quer é uma sub-rotina auxiliar que funciona em um existente combobox. Então você iria chamá-lo assim:

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

eo próprio sub-rotina teria uma assinatura como esta:

Private Sub FillComboBoxFromMDB (ByVal CBO Como ComboBox, _ ByVal sDBName As String, _ ByVal sSQL As String)

(note que é um Sub não um Function). Dentro do corpo da sub-rotina, onde você tem

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

sim ter

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

para agir sobre a ComboBox que foi passado para a sub-rotina.

Eu enfrentei mesmo problema em VB6 e encontrou uma solução também.

A razão por trás a questão era,

meu procedimento armazenado teve várias instruções SELECT.

Solução:. Eu costumava SET NOCOUNT ON na partida do procedimento armazenado e SET NOCOUNT OFF pouco antes da declaração selecção final (output)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top