Schnell-Kurs (Visual-Basic)

Das ist ein möglichst kompakter Schnellkurs in Visual-Basic, wobei die wichtigsten Eigenschaften erklärt werden. Für eine Liste der verfügbaren Funktionen gibt es hier die Visual-Basic Funktionen.

Die in geschweiften Klammern {...Code...} beschreiben Texte sind nur Kommentare oder Platzhalter und nicht Code.

Vorteile von Visual-Basic

Die Vorteile liegen ganz klar das auf der Seite der Lesbarkeit, der einfachen Syntax und der leichten Erlernbarkeit der Sprache. Projekte und Codes in Visual-Basic sind grundsätzlich leichter zu verstehen als vergleichbare Codes in anderen Sprachen, wie zB. C++.

  • Die Syntax ist einfach übersichtlich und leicht zu lesen.
  • Die Sprache läßt sich mit wenig Aufwand erlernen.
  • Die Codes bleiben übersichtlicher und lesbarer als in anderen Programmiersprachen und sind deshalb auch leichter weiterzuentwickeln.
  • Die meisten Anwendungen lassen sich damit programmieren.
  • Ist auch für Hobbyprogrammierer interessant da kein Expertenwissen notwendig ist und schnell die ersten eigenen Programme geschrieben werden können.
  • Programme können mit weniger Zeitaufwand erstellt werden als teilweise in anderen Sprachen.
  • Der Editor ist übersichtlich, gut organisiert und enthält einen guten Dialogeditor, und auch das Compilern ist einfach.
  • Unterstützt Inline Debugging, welches es ermöglicht ein Programm bereits während dem Schreiben schritt für schritt auszuführen (interpretieren) und dabei die Werte und Reaktionen zu beobachten.
  • Auch wenn oft anderes behauptet wird können durchaus auch in VB professionelle Anwendungen entwickelt werden. Nur ab einer bestimmten Größe (da liegt es in der Regel an der Mangelhaften Umsetzung der Klassen-Eigenschaften) oder bei hohen Anforderungen an die Leistung oder sehr systemnahe Programmen (zB. Treiber) ist VB ungeeignet.
    (Das oft gerne ins Feld gebrachte Argument Basic Sprachen führe oft zu unstrukturierten Spaghetti-Codes (durch die GoTo Funktion) ist ein Gerücht. Grundsätzlich ist jede Sprache in der Lage solche Codes zu generieren da jede vernünftige Sprache eine Sprung-Funktion kennt. Dies ist also ein Problem der Programmier und nicht der Sprache. Wahrscheinlich ist das Gerücht in der Zeit der aller ersten Basic Sprachen entstanden als den Programmiern noch die Erfahrung fehlte, und ist längst nicht mehr aktuell.)
  • VB führt standardmäßig eine Überlaufsprüfung, Indexbereichsprüfung und Stack-Überlaufsprüfung durch, was den Code zT. sicherer macht als zB. C. Überlaufsprüfung und Indexbereichsprüfung können optional für das ganze Projekt deaktiviert werden, leider aber nicht auf Modularer oder Prozeduraler Ebene.
    (Sprachen wie C, die zB. keine Stack-Überlaufsprüfung durchführen sind auch gefährdet das passive Datenformate wie Bilder benutzt werden können um Codes auszuführen, wenn die Entsprechenden Programme dafür keine Vorsorge leisten. Auf diese Weise können auch Schadcodes in Systeme eingeschleust werden, und es sind bereits eine ganze Liste von Programmen bekannt die solche Fehler enthalten¦enthielten und dafür empfindlich waren. VB ist durch seine Stackprüfung dagegen grundsätzlich unempfindlich, bei einem Stack-Überlauf bricht ein Programm einfach mit einer Fehlermeldung ab.)

Nachteile von Visual-Basic

Die meisten Nachteile gehen auf kosten der Ausführungsgeschwindigkeit, weshalb zB. keine rechenintensiven Anwendungen wie 3D-Spiele oder Raytracing in Visual-Basic programmiert werden. Auch die mangelhafte Unterstützung von Klassen und Objekt orientiertem Programmieren verhindert das Visual-Basic für große komplexe Projekte verwendet wird. Oder auch da wo sehr System- oder Hardware-nahe Anwendungen geschrieben werden müssen (zB. Treiber, Betriebsystem) da kein Assembler unterstützt wird und auch keine Funktionen verfügbar sind.

Die Nachteile von Visual-Basic waren der Grund für das Eröffnen des Runtime-Basic Projekts und der Entwicklung einer Opensource Sprache die ähnlich leicht erlernbar und benutzbar sein soll wie Visual-Basic.

  • Unterstützt kein Unsigned Daten-Typen.
  • Unterstützt kein Inlining (Codes in Prozeduren werden direkt in die aufrufende Prozedur eingefügt und nicht über Call aufgerufen)
  • Unterstützt Klassen nur unvollständig, zB. keine Polymorphie oder Vererbung, keine echten Klassenmodule welche mehrere Klassen enthalten können.
  • Funktionen können nicht überladen werden (mehrere Funktionen und unterschiedliche Parameter mit dem gleichen Namen.)
  • Unterstützt keine Zeiger.
  • Unterstützt kein Inline Assembler.
  • Kann keine eigenständigen Programme compilieren die ohne Runtime DLL auskommen.
  • Der Codegenerator optimiert den Code an vielen Bereichen nicht gut (zB. wird nicht einmal X^2 durch X*X ersetzt).
  • Einige Optimierungen wie das Steuern der Prüfungen von Überlauf und Indexüberschreitung läßt sich nur für ein ganzes Projekt ein und ausschalten, und nicht auf modularer oder prozeduraler Ebene.
  • Die Sprache gehört einer Firma, ist kostenpflichtig, nicht opensource, und läuft nur auf einem Betriebssystem.
  • Der Sprachumfang ist klein und hat sich kaum weiterentwickelt, zudem wurde die Weiterentwicklung leider eingestellt und da es sich nicht um eine opensource Sprache handelt, kann sie auch nicht von freiwilligen weiterentwickelt werden.

Text im Code

Zeilentrennung

  • Zeilen müssen nicht durch ein Zeichen (zB. In C ist es ";") voneinander getrennt werden. Jede Zeile gilt an ihrem Ende als abgeschlossen, wenn sie nicht mit einem "_ Zeichen Fortgesetzt wird."
  • Es ist möglich mehrere Codezeilen auf einer Zeile zu schreiben, sie müssen dann mit einem ":" Doppelpunkt voneinander getrennt werden.


    Var1 = 1
    Var2 = 2
 
    Var1 = 1: Var2 = 2

Zeile fortsetzen

  • Einige Zeilen können sehr lang werden, was oft nicht der Übersichtlichkeit dient. So ist es möglich eine Zeile zu trennen und auf der Nächsten Zeile fortzusetzen, das geht über ein " _" (unterstrich). Der Unterstrich darf nicht gleich nach einem Text oder Namen folgen, es muß zuvor mindestens ein Lehrzeichen stehen, sonst wird der Unterstrich als zum Code gehörend betrachtet.


    If Var1 = 1 Or Var2 = 2 Or Var3 = 3 Or Var4 = 4 Then
 
    End If
 
    '...oder
 
    If Var1 = 1 Or _
       Var2 = 2 Or _
       Var3 = 3 Or _
       Var4 = 4 _
       Then
 
    End If

Kommentare

  • Es können im Code Kommentare eingefügt werden die vom Compiler ignoriert werden. Alles nach einem '-Zeichen (Apostroph) wird als Kommentar betrachtet. Es können auch Codes auskommentiert werden um sie zu deaktivieren.
  • Das Auskommentieren eines ganzen Blocks ist leider nicht möglich, der Editor bietet aber die Möglichkeit ein markierten Textblock auszukommentieren.


    ' Das ist ein Kommentar
    ' Var1 = 1    ' diese Zeile ist deaktiviert
 
    Var1 = 1

Beschreibung

  • Alle Deklarationen auf Modul-Ebene (Public¦Private) müssen vor dem Code, also vor der ersten Prozedur geschrieben werden.


In den Beispielen wird angegeben wo sich der Quelltext befindet.

'-------- Deklaration
    '{... Diese Quelltexte befinden sich im Deklarationsteil des Moduls, also vor der ersten Prozedur.}
 
'-------- Code
    '{... Diese Quelltexte befinden sich innerhalb einer Prozedur.}

Allgemeines

