Sie sind auf Seite 1von 31

Tut ori al

3
EDVINNOVATION&CONSULTING
StefanKulpa
GerhardDomagkStr.6
D41540Dormagen
http://www.kulpaonline.com
Email:stefan@kulpaonline.com

VBA
EINFHRUNG
LEVELADVANCED

Inhaltsverzeichnis

EFFEKTI VES ERROR CODI NG I MPLEMENTI EREN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4


ExplizitesCodieren........................................................................................................................ 4
BenutzeIMMEROptionExplicit ................................................................................................................4
BenutzeIMMERexpliziteVariablentypen.................................................................................................5
VermeideDeftypeStatements..................................................................................................................5
InitialisierenVariablen...............................................................................................................................6
NutzeTypeName,VarTypeundTypeOf ....................................................................................................7
Argumente .................................................................................................................................... 7
NutzeimmerByRefundByVal ..................................................................................................................7
NutzeexpliziteTypArgumente.................................................................................................................8
SetzteexplizitStandardwertefroptionaleArgumente...........................................................................8
ValidierealleArgumente...........................................................................................................................8
BenutzebenannteArgumente..................................................................................................................8
Arrays(Datenfelder) ..................................................................................................................... 9
UnterstelleniemalsuntereArrayGrenzen................................................................................................9
VermeidehartcodierteArrayGrenzen...................................................................................................10
VermeidedieOptionBaseAnweisung ....................................................................................................10
CODI EREMPFEHLUNGEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
ImplementiereimmereinenElseFall .....................................................................................................11
Vermeidees,Standardeigenschaftenzubenutzen.................................................................................12
VermeidevermischteDatentypeninAusdrcken...................................................................................12
BenutzeKonstanten................................................................................................................................13
VermeideOperatorenPrioritten...........................................................................................................13
PrfeStringLngen.................................................................................................................................13
SchlieealleoffenenObjekte..................................................................................................................14
SetzeObjekteaufNothing ......................................................................................................................14
SchalteFehlerhandlingsexplizit(wieder)aus .........................................................................................14
TreffeniemalsAnnahmenberdieexterneWelt................................................................................15
CodiereniemalsmitKopierenundEinfgen........................................................................................15
Benutze+und&korrekt .........................................................................................................................15
SetzeEigenschaftenzurLaufzeit .............................................................................................................15
ERROR CODI NG MECHANI SMEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
OnErrorResumeNext.............................................................................................................................16
OnErrorGoto..........................................................................................................................................16
Programmablaufwiederaufnehmen.......................................................................................................16
Resume....................................................................................................................................................17
ResumeNext ...........................................................................................................................................17
ResumeLine ............................................................................................................................................17
MehrereErrorHandles............................................................................................................................18
DasErrorObjekt ......................................................................................................................... 18
berprfenderFehlernummer...............................................................................................................19
BereinigendesErrorObjekts ..................................................................................................................20
AusschaltendesErrorHandlers ..............................................................................................................21
GltigkeitsbereichvonErrorHandlern ...................................................................................................21
FehlercodesimAufrufstapel ...................................................................................................................23

DEBUGGI NG I N VBA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
DebuggingerfolgtimCode ......................................................................................................... 24
DasDirektfenster ....................................................................................................................................25
DasLokalFenster ....................................................................................................................................26
Dasberwachungsfenster ......................................................................................................................27
WI SSENSWERTES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
GltigkeitsbereicheundLebensdauervonVariablen................................................................. 28
Gltigkeitsbereiche:DienacktenFakten.................................................................................................29
PassaufDeineTypenauf... .....................................................................................................................30
Datentypen(Zusammenfassung) ................................................................................................ 30

E F F E K T I V E S E R R O R C O D I N G I M P L E M E N T I E R E N
Kapi t el
1
StefanKulpa2006http://www.kulpaonline.com Seite4von31
EFFEKTIVESERROR
CODINGIMPLEMENTIEREN
inenVBACodeschreibenisteineSache.IhnzumLaufenzubringen,eineandere.Denn
hier beginnt die eigentliche Arbeit. Fehler aufzuspren und zu beseitigen ist ein wich
tiger Teil des Programmierens. Wie man das in VBA am besten macht, beschreibt die
sesTutorial.Wirgehenauerdemdaraufein,wiemanFehlerneineFallestelltunddemPro
grammdamitermglicht,unbeabsichtigteEreignisseelegantzuparieren.
E
WirmchtenIhnenvorabschoneinenTippmitaufdenWeggeben,dereventuellsehrwich
tig fr Ihre Gemtsverfassung sein kann: Regen Sie sich niemals, also das bedeutet an kei
nen Tag, zu keiner Stunde, wegen eines Programmierfehlers auf! Ein guter Programmierer
ist auch ein guter Fehlersucher, der Fehlermeldungen nur als dankbaren Hinweis der Umge
bungbetrachtet,wieereventuelldenFehlerschnellerfindenkann.
Jeder, der eigene Programme schreibt, wird mit Fehlermeldungen konfrontiert. Sie gehren
genauso zur tglichen Arbeit, wie das stndige Klappern der Tastatur. Je mehr Sie sich aller
dings ber die Hinweise aufregen, desto genervter gehen Sie an die Lsung der Probleme
heranundverschlimmernnurnochalles.WiegingdasLindnochvonBobbyMcFerrin?Dont
worry,behappy!
ExplizitesCodieren
BenutzeIMMEROptionExplicit
DasfolgendeBeispiel
Sub Di spl ayName( )
sUser Name = " J . Br own"
MsgBox " My name i s " & sUsr Name
End Sub
wrdeohnegesetztesOptionExplicitproblemloskompiliertundausgefhrtwerden.
Sobald jedoch Option Explicit gesetzt wird, meldet der Compiler die unbekannte Variable
sUsrName.EinebessereVariantewredemnach:

