& # 8220; Variabile oggetto o Con variabile blocco non impostata & # 8221; errore di runtime in VB6

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

  •  05-07-2019
  •  | 
  •  

Domanda

Ho un problema con VB6. Ho un modulo con diversi oggetti ComboBox su di esso. Desidero popolare i ComboBox tramite una funzione che accetta una query SQL come parametro. Quindi il codice è simile a questo

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

Chiamo la funzione in questo modo.

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

Quindi in pratica capisco che questo si riduce all'istanza, ma non ho trovato nulla di utile al riguardo online. La nuova parola chiave non funziona come funziona in VB.Net. Come posso creare un'istanza della casella combinata FillComboBoxFromMDB affinché la funzione funzioni? È anche possibile?

Grazie in anticipo!

È stato utile?

Soluzione

Il codice esprime la convinzione che l'identificatore FillComboBoxFromMDB abbia acquisito un riferimento alla casella combinata sul lato sinistro del compito nella procedura Test.

Questo non è il caso in cui la funzione verrà eseguita per prima con FillCombBoxFromMDB che è Nothing una volta che tenterà (e non riuscirà) di assegnare il risultato sul lato sinistro.

Devi passare la casella combinata come parametro.

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

Chiamalo così: -

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

Altri suggerimenti

Che il problema con il funzionamento con i moduli vb6 controlli, possono essere istanziati solo in un modulo. Che strana cavallina! Oh sì, puoi registrare la DLL in cui risiedono i controlli. Divertiti con quello! Mi sono imbattuto in questo con il socket tcp / ip.

La mia soluzione era quella di creare un'interfaccia SocketDriver. Creare un modulo e inserire il socket nel modulo. Rendi invisibile il modulo. Implementare l'interfaccia SocketDriver sul modulo. Ora puoi passare SocketDriver in giro.

Mi piace la risposta di Anthony, tranne per il fatto che avrei creato un'interfaccia chiamata 'DataFiller' con un metodo.

Public Sub AddItem(item As String)
End Sub

Quindi implementare sul modulo.

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

Ora 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

Usando l'interfaccia puoi avere una certa separazione delle preoccupazioni. Il tuo accesso ai dati non sa nulla di moduli o controlli e i tuoi from e controlli non sanno da dove provengano quei dati perché la dipendenza è su un'interfaccia

D: Cos'è FillComboBoxFromMDB impostato prima di chiamare AddItem?
A: Niente, ecco perché ottieni l'errore

Prova a definire una variabile come

Dim Value as ComboBox

Quindi chiamando AddItem su questo

Value.AddItem(...)

quindi alla fine della funzione hai

FillComboBoxFromMDB = Value

O come l'altra risposta se non vuoi usare un tipo di ritorno come stavi cercando di usare.

Hai una funzione che afferma che il suo tipo di ritorno è ComboBox , ma non riesco a vedere da nessuna parte dove tu abbia mai effettivamente impostato il valore di ritorno. Poiché il valore restituito non è mai impostato, sarà Nothing , quindi l'errore quando si accede ad esso.

Dal caso d'uso fornito, penso che ciò che desideri sia una subroutine di supporto che funzioni su una casella combinata esistente . Quindi lo chiameresti così:

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

e la stessa subroutine avrebbe una firma come questa:

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

(nota che si tratta di un Sub non di un Function ). All'interno del corpo della subroutine, dove hai

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

invece ha

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

per agire sul ComboBox passato nella subroutine.

Ho riscontrato lo stesso problema in vb6 e ho trovato anche una soluzione.

Il motivo alla base del problema era,

la mia procedura memorizzata aveva più istruzioni select.

Soluzione: ho usato SET NOCOUNT ON all'inizio della procedura memorizzata e SET NOCOUNT OFF appena prima dell'istruzione di selezione (output) finale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top