Just nu i M3-nätverket
Gå till innehåll

Hur ska jag hantera loggning av fel?


Shape_sthlm

Rekommendera Poster

Jag loggar fel med hjälp av följande funktion.

 

Givetvis blir det fel om det inte finns någon aktiv kontroll. Hur kan jag komma runt det?

 

Call LoggError(Err, Err.Description, Err.Source, Me.ActiveControl.Name)

 

variablerna deklareras enligt följande:

Public Sub LoggError(lngErr As Long, _
                   strDesc As String, _
                   strSource As String, _
                   Optional strActiveControl As String)

 

jag testade med att lägga till en rad

If Err.Number = 2474 Then Call LoggError(Err, Err.Description, Err.Source)

 

men utan resultat. Vilket kanske inte e så konstigt eftersom jag inte vet hur jag ska göra :-)

 

Kortfattat:

 

Först uppstår ett fel. > Detta ska loggas

 

När jag sedan anropar denna så blir det ett "nytt" fel (nr 2474), eftersom me.activecontrol.name inte finns. För själva loggningen är detta inget problem, värdet är Optional. Men givetvis blir det fel i koden... Hur kan jag komma runt detta?

 

/M

 

(Tanken är att jag ska kunna använda samma kod för alla error-hantering, oavsett om det finns en "aktiv kontroll" eller inte.)

Länk till kommentar
Dela på andra webbplatser

Om du ska jobba med dynamiska kontroller är det bättre att adressera dem via en samling istället för via en direkt referens.

 

Exempelvis.

 

Dim mySh as Shape
On Error Resume Next
Set mySh = Me.Shapes("MinKontroll")
If mySh Is Nothing Then Exit Sub
On Error Goto 0

Kontroller finns även samlade i OleObjects och vilken kan ska söka i beror lite på vad för objekt man söker.

 

det är mitt svar på din fråga :)

 

Bästa felet är ett fel som aldrig löser ut! Som ovan, om objektet inte finns fallerar tilldelningen vilket hanteras av On Resume Next och koden fortsätter med en enkel kontroll och aktion.

Länk till kommentar
Dela på andra webbplatser

jo, detta fungerar. Men jag vill ju kunna hitta en lösning där jag kan kopiera in samma kod för felhanterare i alla procedurer eller funktioner som jag önskar logga fel, utan att behöva deklarera nya variabler som eventuellt inte ens är aktuella.

 

alltså konceptuellt sett

 

If Me.ActiveControl.Name Is Nothing Then Call LoggError(Err, Err.Description, Err.Source)
else: Call LoggError(Err, Err.Description, Err.Source, Me.ActiveControl.Name)
End if

 

Dessutom, för att komma till aktuellt kod så har ett inträffat fel redan triggat detta. Dvs fel på fel fungerar ju inte om jag har förstått det hela rätt. Jag kan alltså inte använda On Error Resume Next, eftersom det redan "är ett error"... eller? För om jag nollställer så har ju informationen om första felet "försvunnit", men det är ju det som jag vill logga.

 

Förstår du hur jag tänker? Svårt att förklara detta

Länk till kommentar
Dela på andra webbplatser

vad är Me.ActiveContol för något? ActiveControll finns inte, menar du att detta ska vara en referens till aktivt objekt? Eller vad?

 

nåja, oavsett är felhantering är alltid lite klurigt och man får tänka till lite.

 

om vi säger att du har ett blad där du ibland har tre knappar på men inte alltid. Det kan tänkas att kod tar bort eller lägger till knapparna innan du kommer till en viss procedur.

 

Då är det inte i sig inte ett fel som sker när knappen inte finns där, det är ett förväntat läge som du ska hantera. Okej, du kan använda en generell felhanterare men det bör finnas en hantering i koden.

 

Vill du logga fel då får du tänka ett steg till.

vad vill du logga?

hur ska du få denna information?

Samt felhanteringen i sig får inte generera fel.

 

mmh, din tanke är inte fel... Ett exempel. Ett blad med några knappar på

 

Sub test()
On Error GoTo errHandle

OLEObjects("bnOne").Delete
Debug.Print "Raderad"
bnOne.Enabled = False
Debug.Print "Sista raden"
Exit Sub
errHandle:
Modul1.LoggError Err.Number, Err.Description, Err.Source
Resume Next
End Sub

bnOne används i exemplet och eftersom den raderas i första anropet blir det fel i andra.

 