Option Explicit

  • Option Explicit Erzwingt das Variabeln explizit deklariert werden müssen. Auf diese Weise wird verhindert das zB. durch falsche Schreibweise unbemerkt neue Variablenamen deklariert werden und dies im Code überhaupt nicht auffällt. Das Fehlersuchen wird dann sehr schwer. Es ist zwar möglich die Daten-Typen teilweise auch mit Kürzeln anzugeben (&%!#@), tut man dies aber nicht werden sie automatisch als Variant behandelt, die viel zeitaufwendiger sind und auch mehr Speicher benutzen, und durch das wegfallen der Typenprüfung auch eine Fehlerquelle darstellen.
  • Diese Anweisung wird im Code am besten ganz oben eingefügt und kann über eine Option im Editor automatisch in Projekte eingefügt werden.


'-------- Deklaration
Option Explicit

Namensvergabe

  • Namen sind in VB nicht casesensitiv, das heist de GroߦKlein-Schreibung spielt keine Rolle.
  • Namen sollten in CamelCase deklariert werden da dies die Lesbarkeit erhöht, das heißt das jedes Einzelwort in einem Name im ersten Buchstaben groß geschrieben wird. (zB. "StrRead" statt "strread")
  • Namen sollten ihren Zweck ausdrücken ("StrRead" ist besser als "StrR" oder "sr")
  • Namen sollten sinnvoll alphabetisch sortiert werden können, also ist es besser erst die höhere Zuordnung anzugeben und dann erst die spezifischen, ähnlich wie es bei Objekten durch den "."-Syntax gemacht wird ("Str.Read"). ("StrRead" ist besser als "ReadStr")
    • Die Namenskonvention unterläuft dies leider da der Daten-Typ als erstes eingegeben werden soll. Es spricht aber nichts gegen eine umgekehrte Schreibweise, falls man sich nicht an eine Vorgabe halten muß. ("StrReadTxt" ist besser als "txtStrRead")
  • Die Namensvergaben ist ganz besonders bei Public (projektweit sichtbaren) Namen wichtig, erstens um am Namen zu erkennen worum es sich handelt, und zweitens um zu verhindern das Public Namen in verschiedenen Modulen sich durch Namensgleichheit gegenseitig überschneiden. Aber auch private und Lokale Namen sollten sinnvoll benannt werden damit ein Code auch nach dem Fertigstellen leicht verstanden werden kann. Einsilbige Namen wie "i j uu cs usw." sollte man vermieden (in Local Namen sind diese vielleicht noch tolerierbar wenn auch nicht sinnvoll, in Public Private aber nicht mehr).

Block-Struktur

  • Viele Strukturen funktionieren als Blöcke (If-Then, For-Next, Do-Loop, Sub Function), und solche Blöcke können verschachtelt werden (in welchem ein Block kompletter von einem anderen umschlossen ist), aber dürfen sich nicht überschneiden.


'-- Richtig
    If ... Then
      For ...
      Next
    End If
 
'-- Falsch
    If ... Then
      For ...
    End If
      Next

Konsolen Ausgabe

  • Um Informationen während der Entwicklungszeit auszugeben, kann mit Debug.Print Text im Konsolenfenster ausgegeben werden.
  • Debug.Print Code wird nicht compiliert sondern nur während der Entwicklungszeit ausgeführt.


Debug.Print "Info", Var1, Var2

Haltepunkt mit Bedingungen

  • Mit Debug.Assert kann während der Entwicklungszeit auch ein Wahrheitswert geprüft werden wie mit If, und wenn dieser False ist funktioniert Debug.Assert wie ein Haltepunkt und unterbricht das laufende Programm an dieser Stelle.
  • Debug.Assert wird wie Debug.Print nicht compiliert sondern nur während der Entwicklungszeit ausgeführt.


Debug.Assert CheckVar = 1    ' Ist CheckVar nicht 1, wird während Entwicklungszeit der Programmlauf hier unterbrochen


  • Da VB leider keine Compiler-Konstante deklariert, mit der festzustellen werden kann ob das Programm in der Entwicklungszeit (Editor) oder in der Laufzeit (compiliert) ausgeführt wird, kann Debug.Assert verwendet werden um dies im Programmlauf festzustellen. Mit #If Compilerbedingungen abhängig Compilieren, je nachdem ob der Code in Entwicklungszeit oder Laufzeit läuft ist leider nicht möglich.


'-- In einem Modul die Variable und die Funktionen Deklarieren
 
' Eine Pseudo-Konstante als Read-Only Property oder geschützte Variable
Private CheckIsIDEVar As Boolean    ' CheckIsIDEVar Sollte nicht direkt verwendet werden oder man muß sicherstellen daß sie später nur gelesen und nie beschrieben wird
                                    '  CheckIsIDE() anstelle von CheckIsIDEVar verwenden.
 
' CheckIsIDESet muß über Debug.Assert möglichst beim Programmstart ausgeführt werden
Public Function CheckIsIDESet() As Boolean
    CheckIsIDEVar = True   ' Damit steht ab jetzt diese Variable zur Verfügung
    CheckIsIDESet = True   ' Damit der Debug.Assert keinen Break erzeugt.
End Function
 
' Zum schreibgeschützten Anfragen von CheckIsIDEVar
Public Function CheckIsIDE() As Boolean
    CheckIsIDE= CheckIsIDEVar
End Function 
 
 
 
'-- Im Code beim Programmstart ausführen um die CheckIsIDEVar zu setzen
 
Private Sub Form_Initialize()
    Debug.Assert CheckIsIDESet()    ' Diese Anweisung wird in der EXE nicht ausgeführt, also bleibt CheckIsIDEVar = False
End Sub
 
 
 
'-- Jetzt kann über CheckIsIDE() geprüft werden ob der Code in IDE-Entwicklungszeit oder compilierter Laufzeit ausgeführt wird
 
    If CheckIsIDE() Then
      ' In IDE
    End If

Compiler-Konstanten, #Const #If-Then

  • Über Compiler-Konstanten können bestimmte Codeteile während der Entwicklung Ein- und Ausgeschaltet werden. Codes die in einem #If-Then Block stehen die deaktiviert sind, werden auch nicht in den ausführbaren Code compiliert. Man kann diese Compiler-Konstanten gut gebrauchen wenn man entweder große Blöcke deaktivieren will, oder wenn man Codes zum Debugging (Fehlersuchen) einfügen will, die man dann leicht ein- und ausschalten kann.
  • #If-Then Blöcke dürfen die Blockstruktur anderer Blöcke durchbrechen, es wird nur die eigene Struktur beachtet. Und dürfen im ganzen Modul verwendet werden auch außerhalb von Prozeduren.
  • Compiler-Konstanten können leider nicht Public deklariert werden sondern gelten immer nur Private.


'-------- Deklaration
#Const CompileDebugging = True
 
 
'-------- Code
#If CompileDebugging Then
    '{... Code die ausgeführt und in das Programm compiliert werden wenn: CompileDebugging = True}
#Else
    '{... Code die ausgeführt und in das Programm compiliert werden wenn: CompileDebugging = False}
#End If
 
 
#If 1 = 0 Then   ' So kann man Codeblöcke schnell ein- und ausschalten.
    '{... Code}
#End If
 
 
' Blockstruktur anderer Blöcke durchbrechen
#If CompileDebugging Then
    Private Sub Test1(ByVal Par1 As Long, ByVal Par2 As Long)
#Else
    Private Sub Test1(Optional ByRef Par1 As Long, Optional ByRef Par2 As Long)
#End If
      '{... Code}
    End Sub

Programm Beenden

  • End beendet das Programm sofort.
  • Die sofortige Beendung eines Programms hat aber auch Nachteile, da Initialisierte Klassen nicht auf Nothing gesetzt und damit aus dem Speicher gelöscht werden, verbleiben sie auch nach dem Programmende im Speicher. Und auch das Formular eines Programms ist eine Klasse, das beim abrupten beenden eines Programms im Speicher verbleibt. Programme sollten nie mit End beendet werden, es sollten zuerst mit Unload alle Formulare beendet werden und dann das Hauptformular beendet werden.


End               ' dies beendet das Programm sofort
 
' Code im Hauptformular
Unload Form2      ' Dies beendet zuerst ein zweites Formular
Unload Me         ' und dann wird das Hauptformular beendet

Daten-Typen

  • Die Standard Daten-Typen sind die Basis jedes Programms und stellen das Format der Datenspeicherung dar, in welcher Werte abgelegt verwendet und verändert werden können.
  • Die Standard Daten-Typen werden fast alle auch direkt vom Prozessor unterstützt. Intern rechten man also mit Prozessor Registern, deshalb sind die Größen und Eigenschaften auch von der Hardware unterstützen Arithmetik abhängig.
  • Es gibt 3 Hauptarten der Standard Daten-Typen, numerisch ganzzahlig (Integer), numerisch bruchzahlig (Float) und Text (String). Dazu kommen weitere spezielle Daten-Typen wie Boolean Currency usw. und auch solche mit polymorphen Eigenschaften wie Variant oder Object hinzu.
  • Je nach Daten-Typ können unterschiedliche Werte aufgenommen und berechnet werden. Bei einer Deklaration einer Variable Konstanten oder Parameter wird festgelegt welchen Daten-Typ sie abbilden und damit welche Werte sie aufnehmen können und wie diese berechnet werden.
  • Es werden leider nicht alle Daten-Typen unterstützt, zB. gibt es kein Unsigned (Ganzzahl ohne Vorzeichen) für Integer oder Long. Aber man kommt mit den vorhandenen schon recht weit.
  • Decimal ist ein Untertyp der nur über eine Variant-Variable in Vb6 erreichbar ist. es ist nicht möglich direkt zu deklarieren.


Daten-TypPostFixPräFixKonvvb-NameGröße in ByteMinimumMaximumInfo
BytebytCBytevbByte10255Ganzzahl ohne Vorzeichen
-1-128127Ganzzahl mit Vorzeichen
-2065536Ganzzahl ohne Vorzeichen
Integer%intCIntvbInteger2-32'76832'767Ganzzahl mit Vorzeichen
-404'294'967'295Ganzzahl ohne Vorzeichen
Long&lngCLngvbLong4-2'147'483'6482'147'483'647Ganzzahl mit Vorzeichen
Single!sngCSngvbSingle4-3.402823E+38
-1.401298E-45
3.402823E+38
1.401298E-45
Gleitkommazahl
Double#dblCDblvbDouble8-1.79769313486232E+308
-4.94065645841247E-324
1.79769313486232E+308
4.94065645841247E-324
Gleitkommazahl
BooleanblnCBoolvbBoolean2False (0)True (-1)Wahrheitswert
Currency@CCurvbDecimal8-922'337'203'685'477.5808922'337'203'685'477.5807Ganzzahl skaliert
kleinste Zahl ungleich Null ist +/-0.0001
DecimalcurCDecvbCurrency14-79'228'162'514'264'337'593'543'950'335+79'228'162'514'264'337'593'543'950'335Gleitkommazahl
String (variable Länge)$strCStrvbString10 +LängeLänge: 0Länge: 2'147'483'647Zeichenkette Unicode
String (feste Länge)$strCStrvbStringLängeLänge: 1Länge: 65'536Zeichenkette Unicode
Variant (mit Zahlen)vntCVarvbVariant16Numerische Werte im Bereich des Datentyps Double
Variant (mit Zeichen)vntCVarvbVariant22 +LängeWie bei String mit variabler Länge
ObjectobjvbObject4--Beliebiger Verweis auf ein Objekt vom Typ Object
DatedtmCDatevbDate81. Januar 100Dezember 9999Zeit
ErrorerrCVErrvbError--
TypeudtvbUserDefinedTypeSumme Elemente--Daten-Struktur Benutzerdefiniert
(Datenfeld)vbArrayElemente: 0Elemente: 2'147'483'647Array, Datenfeld
(Datenzugriffsobjekt)vbDataObjectDatenzugriffsobjekt
(Collection-Objekt)col--Collection-Objekt
(nicht initialisiert)vbEmpty---nicht initialisiert Objekt
(ungültig)vbNull---keine gültigen Daten im Objekt



  • Bei Fließpunkt Werten ist es wichtig zu beachten, das bei Operationen automatisch eine Rundung stattfindet (Alles <0.5 auf die nächst kleinere Ganzzahl, sonst auf die nächst größere), wenn diese an ein Ganzzahl übergeben werden. Ist dies unerwünscht können die Werte mit Fix() auf die nächst kleinere Ganzzahl gerundet werden.


    Dim Var1 As Long
 
    Var1 = 3 / 2      ' Resultat ist 2, da die Berechnung im Fließpunkt Format durchgeführt wird und das Resultat 1.5 automatisch aufgerundet wird.
    Var1 = 1.5        ' Resultat ist 2, gleicher Grund wie oben.
    Var1 = 3 \ 2      ' Resultat ist 1, hier wird die Berechnung in Ganzzahlen durchgeführt, und dabei werden die Bruchwerte einfach weggeschnitten.
 
    '! Ganzzahl Divisionen sind viel schneller. Also sollte man besser "3 \ 2" statt "Fix(3 / 2)" verwenden.

Zahlensysteme

  • Ganzzahlen können mit und ohne Vorzeichen interpretiert werden, das heißt mit negativen werden oder nur 0 und Positive Werte.
TypBeschreibung
UnsignedOhne Vorzeichen, nur 0 und positive Zahlen (zB. Byte -> 0 bis 255)
SignetMit Vorzeichen, also auch negative Zahlen (zB. Integer -> -32'768 bis 32'767)



  • Es ist möglich Ganzzahlen in verschiedenen Zahlensystemen zu schreiben. Unterstützt wird Dezimal (10) Hexadezimal (16) und Oktal (8).


    Var1 = 100     ' Dezimal
    Var1 = &H64    ' Hexadezimal
    Var1 = &O144   ' Oktal


  • Fließpunktzahlen werden in der dieser Schreibweise geschrieben.
    {Mantisse}E[+-]{Exponent}


    Var1 = 1.23456789E+19
      ' ist gleich wie
    Var1 = 1.23456789 * 10 ^ 19
    Var1 = 12345678900000000000
 
    Var1 = 1.23456789E-19
      ' ist gleich wie
    Var1 = 1.23456789 * 10 ^ -19
    Var1 = 0.000000000000000000123456789

Variant

  • Variant ist ein besonnter Daten-Typ weil er fast alle Informationen aufnehmen kann und dadurch eine flexible Datenspeicherung ermöglicht (er ist polymorph, vielgestaltig). Es ist aber durch den zusätzlichen Verarbeitungsaufwand auch langsamer und sollte deshalb nur eingesetzt werden wenn man diese Eigenschaft Braucht.
    • Er kann aufnehmen: Standard Daten-Typen, Array und Objekte
    • Er kann nicht aufnehmen: benutzerdefinierte Typen, Strings mit fester Länge
  • Wird eine Information an eine Variant Variable übergeben, Werden diese Daten abgelegt und die Variant-Variable verweist über ein Zeiger auf diese Daten. Gleichzeitig wird im auch eine Unter Daten-Typ festgelegt der auch enthält um welche Art von Daten es sich handelt, also um welchen Standard Daten-Typen, ob es sich um ein Array handelt oder das Objekt.
  • Ein Variant belegt mindestens 16 Bytes im Speicher und bei jedem Datenaustausch finden Typenprüfungen und wenn notwendig Konvertierungen statt.
  • Objektverweise in Variant-Variablen werden immer zur Laufzeit aufgelöst, da während de Compilierungszeit nicht festgelegt ist was die Variant-Variable aufnehmen wird.

Nichts Leer und Null

  • Variant kann auch "Nichts" enthalten.
    • Nothing wird im zusammehang mit Objekten verwendet und ist kein Untertyp sondern ein Inhalt. wenn also eine Variant-Variable als träger für ein Objekt dient, kann der Inhalt dieses Objekts Nothing sein, und zeigt an das ein Objekt-Varible noch keiner Instanz zugewiesen wurde.
    • Empty ist eine Variant-Variable dann, wenn nach der Deklaration noch kein Wert zugewiesen wurde, und somit noch Nichts enthalten ist, und auch noch kein Untertyp festgelegt wurde. Zurückgegeben wird Kontextabhängig 0 oder "" (Leer-String).
    • Null zeigt ann das der Variant-Variable absichtlich keine gültigen Daten enthält
    • Error ist noch die Möglichkeit ein bearbeitungsfehler (wie zB. ein überlaf) zu markieren, es bedeutet das die Daten zerstört wurden.

Typ Ermitteln

  • Über die Funktion VarType() können die Untertypen über Konstanzern abgefragt werden, zurückgegeben wird eine Konstante. Dies funktioniert auch mit anderen Daten-Typen.
KonstanteWertBeschreibung
vbEmpty0Nicht initialisiert (Voreinstellung), es wurde nichts übergeben, oder mit Nothing Zuweisung gelöscht
vbNull1Enthält keine gültigen Daten, wurde mit Null Zuweisung
vbError10Fehler, in einer Berechnung oder Verarbeitung ist ein Fehler aufgetreten, oder wurde mit CVErr() zugewiesen
vbByte17Daten-Typ Byte
vbInteger2Daten-Typ Integer
vbLong3Daten-Typ Long
vbSingle4Daten-Typ Single
vbDouble5Daten-Typ Double
vbBoolean11Daten-Typ Boolean
vbCurrency6Daten-Typ Currency
vbString8Daten-Typ Typ String
vbArray8192Datenfeld
vbObject9Objekt
vbVariant12Wert vom Typ Variant (angewendet nur bei Datenfeldern mit Variant-Werten)
vbDate7Daten-Typ Typ Date
vbDataObject13Datenzugriffs-Objekt
vbDecimal14Daten-Typ Typ Decimal (nur als Untertyp von Variant verwendbar)
vbUserDefinedType36Werte vom Typ Variant, die benutzerdefinierte Typen enthalten



  • Über Funktionen kann die Daten-Art ermitteln werden, ist True wenn der Inhalt der Daten-Art angehört.
FunktionTrue wenn...
IsEmpty()die Variable nicht initialisiert wurde.
IsNull()die Variable keine gültigen Daten enthält.
IsError()die Variable ein Fehlerwert enthält, also ein Fehler aufgetreten ist.
IsMissing()in einer Prozedur ein Optionaler Parameter nicht übergeben wurde.
IsNumeric()der gesamte Ausdruck als Zahl interpretiert werden kann, also auch ein String mit einem gültigen Zahlenwert.
IsArray()die Variable ein Array ist.
IsObject()es eine Objekt-Variable ist.
IsDate()ein Ausdruck in ein Datum umgewandelt werden kann.

Gültigkeitsbereich (Namespace): Local, Private, Public

  • Es gibt drei Arten von Gültigkeitsbereichen, die bestimmen wo eine Deklaration gültig¦zugänglich¦sichtbar ist.
SchlüsselwortGültigkeitsbereichen
PublicIm gesamten Projekt
PrivateInnerhalb eines Moduls oder Klasse
LocalInnerhalb einer Prozedur


  • Variabeln werden innerhalb einer Prozedur immer als Lokal deklariert, sollen sie Private oder Public gültig sein, müssen sie alle vor der ersten Prozedur im Deklarationsbereich geschrieben werden. Nach einer Prozedur dürfen keine Deklarationen mehr geschrieben werden. In einer Prozedur können keine Namen Public¦Privare deklariert werden.
  • Lokal innerhalb einer Prozedur werden Variablen mit Dim deklariert. Ansonsten mit Private oder Public.
  • Lokal deklarierte Variabeln erhalten ihre Werte nur solange sich das Programm in der Prozedur befindet. Beim Verlassen der Prozedur gehen die Werte verloren. (Dies kann mit Static verhindert werden, siehe: Statische Werte: Static.)
  • Public sollten wirklich nur die Daten deklariert werden die auch tatsächlich im gesamten Projekt verwendet werden, damit es nicht zu Namensüberschneidungen kommt.
  • Lokal können Namen auch mit dem Postfix Zeichen deklariert werden, das am Ende des Namens geschrieben wird.


'-------- Deklaration
Private Var1 As Long    ' nur im Modul gültig
Public Var2 As Single   ' überall gültig
 
'-------- Code
    Dim Var1 As Long        ' nur in Prozedur gültig
    Dim Var2&               ' auch Long nur anders deklariert mit Postfix-Zeichen

Variabeln: deklarieren, benutzen

  • Variabeln sind die einfachste Datenart in einem Programm und die meisten Standard Daten-Typen werden so wie sie sind von Prozessor unterstützt.
  • Numerische Variabeln werden automatisch konvertiert, werden sie auf ein unterschiedlichen Typen übergeben, wird aber ein größerer Daten-Typ an ein kleineren übergeben, besteht immer die Potentielle Gefahr das ein Überlauf während der Laufzeit stattfinden kann, wenn zB. ein Long an ein Integer übergeben wird, oder sogar ein Double an ein Integer. Zudem macht die Konvertierung den Code langsamer. Normalerweise sollte man alle Werte die man in einem Code miteinander verwenden vom gleichen Daten-Typ sein. In 32Bit Systemen ist Long am schnellsten.


'-------- Deklaration
Private Var1 As Long   ' Deklaration mit Name Var1 und Daten-Typ Long (4-Byte Ganzzahl Signed)
Public Var2 As Single  ' Deklaration mit Name Var2 und Daten-Typ Single (4-Byte Fließpunktzahl)
 
'-------- Code
    Dim Var1 As Long   ' Deklaration mit Name Var1 und Daten-Typ Long (4-Byte Signed)
 
    Var1 = 1           ' die Variable enthält nun den Wert 1

Konstanten: Const

  • Alle Werte die in einem Programm als Wert oder "Text" eingegeben werden gelten als Konstanten. Es können aber auch Konstanten über das Schlüsselwort Const als Namen Deklariert werden. Dies hat den großen Vorteil das bestimmte Werte an verschiedenen stellen immer gleich lauten und über ein Name angegeben werden können. So können sie leicht geändert werden oder auch durch eine Variable ersetzt werden falls man im laufe der Programmierung feststellt das der Wert variabel sein sollte. Der Wert der die Konstante repräsentieren soll wird gleich bei der Deklaration angegeben.


'-------- Deklaration
Public Const Con1 As Long = 100
Private Const Con2 As String = "zwei"
 
'-------- Code
Const Con3 As Long = 300
 
    Var1 = Con1 + Con3
'     Wird interpretiert wie
'   Var1 = 100 + 300

Konstanten Aufzählung: Enum

  • Es können mehrere Konstanten auch in einem Enum zusammengefaßt werden.
  • Die Werte können angegeben werden, werden sie weggelassen wird automatisch der Wert in jedem neuen Namen um 1 erhöht, beginnend bei 0.
  • Es ist erlaubt mehrere Namen mit dem gleichen Wert zu deklarieren.
  • Ein Enum kann auch als Parameter Daten-Typ in einer Prozedur deklariert werden.
  • Die Enum Daten-Typen können nicht mit As festgelegt werden.
  • Enum könne nicht in einer Prozedur deklariert werden.


'-------- Deklaration
Private Enum Aufzaelung
    Name1        ' Name1 = 0
    Name2        ' Name2 = 1
    Name3 = 10   ' Name3 = 10
    Name4        ' Name4 = 11
End Enum

Text: String

  • String wird als Kette von Werten verstanden und verarbeitet.
  • String ist ein Standard Daten-Typ der Text aufnehmen kann, aber auch binäre Informationen enthalten kann.
  • Es stehen eine Reihe von Funktionen zur Verfügung um zB. die GroߦKlein-Schreibung zu ändern, Leerzeichen wegzuschneiden, Teile aus dem String zu kopieren oder ein String in einem anderen zu suchen.
  • Bei Übergabe von Text muß dieser immer mit "-Zeichen (Anführungszeichen) begonnen und abgeschlossen werden.
  • Ein leerer String wird mit zwei Anführungszeichen "" angegeben.
  • Will man ein "-Zeichen Anführungszeichen im Text beschrieben, tut man dies mit zwei Anführungszeichen "" im Text.
  • Strings können mit dem &-Zeichen verketten werden. Auch + wird als Verkettungszeichen akzeptiert, ist aber nicht ganz sauber, da so eine Verwechslung mit Zahlenmathematik auftreten kann.
  • Es ist bei der Deklaration eines Strings auch möglich eine feste Länge anzugeben. Dies bewirkt das diese feste Speichergröße deklariert wird und während der Laufzeit nicht geändert werden kann. Interessant ist dies vorallem im Zusammenhang mit Typen, da dann eine feste Größe deklariert wird und nicht nur ein Zeiger der auf eine Variable Größe verweist.


    Dim Text1 As String        ' Zeichenkette mit variabler Länge
    Dim Text2 As String * 10   ' Zeichenkette mit fester Länge
 
    Text1 = "Dies ist ein Text"                 'entspringt: {Dies ist ein Text}
    Text1 = "Dies ist " & "ein Text"            'entspringt: {Dies ist ein Text}
    Text1 = "Dies ist " & 1 + 2 & " ein Text"   'entspringt: {Dies ist 3 ein Text}
 
    Text1 = "Dies ""ist ein"" Text"             'entspringt: {Dies "ist ein" Text}
    Text1 = """" & "Dies ist ein Text" & """"   'entspringt: {"Dies ist ein Text"}
 
                                                'entspringt: {          }, vor der ersten Zuweisung enthält Text2 10 Null-Werte
    Text2 = "1"                                 'entspringt: {1         }, die restlichen Zeichen werden mit Lehrzeichen aufgefüllt
    Text2 = "12345678901234567890"              'entspringt: {1234567890}, die Zeichen länger als die deklarierte Länge werden weggeschnitten.

ASCII, Unicode

  • Intern werden String automatisch zu Unicode konvertiert, nach Außen aber werden Strings immer als Ascii interpretiert. VB Konvertiert als immer Strings beim lesen von Ascii zu Unicode, und beim schreiben von Unicode zu Ascii.
  • Leider ist die Trennung dieser beiden String-Formate nicht sauber gelöst, da es nicht möglich ist ein Ascii-String zu deklarieren. Gleichzeitig aber beim Schreiben nach Außen immer eine Konvertierung durchgeführt wird. Dies kann auch zu Konflikten führen wenn dies nicht berücksichtigt wird und nicht die Formate übergeben werden wie sie erwartet werden, zB. auch im Zusammenhang mit API-Deklarationen.
TypBeschreibung
AsciiDas Standard Zeichenformat in welchem für jedes Zeichen 1 Byte reserviert wird. So ist es möglich 256 Symbole abzubilden, wobei die ersten 32 Steuerzeichen und keine Text-Symbole darstellen.
Die Symbole sind ein allgemein gültiger ISO-Standard.
Es existieren 2 Ascii Standards, das neu Windows Format welches unter VB verwendet wird, aber auch das alte DOS Format, welches noch Symbole enthielt für die grafische Abbildung von Rahmen mit Textsymbolen.
UnicodeIst ein neues Standard Zeichenformat in welchem für jedes Zeichen 2 Byte reserviert werden. Es ist auf diese weise möglich mehrere Sprachen und Sonderzeichen abzubilden da jedes Zeichen 65536 Symbole abbilden kann.
Auch dies ist ein ISO-Standard, der permanent weiterentwickelt wird. Die ersten 256 Zeichen im Unicode sind identisch mit dem aus dem Ascii-Code (Windows).

Daten-Felder: Array

  • Daten-Typen können auch als Feld oder Array deklariert werden, sie können ein oder mehrdimensional deklariert werden und können so Listen oder Matrizen von Daten enthalten.
  • Wie bei normalen Variablen dürfen alle Daten-Typen deklariert werden. Ist eine Deklaration aber einmal erfolgt, kann der Daten-Typ bei einer Redimensionierung nicht mehr geändert werden.
  • Bei einer Dimensionierung eines Arrays werden alle Werte auf 0 initialisiert. Das gleichzeitige Festlegen von Werten bei der Dimensionierung ist leider nicht möglich.
  • Über Erase kann ein Array aus dem Speicher gelöscht und der reservierte Speicherbereich wieder freigegeben werden.
  • Wird nur ein Wert und kein Bereich deklariert, wird automatisch die Standarduntergrenze 0 verwendet. Diese kann über die Option "Option Base ?" geändert werden, erlaubt sind die Werte 0 und 1.
  • Felder können Statisch mit Dim oder Dynamisch mit ReDim deklariert werden. Statisch bedeutet das die Größe des Arrays während der Laufzeit nicht geändert werden kann, bei dynamischen Arrays kann die Größe während der Laufzeit geädert werden.
  • Wird ein Dynamisches Array ohne Angabe der Größe deklariert, und auf dieser zugegriffen bevor eine Dimensionierung durchgeführt wurde, wird ein Laufzeitfehler auftreten.
  • Die Größe Dynamische Arrays kann geändert werden, dabei gehen aber die enthaltenen Daten verloren. Um dies zu verhindern kann das Schlüsselwort Preserve verwendet werden.
  • Um die Größe eines Arrays zu ermitteln können die Funktionen LBound für Untergrenze und UBound für Obergrenze verwendet werden.
  • Es wird bei mehrdimensionalen Arrays leider keine Reimensionierung aller Dimensionen unterstützt, da dazu eine Umformung der Datenstruktur im speichern notwendig wäre. Durch die Struktur im Speicher ist nur die Redimensionierung der letzen Dimension möglich. Also sollte man zB. bei einem 2 dimensionalen Array in welchem die Zeilenanzahl redimensionierbar sein soll, die Zeilen auf der zweiten Dimension abgebildet werden Arr1(Spalten, Zeilen).


'-------- Deklaration
Option Base 0                            ' Legt die Standarduntergrenze auf 0 fest
 
Private Arr1() As Long                   ' Legt ein dynamisches Array an, das noch keine Dimensionierung besitzt
 
Private Arr2(10) As Long                 ' Legt ein statisches 1-dimensionales Array an, das dimensioniert ist mit: 11 Feldern, von 0 bis 10.
Private Arr3(1 To 10) As Long            ' Legt ein statisches 1-dimensionales Array an, das dimensioniert ist mit: 10 Feldern, von 1 bis 10.
 
Private Arr4(1 To 10, 1 To 20) As Long   ' Legt ein statisches 2-dimensionales Array an, das dimensioniert ist mit: 10x20 Feldern, von 1 bis 10 und 1 bis 20.
 
 
'-------- Code
  Dim Arr5(1 To 10) As Long        ' Legt ein statisches 1-dimensionales Array an
 
  ReDim Arr6() As Long             ' Legt ein dynamisches 1-dimensionales Array an, das noch keine Dimensionierung besitzt
  ReDim Arr7(1 To 10) As Long      ' Legt ein dynamisches 1-dimensionales Array an
  ReDim Arr8(-10 To 10) As Long    ' Legt ein dynamisches 1-dimensionales Array an
 
  ReDim Arr9(1 To 2, 1 To 100) As String   ' Legt ein dynamisches 2-dimensionales Array an, wobei die erste Dimension 2 Spalten und die zweite 100 Zeilen enthält.
 
  ReDim Arr1(1 To 10)              ' das zuvor bereits deklarierte Arr1 wird jetzt erst Dimensioniert. Der Daten-Typ kann nun auch weggelassen werden da er <cls code>Long</cls> bleiben muß.
 
 
    Arr1(1) = 100                  ' Werte können nun in das Array geschrieben werden wie bei einer Variable auch.
    Arr1(2) = 200
    Arr9(2, 5) = "Text"
 
 
    Redim Preserve Arr1(1 To 20)   ' Ein dynamisches Array kann redimensioniert werden ohne die Enthaltenen werden zu löschen.
    Debug.Print Arr1(1)            ' der Wert 100 bleibt erhalten
 
 
    Erase Arr1                     ' Löscht den Speicher der von "Arr1" belegt wird, "Arr1" ist danach leer

Daten-Struktur: Type

  • Es können auch mehrere Daten-Typen zu einer Daten-Struktur zusammengefaßt werden, dies geschieht über das Schlüsselwort Type. Ist eine Daten-Struktur einmal Deklariert, kann man ihn genauso zum Deklarieren von Variabelname oder Parameter verwenden wie ein Standard Daten-Typen.
  • Daten-Strukturen stellt nur die Form zur Verfügung, um auch Speicher zu deklarieren muß über Dim eine Variable Deklariert werden wie bei den Normalen Daten-Typen auch.
  • Daten-Strukturen haben viele Vorteile, da man sie auch genauso durch eine Zuweisung als ganzes an ein anderen gleichnamigen Type kopieren kann oder auch mit allen enthaltenen Daten speichern kann. Hat man in einem Programm mehrere Variablen die zusammen gehören, sollte man sie über eine Daten-Struktur schon wegen der Übersichtlichkeit zusammenfassen.
  • Type können nur Private oder Public, also außerhalb einer Prozedur deklariert werden, innerhalb einer Prozedur wird eine Type Deklaration leider nicht zugelassen.
  • Die Größe einer Daten-Struktur kann über die Funktion Len nur dann ermittelt werden, wenn alle Daten mit einer festen Länge deklariert wurden. Ist ein zB. String mit variabler Länge oder ein Objekt enthalten, kann der Speicherbedarf des Typs nicht ermittelt werden.
  • Daten-Strukturen können auch andere Daten-Strukturen enthalten und so verschachtelt werden.
'-------- Deklaration
 
Private Type TypenName1
    VarA1 As Long
    VarA2 As String * 8   ' String mit fester Länge
    VarA3 As String       ' String mit variabler Länge
End Type
 
Private Type TypenName2
    VarB1 As Long
    VarB2 As Long
 
    VarB3 As Double
    VarB4 As Double
 
    DatB1 As TypenName1   ' Typen können auch andere Typen enthalten und so verschachtelt werden.
End Type
 
 
'-------- Code
 
    Dim Typ1 As TypenName2
 
    Typ1.VarB1 = 1
    Typ1.VarB2 = 2
    Typ1.DatB1.VarA1 = 3
    Typ1.DatB1.VarA2 = "4"  ' Obwohl nur 1 Zeichen übergeben wird, bleibt der String dennoch 8 Zeichen lang
    Typ1.DatB1.VarA3 = "5"  ' Hier wird Text genau so übergeben wie angegeben
 
 
    Dim Typ2 As TypenName2
 
    Typ2 = Typ1             ' Daten-Strukturen können kopiert werden

With

  • Über das Schlüsselwort With kann man die Schreibweise verkürzen. Innerhalb eines With Blocks kann man dann den deklarierten Namensteil weglassen. Das funktioniert überall da wo im Namensteile durch ein "." Punkt getrennt werden, also auch bei Klassen.
  • With kann auch den Zugriff auf Daten beschleunigen, besonders bei Objekten, da dann jede "." Hierarchie eine Operation benötigt.


  With Typ1
    .VarB1 = 1
    .DatB1.VarA1 = 2
  End With
 
  With Typ1.DatB1
    Typ1.VarB1 = 3 ' Hier muß er wieder voll angegeben werden
    .VarA1 = 4
  End With

Prozeduren: Sub, Function

  • Prozeduren sind Programmeinheiten die eine bestimmte Aufgabe erledigen. So lassen sich Programmcodes für wiederholende Aufgaben mehrfach verwenden, aus dem Grund sollten Entwickler auch darauf achten ihre Codes so zu schreiben das sie möglichst universell nutzbar sind.
  • Es gibt zwei Arten von Prozeduren, eine ohne und eine mit Rückgabe Wert.
TypBeschreibung
SubProzedur (Subroutine) ohne Rückgabewerte
FunctionProzedur (Function) mit Rückgabewerte



  • Aufgerufen wird eine Prozedur über Call (das Call kann auch weggelassen werden, oder der Übersichtlichkeit halber kann man es schreiben. Wird Call weggelassen ändert sich der Syntax, die klammer werden dann ebenfalls nicht mehr geschrieben.)
  • An eine Prozedur können auch beliebige Parameter übergeben werden.
  • Auch Funktionen können ohne Rückgabewert über Call aufgerufen werden, wenn der Rückgabewert nicht benötigt wird.
'-------- Code
 
Private Sub Main()
  Dim ReturnVal As Long
  Dim Val1 As Long, Val2 As Long
 
    Call Test1(Val1, Val2)
    '...oder
    Test1 Val1, Val2
 
    ReturnVal = Test2(Val1, Val2)   ' Die Rückgabe wird an ReturnVal übergeben
    Call Test2(Val1, Val2)          ' Die Rückgabe wird verworfen
 
End Sub
 
 
Private Sub Test1(ByVal Par1 As Long, ByVal Par2 As Long)
    '{... irgend ein Code}
    Exit Sub   ' die Prozedur wird sofort verlassen
    '{... wird nicht mehr ausgeführt}
End Sub
 
Private Function Test2(ByVal Par1 As Long, ByVal Par2 As Long) As Long
    '{... irgend ein Code}
    Test2 = 2       ' der Rückgabewert wird festgelegt (ohne die Prozedur zu verlassen)
    Exit Function   ' die Prozedur wird sofort verlassen
    '{... wird nicht mehr ausgeführt}
End Function

Parameter: Referenz¦Wert, ByRef¦ByVal

  • Es kann über ein zusätzliches Schlüsselwort festgelegt werden auf welche Weise ein Parameter übergeben wird. Auf die Benutzung der Parameter-Variable innerhalb der Prozedur hat dies kein Einfluß, aber auf die Rückgabe des Wertes. (Es wird immer der tatsächliche Wert abgebildet, die Referenz ist kein Zeiger also keine Speicheradresse.)
  • Wird keines der beiden Schlüsselwort angegeben, gilt ByRef.
  • Bei ByVal wird eine Typenkonvertierung durchgeführt, bei ByRef müsset die Daten-Typen der Deklaration entsprechen.
  • ByVal hat noch Vorteile, durch das Kopieren werden Daten-Typen konvertiert falls die zu übergebende Variable und der Parameter noch identische Daten-Typen haben. Und ByVal ist im Code schneller als ByRef.
  • Es ist auch möglich bei Calls in DLL-Prozeduren (zB. API-Funktionen) bei der Übergabe ByRef oder ByVal zu erzwingen, in dem das Schlüsselwort im Call eingefügt wird. In normalen Prozeduren geht das allerdings nicht.
TypBeschreibung
ByRef"By Reference" Bedeutet das die Referenz von dem Parameter übergeben wird.
Das bewirkt: wird der Wert einer Variable innerhalb der Prozedur geändert, ändert sich der Wert auch außerhalb der Prozedur. Man kann dies also auch als weitere Rückgabewerte benutzen.
ByVal"By Value" Bedeutet das der Wert des Parameters übergeben wird, beim Übergeben wird der Inhalt des Parameters vor der Übergabe kopiert.
Das bewirkt: wird der Wert einer Variable innerhalb der Prozedur geändert, ändert sich der Wert außerhalb der Prozedur nicht. Auf diese Weise können Werte vor der Veränderung geschützt werden, ohne das sie in der Prozedur zusätzlich kopiert werden müßten. Es können aber nicht alle Daten-Typen ByVal übergeben werden.
ByVal ist im Code schneller als ByRef, außer bei großen Daten-Typen wie zB. String wo das Kopieren dann mehr Zeit benötigt als das übertragen der Reverenz.



Private Sub Main()
  Dim Var1 As Long
 
    Var1 = 0
    Call Test1(Var1) ' Var1 ist 0, bleibt unverändert
    Call Test2(Var1) ' Var1 ist 2, wurde nun verändert
 
End Sub
 
 
Private Sub Test1(ByVal Par1 As Long)
    Par1 = 1
End Sub
 
Private Sub Test2(ByRef Par1 As Long)
    Par1 = 2
End Sub

Statische Werte: Static

  • Lokal deklarierte Variabeln verlieren ihren Wert sobald das Programm die Prozedur verläßt. Dies kann mit dem Schlüsselwort Static verhindert werden, dann behalten Werte auch nach dem verlassen der Prozedur ihre Werte.
  • Static kann bei der Prozedur-Deklaration angegeben werden, dann bleiben alle Variabeln der Prozedur erhalten, oder als Ersatz der Dim Deklaration, dann gilt Static nur für die Deklarierten Variablen.
    Man sollte aber grundsätzlich nicht alle lokalen Variablen als Static deklarieren, sondern nur explizit die welche man benötigt.
  • Das Static Handling ist leider relativ langsam da VB6 diese über den Stack umkopiert, falls man eine Prozedur möglichst schnell Programmieren will, kann man diese Variabeln auch Private deklarieren. Um sicherzustellen das keine Namensüberschneidungen auftreten, kann der Variabelnamen der Prozedurname hinzugefügt werden (zB. Prozedurname_Variabelnamen).


'-------- Deklaration
Private Var1 As Long   ' Private und Public Deklarationen erhalten ihre Werte während des ganzen Programmlaufs.
 
 
'-------- Code
Private Sub Main()
 
    Call Test1()
    Call Test1()
    Call Test1()
 
'------------------------
'Das Resultat lautet:
'Var1, Var2, Var3  ' Var1 ist Private, Var2 Local-Static, Var3 Local
'0,    0,    0
'10,   10,   0     ' erster Call Test1(), Var1 und Var2 haben ihre Werte auch nach dem verlassen der Prozedur beibehalten, Var3 nicht.
'20,   20,   0
'30,   30,   0
'------------------------
End Sub
 
 
Private Sub Test1()
  Static Var2 As Long   ' Var2 bleibt nach dem verlassen der Prozedur erhalten
  Dim Var3 As Long
 
    Var1 = Var1 + 10
    Var2 = Var2 + 10
    Var3 = Var3 + 10
 
    Debug.Print Var1, Var2, Var3
 
End Sub

Parameter: Optional

  • Es ist möglich Parameter als Optional zu deklarieren, das bedeutet das man beim Call diese Parameter nicht angeben muß. Und man kann zusätzlich ein Standard Wert angeben der dann verwendet wird wenn kein Parameter übergeben wurde.
  • Nach dem ersten optionalen Parameter müssen auch alle folgenden optional sein.


Private Sub Main()
 
    Call Test1(1, 2, 3)
 
    Call Test1(1)                  ' Hier werden Parameter weggelassen
    '{... Call Test1(1, 200, 300)  ' eigentlich wird es so interpretiert}
 
    Call Test1(1, ,3)              ' Hier werden Parameter weggelassen
    '{... Call Test1(1, 200, 3)    ' eigentlich wird es so interpretiert}
 
