© Martin Korneffel, Stuttgart 2005 +++ email: trac@n.zgs.de +++ web: www.s-line.de/homepages/trac
BASIC ist ein Akronym (Beginner’s All-purpose Symbolic Instruction Code = Allzweck-Symbolbefehlssprache für Anfänger) und bezeichnet eine Programmiersprache, die Mitte der 60-er von den US- Amerikanern John Kemeny und Thomas Kurtz entwickelt wurde. Sie diente ursprünglich für Schulungszwecke.
Ursprünglich war BASIC als Interpretersprache konzipiert. Ein geringer Umfang an Befehlen, die Insensitivität gegenüber der Groß/Kleinschreibung und die Interaktivität durch den Interpreter führten dazu, daß BASIC inbesondere unter Anfängern beliebt wurde.
Beispiel: EXCEL wird als Kalkulationssoftware eingesetzt. Bestimmte Kalkulationen sollen online auf einem Webserver veröffentlicht werden, indem Inhalte aus Tabellenzellen in Datenbanktabellen auf dem Webserver übertragen werden. Für den Anwender soll die Übertragung genauso einfach wie ein Speichern des Arbeitsblattes sein. Als Werkzeug bietet sich hier VB und VBA an.
Sich wiederholende, komplexe Arbeitsabläufe können in einem Script erfasst, und auf Knopfdruck gestartet werden. Beispiele: Backup von Datenbanken/Festplatten, Wiederherstellen von Arbeitsoberflächen (Anmeldescripte). Als Werkzeuge bieten sich hier Scriptsprachen wie PERL ound VBScript an.
Auf einer Plattform (PC oder Microcontroller) wird eine völlig neue Anwendung erstellt. Als Werkzeuge bieten sich hier Entwicklungsumgen wie Visual C++ oder Visual.NET an. Dies ist der kompliziteste Fall. Die Entwicklung von Individualsoftware kann sogar zur entwicklung völlig neuer Programmierwerkzeuge führen (UNIX-> C, DHTML-> JavaScript)
Die Welt besteht aus Objekten, die miteinander kommunizieren. Die Kommunikation erfolgt über Botschaften, die in den meisten objektoriantierten Sprachen als Methoden realisiert sind. Botschaften können Produkte von Ereignissen im System sein wie z.B. das Anklicken einer Schalftfläche durch einen Benutzer. Anderseits können Botschaften programmgesteuert an Objekte gesendet werden. Damit lassen sich Verarbeitungsformen wie Stapelverarbeitung (übergabe der Kontrolle an ein weiteres Objekt) und Client/Server (Ausfrufen eines Dienstes im Objekt) realisieren.
Im folgenden werden die Stufen der Übersetzung eines VB.NET- Programmsdargestellt:
Die Strenge der Typisierung von VB kann über zwei Schalter gesteuert werden.
Option Explicit erzwingt bei On, daß alle Variablen vor ihrer Verwendung deklariert werden müssen.
Option Strict erzwingt zusätzlich eine strenge Typisierung: Deklarationen müssen Typen definieren, die Zuläsigkeit von Konvertierungen werden während der Kompilation und auch während der Laufzeit überwacht.
In Visual Studio 2005 können diese Optionen für alle VB- Projekte eingestellt werden unter
Extras/Optionen/Projekte und Projektmappen/VB Standard
Für jedes einzelne VB- Projekt kann davon in den Projekteinstellungen abweichend konfoguriert werden.
Im Folgenden wird ein einfaches Programm erstellt, welches auf der Kommandozeile den String "Hallo Welt" ausgibt. Anhand des Programmes wird die Kompilation in MSIL sowie das Kompilat selbst untersucht.
Legen sie eine Datei namens Hallo.vb an.
=> Quelltexte werden in Unicode- Dateien mit der Endung vb gespeichert.
' VB.NET Kennenlernen ' Kommentare sind einzeilig und werden mit einem Hochkomma (') eingeleitet ' Alle Prozeduren und Funktionen müssen in einem Modul- ' oder Klassenblock eingeschlossen werden Module m1 ' Die Prozedur Main hat eine besondere Bedeutung: Beim Programmstart ' wird vom Lader des Betriebssystems an diese die Kontrolle übergeben Sub Main() ' Hier wird ein Unterprogramm aus der Bibliothek System.dll aufgerufen ' Mittels des Unterprogramms Console.WriteLine erfolgt die Ausgabe ' der Zeichenkette "Hallo Maja" auf der Kommandozeile System.Console.WriteLine("Hallo Maja") End Sub End Module
Das Beispielprogramm kann auf der Kommandozeile (Visual- Studio- Tools/Command Prompt) durch folgenden Befehl kompiliert werden:
c:\vb-kurs\vbc hallo.vb /r: System.dll
Die Option /r weist den Compiler an, Einsprungpunkte für Unterprogramme aus der Bibliothek System.dll anzulegen.
Mittels Präprozessordirektiven können Abschnitte von der Kompilation ausgeschlossen werden.
Mit #const kann eine Konstante definiert werden, die in Präprozessorblöcken für die bedingte Kompilation ausgewertet wird. Die Konstanten müssen als erste Anweisungen in einer Quelltextdatei definiert werden.
#const XX_GRUSS_MAJA = True Module m1 Sub Main() : End Sub End Module
Hier wird eine Konstante namens XX_GRUSS_MAJA deklariert.
Nicht deklarierte Konstanten in Präprozessorblöcken werden durch Nothing ersetzt und stellen damit den boolschen Wert false dar.
In Abhängigkeit von bedingten Konstanten können Abschnitte im Quelltext von der Kompilation ausgeschlossen werden oder nicht:
#const XX_GRUSS_MAJA = True Module m1 Sub Main() #if XX_GRUSS_MAJA then System.Console.WriteLine("Hallo Maja") #else System.Console.WriteLine("Hallo Marina") #endif End Sub End Module
In diesem Beispiel wird die Zeile zwischen #else ... #endif nicht kompiliert. Wenn die erste Zeile (#const ...) auskommentiert wird, dann erfolgt keine Kompilation für die Zeile zwischen #if ... #else.
Dient zur logischen Gliederung des Quelltextes. Die IDE kann Regionen wahlweise auf- und zuklappen. Bsp.:
#region "mm" sub p1 ... end sub sub p2 ... end sub #end region
VB.NET ist eine vollständig objektorientierte Programmiersprache. Im Mittelpunkt der Progammierung mit VB.NET steht
die Beschreibung des Aufbaus von Objekten durch Klassendeklarationen
das Senden von Nachrichten an Objekte durch Methodenaufrufe
die Reaktion auf asynchrone Nachrichten/Ereignisse durch Ereignisse
Die gesamte Logik muß in Klassendeklarationen verpackt werden. Es gibt 2 Arten von Klassendeklarationen:
Module |
Class |
---|---|
Alle Elemente sind implizit shared |
Zugriff auf die Elemente muss individuell festgelegt werden |
Folgendes Beispiel zeigt ein einfaches Befehlszeilenprogramm. Es wird durch eine Modul- Klassendeklaration realisiert.
Module Module1 Class class1 Public x As Short Sub New() ' Konstruktor x = 99 End Sub Function add_to_x(ByVal s As Short) Return x + s End Function End Class Sub Main() ' Hier steht ein Kommentar Dim x, y As Short Dim c As New class1 x = 1 ' Werte von x aus Main und x aus c ausgeben Console.WriteLine("Wert von x= {0:D}", x) Console.WriteLine("Wert von c.x= {0:d}", c.x) ' Eine Memberfunktion von class1 aufrufen y = c.add_to_x(5) ' Das Ergebnis in y ausgeben Console.WriteLine("Wert von c.x= {0:d}", y) ' Warten auf eine Eingabe des Benutzers Console.ReadLine() End Sub End Module
Namespaces dienen zur Abgrenzung der Namensmengen zwischen verschiedenen Teilen von Bibliotheken und Programmen.
Namespace outer Namespace inner ' Deklaration des Namens x im Namespace outer.inner public x as Integer End Namespace End Namespace // Zugriff auf x outer.inner.x = 99;
Imports Namespace Imports Alias = Namespace
Menge |
Beispiel |
---|---|
ganze Zahlen, dezimal |
123 |
ganze Zahlen, Hexadezimal |
&HAF |
ganze Zahlen, Oktal |
&O73 |
negative Zahlen |
-123 |
rationale Zahlen |
123.4 |
rationale Zahlen in Exponentialschreibweise |
1.23e4 |
Zeichen |
"A"C |
Zeichenketten |
"ABC" |
Wahrheitswerte |
true oder false |
Datumsangaben (ami- Format MM/DD/YYYY) |
#02/13/2004# |
Operator |
Beschreibung |
---|---|
( ) |
Klammern |
^ |
Potenzieren |
- |
negatives Vorzeichen |
* / |
Multiplikation und Division |
\ |
Integer Division |
Mod |
Modulo bzw. Rest aus Division, z.B. 7 Mod 3 = 1 denn 2*3 + Rest 1 = 7 |
+ - |
Addition und Subtraktion |
< > = |
kleiner als, größer als, gleich |
<> <= >= Like Is TypeOf |
ungleich, kleiner gleich, größer gleich wie ist Typ-von |
Not |
logisches NICHT (Negation) |
And Or |
logisches UND, logisches ODER |
Xor Equ |
logisches Exlisiv ODER, Äquivalenz |
Unsere Programme realisieren Algorithmen, mit denen wir Daten verarbeiten. Um Zugriffe auf die Daten im Computerspeicher zu formulieren, muß uns die Programmiersprache entsprechende Ausdrucksmittel zur Verfügung stellen.
Ein elementares Ausdrucksmittel für Speicherzugriffe sind Variabeln.
Unter Variabeln können wir uns benannte Speicherplätze vorstellen. Variabeln sind immer vor ihrer Verwendung im Programmtext mittels einer Deklaration zu vereinbaren. In der Deklaration wird der zu verwendende Name für den Speicherplatz und der Datentyp festgelegt.
Zugriffsmodifikatoren Variabelname As Datentyp [= Startwert]
Der Datentyp steht für eine Klasse von Daten. Beispielsweise verbirgt sich hinter dem Datentyp Integer die Menge aller ganzen Zahlen im Intervall [-32768, 32767]. Der Datentyp bestimmt, wie die Informationen als Dualzahlen im Speicher zu verschlüsseln sind, und wieviel Speicherplatz für die Variabel benötigt wird. So werden Variabeln vom Typ Integer vom Dezimal- ins Dualsystem konvertiert, und für sie ein Speicherplatz von 16bit = 2Byte reserviert.
Die primitiven Typen sind im Namespace System definiert:
VB.NET |
CTS |
Wertebereich |
Literale |
---|---|---|---|
Boolean |
System.Boolean |
{true, false} |
true |
|
System.SByte |
[-128, 127] |
99 |
Byte |
System.Byte |
[0, 255] |
255 |
Char |
System.Char |
[0, 65535] |
"A"C |
Short |
System.Int16 |
[-32768, 32767] |
199S |
|
System.UInt16 |
[0, 65535] |
199 |
Integer |
System.Int32 |
[-2147483648, 2147483647] |
199 |
|
System.UInt32 |
[0, 4294967295] |
199 oder 199U |
Long |
System.Int64 |
[-9223372036854775808, 9223372036854775807] |
199 oder 199L |
|
System.UInt32 |
[0, 18446744073709551615] |
199 oder 199UL |
Single |
System.Single |
[-3.402823E+38, 3.402823E+38] |
3.14 oder 3.14F |
Double |
System.Double |
[-1.79769313486232E+308, 1.79769313486232E+308] |
9.0 oder 9D |
Decimal |
System.Decimal |
[0, 79.228.162.514.264.337.593.543.950.335] |
125.99M |
String |
System.String |
0- 2 Mrd. Unicodezeichen |
"Hallo Welt" |
Date |
System.DateTime |
00001-1-1 0:0:0 bis 9999-12-31 23:59:59 |
|
Object |
System.Object |
|
|
Durch Zugriffsmodifikatoren wird das Prinzip der Kapselung in VB realisiert. Über Zugriffsmodifikatoren wird zur Entwurfszeit gesteuert, von welchen Programmteilen aus auf eine Variable zugegriffen werden kann. Dadurch können Implementierungsdetails von Bibliotheken verborgen werden. Sinn macht die Diskussion der Zugriffsmodifikatoren erst im Zusammenhang mit Klassen. An dieser Stelle wird nur der Zugriffsnodifikator Dim und Static eingeführt:
Zugriffsmodifikator |
Beschreibung |
Nicht deklarierebar in |
---|---|---|
Dim |
nur im Block sichtbar, in dem deklariert wurde |
|
Static |
Definiert eine lokale Variable innerhalb einer Prozedur oder Funktion, die für den gesamten Zeitraum des Programmablaufes gültig, aber nur innerhalb der Methode sichtbar ist. |
für Member einer Klasse oder Modul |
Shared |
Definiert einen Klassenmember. Der Member ist unabhängig von Instanzen der Klasse. Entspricht den Modulvariablen oder Prozeduren von VB6 |
|
Für Variablen in statischen Methoden erfolgt eine automatische Initialisierung. Variablen in nichtstatischen Methoden müssen manuell initialsiert werden:
Dim i as int = 0
In Sonderfällen kann es sinvoll sein, die Lebensdauer von Variablen in Funktionen und Prozeduren über die Blockgrenzen hinaus zu verlängern. Soll z.B. Protokolliert werden, wie oft eine Methode in einem Programm schon aufgerufen wurde, dann muß eine Zählervariable bereitgestellt werden, die wie eine Globale Variable zu Programmstart initialisiert und erst bei Programmende vernichtet wird.
Module Utils Function MakeID() as Long static id as Long = 0 id += 1 return id End Function End Module
Alle Typen sind auf den Basistyp System.Object rückführbar. D.h. alle Typen verfügen über die Eigenschaften und Methoden von System.Object.
Die Menge aller Typen, die sich von System.Object ableiten, kann in zwei Teilmengen aufgeteilt werden: den Referenztypen und den Wertetypen. Die Wertetypen werden grundsätzlich auf dem Programmstack angelegt und entsprechen den eigebauten Typen in älteren Programmiersprachen.
Referenztypen
erfordern eine Instanzieirung in 2 Schritten:
Zwecks erhöhung der Ausführungsgeschwindigkeit werden Wertetypen auf dem Stack wie in allen anderen nicht .NET- Sprachen als reine Werte abgelegt. Da aber alle Typen konmplexe Objekte darstellen, erfogt eine Konvertierung, wenn ein Wertetyp in einem Objektkontext aufgerufen wird. Dabei wird temporär auf dem Heap ein Objekt angelegt, und der Wert des Wertetypen hinenkopiert. Dies wird als boxing bezeichnet.
char zeichen = 'A'; // vf ist ein Wertetyp und // Im folgenden wird der Wertetyp in einem Objektkontext eingesetzt (zeichen.isDigit()) // Hier wird auf dem Heap ein Objekt erzeugt, dessen Kopie zeichen aufnimmt. string aussage = zeichen.isDigit() ? "Ziffer" : "keine Ziffer";
Der Is- Operator ergibt True, wenn zwei Referenzen auf dasselbe Objekt verweisen:
If ref_a is ref_b return True End IF
Mittels des typeof- Operators kann zu einer Klasse ein Typ- Objekt erzeugt werden. Er entspricht der statischen Methode System.Type.GetType(..).
if TypeOf a Is Integer Then .... end if
Jedes Objekt erbt von der .net Wuzel System.Object die Methode GetType. Diese liefert ein Type- Objekt, welches alle Metainformationen zu einem Typ enthält.
Der GetType(x as Object)- Operator ermöglicht es, zu einem beliebigen Typ (Klassenname) das Type- Objekt zu bestimmen, ohne das ein Instanz notwendig ist.
Implizite Typkonvertierungen sind zwischen verwandten Datentypen möglich, wenn der Zieltyp mehr Informationen aufnehmen kann als der Quelltyp:
Explizite Typkonvertierungen erzwingen die Umwandlung von einem Typ in einen anderen. Dabei gibt es jedoch verschieden starke Konvertierungsoperatoren. Auf der einen Steite gibt es die VB- Konvertierungsoperatoren, auf der anderen Seite die Operatoren der Klasse Convert.
VB |
VB.NET |
Convert-Klasse |
---|---|---|
x = Cbool(<expr>) |
x = Ctype(<expr>, Boolean) |
toBoolean(<expr>) |
x = Cbyte(<expr>) |
x = Ctype(<expr>, Byte) |
toByte(<expr>) |
x = Cchar(<expr>) |
x = Ctype(<expr>, Char) |
toChar(<expr>) |
x = Cdec(<expr>) |
x = Ctype(<expr>, Decimal) |
toDecimal(<expr>) |
Die Convert Funktionen sind am stärksten Konvertierungsfunktionen. Sie ermöglichen eine konvertierung zwischen an sich inkompatibelen Typen wie Zahlenwerte in Strings in nummerische Werte von Int32 etc.
Die in den Type- Objekten gespeicherten Metainformationen beschreiben die Struktur einer Klasse vollständig. Beispielsweise können alle Member einer Klasse wie folgt aufgelistet werden:
Imports System Imports System.Reflection class CTest Dim ganzZahl as Integer enum EPartei gut boese gerecht End Enum Function TueWas() as Integer ganzZahl += 1 Return ganzZahl End Function End Class : Sub Main() Dim t As Type t = GetType(CTest) ' Alle Felder, Eigenschaften und Methoden werden aufgelistet Dim minfos() As MemberInfo = t.GetMembers() For Each minfo As MemberInfo In minfos Console.WriteLine("{0}", minfo.ToString()) Next End Sub
Entwickeln Sie eine Klasse CTypeBrowser, welche die Methode info(object) implementiert, die zu einem gegebenen Objekt alle Felder und Methoden auflistet.
Nothing ist ein spezieller Wert, der jeder Variablen zugewiesen werden kann.
Zuweisung an Variable vom |
bewirkt |
---|---|
Wertetyp |
Die Variable wird auf ihren Standardwert zurückgesetzt (Strings z.B. auf leere Zeichenkette) |
Referenztyp |
Bei Objektvariablen verweisen diese nicht mehr auf das Objekt. Das Objekt wird jedeoch erst gelöscht, wenn die Garbage Collection keine Verweise auf das Objekt vorfindet. |
Beispiel:
Dim preis As Dezimal = 99.45 Console.WriteLine("Preis: {0,10:########.##}€", preis)
Über Formatzeichenfolgen wird abhängig vom Datentyp die Darstellung eines Wertes als String gesteuert. Es gibt Formatzeichenfolgen für:
nummersiche Typen
Datumstypen
Aufzählungstypen
Formatzeichenfolgen bestehen aus einem Formatbezeichner und optional aus der Angabe einer Genauigkeit XX. Um eine Zahl mit max. 3 Nachkommastellen auszugeben, kann folgende Formatzeichenfolge verwendet werden:
N3
Folgende Formatbezeichner sind vordefiniert:
Formatbezeichner |
Bedeutung |
Beispiel |
Resultat |
---|---|---|---|
C |
Währungsbetrag |
(99.490).ToString("C") |
99,49 € |
D |
Ganzzahliger Wert. Die Genauigkeit definiert die minimale Ausgabebreite. Sollte die darzustellende Zahl die minimale Ausgabebreite nicht erreichen, dann wird mit führenden 0-en aufgefüllt |
(123).ToString("D5") |
00123
|
E |
Zahl in Exponentialschreibweise |
(99.49).ToString("E") |
9,95E+005 |
F |
Festkomma. Die Genauigkeit gibt eine feste Anzahl von Nachkommastellen an |
(99.49).ToString("F1") |
99,5 |
G |
Allgemein- Formatierung erfolgt abhängig vom Typ der Zahl |
(99.49).ToString("G") |
99,5 |
N |
Zahl (allgemein). Die Genauigkeit beschreibt die Anzahl der Nachkommastellen |
(99.49).ToString("N") |
99,49 |
P |
Prozentzahl. Der Wert wird mit 100 multiplizieret und mit einem Prozentzeichen versehen |
(0.15).ToString("P") |
15,00% |
H |
Hexadezimal |
(0xA1).ToString("H") |
A1 |
R |
Stellt Zahlen so als Zeichenkette dar, daß sie aus diesen ohne Genauigkeitsverlust wieder zurückkonvertiert werden können. |
(99.49).ToString("R") |
99,49 |
Neben vordefinierten Formatzeichenfolgen können Formate wie im obigen Beispiel auch selbst definiert werden. Siehe dazu: Benutzerdefinierte Formatzeichenfolgen
Formatbezeichner |
Bedeutung |
Beispiel |
Resultat |
---|---|---|---|
d |
Kurzes Datumsformat |
DateTime.Now.ToString("d") |
|
D |
Langes Datumsformat |
DateTime.Now.ToString("D") |
|
T |
Zeitformat |
DateTime.Now.ToString("T") |
|
s |
ISO 8601 konformes Datumsformat. Werte sind sortierbar. Dieser Typ wird z.B. in XML- Schema angewendet |
DateTime.Now.ToString("s") |
|
Formatbezeichner |
Bedeutung |
Beispiel |
Resultat |
---|---|---|---|
G |
Stellt Wert eines Aufzählungstyps als String dar, falls möglich. Andernfalls wird der Wert als Integer- Zahlenwert dargestellt |
(SUnits.cm).ToString() |
"SUnits.cm" |
F |
Stellt Wert eines Aufzählungstyps als String dar, falls möglich. Andernfalls wird der Wert als Integer- Zahlenwert dargestellt |
(SUnits.cm).ToString() |
|
D |
Stellt Wert eines Aufzälungstyps als dezimalen Integer dar |
(SUnits.cm).ToString() |
2 |
X |
Stellt Wert eines Aufzälungstyps als hexadezimalen Integer dar |
(SUnits.cm).ToString() |
0x2 |
Imports System.Globalization; ' Kopie des aktuell wirksamen Formatproviders erzeugen Dim nif as NumberFormatInfo nif = CType(System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.Clone(), NumberFormatInfo) ' Währungssysmbol auf Dollar umstellen nif.CurrencySymbol = "$" ' Ausgabe eines Währungswertes Dim preis as Double preis = 99.99 Console.WriteLine(preis.ToString("C", nif))
In Methoden wie Console.WriteLine("Formatstring", object, ...) können Textkonstanten und Formatblöcke, die Formatzeichenfolgen für auszugebende Parameter enthalten, kombiniert werden. Dies wird als Composit- Formating bezeichnet. Soll z.B. ein Längenmaß ausgegeben werden, welches aus dem Wert und der Längeneinheit besteht, dann könnte dies durch folgende Anweisung erfolgen:
Console.WriteLine("Längenmaß: {0,5:N} {1,2}", LMasz.value, LMasz.unitToString());
Ein Formatblock hat folgende Syntax:
{ParamListenIndex[,alignment][:Formatzeichenfolge]}
Der ParamListenIndex bezeichnet den Parameter aus der Parameterliste, dessen Wert durch den Parameterblock formatiert werden soll. Das Alignment definiert die Ausrichtung und mindestbreite. Positive Werte stehen für eine Rechtsausrichtung, negative für eine Linksausrichtung.
Endliche Mengen lassen sich durch Aufzählungen modellieren (Enumarations). Beipiel:
Enum enumLaengenEinheiten mm cm dm m km AE LichtJahr End Enum
Datenstrukturen werden deklariert durch Blöcke mit dem Schlüsselwort Structure (bei VB 6.0 Type). Jedes Element einer Strukture muß mit einem Zugriffsmodifikator versehen werden (Public, friend, Protected, Private). Dim entspricht dem Zugriffsmodifikator Public.
Structure Point Dim x as Double Dim y as Double End Structure
Strukturen sind Wertetypen
Strukturen können Eigenschaften, Methoden und Ereignisse besitzen
Es können parametrisierbare Konstruktoren definiert werden.
Der parameterlose Konstruktor new() darf nicht überschrieben werden.
Werden Strukturvariablen ohne New definiert, dann werden die Felder der Struktur nicht initialisiert
Werden Strukturvariablen mit New definiert, dann erfolgen Standardinitialisierungen der Felder
In seiner Grundbetriebsart lädt der Computer eine Anweisung nach der anderen aus dem Arbeitsspeicher und führt sie aus. Viele Algorithmen erfordern jedoch, daß einige Abschitte aus den Anweisungslisten nur unter bestimmten Bedingungen auszuführen sind (z.B. „Wenn bis zum Tag X kein Zahlungseingang erfolgte, dann Mahnung abschicken“) oder wiederholt werden müssen. Um dies zu ermöglichen, verfügt der Computer über spezielle Anweisungen, die den Befehlszählerstand manipulieren. Sie bewirken, daß nach ihrer Ausführung das Programm an einer beliebigen neuen Adresse fortgesetzt wird. Aufgrund dieser Wirkung werden sie Sprunganweisungen genannt.
In VBA sind die Sprunganweisungen in Form von bedingt ausführbaren, oder bedingt wiederholbaren Programmabschnitten implementiert.
Der bedingt ausführbare Programmabschnitt entspricht einer Wenn ... dann Regel.
IF Bedingung Then Anweisung 1 Anweisung 2 : Anweisung n End IF
Trifft die Bedingung nicht zu, dann kann anschließend mit dem Schlüsselwort Else ein Programmabschnitt als Alternative formuliert werden:
IF Bedingung Then Anweisung 1 : Anweisung n Else Anweisung n+1 : Anweisung n+m End IF
Gibt es mehrere Alternativen, die von Zusatzbedingungen abhängig sind, dann können diese in ElseIf- Blöcken formuliert werden:
IF Bedingung Then Anweisung 1 : Anweisung n ElseIF Bedingung2 Anweisung n+1 : Anweisung n+m End IF
Ist die Ausführung mehrerer Programmabschnitte vom Wert eines einzigen Ausdrucks abhängig, dann kann alternativ zu ElseIf eine vereinfachte Schreibweise mittels Select Case Block gewählt werden:
Select Case Ausdruck Case Wert1 Anweisung 1 : Anweisung n Case Wert2 Anweisung n+1 : Anweisung n+m Case Wert3 : Case Else Anweisung End Select
Es handelt sich hierbei um Programmabschnitte, die sooft wiederholt werden, solange eine Bedingung zutrifft (wahr ist). Sie werden gewöhnlich als Schleifen bezeichnet. Zwei elementare Formen der Schleifen werden unterschieden: die abweisende, und die nichtabweisende Schleife.
Bei der abweisenden Schleife wird stets am Anfang des Programmabschnittes geprüft, ob die Bedingung für eine Ausführung des Abschnittes erfüllt ist. Wenn ja, dann wird der Programmabschnitt ausgeführt, und am Ende der Befehlszähler wieder auf die Startadresse des Programmabschnittes gesetzt. Gilt die Bedingung weiterhin, dann erfolgt eine wiederholte Ausführung des Programmabschnittes. Trifft die Bedingung nicht zu, dann wird der Programmabschnitt übersprungen.
DO Bedingung Anweisung 1 Anweisung 2 : Anweisung n Loop
Bei der nichtabweisenden Schleife wird die Bedingung erst am Ende des Programmabschnittes überprüft. Trifft sie zu, dann wird der Befehlszähler auf den Abschnittanfang gesetzt, und dieser wiederholt. Sonst wird mit der nachfolgenden Anweisung fortgesetzt.
Da die Bedingung erst am Ende des Abschnittes überprüft wird, wird der Abschnitt immer mindestens einmal ausgeführt.
DO Anweisung 1 Anweisung 2 : Anweisung n Loop Bedingung
Sind Datenfelder fester Länge zu durchlaufen, oder Berechnung mit einer vorgegebenen Zahl wiederholt auszuführen, dann bietet sich die For...to ... next Schleife an:
FOR i = <Startwert> TO <Endwert> [STEP <Schrittweite>] Anweisung 1 Anweisung 2 : Anweisung n Next
foreach
For Each el [as Type] in Collection ... Next
Zur Verarbeitung tabelarischer Daten dienen in VB Arrays. Durch die Deklaration eines Arrays werden im RAM n Speicherplätze zur Aufnahme von Werten des Typs x reserviert.
Arrays sind Referenztypen
Deklaration eines Arrays hat folgenden Aufbau:
Dim a(3) as Integer | | +----- Typ der Einträge | +------------- größter Index eines Eintrages +--------------- Name des Arrays
Nach einer Arraydeklaration ergibt sich folgendes Format im Arbeitspeicher:
Der
Zugriff auf die Elemente eines Arrays erfolgt über den Namen und
den Indize:
Dim x as Integer ' x hat nach Ausführung dieser Anweisung den Wert 2 x = a(2) | +--- Indize (Platznummer) +----- Arrayname
Die Indizes können dynamisch zur Laufzeit festgelegt werden. Damit ist eine komfortable Verarbeitung der Arraydaten in Schleifen möglich:
Dim i as Integer, s as Long ' s enthält nach der Schleife die Summe aller Einträge for i = 0 to 3 s = s + a(i) next
Dim primz() as Integer = {2, 3, 5, 7, 11}
Dim anz_elems as Int32 = primz.length 'Anzahl der Elemente in über alle Dimensionen Dim anz_dims as Int32 = primz.rank 'Anzahl der Dimensionen eines Arrays
Durch Zuweisung wird nur eine Referenz erzeugt, jedoch keine Kopie.
Dim prim2() As Int32 = prim
Die Methode Clone() eines Arrays erzeugt eine 1:1 Kopie
Dim prim3() As Int32 = prim.Clone()
Zur Laufzeit können die Dimensionen eines dynamischen Arrays mit der Prozedur ReDim <arrayName>( <neuerMaxIndex>) vergrößert und verkleinert werden wie folgt:
: ReDim Preserve a(6) ' Das Array wird um 3 Elemente vergrößert, wobei der alte Inhalt erhalten bleibt : ReDim a(9) ' Das Array wird wiederum um 3 Elemente vergrößert. Diesmal wird der alte Inhalt jedoch nicht ' erhalten (Preserve fehlt)
For Each quadrat as Integer in quadrate) Console.WriteLine(quadrat); Next
Dim planeten() as String = {"Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn"} Array.Sort(planeten);
enum ELaenge {mm, cm, dm, m, km}; struct Laenge : IComparer { public float wert; public enumLaengenEinheiten einheit; public int Compare(object obj1, object obj2) { Laenge l1 = (Laenge)obj1; Laenge l2 = (Laenge)obj2; // alles in mm umrechnen float il1 = tomm(l1), il2 = tomm(l2); if (il1 == il2) return 0; else if (il1 < il2) return -1; else return 1; } float tomm(Laenge l) { switch (l.einheit) { case ELaenge.mm: return l.wert; case ELaenge.cm: return l.wert * 10; case ELaenge.dm: return l.wert * 100; case ELaenge.m: return l.wert * 1000; case ELaenge.km: return l.wert * 1000000; } return -1; } } // In Main Laenge[] fahrten = new Laenge[3]; fahrten[0].einheit = ELaenge.mm; fahrten[0].wert = 100000; fahrten[1].einheit = ELaenge.cm; fahrten[1].wert = 3000; fahrten[2].einheit = ELaenge.km; fahrten[2].wert = 0.99F; Array.Sort(fahrten, fahrten[0]); foreach (Laenge fahrt in fahrten) { Console.WriteLine("{0} {1}", fahrt.wert, fahrt.einheit.ToString()); }
Min/Max- Suche,
Sortieren
Messwerterfassung (akt. Wert, dyn. Mittelwert)
Grundlage für die Datumsberechnung ist ein linearer Zeitstrahl, der in Ticks unterteilt ist. Ein Tick hat die Dauer von 10-7s (zehnmillionstel Sekunde). Zeitpunkte auf dem Zeitstrahl werden durch Werte vom Typ Date angegeben. Ein Datumswert wird hat das Format #M/D/YYYY# (amerikanisches Datumsformat).
Date
basiert auf System.DateTime. Die Konstruktoren von
System.DateTime sind mehrfach überladen:
dim dat1 as New System.DateTime(Ticks) dim dat2 as New System.DateTime(YYYY, MM, DD) dim dat2 as New System.DateTime(YYYY, MM, DD, hh, min, sec, millisec)
Zur Darstellung von Zeiträumen dient die Klasse TimeSpan.
.NET unterstützt Unicode. Quelltexte können als Unicode- Dateien verpackt werden, und Zeichentypen wie char und string basieren auf 16bit Unicode. Folgendes Windows- Programm liefert einen Dialog mit einem kyrillischen Text:
Public Class Form1 Inherits System.Windows.Forms.Form #Region " Vom Windows Form Designer generierter Code " : #End Region Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ' char verarbeiten Unicode- Zeichen Dim c1, c2, c3, c4, c5, c6, c7 As Char c1 = ChrW(1051) c2 = ChrW(1070) c3 = ChrW(1041) c4 = ChrW(1054) c5 = ChrW(1042) c6 = ChrW(1068) Dim str As String str += c1.ToString + c2.ToString + c3.ToString + c4.ToString + c5.ToString + c6.ToString lblDasWichtigste.Text = str End Sub End Class
Mittels der Funktion ChrW(Zahl) wird eine nummerischer Unicode in ein Unicodezeichen umgewandelt. Der String aus den Unicodezeichen wird schließlich über ein Label (lblDasWichtigste) im Formular angezeigt.
Programm, welches in einer Textbox eine Teilmenge des Unicodes als Zeichencodetabelle ausgibt. Bsp: Währungssymbole von 20A1 bis 20AF
Programm, welches alle Satzzeichen im Unicode ausfiltert und anzeigt
Siehe .NET Doku
Dim txt as String = "Anton,Berta,Cäsar" Console.WriteLine(txt.Substring(6, 5))
Dim txt as String = "Hallo Welt" Console.WriteLine("Alles groß: {0}", txt.ToUpper()) Console.WriteLine("Alles klein: {0}", txt.ToLower())
Dim txt as String = "Anton,Berta,Cäsar" Dim pos as Int32 = txt.IndexOf("Berta")
Dim txt as String = "Anton,Berta,Cäsar" txt = txt.Insert(txt.IndexOf("Berta"), "Aladin,")
Dim txt as String = "Anton,Berta,Cäsar"; Dim namen() as String = txt.Split(","c);
Dim r As Regex = New Regex("\s*=\s*") Dim aw() As String = r.Split("Durchmesser = 199") Console.WriteLine("Attribut {0} hat Wert {1}", aw(0), aw(1))
' In folgendem String sollen alle Vorkommen von keinen durch [] markiert werden txt = "Das Pferd frisst keinen Gurkensalat. Ich habe keine Ahnung warum" Dim txt_neu As String = Regex.Replace(txt, "keinen", "[keinen]") Console.WriteLine(txt_neu)
Romzahlkonverter
Zählen der Buchstabenhäufigkeit in gegebenen Texten
Die wichtigsten mathematischen Funktionen sind im Math- Objekt des Namespace System enthalten.
Beispiel: Eine Funktion soll implementiert werden, welche den Zeitraum zwischen zwei gegebenen Daten bestimmt. Als Standard wird der Zeitraum in Sekunden ausgegeben. Optional kann die verstrichene Zeit aber auch in Minuten, und Stunden ausgegeben werden:
Function Zeitraum_zwischen(ByVal start As Date, ByVal ende As Date, Optional ByVal einheit As String = "sec") Dim ticks As Long = Math.Abs(start.Ticks - ende.Ticks) Dim zr As New TimeSpan(ticks) Select Case (einheit) Case "sec" Return zr.TotalSeconds Case "min" Return zr.TotalMinutes Case "hh" Return zr.TotalHours Case Else Throw New Exception("Unbekannte Zeiteinheit") End Select End Function
Aufgabe:
Die Funktion Zeitraum_zwischen(...) zur Berechnung von Zeiträumen in Minuten und Stunden anwenden.
Beispiel:
Function summe_aus(ByVal ParamArray summanden( ) As Double) Dim i As Integer, sum As Double For i = 0 To summanden.GetUpperBound(0) sum += summanden(i) Next Return sum End Function
Aufgabe:
Die Funktion summe_aus (...) zur Berechnung der Summe verschiedener Listen einsetzen.
Komponeten wie z.B. Formulare und strombasierte XML- Parser können über Ereignisroutinen (Eventhandler) an die Wünsche des Anwenders angepasst werden. Ereignisroutinen werden individuell vom Anwender erstellt und ähneln gewöhnlichen Prozeduren. Anschießend muß der Komponete die Ereignisroutinen bekannt gemacht werden. In C++ benutzt man dazu z.B. Funktionszeiger. Da VB.NET keine Zeiger bereitstellt, gibt es ein Sprachkonstrukt, die sog. Delegats (Delegierungen). Es handelt sich hierbei letzendlich um typisierte Funktionszeiger, deren Wert jedoch nicht geändert werden darf.
Jeder Delegate muß vor seiner Verwendung deklariert werden:
[Zugriffsmodifikator] Delegate Methodendeklaration z.B.: Public Delegate OnDirOpen(name as String)