E F F E K T I V E S E R R O R C O D I N G I M P L E M E N T I E R E N
StefanKulpa2006http://www.kulpaonline.com Seite5von31
Opt i on Expl i ci t
Sub Di spl ayName( )
Di msUser Name As St r i ng
sUser Name = " J . Br own"
MsgBox " My name i s " & sUser Name
End Sub
In Visual Basic und in Visual Basic For Application lsst sich das automatische Einfgen von
Option Explicit in jedes neue Modul einstellen (Extras Optionen Variablendeklaration
erforderlich).
BenutzeIMMERexpliziteVariablentypen
Visual Basic geht grundstzlich davon aus, dass eine Variable vom Typ Variant ist, solange
diesenichtexplizitmiteinemspeziellenDatentypdeklariertwird.
Di mi , j , k As Long
In diesem Beispiel werden mit i und j implizit zwei Variant Variablen und mit k explizit eine
LongintegerVariabledeklariertobwohldiessichernichtsobeabsichtigtwar.
BesserwrefolgendeVariante:
Di mi As Long, j As Long, k As Long
oder
Di mi As Long
Di mj As Long
Di mk As Long
Diese zweite Variante erlaubt es, hinter den Variablen deren Bestimmung zu beschreiben.
Dieserfolgtleidernurallzuselten,wasdieLesbarkeitdesCodesnichtgeradefrdert.
VermeideDeftypeStatements
VisualBasickenntfolgendeDefTypeBefehle
Def Bool , Def Byt e, Def I nt , Def Lng
Def Cur , Def Sng, Def Dbl , Def Dec
Def Dat e, Def St r , Def Obj , Def Var
Wenn man diese Befehle noch nicht kennt, sollte man es dabei belassen. Wer diese Befehle
jedochkenntundvielleichtaucheinsetzt,solltedieszuknftigvermeiden.
DeftypeBefehle werden modulglobal gesetzt und werden auf alle Variablen in einem be
stimmten Bereich angewendet, die nicht explizit mit einem Variablentypen deklariert wer
den.
E F F E K T I V E S E R R O R C O D I N G I M P L E M E N T I E R E N
StefanKulpa2006http://www.kulpaonline.com Seite6von31
Beispiel:
Opt i on Expl i ci t
Def I nt A- K
Sub Def TypeCheck( )
Di ma, l , mAs Long
Debug. Pr i nt Var Type( a) ' - > 2 = I nt eger
Debug. Pr i nt Var Type( l ) ' - > 0 = ni cht i ni t i al i si er t
Debug. Pr i nt Var Type( m) ' - > 3 = Long
End Sub
DieVariableaflltindenBereichDefIntAKundwirddaheralsIntegerdeklariert.
DieVariablelflltwederindenDefIntBereichnochwirdsieexplizitdeklariert;eshan
deltsichalsoumeinenVariant.
DieVariablemwurdeexplizitalsLongintegerdeklariert.
Bereits in diesem simplen Beispiel sieht man die potentiellen Gefahren im Umgang mit den
DefTypeDeklarationen. Daher sollte man diese Art der impliziten Variablendeklaration ganz
ausdemCodeverbannen.
Grundstzlich gilt: Nutze Variant und ObjekttypVariablen grundstzlich nur in speziellen
Situationen,woessichnichtvermeidenlsst.
InitialisierenVariablen
MansollteniedieimpliziteInitialisierungvonVariablenvoraussetzen.NumerischeVariablen
werden durch die Deklaration normalerweise mit 0 und StringVariablen mit einem Leer
string initialisiert. Aber bleibt dies so auch in spteren Versionen bestehen? Wie wird eine
VariantoderObjektVariableinitialisiert?
Was passiert, wenn VB Code nach VBScript oder eine andere Sprache portiert wird? Erfolgt
dortauchdiese implizite Initialisierung? EsgibtnocheineReiheandererFragen, sodassdie
einzig korrekte Antwort das explizite Initialisieren von Variablen ist. Dies ist nicht nur direkt
nachderDeklarationnotwendig,sondernauchvorderenNutzung.
For i = LBound( MyAr r ay) To UBound( MyAr r ay)
s = s & MyAr r ay( i )
Next
Wiekannmansichersein,dassindieVariableszuBeginnderSchleifeleerist?Vorallemin
groen Codemodulen kann es schon mal passieren, dass eine Variable mehrfach benutzt
wird.EinesimpleInitialisierungschaffthierAbhilfe:
s = " "
For i = LBound( MyAr r ay) To UBound( MyAr r ay)
s = s & MyAr r ay( i )
Next
Hinweis:ObjektvariablesolltendirektnachihrerDeklarationmitNothinginitialisiertwerden.
Di mobj MyObj ect As Obj ect
Set obj MyObj ect = Not hi ng
E F F E K T I V E S E R R O R C O D I N G I M P L E M E N T I E R E N
StefanKulpa2006http://www.kulpaonline.com Seite7von31
NutzeTypeName,VarTypeundTypeOf
DiesedreiVisualBasicFunktionensindbeinativenVariantenundObjektvariablensehrntz
lich:
Sub ShowUser s( User As Obj ect )
I f TypeName( User ) = " User Obj ect " Then
MsgBox " The User Name i s: " & User . Name
End I f
End Sub

Sub ShowUser s( User Name As Var i ant )
I f Var Type( User Name) = vbSt r i ng Then
MsgBox " The User Name i s: " & User Name
End I f
End Sub

Sub ShowUser s( User As Obj ect )
I f TypeOf User I s User Obj ect Then
MsgBox " The User Name i s: " & User . Name
End I f
End Sub
Argumente
NutzeimmerByRefundByVal
Argumente(Parameter)werdeninVisualBasicimplizitByRefalsReferenzbergeben.
Die so bergebenen Argumente knnen durch die aufgerufene Routine verndert werden. Dies
kanngewolltsein,oderauchnicht.
Werden Argumente explizit ByVal bergeben, so bleibt die ursprngliche Variable unverndert
undeswirdeineKopieandieaufgerufeneRoutinebergeben.

Sub Ar gument s( )
Di msMyVal ue As St r i ng

sMyVal ue = " Hel l o Wor l d! "
Debug. Pr i nt sMyVal ue ' - > Hel l o Wor l d!

Cal l ByRef Sampl e( sMyVal ue)
Debug. Pr i nt sMyVal ue ' - > Resul t f r omByRef Sampl e

Cal l ByVal Sampl e( sMyVal ue)
Debug. Pr i nt sMyVal ue ' - > Resul t f r omByRef Sampl e
End Sub

Sub ByRef Sampl e( ByRef sMyVal ue As St r i ng)
sMyVal ue = " Resul t f r omByRef Sampl e"
End Sub

Sub ByVal Sampl e( ByVal sMyVal ue As St r i ng)
sMyVal ue = " Resul t f r omByVal Sampl e"
End Sub
GrundstzlichsolltemanByRefArgumentevermeidenundArgumenteexplizitByValberge
ben,sofernkeinetriftigenGrndedagegensprechen.
E F F E K T I V E S E R R O R C O D I N G I M P L E M E N T I E R E N
StefanKulpa2006http://www.kulpaonline.com Seite8von31
NutzeexpliziteTypArgumente
AuchbeiArgumentensolltenexpliziteDatentypengenanntwerden.
Sub ShowUser s( ByVal User Count )
In diesem Beispiel knnte es sich bei UserCount um einen Varianten handeln, da dies stan
dardmig der Fall ist. Es knnte aber auch aufgrund einer DefTypeAnweisung ein ganz an
derer Datentyp sein. Deutlich stabiler wird diese Routine durch explizite TypDefinition des
ArgumentsUserCount;z.B.:
Sub ShowUser s( ByVal User Count As Var i ant )
SetzteexplizitStandardwertefroptionaleArgumente
Optionale Argumente ohne Standardwerte knnen bzw. sollten vor ihrer Verwendung ge
prftwerden:
Sub ShowUser Name( Opt i onal ByVal User Count As Var i ant )
I f I sMi ssi ng( User Count ) Then User Count = 0
End Sub
Durch die Vergabe eines Standardwerts ist zum einen die berprfung mit IsMissing nicht
notwendigzumanderenwirdzumindestimFalleeinesVariantendessenTypklar(er).
Sub ShowUser Name( Opt i onal ByVal User Count As Var i ant = 0)
In diesem Beispiel wird klar, dass es sich um ein numerisches Argument mit dem Standard
wert0handelt.
ValidierealleArgumente
JedeRoutinesolltedieVerantwortungfrdieValidierungihrerArgumentehaben:
Argumentesindoptionalodernicht
GltigeArgumentebesitzendenkorrektenDatentypen
NumerischeArgumenteliegenimerwartetenWertebereichetc.
Grundstzlich sollten keine Annahmen ber die Gltigkeit von Argumenten getroffen wer
den!
Eine Routine kann/sollte nicht wieder verwendet werden, wenn es nicht seine Argumente
berprft!
BenutzebenannteArgumente
Code wird deutlich lesbarer, wenn Argumente beim Aufruf einer Routine benannt werden.
Zudem vereinfacht dies die Handhabung von Routinen mit vielen optionalen Argumenten
drastisch; gleichermaen verringert sich die Fehleranflligkeit durch falsch benutzte Argu
mente.
E F F E K T I V E S E R R O R C O D I N G I M P L E M E N T I E R E N
StefanKulpa2006http://www.kulpaonline.com Seite9von31
DieCodezeile
I f bGet User I nf o( sUser Name, Fal se) Then
wirddurchNennungderArgumentedeutlichlesbarer
I f bGet User I nf o( sUser Acount Name: =sUser Name, _
bShowPasswor t Di al og: =Fal se) Then
Arrays(Datenfelder)
DatenfeldOperationensindeinweiteresSpektrum,FehlerndurchimplizitesVerhaltendie
Tren zu ffnen. Nachfolgende werden einige implizite Verhaltensweisen dargestellt, die
vermiedenwerdensollten.
UnterstelleniemalsuntereArrayGrenzen
AufgrundderStandardgrenzefrdieuntereArrayGrenze(=0)luftmanGefahr,dieseunte
re Grenze grundstzlich als gesetzt anzunehmen. Bereits eine globale Abweichung dieser
GrenzedurcheineOptionBaseAnweisungfhrthierbereitszupotentiellenFehlern.
DahersolltemangrundstzlichdieuntereGrenzeexplizitsetzen,woraufdannaucheineOp
tionBase AnweisungkeinenEinflussmehrnimmt.
Opt i on Expl i ci t


Sub Count Down( )

Di mi As I nt eger
Di msNums( 10) As St r i ng

