| 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. 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.)
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.
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 = 2Einige 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
' Das ist ein Kommentar
' Var1 = 1 ' diese Zeile ist deaktiviert
Var1 = 1Alle 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.}
'-------- Deklaration
Option Explicit 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 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).
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
NextUm 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 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Ü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
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 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-Typ | PostFix | PräFix | Konv | vb-Name | Größe in Byte | Minimum | Maximum | Info |
|---|
| Byte | | byt | CByte | vbByte | 1 | 0 | 255 | Ganzzahl ohne Vorzeichen | | - | | | | | 1 | -128 | 127 | Ganzzahl mit Vorzeichen | | - | | | | | 2 | 0 | 65536 | Ganzzahl ohne Vorzeichen | | Integer | % | int | CInt | vbInteger | 2 | -32'768 | 32'767 | Ganzzahl mit Vorzeichen | | - | | | | | 4 | 0 | 4'294'967'295 | Ganzzahl ohne Vorzeichen | | Long | & | lng | CLng | vbLong | 4 | -2'147'483'648 | 2'147'483'647 | Ganzzahl mit Vorzeichen | | Single | ! | sng | CSng | vbSingle | 4 | -3.402823E+38 -1.401298E-45 | 3.402823E+38 1.401298E-45 | Gleitkommazahl | | Double | # | dbl | CDbl | vbDouble | 8 | -1.79769313486232E+308 -4.94065645841247E-324 | 1.79769313486232E+308 4.94065645841247E-324 | Gleitkommazahl | | | | | | | | | |
|---|
| Boolean | | bln | CBool | vbBoolean | 2 | False (0) | True (-1) | Wahrheitswert | | Currency | @ | | CCur | vbDecimal | 8 | -922'337'203'685'477.5808 | 922'337'203'685'477.5807 | Ganzzahl skaliert kleinste Zahl ungleich Null ist +/-0.0001 | | Decimal | | cur | CDec | vbCurrency | 14 | -79'228'162'514'264'337'593'543'950'335 | +79'228'162'514'264'337'593'543'950'335 | Gleitkommazahl | | String (variable Länge) | $ | str | CStr | vbString | 10 +Länge | Länge: 0 | Länge: 2'147'483'647 | Zeichenkette Unicode | | String (feste Länge) | $ | str | CStr | vbString | Länge | Länge: 1 | Länge: 65'536 | Zeichenkette Unicode | | | | | | | | | |
|---|
| Variant (mit Zahlen) | | vnt | CVar | vbVariant | 16 | | | Numerische Werte im Bereich des Datentyps Double | | Variant (mit Zeichen) | | vnt | CVar | vbVariant | 22 +Länge | | | Wie bei String mit variabler Länge | | Object | | obj | | vbObject | 4 | - | - | Beliebiger Verweis auf ein Objekt vom Typ Object | | Date | | dtm | CDate | vbDate | 8 | 1. Januar 100 | Dezember 9999 | Zeit | | Error | | err | CVErr | vbError | | - | - | | | | | | | | | | |
|---|
| Type | | udt | | vbUserDefinedType | Summe Elemente | - | - | Daten-Struktur Benutzerdefiniert | | | | | | | | | |
|---|
| (Datenfeld) | | | | vbArray | | Elemente: 0 | Elemente: 2'147'483'647 | Array, Datenfeld | | (Datenzugriffsobjekt) | | | | vbDataObject | | | | Datenzugriffsobjekt | | (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.| Typ | Beschreibung |
|---|
| Unsigned | Ohne Vorzeichen, nur 0 und positive Zahlen (zB. Byte -> 0 bis 255) | | Signet | Mit Vorzeichen, also auch negative Zahlen (zB. Integer -> -32'768 bis 32'767) |
Var1 = 100 ' Dezimal
Var1 = &H64 ' Hexadezimal
Var1 = &O144 ' Oktal
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.000000000000000000123456789Variant 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. 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.
Variant kann auch "Nichts" enthalten.
| Konstante | Wert | Beschreibung |
|---|
| vbEmpty | 0 | Nicht initialisiert (Voreinstellung), es wurde nichts übergeben, oder mit Nothing Zuweisung gelöscht | | vbNull | 1 | Enthält keine gültigen Daten, wurde mit Null Zuweisung | | vbError | 10 | Fehler, in einer Berechnung oder Verarbeitung ist ein Fehler aufgetreten, oder wurde mit CVErr() zugewiesen | | | | | vbByte | 17 | Daten-Typ Byte | | vbInteger | 2 | Daten-Typ Integer | | vbLong | 3 | Daten-Typ Long | | vbSingle | 4 | Daten-Typ Single | | vbDouble | 5 | Daten-Typ Double | | vbBoolean | 11 | Daten-Typ Boolean | | vbCurrency | 6 | Daten-Typ Currency | | vbString | 8 | Daten-Typ Typ String | | | | | vbArray | 8192 | Datenfeld | | vbObject | 9 | Objekt | | vbVariant | 12 | Wert vom Typ Variant (angewendet nur bei Datenfeldern mit Variant-Werten) | | vbDate | 7 | Daten-Typ Typ Date | | vbDataObject | 13 | Datenzugriffs-Objekt | | vbDecimal | 14 | Daten-Typ Typ Decimal (nur als Untertyp von Variant verwendbar) | | vbUserDefinedType | 36 | Werte vom Typ Variant, die benutzerdefinierte Typen enthalten |
| Funktion | True 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. |
| Schlüsselwort | Gültigkeitsbereichen |
|---|
| Public | Im gesamten Projekt | | Private | Innerhalb eines Moduls oder Klasse | | Local | Innerhalb 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
'-------- 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
'-------- 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 + 300Es 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 EnumString 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.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.
| Typ | Beschreibung |
|---|
| Ascii | Das 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. | | Unicode | Ist 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-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 leerEs 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Ü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 WithProzeduren 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.
| Typ | Beschreibung |
|---|
| Sub | Prozedur (Subroutine) ohne Rückgabewerte | | Function | Prozedur (Function) mit Rückgabewerte |
'-------- 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 FunctionEs 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.
| Typ | Beschreibung |
|---|
| 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 SubLokal 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 SubEs 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 SubWill 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 SubEs 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.
' 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 FunctionSprü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:
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 IfMan 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 SelectWichtig 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 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 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) 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.
Ü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)}
NextFor 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Ü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 ü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
NextIst 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 SelectObwohl 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
Da man es aber beim API mit einer C-Umgebung zutun hat müssen einige Dinge in der Kommunikation mit VB<>C beachtet werden.
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)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.)
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.
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.
| I O | AND | OR | XOR | EQU | IMP |
|---|
| 0,0 | 0 | 0 | 0 | 1 | 1 |
|---|
| 0,1 | 0 | 1 | 1 | 0 | 1 |
|---|
| 1,0 | 0 | 1 | 1 | 0 | 0 |
|---|
| 1,1 | 1 | 1 | 0 | 1 | 1 |
|---|
| 9.1 | 9.5 | 9.9 | | -9.1 | -9.5 | -9.9 |
|---|
| Fix | 9 | 9 | 9 | | -9 | -9 | -9 |
|---|
| Int | 9 | 9 | 9 | | -10 | -10 | -10 |
|---|
| CInt | 9 | 10 | 10 | | -9 | -10 | -10 |
|---|
| Round | 9 | 10 | 10 | | -9 | -10 | -10 |
|---|
| \1 | 9 | 10 | 10 | | -9 | -10 | -10 |
|---|
| Var | Daten-Typen |
|---|
| B | Boolean | | I | Integer | | L | Long | | F | Single | | D | Double | | C | Currency | | V | Variant |
| Berechnung | Faktor |
|---|
| | | Long | |
|---|
| L = 3 | 1.1 | | L = L2 + 3 | 0.7 | | L = L2 * 3 | 1.0 | | L = L2 / 3 | 19.1 | | L = L2 \ 3 | 1.1 | | L = Sqr(L2) | 25.2 | | L = L2 ^ 3 | 100.6 | | L = L2 Mod 3 | 5.7 | | L = L2 Xor 3 | 0.6 | | | | Double | |
|---|
| D = 3 | 3.7 | | D = D2 + 3 | 5.1 | | D = D2 * 3 | 5.5 | | D = D2 / 3 | 11.2 | | D = D2 \ 3 | 11.1 | | D = Sqr(D2) | 17.4 | | D = D2 ^ 2 | 96.9 | | D = D2 Mod 3 | 17.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 + 3 | 5.8 | | I = 2: I = I * 3 + 3 | 1.7 | | L = 2: L = L * 3 + 3 | 1.6 | | F = 2: F = F * 3 + 3 | 4.9 | | D = 2: D = D * 3 + 3 | 6.7 | | C = 2: C = C * 3 + 3 | 15.9 | | V = 2: V = V * 3 + 3 | 31.2 | | | | Diverse | |
|---|
| If L2 And L Then: L = 0 | 0.7 | | | | L = UBound(DimL) | 3.5 | | | | DoEvents | 485.7 |
Hier eine Liste aller VB Datei-Typen. | Type | Datei-Type |
|---|
| BAS | Basis-Modul | | CLS | Klassen-Modul | | FRM | Formular-Datei | | FRX | Formular-Datei, Binärdaten | | CTL | Benutzerdefinierte Steuerelemente | | CTX | Benutzerdefinierte Steuerelemente, Binärdaten | | RES | Ressourcen-Datei | | VBP | VisualBasic Projekt-Datei | | VBG | VisualBasic Gruppen Projekt-Datei |
| Type | Datei-Type |
|---|
| DCA | Active-Designer-Cache | | DDF | CAB-Informations-Datei des Paket und Weitergabe-Assistenten | | DEP | Abhängigkeits-Datei des Paket und Weitergabe-Assistenten | | DOB | Formular-Datei für ActiveX-Dokument | | DOX | Formular-Datei für ActiveX-Dokument, Binärdaten | | DSR | Active-Designer | | DSX | Active-Designer, Binärdaten | | DWS | Skript-Datei des Weitergabe-Assistenten | | LOG | Protokoll-Datei für Ladefehler | | PAG | Eigenschaftenseite | | PGX | Eigenschaftenseite, Binärdaten | | TLB | TypeLib-Datei RemAuto | | OCA | TypeLib-Steuerelement Cache-Datei | | VBL | Lizenzüberwachungs-Datei | | VBR | RemAuto-Registrierungs-Datei | | VBZ | Datei zum Starten des Assistenten | | VBW | VisualBasic Projekt Arbeitsbereichs-Datei | | WCT | WebClass-HTML-Vorlage |
| Type | Datei-Type |
|---|
| EXE | Ausführbare Datei oder ActiveX-Komponente | | DLL | Prozeßinterne ActiveX-Komponente | | OCX | ActiveX-Steuerelement | | VBD | Status-Datei für ActiveX-Dokument | | WCT | WebClass HTML Template |
|