End Sub
 
 
Private Sub Test1(ByVal Par1 As Long, Optional ByVal Par2 As Long = 200, Optional ByVal Par3 As Long = 300)
    '{... Code}
End Sub

ParamArray()

  • Will man eine beliebige Anzahl an Optionalen Parametern ermöglichen kann man dies über das Schlüsselwort ParamArray.
  • Alle Parameter werden dann als ein Array vom Daten-Typ Variant interpretiert, das heißt das auch beliebige Werte und Texte gemischt als Parameter übergeben werden können.
  • Nach ParamArray sind keine weiteren Parameter erlaubt, ParamArray muß immer der letzte Parameter sein.


Private Sub Main()
 
    Call Test1(1, 2, 30, "4", 5.5)
 
'------------------------
'Das Resultat lautet:
'2      ' Variant-Untertyp: Ganzzahl
'30     ' Variant-Untertyp: Ganzzahl
'4      ' Variant-Untertyp: Text
'5.5    ' Variant-Untertyp: Fließpunktzahl
'------------------------
End Sub
 
 
Private Sub Test1(ByVal Par1 As Long, ParamArray ParList())
  Dim Pos1 As Long
 
    For Pos1 = LBound(ParList) To UBound(ParList)
      Debug.Print ParList(Pos1)
    Next lLoop
 