sNums( 10) = " Zehn"
sNums( 9) = " Neun"
sNums( 8) = " Acht "
sNums( 7) = " Si eben"
sNums( 6) = " Sechs"
sNums( 5) = " Fnf "
sNums( 4) = " Vi er "
sNums( 3) = " Dr ei "
sNums( 2) = " Zwei "
sNums( 1) = " Ei ns"
sNums( 0) = " Nul l "

' / / Count down von 10 bi s 0
For i = UBound( sNums) To _
LBound( sNums) St ep - 1
Debug. Pr i nt sNums( i )
Next

End Sub
Opt i on Expl i ci t
Opt i on Base 1

Sub Count Down( )

Di mi As I nt eger
Di msNums( 10) As St r i ng

sNums( 10) = " Zehn"
sNums( 9) = " Neun"
sNums( 8) = " Acht "
sNums( 7) = " Si eben"
sNums( 6) = " Sechs"
sNums( 5) = " Fnf "
sNums( 4) = " Vi er "
sNums( 3) = " Dr ei "
sNums( 2) = " Zwei "
sNums( 1) = " Ei ns"
sNums( 0) = " Nul l "

' / / Count down von 10 bi s 0
For i = UBound( sNums) To _
LBound( sNums) St ep - 1
Debug. Pr i nt sNums( i )
Next

End Sub
Dieses Beispiel funktioniert, da implizit die un
tereArrayGrenzeauf0gesetztwird.
Dieses Beispiel fhrt zu einem Fehler, da die
Anweisung Option Base 1 alle unteren Array
grenzen grundstzlich auf 1 stellt, sofern diese
nichtexplizitgesetztwerden.
E F F E K T I V E S E R R O R C O D I N G I M P L E M E N T I E R E N
StefanKulpa2006http://www.kulpaonline.com Seite10von31
AusdiesemGrundsolltenuntereArraygrenzengrundstzlichdeklariertwerden:
Di msNums( 0 To 10) As St r i ng
VermeidehartcodierteArrayGrenzen
HartcodierteArrayGrenzenerschwerendiePflegedesCodes.WennsichspterdieGrenzen
ndern, mssen alle Stellen, an denen auf die ArrayGrenzen zugegriffen werden, gesucht
undberarbeitetwerden.
WerdenstattdessenKonstantengenutzt,mssenlediglichdieKonstantengendertwerden.
Opt i on Expl i ci t

Sub Count Down( )

Di mi As I nt eger
Di msNums( 0 To 10) As St r i ng

sNums( 10) = " Zehn"
sNums( 9) = " Nen"
sNums( 8) = " Acht "
sNums( 7) = " Si eben"
sNums( 6) = " Sechs"
sNums( 5) = " Fnf "
sNums( 4) = " Vi er "
sNums( 3) = " Dr ei "
sNums( 2) = " Zwei "
sNums( 1) = " Ei ns"
sNums( 0) = " Nul l "

' / / Count down von 10 bi s 0
For i = 10 To 0 St ep - 1
Debug. Pr i nt sNums( i )
Next

End Sub




Opt i on Expl i ci t

Sub Count Down( )

Const COUNT_MI N As I nt eger = 0
Const COUNT_MAX As I nt eger = 10

Di mi As I nt eger
Di msNums( COUNT_MI N To _
COUNT_MAX) As St r i ng

sNums( 10) = " Zehn"
sNums( 9) = " Neun"
sNums( 8) = " Acht "
sNums( 7) = " Si eben"
sNums( 6) = " Sechs"
sNums( 5) = " Fnf "
sNums( 4) = " Vi er "
sNums( 3) = " Dr ei "
sNums( 2) = " Zwei "
sNums( 1) = " Ei ns"
sNums( 0) = " Nul l "

' / / Count down von 10 bi s 0
For i = COUNT_MAX To COUNT_MI N St ep - 1
Debug. Pr i nt sNums( i )
Next

End Sub
VermeidedieOptionBaseAnweisung
Wie bereits zuvor geschildert, fhrt die Option Base Anweisung zu potentiellen Fehlersitua
tionen.
Da die explizite Deklaration der ArrayGrenzen zu bevorzugen ist, sollte auch auf die Option
BaseAnweisunggrundstzlichverzichtetwerden,dadiesebeiexpliziterGrenzenbestimmung
keine Wirkung mehr hat.
C O D I E R E M P F E H L U N G E N
K
StefanKulpa2006http://www.kulpaonline.com Seite11von31
CODIEREMPFEHLUNGEN
api t el
2
ie nachfolgenden Kapitel beinhalten Empfehlungen fr ein explizites Codieren, um
denCodezuverbessernundpotentielleFehlerquellenauszuschalten.
ImplementiereimmereinenElseFall
D
In jedem IfThen und Select Case Block sollte immer ein Else Zweig implementiert werden,
auchwennmansichsicherist,daskeinandererFalleintretenkann.SptestensbeiErweite
rungendesCodessinddieseBlckehilfreich,umGrenzflleabzufangen:
Beispiel:
Sub Handl eMenu( mnuChoi ce As I nt eger )

Sel ect Case mnuChoi ce
Case MNU_OPEN
OpenFi l e
Case MNU_CLOSE
Cl oseFi l e
Case MNU_SAVE
SaveFi l e
Case El se
MsgBox " Unbekannt er Menbef ehl ! "
End Sel ect

End Sub
bzw.
Sub Handl eMenu( mnuChoi ce As I nt eger )

I f mnuChoi ce = MNU_OPEN Then
OpenFi l e
El seI f mnuChoi ce = MNU_CLOSE Then
Cl oseFi l e
El seI f mnuChoi ce = MNU_SAVE Then
SaveFi l e
El se
MsgBox " Unbekannt er Menbef ehl ! "
End I f