Och en felhanterare

Public Sub LoggError(lngErr As Long, _
	strDesc As String, _
	strSource As String, _
	Optional strActiveControl As String)
Debug.Print lngErr
Debug.Print strDesc
Debug.Print strSource


End Sub

 

fungerar. (Fast det är ju ett programmeringsfel det där då programmeraren ska veta att objektet inte finns. )

 

Är det något sådant du tänker dig men då att ändra Debug.print mot att du, exempelvis, skriver data till celler på ett blad?

 

Resume Next innebär att koden återstartar på nästa rad.

Vill du försöka dig på samma rad igen skriv bara Resume

Länk till kommentar
Dela på andra webbplatser

Tack Monshi för bra synpunkter. Nu har jag fått ordning på det... (tror jag), även om det är lite moment 22 beträffande det faktum att en felhanterare inte får generera några fel... Jag får väl testa detta lite nu och se hur det fungerar.

 

 

Vid fel triggas felhanteraren:

 

ExitFel:
   Exit Sub
Fel:
   MsgBox Err & " " & Error$
   Select Case Application.CurrentObjectType
       Case Is = 2
       Call LoggError(Err, Err.Description, Err.Source, Application.CurrentObjectName)
       Case Is = 3
       Call LoggError(Err, Err.Description, Err.Source, , Application.CurrentObjectName)
       Case Else
       Call LoggError(Err, Err.Description, Err.Source)
   End Select
   Resume ExitFel

 

 

I modulen loggas felet (med uppgifter om vilken kontroll som eventuellt använts.)

 

Public Sub LoggError(lngErr As Long, _
                   strDesc As String, _
                   strSource As String, _
                   Optional strForm As String, _
                   Optional strReport As String)


'Dim dteNow As Date ' detta är ett autofält (default)
Dim dbs As DAO.Database
Dim strComputer As String, strUser As String, strUserDomain As String
Dim strApp As String, strCurrentProject As String, strSQL As String
Dim strAccVer As String
Dim strOS As String
Dim strCurrentObject As String
Dim intObject As Integer, strObject As String

'kontrollera om felet utlöstes av en kontroll
Dim myForm As Form, myReport As Report, strControl As String

strControl = ""
On Error Resume Next
If Not strForm = "" Then
   Set myForm = Forms(strForm)
   With myForm
       If Not .ActiveControl Is Nothing Then strControl = .ActiveControl.Name
   End With
   Else:
       If Not strReport = "" Then
           Set myReport = Reports(strReport)
           With myReport
               If Not .ActiveControl Is Nothing Then strControl = .ActiveControl.Name
           End With
       End If
End If
On Error GoTo Fel:

'tilldela värden
'5 objectType
If Application.CurrentObjectType = True Then
   intObject = 99
   Else:
   intObject = Nz(Application.CurrentObjectType, 99)
End If
strCurrentObject = CurrentObjectName '6
strUser = Environ("USERNAME") '7
strUserDomain = Environ("USERDOMAIN") '8
strApp = CurrentProject.FullName '9
strComputer = Environ("COMPUTERNAME") '10
strAccVer = SysCmd(acSysCmdAccessVer) '11
strOS = Environ("OS") '12

'Bygg en SQL-sträng som ska köras.
strSQL = "INSERT INTO tbl_ErrorLog ([ErrNumber], [ErrDescription], [ErrSource], [ActiveControl]," & _
   "[ObjectType], [ObjectName], [tUser], [tUserDomain], [tApp], [tComputer], [tAccessVersion], [tSystem])" & _
" VALUES ('" & lngErr & "', '" & strDesc & "', '" & strSource & "', '" & strControl & "', '" & intObject & "', '" & strCurrentObject & "', '" & strUser & "', '" & strUserDomain & "', " & _
"'" & strApp & "', '" & strComputer & "', '" & strAccVer & "', '" & strOS & "');"

'Kör SQL
Set dbs = CurrentDb
dbs.Execute strSQL, dbFailOnError

ExitFel:
   Set dbs = Nothing
   Set myForm = Nothing
   Set myReport = Nothing
   Exit Sub
Fel:
   MsgBox Err & " " & Error$
   Resume ExitFel
End Sub

Länk till kommentar
Dela på andra webbplatser

Arkiverat

Det här ämnet är nu arkiverat och är stängt för ytterligare svar.

×
×
  • Skapa nytt...