Eigene Funktionen erstellen (Meter in Meilen & Celsius in Fahrenheit)

Eine Vielzahl an Funktionen und Formeln sind bereits standardmässig in Excel verfügbar. Dem Standarduser genügt dieses Angebot grundsätzlich, doch können auch da eigene Funktionen den Umgang mit Excel erleichtern. Dieser Blog zeigt auf, wie benutzerdefinierte Funktionen und Formeln angelegt werden können, die danach jederzeit verfügbar sind. Als Beispiel werden wir hier Meter in Meilen sowie Grad Celsius in Fahrenheit umwandeln.

Meter in Meilen

Die erste Funktion, die angelegt werden soll, ist die Umwandlung von Meter in Meilen (eine englische Meile beträgt 1'609.344 Meter). Öffne hierzu eine neue Arbeitsmappe und gehe in die VBA-Umgebung (Alt + F11 oder Rechtsklick auf ein Tabellenblatt → "Code anzeigen"). Auf der linken Seite befindet sich die Projekt-Übersicht - dort sind alle geöffneten Excel-Dateien zu sehen. Mittels Rechtsklick auf die neue Arbeitsmappe lässt sich ein Modul einfügen, wo die Funktion eingepflegt werden kann:

NeuesModulEinfuegen

Im angelegten Modul1 wird nun die Funktion eingetragen. Für die Umrechnung von Meter in Meilen gilt folgender Code:

Public Function MeterInMeilen(ByVal X As Double)

MeterInMeilen = X / 1609.344

End Function

Die Formel nennen wir "MeterInMeilen". Achte bei der Vergabe der Namen darauf, dass diese nicht bereits vorhanden sind. In unserer Excel-Datei kann alsdann mit der Umwandlung begonnen werden. Die Funktion findet sich unter sämtlichen anderen - gebe in Excel einfach "=M" ein und die Vorschläge erscheinen in einer Auswahlliste, dort ist auch "MeterInMeilen" aufgeführt:

EigeneFunktionenAuswahl

Um die Umwandlung der Massangaben zu veranschaulichen, habe ich eine kleine Tabelle angelegt:

MeterInMeilen

In Zelle "B3" sind 1000 Meter eingetragen, dieser Wert kann selbst gewählt werden. In Zelle "C3" kommt unsere benutzerdefinierte Funktion zum Einsatz. Füge da nun die folgende Formel ein:

=MeterInMeilen(B3)

Ein simpler Bezug auf die Zelle "B3" reicht bereits aus, um die Meterangabe in Meilen zu konvertieren. Uns interessiert zudem, wie wir die Rückkonvertierung vornehmen können. Dazu wird folgender Programmcode eingetragen, um die Funktion "MeilenInMeter" anzulegen:

Public Function MeilenInMeter(ByVal X As Double)

MeilenInMeter = X * 1609.344

End Function

Diese Zeilen können direkt unterhalb von "End Function" der ersten Funktion in Modul1 eingetragen werden. In der Excel-Beispieltabelle kann für die Meter-Rückkonvertierung die neue Formel eingegeben werden:

=MeilenInMeter(C3)

Das Resultat davon ist wiederum exakt 1'000 Meter.

Celsius in Fahrenheit

Analog der Konvertierung oben soll nun zudem Grad Celsius in Fahrenheit umgewandelt werden können. Folgender Code erfüllt diese Anforderung:

Public Function CelsiusInFahrenheit(ByVal X As Double)

CelsiusInFahrenheit= X * 9 / 5 + 32

End Function

Wiederum als Beispieltabelle in Excel wird in Spalte C die Berechnung von diversen Temperaturangaben vorgenommen.

CelsiusInFahrenheit

Die angegebenen Werte sind korrekt, man könnte zudem die Dezimalstellen einblenden (beispielsweise 22 Grad Celsius entsprechen 71.6 Grad Fahrenheit). Die angelegte Funktion kann damit ebenfalls umgehen, da der Variablentyp "Double" gewählt wurde.

Auf die Rückkonvertierung wird hier nicht eingegangen, wir lassen dies als mögliche "Übungsaufgabe" offen. Bei Fragen kann stets die Kommentar-Sektion verwendet werden.

Zuletzt ist anzumerken, dass neben komplett neuen Funktionen wie den oben gezeigten Umwandlungs-Formeln auch bestehende Standard-Formeln individuell optimiert werden könnten. Ein Beispiel ist der SVERWEIS, bei dem Benutzer je nach dem immer wieder Probleme bekunden - bei dem Verweis gibt es diverse Fehlerursachen. Mit einer eigenen Funktion (z.B. analog der INDEX-VERGLEICH-Kombination) kann der SVERWEIS benutzerfreundlicher gestaltet werden und zugleich auch Daten links von dem Suchkriterium ausgeben.

Eigene Icons/Symbole zum Menüband hinzufügen

Wie man das Menüband individuell gestalten und um eigene Register und Sektionen erweitert kann, wurde vor einiger Zeit im Beitrag "Makro als Add-In einbetten" illustriert. Für die gewünschten Funktionen gibt es diverse Standard-Symbole, die man verwenden kann. Dies ist eine Übersicht:

StandardIcons

Je nach Anwendungsfall lässt sich jedoch kein passendes Bild finden - oder man strebt grundsätzlich eine komplett eigene Lösung an. Hier wird dargestellt, wie ein selbst erstelltes Symbol eingefügt werden kann: Die Bilddatei sollte im Format .png und quadratisch sein. Da es kleine Icons sind, sollten die Masse nicht über 256x256 Pixel sein. Ich habe ein Bild in Photoshop mit den Massen 100x100 Pixel erstellt und lokal abgespeichert:

ArrowPlus10

Die Funktion, die über dieses Symbol abgerufen werden soll, ist eine Erhöhung des selektierten Wertes um 10%. Um dieses Beispiel zu illustrieren, habe ich eine simple Umsatzplanung für das nächste Jahr erstellt:

Umsatzplanung2020

Es soll über die angesprochene Funktion entweder die aktuelle Menge oder der jetzige Preis um 10% erhöht werden, da sich der Umsatz ohnehin aus Preis * Menge zusammensetzt. Um dies zu bewerkstelligen, legst Du folgendes Makro an:

Sub IncreaseBy10Percent()

Dim CurrentValue As Double
Dim NewValue As Double

CurrentValue = ActiveCell.Value
NewValue = CurrentValue * 1.1
ActiveCell = NewValue

End Sub

(Beachte: Es sind keinerlei Kontrollen und Sicherheiten eingebaut. Es wird nicht überprüft, welcher Wert in der selektierte Zelle steht oder ob gar ein Bereich ausgewählt wurde - das kann zu Fehlermeldungen führen!)

Office RibbonX Editor

Um das Custom-Icon einzufügen, verwenden wir die Software "Office RibbonX Editor" (analog "Custom UI Editor"). Es handelt sich dabei nicht um ein Microsoft Produkt. Fernando Andreu hat das Tool auf GitHub zur Verfügung gestellt (hier geht es zur Release-Seite).

Nach dem Öffnen der Datei ist das gewünschte Excel-File auszuwählen (File → Open). Daraufhin fügen wir - je nach Excel-Version - einen "Custom UI Part" ein (ich verwende "Office 2010+"). Dies erfolgt via Rechtsklick auf die Excel-Datei im Editor:

InsertCustomUiPart

Als nächstes ist die erstellte Grafik einzufügen. Gehe dazu auf "Insert Icons". Wie im Screenshot unten ersichtlich ist das Icon ebenfalls innerhalb des Editors auf der linken Seite (Navigation) aufgeführt. Der fertige Code, um das entsprechende Icon ("ArrowPlus10.png") in ein neues Menüband-Register "Eigene Makros" und der Sektion "Umsatzplanung" einzubetten, ist unten dargestellt. Am Ende dieses Beitrags ist zudem der Code als "Zitat" zu finden - für Copy+Paste-Zwecke. Nach einer Anpassung in dem Editor kannst Du jederzeit auf "Validate" klicken, um den Code zu testen. Speichere die Änderungen im Editor ab ("Save") und öffne das Excel-File erneut.

RibbonXCode

Die obigen Bezeichnungen wie "Menüband-Register" oder "Sektion" können individuell ausgestaltet werden. Auch die Anordnung/Reihenfolge des Menübands kann hier beeinflusst werden (in Zeile 4: "insertAfterMso="). Im fertigen Screenshot unten habe ich unser eigenes Register hinter "TabHome" eingefügt, damit es auf der Abbildung besser ersichtlich ist:

RibbonSolution

Ein Klick auf diesen individuell gestalteten "Button" erhöht daraufhin den selektierten Wert wie gewünscht um 10%.

Dies ist der Code für den "Custom UI Part":

<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon>
<tabs>
<tab id="customTab" label="Eigene Makros" insertAfterMso="TabHelp">

<group id="customGroup" label="Umsatzplanung">
<button id="customButton1" label="Erhöhe Wert" size="large" onAction="IncreaseBy10Percent" image="ArrowPlus10" />

</group>
</tab>
</tabs>
</ribbon>
</customUI>

Loop durch Tabellenblätter mit Sheets.Index (VBA)

Angeknüpft an den letzten Beitrag zu dynamischen Formeln über mehrere Tabellenblätter, behandelt dieser Beitrag die Thematik, wie mittels einer VBA-Schleife (Loop) durch mehrere Tabellenblätter navigiert werden kann, ohne dass der Code jeweils anzupassen ist. [Eine Einführung zum hier angewandten "For"-Loop - einer VBA-Schleife - findest Du in diesem Beitrag.] Ziel ist es also, weitere Tabellenblätter einfügen zu können, ohne auf diese spezifisch im Code verweisen zu müssen.

Unser Beispielunternehmen weist Zahlen für die jeweiligen Regionen und Unternehmenseinheiten aus. Unten ist ein Beispiel dargestellt, bei dem unterschiedliche Kantone ("Basel", "Bern" und "Zürich") vorhanden sind. Zudem werden die Daten auf Konzernebene aggregiert (Tabellenblatt "Total"):

SheetIndexSheetsA

Wir gehen davon aus, dass jede einzelne Region die gleiche Struktur aufweist und wir demnach denselben Makro-Code auf alle Tabellenblätter anwenden können - ein perfekter Anwendungsfall also für einen Loop! In einem ersten Schritt sollten die notwendigen Befehle für ein einzelnes Tabellenblatt aufgezeichnet, geschrieben und getestet werden. Auf jedem Blatt sollen beispielsweise Spalten ausgeblendet sowie Formatierungen vorgenommen werden. Es bieten sich nun unterschiedliche Schleifen an, die sich über alle gewünschten Tabellenblätter erstrecken. In unserem Fall soll der Loop jedoch dynamisch sein, damit wir jederzeit neue Regionen einfügen können. Verweisen wir im Code demnach explizit auf die aktuell erste Region "Basel", hat dies später allenfalls keine Gültigkeit mehr (Beispiel: Wenn wir "Aargau" einfügen, rückt dieser Kanton an erste Stelle). Im anfangs verlinkten Beitrag zu dynamischen Formeln über mehrere Tabellenblätter haben wir Hilfstabellenblätter eingefügt ("Kanton_AA" und "Kanton_ZZ") und diese am Ende ausgeblendet:

SheetIndexSheetsZ

Durch diesen Mechanismus kann nun ein "For"-Loop angewandt werden. Unser Makro ermittelt den "Sheet.Index" dieser Hilfsblätter; das heisst, an welcher Stelle in der Datei diese Tabellenblätter stehen. Wir definieren hier einerseits die Variablen des Typs "Integer" (vereinfacht: Zahlen) im Makro:

Dim SheetIndexStart As Integer
Dim SheetIndexEnd As Integer

Danach kann der Indexwert dieser beiden Tabellenblätter ermittelt werden:

SheetIndexStart = Sheets("Kanton_AA").Index
SheetIndexEnd = Sheets("Kanton_ZZ").Index

In unserem Beispiel wird für "Kanton_AA" der Wert "2" als Variable abgespeichert, für "Kanton_ZZ" ist dies der Wert "6". Nun kann der "For"-Loop eingesetzt werden, der den Code mit den Befehlen für die Tabellenblätter umfasst:

For x = SheetIndexStart + 1 To SheetIndexEnd - 1
Sheets(x).Activate
'Befehle zur Bearbeitung der Tabellenblätter
Next

Da wir die Hilfsblätter nicht zwingend bearbeiten müssen, kannst Du entweder direkt bei der Definition der Variablen "+1" addieren respektive "-1" subtrahieren, oder wie im Code oben beim Beginn des "For"-Loop die Index-Zahl um eins erhöhen und reduzieren. Mit "Sheets(x).Activate" wird dann in jedem Durchlauf der Schleife jeweils das entsprechende Tabellenblatt aktiviert und bearbeitet. Beachte, dass Du die Hilfstabellenblätter "Kanton_AA" und "Kanton_ZZ" allenfalls zuerst durch das Makro einblenden musst. Füge hier zu Beginn Deines Makros einfach ein:

Sheets("Kanton_AA").Visible = True
Sheets("Kanton_ZZ").Visible = True

... und am Ende dasselbe, mit dem Boolean-Wert "False", damit die Blätter direkt wieder ausgeblendet sind.

Fügst Du nun eine neue Region (z.B. "Genf" oder "Aargau") ein, wird das Makro dank der Ermittlung des "Index-Wertes" auch diese Tabellenblätter in der Loop-Bearbeitung berücksichtigen können. Entsprechend reagiert die Selektion, falls Du weitere Tabellenblätter weiter vorne in der Datei einfügst (beispielsweise eine weitere Auswertung neben dem "Total") oder die Kantone mitsamt den beiden Hilfsblätter an eine andere Stelle innerhalb der Datei verschiebst.