End Sub
Wird fr diese Routinen das zugrunde liegende Men erweitert, ist schnell klar, an welcher
Stelle die Codeblcke nachbearbeitet werden mssen. Ohne diese ElseZweige wrde gar
nichts passieren und es wre nicht unbedingt immer direkt offensichtlich, an welcher Stelle
nachzubessernist.
C O D I E R E M P F E H L U N G E N
StefanKulpa2006http://www.kulpaonline.com Seite12von31
Vermeidees,Standardeigenschaftenzubenutzen
Sehr oft werden Standardeigenschaften von Objekten genutzt, ohne diese explizit zu
(be)nennen.
DerCodewirdfrmanchedadurchschlankerundlesbarer.DiebeidennachfolgendenZei
lenzeigendiegleicheInformation:
MsgBox Er r . Number
MsgBox Er r
DerCodefunktioniert,daNumberdieStandardeigenschaftdesErrObjektsist.
StandardeigenschaftenknnensichinNachfolgeversionenndern.ZudemistdasWeglassen
dieser (Standard)Eigenschaften nicht wirklich der Lesbarkeit dienlich. Darber hinaus ist es
auch nicht immer direkt ersichtlich, ob man ein Objekt referenziert und lediglich dessen
Standardwertabfragt.
Ein weiterer technischer Grund fr die explizite Nutzung/Nennung der Standardeigenschaf
ten, sind bekannte Speicherprobleme mit manchen COMObjekten bei der impliziten Nut
zungderStandardeigenschaften.
DerwohlammeistenimplizitgenutzteEigenschaftswertistderFieldValuebeiRecordsets.
VieleProgrammierernutzendieseEigenschaftungefhrwiefolgt:
r s( " Fi el dName" )
Hier liegt sogar ein doppelter impliziter Standard vor. Die vollstndige und empfohlene
Referenzsolltewiefolgtaussehen:
r s. Fi el ds( " Fi el dName" ) . Val ue
VermeidevermischteDatentypeninAusdrcken
VisualBasicerlaubtvermischteAusdrckewiez.b.:
Cur Dat e = Now + 1
DerartigeKonstruktesolltenvermiedenwerden,dasievoraussetzen,dass
derProgrammiererdieseVB/AspezifischenimplizitenAusdrckekennt
diePortierbarkeitdesCodeserschwertwird
esnichtgewhrleistetwird,dassimpliziteUntersttzungimmergltigist
Esistdaherbesser,Funktionenzunutzen,diefrdenjeweiligenFallausgelegtsind;z.B.:
Cur Dat e = Dat eAdd( " d" , 1, Now)
C O D I E R E M P F E H L U N G E N
StefanKulpa2006http://www.kulpaonline.com Seite13von31
BenutzeKonstanten
Nutze niemals hartcodierte Elemente wie z.b. Array Grenzen, Control Indizes (nur VB) o
derSpalten/ZeilenpositioneninMatrixObjekten(Gridsetc.).
WennsichderenWertendern,kannesu.U.uerstschwierigsein,allebetroffenenStellen
zukorrigieren.
Har d- codi er t e El ement e Nut zung von Konst ant en
Di mnums( 0 To 10)
gr i d. Col ( 4) . Text = " 12345"
t xt I nput ( 4) . Text = " 12345"
Di mnums( NUMS_LOWER To NUMS_UPPER)
gr i d. Col ( GRI D_ZI P) . Text = " 12345"
t xt I nput ( TEXT_SSN) . Text = " 12345"
VermeideOperatorenPrioritten
Grundstzlich sollte man nicht davon ausgehen, dass mathematische Regeln wie Punkt vor
Strichkorrektumgesetztwerden.AusdiesemGrundsolltemanimmermitentsprechenden
Klammernarbeiten:
st at t Dbl Resul t = dbl Base + dbl Cost * dbl Uni t s
besser Dbl Resul t = dbl Base + ( dbl Cost * dbl Uni t s)
oder
st at t Dbl Resul t = dbl Base + dbl Cost * dbl Uni t s + 4. 6 / dbl Adj
besser Dbl Resul t = dbl Base + ( dbl Cost * dbl Uni t s) + ( 4. 6 / dbl Adj )
PrfeStringLngen
Je nach VB/VBA Version werden ungltige StringLngen mal als Fehler und mal nicht als
Fehlerbehandelt.
Funct i on Get Zi pOnl y( st r Zi p As St r i ng) As St r i ng
Const ZI P_BASELENGTH = 5
Get Zi pOnl y = Lef t $( st r Zi p, ZI P_BASELENGTH)
End Funct i on
Was passiert, wenn der Wert des Arguments strZip kleiner als 5 Zeichen lang ist? Je nach
VB/AVersion wird ein Laufzeitfehler erzeugt oder aber auch nicht. Darauf sollte man sich
nichtverlassen,undgrundstzlichStringLngenprfen;z.B.:
Funct i on Get Zi pOnl y( st r Zi p As St r i ng) As St r i ng
Const ZI P_BASELENGTH = 5
I f Len( st r Zi p) < ZI P_BASELENGTH + 1 Then
Get Zi pOnl y = st r Zi p
El se
Get Zi pOnl y = Lef t $( st r Zi p, ZI P_BASELENGTH)
End I f
End Funct i on
C O D I E R E M P F E H L U N G E N
StefanKulpa2006http://www.kulpaonline.com Seite14von31
SchlieealleoffenenObjekte
Grundstzlich sollten alle Objekte nach deren Nutzung explizit geschlossen werden. Auch
wennVB/AvermeintlichObjekteautomatischschliet,wenneineRoutineverlassenwird,so
sollte man sich nicht darauf verlassen. Zudem kann das NichtSchlieen von Objekten bei
spteren Erweiterungen des Codes zu Fehlern fhren, wenn dieser Umstand nicht berck
sichtigtwird.
Set r s = OpenRecor dset ( db, sql )
sName = r s. Fi el ds( " Name" ) . Val ue
r s. Cl ose
DasexpliziteSchlieenvonObjektesolltejeweilsdurchgefhrtwerden;diesgiltauchfrDa
teioperationen, bei denen die betroffenen Dateien stets nach deren Nutzung geschlossen
werden!
SetzeObjekteaufNothing
Alle Objekte, die nicht mehr genutzt werden, sollten explizit auf Nothing gesetzt werden.
DieserPunktwirdsehroftdiskutiertundeshltsichhartnckigdasArgument,dassObjekte
automatisch auf Nothing gesetzt werden, wenn sie sich nicht mehr im aktuellen Gltig
keitsbereichbefinden.
Das mag zum Teil stimmen, aber was spricht dagegen, auch diese Annahme durch explizites
ZerstrenvonObjektenzurGewissheitwerdenzulassen?
SchalteFehlerhandlingsexplizit(wieder)aus
Eine On Error Anweisung schaltet VB/A explizit in einen FehlerHandlingModus. Daher
sollte grundstzlichnachjedemlogischenBlock dasErrorHandlingauchwiederexplizit aus
geschaltetwerden.
Di mr s As Recor dset
Di msName As St r i ng

On Er r or Resume Next
Set r s = OpenRecor dset ( db, sql )
I f Er r . Number <> 0 Then Exi t Sub
sName = r s. Fi el ds( " Name" ) . Val ue
r s. Cl ose
In diesem Beispiel wird zwar ein FehlerHandling aktiviert aber nicht wieder ausgeschaltet.
Esistbesser,dasErrorHandlingentsprechendzubeenden:
Di mr s As Recor dset
Di msName As St r i ng
Di mi nt Er r or As I nt eger
On Er r or Resume Next
Set r s = OpenRecor dset ( db, sql )
i nt Er r or = Er r . Number
On Er r or GoTo 0
I f i nt Er r or <> 0 Then Exi t Sub
sName = r s. Fi el ds( " Name" ) . Val ue
r s. Cl ose
C O D I E R E M P F E H L U N G E N
StefanKulpa2006http://www.kulpaonline.com Seite15von31
TreffeniemalsAnnahmenberdieexterneWelt
Man sollte grundstzlich keine Annahmen ber die Welt auerhalb des eigenen Pro
gramms treffen, die man nicht beeinflussen kann. Beim Lesen von Dateien oder Datenban
kenundwhrend derKommunikationmitSchnittstellenkannmanniedenjeweiligenStatus
voraussetzen.Dateienknnenschreibgeschtzt,DatenbankenexklusivgeffnetundSchnitt
stellenaktuellnichtverfgbarsein.
Es liegt jeweils in der Verantwortung des zugreifenden Programms mit mglichen Fehlern
beimZugriffintelligentumzugehenundniemalsdengewnschtenStatusvorauszusetzen.
CodiereniemalsmitKopierenundEinfgen
EinedergrtenProgrammkrankheitenhatihrenUrsprungimKopierenundEinfgenvon
CodeteilenausanderenProgrammen.Hierbeiwerdennichtnurbestehendebzw.potentielle
Fehlerquellen gleich mit kopiert, sondern der nderungsaufwand wird oft unterschtzt, so
dassinvielenFllendieErstellungeinesneuen,robustenCodeseffektiverist.
Benutze+und&korrekt
Obwohl VB/A das PlusZeichen zum Konkatenieren (Verknpfen) von Strings untersttzt,
sollte hierzu grundstzlich das kaufmnnische UND benutzt werden. Das PlusZeichen sollte
ausschlielichfrmathematischeOperationenverwendetwerden.
SetzeEigenschaftenzurLaufzeit
DasSetzenvonControlEigenschaftenzurDesignZeiterscheintschnellundbequemvonstat
tenzugehen.Dies sollte mantrotzdemvermeidenundalleEigenschaftenzurLaufzeitexpli
zitberdieControl/Objekteigenschaftensetzen.DiesmachtdenCodelesbarerundwartba
rer; zudem knnen beispielsweise ControlUpdates nicht mehr strend auf diese Eigen
schaften einwirken.
E R R O R C O D I N G M E C H A N I S M E N
K
StefanKulpa2006http://www.kulpaonline.com Seite16von31
ERRORCODING
MECHANISMEN
api t el
3
mdieinterneFehlerbehandlungzuaktivieren,musseinederbeidenOnErrorAnwei
sungengenutztwerden;OnErrorResumeNextoderOnErrorGoto.
OnErrorResumeNext
U
DieAnweisungOnErrorResumeNextistdieersteAnweisungzumSchutzvorFehlern.Dabei
wirdVB/Averanlasst,beieinemFehlerinderZeiledenCodefortzufhren,dienachderZeile
kommt,diedenFehler verursachthat.Belsst man es beidieserAnweisung, handeltes sich
nichtumFehlerbehandlung,sondernumFehlerunterdrckung.Fehlerunterdrckungistsehr
gefhrlich.EsverstecktFehlervordemProgrammierer,demTesterundletztendlichdemBe
nutzer.
EsgibtnursehrwenigeSituationen,indenendieseFehlerunterdrckunglegitimist.
OnErrorGoto
DieAnweisungOnErrorGotoistdiezweiteAnweisungzumSchutzvorFehlern.DieseAnwei
sung veranlasst VB/A bei einem Fehler zu einer bestimmten Marke in der Routine zu sprin
gen,indersicheineFehlerbehandlungbefindet.
Fehl er unt er dr ckung Fehl er behandl ung
Di mi As I nt eger
On Er r or Resume Next
i = 8 / 0




