Portable Basic-Programme

Portable Basic-Programme

Zielgruppe sind StudentInnen und ambitionierte Informatik-Amateure

Grundkenntnisse der Tabellen-Kalkulation und von Basic (VBA) werden vorausgesetzt.


Faustregeln


Mit diesen Regeln kann man einfache Aufgaben portabel programmieren:


Beachten sie in jedem Fall die Hinweise zum → Portieren von Basic-Quelltext zwischen Programmen.

Basic-Interpreter Optionen


Jedes gängige Tabellen-Kalkulations-Programm enthält einen Basic-Interpreter.
Dieser muss vor der Verwendung in der Konfiguration (→ LibreOffice, → MS-Excel, → OpenOffice) aktiviert werden.



Alle verwendeten Optionen müssen am Anfang eines Basic-Moduls stehen. Davor sind nur Kommentare zulässig, jedoch kein anderer Basic-Quelltext.



Beispiel: Wenn man eine Variable mit dem Namen i im Basic-Programm verwenden will, dann muss man vorher in einer Dim-Anweisung Name und Typ bekanntgeben:
Dim i As Integer
Wenn man die Variable ohne Deklaration verwendet, dann wird ein Fehler gemeldet.



Setzen sie diese Option bei eigenen Programmen: Basic-Arrays verhalten sich dann so wie in allen modernen Programmiersprachen.
Verwenden sie diese Option nicht, wenn sie Basic-Quelltext aus fremden Basic-Beispielen importieren.



Die Option wirkt sich auf die Portablilität nicht merkbar aus, insbesondere nicht auf die Verwendung des Range-Objekts.



LibreOffice kann mit dieser Option Range-Objekte genauso verwenden wie in MS-VBA. Die Basic-Programme sind damit zwischen MS-Excel und LibreOffice-Calc portabel.

Leider funktioniert die Option manchmal nur dann, wenn ein Basic-Programm geändert wurde. Wenn man die Datei speichert und erneut öffnet, dann werden die Basic-Module nicht übersetzt und es ist keine darin enthaltene Funktion verwendbar.
Wenn man ein einziges Zeichen im Basic-Quelltext ändert, dann wird er neu übersetzt und alle Basic-Funktionen sind wieder verwendbar.
Das ist allerdings in der Praxis unzumutbar, daher wurde die Option vorläufig aus den hier gezeigten Beiospielen entfernt.

Funktions-Argumente


Rufen sie eine Function immer mit genau der programmierten Anzahl von Argumenten und mit genau den angegebenen Typen auf.

Beispiel
Dieses Beispiel addiert 2 Zahlenwerte. Die Funktion erhält daher genau 2 Argumente (hier v1 und v2). Mehrere Argumente werden im Basic-Quelltext immer durch , Beistriche getrennt.
Function Add (v1 As Double, v2 As Double) As Double
Add = v1 + v2
End Function