End Sub

Rekursion (und Stack)

  • Es ist möglich, das Prozeduren auch sich selber aufrufen können, dies wird Rekursiver Aufruf genannt.
  • Bestimmte Aufgaben lassen sich durch Rekursive Algorithmen besser lösen also durch iterative Algorithmen (Schleifen). zB. Aufgaben die mit der Behandlung von Baum-Strukturen zutun haben, wie das durchsuchen eines Verzeichnisses oder eines Datenbaums.
  • Bei Rekursiven Prozeduren muß aber folgendes beachtet werden.
    • Rekursive Algorithmen die eigentlich auch problemlos über iterative gelöst werden könnten sind langsamer, dann sollte auf Rekursion verzichtet werden. Es sollten nur die Algorithmen rekursiv gelöst werden bei deren dies auch Sinn macht.
    • Jeder rekursive Aufruf schreibt Werte in den sogenannten Stack (Siehe: Stack). Dieser Speicherbereich ist aber Begrenzt und wird auch für andere Programmaufgaben benutzt, zB. bei der Übergabe von Parametern oder bei der Deklaration von lokalen Variablen. Werden zu viele Rekursionen erzeugt besteht die Gefahr eines Stack-Überlaufs, was ein harter Absturz des Programms zur folge hat. Dies muß bei der Entwicklung solcher rekursiven Prozeduren beachtet werden.