Di mi As I nt eger
On Er r or GoTo Er r Tr ap
i = 8 / 0
Exi t Sub

Er r Tr ap:
MsgBox " Es i st ei n Fehl er auf get r et en. "
Programmablaufwiederaufnehmen
Sobald der interne ErrorHandler aktiviert wurde, muss das Programm zum normalen Ab
lauf zurckkehren. Hierfr stellt VB/A die Anweisung Resume (Wiederaufnehmen) zur Ver
fgung.
ManunterscheidetdreiVarianten:
E R R O R C O D I N G M E C H A N I S M E N
StefanKulpa2006http://www.kulpaonline.com Seite17von31
Resume
Die Anweisung Resume entspricht einer RetryAnweisung, also die Wiederholung der Co
dezeile,diedenFehlerverursachthat.DasmachtnurdannSinn,wenninderFehlerbehand
lungdieVoraussetzungenerflltwurden,umdasProgrammabderentsprechendenCodezei
lejetztohneFehlerfortfhrenzuknnen;z.B.:
Sub Di vi deByZer o( )
Di mi As I nt eger
Di mi nt DenomAs I nt eger
On Er r or GoTo Er r Handl er
i nt Denom= 0
i = 8 / i nt Denom
Exi t Sub
Er r Handl er :
i nt Denom= I nput Box( " Bi t t e gl t i gen Di vi sor ei ngeben ( >0) " )
Resume ' Ret r y
End Sub
ResumeNext
DieResumeNextAnweisungisthnlichderResumeAnweisung,wobeihiernuninderCode
zeiledasProgrammfortgefhrtwird,diederFehlerverursachendenCodezeilefolgt;z.B.:
Sub Di vi deByZer o( )
Di mi As I nt eger
Di mi nt DenomAs I nt eger
On Er r or GoTo Er r Handl er
i nt Denom= 0
i = 8 / i nt Denom
Exi t Sub
Er r Handl er :
MsgBox " Di vi si on wur de abgebr ochen! "
Resume Next
End Sub
oder
Sub Di vi deByZer o( )
Di mi As I nt eger
Di mi nt DenomAs I nt eger
On Er r or Resume Next
i nt Denom= 0
i = 8 / i nt Denom
I f Er r . Number <> 0 Then
MsgBox " Di vi si on wur de abgebr ochen! "
End I f
End Sub
ResumeLine
DiedritteVersionderResumeAnweisungverweistmitLineaufeingltigesProgrammLabel
odereinegltigeZeilennummer;z.B.:
E R R O R C O D I N G M E C H A N I S M E N
StefanKulpa2006http://www.kulpaonline.com Seite18von31
Sub Di vi deByZer o( )
Di mi As I nt eger
Di mi nt DenomAs I nt eger
On Er r or GoTo Er r Handl er
i nt Denom= 0
i = 8 / i nt Denom
Exi t Sub
Al t Cal c:
i = ERR_VALUE
Exi t Sub
Er r Handl er :
MsgBox " Di vi si on wur de abgebr ochen! "
Resume Al t Cal c
End Sub
Bei der Nutzung der Resume Line Anweisung sollte man sehr vorsichtig sein. Wenn
die Resume-Anweisung aufgerufen wird, ohne das ein Error-Handler aktiv ist, fhrt
dies wiederum zu dem Fehler 20 (Resume ohne Fehler!).
MehrereErrorHandles
Ineiner ProzedurkannjeweilsimmernureinErrorHandler aktiviert werden.Zudemgiltein
ErrorHandler immer nur in einer Prozedur. Demzufolge gibt es keinen globalen Error
Handler, der ber mehrere Prozeduren wacht. Um also jede Prozedur in einem Programm
vor Fehlern zu schtzen, muss in jeder Prozedur ein eigener ErrorHandler implementiert
werden.
DasnachfolgendeBeispielbesitztsog.ZeilennummerneinRelikt,dassseitdererstenBasic
VersionexistiertundbiszuraktuellstenVB/VBAVersionbeibehaltenwurde.
Sub Di vi deByZer o( )

1 On Er r or Resume Next
2 i = 8 / 0 ' Di ese Zei l e wi r d ni cht bewer t et !
3 Di vi deByZer oAgai n

7 End Sub

Sub Di vi deByZer oAgai n( )

4 On Er r or Resume Next
5 i = 8 / 0 ' Di ese Zei l e wi r d ni cht bewer t et !

6 End Sub
InbeidenProzedurenwerdenFehlerjeweilsdurchdieErrorHandlerabgefangen.DiesesBei
spielsolllediglichaufzeigen,inGltigkeitderErrorHandlerdarstellen.
DasErrorObjekt
Grundstzlich besitzt jede VB/VBARoutine automatisch eine Referenz auf das sog. Error
Objekt.DurchdieNutzungeinerOnErrorAnweisungwirdinderjeweiligenRoutinederEr
rorHandleraktiviert,welcherwiederumdasErrorObjektbenutzt,umnhereInformationen
zudemaufgetretenenFehlerzudokumentieren.
DasErrorObjektbesitztfolgendeEigenschaften
E R R O R C O D I N G M E C H A N I S M E N
StefanKulpa2006http://www.kulpaonline.com Seite19von31
Err
dasErrorObjektselbst
. Number
Gibt einen numerischen Wert zurck oder legt einen numerischen
Wert fest, der einen Fehler angibt. Number ist die Standardeigen
schaftdesErrObjekts.
. Descr i pt i on
Die Einstellung fr die DescriptionEigenschaft enthlt eine kurze Be
schreibungdesFehlers.MitdieserEigenschaftkannmanfrBenutzer
eine Warnmeldung zu einem Fehler ausgeben, den man nicht verar
beitenkannoderwill.
. Last Dl l Er r or
Enthlt unter Betriebssystemen vom Typ 32Bit Microsoft Windows
nurdenSystemfehlerCodefrdenletztenAufrufeinerDynamicLink
Library(DLL).
. Sour ce
Die SourceEigenschaft gibt einen Zeichenfolgenausdruck an, der das
Objekt darstellt, das den Fehler ursprnglich ausgelst hat. Der Aus
druck ist normalerweise der Name der Klasse des Objekts oder die
RessourceID.
. Hel pFi l e
Wenn eine Microsoft WindowsHilfedatei in HelpFile angegeben ist,
wirdsieautomatischaufgerufen,wennderBenutzerimDialogfeldmit
der Fehlermeldung die Schaltflche Hilfe whlt (oder die F1Taste
drckt).
. Hel pCont ext
DieHelpContextEigenschaftwirdverwendet,umautomatischdasHil
fethemaanzuzeigen,dasinderHelpFileEigenschaftangegebenist.
. Rai se
RaisewirdzumErzeugenvonLaufzeitfehlernverwendetundkannan
stellederErrorAnweisungverwendetwerden.Raiseisthilfreichbeim
Erzeugen von Fehlern, wenn man Klassenmodule schreiben, da das
ErrObjekt mehr Informationen zur Verfgung stellt als die Error
Anweisung.MitderRaiseMethodekannzumBeispielderursprngli
che Auslser des Fehlers in der SourceEigenschaft angegeben wer
den,odermankannaufdieHilfefrdenFehlerverweisenusw.
. Cl ear
Mit Clear lscht man das ErrObjekt explizit, nachdem ein Fehler ver
arbeitetwurde.DiesistzumBeispielerforderlich,wennmanOnError
ResumeNextverwendetunddieFehlererstspterverarbeitet.
Die ClearMethode wird automatisch aufgerufen, sobald eine der fol
gendenAnweisungenausgefhrtwird:
AlleArtenvonResumeAnweisungen
ExitSub,ExitFunction,ExitProperty
JedeOnErrorAnweisung
berprfenderFehlernummer
Bei der berprfung von Fehlernummern sollte in jedem Fall vermieden werden, logische
Funktionenanzuwenden.
FolgendesBeispielfunktioniert:
E R R O R C O D I N G M E C H A N I S M E N
StefanKulpa2006http://www.kulpaonline.com Seite20von31
Sub Di vi deByZer o( )

