“Variável Object ou com variável bloco não definida” erro de execução em VB6
-
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!
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 ??p>
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)