' Ein Beispiel einer Fakultätsberechnung
' Fakultätsberechnung ist ein Algorithmen der besser über Iteration gelöst wird.
 
Private Function TestIteration(ByVal Factorial As Long) As Long
  Dim Temp1 As Long
 
    Temp1 = 1
    Do While Factorial > 1
      Temp1 = Temp1 * Factorial
      Factorial = Factorial - 1
    Loop
 
  TestIteration = Temp1
End Function
 
 
Private Function TestRekursion(ByVal Factorial As Long) As Long
    If Factorial = 0 Then
      TestRekursion = 1
    Else
      TestRekursion = Factorial * TestRekursion(Factorial - 1) ' hier ruft sich die Funktion selbst auf
    End If
End Function

Code-Sprung: GoTo

  • Mit GoTo kann an eine bestimmte Sprungmarke gesprungen werden, und der Code wird an dieser Stelle vorgesetzt.
  • Die Sprungmarker müssen mit einem ":" Doppelpunkt abgeschlossen werden, und dürfen nicht mehrfach in einer Prozedur deklariert werden.
  • Sprünge sind nur innerhalb einer Prozedur möglich.
  • Sprünge haben aber die Eigenschaft Unstrukturierten Code (sogenannten Spaghetti-Code) zu erzeugen, da sich Sprünge nicht an die übliche Blockstruktur der anderen Funktionen halten. Alle Codes die sich in logische Blöcken strukturieren lassen, sollten auch so programmiert werden. Im Normalfall sollten Sprünge nicht verwendet werden, da sonst schnell die Logik in einem Code kaum noch verstanden werden kann. Codes mit Block-Strukturen können als Codebaum abgebildet werden, GoTo-Strukturen nur als Flußdiagramm.

    Es gibt aber einige Einzelfälle in welchen GoTo Sinn macht.
    • Herausspringen aus dem Code nach einem Fehler der die Prozedurausführung abbricht. (Kein Try, Catch in VB6)
    • Ans Ende einer Schleife springen. (Kein Continue in VB6)
    • Herausspringen aus mehrfach verschachtelten Schleifen.
    • In speziellen Algorithmen die sich nicht sinnvoll in Blöcke auflösen lassen.