Di mi As I nt eger
On Er r or Resume Next
i = 8 / 0
I f Er r . Number Then
MsgBox " Es t r at ei n Fehl er auf : " & Er r . Descr i pt i on
End I f

End Sub
Demzufolgesolltemanannehmen,dassfolgendesBeispielebenfallsfunktioniert:
Sub Di vi deByZer o( )

Di mi As I nt eger
On Er r or Resume Next
i = 8 / 0
I f Not Er r . Number Then
MsgBox " Es t r at kei n Fehl er auf ! "
End I f

End Sub
IndiesemzweitenBeispielwirddieMeldung"EstratkeinFehlerauf!"auchdannangezeigt,
wenneszueinemFehlerkommt.
FrdieNot Funktion der If-Anweisung ist nur 0=False und 1=True.
Das heit, dass in einer IfAnweisung eine 0 stets als False und ein Wert ungleich 0 stets als
Truegewertetwerden.
Der Wert Err.Number in dem Beispiel besitzt den Wert 11 (Division durch Null); dieser
Wertistungleich0undfhrtdemnachinderIfNotAnweisungzuTrue!!!
Fazit: Man sollte grundstzlich auf den Wert (bzw. auf 0) prfen und nicht mit logischen
FunktionendieFehlersituationberprfen!
BereinigendesErrorObjekts
Wenn ein Fehler auftritt, behlt das Fehlerobjekt solange die Fehlerdaten, bis das Fehlerob
jektbereinigtwird.
Sub Di vi deByZer o( )

Di mi As I nt eger
On Er r or Resume Next
i = 8 / 0
I f Er r . Number <> 0 Then
MsgBox " Es t r at ei n Fehl er auf ! "
End I f
i = 8 / 4
I f Er r . Number <> 0 Then
MsgBox " Es t r at ei n Fehl er auf ! "
End I f

End Sub
E R R O R C O D I N G M E C H A N I S M E N
StefanKulpa2006http://www.kulpaonline.com Seite21von31
In diesem Beispiel wird zweimal ein Fehlerhinweis angezeigt, obwohl nur die erste Division
zueinemFehlerfhrt!
Das Fehlerobjekt sollte demnach sofort nach dem FehlerHandling bereinigt werden; hierzu
stelltunddasError.ObjektdieClearMethodezurVerfgung:
Sub Di vi deByZer o( )

Di mi As I nt eger
On Er r or Resume Next
i = 8 / 0
I f Er r . Number <> 0 Then
MsgBox " Es t r at ei n Fehl er auf ! "
End I f
Er r . Cl ear
i = 8 / 4
I f Er r . Number <> 0 Then
MsgBox " Es t r at ei n Fehl er auf ! "
End I f
Er r . Cl ear

End Sub
DasErrorObjektwirdebenfallsnachjederResumeAnweisunginitialisiert.
AusschaltendesErrorHandlers
Ob man innerhalb einer Routine ein Fehlerhandling an und wieder ausschaltet, ist
eher eine philosophische Frage. Grundstzlich wird das Fehlerhandling durch die
Anweisung OnErrorGoto0 ausgeschaltet:
Sub Di vi deByZer o( )

Di mi As I nt eger
On Er r or Resume Next
i = 8 / 0 ' Fehl er wi r d unt er dr ckt
On Er r or GoTo 0
i = 8 / 0 ' Fehl er wi r d ni cht behandel t

End Sub
In jedem Fall sollte der ErrorHandler vor Beendigung der Routine explizit ausgeschaltet
werden.
GltigkeitsbereichvonErrorHandlern
EinErrorHandlerwirdbeimVerlasseneinerSubRoutine,einerFunctionodereinerProperty
deaktiviert. Die On Error Anweisung ist beim Rcksprung in die aufrufende Prozedur nicht
lngergltig.
E R R O R C O D I N G M E C H A N I S M E N
StefanKulpa2006http://www.kulpaonline.com Seite22von31
Sub Fi r st Sub( )
Di mi As I nt eger
SecondSub
i = 8 / 0 ' hi er kommt es zumbehandel t en Fehl er !
End Sub

Sub SecondSub( )
Di mi As I nt eger
On Er r or Resume Next
i = 8 / 0 ' di eser Fehl er wi r d unt er dr ckt
End Sub
InnachfolgendemBeispielwirdtrotzFehlerunterdrckungdieFehlernachrichtangezeigt:
Sub Fi r st Sub( )
Di mi As I nt eger
On Er r or Resume Next
SecondSub
i = 8 / 4
I f Er r . Number <> 0 Then MsgBox " Fehl er ! "
End Sub

Sub SecondSub( )
Di mi As I nt eger
On Er r or Resume Next
i = 8 / 0
End Sub
Grund fr diese Fehlermeldung ist ein nicht initialisiertes ErrorObjekt beim Verlassen der
RoutineSecondSub.DortwirdzwarderFehler11unterdrckt,aberderFehlerbleibtsolange
imFehlerobjekterhalten,bisdasObjektdurchErr.Clear(odereineentsprechendenResume
Anweisung)initialisiertwird.
DieAnweisungi=8/4inderRoutineFirstSubfhrtzwarnichtzueinemFehler,aberdasEr
rorObjekt besitzt noch die Fehlerinformationen aus der zuvor aufgerufenen SecondSub, so
dass Err.Number immer noch den Wert 11 besitzt und es somit zur Anzeige der Fehlermel
dungkommt!DiekorrekteImplementierungderErrorHandlersiehtwiefolgtaus:
Sub Fi r st Sub( )

Di mi As I nt eger
Di ml ngEr r or As Long

SecondSub

On Er r or Resume Next
i = 8 / 4
l ngEr r or = Er r . Number
On Er r or GoTo 0
I f l ngEr r or <> 0 Then MsgBox " Fehl er ! "

End Sub

Sub SecondSub( )

Di mi As I nt eger
On Er r or Resume Next
i = 8 / 0
On Er r or GoTo 0

End Sub
E R R O R C O D I N G M E C H A N I S M E N
StefanKulpa2006http://www.kulpaonline.com Seite23von31
FehlercodesimAufrufstapel
Es ist nicht unbedingt notwendig, in jeder Routine ein FehlerHandling zu implementieren,
um eine Fehlermeldung zu erhalten. VB/A sucht bei einem Fehler den Aufrufstapel solange
durch,biseseineFehlerbehandlungfindet:
Sub Mai nSub( )

1 On Er r or Resume Next
2 Fi r st Sub
5 I f Er r . Number <> 0 Then MsgBox " Fehl er ! "
6 On Er r or GoTo 0

End Sub

Sub Fi r st Sub( )

3 SecondSub
i = 8 / 4

End Sub

Sub SecondSub( )

4 i = 8 / 0 ' di eser Fehl er f hr t zumRckspr ung i n Mai nSub

