2008-11-10 7 views
0

Je suis l'exécution d'une requête comme ceciMS Access: comment contourner/supprimer une erreur?

select field from table; 

Dans cette requête, il y a une boucle en cours d'exécution sur plusieurs tables. Donc, si le champ est présent dans une table, je reçois un

Erreur d'exécution 3061

Comment puis-je passer par cette erreur comme celle sur ce flux d'erreur devrait aller à un autre point?

Ceci est le code que j'ai récemment après avoir parcouru ce forum.

Option Explicit 

Private Sub UpdateNulls() 
Dim rs2 As DAO.Recordset 
    Dim tdf As DAO.TableDef 
    Dim db As Database 
    Dim varii As Variant, strField As String 
    Dim strsql As String, strsql2 As String, strsql3 As String 
    Dim astrFields As Variant 
    Dim intIx As Integer 
    Dim field As Variant 
    Dim astrvalidcodes As Variant 
    Dim found As Boolean 
    Dim v As Variant 


    Open "C:\Documents and Settings\Desktop\testfile.txt" For Input As #1 
    varii = "" 
    Do While Not EOF(1) 
    Line Input #1, strField 
    varii = varii & "," & strField 
    Loop 
    Close #1 
    astrFields = Split(varii, ",") 'Element 0 empty 




     For intIx = 1 To UBound(astrFields) 


     'Function ListFieldDescriptions() 
          Dim cn As New ADODB.Connection, cn2 As New ADODB.Connection 
          Dim rs As ADODB.Recordset, rs3 As ADODB.Recordset 
          Dim connString As String 
          Dim SelectFieldName 

          Set cn = CurrentProject.Connection 

          SelectFieldName = astrFields(intIx) 

          Set rs = cn.OpenSchema(adSchemaColumns, Array(Empty, Empty, Empty, SelectFieldName)) 

          'Show the tables that have been selected ' 
          While Not rs.EOF 

          'Exclude MS system tables ' 
          If Left(rs!Table_Name, 4) <> "MSys" Then 
          strsql = "Select t.* From [" & rs!Table_Name & "] t Inner Join 01UMWELT On t.fall = [01UMWELT].fall Where [01UMWELT].Status = 4" 
          End If 

          Set rs3 = CurrentDb.OpenRecordset(strsql) 

      'End Function 

      strsql2 = "SELECT label.validcode FROM variablen s INNER JOIN label ON s.id=label.variablenid WHERE varname='" & astrFields(intIx) & "'" 

      Set db = OpenDatabase("C:\Documents and Settings\Desktop\Codebook.mdb") 
      Set rs2 = db.OpenRecordset(strsql2) 

       With rs2 
       .MoveLast 
       .MoveFirst 
       astrvalidcodes = rs2.GetRows(.RecordCount) 
       .Close ' 
       End With 


        With rs3 
        .MoveFirst 
        While Not rs3.EOF 
         found = False 
         For Each v In astrvalidcodes 
         If v = .Fields(0) Then 
         found = True 
         Debug.Print .Fields(0) 
         Debug.Print .Fields(1) 


       Exit For 
        End If 
        Next 
       If Not found Then 
       msgbox "xxxxxxxxxxxxxxxx" 

       End If 
       End If 
       .MoveNext 


       Wend 
       End With 

      On Error GoTo 0  'End of special handling 

    Wend 



Next intIx 


    End Sub 

Je reçois

Incohérence de type Erreur d'exécution

dans Set rs3 = CurrentDb.OpenRecordset(strsql)

Je suppose que je suis mélanger ado et dao mais je ne suis pas sûr sûr où c'est.

+0

Tout d'abord: arrêtez d'utiliser GoTo. Immédiatement. C'est mauvais. Je veux dire vraiment * mal *, comme dans "Pandora's Box". Le seul endroit où GoTo est valide dans le code VB est dans les instructions "On Error Goto". – Tomalak

+0

Deuxièmement: Changez-le pour utiliser le style "On Error Resume Next", il est beaucoup plus approprié ici. Avez-vous vérifié que 3061 est le numéro réel de l'erreur? Utilisez le débogueur pour parcourir votre code. – Tomalak

+0

je ai codé à contrecoeur goto mais je l'ai enlevé j'ai essayé le débogage mais toujours la même erreur 3061 – tksy

Répondre

3

Plutôt que de piéger l'erreur, pourquoi ne pas utiliser TableDefs pour vérifier le champ ou utiliser un mélange d'ADO et DAO? Les schémas ADO peuvent fournir une liste de tables contenant le champ requis:

Function ListTablesContainingField() 
Dim cn As New ADODB.Connection, cn2 As New ADODB.Connection 
Dim rs As ADODB.Recordset, rs2 As ADODB.Recordset 
Dim connString As String 
Dim SelectFieldName 

    Set cn = CurrentProject.Connection 

    SelectFieldName = "Fall" 'For tksy ' 

    'Get names of all tables that have a column called 'ID' ' 
    Set rs = cn.OpenSchema(adSchemaColumns, _ 
    Array(Empty, Empty, Empty, SelectFieldName)) 

    'Show the tables that have been selected ' 
    While Not rs.EOF 

     'Exclude MS system tables ' 
     If Left(rs!Table_Name, 4) <> "MSys" Then 
      ' Edit for tksy, who is using more than one forum ' 
      If tdf.Name = "01UMWELT" Then 
       strSQL = "Select * From 01UMWELT Where Status = 5" 
      Else 
       strSQL = "Select a.* From [" & rs!Table_Name _ 
       & "] a Inner Join 01UMWELT On a.fall = 01UMWELT.fall " _ 
       & "Where 01UMWELT.Status = 5" 
      End If 
      Set rs2 = CurrentDb.OpenRecordset(strSQL) 

      Do While Not rs2.EOF 
       For i = 0 To rs2.Fields.Count - 1 
        If IsNull(rs2.Fields(i)) Then 
         rs2.Edit 
         rs2.Fields(i) = 111111 
         rs2.Update 
        End If 
       Next 
       rs2.MoveNext 
      Loop 
     End If 
     rs.MoveNext 
    Wend 
    rs.Close 
    Set cn = Nothing 

End Function 
+0

Donc, ici, je vais obtenir les noms des tables dans le jeu d'enregistrements, après cela Dois-je interroger ces tables seul? Comment puis-je interroger les tables répertoriées uniquement dans le jeu d'enregistrements? – tksy

+0

Vous pouvez créer une liste ou un tableau de tables à partir du jeu d'enregistrements (http://wiki.lessthandot.com/index.php/ADO_Schemas) ou insérer un codage supplémentaire dans la boucle While. – Fionnuala

+0

Je ne suis pas sûr si je comprends cela correctement. Maintenant, ici, dans le jeu d'enregistrements, est-ce que j'obtiens seulement les noms de tables ou est-ce que j'obtiens les tables avec le contenu? – tksy

0

Essayez ceci:

On Error Resume Next 'Si une erreur se produit, passez à la déclaration suivante.

... déclaration qui tente select ...

Si (Err <> 0) Puis

...act on error, or simply ignore if necessary... 

End If

On Error Goto 0 'Reset à la manipulation précédente erreur Etat.

4

Utilisez l'instruction On Error qui fournit VBA:

Sub TableTest 
    On Error Goto TableTest_Error 

    ' ...code that can fail... ' 

    Exit Sub 

:TableTest_Error 
    If Err.Number = 3061 Then 
    Err.Clear() 
    DoSomething() 
    Else 
    MsgBox Err.Description ' or whatever you find appropriate ' 
    End If 
End Sub 

Alternativement, vous pouvez désactiver le traitement automatique des erreurs (par exemple casser l'exécution et l'affichage d'un message d'erreur) sur une base ligne par ligne:

Sub TableTest 
    ' ... fail-safe code ... ' 

    On Error Resume Next 
    ' ...code that can fail... ' 
    If Err.Number = 3061 Then 
    Err.Clear() 
    DoSomething() 
    Else 
    MsgBox Err.Description 
    End If 
    On Error Goto 0 

    ' ...mode fail-safe code... ' 
End Sub 

Il y a ces déclarations disponibles:

  • On Error Resume Next désactive complètement la gestion des erreurs intégrée à VBA (boîte de message, etc.), l'exécution reprend simplement sur la ligne suivante. Soyez sûr de vérifier une erreur très tôt après que vous l'ayez utilisé, car une erreur pendante peut perturber le déroulement normal de l'exécution. Effacer l'erreur dès que vous l'avez attrapé pour l'empêcher.
  • On Error Goto <Jump Label> reprend l'exécution à un libellé donné, principalement utilisé pour les gestionnaires d'erreurs par fonction qui interceptent toutes sortes d'erreurs.
  • On Error Goto <Line Number> reprend à un numéro de ligne donné. Restez loin de ça, ce n'est pas utile, même dangereux.
  • On Error Goto 0 c'est cousin proche.RÉINSCRIT la gestion des erreurs intégrée VBA (boîte de message, etc.)

EDIT

De la qestion modifiée, voici ma proposition pour résoudre votre problème.

For Each FieldName In FieldNames ' assuming you have some looping construct here ' 

    strsql3 = "SELECT " & FieldName & " FROM table" 

    On Error Resume Next 
    Set rs3 = CurrentDb.OpenRecordset(strsql3) 

    If Err.Number = 3061 Then 
    ' Do nothing. We dont care about this error ' 
    Err.Clear 
    Else 
    MsgBox "Uncaught error number " & Err.Number & " (" & Err.Description & ")" 
    Err.Clear 
    End If 

    On Error GoTo 0 

Next FieldName 

Assurez-vous d'effacer l'erreur dans tous les cas avant d'aller avec une boucle dans le même Sub ou Function. Comme je l'ai dit, une erreur pendante provoque un flux de code inattendu!

+0

Eh bien, j'ai ajouté le code qui échoue après sur l'erreur reprendre ensuite et essayé de le piéger avec Si Err.Number = 3061 Puis Err.Clear() mais toujours l'erreur a sauté – tksy

+0

Quel est le code qui échoue dans votre cas ? Pouvez-vous éditer votre question et inclure ce que vous avez déjà? – Tomalak

+0

pas encore l'erreur est sortie – tksy