Anwendung
in einer Zelle der Tabellen-Kalkulation:
=Add(A1;A2)
=Add(A1;123)
=Add(234;A2)
(Nur in deutschen Versionen der Tabellen-Kalkulation wird ein ; Strichpunkt als Trennzeichen verwendet.



Die wichtigsten Typen:
Double (Gleitkomma-Zahl) verwendet man im Zweifel für alle Zahlen-Werte.
Integer (Ganze Zahl) kann man nur für ganze Zahlen verwenden. Je nach Anwendung kann der verwendbare Bereich mit ± 32767 begrenzt sein.
String (Zeichenkette), z.B. "ABC" aber auch "0123"

Wenn man einen Typ nicht angibt, dann wird ungefragt der Typ Variant verwendet, mit dem wesentlich mehr Fehler auftreten können.



Verwenden sie nach Möglichkeit keine dieser Typen:
Variant wird von Basic-Interpretern je nach Version unterschiedlich verwendet.
Range (Bezug auf einen Zellen-Bereich) ist wesentlich schwieriger zu programmieren. Ein Beispiel wäre die Formel =MyProg(A1:B5) in einer Kalkulations-Zelle.

Man kann Argumente auch ohne Angabe ihres Typs programmieren: Damit liefert man die AnwenderInnen jedoch dem (unterschiedlichen) Verhalten ihrer jeweiligen Basic-Interpreter-Programe aus.

Groß- und Klein-Buchstaben


Man sollte - nicht nur in der Programmiersprache Basic - prinzipiell nur portabel programmieren. Daher wird empfohlen:
  • Verwenden sie für die Namen von Variablen prinzipilell nur Klein-Buchstaben, z.B. test
  • Beginnen sie die Namen von Konstanten mit Groß-Buchstaben, z.B. Pi oder MWStSatz
  • Verwenden sie niemals mehrere Namen, die sich nur in Groß- oder Klein-Buchstaben unterscheiden, z.B. test, Test

ReadOnly-Argumente


Es ist für wenig erfahrene EntwicklerInnen schwierig, die von einem Programm verwendete Methode herauszufinden oder zu beeinflussen.
Als sichere Faustregel gilt daher:

Argumente sollte man nur lesen, niemals ihren Wert ändern (schreiben).


Sicheres Beispiel

Auch diese Funktion addiert +1 zu ihrem Argument:
Function Inc(ro As Double) As Double
Dim rw As Double
rw = ro
rw = rw + 1
Inc = rw
End Function

Durch saubere Programmierung kann man dieses Problem sicher vermeiden:
Die Typen aller Argumente und des Rückgabe-Werts sind ausdrücklich angegeben.
Der problematische Typ Variant wird nicht verwendet.
Das Argument wird nicht geändert, sondern nur gelesen: Sein Wert wird an eine private Variable (hier rw) zugewiesen, die man gefahrlos ändern kann.

Die Anwendung in einer Kalkulations-Zelle ist sicher:
=Inc(A1)

Optionale Argumente


Function Add(Optional x As Variant, Optional y As Variant) As Double
Dim myx,myy,myz as Double
If (IsMissing(x)) Then
myx = 0
Else
myx = CDbl(x)
End If
If (IsMissing(y)) Then
myy = 0
Else
myy = CDbl(y)
End If
myz = myx + myy
Add = myz
End Function


Es gibt auch einige andere Möglichkeiten, um optionale Argumente zu programmieren. Davon wird abgeraten, weil sie nicht zuverlässig portabel sind. Wenn die Kalkulations-Datei auf einem anderen Betriebssystem oder mit einem anderen Programm verwendet wird, dann kann sie unterschiedliche Ergebnisse liefern.



Bei der Zuweisung eines Arguments an eine private Variable (myx, myy) wird der Typ umgewandelt. Für Gleitkomma-Zahlen verwendet man dazu die Funktion CDbl(), für Ganze Zahlen CInt()
Wenn man die Typ-Umwandlung nicht programmiert, dann wird sie vom Basic-Interpreter ohne Möglichkeit der Beeinflussung ausgeführt.

Wenn die Werte aller privaten Variablen eindeutig festgelegt sind, wird die Funktion berechnet, zuletzt das Ergebnis (hier: myz) zurückgegeben.



Wenn man Argumente vom Typ Variant verwendet, dann darf man deren Werte keinesfalls ändern, weil das Rückwirkungen auf jene Zellen haben kann, aus denen die Daten der Argumente stammen.
Daher muss man die Werte der Argumente vor der Verwendung an private Variable zuweisen.

Bei der Zuweisung können Fehler auftreten, wenn ein/e AnwenderIn unerwartete Werte als Argument verwendet. Daher sollte man nicht nur den zugewiesenen Typ (hier mit Funktion CDbl() ) kontrollieren, sondern darüber hinaus auch eine Validierung des Werts anschließen.

Bereich


Man kann Bereiche auch an Basic-Funktionen als Argumente übergeben, eine portable Programmierung scheint jedoch derzeit nicht möglich. Alle betroffenen Beispiele dieses Webs werden daher in 2 verschiedenen Versionen gezeigt.


Beispiel für MS-Excel

Function sum_excel(bereich As Range) As Double
Dim summe As Double
Dim zelle As Range
summe = 0
For Each zelle In bereich
summe = summe + zelle.Value
Next
sum_excel = summe
End Function
Diese Syntax ist einfach, übersichtlich und funktioniert auch mit einer einzelnen Zelle als Argument.


Diese Version behandelt einen Bereich als Objekt vom Typ Range
Umgekehrt ist es nicht realistisch in MS-VBA einen Bereich als Array zu behandeln, obwohl die Informations-Funktion IsArray() einen Bereich als Array angibt.

Es erscheint derzeit nicht möglich, mit einem einzigen Basic-Quelltext eine portable Version von Funktionen mit Range-Argumenten zu erstellen.

Trigger



• Ausnahmen: Einige wenige Funktionen werden nach jeder Änderung irgend einer Zelle oder mit Taste F9 neu berechnet, z.B. =ZUFALLSZAHL() oder =JETZT()



Basic-Funktion mit Auslöser (Trigger):
Function TrigDemo(Optional Trigger As Variant)
Dim MyTrig As Double
If (IsMissing(Trigger)) Then
MyTrig = 0
Else
MyTrig = CDbl(Trigger)
End If
TrigDemo = Rnd
End Function

Bei dieser Anwendung wird die Funktion nur 1mal berechnet:
=TrigDemo()
Hier wird immer dann neu berechnet, wenn sich der Wert in Zelle A1 geändert hat:
=TrigDemo(A1)
Hier wird die Funktion bei jeder Änderung oder mit Taste F9 neu berechnet:
=TrigDemo(ZUFALLSZAHL())

Die Trigger-Variable wird im Programm nur scheinbar verwendet, damit sie von einem Basic-Interpreter nicht weg-rationalisiert wird.



Function Zufall_Normal( _
Optional Trigger As Variant) As Double
Dim w, x1, x2 As Double
If (Not IsMissing(Trigger)) Then
w = CDbl(Trigger)
End If
w = 1
While (w >= 1)
x1 = 2 * Rnd - 1
x2 = 2 * Rnd - 1
w = x1 * x1 + x2 * x2
Wend
w = Sqr((-2 * Log(w)) / w)
Zufall_Normal = w
End Function

Functions & Subs



Beispiel (Addiert +1 zu einer Zahl):
Function Inc(v As Double) As Double
Inc = v + 1
End Function

Anwendung:
Tragen sie in eine Kalkulations-Zelle einen beliebigen Zahlenwert ein, z.B.
A1=ZUFALLSZAHL()
Verwenden sie die Funktion mit Bezug auf den Zahlenwert, z.B.
B1=Inc(A1)
Neue Zufallswerte mit Taste F9



Beispiel: (Öffnet ein Meldungs-Fenster):
Sub Hallo()
MsgBox "Hier ist Hallo"
End Sub

Anwendung:
Legen sie ein beliebiges Objekt an, z.B. einen Button, und verknüpfen sie es mit dem Sub. Beim Anklicken wird das Sub ausgeführt.

Details im Beispiel → Animation

Public oder Private


Es hat keine negativen Folgen, Private oder Public trotzdem zu verwenden, deshalb ist dieses Thema in den Faustregeln nicht angeführt.

Rechnen sie jedoch damit, dass jede ihrer Funktionen für alle AnwenderInnen sichtbar und verwendbar ist:
Kommentieren sie daher jede Funktion, ihre Anwendung und deren Grenzen.

Namen statt Adressen



Lösung: Definieren sie Namen für wichtige Zellen, z.B. MWStSatz für Zelle B1

Dazu markiert man die Zelle und trägt den Namen in das Adress-Feld ein (meist nahe der linken oberen Ecke).
Quittieren sie mit Return- oder Enter-Taste: Danach sollte dort nicht mehr die Adresse angezeigt werden (B1) sondern der Name (MWStSatz).
Namen dürfen keine Leerzeichen oder Sonderzeichen enthalten und nicht mit Spalten oder Adressen verwechselbar sein: Namen wie M oder M3 sind verboten.

Ändern sie die Formel in Zelle B3 auf
=B2*(1+MWStSatz)
und das Basic-Programm auf
mws = Range("MWStSatz").Value
Danach rechnen beide Versionen korrekt - Auch dann, wenn man die Zelle mit dem MWSt-Satz verschiebt.