End Sub
In diesem Beispiel kann man anhand der Zeilennummer verfolgen, wie das Programm ab
luft.
DainMainSubdieFehlerbehandlungunterdrcktwird,erfolgtnachZeile4einRcksprungin
MainSub und Anzeige der Fehlermeldung. Die Zeile i = 8 / 4 in der Routine FirstSub wird in
diesemZusammenhanggarnichtdurchgefhrt!
Bei allen Mglichkeiten zur Fehlerbehandlung ist es immer besser, Fehler zu vermeiden an
stelleFehlerabzufangenundanzuzeigen.
Die Mglichkeiten Fehler zu vermeiden sind sehr vielfltig und wrden den Rahmen dieses
Workshopssprengen.
Grundstzlich sollte man aus seinen Fehlern lernen und entsprechende Sicherheitsmecha
nismen einbauen, um einen einmal aufgetretenen Fehler mglichst nicht ein weiteres Mal
auftretenzulassen.
D E B U G G I N G I N V B A
K
StefanKulpa2006http://www.kulpaonline.com Seite24von31
DEBUGGINGINVBA
api t el
4
xku
dur
In der Fr
rs:EinBugisteinProgrammfehler.DerNameBug(engl.Kfer,Wanze)gehtaufdie
chInsektenverursachtenFehlerinRechenmaschinenzurck.
hzeit der Datenverarbeitung, als Computer noch mit Relais als Schaltelementen
funktionierten, strten manchmal Insekten die Datenverarbeitung. Sie krabbelten in die da
mals noch riesigen Computergehuse und wurden zwischen den Schaltern zerquetscht. Die
Bezeichnung Bug fr Programmfehler wurde auch bei den heutigen Computern, die auf in
tegriertenSchaltungenbasieren,beibehalten.GemeinhinwirddieBezeichnungBugderEnt
wicklerin Grace Hopper zugewiesen, die 1945 tatschlich einen Kfer in einem Relais ent
deckthabensoll.DieMotte,dieschuldwaraneinemDefekt,istheuteimMarinemuseumin
Dahlgren,Virginia/USAausgestellt.JedochwurdederAusdruckBugbereitsim19Jh.zurBe
zeichnungvonmechanischenDefektenverwendet.(So1878schriftlichbelegtineinemBrief
vonThomasAlvaEdison).
E
SelbstdasbesteFehlerhandlingreichtnichtimmeraus,dieUrsachenfrFehlerherauszufin
den.
Um nun solche Bugs (=Fehler) analysieren zu knnen, stellt uns VB bzw. VBA verschiedene
sog. Debugging Mechanismen und Tools zur Verfgung. Leider wird davon heutzutage viel
zu wenig bis gar nicht Gebrauch gemacht. Es gibt tatschlich VB/VBAProgrammierer, die
nichteinmaldieseWerkzeugekennen!
Die konsequente Nutzung von ErrorHandlern im Programmcode ist sicherlich wichtig und
notwendig, doch durch das Abfangen von Fehlern und der Anzeige von Fehlernachrichten
wird ein Programm auf lange Sicht nicht wirklich besser. Aus diesem Grund sollte man sich
mitjedemauftretendenFehlerintensivbeschftigen,umManahmenzuergreifen,dassdie
serFehlermglichstnichtmehrauftritt.
DebuggingerfolgtimCode
Obwohl ber optional einblendbare Symbolleisten DebuggerFunktionen auswhlbar sind,
werden nachfolgend die verfgbaren Tastenkombinationen aufgelistet die direkt oder indi
rektzumThemaDebuggingzurVerfgungstehen:
D E B U G G I N G I N V B A
StefanKulpa2006http://www.kulpaonline.com Seite25von31
Umdaszutun Mussdasgedrcktwerden
EineCodezeileausfhren(Einzelschritt) F8
Anweisungen zeilenweise ausfhren, ohne Prozeduren
aufzurufen(Prozedurschritt)
Umschalt+F8
AusfhrenbisCursorPosition Strg+F8
Haltepunkt in der CursorZeile ein und ausschalten
(Haltepunktein/aus)
F9
AlleHaltepunktelschen Strg+Umschalt+F9
NchsteAnweisungfestlegen Strg+F9
(AktuellenWertanzeigen) Umschalt+F9
DenFehlerbeseitigungscodeausfhrenoderdenFehler
andieaufrufendeProzedurzurckgeben
Alt+F5
In die Fehlerbehandlungroutine einsteigen oder den
FehlerandieaufrufendeProzedurzurckgeben
Alt+F8
Prozedurabschlieen Strg+Umschalt+F8
TypundGltigkeiteinerVariablenanzeigen Strg+I
Aufruf/AnzeigedesDirektfensters Strg+G
SprungvorVariablen/Funktionsdeklaration Umschalt+F2
RcksprungzurletztenPosition Strg+Umschalt+F2
(AnzeigederAufrufliste) Strg+L
WechselvomObjekt(Bsp.:UserForm)zumCodebereich F7
RcksprungvomCodebereichzumObjekt Umschalt+F7
AufrufdesObjektkatalogs F2
JenachVB/VBAVersionstehenggf.weitereTastenkombinationenzurVerfgung.
Der Schlssel zur Behebung von Programmfehlern ist der VB/VBA Haltemodus. Im Haltemo
dusluftdasProgrammimPrinzip,wirdaberaneinerbestimmtenAnweisungimCodeinder
Schwebegehalten.DadasProgrammaberdennochaktivist,kannmansichinallerRuhedie
aktuellenWerteallerVariablenansehen.
Praktischerweise kann man im Haltemodus den Code bearbeiten, notwendige nderungen
vornehmenoderspontanneueZeilenhinzufgen,unddasallesbeilaufendemProgramm.
DasDirektfenster
Mithilfe der Tastenkombination Strg + G wird das Direktfenster eingeblendet. In diesem Di
rektfenster knnen Codesegmente oder aber auch direkte mathematische Operationen aus
gefhrtwerden.
Die Debug.Print Anweisung im Code veranlasst VB/A dazu, den entsprechenden Wert im Di
rektfensteranzuzeigen.
D E B U G G I N G I N V B A
VariablenknnenimDirektfensterandereWertezugewiesenwerden.

Abbildung1DasDirektfenster
DasLokalFenster
WennmangengendPlatzzurVerfgunghat,solltemandasLokalFensterwhrenddesDe
bugging im Haltemodus immer auf dem Bildschirm haben (Ansicht LokalFenster). Das Lo
kalFenster zeigt automatisch alle in der laufenden Prozedur zugnglichen Variablen, ihren
Namen,WerteundDatentypenan.WeilderVBAEditordieseInformationennachjederAus
fhrungeinerAnweisungaktualisiert,bildetdasLokalFensterimmerdieaktuellenWerteab.

Abbildung2DasLokalFenster
AusschnittausdemLokalFensterwhrenddemDebuggingeinerAccessApplikation.
StefanKulpa2006http://www.kulpaonline.com Seite26von31
D E B U G G I N G I N V B A
Dasberwachungsfenster
Das berwachungsfenster funktioniert hnlich dem LokalFenster, nur das man hier selbst
bestimmt,welcheWerteangezeigtwerden.
Dieses Fenster erscheint automatisch, wenn man einen berwachungsausdruck defi-
niert hat.
Um eine Variable fr die berwachung zu bercksichtigen, ist diese im Code zu markieren
und im Kontextmen (rechte Maustaste) der Menpunkt berwachung hinzufgen... aus
zuwhlen:

Abbildung3Dasberwachungsfenster

