2017-03-16 5 views
0

J'ai deux fonctions principales, la première est search_bank. Il parcourt les colonnes Credits, Type et Store, cellule par cellule et détermine si nous avons une correspondance ou non. S'il y a correspondance, elle renvoie True et, en tant qu'effet secondaire, change la couleur de la cellule correspondante. J'utilise pour tester la première fonction. Le problème que j'ai est que je reçois un Erreur d'exécution '424': Objet requis sans indication d'où le problème est.VBA: La fonction donne "Run time error '424': Objet requis" Erreur lors de l'appel

Voici la première fonction:

Function search_bank(Store As String, amount As Double, Amex As Boolean) As Boolean 
    Dim m_store As Range 
    Dim m_type As Range 
    Dim Credit_Amt_Col As Range 

    Set m_store = bank_sheet.Range("1:1").Find("M_STORE") 
    Set m_type = bank_sheet.Range("1:1").Find("M_TYPE") 
    Set Credit_Amt_Col = bank_sheet.Range("1:1").Find("Credit Amt") 

    search_bank = False 
    Dim i As Long 
    For i = 1 To 9000 
     If Not search_bank Then 
      Dim store_cell As Range 
      Dim type_cell As Range 
      Dim credit_cell As Range 

      Set store_cell = Worksheets(2).Cells(i, m_store.Column) 
      Set type_cell = Worksheets(2).Cells(i, m_type.Column) 
      Set credit_cell = Worksheets(2).Cells(i, Credit_Amt_Col.Column) 

      If InStr(UCase(store_cell.Value), UCase(Store)) > 0 And credit_cell.Value = amount Then 
       If store_cell.Interior.ColorIndex <> 46 Then 
        If Amex And InStr(UCase(type_cell.Value), UCase("amex deposit")) Then 
         store_cell.Interior.ColorIndex = 46 
         search_bank = True 

        End If 
        If Not Amex And InStr(UCase(type_cell.Value), UCase("Credit Card Deposit")) Then 
         store_cell.Interior.ColorIndex = 46 
         search_bank = True 

        End If 
       End If 
      End If 
     End If 
    Next i 

End Function 

et est ici le testeur:

Sub Tester() 
    Dim x As Boolean 
    x = search_bank("ctc", 38.4, True) 
    Debug.Print (x) 
End Sub 

J'ai essayé d'utiliser 'set' sur le testeur:

Sub Tester() 
    Dim x As Boolean 
    Set x = search_bank("ctc", 38.4, True) 
    Debug.Print (x) 
End Sub 

Et même en déclarant la variable avant de les passer dans le testeur (je ne suis pas très habitué à VBA mais pour un moment je croyais que c'était juste si ancien, ça devait les choses déduites à être déclarées avant qu'elles soient passées)

Sub Tester() 
    Dim x As Boolean 
    Dim store As String 
    Dim Amount As Double 
    Dim amex As Boolean 
    store = "ctc" 
    Amount = 38.4 
    amex = True 
    x = search_bank(store, Amount, amex) 
    Debug.Print (x) 
End Sub 
+2

Lorsque vous obtenez l'erreur d'exécution, sélectionnez l'option Déboguer et utilisez la touche F8 pour parcourir le code jusqu'à ce que la ligne indique les erreurs. –

+0

Où/quand/comment déclarez-vous 'bank_sheet'? – BruceWayne

+1

Assurez-vous également que le résultat de vos trois méthodes 'Find' renvoie des objets valides. Si les valeurs ne sont pas trouvées dans la ligne 1, elles renverront un 'Nothing', ce qui augmenterait cette erreur plus tard dans votre code. –

Répondre

0

Il y a beaucoup de bons commentaires sous votre OP, et avec la réponse de @ BrandonBarney aussi, mais voici mes deux cents:

Cent un: La plus grande chose que je vois est que vous ne déclarez jamais que blank_sheet essayez encore de l'utiliser lors de la configuration un objet de gamme. C'est de là que vient votre erreur. Il cherche à faire Range("1:1").Find("M_STORE"), mais ne sait pas ce que bank_sheet est.

Cent deux: Un moyen rapide de vous faire remarquer est always use Option Explicit en haut de votre code. Cela garantit que toute variable que vous utilisez est explicitement déclarée. I.e. .:

Option Explicit 

