Ανεξάρτητα από το πόσο έμπειροι είστε με την κωδικοποίηση VBA, τα λάθη θα είναι πάντα μέρος αυτής.
Η διαφορά μεταξύ ενός αρχάριου και ενός ειδικού προγραμματιστή VBA είναι ότι οι ειδικοί προγραμματιστές γνωρίζουν πώς να χειρίζονται και να χρησιμοποιούν αποτελεσματικά τα σφάλματα.
Σε αυτό το σεμινάριο, θα σας δείξω διάφορους τρόπους που μπορείτε να χρησιμοποιήσετε για να χειριστείτε αποτελεσματικά τα σφάλματα στο Excel VBA.
Πριν ασχοληθούμε με τον χειρισμό σφαλμάτων VBA, ας κατανοήσουμε πρώτα τους διαφορετικούς τύπους σφαλμάτων που πιθανόν να αντιμετωπίσετε κατά τον προγραμματισμό σε Excel VBA.
Τύποι σφαλμάτων VBA στο Excel
Υπάρχουν τέσσερις τύποι σφαλμάτων στο Excel VBA:
- Σφάλματα σύνταξης
- Σφάλματα σύνταξης
- Σφάλματα χρόνου εκτέλεσης
- Λογικά σφάλματα
Ας καταλάβουμε γρήγορα ποια είναι αυτά τα σφάλματα και πότε είναι πιθανό να τα συναντήσετε.
Συντακτικό λάθος
Ένα σφάλμα σύνταξης, όπως υποδηλώνει το όνομα, συμβαίνει όταν το VBA εντοπίσει κάτι λάθος με τη σύνταξη στον κώδικα.
Για παράδειγμα, εάν ξεχάσετε ένα μέρος της δήλωσης/σύνταξης που χρειάζεται, τότε θα δείτε το σφάλμα μεταγλώττισης.
Στον παρακάτω κώδικα, μόλις πατήσω enter μετά τη δεύτερη γραμμή, βλέπω ένα σφάλμα μεταγλώττισης. Αυτό συμβαίνει γιατί το IF δήλωση πρέπει να έχει το ‘Τότε«Εντολή, η οποία λείπει στον παρακάτω κώδικα.
Για να βεβαιωθείτε ότι βλέπετε το σφάλμα σύνταξης κάθε φορά που λείπει κάτι, πρέπει να βεβαιωθείτε ότι ο έλεγχος Autosyntax είναι ενεργοποιημένος. Για να το κάνετε αυτό, κάντε κλικ στο «Εργαλεία» και στη συνέχεια κάντε κλικ στο «Επιλογές». Στο παράθυρο διαλόγου "Επιλογές", βεβαιωθείτε ότι είναι ενεργοποιημένη η επιλογή "Αυτόματος έλεγχος σύνταξης".
Εάν η επιλογή «Αυτόματος έλεγχος σύνταξης» είναι απενεργοποιημένη, το VBA θα επισημάνει τη γραμμή με το σφάλμα σύνταξης με κόκκινο χρώμα, αλλά δεν θα εμφανίσει το παράθυρο διαλόγου σφάλματος.
Σφάλμα μεταγλώττισης
Τα σφάλματα μεταγλώττισης εμφανίζονται όταν λείπει κάτι που απαιτείται για την εκτέλεση του κώδικα.
Για παράδειγμα, στον παρακάτω κώδικα, μόλις προσπαθήσω να εκτελέσω τον κώδικα, θα εμφανιστεί το ακόλουθο σφάλμα. Αυτό συμβαίνει καθώς έχω χρησιμοποιήσει τη δήλωση IF Στη συνέχεια χωρίς να την κλείσω με το υποχρεωτικό «Τέλος εάν».
Το VBA ελέγχει κάθε γραμμή καθώς πληκτρολογείτε τον κώδικα και επισημαίνει το σφάλμα σύνταξης μόλις η γραμμή είναι εσφαλμένη και πατήσετε enter. Τα σφάλματα μεταγλώττισης, από την άλλη πλευρά, εντοπίζονται μόνο όταν αναλυθεί ολόκληρος ο κώδικας από το VBA.
Παρακάτω είναι μερικά σενάρια όπου θα συναντήσετε το σφάλμα μεταγλώττισης:
- Χρήση δήλωσης IF χωρίς το τελικό IF
- Χρήση για δήλωση με το Επόμενο
- Χρήση της δήλωσης Επιλογή χωρίς χρήση της Επιλογής Τέλους
- Μη δήλωση της μεταβλητής (αυτό λειτουργεί μόνο όταν είναι ενεργοποιημένη η Option Explicit)
- Κλήση υπο -συνάρτησης που δεν υπάρχει (ή με λανθασμένες παραμέτρους)
Λάθη χρόνου εκτέλεσης
Τα σφάλματα χρόνου εκτέλεσης είναι αυτά που συμβαίνουν κατά την εκτέλεση του κώδικα.
Τα σφάλματα χρόνου εκτέλεσης θα εμφανιστούν μόνο όταν ληφθούν υπόψη όλα τα σφάλματα σύνταξης και μεταγλώττισης.
Για παράδειγμα, εάν εκτελείτε κώδικα που υποτίθεται ότι ανοίγει ένα βιβλίο εργασίας του Excel, αλλά αυτό το βιβλίο εργασίας δεν είναι διαθέσιμο (είτε έχει διαγραφεί είτε άλλαξε όνομα), ο κωδικός σας θα σας δώσει ένα σφάλμα χρόνου εκτέλεσης.
Όταν προκύψει σφάλμα χρόνου εκτέλεσης, θα σταματήσει ο κωδικός και θα εμφανιστεί το παράθυρο διαλόγου σφάλματος.
Το μήνυμα στο παράθυρο διαλόγου Σφάλμα χρόνου εκτέλεσης είναι λίγο πιο χρήσιμο. Προσπαθεί να εξηγήσει το πρόβλημα που μπορεί να σας βοηθήσει να το διορθώσετε.
Εάν κάνετε κλικ στο κουμπί εντοπισμού σφαλμάτων, θα επισημάνει το τμήμα του κώδικα που οδηγεί στο σφάλμα.
Εάν έχετε διορθώσει το σφάλμα, μπορείτε να κάνετε κλικ στο κουμπί Εκτέλεση στη γραμμή εργαλείων (ή πατήστε F5) για να συνεχίσετε να εκτελείτε τον κώδικα από εκεί που έφυγε.
Or μπορείτε επίσης να κάνετε κλικ στο κουμπί Τέλος για να βγείτε από τον κώδικα.
Σπουδαίος: Σε περίπτωση που κάνετε κλικ στο κουμπί Τέλος στο παράθυρο διαλόγου, θα σταματήσει ο κωδικός στη γραμμή στην οποία συναντάτε. Ωστόσο, όλες οι γραμμές κώδικα πριν από αυτό θα είχαν εκτελεστεί.Λογικά σφάλματα
Τα λογικά σφάλματα δεν θα σταματήσουν τον κωδικό σας, αλλά μπορούν να οδηγήσουν σε λάθος αποτελέσματα. Αυτά θα μπορούσαν επίσης να είναι τα πιο δύσκολα είδη σφαλμάτων για αντιμετώπιση προβλημάτων.
Αυτά τα σφάλματα δεν επισημαίνονται από τον μεταγλωττιστή και πρέπει να αντιμετωπιστούν με μη αυτόματο τρόπο.
Ένα παράδειγμα λογικού σφάλματος (με το οποίο συχνά βρίσκομαι κολλημένος) βρίσκεται σε έναν ατελείωτο βρόχο.
Ένα άλλο παράδειγμα θα μπορούσε να είναι όταν δίνει ένα αποτέλεσμα που είναι λάθος. Για παράδειγμα, μπορεί να καταλήξετε να χρησιμοποιείτε μια λανθασμένη μεταβλητή στον κώδικα ή να προσθέσετε δύο μεταβλητές όταν η μία είναι εσφαλμένη.
Υπάρχουν μερικοί τρόποι που χρησιμοποιώ για την αντιμετώπιση λογικών σφαλμάτων:
- Εισαγάγετε το πλαίσιο μηνυμάτων σε κάποιο σημείο του κώδικα και επισημάνετε τιμές/δεδομένα που μπορούν να σας βοηθήσουν να καταλάβετε εάν τα πάντα πηγαίνουν όπως αναμενόταν.
- Αντί να εκτελέσετε τον κώδικα με τη μία, περάστε από κάθε γραμμή μία προς μία. Για να το κάνετε αυτό, κάντε κλικ οπουδήποτε στον κώδικα και πατήστε F8. θα παρατηρήσετε ότι κάθε φορά που πατάτε το F8, εκτελείται μία γραμμή. Αυτό σας επιτρέπει να περνάτε τον κώδικα μία γραμμή τη φορά και να προσδιορίζετε τα λογικά σφάλματα.
Χρήση εντοπισμού σφαλμάτων για εύρεση σφαλμάτων σύνταξης/σύνταξης
Μόλις τελειώσετε με τον κώδικα, είναι καλή πρακτική να τον μεταγλωττίσετε πρώτα πριν την εκτέλεση.
Για να μεταγλωττίσετε έναν κώδικα, κάντε κλικ στην επιλογή εντοπισμού σφαλμάτων στη γραμμή εργαλείων και κάντε κλικ στο στοιχείο Μεταγλώττιση VBAProject.
Όταν συντάσσετε ένα έργο VBA, περνάει από τον κώδικα και εντοπίζει σφάλματα (εάν υπάρχουν).
Σε περίπτωση που εντοπίσει σφάλμα, θα σας εμφανίσει ένα παράθυρο διαλόγου με το σφάλμα. Βρίσκει λάθη ένα -ένα. Έτσι, αν εντοπίσει σφάλμα και το έχετε διορθώσει, πρέπει να εκτελέσετε ξανά μεταγλώττιση για να βρείτε άλλα σφάλματα (εάν υπάρχουν).
Όταν ο κωδικός σας είναι απαλλαγμένος από σφάλματα, η επιλογή Compile VBAProject θα είναι γκρι.
Σημειώστε ότι η μεταγλώττιση θα εντοπίσει μόνο σφάλματα "Σύνταξη" και σφάλματα "Μεταγλώττιση". ΔΕΝ θα βρει τα σφάλματα χρόνου εκτέλεσης.
Όταν γράφετε κώδικα VBA, δεν θέλετε να εμφανιστούν τα σφάλματα. Για να αποφευχθεί αυτό, υπάρχουν πολλές μέθοδοι χειρισμού σφαλμάτων που μπορείτε να χρησιμοποιήσετε.
Στις επόμενες ενότητες αυτού του άρθρου, θα καλύψω τις μεθόδους που μπορείτε να χρησιμοποιήσετε για το χειρισμό σφαλμάτων VBA στο Excel.
Διαμόρφωση ρυθμίσεων σφαλμάτων (χειρισμός έναντι μη χειρισμένων σφαλμάτων)
Πριν ξεκινήσετε να εργάζεστε με τον κωδικό σας, πρέπει να ελέγξετε για μία ρύθμιση στο Excel VBA.
Μεταβείτε στη γραμμή εργαλείων VBA και κάντε κλικ στο Εργαλεία και, στη συνέχεια, κάντε κλικ στο κουμπί Επιλογές.
Στο παράθυρο διαλόγου Επιλογές, κάντε κλικ στην καρτέλα Γενικά και βεβαιωθείτε ότι στην ομάδα «Παγίδευση σφαλμάτων» είναι επιλεγμένο το «Διάλειμμα σε μη χειρισμένα σφάλματα».
Επιτρέψτε μου να εξηγήσω τις τρεις επιλογές:
- Διάλειμμα σε όλα τα σφάλματα: Αυτό θα σταματήσει τον κωδικό σας για όλους τους τύπους σφαλμάτων, ακόμη και όταν έχετε χρησιμοποιήσει τις τεχνικές για να χειριστείτε αυτά τα σφάλματα.
- Διάλειμμα στην ενότητα τάξης: Αυτό θα σταματήσει τον κωδικό σας σε όλα τα μη διαχειριζόμενα σφάλματα και ταυτόχρονα, εάν χρησιμοποιείτε αντικείμενα όπως Userforms, θα σπάσει επίσης μέσα σε αυτά τα αντικείμενα και θα επισημάνει την ακριβή γραμμή που προκαλεί το σφάλμα.
- Διάλειμμα για μη χειριζόμενα σφάλματα: Αυτό θα σταματήσει τον κωδικό σας μόνο για τα σφάλματα που δεν αντιμετωπίζονται. Αυτή είναι η προεπιλεγμένη ρύθμιση καθώς διασφαλίζει ότι τυχόν μη διαχειριζόμενα σφάλματα θα ειδοποιηθούν. Εάν χρησιμοποιείτε αντικείμενα όπως οι μορφές χρηστών, αυτό δεν θα επισημάνει τη γραμμή που προκαλεί το σφάλμα στο αντικείμενο, αλλά θα επισημάνει μόνο τη γραμμή που αναφέρεται στο συγκεκριμένο αντικείμενο.
Με λίγα λόγια - εάν ξεκινάτε με το Excel VBA, βεβαιωθείτε ότι είναι επιλεγμένο το "Break on Unhandled Errors".
Χειρισμός σφαλμάτων VBA με δηλώσεις "On Error"
Όταν ο κωδικός σας αντιμετωπίζει σφάλμα, μπορείτε να κάνετε μερικά πράγματα:
- Αγνοήστε το σφάλμα και αφήστε τον κώδικα να συνεχίσει
- Έχετε έναν κωδικό χειρισμού σφάλματος στη θέση του και εκτελέστε τον όταν προκύψει σφάλμα
Και οι δύο αυτές μέθοδοι χειρισμού σφαλμάτων διασφαλίζουν ότι ο τελικός χρήστης δεν θα δει ένα σφάλμα.
Υπάρχουν μερικές δηλώσεις "Σφάλμα" που μπορείτε να χρησιμοποιήσετε για να τις ολοκληρώσετε.
Στο Σφάλμα Συνέχιση Επόμενο
Όταν χρησιμοποιείτε το «On Error Resume Next» στον κωδικό σας, τυχόν σφάλμα που θα αντιμετωπιστεί θα αγνοηθεί και ο κώδικας θα συνεχίσει να εκτελείται.
Αυτή η μέθοδος χειρισμού σφαλμάτων χρησιμοποιείται αρκετά συχνά, αλλά πρέπει να είστε προσεκτικοί όταν τη χρησιμοποιείτε. Δεδομένου ότι αγνοεί εντελώς κάθε σφάλμα που μπορεί να προκύψει, ενδέχεται να μην μπορείτε να εντοπίσετε τα σφάλματα που πρέπει να διορθωθούν.
Για παράδειγμα, εάν εκτελεστεί ο παρακάτω κώδικας, θα επιστρέψει ένα σφάλμα.
Sub AssignValues () x = 20 /4 y = 30 /0 Τέλος υπο
Αυτό συμβαίνει επειδή δεν μπορείτε να διαιρέσετε έναν αριθμό με το μηδέν.
Αλλά αν χρησιμοποιήσω τη δήλωση «On Error Resume Next» σε αυτόν τον κώδικα (όπως φαίνεται παρακάτω), θα αγνοήσει το σφάλμα και δεν θα γνωρίζω ότι υπάρχει ένα ζήτημα που πρέπει να διορθωθεί.
Sub AssignValues () On Error Συνέχιση Επόμενο x = 20 /4 y = 30 /0 Τέλος υπο
Το Error Resume Next πρέπει να χρησιμοποιείται μόνο όταν γνωρίζετε σαφώς το είδος των σφαλμάτων που αναμένεται να προκαλέσει ο κώδικας VBA και είναι εντάξει να το αγνοήσετε.
Για παράδειγμα, παρακάτω είναι ο κώδικας συμβάντος VBA που θα προσθέσει αμέσως την τιμή ημερομηνίας και ώρας στο κελί Α1 ενός νέου φύλλου που έχει εισαχθεί (αυτός ο κωδικός προστίθεται στο φύλλο εργασίας και όχι σε μια ενότητα).
Private Sub Workbook_NewSheet (ByVal Sh As Object) Sh.Range ("A1") = Format (Now, "dd-mmm-yyyy hh: mm: ss") End Sub
Αν και αυτό λειτουργεί τέλεια στις περισσότερες περιπτώσεις, θα έδειχνε σφάλμα αν προσθέσω ένα φύλλο γραφήματος αντί για ένα φύλλο εργασίας. Δεδομένου ότι ένα φύλλο γραφήματος δεν έχει κελιά, ο κώδικας θα έριχνε ένα σφάλμα.
Έτσι, εάν χρησιμοποιήσω τη δήλωση «On Error Resume Next» σε αυτόν τον κώδικα, θα λειτουργήσει όπως αναμένεται με τα φύλλα εργασίας και δεν κάνει τίποτα με τα φύλλα γραφήματος.
Private Sub Workbook_NewSheet (ByVal Sh As Object) On Error Resume Next Sh.Range ("A1") = Format (Now, "dd-mmm-yyyy hh: mm: ss") End Sub
Σημείωση: Στο Error Resume Η επόμενη δήλωση χρησιμοποιείται καλύτερα όταν γνωρίζετε τι είδους σφάλματα είναι πιθανό να αντιμετωπίσετε. Και στη συνέχεια, εάν πιστεύετε ότι είναι ασφαλές να αγνοήσετε αυτά τα σφάλματα, μπορείτε να το χρησιμοποιήσετε.
Μπορείτε να ανεβάσετε αυτόν τον κώδικα στο επόμενο επίπεδο αναλύοντας αν υπήρξε σφάλμα και εμφανίζοντας ένα σχετικό μήνυμα για αυτό.
Ο παρακάτω κώδικας θα εμφανίζει ένα πλαίσιο μηνυμάτων που θα ενημερώνει τον χρήστη ότι δεν έχει εισαχθεί φύλλο εργασίας.
Private Sub Workbook_NewSheet (ByVal Sh As Object) On Error Resume Next Sh.Range ("A1") = Format (Now, "dd-mmm-yyyy hh: mm: ss") If Err.Number 0 Then MsgBox "Looks like you εισαγάγει ένα φύλλο γραφήματος "& vbCrLf &" Error - "& Err.Description End If End Sub
Το 'Err.Number' χρησιμοποιείται για να λάβετε τον αριθμό σφάλματος και το 'Err.Description' χρησιμοποιείται για να λάβετε την περιγραφή του σφάλματος. Αυτά θα καλυφθούν αργότερα σε αυτό το σεμινάριο.
Σφάλμα GoTo 0
Το "On Error GoTo 0" θα σταματήσει τον κωδικό στη γραμμή που προκαλεί το σφάλμα και εμφανίζει ένα πλαίσιο μηνυμάτων που περιγράφει το σφάλμα.
Με απλά λόγια, ενεργοποιεί την προεπιλεγμένη συμπεριφορά ελέγχου σφαλμάτων και εμφανίζει το προεπιλεγμένο μήνυμα σφάλματος.
Τότε γιατί να το χρησιμοποιήσω;
Κανονικά, δεν χρειάζεται να χρησιμοποιήσετε το "On Error Goto 0", αλλά μπορεί να είναι χρήσιμο όταν το χρησιμοποιείτε σε συνδυασμό με το "On Error Resume Next"
ΑΣΕ με να εξηγήσω!
Ο παρακάτω κώδικας θα επιλέξει όλα τα κενά κελιά στην επιλογή.
Sub SelectFormulaCells () Selection.SpecialCells (xlCellTypeBlanks). Επιλέξτε End Sub
Αλλά θα έδειχνε σφάλμα όταν δεν υπάρχουν κενά κελιά στα επιλεγμένα κελιά.
Έτσι, για να αποφύγετε την εμφάνιση του σφάλματος, μπορείτε να χρησιμοποιήσετε το On Error Resume next ’
Τώρα, θα εμφανίσει επίσης οποιοδήποτε σφάλμα κατά την εκτέλεση του παρακάτω κώδικα:
Sub SelectFormulaCells () On Error Resume Next Selection.SpecialCells (xlCellTypeBlanks). Επιλέξτε End Sub
Μέχρι εδώ καλά!
Το πρόβλημα προκύπτει όταν υπάρχει ένα μέρος του κώδικα όπου μπορεί να παρουσιαστεί σφάλμα και επειδή χρησιμοποιείτε το «On Error Resume Next», ο κώδικας απλώς θα το αγνοήσει και θα μετακινηθεί στην επόμενη γραμμή.
Για παράδειγμα, στον παρακάτω κώδικα, δεν θα υπήρχε ερώτημα σφάλματος:
Sub SelectFormulaCells () On Error Resume Next Selection.SpecialCells (xlCellTypeBlanks). Επιλέξτε '… περισσότερο κώδικα που μπορεί να περιέχει σφάλμα Τέλος υπο
Στον παραπάνω κώδικα, υπάρχουν δύο σημεία όπου μπορεί να προκύψει σφάλμα. Το πρώτο μέρος είναι όπου επιλέγουμε όλα τα κενά κελιά (χρησιμοποιώντας Selection.SpecialCells) και το δεύτερο είναι στον υπόλοιπο κώδικα.
Ενώ το πρώτο σφάλμα αναμένεται, οποιοδήποτε σφάλμα μετά από αυτό δεν είναι.
Εδώ έρχεται να σώσει το On Error Goto 0.
Όταν το χρησιμοποιείτε, επαναφέρετε τη ρύθμιση σφάλματος στην προεπιλογή, όπου θα αρχίσει να εμφανίζει σφάλματα όταν το συναντά.
Για παράδειγμα, στον παρακάτω κώδικα, δεν θα υπήρχε σφάλμα σε περίπτωση που δεν υπάρχουν κενά κελιά, αλλά θα υπήρχε μια προτροπή σφάλματος λόγω του '10/0
Sub SelectFormulaCells () On Error Resume Next Selection.SpecialCells (xlCellTypeBlanks). Επιλέξτε On Error GoTo 0 '… περισσότερος κώδικας που μπορεί να περιέχει σφάλμα End Sub
On Error Goto [Ετικέτα]
Οι δύο παραπάνω μέθοδοι - «On Error Resume Next» και «On Error Goto 0» - δεν μας επιτρέπουν να χειριστούμε πραγματικά το σφάλμα. Το ένα κάνει τον κωδικό να αγνοήσει το σφάλμα και το δεύτερο να συνεχίσει τον έλεγχο σφάλματος.
Στο Error Go [Label] είναι ένας τρόπος με τον οποίο μπορείτε να καθορίσετε τι θέλετε να κάνετε σε περίπτωση που ο κωδικός σας έχει σφάλμα.
Παρακάτω είναι η δομή κώδικα που χρησιμοποιεί αυτόν τον χειριστή σφαλμάτων:
Sub Test () Στο Error GoTo Label: X = 10 /0 'αυτή η γραμμή προκαλεί σφάλμα'…. Ο υπόλοιπος κωδικός σας πηγαίνει εδώ Exit Sub Label: 'code for handle the error End End
Λάβετε υπόψη ότι πριν από το Σφάλμα κατά τον χειρισμό της «Ετικέτας», υπάρχει ένα Exit Sub. Αυτό διασφαλίζει ότι σε περίπτωση που δεν υπάρχουν σφάλματα, το δευτερεύον τμήμα εξέρχεται και ο κώδικας "Ετικέτα" δεν εκτελείται. Σε περίπτωση που δεν χρησιμοποιείτε το Exit Sub, θα εκτελεί πάντα τον κώδικα "Ετικέτα".
Στο παρακάτω παράδειγμα κώδικα, όταν προκύψει σφάλμα, ο κώδικας μεταπηδά και εκτελεί τον κώδικα στην ενότητα χειριστή (και εμφανίζει ένα πλαίσιο μηνυμάτων).
Sub Errorhandler () On Error GoTo ErrMsg X = 12 Y = 20 /0 Z = 30 Exit Sub ErrMsg: MsgBox "Φαίνεται να υπάρχει σφάλμα" & vbCrLf & Err.Description End Sub
Σημειώστε ότι όταν εμφανιστεί σφάλμα, ο κώδικας έχει ήδη εκτελέσει και εκτελέσει τις γραμμές πριν από τη γραμμή που προκαλεί το σφάλμα. Στο παραπάνω παράδειγμα, ο κώδικας ορίζει την τιμή X ως 12, αλλά επειδή το σφάλμα εμφανίζεται στην επόμενη γραμμή, δεν ορίζει τις τιμές για Y και Z.
Μόλις ο κωδικός μεταβεί στον κωδικό χειριστή σφαλμάτων (ErrMsg σε αυτό το παράδειγμα), θα συνεχίσει να εκτελεί όλες τις γραμμές μέσα και κάτω από τον κωδικό χειριστή σφάλματος και την έξοδο από το δευτερεύον.
Στο Error Goto -1
Αυτό είναι λίγο περίπλοκο και στις περισσότερες περιπτώσεις, είναι απίθανο να το χρησιμοποιήσετε.
Αλλά θα το καλύψω ακόμα καθώς έχω αντιμετωπίσει μια κατάσταση όπου αυτό ήταν απαραίτητο (μη διστάσετε να το αγνοήσετε και να μεταβείτε στην επόμενη ενότητα εάν ψάχνετε μόνο για τα βασικά).
Πριν μπω στη μηχανική του, επιτρέψτε μου να προσπαθήσω και να εξηγήσω πού μπορεί να είναι χρήσιμο.
Ας υποθέσουμε ότι έχετε έναν κωδικό όπου παρουσιάζεται σφάλμα. Αλλά όλα είναι καλά καθώς έχετε έναν χειριστή σφαλμάτων στη θέση του. Τι συμβαίνει όμως όταν υπάρχει άλλο σφάλμα στον κωδικό χειρισμού σφαλμάτων (ναι … κάπως σαν την ταινία έναρξης).
Σε μια τέτοια περίπτωση, δεν μπορείτε να χρησιμοποιήσετε τον δεύτερο χειριστή καθώς το πρώτο σφάλμα δεν έχει διαγραφεί. Έτσι, ενώ χειρίζεστε το πρώτο σφάλμα, στη μνήμη του VBA εξακολουθεί να υπάρχει. Και η μνήμη VBA έχει μόνο μια θέση για ένα σφάλμα - όχι δύο ή περισσότερα από αυτό.
Σε αυτό το σενάριο, μπορείτε να χρησιμοποιήσετε το On Error Goto -1.
Διαγράφει το σφάλμα και απελευθερώνει τη μνήμη VBA για να χειριστεί το επόμενο σφάλμα.
Αρκετή κουβέντα!
Ας εξηγήσω τώρα χρησιμοποιώντας παραδείγματα.
Ας υποθέσουμε ότι έχω τον παρακάτω κωδικό. Αυτό θα ρίξει ένα σφάλμα καθώς υπάρχει διαίρεση με το μηδέν.
Sub Errorhandler () X = 12 Y = 20 /0 Z = 30 End Sub
Έτσι, για να το χειριστώ, χρησιμοποιώ έναν κωδικό χειρισμού σφαλμάτων (με το όνομα ErrMsg) όπως φαίνεται παρακάτω:
Sub Errorhandler () On Error GoTo ErrMsg X = 12 Y = 20 /0 Z = 30 Exit Sub ErrMsg: MsgBox "Φαίνεται να υπάρχει σφάλμα" & vbCrLf & Err.Description End Sub
Όλα πάλι καλά τώρα. Μόλις παρουσιαστεί το σφάλμα, χρησιμοποιείται ο χειριστής σφαλμάτων και εμφανίζει ένα πλαίσιο μηνυμάτων όπως φαίνεται παρακάτω.
Τώρα, επεκτείνω τον κώδικα έτσι ώστε να έχω περισσότερο κώδικα μέσα ή μετά τον χειριστή σφαλμάτων.
Sub Errorhandler () On Error GoTo ErrMsg X = 12 Y = 20 /0 Z = 30 Exit Sub ErrMsg: MsgBox "Φαίνεται να υπάρχει σφάλμα" & vbCrLf & Err.Description A = 10 /2 B = 35 /0 End Sub
Δεδομένου ότι το πρώτο σφάλμα έχει αντιμετωπιστεί αλλά το δεύτερο δεν έχει γίνει, βλέπω ξανά ένα σφάλμα όπως φαίνεται παρακάτω.
Ακόμα όλα καλά. Ο κώδικας συμπεριφέρεται με τον τρόπο που περιμέναμε.
Έτσι, για να χειριστώ το δεύτερο σφάλμα, χρησιμοποιώ άλλο χειριστή σφαλμάτων (ErrMsg2).
Sub Errorhandler () On Error GoTo ErrMsg X = 12 Y = 20 /0 Z = 30 Exit Sub ErrMsg: MsgBox "Φαίνεται να υπάρχει σφάλμα" & vbCrLf & Err.Description On Error GoTo ErrMsg2 A = 10 /2 B = 35 / 0 Exit Sub ErrMsg2: MsgBox "Φαίνεται να υπάρχει ξανά σφάλμα" & vbCrLf & Err.Description End Sub
Και εδώ είναι που είναι δεν λειτουργεί όπως αναμενόταν.
Εάν εκτελέσετε τον παραπάνω κώδικα, θα εξακολουθήσει να σας εμφανίζει σφάλμα χρόνου εκτέλεσης, ακόμη και μετά την τοποθέτηση του δεύτερου χειριστή σφαλμάτων.
Αυτό συμβαίνει καθώς δεν καθαρίσαμε το πρώτο σφάλμα από τη μνήμη του VBA.
Ναι, το χειριστήκαμε! Παραμένει όμως στη μνήμη.
Και όταν το VBA αντιμετωπίζει άλλο σφάλμα, εξακολουθεί να κολλάει με το πρώτο σφάλμα και ως εκ τούτου ο δεύτερος χειριστής σφαλμάτων δεν χρησιμοποιείται. Ο κωδικός σταματά στη γραμμή που προκάλεσε το σφάλμα και εμφανίζει το μήνυμα σφάλματος.
Για να καθαρίσετε τη μνήμη του VBA και να καθαρίσετε το προηγούμενο σφάλμα, πρέπει να χρησιμοποιήσετε το «On Error Goto -1».
Έτσι, αν προσθέσετε αυτήν τη γραμμή στον παρακάτω κώδικα και την εκτελέσετε, θα λειτουργήσει όπως αναμενόταν.
Sub Errorhandler () On Error GoTo ErrMsg X = 12 Y = 20 /0 Z = 30 Exit Sub ErrMsg: MsgBox "Φαίνεται να υπάρχει σφάλμα" & vbCrLf & Err.Description On Error GoTo -1 On Error GoTo ErrMsg2 A = 10 / 2 B = 35 /0 Exit Sub ErrMsg2: MsgBox "Φαίνεται να υπάρχει ξανά σφάλμα" & vbCrLf & Err.Description End SubΣημείωση: Το σφάλμα διαγράφεται αυτόματα όταν τελειώσει μια υπορουτίνα.Έτσι, το ‘On Error Goto -1’ μπορεί να είναι χρήσιμο όταν λαμβάνετε δύο ή περισσότερα από δύο σφάλματα στην ίδια υπορουτίνα.
Το αντικείμενο Err
Κάθε φορά που συμβαίνει σφάλμα με έναν κωδικό, είναι το αντικείμενο Err που χρησιμοποιείται για τη λήψη λεπτομερειών σχετικά με το σφάλμα (όπως ο αριθμός σφάλματος ή η περιγραφή).
Err Object Properties
Το αντικείμενο Err έχει τις ακόλουθες ιδιότητες:
Ιδιοκτησία | Περιγραφή |
Αριθμός | Ένας αριθμός που αντιπροσωπεύει τον τύπο σφάλματος. Όταν δεν υπάρχει σφάλμα, αυτή η τιμή είναι 0 |
Περιγραφή | Μια σύντομη περιγραφή του σφάλματος |
Πηγή | Όνομα έργου στο οποίο παρουσιάστηκε το σφάλμα |
HelpContext | Το αναγνωριστικό περιβάλλοντος βοήθειας για το σφάλμα στο αρχείο βοήθειας |
HelpFile | Μια συμβολοσειρά που αντιπροσωπεύει τη θέση του φακέλου και το όνομα αρχείου του αρχείου βοήθειας |
Ενώ στις περισσότερες περιπτώσεις δεν χρειάζεται να χρησιμοποιήσετε το αντικείμενο Err, μπορεί μερικές φορές να είναι χρήσιμο κατά τον χειρισμό σφαλμάτων στο Excel.
Για παράδειγμα, ας υποθέσουμε ότι έχετε ένα σύνολο δεδομένων όπως φαίνεται παρακάτω και για κάθε αριθμό, στην επιλογή, θέλετε να υπολογίσετε την τετραγωνική ρίζα στο διπλανό κελί.
Ο παρακάτω κώδικας μπορεί να το κάνει, αλλά επειδή υπάρχει μια συμβολοσειρά κειμένου στο κελί A5, εμφανίζει σφάλμα μόλις συμβεί αυτό.
Sub FindSqrRoot () Dim rng As Range Set rng = Επιλογή για κάθε κελί στο κελί rng. Offset (0, 1). Value = Sqr (cell.Vale) Επόμενο κελί Τέλος υπο
Το πρόβλημα με αυτόν τον τύπο μηνύματος σφάλματος είναι ότι δεν σας δίνει τίποτα για το τι έχει πάει στραβά και πού παρουσιάστηκε το πρόβλημα.
Μπορείτε να χρησιμοποιήσετε το αντικείμενο Err για να κάνετε αυτά τα μηνύματα σφάλματος πιο ουσιαστικά.
Για παράδειγμα, εάν χρησιμοποιώ τώρα τον παρακάτω κώδικα VBA, θα σταματήσει τον κωδικό μόλις εμφανιστεί το σφάλμα και θα εμφανίσει ένα πλαίσιο μηνύματος με τη διεύθυνση κελιού του κελιού όπου υπάρχει πρόβλημα.
Sub FindSqrRoot () Dim rng As Range Set rng = Επιλογή για κάθε κελί In rng On Error GoTo ErrHandler cell.Offset (0, 1). Value = Sqr (cell.Value) Επόμενο κελί ErrHandler: MsgBox "Error Number:" & Err .Number & vbCrLf & _ "Error Description:" & Err.Description & vbCrLf & _ "Error at:" & cell.Address End Sub
Ο παραπάνω κώδικας θα σας έδινε πολύ περισσότερες πληροφορίες από την απλή «Αναντιστοιχία τύπου», ειδικά τη διεύθυνση κελιού, ώστε να γνωρίζετε πού συνέβη το σφάλμα.
Μπορείτε να βελτιώσετε περαιτέρω αυτόν τον κώδικα για να βεβαιωθείτε ότι ο κώδικάς σας λειτουργεί μέχρι το τέλος (αντί να σπάσει σε κάθε σφάλμα) και, στη συνέχεια, σας δίνει μια λίστα με τη διεύθυνση κυψέλης όπου εμφανίζεται το σφάλμα.
Ο παρακάτω κώδικας θα το έκανε αυτό:
Sub FindSqrRoot2 () Dim ErrorCells As String Dim rng As Range On Error Resume Next rng = Selection For each cell In rng cell.Offset (0, 1). Value = Sqr (cell.Value) If Err.Number 0 Then ErrorCells = ErrorCells & vbCrLf & cell.Address On Error GoTo -1 End If Next cell MsgBox "Σφάλμα στα ακόλουθα κελιά" & ErrorCells Exit Sub End Sub
Ο παραπάνω κώδικας εκτελείται μέχρι το τέλος και δίνει την τετραγωνική ρίζα όλων των κελιών που έχουν αριθμούς (στην παρακείμενη στήλη). Στη συνέχεια εμφανίζει ένα μήνυμα που παραθέτει όλα τα κελιά όπου υπήρξε σφάλμα (όπως φαίνεται παρακάτω):
Err Object Methods
Ενώ οι ιδιότητες Err είναι χρήσιμες για την εμφάνιση χρήσιμων πληροφοριών σχετικά με τα σφάλματα, υπάρχουν επίσης δύο μέθοδοι Err που μπορούν να σας βοηθήσουν στον χειρισμό σφαλμάτων.
Μέθοδος | Περιγραφή |
Σαφή | Διαγράφει όλες τις ρυθμίσεις ιδιοτήτων του αντικειμένου Err |
Υψώνω | Δημιουργεί σφάλμα χρόνου εκτέλεσης |
Ας μάθουμε γρήγορα τι είναι αυτά και πώς/γιατί να τα χρησιμοποιήσουμε με το VBA στο Excel.
Err Clear Method
Ας υποθέσουμε ότι έχετε ένα σύνολο δεδομένων όπως φαίνεται παρακάτω και θέλετε να λάβετε την τετραγωνική ρίζα όλων αυτών των αριθμών στην παρακείμενη στήλη.
Ο ακόλουθος κώδικας θα πάρει τις τετραγωνικές ρίζες όλων των αριθμών στην παρακείμενη στήλη και θα εμφανίσει ένα μήνυμα ότι προέκυψε σφάλμα για τα κελιά A5 και A9 (καθώς αυτά έχουν κείμενο σε αυτό).
Sub FindSqrRoot2 () Dim ErrorCells As String Dim rng As Range On Error Resume Next rng = Selection For each cell In rng cell.Offset (0, 1). Value = Sqr (cell.Value) If Err.Number 0 Then ErrorCells = ErrorCells & vbCrLf & cell.Address Err.Clear End If Next cell MsgBox "Σφάλμα στα ακόλουθα κελιά" & ErrorCells End Sub
Σημειώστε ότι έχω χρησιμοποιήσει τη μέθοδο Err.Clear μέσα στη δήλωση If then.
Μόλις παρουσιαστεί ένα σφάλμα και παγιδευτεί από τη συνθήκη If, η μέθοδος Err.Clear επαναφέρει τον αριθμό σφάλματος στο 0. Αυτό διασφαλίζει ότι η συνθήκη IF παγιδεύει μόνο τα σφάλματα για τα κελιά όπου εμφανίζεται.
Αν δεν χρησιμοποιούσα τη μέθοδο Err.Clear, μόλις παρουσιαστεί το σφάλμα, θα ήταν πάντα αληθές στην κατάσταση IF και ο αριθμός σφάλματος δεν έχει επαναφερθεί.
Ένας άλλος τρόπος εκτέλεσης αυτού του έργου είναι χρησιμοποιώντας το On Error Goto -1, το οποίο επαναφέρει εντελώς το σφάλμα.
Σημείωση: Το Err.Clear διαφέρει από το On Error Goto -1. Err.Clear διαγράφει μόνο την περιγραφή σφάλματος και τον αριθμό σφάλματος. δεν το επαναφέρει εντελώς. Αυτό σημαίνει ότι εάν υπάρχει άλλη περίπτωση σφάλματος στον ίδιο κώδικα, δεν θα μπορείτε να το χειριστείτε πριν την επαναφέρετε (κάτι που μπορεί να γίνει με το «On Error Goto -1» και όχι με το «Err.Clear»).Err Raise Method
Η μέθοδος Err.Raise σας επιτρέπει να εμφανίσετε ένα σφάλμα χρόνου εκτέλεσης.
Παρακάτω είναι η σύνταξη της χρήσης της μεθόδου Err.Raise:
Err.Raise [αριθμός], [πηγή], [περιγραφή], [helpfile], [helpcontext]
Όλα αυτά τα ορίσματα είναι προαιρετικά και μπορείτε να τα χρησιμοποιήσετε για να κάνετε το μήνυμα σφάλματος πιο ουσιαστικό.
Γιατί όμως θα θέλατε ποτέ να κάνετε εσείς ένα σφάλμα;
Καλή ερώτηση!
Μπορείτε να χρησιμοποιήσετε αυτήν τη μέθοδο όταν υπάρχει περίπτωση σφάλματος (που σημαίνει ότι ούτως ή άλλως θα υπάρξει σφάλμα) και, στη συνέχεια, χρησιμοποιήστε αυτήν τη μέθοδο για να πείτε στον χρήστη περισσότερα σχετικά με το σφάλμα (αντί για το λιγότερο χρήσιμο μήνυμα σφάλματος που εμφανίζει το VBA από προεπιλογή).
Για παράδειγμα, ας υποθέσουμε ότι έχετε ένα σύνολο δεδομένων όπως φαίνεται παρακάτω και θέλετε όλα τα κελιά να έχουν μόνο αριθμητικές τιμές.
Sub RaiseError () Dim rng As Range Set rng = Selection On Error GoTo ErrHandler For Every Cell In rng If Not (IsNumeric (Cell.Value)) Στη συνέχεια Err.Raise vbObjectError + 513, Cell.Address, "Not a number", " Test.html "Τέλος αν το επόμενο κελί ErrHandler: MsgBox Err.Description & vbCrLf & Err.HelpFile End Sub
Ο παραπάνω κώδικας θα εμφανίσει ένα μήνυμα σφάλματος που έχει την καθορισμένη περιγραφή και το αρχείο περιβάλλοντος.
Προσωπικά, δεν έχω χρησιμοποιήσει ποτέ το Err.Raise καθώς κυρίως δουλεύω μόνο με Excel. Αλλά για κάποιον που χρησιμοποιεί VBA για να συνεργαστεί με το Excel μαζί με άλλες εφαρμογές όπως το Outlook, το Word ή το PowerPoint, αυτό μπορεί να είναι χρήσιμο.
Ακολουθεί ένα αναλυτικό άρθρο σχετικά με τη μέθοδο Err.Raise σε περίπτωση που θέλετε να μάθετε περισσότερα.
VBA Error Handling Best Practices
Ανεξάρτητα από το πόσο εξειδικευμένοι αποκτάτε τη συγγραφή κώδικα VBA, τα λάθη θα είναι πάντα μέρος αυτού. Οι καλύτεροι κωδικοποιητές είναι εκείνοι που έχουν τις ικανότητες να χειρίζονται σωστά αυτά τα σφάλματα.
Ακολουθούν μερικές βέλτιστες πρακτικές που μπορείτε να χρησιμοποιήσετε όταν πρόκειται για χειρισμό σφαλμάτων στο Excel VBA.
- Χρησιμοποιήστε το «On Error Go [Label]» στην αρχή του κώδικα. Αυτό θα διασφαλίσει ότι αντιμετωπίζεται οποιοδήποτε σφάλμα μπορεί να συμβεί από εκεί.
- Χρησιμοποιήστε το «On Error Resume Next» ΜΟΝΟ όταν είστε σίγουροι για τα σφάλματα που μπορεί να προκύψουν. Χρησιμοποιήστε το μόνο με το αναμενόμενο σφάλμα. Σε περίπτωση που το χρησιμοποιήσετε με απροσδόκητα λάθη, απλά θα το αγνοήσει και θα προχωρήσει. Μπορείτε να χρησιμοποιήσετε το «On Error Resume Next» με το «Err.Raise» εάν θέλετε να αγνοήσετε έναν συγκεκριμένο τύπο σφάλματος και να εντοπίσετε το υπόλοιπο.
- Όταν χρησιμοποιείτε χειριστές σφαλμάτων, βεβαιωθείτε ότι χρησιμοποιείτε το Exit Sub πριν από τους χειριστές. Αυτό θα διασφαλίσει ότι ο κωδικός χειρισμού σφαλμάτων εκτελείται μόνο όταν υπάρχει σφάλμα (αλλιώς θα εκτελείται πάντα).
- Χρησιμοποιήστε πολλαπλούς χειριστές σφαλμάτων για να παγιδεύσετε διαφορετικά είδη σφαλμάτων. Η κατοχή πολλαπλών χειριστών σφαλμάτων διασφαλίζει ότι το σφάλμα αντιμετωπίζεται σωστά. Για παράδειγμα, θα θέλατε να χειριστείτε ένα σφάλμα "ασυμφωνίας τύπου" διαφορετικά από ένα σφάλμα χρόνου εκτέλεσης "Διαίρεση με 0".
Ελπίζω να βρήκατε χρήσιμο αυτό το άρθρο στο Excel!
Ακολουθούν μερικά ακόμη σεμινάρια Excel VBA που μπορεί να σας αρέσουν:
- Τύποι δεδομένων Excel VBA - Ένας πλήρης οδηγός
- Excel VBA Loops - For Next, Do while, Do till, για καθένα
- Excel VBA Events - Ένας εύκολος (και πλήρης) οδηγός
- Excel Visual Basic Editor - Πώς να το ανοίξετε και να το χρησιμοποιήσετε στο Excel