Nun kann man nicht nur die Variable selbst hnlich wie im LokalFenster berwachen, son
dernauchAusdrckehinzufgen.IndiesemBeispielwurdefestgelegt,dassdieProgramm
ausfhrunggestopptwird,wenndenWertderVariableniValue>50ist.
Der Gltigkeitsbereich dieser berwachung kann auf Prozedur bzw. Modulebene entspre
chenderweitertwerden;diesfhrtjedochu.u.zueinemdeutlichlangsamerenProgrammab
lauf.
AberfrdasAufsprenvonFehlerwartetmanjagernebisschen...
StefanKulpa2006http://www.kulpaonline.com Seite27von31
W I S S E N S W E R T E S
K
StefanKulpa2006http://www.kulpaonline.com Seite28von31
WISSENSWERTES
api t el
5
GltigkeitsbereicheundLebensdauervonVariablen
ede Sprache hat Regeln fr die Definition des Gltigkeitsbereichs und der Lebensdauer
von Variablen und Prozeduren. Basic macht da keine Ausnahme, obwohl die Regeln sich
leider anscheinend mit jeder Version ndern. Whrend der verwickelten Geschichte der
Sprache haben alle die Versuche, neue Zustze einzufgen, ohne wiederum dafr mit alten
zu brechen, ein heilloses Durcheinander angerichtet. Die BasicLandschaft ist berst von
aufgegebenen Modifikatoren fr Reichweite und Gltigkeitsbereich, wie Shared, Common
und jetzt auch noch Global. In der aktuellen Version haben selbst die besten Absichten die
Angelegenheitnichtdurchschaubarergemacht:
J
DasSchlsselwortDim (dasWortmitderabsolutschlechtestenGedchtnissttzefrdieBe
deutung)erstellteineVariablemitlokalemGltigkeitsbereichundvorbergehenderLebens
dauer,wennesinnerhalbeinerProzedurverwendetwird(auerdassdieLebensdauerunbe
grenzt ist, wenn die Prozedur als statisch deklariert wird). Wenn es aber auerhalb einer
Prozedurverwendetwird, erstelltDimeineVariablemitdemGltigkeitsbereichPrivateund
unbegrenzter Lebensdauer (trotz der Tatsache, dass die Lebensdauer in einem Standardmo
dulwiederumwichtigist).
Private und Public sind Deklaratoren fr Variablen; fr Konstanten, Deklarationen, Typen
undProzedurensindesaberModifikatoren.
FallsdudasdurchschaustundDimimmerrichtigverwendest,brauchstdudiesenKursnicht.
Fr alle anderen knnte es hilfreich sein, sich einen Mythos zu erschaffen und vorzugeben,
daranzuglauben.HiersinddieGebotenfreinenmglichenBasicDatenMythos:
1. Das Wort Dim bedeutet in der Eingeborenensprache eines BasicVolksstammes im
nordstlichenCathistantatschlichLokal.DeshalbsolltemanDimnurfrlokaleVa
riablen verwenden. Es sieht zwar so aus, als wenn Basic Dim auch in anderen Zu
sammenhngenzulsst,derCodewirddannabervonbsenGeisternheimgesucht.
2. Verwende Static fr lokale Variablen mit unbegrenzter Lebensdauer. Deklariere
niemalsFunktionenalsStatic,weilesdieBedeutung vonDimverndert.Auerdem
wirdmandavonWarzenbekommen.
3. Verwende Private fr Variablen mit modularem Gltigkeitsbereich. Widerstehe der
Versuchung,indiesemZusammenhangDimzuverwenden,obwohlesfreinigeZeit
zufunktionierenscheint.
4. Verwende Public fr Variablen mit globalem Gltigkeitsbereich. Vor langer, langer
Zeit(nachanderenQuellenindervorletztenVersion)bedeuteteGlobalPublic.Eini
ge Abweichler vom Wahren Glauben behaupten, dass es immer noch als eine Art
W I S S E N S W E R T E S
StefanKulpa2006http://www.kulpaonline.com Seite29von31
Huldigung an die bse Gottheit Kompatibilitt funktioniert. Ignoriere diese Gerch
te.
5. Deklariere dynamische (in der Gre vernderbare) Datenfelder immer mit leeren
Klammern und dem richtigen VariablenSchlsselwort. Die Behauptung, dass Redim
ohne vorherige Deklaration auf lokale Variablen angewendet werden kann, fhrt
unweigerlichindenWahnsinn.
6. Gib immerPublic oder Privatefr benutzerdefinierte Typen und Deklarations-
anweisungen an. Bei Klassen- und Formularmodulen erzwingt Basic die De-
klaration, bei Standardmodulen aber bietet es eine automatische Voreinstel-
lung. Einige Experten glauben, dass sie diese Regel auch bei Konstanten und
Prozeduren befolgen sollten. Wenn man jedoch die Standardeinstellung
verwendet, wird man trotzdem weiterleben.
Gltigkeitsbereiche:DienacktenFakten
Fr all die eher prosaischen Leser, die mehr an Fakten als an Meinungen interessiert sind,
sind in der nachfolgenden Tabelle die StandardGltigkeitsbereiche fr verschiedene Ele
menteaufgelistet,diemaninseinemProgrammdeklarierenkann:
Standardmodule FormundKlassenmodule
Standard:Private Standard:Private
PrivateOK PrivateOK
Konstanten
PublicOK Publicillegal
Standard:Public Standard:illegal
PrivateOK Privateerforderlich
BenutzdefinierteTypen
PublicOK Publicillegal
Standard:Public Standard:illegal
PrivateOK Privateerforderlich
Deklarationsanweisungen
PublicOK Publicillegal
Standard:Private*) Standard:Private*)
PrivateOK PrivateOK
Variablen
PublicOK PublicdefiniertEigenschaft
Standard:Public Standard:definiertMethode
PrivateOK PrivateOK
FunktionenundSub
Prozeduren
PublicOK PublicerstelltMethode
Standard:Public Standard:Public
PrivateOK PrivateOK
Eigenschaften
PublicOK PublicOK
*)StandardbedeutetDeklarationmitDim,nichtmitPrivateoderPublic.
W I S S E N S W E R T E S
StefanKulpa2006http://www.kulpaonline.com Seite30von31
PassaufDeineTypenauf...
Einer der gefhrlichsten Fehler in Visual Basic (For Applications) tritt auf, wenn man ver
sucht,mehrereDeklarationenineinerZeileunterzubringen.ZumBeispiel:
Di mc, i , h As Long
Man knnte jetzt glauben, drei Longinteger definiert zu haben. Falsch! Man hat stattdessen
zwei Varianten (der Standardtyp fr die ersten beiden) und eine explizit deklarierte Longin
tegerVariablegeschaffen.HiereineandereVariante:
Di mc As Long, i , h
Richtigist:
Di mc As Long, i As Long, h As Long
bzw.:
Di mc As Long
Di mi As Long
Di mh As Long
Datentypen(Zusammenfassung)
Die folgende Tabelle enthlt die von Visual Basic untersttzten Datentypen sowie deren Spei
cherbedarfundWertebereiche.
Datentyp Speicherbe
darf
Wertebereich
Byte 1Byte 0bis255
Boolean 2Bytes TrueoderFalse
Integer 2Bytes 32.768bis32.767
Long
(langeGanzzahl)
2.147.483.648bis2.147.483.647
Single
(Gleitkommazahlmiteinfa
cherGenauigkeit)
4Bytes 3,402823E38bis1,401298E45frnegative
Werte;
1,401298E45bis3,402823E38frpositiveWer
te.
Double
(Gleitkommazahlmitdop
pelterGenauigkeit)
8Bytes 1,79769313486232E308bis
4,94065645841247E324frnegativeWerte;
4,94065645841247E324bis
1,79769313486232E308frpositiveWerte.
Currency
(skalierteGanzzahl)
8Bytes 922.337.203.685.477,5808bis
922.337.203.685.477,5807
W I S S E N S W E R T E S
StefanKulpa2006http://www.kulpaonline.com Seite31von31
Datentyp Speicherbe
darf
Wertebereich
Decimal 14Bytes +/79.228.162.514.264.337.593.543.950.335
ohneDezimalzeichen;
+/7,9228162514264337593543950335mit28
Nachkommastellen;diekleinsteZahlungleich
Nullist
+/0,0000000000000000000000000001.
Date 8Bytes 1.Januar100bis31.Dezember9999.
Object 4Bytes BeliebigerVerweisaufeinObjektvomTypOb
ject.
String
(variableLnge)
10Bytesplus
Zeichenfolgen
lnge
0bisca.2Milliarden.
String
(festeLnge)
Zeichenfolgen
lnge
1bisca.65.400
Variant
(mitZahlen)
16Bytes NumerischeWerteimBereichdesDatentyps
Double.
Variant
(mitZeichen)
22Bytesplus
Zeichenfolgen
lnge
WiebeiStringmitvariablerLnge.
Benutzerdefiniert
(mitType)
Zahlistvon
Elementen
abhngig
DerBereichfrjedesElemententsprichtdem
BereichdeszugehrigenDatentyps.
Datenfelder eines beliebigen Datentyps bentigen 20 Bytes im Speicher, vier Bytes fr jede
Datenfelddimension und die Anzahl an Bytes, die fr die eigentlichen Daten bentigt wer
den. Der fr die Daten bentigte Speicher kann durch Multiplikation der Anzahl an Daten
elementen mit der Gre eines einzelnen Elements ermittelt werden. Die Daten in einem
eindimensionalen Datenfeld, das vier Elemente vom Typ Integer mit jeweils zwei Bytes ent
hlt, belegen zum Beispiel acht Bytes. Insgesamt bentigt das Datenfeld die acht Bytes fr
dieDatenzuzglich24BytesfrVerwaltung,also32Bytes.
Ein Wert vom Typ Variant, der ein Datenfeld enthlt, bentigt 12 Bytes zustzlich zu dem
Speicher,derfrdasDatenfeldalleinebentigtwird.