'---- Hier macht ein GoTo Sinn
 
'-- Fehlerbehandlung
 
Private Sub Test1()
 
    '{... Code}
    '{... eine Anweisung die ein Fehlercode zurückgeben kann}
    If FehlerCode <> 0 Then GoTo FehlerHandling
    '{... Code Fortsetzung}
 
 
'-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
CodeOK:
    '{... OK}
 
 GoTo ProzedurEnde:
FehlerHandling:
    '{... Fehler Behandlung}
 
ProzedurEnde:
    '{... Code der auf jeden fall vor dem Verlassen der Prozedur noch ausgeführt werden soll (zB. schließen von vielleicht noch offenen Dateien).}
 
End Sub
 
 
 
'-- Continue
 
    For Pos1 = 1 To 1000
      '{... Code}
      If Bedingung Then GoTo Continue1      ' Sofortiges Ausführen des nächsten Schleifendurchlaufs
      '{... Code}
 
Continue1:
    Next
 
 
 
'-- Verschachtelte Schleifen
 
    For Pos1 = 1 To 1000
     For Pos2 = 1 To 1000
      For Pos3 = 1 To 1000
        '{... Code}
        If Bedingung Then GoTo SprungMarke1
        '{... Code}
      Next
     Next
    Next
SprungMarke1:

Verzweigung: If-Then-ElseIf-Else

  • Ein Logischer Baustein jedes Programms sind Verzweigungen, die nach einer Bedingung entschieden wo das Programm fortgesetzt wird. Die Reaktion ist das entweder das Programm unverändert Fortgesetzt wird oder das an die nächste Blockposition oder an das Blockende gesprungen wird.


    If Bedingung Then Var1 = BedingungIstWahr Else Var1 = Sonst
 
 
    If Var1 = 1 Then
      '{... Bedingung ist Wahr}
    End If
      '{... Bedingung ist Falsch}
 
 
    If Var1 = 0 Then
      '{... Bedingung ist Wahr}
    ElseIf Var1 <= 2 Then
      '{... Sonst, diese Bedingung ist Wahr}
    ElseIf Var1 => 2 Then
      '{... Sonst, diese Bedingung ist Wahr}
    Else
      '{... Sonst}
    End If

Verzweigungs-Block: Select-Case

  • Man kann eine Verzweigung mit immer der gleichen Vergleichsvariable auch über ein Select-Case Block vereinfachen.
  • Es können ein Wert, mehrere Werte, Ein Wehrbereich, Ein Vergleich oder auch eine Nichterfüllung und ein Else verwendet werden um die deklarierte Variable zu prüfen.
  • Case Else muß als letztes verwendet werden.


    Select Case Var1
     Case 1                            ' ein Wert
       '{... Code wenn Var1 = 1}
     Case 2                            ' ein Wert
       '{... Code wenn Var1 = 2}
     Case Else                         ' sonst
       '{... Code sonst}
    End Select
 
 
    Select Case Var1
     Case 1                            ' ein Wert
     Case 2, 4, 6                      ' mehrere Werte
     Case 10 To 20                     ' ein Bereich
     Case 21, 22, 24 To 26             ' Kombinationen
     Case 30 To 40, 50 To 60           ' Kombinationen
     Case Is < 70                      ' Vergleich
     Case Is <> 80, 81, 82, 84 To 86   ' Kombinationen
     Case Not 91, 92, 90 To 100        ' Bedingungen nicht erfüllend, Kombinationen
     Case Else                         ' sonst
    End Select

Auswahl

IIf: über Wahrheitswert

  • IIf ist eine vereinfachte If Anweisung, die abhängig von einem Wahrheitswert einen von zwei Werten zurück gibt.
  • Wichtig ist zu beachten, das Visualbasic leider unabhängig von der Bedingung immer beide möglichen Rückgabewerte auswertet. Das kann langsam sein und zu Fehlern führen wenn zB ein Division durch Null auftreten kann, obwohl dies nur bei einer Bedingung auftreten würde. Ist also mehr erforderlich als die Rückgabe von zwei Werten, sollte besser If verwendet werden.


    Var1 = IIf(Bedingung, IstWahr, IstFalsch)

Switch: über Bedingungen

  • Switch ist eine vereinfachte If Anweisung mit mehreren ElseIf Bedingungen, die abhängig von einem Wahrheitswert den ersten passenden Werten zurück gibt.
  • Die Bedingungen und dazugehörigen Rückgabewerte müssen paarweise angegeben werden, andernfalls tritt ein Laufzeitfehler auf.
  • Nur das erste Bedingung-Rückgabewert Paar muß angegeben werden, danach können beliebig viele weitere Paare folgen.
  • Ist keine Bedingung True, wird Null zurückgegeben.
  • Wichtig ist zu beachten, das Visualbasic leider unabhängig von den Bedingungen immer alle möglichen Rückgabewerte auswertet. Das kann langsam sein und zu Fehlern führen wenn zB ein Division durch Null auftreten kann, obwohl dies nur bei einer Bedingung auftreten würde. Ist also mehr erforderlich als die Rückgabe von einzelnen Werten, sollte besser If verwendet werden.


    Var1 = Switch(Bedingung1, IstWahr1, Bedingung2, IstWahr2, Bedingung3, IstWahr3)

Choose: über Index

  • Choose ist eine vereinfachte Select Case Anweisung, die abhängig von einem Index einen Wert aus einer Liste von Werten zurück.
  • Nur der erste Rückgabewert muß angegeben werden, danach können beliebig viele weitere Rückgabewerte folgen.
  • Der erste mögliche Indexwert beginnt mit 1.
  • Ist der Index kleiner 1 oder größer als die Anzahl möglicher Rückgabewerte, wird Null zurückgegeben.
  • Ist der Index keine ganze Zahl, wird er auf die nächste ganze Zahl gerundet.
  • Wichtig ist zu beachten, das Visualbasic leider unabhängig vom Index immer alle möglichen Rückgabewerte auswertet. Das kann langsam sein und zu Fehlern führen wenn zB ein Division durch Null auftreten kann, obwohl dies nur bei einem Indexwert auftreten würde. Ist also mehr erforderlich als die Rückgabe von einzelnen Werten, sollte besser Select Case verwendet werden.


    Var1 = Choose(Index, Ist1, Ist2, Ist3)

Schleifen: For-Next, Do-Loop

  • Für wiederholende Prozesse gibt es Schleifen welche ein Codestück solange wiederholen können bis eine bestimmte Bedingung erfüllt ist.
  • Um aus einer Schleife wird das Schlüsselwort Exit verwendet.
  • Eine Funktion um eine Schleife sofort zu wiederholen (Continue) gibt es leider nicht.

For-Next: Zähler-Schleife

Über For-Next können eine bestimmte Anzahl von Durchläufen in einem Code wiederholt werden, wobei der Zähler an eine Variable übergeben wird.

  • Der erste Wert der Schleife deklariert den Wert mit der die Zählung beginnt und der zweite Wert deklariert das Ende oder Abbruchbedingung.
  • Die Schrittweite ist immer 1, diesen Wert kann man aber über das Schlüsselwort Step verändern und zB. auch rückwärts Zählen. Beim Rückwärts zählen muß natürlich der erste Wert größer sein als der zweite.
  • Es ist möglich die For-Zählervariable auch innerhalb der Schleife zu verändern. Dabei muß aber beachtet werden das nicht eine Endlos-Schleife entsteht, aus der sich der Code nie wieder befreien kann, da das Ende des Zählers nie erreicht wird.
  • Es muß darauf geachtet werden das eine For-Schleife ein Überlauf erzeigen kann, wenn bis an die Grenze des Daten-Typs gezählt wird, da am Ende der Schleife der Zähler immer +1 (oder der Step Wert) größer ist als die Obergrenze. Ist der Zähler also als Byte deklariert, kann nicht bis 255 gezählt werden, da beim verlassen der Schleife eigentlich 256 tragen sollte und dies bei einem Byte ein Überlauf-Fehler verursacht.


    For Pos1 = 1 To 4
      '{... irgend ein Code (Pos1 zählt bei jedem Durchlauf: 1, 2, 3, 4)}
      Exit For  ' Hier wird die Schleife abgebrochen, Pos1 verändert sein Wert nicht mehr
    Next
 
    For Pos1 = 1 To 4 Step 2
      '{... irgend ein Code (Pos1 zählt bei jedem Durchlauf: 1, 3)}
    Next
 
    For Pos1 = 4 To 1 Step -1
      '{... irgend ein Code (Pos1 zählt bei jedem Durchlauf: 4, 3, 2, 1)}
    Next