Function search_bank(Store As String, amount As Double, Amex As Boolean) As Boolean 
    Dim m_store As Range 
    Dim m_type As Range 
    Dim Credit_Amt_Col As Range 

    ''''' New code here: '''''' 
    Dim bank_sheet as Worksheet 
    Set bank_sheet = Worksheets("Bank Sheet") ' change to whatever the name is. 
    ''''''''''''''''''''''''''' 
    Set m_store = bank_sheet.Range("1:1").Find("M_STORE") 
    Set m_type = bank_sheet.Range("1:1").Find("M_TYPE") 
    Set Credit_Amt_Col = bank_sheet.Range("1:1").Find("Credit Amt") 
    ' etc. etc. 

Option Explicit va aussi aider si jamais vous avez accidentellement une faute de frappe. Donc, si vous avez déjà fait bank_sheeet.Range("A:A") il va erreur et vous demander de déclarer bank_sheeet. Ou, bien sûr, vous réaliserez que c'est une faute de frappe et que vous le corrigerez.

Bonus cent: Vous pouvez enregistrer quelques lignes en combinant vos Dim s:
Dim m_store as Range, m_type as Range, Credit_Amt_Col as Range peuvent tous être sur une seule ligne.

(Note: Faire Dim m_store, m_type, Credit_Amt_Col as Range sera pas mettre tous les trois type Range Il va faire m_store et m_type un Variant car il est pas déclarée..Seul Credit_Amt_Col serait un Range dans ce cas. Donc, vous devez toujours indiquer explicitement le type pour chaque variable).

1

Je signalerais ceci comme commentaire si je pourrais, mais je ne peux pas. Donc, je sais que cela ne le résoudra pas directement, mais cela aidera au débogage. Voir ci-dessous:

Function search_bank(Store As String, amount As Double, Amex As Boolean) As Boolean 
Dim m_store As Range 
Dim m_type As Range 
Dim Credit_Amt_Col As Range 

' It is always best to check the inverse of an object before setting 
' setting an object variable to the target object. In this case 
' I check to make sure each range can be found, and if not, I 
' debug.print which variable cannot be set. 

Set m_store = bank_sheet.Range("1:1").Find("M_STORE") 
Set m_type = bank_sheet.Range("1:1").Find("M_TYPE") 
Set Credit_Amt_Col = bank_sheet.Range("1:1").Find("Credit Amt") 

If m_store is Nothing then Debug.Print "m_store is nothing" 
If m_type is Nothing then Debug.Print "m_type is nothing" 
If Credit_Amt_Col is Nothing then Debug.Print "Credit_Amt_Col is nothing." 

search_bank = False 
Dim i As Long 
For i = 1 To 9000 
    If Not search_bank Then 
     Dim store_cell As Range 
     Dim type_cell As Range 
     Dim credit_cell As Range 

     ' Use the inverse method above on these three items as well. 
     Set store_cell = Worksheets(2).Cells(i, m_store.Column) 
     Set type_cell = Worksheets(2).Cells(i, m_type.Column) 
     Set credit_cell = Worksheets(2).Cells(i, Credit_Amt_Col.Column) 

     If InStr(UCase(store_cell.Value), UCase(Store)) > 0 And credit_cell.Value = amount Then 
      If store_cell.Interior.ColorIndex <> 46 Then 
       If Amex And InStr(UCase(type_cell.Value), UCase("amex deposit")) Then 
        store_cell.Interior.ColorIndex = 46 
        search_bank = True 

       End If 
       If Not Amex And InStr(UCase(type_cell.Value), UCase("Credit Card Deposit")) Then 
        store_cell.Interior.ColorIndex = 46 
        search_bank = True 

       End If 
      End If 
     End If 
    End If 
Next i 

End Function 

J'ai posté une ligne de commentaire, mais au fond, j'ajouté un contrôle inverse pour vos trois premiers objets (que vous voulez faire pour votre deuxième ensemble d'objets aussi bien). C'est la meilleure pratique, mais dans ce cas, il vous aidera également (espérons-le) à déterminer où l'objet ne peut pas être trouvé.

+1

serait plus facile à 'Set' la variable d'objet et ensuite simplement tester' Si Set m_store is nothing' etc. Aussi moins de surcharge, et moins de littéraux de chaîne "hard-coded". –

+0

Si vous avez essayé de ne pas utiliser après l'ensemble, vous pourriez rencontrer l'erreur 'Object Variable not Set' si find ne retourne pas un objet. C'est l'intention du bloc d'inversion en premier lieu. De plus, j'éliminerais idéalement les littéraux de chaînes codés en dur, et j'utiliserais probablement un objet listobject si possible au lieu d'utiliser Find, mais ce n'est pas Codereview. Il y a beaucoup à faire pour améliorer le code, mais le problème doit d'abord être identifié. –

+1

Si les variables sont correctement saisies, "Si m_store is nothing" ne déclenche aucune erreur. –