& # 8220; Variable d'objet ou Variable avec bloc non définie & # 8221; erreur d'exécution dans VB6

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

  •  05-07-2019
  •  | 
  •  

Question

J'ai un problème avec VB6. J'ai un formulaire avec plusieurs objets ComboBox dessus. Je souhaite remplir les ComboBox via une fonction qui prend une requête SQL en tant que paramètre. Donc, le code ressemble à ceci

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

J'appelle la fonction comme ceci.

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

Donc, en gros, je comprends que cela revient à l’instanciation, mais je n’ai rien trouvé d’utile à ce sujet en ligne. Le mot-clé New ne fonctionne pas comme dans VB.Net. Comment instancier la combobox FillComboBoxFromMDB afin que la fonction fonctionne? Est-ce même possible?

Merci d'avance!

Était-ce utile?

La solution

Votre code exprime la conviction que l'identificateur FillComboBoxFromMDB a acquis une référence à la liste déroulante du côté gauche de l'affectation dans la procédure de test.

Ce n’est pas le cas, la fonction s’exécutera d’abord avec FillCombBoxFromMDB étant définie sur Nothing dès lors qu’elle tenterait (et échouerait) d’attribuer le résultat à gauche.

Vous devez passer la liste déroulante en tant que paramètre.

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

Appelez ça comme ça: -

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

Autres conseils

Le problème avec l'utilisation des contrôles de formulaire vb6, ils ne peuvent être instanciés que dans un formulaire. Quel foutu horseshit! Ah oui, vous pouvez enregistrer la DLL dans laquelle se trouvent les contrôles. Amusez-vous avec ça! Je me suis heurté à cela avec la prise TCP / IP.

Ma solution était de créer une interface SocketDriver. Créez un formulaire et placez le socket sur le formulaire. Rendre le formulaire invisible. Implémentez l'interface SocketDriver sur le formulaire. Maintenant, vous pouvez faire circuler le SocketDriver.

J'aime la réponse d’Anthony, sauf que j’aurais créé une interface nommée "DataFiller" avec une seule méthode.

Public Sub AddItem(item As String)
End Sub

Ensuite, implémentez sur votre formulaire.

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

Maintenant, utilisez Signature

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

En utilisant l'interface, vous pouvez séparer les problèmes. Votre accès aux données ne connaît rien des formulaires ni des contrôles, et vos froms et contrôles ne savent pas d’où viennent ces données, car la dépendance dépend d’une interface

Q: Qu'est-ce que FillComboBoxFromMDB est défini avant d'appeler AddItem?
A: Rien, c'est pourquoi vous obtenez l'erreur

Essayez de définir une variable comme

Dim Value as ComboBox

Appelez ensuite AddItem sur cette

Value.AddItem(...)

puis à la fin de la fonction ont

FillComboBoxFromMDB = Value

Ou comme autre réponse si vous ne souhaitez pas utiliser un type de retour identique à celui que vous tentiez d'utiliser.

Vous avez une fonction qui prétend que son type de retour est ComboBox , mais je ne vois nulle part où vous avez défini la valeur de retour. Comme la valeur de retour n’est jamais définie, ce sera Nothing , d’où votre erreur lorsque vous y accéderez.

D'après le cas d'utilisation que vous fournissez, je pense que ce que vous voulez, c'est un sous-programme d'assistance qui fonctionne sur une liste déroulante existante . Donc, vous l'appelleriez comme ceci:

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

et le sous-programme lui-même aurait une signature comme celle-ci:

Sous-groupe privé FillComboBoxFromMDB (ByVal cbo As ComboBox, _                                 ByVal sDBName As String, _                                 ByVal sSQL As String)

(notez qu'il s'agit d'un Sub et non d'une Fonction ). Dans le corps du sous-programme, où vous avez

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

à la place

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

pour agir sur la ComboBox qui a été transmise au sous-programme.

J'ai rencontré le même problème dans VB6 et j'ai également trouvé une solution.

La raison derrière ce problème était,

ma procédure stockée avait plusieurs instructions de sélection.

Solution: J'ai utilisé SET NOCOUNT ON dans le démarrage de la procédure stockée et SET NOCOUNT OFF juste avant l'instruction de sélection finale (sortie).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top