For-Each

  • For Each ist eine Spezielle Variante der For-Schleife, über welche man die Möglichkeit hat sich durch eine Liste von Elementen zu arbeiten.
  • Diese For-Variante durchläuft die ganze Liste vom ersten bis zum letzen Element, ein Bereich anzugeben ist nicht möglich.
  • Die For-Each Schleife benutzt nicht wie die normale For Schleife das Ende als Abbruchs-Kriterium, sie Springt von jedem Element zum nächsten, und somit wird die Schleife dann beendet, wenn das letzte Element durchlaufen ist. Ändert sich in der Liste die Elemente durch Löschen oder Einfügen wird dennoch die Schleife bis zum letzen Element durchlaufen.
    • Dabei ist zu beachten, das wenn in der Schleife zB. ein Collection-Objekt durchläuft, und in jedem durchlauf neue Elemente vor dem gerade aktuellen Element hinzugefügt werden, die Schleife nicht mehr beendet wird da in jedem durch lauf wieder ein neues hinzukommt das in For-Each auch durchlaufen wird. In einer normalen For-Schleife über .Count passiert dies nicht, da der For-Endwert nicht neu gelesen wird, sonder so bleibt wie er beim Beginn der Schleife war.


'Liste:   ist eine Liste von Objekten ein Collection oder ein Array
'Element: ist die Variable welche das Element aus der Liste trägt,
'         Element muß entweder vom gleichen Daten-Typ wie die Elemente in der Liste sein oder vom Daten-Typ Variant
 
    For Each Element In Liste
      '{... Code}
      Exit For      ' Hier wird die Schleife abgebrochen
    Next
 
 
'--- Dieses Beispiel durchläuft alle Control-Elemente zB. in einem Formular
  Dim Obj1 As Control
 
    For Each Obj1 In Me.Controls
      '{... Obj1 enthält in jedem Durchlauf das nächste Element}
      Debug.Print Obj1.Name    ' hier wird der Name des Control-Elementes ausgegeben
    Next

Do-Loop: Bedingungs-Schleife

  • Über Do-Loop kann ein Codeteil solange wiederholt werden bis eine bestimmte Bedingung erfüllt ist.
  • Die Abbruch-Bedingung kann am Schleifen-Beginn oder am -Ende angegeben werden. Aber nicht bei beiden gleichzeitig.
  • Dabei muß beachtet werden das nicht eine Endlos-Schleife entsteht, aus der sich der Code nie wieder befreien kann wenn die Abbruch-Bedingung nie eintreten kann.
  • Über die Schlüsselwörter While wird die Schleife solange aufgeführt wie die Bedingung True ist, und Until solange bis die Bedingung False.
  • Es gibt noch eine Veraltete Schreibweise über die Schlüsselwörter While und WEnd, diese Schleife entspricht Do While und Loop


    'Vergleich am Block-Anfang
    Do While WahrheisWert
      '{... die Schleife wird Solange ausgeführt bis WahrheisWert = False ist}
      Exit Do   ' hier wird die Schleife verlassen
    Loop
 
 
    'Vergleich am Block-Ende
    Do
      '{... die Schleife wird Solange ausgeführt bis WahrheisWert = False ist}
    Loop While WahrheisWert
 
 
    Do Until WahrheisWert
      '{... die Schleife wird Solange ausgeführt bis WahrheisWert = True ist}
    Loop
 
 
    '!!! Am Blockstart und Ende eine Prüfung durchzuführen ist nicht zugelassen
    Do Until WahrheisWert
      '{... Code}
    Loop Until WahrheisWert
 
    '!!! Dies sind Endlosschleifen die nie beendet werden
    Do
      '{... Code}
    Loop
 
    Do While 1 = 1
      '{... Code}
    Loop

DoEvents

  • Einige Berechnungen, besonders innerhalb von langen Schleifen können den Prozeßlauf des Programms blockieren und die gesamte Rechenleistung für sich in Anspruch nehmen. Es kann dann so aussehen als ob das Programm Stecken geblieben ist. Leider existiert keine saubere Prozeß(Tread)-Kontrolle die das verhindert. Um dem System Zeit zu geben andere Aufgaben zu erledigen oder auch die Anzeige des Programms selbst zu erneuern, kann mit DoEvents der Prozeßlauf für ein Moment an das System abgegeben werden. In langen Berechnungen, zB. Schleifen mit einer langen Laufzeit sollte also DoEnevts eingesetzt werden damit das System Rechenzeit für andere Aufgaben erhält.
  • Es wird ebenfalls eine Neudarstellung (Repaint) durchgeführt und so die Formularanzeige erneuert (bei zeitaufwendigen Berechnungen bleibt die Anzeige in einem Formular stecken da sie nicht erneuert wird).
  • Da DoEnevts sehr zeitaufwendig ist, kann zB. über ein Zähler oder besser Timer der Aufruf begrenzt werden damit dem Programm nicht zuviel Rechenzeit verloren geht. (oder noch besser da Timer ebenfalls langsam ist, mit der API-Funktion GetTickCount.)


    ' DoEvents über Zähler, ist schnell geprüft aber je nachdem wie schnell ein System ist, ist ein Zähler zu ungenau.
    For Pos1 = 1 To 1000000
      '{... irgend ein Code}
      If Pos1 Mod 256 Then DoEvents   ' Alle 256 Durchläufe wird dem System Rechenzeit abgegeben
    Next
 
 
    ' DoEvents über Timer, ist Exakter da eine Zeitperiode angegeben werden kann.
    ' (Auch Timer ist eine relativ langsame Funktion, über die API-Funktion GetTickCount kann das beschleunigt werden.)
    Dim TimerAlt As Single
    For Pos1 = 1 To 1000000
      '{... irgend ein Code}
 
      If (Timer - TimerAlt) => 0.1 Then
        DoEvents   ' alle 100 Millisekunden wird dem System Rechenzeit abgegeben
        TimerAlt = Timer
      End If
    Next

