views:

2077

answers:

3

i am executing a query like this

select field from table;

here there is a loop running on many tables so if a field is not present in a table i get a runtime error 3061.

how can i by pass this error such as that on this error flow should goto another point

this is the code I have at present after goin through this 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

I am getting an type mismatch runtime error in Set rs3 = CurrentDb.OpenRecordset(strsql) i guess I am mixing up ado and dao but i am not sure where

A: 

Try this:

On Error Resume Next ' If an error occurs, move to next statement.

...statement that tries the select...

If (Err <> 0) Then

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

End If

On Error Goto 0 ' Reset error handling to previous state.

JTeagle
+4  A: 

Use the On Error statement that VBA supplies:

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

Alternatively, you can switch off automatic error handling (e.g. breaking execution and displaying an error message) on a line-by-line basis:

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

There are these statements available:

  • On Error Resume Next switches off VBA-integrated error handling (message box etc.) completely, execution simply resumes on the next line. Be sure to check for an error very early after you've used that, as a dangling error can disrupt the normal execution flow. Clear the error as soon as you caught it to prevent that.
  • On Error Goto <Jump Label> resumes execution at a given label, primarily used for per-function error handlers that catch all sorts of errors.
  • On Error Goto <Line Number> resumes at a given line number. Stay away from that, it's not useful, even dangerous.
  • On Error Goto 0 it's close cousin. Reinstates the VBA integrated error management (message box etc.)


EDIT

From the edited qestion, this is my proposal to solve your problem.

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

Be sure to clear the error in any case before you go on with a loop in the same Sub or Function. As I said, a dangling error causes code flow to become unexpected!

Tomalak
well i added the code that fails after on error resume next and tried to trap it with If Err.Number = 3061 Then Err.Clear()but still the error popped out
tksy
What is the code that fails in your case? Can you edit your question and include what you've got so far?
Tomalak
no still the error is popping out
tksy
What do you mean by "popping out"? In the debugger, when you step through your code line by line: After "OpenRecordset(...)" does it *not* resume on the next line but instead displays the error right away?!
Tomalak
yes that s it! it displays the error right away
tksy
If your code is all right, then this is impossible. Can you edit your answer once more and show what you currently use. Ideally with enough context (outer loop etc) so I can see where the error is.
Tomalak
I voted this down because of the second alternative, using On Error Resume Next to skip over the error without using a proper error handler. This is just bad, bad practice, in my opinion. On Error Resume Next is dangerous and logically problematic and should only be used with great caution.
David-W-Fenton
Thanks for explaining your reasons, appreciated. But I think you've misread me. I did not suggest to use "On Error Resume Next" unconditionally and then forget about it. Quite the opposite, I recommended great caution ("handle errors as early as possible", "dangling errors are dangerous", etc.)
Tomalak
On Error Resume Next is a great way to handle a problematic section of code in an otherwise fail-safe function, and that's exactly what it's been made for. No obstruction of execution flow, chance to react to or ignore specific expected conditions, no need for the far more dangerous GoTo statements.
Tomalak
+3  A: 

Rather than trapping the error, why not use the TableDefs to check for the field or use a mixture of ADO and DAO? ADO Schemas can provide a list of tables that contain the required field:

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
Remou
So here i will get the names of the tables in the recordset, after that Do i have to query those tables alone? How do I query the tables listed only in the recordset?
tksy
You can build a list or array of tables from the recordset (http://wiki.lessthandot.com/index.php/ADO_Schemas) or insert additonal coding in the While loop.
Remou
i am not sure whther I am understanding this correctly. Now here in the recordset do i get only the table names or do i get the tables with the contents
tksy
It is safe to try the code. It will return a list of table names that contain the field that you select.
Remou
i added Your code and then used a for loop like thisFor Each tdf In CurrentDb.TableDefs If tdf.Name = rs!Table_Name Thenbut i think the if statement is not working i am getting runtime error -2147217908(80040e0c)
tksy
i am sorry but this task of mine is not exactly the previous task of updating null values, this deals with validation and hence the remainder part of coding is different
tksy
It's always better, in my opinion, if you anticipate an error, instead of recovering from it, avoid it in the first place. So the basic concept recommended in this post is much better, in my opinion, even if the specific example offered did not exactly resolve the OP's problem.
David-W-Fenton