© Martin Korneffel, Stuttgart 2003 +++ email: Martin.Korneffel@t-online.de +++ web: trac.biz
Ein Macro (engl. "Zusammenfassung von Befehlen") ist eine Liste von Instruktioen, die Excel- Objekte wie Zellen und Grafiken manipulieren. Macros dienen der Rationalisierung durch Automation sich häufig wiederholender Arbeitsschrittfolgen.
Objekt |
Aufgabe |
Macro |
---|---|---|
Zelle |
Schriftfont formatieren |
Sub ZelleFormatierenMakro() ' Tastenkombination: Strg+Umschalt+R ' With Selection.Font .Name = "Arial" .FontStyle = "Fett" .Size = 10 .Strikethrough = False .Superscript = False .Subscript = False .OutlineFont = False .Shadow = False .Underline = xlUnderlineStyleNone .ColorIndex = xlAutomatic End With End Sub |
|
Formatieren eines Zellenpaar als etikettiertes Ergebnis, z.B. Saldo 100,00 € Erste Zelle mit fetter Schrift, Zelle links davon mit Währungsformat, doppelter Unterstreichung |
Sub ErgebnisFormatierenMakro() ' Tastenkombination: Strg+Umschalt+R ' With Selection.Font .Name = "Arial" .FontStyle = "Fett" .Size = 10 .Strikethrough = False .Superscript = False .Subscript = False .OutlineFont = False .Shadow = False .Underline = xlUnderlineStyleNone .ColorIndex = xlAutomatic End With ActiveCell.Offset(0, 1).Range("A1").Select Selection.NumberFormat = "#,##0.00 $" With Selection.Font .Name = "Arial" .FontStyle = "Standard" .Size = 10 .Strikethrough = False .Superscript = False .Subscript = False .OutlineFont = False .Shadow = False .Underline = xlUnderlineStyleDouble .ColorIndex = xlAutomatic End With End Sub |
Diagramm |
Tortendiagramm für eine Datenreihe erstellen |
Sub TorteMakro() ' Tastenkombination: Strg+a ' Charts.Add ActiveChart.ChartType = xlPie ActiveChart.SetSourceData Source:=Sheets("Kopie (1) von FileTypeStatistic"). _ Range("A2:B33"), PlotBy:=xlColumns ActiveChart.Location Where:=xlLocationAsObject, Name:= _ "PieFileTypeStatistic" End Sub |
Um Excel- VBA zu erforschen, kann der Macrorecorder genutzt werden. Er erzeugt aus einer Reihe von Benutzerinteraktionen reinrassigen VBA- Code.Der Macrorecorder ist erreichbar unter Extras/Macros/Macrorecorder.
In Excel wird ein Makro durch eine Prozedur in VBA realisiert. Eine Prozedur ist ein Block, der eine Liste von VBA- Anweisungen enthält. Eine Prozedur hat einen Namen und kann über diesen Namen zur Ausführung gebracht werden.
Sub Macrobname <- Hier startet der Prozedurblock ' Ein Kommentar <- Kommentare dienen dem Entwickler als Speichern von Hilfeinformationen für das Verständnis <Eine Liste von VBA- Anweisungen> <- Durch die Anweisungen werden Excel- Objekte gesteuert End Sub <- Hier endet der Prozedurblock
In VBA können die Objekte über spezielle Bezeichner (Namen) angesprochen werden. Die aktuell selektierte Zelle ist z.B. über Selection erreichbar. Eine Zelle hat viele Eigenschaften wie z.B. den eingegebenen Wert oder die Hintergrundfarbe. Diese Eigenschaften werden über den Objektnamen adressiert, indem der Eigenschaftsname, separiert durch einen Punkt an den Objektnamen angehängt wird.
Objektname.Eigenschaftsname
Beispiel:
' Zugriff auf Wert der aktuell selektierten Zelle Selection.Value
Verändert werden die Eigenschaften indem entweder ihnen neue Werte zugewiesen-, oder auf ihnen bestimme Methoden aufgerufen werden:
' Setzen eines Neuen Werts in einer Zelle Selection.Value = 99 ' Hinzufügen eines neuen Diagramms zur Arbeitsmappe Charts.Add
Objekt |
Ein Objekt fasst Prozeduren und Daten zusammen, die Dinge und Prozesse beschreiben, welche in einem unmittelbaren Zusammenhang stehen. In der objektorientierten Sichtweise werden die Prozeduren eines Objektes als Methoden, und die Daten als Elemente bezeichnet. |
Durch die Einführung des Objektbegriffes in VB können Systeme mit komplexer innerer Struktur direkt beschrieben werden. Jedes Objekt wird mit einem Namen gekennzeichnet, jeder Prozess in einem Objekt durch eine sogenannte Methode ausgedrückt, und jeder Zustand durch eine Eigenschaft dokumentiert. Beziehungen und Prozesse, an denen mehrere Objekte beteiligt sind, können durch Methoden, die Objekte als Parameter erwarten, und Eigenschaften, die wiederum Objekte sind, ausgedrückt werden.
Application <=> Excel- Anwendung | +-> OrganizationName <=> Name der Firma, für das das Produkt lizensiert wurde | +-> UserName <=> Name des Benutzers, der Excel ausführt | +-> OperatingSystem <=> Betriebssystemversion, unter dem die Anwendung läuft | +-> ActivePrinter <=> Name des aktuell eingestellten Standarddruckers | +-> Selection <=> Referenz auf selektierten Bereich | +-> ActiveCell <=> Referenz auf aktive Zelle | +-> ActiveChart <=> Referenz auf aktives Diagramm | +-> ActiveSheet <=> Referenz auf aktives Tabellenblatt | +-> ActiveWindow <=> Referenz auf aktives Fenster | +-> ActiveWorkbook <=> Datei, die IO- aktiv ist | +-> ThisWorkbook <=> Datei, die momentan | ausgeführtes Macro enthält | +-> ScreenUpdating <=> TRUE, dann werden alle Änderungen an Zellen | sofort angezeigt | FALSE, die Änderungen werden nicht angezeigt +-> M: GetOpenFilename([Filter], ...) <=> Zeigt einen "Datei öffnen" Dialog an, | und gibt den Name der zu öffnenden Datei zurück | +-> M: GetSaveAsFilename(...) <=> Zeigt einen "Datei speichern unter..." Dialog an, | und gibt den Namen der Datei zurück, in die gesichert werden soll. | +-> Workbooks <=> Aufzählung aller geladenener | Excel- Dateien. | Zugriff über: Workbooks(Nr) oder | Workbooks(„Dateiname“) | liefert die Referenz auf ein | Workbook- Objekt. | +-> M: Add <=> neue, leere Arbeitsmappe anlegen | +-> count <=> Anzahl der aktuell geladenen Arbeitsmappen | +-> M: open „Dateiname“ <=> Vorhandene Excel-Datei laden | +-> M: Close <=> schließen einer Excel- Datei
Workbook <=> Arbeitsmappe, entspricht einer | Excel- Datei | +-> M: Activate <=> Datei zur IO- aktiven machen | +-> M: Save <=> Arbeitsmappe sichern | +-> Path <=> Verzeichnis, in dem die Arbeitsmappe gepeichert ist | +-> Sheets <=> Aufzählung aller Arbeitsblätter der | Arbeitsmappe | Zugriff über: Sheets(Nr) oder | Sheets(„Name“) | Ein Sheet kann ein Tabellenblatt, ein | Diagramm oder ein Dialog sein. | +-> M: Add <=> neue, leere Arbeitsmappe anlegen | +-> count <=> Anzahl der aktuell geladenen Arbeitsmappen | +-> M: Close <=> schließen einer Excel- Datei
Worksheet <=> Excel- Tabelle | +-> M: Activate <=> Tabelle zur IO- aktiven machen | +-> ChartObjects <=> Aufzählung aller Diagrammobjekte in einem Arbeitsblatt | | | +->>ChartObject | +-> Cells <=> Aufzählung aller Tabellenzellen. | Zugriff erfolgt über Zeilen und | Spaltenindizes z.B. Cells(1, 2) | liefert Zugriff auf Zelle B2 | +-> Range <=> Afzählung aller Tabellenzellen. | Zugriff erfolgt über A1- Adressen | z.B. Range(„B2:C4“) liefert Aufzählung | aller Zellen aus dem Bereich B2:C4, | Range("A1") liefert die Zelle A1 | +-> Interior <=> Hintergrundfarbe und -Muster einer Zelle | +-> Borders <=> Aufzählung aller Umrandungslinien eines Zellbereiches | | | +-> Line | | | +-> LineStyle <=> Linienstil einer Umrandungslinie | +-> Value <=> Wert der Zelle | +-> Formula <=> In Zelle gespeicherte Formel | +-> HasFormula <=> True, wenn Zelle eine Formel enthält | +-> Font <=> Von der Zelle verwendete Schriftart | | | +-> Name <=> Name des Schriftfonts | | | +-> FontStyle <=> Schriftschnitt (z.B. Bold ) | +-> NumberFormat <=> Nummerische Formatierung des Zelleninhaltes. Zulässige | Werte sind Zeichenketten wie im Dialog Zellen Formatieren
Das aktivierte Diagramm ist über die Eigenschaft Applicatio.ActiveSheet erreichbar.
Die Deaktivierung eines Diagramms erfolgt über die Eigenschaft Application.ActiveWindow.Visble = False. Die Ursache dafür besteht darin, dass ein Diagramm als OLE- Objekt behandelt wird.
Charts <=> Aufzählung aller Diagramme | +-> Chart <=> Diagramm | +-> ChartArea <=> Hintergrund des gesamten Diagrammes | +-> PlotArea <=> Hintergrund des Zeichnungsbereiches | +-> Foor <=> Boden eines 3D Diagramms | +-> Walls <=> Seitenwände eines 3D Diagramms | +-> Corners <=> Ecken eines 3D Diagramms | +-> ChartTitle <=> Titel | +-> Legend <=> Beschriftung der Datenreihe | +-> Axes <=> Diagrammachsen | | | +->> Axis | | | +-> TickLabels <=> Markierungen von Achspunkten | | | +-> Gridlines <=> Orientierungslinien | +-> SeriesCollection <=> Datenreihen | +-> Series | +-> Points <=> Datenpunkte | | | +->> Point | +-> Trendlines <=> Trend und Ausgleichslinien | +->> Trendlinie
Menü: Ansicht/Direktfenster Strg+G
Im Direktfenster können VBA- Anweisungen ausgetestet werden oder Funktionen und Prozeduren ausgeführt werden. So kann eine Messagebox wie folgt gestartet werden:
MsgBox "Hallo, heute ist der " & Now
Der Objektkatalog listet alle von Excel aus manipulierbaren Objekte samt ihrer Eigenschaften und Methoden auf.
Menge |
Beispiel |
---|---|
ganze Zahlen |
123 |
negative Zahlen |
-123 |
rationale Zahlen |
123.4 |
rationale Zahlen in Exponentialschreibweise |
1.23e4 |
Wahrheitswerte |
true oder false |
Datumsangaben (ami- Format MM/DD/YYYY) |
#02/13/2004# |
Priorität |
Operator |
Beschreibung |
---|---|---|
höchste |
( ) |
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 |
|
<> <= >= |
ungleich, kleiner gleich, größer gleich |
|
Not |
logisches NICHT (Negation) |
|
And Or |
logisches UND, logisches ODER |
niedrigste |
Xor Equ |
logisches Exlisiv ODER, Äquivalenz |
Unsere Programme realisieren Algorithmen, mit denen wir Daten verarbeiten. Um Zugriffe auf die Daten im Computerspeicher zu formulieren, muss uns die Programmiersprache entsprechende Ausdrucksmittel zur Verfügung stellen.
Ein elementares Ausdrucksmittel für Speicherzugriffe sind Variabeln.
Unter Variablen 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.
Dim Variablenname As Datentyp
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.
Im der folgenden Tabelle werden alle elementaren Datentypen der Programmiersprache VBA aufgelistet:
Datentyp |
Kürzel |
Speicherbelegung |
Beschreibung |
---|---|---|---|
Byte |
|
1 Byte |
Ganze Zahlen im Intervall [0, 255] |
Boolean |
- |
2 Byte |
Wahrheitswerte der Menge {TRUE, FALSE} |
Integer |
% |
2 Byte |
Ganze Zahlen im Intervall [-32768, 32768] |
Long |
& |
4 Byte |
Ganze Zahlen im Intervall [-2147483648, 2147483647] |
Currency |
@ |
8 Byte |
Festkommazahlen mit 15 Stellen vor und 4 Stellen nach dem Komma |
Decimal |
|
12 Byte |
Unterdatentyp von Variant. Die Genauigkeit beträgt 28 Stellen. Die Anzahl der Nachkommastellen hängt von der Größe der Zahl ab- für eine 10- Stellige Zahl bleiben 18 Nachkommastellen. |
Single |
! |
4 Byte |
Fließkommazahlen mit 8 Stellen Genauigkeit |
Double |
# |
8 Byte |
Fließkommazahlen mit 16 Stellen Genauigkeit |
Date |
- |
8 Byte (64bit) |
Datum und Uhrzeit. [1.1.100 00:00:00 bis 31.12.9999 23:59:59] |
String |
$ |
10 Byte + 2Byte pro Zeichen |
Zeichenketten. Die Maximal mögliche Länge ist nur durch den verfügbaren Speicherplatz beschränkt. |
Object |
- |
4 Byte |
Verweist auf ein Objekt. Dazu später mehr. |
Variant |
- |
16 Byte mindestens |
Defaultdatentyp, nimmt je nach Bedarf einen der obigen Variabletypen an. Der Speicherplatz wird an die Erfordernisse angepasst. |
VB ermöglicht aus Gründen der Abwärtskompatibilität, auf die explizite Deklaration von Variablen zu verzichten. Die Deklaration erfolgt dann implizit durch Zuweisen eines Wertes an einen Variablenamen. Damit werden allerlei exotische Fehler, die sich oft erst zur Laufzeit outen, ermöglicht. Um diesen offensichtlichen Unsinn abzustellen, muss an den Beginn eines jeden Moduls die Compileranweisung
Option Explicit
gesetzt werden.
In der VB- Entwicklungsumgebung kann unter Extras\Optionen\Editor eingestellt werden, dass jedes neu erzeugte Modul am Anfang ein solches Option Explicit gestempelt bekommt. Dazu bei Variablendeklarationen erforderlich einen Haken setzen.
Der aktuelle Typ einer Variable kann mittels der Type- Name Funktion bestimmt werden. Dies ist besonders bei Variantvariablen hilfreich:
x = 123 typ_x = TypeName(x) ' typ_x = "Integer"
Mit den Prädikaten IsNumeric und IsDate kann getestet werden, ob eine Zeichenkette in einen nummerischen- oder einen Datumswert gewandelt werden kann.
Dim eingabe As Variant, test As Boolean eingabe = "einundzwanzig" test = IsNumeric(eingabe) eingabe = "21a" test = IsNumeric(eingabe) eingabe = "21,1" test = IsNumeric(eingabe) eingabe = "21#1" test = IsNumeric(eingabe) '---------------------------------------------------------------- eingabe = "2003-01-31" ' Datumsangabe im ODBC- Format test = IsDate(eingabe) eingabe = "2003-31-01" ' Datumsformat im SQL- Server Format test = IsDate(eingabe) eingabe = "2003-14-07 15:12:00" test = IsDate(eingabe) eingabe = #7/14/2003 3:12:00 PM# test = IsDate(eingabe)
Wurde einer Variantvariable noch kein Wert zugewiesen, dann befindet sich das Typkodefeld in einem Startzustand EMPTY. Dieser Besondere Zustand kann mittels des Prädikates IsEmpty geprüft werden.
Bei der Datenbank-Programmierung trifft man sehr häufig auf Null-Felder, also Felder, die absolut leer sind. VB kennt für diesen Zustand die Konstante Null, welche nur selten für sinnvolle Operationen benutzt werden kann, im Gegensatz zu Empty, das sich wie ein neutrales Element (bzgl. Addition) verhält.
So ergibt z.B. Null + 5 einfach nur Null. Eine Zuweisung von Null an einen nicht-Variant erzeugt sogar einen Fehler. Mittels des Prädikates IsNull kann auf einen Null- Wert geprüft werden.
Input- Formularelemente speichern Werte immer als Zeichenketten.
Funktion |
Format |
---|---|
Asc(zeichen) |
ASCII- Zeichenwert |
Cbool(d) |
Umwandlung in einen Boolean |
CByte(wert) |
Umwandlung in Byte |
CCur(wert) |
Umwandlung ins Währungstyp |
CDate(wert) |
Umwandlung in einen Datumstyp |
CDbl(wert) |
Umwandlung in doppelt genaue Fließkomma |
Chr(code) |
Zeichen aus Ascii- Code erzeugen |
CInt(wert) |
In einen Integer umwandeln |
CLng(wert) |
In einen Long umwandeln |
CSng(wert) |
Umwandlung in einfach genaue Fließkommazahl |
Fix(wert) |
Abschneiden der Nachkommastellen -8.4 wird zu -8 |
Int(wert) |
Umwandeln in Integer -8.4 wird zu -9 |
Implementieren Sie das Prädikat IsInteger(test as Variant) welches true zurückgibt, wenn test ein Integer- Literal ist, und sonst false.
Mittels der Format(Zahl, "Formatstring") Funktion kann ein Zahlenwert in eine Formatierte Zeichenkette umgewandelt werden.
dim ztxt as string ztxt = Format(1234.5678, "000000,##") 'ztxt hat jetzt den Wert 001234,57
Zeichenketten können mit den Operatoren + und & zu einer neuen Verbunden werden.
Funktion |
Beschreibung |
---|---|
Mid(zk, pos, länge) |
Schneidet aus Zeichenkette zk ab Position pos einen Substring der Länge länge aus. |
Len(zk) |
Bestimmt die Anzahl der Zeichen in Zeichenkette zk |
UCase(zk) |
Wandelt alle Zeichen in der Zeichenkette zk in Großbuchstaben um. |
LCase(zk) |
Wandelt alle Zeichen in der Zeichenkette zk in Kleinbuchstaben um. |
LTrim(zk), RTrim(zk), Trim(zk) |
Eliminiert alle Leerzeichen am Anfang, am Ende und am Anfang und Ende der Zeichenkette zk |
InStr(Start, zk1, zk2) |
liefert Position des ersten Vorkommens von zk2 innerhalb von zk1 ab Start |
Ü: Romzahl
Datumsangaben werden als Variant- Subtyp Date gespeichert.
Dim dat As Date
Etwas problematisch sind die Literale für Datumsangaben. Sie müssen stets im amerikanischen Format vorliegen (Monat/Tag/Uhrzeit) wobei sie in #-Symbolen geklammert werden
weihnachten = #12/24/2003#
Möchte man lieber das europäische Datumsformat verwenden, dann kann die Cdate- Funktion verwendet werden:
silvester = CDate(31.12.2003 00:00)
Aus einzelnen Partikeln wie Jahr, Monat und Tag kann ein Datumswert mittels der Funktion DateSerial gewonnen werden:
silvester = DateSerial(2003, 12, 31)
Das aktuelle Datum wird mittels der eingebauten Funktion Now bestimmt
dat = Now ' Bestimmt aktuelles Datum und Uhrzeit
Au einem Datum sind Partikel wie Tag, Monat und Jahr herauslösbar
Dim tag As Integer, monat As Integer, jahr As Integer tag = Day(dat) monat = Month(dat) jahr = Year(dat)
Zur Bestimmung von Wochentagnummer und Name gibt es wiederum spezielle Funktionen
' Wochentagnummer und Wochentagname Dim wtagnr As Integer, wtagname As String wtagnr = Weekday(dat, vbMonday) wtagname = WeekdayName(wtagnr, , vbMonday)
Der Zeitraum zwischen zwei Zeitpunkten kann mittels der Funktion DateDiff berechnet werden:
' Seit wieviel Tagen gibt es Unix Dim unixzeit_in_tagen As Integer unixzeit_in_tagen = DateDiff("d", DateSerial(1970, 1, 1), Now)
Zeitpunkte in der Zukunftund in der Vergangenheit können mittels DateAdd berechnet werden:
' Berechnen des Fälligkeitsdatums mittels DateAdd Dim faelligkeit As Date faelligkeit = DateAdd("m", 1, Now)
Ü: Gbt-Wochentag, Wieviel Tage lebe ich
Zur Verarbeitung tabellarischer Daten dienen in VB Arrays. Durch die Deklaration eines Arrays werden im RAM n Speicherplätze zur Aufnahme von Werten des Typs x reserviert.
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 Array- Deklaration ergibt sich folgendes Format im Arbeitsspeicher:
Der
Zugriff auf die Elemente eines Arrays erfolgt über den Namen und
den Indizes:
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 Array- Daten 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
Ü: Min/Max- Suche, Sortieren
Der größte und der kleinste Index pro Dimension kann mittels der Funktionen UBound und LBound wie folgt ermittelt werden:
Dim translator(1 To 4, 1 To 2) As String translator(1, 1) = "unten": translator(1, 2) = "down" translator(2, 1) = "oben": translator(2, 2) = "up" translator(3, 1) = "links": translator(3, 2) = "left" translator(4, 1) = "rechts": translator(4, 2) = "right" Dim zeile As Integer For zeile = LBound(translator, 1) To UBound(translator, 1) For spalte = LBound(translator, 2) To UBound(translator, 2) Range("A3").Cells(zeile, spalte).Value = translator(zeile, spalte) Next Next
Der Indexbereich eines Arrays kann auch völlig Flexibel mittels To Direktive definiert werden:
Dim Umsatzprognose(5 To 10) as Currency print LBound(Umsatzprognose) ' =5 print UBound(Umsatzprognose) ' =10
Die Anzahl der Plätze eines gewöhnlichen Arrays wird bei der Deklaration fest definiert. Wird ein Array mit Daten kontinuierlich gefüllt, dann läuft es irgend wann einmal voll. Sollen weitere Daten im Array abgelegt werden, dann muß es vergrößert werden.
Gewöhnliche Arrays sind nicht vergrößerbar. VB bietet einen zweiten Typ von Arrays, die sog. dynamischen Arrays. Sie werden mit einem unbestimmten max. Index wie folgt deklariert:
dim a() as Integer
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)
Ü: Prog. Messwerterfassung (akt. Wert, dyn. Mittelwert)
S.124
Dim telbuch as New Dictionary
telbuch.add "Schlüssel-1", wert1 : telbuch.add "Schlüssel-N", wertN
dim key as String for each key in telbuch MsgBox telbuch(key) next key
Eine spezielle Form von Variabeln sind Konstanten. Eine Konstante erhält bei der Deklarartion einen Wert zugewiesen. Im weiteren Programmablauf kann der Konstanten kein neuer Wert zugewiesen werden.
Const Name_der_Konstante = Wert
Beispiel
Const Pi = 3.142
Der Typ der Konstante wird automatisch bei der Zuweisung des Wertes aus diesem bestimmt.
In VBA gibt es eine Menge vordefinierte Konstanten, z.B. für Farbwerte (z.B. vbRed) oder für Zeilenumbruchszeichen (z.B. vbCrLf). Diese können im Objektexplorer unter der VBA- Bibliothek studiert werden.
|
|
|
|
---|---|---|---|
|
Applikation |
|
|
|
|
|
|
|
|
Modul 1 |
|
|
|
|
Public eingabezeile as String ' Variable in der gesamten Anwendung sichtbar |
|
|
|
Private akku as Double ' Variable nur im Modul1 sichtbar |
|
|
|
Private Sub addiere_click() |
|
|
|
Dim wert as Double ' Variable nur in der Prozedur sichtbar |
|
|
|
wert = Val(eingabezeile) |
|
|
|
akku = akku + wert |
|
|
|
End Sub |
|
|
|
|
|
|
|
|
|
|
Modul 2 |
|
|
|
|
Private arabzahl as Integer ' Variable nur in Modul2 sichtbar |
|
|
|
Private Sub M_Click() |
|
|
|
arabzahl = arabzahl + 1000 |
|
|
|
eingabezeile = Str$(arabzahl) |
|
|
|
End Sub |
|
|
|
|
|
|
|
|
|
|
|
|
In seiner Grundbetriebsart lädt der Computer eine Anweisung nach der anderen aus dem Arbeitsspeicher und führt sie aus. Viele Algorithmen erfordern jedoch, dass einige Abschnitte 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, dass 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.
Bedingte Ausdrücke haben die Form
IIF(Bedingung, ExprA, ExprB)
Zuerst wird die Bedingung evaluiert. Ergibt sie den Wert true, dann wird ExprA evaluiert und deren Wert ersetzt den kompletten bedingten Ausdruck. Sonst wird ExprB evaluiert, und deren Wert ersetzt den Ausdruck.
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 nicht abweisende 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 nicht abweisenden Schleife wird die Bedingung erst am Ende des Programmabschnittes überprüft. Trifft sie zu, dann wird der Befehlszähler auf den Abschnittsanfang 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
Zum Durchlaufen aller Felder eines Arrays kann die For Each - Schleife benutzt werden.
Fehler werden ignoriert:
On Error Resume Next
Nach Auftreten eines Fehlers wird zu einer Sprungmarke gesprungen, und das Programm dort fortgesetzt:
On Error Goto Sprungmarke
Informationen zum Fehler sind über das Fehlerobjekt Err abrufbar:
Err.Number ' Fehlernummer Err.Description ' Fehlerbeschreibung
In VBA werden Unterprogramme unterschieden nach Prozeduren und Funktionen. Für jeden Typ gibt es eine spezielle Syntax.
Mit Unterprogrammen werden verallgemeinerte Routinen wie z.B. HintergrundAllerSelektierterZellenRotFärben verstanden. Sie kapseln sich häufig wiederholende Programmabschnitte und reduzieren damit die Anzahl an Codezeilen. Bsp:
' Deklaration einer Prozedur Sub SetBackgroundColorRed(select as Range) : End Sub ' Aufruf einer Prozedur SetBackgroundColorRed Selection
Funktionen ordnen einer Menge von Argumenten einen Funktionswert zu. In VB kann diese Zuordnung durch einen Spzeialform eines Unterprogrammes, der Function beschrieben werden. Beispiel: Umrechnen einer Wegeinheit in die Basiseinheit Meter:
' Deklaration der Funktion Function ToMeter(value as Double, unit as String) as Double ' Rückgabewert deklarieren : ToMeter = wertInMetern End Function ' Aufruf der Funktion summeWege = ToMeter(12, "km") + ToMeter(20000, "dm")
Mittels VBA kann die Menge der Excel – Funktionen wie Summe, Mittelwert usw. um selbsdefinierte erweitert werden. Jedoch sind folgende Einschränkungen zu beachten:
Die Funktion muss in einem Modul definiert werden. Wird die Funktion in einem Excel- Tabellenobjekt oder einem Formular definiert, dann kann sie nicht verwendet werden
Rückgabewert und Parameter müssen vom Typ Variant sein !
Treten in der Funktion Fehler auf, ist Excel nicht sehr kooperativ. Wird die Funktion das erste Mal verwendet, dann sollte der Funktionsassistent aufgerufen werden.
Beispiel:
Function meineMwSt(pNetto, pWg) Dim Netto As Currency, Wg As String If TypeName(pNetto) = "Range" Then Netto = pNetto.Cells(1, 1).Value Else Netto = pNetto End If If TypeName(pWg) = "Range" Then Wg = pWg.Cells(1, 1).Value Else Wg = pWg End If If Wg = "A" Or Wg = "a" Then meineMwSt = Netto * 1.07 Else meineMwSt = Netto * 1.16 End If End Function
Mittels der MSForms- Bibliothek bietet Excel einen Satz grafischer Steuerelemente an, mit denen Excel – Makros graphische Benutzeroberflächen verpasst werden können. Die Steuerelemente können direkt in auf einem Tabellenblatt oder auf einem separaten Formular platziert werden. Wer jedoch vermutet, dass es sich in beiden Fällen um dieselben Steuerelemente handelt, irrt: Steuerelemente auf Tabellenblättern haben teilweise andere Eigenschaften als Steuerelemente auf Dialogen !
Alle Steuerelemente verfügen über einen gemeinsamen Satz an Methoden und Eigenschaften. Das folgende Objektdiagramm gibt eine Überblick über die wichtigsten:
Private Sub UserForm_Initialize() With ListBox1 .AddItem ("Gagarin") .AddItem ("Amstrong") .AddItem ("Taikonaut") .MultiSelect = fmMultiSelectSingle End With End Sub Private Sub btnLBoxAuswerten_Click() Dim txt As String, i As Integer If ListBox1.MultiSelect = fmMultiSelectMulti Then For i = 0 To ListBox1.ListCount - 1 If ListBox1.Selected(i) Then txt = txt + ListBox1.List(i) + vbCrLf End If Next Else txt = ListBox1.List(ListBox1.ListIndex) End If TextBox1.Text = txt End Sub
Unter Weitere Steuerelemente kann aus dem großen Angebot von ActiveX- Controls ausgewählt werden. Bsp.: MSCAL- Kalender Steuerelement.
Über Formulare kann dem Benutzer eine komfortable Steuerung von Makros ermöglicht werden
Durch die Methoden show und hide können Formulare angezeigt und wieder verdeckt werden:
Private Sub btnFormularVerdecken_Click() UserForm1.Hide End Sub Private Sub btnStarteFormular_Click() UserForm1.Show (False) End Sub
Jedes selbstdefinierte Formular in Excel folgt dem Bauplan der Klasse UserForm. Im Folgenden ein Ausschnitt aus dem Objektmodell der Klasse UserForm.
Alle Steuerelemente eines Formulars sind in der Controls- Collection aufgelistet
Dim elem As Control, i As Integer For Each elem In UserForm1.Controls elem.ControlTipText = tbxTipText & i i = i + 1 Next
Mittels komfortabler Dialoge können Dateipfade zum lesen und schreiben geöffnet werden:
Application.GetOpenFilename ("Messdaten (*.csv), *.csv") Application.GetSaveAsFilename()
' Diagramm löschen ChartObjects(1).Delete ' neues Diagramm aufbauen ChartObjects.Add(135, 150, 400, 150).Name = "Plot" ChartObjects("Plot").Activate Dim bereich As String bereich = "B12:B" & (akt_anz_werte + 12) ActiveChart.ChartWizard Range(bereich), xlLine, , , , , 0
Es gibt zwei Varianten des Zugriffs auf Dateien: IO über die VBA- eigenen Funktionen (prozedural) und über eine COM- Klasse des Betriebssystems (objektorientiert)
Zeit |
Operation |
Beispiel |
---|---|---|
1 |
Öffnen |
Open "Daten.txt" For Input As #1 |
2 |
Lesen |
Dim w as String Input #1, w |
3 |
Schließen |
Close #1 |
Operation |
Textdateien |
Typisierte Dateien |
---|---|---|
Trennzeichen zw. Datensätze |
ASCII 13 (Wagenrücklauf) und 10 (Zeilenvorschub) |
keine |
Öffnen |
'nur lesen Open <Dateiname> For Input As #<DatNr> 'nur schreiben Open <Dateiname> For Output As #<DatNr> 'Anhängen von Text Open <Dateiname> For Append As #<DatNr> |
'lesen und schreiben Open <Dateiname> For Random As #<DatNr> |
Lesen |
'Zeilenweise einlesen Dim s as String Line Input #1, s 'Anz Zeichen lesen (z.B. 3) s = Input(3, 1) |
' N-ten Datensatz lesen Get #1, N, <Datensatzvariabel> |
Schreiben |
Print #1, "Auszugebender Text" |
'N-ten Datensatz schreiben Put #1, N, <Datensatzvariabel> |
Dateilänge in Byte bestimmen |
Dim laenge as Integer laenge = LOF(1) |
|
Bestimmen, ob Datensatzende erreicht wurde |
Dim datenstzende as Boolean datensatzende = EOF(1) |
|
Anzahl der Datensätze Bestimmen |
Dim anz_datensaetze as Integer anz_datensaetze = LOF(1)/LEN(<datensatz>) |
|
Datensatzzeiger positionieren |
Seek #1, <neue_position> |
|
aktuelle Datensatzposition bestimmen |
Dim akt_pos as Integer akt_pos = Seek(#1) |
Die Com- Komponente, welche eine objektorientierte Schnittstelle für das Dateisystem anbietet, befindet sich in Microsoft Scripting Runtime. Auf diese muss vor Benutzung der Com- Klassen über Extras/Verweise im VBA- Editor verwiesen werden.
Option Explicit ' (c) Martin Korneffel 15.12.2008 ' Implementierung eines Dateibaumscanners unter VBA '--------------------------------------------------------------------------------- ' Fehlernummern Const ErrDirectoryDontExist = 1 '------------------------------------------------------------------------------------------- ' Implementierungsdetails ' Zugreifen auf den Ordner über die ActivX- Komponente Scripting.FileSystemObject ' Voraussetzungen: In Extras/Verweise auf "Microsoft Scripting Runtime" verweisen Dim mFso As Scripting.FileSystemObject Dim mCountFiles As Long Dim mCountDirs As Long Dim mStopScan As Boolean '------------------------------------------------------------------------------------------- ' Ereignisse ' Wird zu Begin des Verzeichnisdurchlaufes aufgerufen Event BeginScanDir(rootPath As String) ' Wird am Ende des Verzeichnisdurchlaufes aufgerufen Event EndScanDir(rootPath As String) ' Wird beim Betreten eines Unterverzeichnisses aufgerufen Event EnterDir(path As String, name As String) ' Wird beim Verlassen eines Unterverzeichnisses aufgerufen Event ExitDir(path As String, name As String) ' Wird beim besuchen einer Datei aufgerufen Event TouchFile(path As String, name As String) Private Sub Class_Initialize() Set mFso = New Scripting.FileSystemObject End Sub ' nur Leseeigenschaften für die Statistikdaten eines Dateidurchlaufes Property Get CountFiles() As Long CountFiles = mCountFiles End Property Property Get CountDirs() As Long CountDirs = mCountDirs End Property Property Let StopScan(value As Boolean) mStopScan = value End Property ' Fehlerereignis aus dem Klassenmodul heraus auslösen Sub Raise(errId As Integer, descr As String) With Err .Clear .Description = descr .Number = vbObjectError + 513 + errId End With Err.Raise Err.Number End Sub '-------------------------------------------------------------------------------------- Public Sub scan(rootPath As String) ' Reset der Statistik mCountDirs = 0 mCountFiles = 0 mStopScan = False ' Start des Durchlaufes If Not mFso.FolderExists(rootPath) Then Raise ErrDirectoryDontExist, "Das Verzeichnis " & rootPath & " existiert nicht" Exit Sub End If RaiseEvent BeginScanDir(rootPath) Dim folder As Object Set folder = mFso.GetFolder(rootPath) Dim endedWithFailure As Boolean endedWithFailure = traverse(rootPath, folder.name) RaiseEvent EndScanDir(rootPath) End Sub Function traverse(path As String, name As String) As Boolean If mStopScan Then traverse = False Exit Function End If If mFso.FolderExists(path) Then RaiseEvent EnterDir(path, name) ' Alle Unterverzeichnisse durchlaufen Dim subFolder As Object For Each subFolder In mFso.GetFolder(path).SubFolders mCountDirs = mCountDirs + 1 If (Not traverse(subFolder.path, subFolder.name)) Then traverse = False Exit Function End If Next ' Alle Dateien im Unterverzeichnis durchlaufen Dim file As Object For Each file In mFso.GetFolder(path).files mCountFiles = mCountFiles + 1 RaiseEvent TouchFile(file.path, file.name) Next RaiseEvent ExitDir(path, name) Else Raise ErrDirectoryDontExist, "Das Verzeichnis " & path & " existiert nicht" traverse = False Exit Function End If traverse = True End Function
Option Explicit ' © Martin Korneffel 15.12.2008 ' Einsatz der Verzeichnisscannerklasse, die auf FileSystemObjects basiert '------------------------------------------------------------------------------------------------- ' DirTree- Objektvariable mit Events einführen Dim WithEvents scanner As DirTree ' Dictionary, mit der die Dateitypen auf den summierten Speicherplatzverbrauch abgebildet werden Dim dictTypeSumSize As Scripting.Dictionary Private Sub btnQuit_Click() Me.Hide End Sub '------------------------------------------------------------------------------------------------ ' Eventhandler des Dateiscanners Private Sub scanner_BeginScanDir(rootPath As String) With lbxSizePerTyp .Clear .AddItem ' Spalten des 1. Lisboxeintrages setzen .List(0, 0) = "Dateityp" .List(0, 1) = "Größe in Bytes" End With ' Dictionary, die den Typen die Summe des Speicherplatzes zuordnet Set dictTypeSumSize = New Scripting.Dictionary dictTypeSumSize.CompareMode = 0 End Sub Private Sub scanner_EndScanDir(rootPath As String) Dim key For Each key In dictTypeSumSize With lbxSizePerTyp ' Neue Zeile hinzufügen .AddItem .List(.ListCount - 1, 0) = key .List(.ListCount - 1, 1) = dictTypeSumSize.Item(key) End With Next End Sub Private Sub scanner_TouchFile(filename As String, name As String) Dim fso As Object Set fso = New Scripting.FileSystemObject Dim file As Object Set file = fso.GetFile(filename) If dictTypeSumSize.Exists(file.Type) Then dictTypeSumSize.Item(file.Type) = dictTypeSumSize.Item(file.Type) + file.Size Else dictTypeSumSize.Add file.Type, file.Size End If End Sub ' Konstruktor des UserForms, über welches der Dateiscan gesteuert wird Private Sub UserForm_Initialize() ' Anlegen des Verzeichnisscanner- Objektes (frühe Bindung mittels New ... ' Späte Bindung wäre gegeben mittels CreateObject("Scripting.FileSystemObjects") Set scanner = New DirTree End Sub ' Eventhandler vom UserForm für den Startbutton des Verzeichnisscans Private Sub btnStartScan_Click() Dim rootPath As String If IsEmpty(tbxRootPath.value) Then MsgBox "Sie müssen eine Dateipfad eingeben" Exit Sub End If rootPath = tbxRootPath.value On Error Resume Next scanner.scan (rootPath) If Err.Number <> 0 Then MsgBox "Beim Dateiscann ist ein Fehler aufgetreten: " & Err.Description Exit Sub End If tbxCountDirs.value = CStr(scanner.CountDirs) tbxCountFiles.value = CStr(scanner.CountFiles) End Sub
Option Explicit ' (C) Martin Korneffel 2008 ' Einlesen und analysieren von XML- Dokumenten mittels MSXML ' Verweis auf "Microsoft XML 6.0" muss gesetzt werden Private Sub btnXmlDocEinlesen_Click() Dim filename filename = Application.GetOpenFilename() ' = Planeten.xml If IsEmpty(filename) Then MsgBox "Es muss eine xml- Datei ausgewählt werden" Exit Sub End If ' Xml- Datei in den Arbeitsspeicher als DOM- Baumstruktur laden Dim doc As New MSXML2.DOMDocument60 ' Synchrones laden einschalten doc.async = False doc.Load ("file://" & filename) ' Den im Dokument verwendeten Defaultnamespace einem Präfix (my) zuweisen, damit ' die XPath- Ausdrücke gebildet werden können doc.setProperty "SelectionNamespaces", "xmlns:my=""http://www.tracs.de/Planeten.xsd""" ' Abfragen der Knoten, deren Elementname = 'Planet' ist Dim nodelist As MSXML2.IXMLDOMNodeList Set nodelist = doc.selectNodes("//my:Planet") ' Durchlaufen der gefundenen Knotenmenge Dim node As MSXML2.IXMLDOMNode Dim zeile As Integer zeile = 1 For Each node In nodelist With Range("B10") ' Elementname ausgeben (= Planet) .Cells(zeile, 1).Value = node.nodeName ' Auslesen der Attribute im Element 'Planet' .Cells(zeile, 2).Value = node.Attributes.getNamedItem("name").nodeValue .Cells(zeile, 3).Value = "Durchmesser = " Dim ndDia As IXMLDOMNode Set ndDia = node.selectSingleNode("./my:Durchmesser") .Cells(zeile, 4).Value = ndDia.Attributes.getNamedItem("Wert").nodeValue End With zeile = zeile + 1 Next End Sub