Fehler-Handling: On Error

  • Ist kein Fehlerabfang deklariert, wird jeder Fehler zu einem Absturz des Programms führen.
  • Der Fehlerabfang On Error erlaubt ein GoTo Ereignis auszulösen oder ein Fehler zu übergehen und ihn entweder ganz zu ignorieren oder über ein Fehlercode zu behandeln.
  • Über Err können diverse Informationen über den Fehler verwendet werden um entsprechend reagieren zu können.
  • Fehler werden immer in der Prozedur abgefangen auf der ein Fehlerhandling als erstes deklariert wurde. Ist also in der Prozedur selbst kein Fehlerhandling aktiv, wird die aufrufende Prozedur den Fehler abfangen falls eine vorhanden ist, usw. Ein Fehler Fehlerabfang in der Main Prozedur kann also zB. noch Datensicherungen vornehmen bevor das Programm sich selbst beendet.
  • In der Praxis ist es sinnvoll überall da wo Fehler auftreten können (zB. wenn eine Datei nicht existiert auf die zugegriffen werden soll), es ist aber nicht sinnvoll in allen Routinen Fehler einfach zu unterdrücken, da dann Programmierfehler nicht erkannt werden. Es macht aber Sinn Funktionen zu schützen die für den Programmlauf nicht wichtig sind, wie zB. Zeitanzeigen oder ähnliches. Findet in einer solchen Funktion zB. eine "Division durch Null" statt, funktioniert nur ein unwichtiger Teil des Programms nicht richtig und verursacht dennoch keinen harten Absturz und möglichen Datenverlust. Solche Fehlerhandlings können auch über eine Compileranweisung (#Const, #If) während der Entwicklung ausgeschaltet werden damit mögliche Fehler während der Entwicklung sichtbar bleiben.
  • Über Error können auch selbst definierte Fehler ausgelöst werden.


' Fehler Abfangen
On Error Goto SprungMarke1   ' Tritt ein Fehler auf springt das Programm auf SprungMarke1
On Error Resume Next         ' das Programm wird fortgesetzt
On Error Goto 0              ' der Fehlerabfang wird ausgeschaltet
 
 
' Fehler auslösen
    Error 10000                  ' Es wird ein Fehler ausgelöst mit dem Code 10000
 
    Dim Var1 As Single
    Var1 = 1 / 0                 ' Division durch 0
 
 
' Fehlerhandling Reaktionen
SprungMarke1:
    Select Case Err.Number      ' "Err" ist ein Objekt das Informationen über den letzten aufgetretenen Fehler enthält
     Case 10000
       '{... Code und weitere FehlerCodes}
     Case Else
       '{... Unbekannter Fehler}
    End Select

Adressierung und Zeiger: VarPtr, StrPtr, ObjPtr

  • Obwohl Zeiger in VB6 nicht unterstützt werden kann dennoch auf die Speicheradresse von Daten abgefragt werden.
  • Man kann auf diese Weise zB. feststellen ob zwei ByRef übergebene Parameter die gleichen Variable darstellen, wenn sie beide auf die gleiche Adresse zeigen.
  • Einige Parameter der WinAPI-Funktionen erwarten eine Adresse.


' Hier kann festgestellt werden ob es sich bei Par1 und Par2 um die gleiche Variable handelt.
 
Private Sub Main()
  Dim Var1 As Long
  Dim Var2 As Long
 
    Call Test1(Var1, Var1)
    Call Test1(Var1, Var2)
 
End Sub
 
 
Private Sub Test1(ByRef Par1 As Long, ByRef Par2 As Long)
    If VarPtr(Par1) = VarPtr(Par2) Then
      Debug.Print "Par1 und Par2 sind identisch"
    Else
      Debug.Print "Par1 und Par2 sind nicht identisch"
    End If
End Sub

DLL und Windows API Call: Declare

  • Es ist möglich DLL Dateien einzubinden, die verfügbaren Prozeduren und Konstanten¦Strukturen müssen dazu deklariert werden. Die Deklaration von Prozeduren erfolgt über Declare.
  • Eine Deklarierte Prozedur kann dann genauso verwendet werden wie eine normale Prozedur auch.
  • Da der Funktionsumfang sehr eingeschränkt ist und auch viele Funktionen des Betriebssystem nicht erreichbar sind, können diese über API-Deklarationen zugänglich gemacht werden.



  • Da man es aber beim API mit einer C-Umgebung zutun hat müssen einige Dinge in der Kommunikation mit VB<>C beachtet werden.
    • ! Es muß bei Strings unbedingt darauf geachtet werden ob sie Unicode oder ASCII formatiert sein müssen.
    • ! Es muß bei Parametern unbedingt darauf geachtet werden ob ein Wert oder ein Zeiger erwartet wird.
    • Strings müssen mit 0 abgeschlossen sein (das sind sie in VB automatisch) und bei Binären Strings muß die String-Länge zusätzlich übergeben werden. (Da C Strings ohne Länge speichern und in einem binären String auch 0 enthalten sein kann, ist es nicht möglich zu erkennen wann der String endet.)



  • Proc1 Ist der Platzhalter für den Namen welcher im Code verwendet wird, es kann ein beliebiger Name angegeben werden, sinnvoll ist aber der Original-Name.
  • Lib "name.dll Bezeichnet die Bibliotheks-Datei in welcher sich die Prozedur befindet.
    • Wird kein Pfad angegeben wird die Datei automatisch gesucht: Programm-Verzeichnis -> aktuelles Verzeichnis -> System-Verzeichnis -> Windows-Verzeichnis -> Verzeichnisse aus er "Path"-Umgebungsvariable.
  • Alias "Proc1A Enthält den tatsächlichen Namen in der Bibliotheks-Datei, und muß angegeben werden wenn er sich vom Dekorierten Namen unterschiedet. (Im Windows-API wurden die neuen 32-Bit Funktionen mit einem A am Ende des Namens erweitert um sie von den alten 16-Bit Funktionen zu unterscheiden.)


Eine Windows-API Funktionssammlung gibt es im Windows-API Bereich. Hier ist ein Windows-API Beispiel: File_Open

'-------- Deklaration
 
Declare Sub Proc1 Lib "name.dll" Alias "Proc2A" (ByRef Par1 As Long)
 
Declare Function Proc2 Lib "name.dll" Alias "Proc1A" (ByVal Par1 As Long) As Long
 
 
'-------- Code
 
    Call Proc1(10)
    Call Proc1(ByVal 10)   ' Hier wird die Übergabe mit "ByVal" erreicht
 
    Var1 = Proc2(10)

Optimierung des Codes

  • Der Ausführungsgeschwindigkeit des Codes kann optimiert werden wenn der Programmierer bestimmte Eigenschaften berücksichtigt.

Compiler Optimierung

  • Programme sollten nicht als P-Code (Primitiv Code) sondern als System-Code (Native Code) compiliert werden, da P-Code kein echter Maschinen Code darstellt sonder nur Interpretiert wird.
  • Die Option "Code- Ausführungsgeschwindigkeit optimieren" auswählen.
  • (Die anderen Optimierungen sollten im Normalfall besser nicht eingeschaltet werden da sie die Codeausführung erheblich beeinflussen können.)

Mathematische Optimierung

  • Variant¦Obiect ist sehr langsam und sollte grundsätzlich nur dann verwendet werden wenn wirklich Variante Informationen bearbeitet werden müssen. (Zudem unterlaufen Variante Typen de Typensicherheit.)
  • Konstanten verwenden statt Variablen wenn keine variablen Werte verwendet werden (nur einmal zugewiesen wird).
  • Long ist in einer 32Bit Umgebung am schnellsten, Single ist in bei Fließpunkt Daten-Typen am schnellsten.
  • Ganzzahlen verwenden wenn keine Fließpunkt Zahlen benötigt werden.
  • Boolean enthält zwar ein abgesicherten Wahrheitswert der nur 0 oder -1 sein kann, Integer/Long ist aber schneller.
  • VB optimiert X ^ 2, nicht selbst zu X * X, Potenzen sind sehr langsam. Grundsätzlich gilt das Mathematische Operationen höher Ordnung langsamer sind als die niederen. Weitere Optimierungen können hier gefunden werden. Arithmetische Optimierung
  • Wird Division ohne Rundung durchgeführt, ist eine Ganzzahl Division (\ statt /) schneller.
  • Es sollten möglichst in einer Berechnung nur gleiche Daten-Typen verwendet werden, damit keine Konvertierung durchgeführt werden müssen (also zB. Integer und Long oder Single und Double nicht mischen.). Um so mehr sollte man keine Ganzzahlen mit Fließpunktzahlen mischen.
  • Die Trigonometrischen Funktionen Sin¦Cos¦Tan¦ATan sind langsam. Falls geometrische Operationen über Kreuz¦Punkt-Produkt Berechnungen beschleunigt werden können, kann auf die Trigonometrischen Funktionen verzichtet werden. Auch Kann oft auf Sqr() verzichtet werden, wenn die Berechnungen in den Potenzen gehalten werden können.

Struktur Optimierung

  • Keine Variabeln innerhalb von Schleifen plazieren die mit einem unveränderlichen Wert beschrieben werden.
  • Werden Berechnungen in einer Formel mehrfach ausgeführt, sollten diese in einer weiteren Variable berechnet werden und dann die Variable verwendet werden.
  • Werden Informationen aus Quellen bezogen auf welche der Zugriff langsamer ist (zB aus einem Array) und diese mehrfach in Berechnungen verwendet, sollten die Werte in einer temporären Standard-Variable zwischengespechert und diese zur Berechnung verwendet werden.
  • Da VB kein Inlining unterstützt kann in bestimmten fällen in welcher sehr kurze Codes in Prozeduren liegen und diese in einer schleife sehr häufig aufgerufen werden, diese direkt in den Code eingegeben werden.
  • Call Aufrufe in Klassen sind langsamer als in Module, falls auf Klassen verzichtet werden kann, sind Module in der Ausführung schneller.
  • Bei normalen Daten-Typen sind ByVal aufrufe schneller als ByRef, und sollten auch deshalb bevorzugt werden um die übergebenen Variabeln vor Veränderungen in der aufgerufenen Prozedur zu schützen. ByRef sollte nur dann verwendet werden wenn die Parameter als Rückgabe-Parameter verwendet werden. Es sei den es handelt sich um String, dann dauert der Kopiervorgang lange. Oder bei Daten-Typen die nicht ByVal übergeben werden können.
  • Static ist langsamer als eine Private Variable. (Sie werden in VB über den Stack umkopiert statt abgesichert Private deklariert.)
  • For-Each-Next ist in der Regel schneller als die normale For-Next Schleife beim Zugriff auf Objekte.

Klassen

Auf dieser Seite: Schnell-Kurs_Klassen

Weitere Informationen

Boolean Operationen

I OANDORXOREQUIMP
0,000011
0,101101
1,001100
1,111011

Werte Rundung

9.19.59.9-9.1-9.5-9.9
Fix999-9-9-9
Int999-10-10-10
CInt91010-9-10-10
Round91010-9-10-10
\191010-9-10-10

Geschwindigkeitsvergleiche

VarDaten-Typen
BBoolean
IInteger
LLong
FSingle
DDouble
CCurrency
VVariant



BerechnungFaktor
Long
L = 31.1
L = L2 + 30.7
L = L2 * 31.0
L = L2 / 319.1
L = L2 \ 31.1
L = Sqr(L2)25.2
L = L2 ^ 3100.6
L = L2 Mod 35.7
L = L2 Xor 30.6
Double
D = 33.7
D = D2 + 35.1
D = D2 * 35.5
D = D2 / 311.2
D = D2 \ 311.1
D = Sqr(D2)17.4
D = D2 ^ 296.9
D = D2 Mod 317.3
Trigonometrie
D = Sin(PI03D)24.1
D = Cos(PI03D)22.9
D = Tan(PI03D)36.3
D = Atn(PI03D)30.8
D = Log(PI03D)24.4
D = Exp(PI03D)78.0
D = Rnd(1)79.3
Variabel-Typen
B = 2: B = B * 3 + 35.8
I = 2: I = I * 3 + 31.7
L = 2: L = L * 3 + 31.6
F = 2: F = F * 3 + 34.9
D = 2: D = D * 3 + 36.7
C = 2: C = C * 3 + 315.9
V = 2: V = V * 3 + 331.2
Diverse
If L2 And L Then: L = 00.7
L = UBound(DimL)3.5
DoEvents485.7

Datei-Typen

Hier eine Liste aller VB Datei-Typen.

Wichtigste Entwurfszeit-Dateien

TypeDatei-Type
BASBasis-Modul
CLSKlassen-Modul
FRMFormular-Datei
FRXFormular-Datei, Binärdaten
CTLBenutzerdefinierte Steuerelemente
CTXBenutzerdefinierte Steuerelemente, Binärdaten
RESRessourcen-Datei
VBPVisualBasic Projekt-Datei
VBGVisualBasic Gruppen Projekt-Datei

Weitere Entwurfszeit-Dateien

TypeDatei-Type
DCAActive-Designer-Cache
DDFCAB-Informations-Datei des Paket und Weitergabe-Assistenten
DEPAbhängigkeits-Datei des Paket und Weitergabe-Assistenten
DOBFormular-Datei für ActiveX-Dokument
DOXFormular-Datei für ActiveX-Dokument, Binärdaten
DSRActive-Designer
DSXActive-Designer, Binärdaten
DWSSkript-Datei des Weitergabe-Assistenten
LOGProtokoll-Datei für Ladefehler
PAGEigenschaftenseite
PGXEigenschaftenseite, Binärdaten
TLBTypeLib-Datei RemAuto
OCATypeLib-Steuerelement Cache-Datei
VBLLizenzüberwachungs-Datei
VBRRemAuto-Registrierungs-Datei
VBZDatei zum Starten des Assistenten
VBWVisualBasic Projekt Arbeitsbereichs-Datei
WCTWebClass-HTML-Vorlage

Laufzeit-Dateien

TypeDatei-Type
EXEAusführbare Datei oder ActiveX-Komponente
DLLProzeßinterne ActiveX-Komponente
OCXActiveX-Steuerelement
VBDStatus-Datei für ActiveX-Dokument
WCTWebClass HTML Template

Projekt-Eigenschaften

WRITEME


Visual-Basic/Schnell-Kurs.txt · Zuletzt geändert: 2010/08/20 17:48 von Runtime-Basic