& # 8220; Variable de objeto o Con variable de bloque no establecida & # 8221; error de tiempo de ejecución en VB6

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

  •  05-07-2019
  •  | 
  •  

Pregunta

Tengo un problema con VB6. Tengo un formulario con varios objetos ComboBox en él. Deseo rellenar los ComboBoxes a través de una función que toma una consulta SQL como parámetro. Así que el código se ve así

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

Llamo a la función como esta.

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

Básicamente, entiendo que esto se reduce a la creación de instancias, pero no he encontrado nada útil al respecto en línea. La nueva palabra clave no funciona como funciona en VB.Net. ¿Cómo puedo crear una instancia del cuadro combinado FillComboBoxFromMDB para que la función funcione? ¿Es incluso posible?

Gracias de antemano!

¿Fue útil?

Solución

Su código expresa la creencia de que el identificador FillComboBoxFromMDB ha adquirido una referencia al cuadro combinado en el lado izquierdo de la tarea en el procedimiento de Prueba.

Este no es el caso, la función se ejecutará primero con FillCombBoxFromMDB siendo Nothing una vez que intentará (y fallará) asignar el resultado al lado izquierdo.

Debes pasar el cuadro combinado 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

Llámalo así: -

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

Otros consejos

El problema de trabajar con el formulario vb6 controla que solo se pueden crear instancias en un formulario. ¡Qué maldita mierda! Oh sí, puedes registrar la DLL en la que residen los controles. ¡Diviértete con eso! Me encontré con esto con el socket TCP / IP.

Mi solución fue crear una interfaz SocketDriver. Crear un formulario y poner el socket en el formulario. Hacer la forma invisible. Implementar la interfaz SocketDriver en el formulario. Ahora puedes pasar el SocketDriver.

Me gusta la respuesta de Anthony, excepto que hubiera creado una interfaz llamada 'DataFiller' con un método.

Public Sub AddItem(item As String)
End Sub

Luego implementa en tu formulario.

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

Ahora usa la firma

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

Al usar la interfaz puede tener una cierta separación de preocupaciones. Su acceso a los datos no sabe nada sobre los formularios o controles, y sus valores y controles no saben de dónde provienen esos datos porque la dependencia está en una interfaz

P: ¿Qué es FillComboBoxFromMDB configurado antes de llamar a AddItem?
R: Nada, es por eso que obtienes el error

Intenta definir una variable como

Dim Value as ComboBox

Luego llamando al AddItem en este

Value.AddItem(...)

luego al final de la función tenemos

FillComboBoxFromMDB = Value

O como la otra respuesta si no desea utilizar un tipo de retorno como el que estaba tratando de usar.

Tiene una función que afirma que su tipo de devolución es ComboBox , pero no puedo ver en ningún lugar donde haya establecido el valor de devolución. Dado que el valor de retorno nunca se establece, será Nothing , de ahí su error cuando acceda a él.

Desde el caso de uso que proporciona, creo que lo que quiere es una subrutina auxiliar que funcione en un cuadro combinado existente . Así que lo llamarías así:

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

y la subrutina en sí tendría una firma como esta:

Private Sub FillComboBoxFromMDB (ByVal cbo As ComboBox, _                                 ByVal sDBName como cadena, _                                 ByVal sSQL As String)

(tenga en cuenta que es un Sub no una Function ). Dentro del cuerpo de la subrutina, donde tienes

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

en lugar de tener

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

para actuar sobre el ComboBox que se pasó a la subrutina.

Enfrenté el mismo problema en vb6 y también encontré una solución.

La razón detrás del problema fue,

mi procedimiento almacenado tenía múltiples declaraciones selectas.

Solución: usé SET NOCOUNT ON en el inicio del procedimiento almacenado y SET NOCOUNT OFF justo antes de la declaración de la selección final (salida).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top