In diesem Artikel möchte ich aufzeigen, wie man VBA Programme schreibt die auf unterschiedlichen System, bzw. mit unterschiedlichen Versionen von Excel laufen. Dies trifft in gleichem Maße auch auf die anderen Office Anwendungen zu.
Was ist Portabilität?
Portabilität, oder auch Plattformunabhängigkeit, beschreibt die Eigenschaft eines Programm auf unterschiedlichen Systemen (Hardware, Software) zu laufen. VBA Programme brauchen zur Ausführung zwingend eine Office Anwendung – im Allgemeinen genau die Office Anwendung für das das Programm geschrieben wurde – in unserem Fall also Excel. Auf welchem System Excel wiederum läuft ist aber irrelevant.
Was muss man beachten?
Portabilität kommt nicht automatisch, man muss auch einige Dinge beachten. Hauptsächlich sind das die Unterschiede zwischen den verschiedenen Versionen von Excel. Man muss darauf achten nur solche Funktionen und Eigenschaften zu verwenden, die in allen Versionen verfügbar sind mit denen das eigene Programm später laufen soll.
Ein prominentes Beispiel ist hier das Ribbon. Soll das eigene Programm auch mit Versionen von Excel <= 2003 laufen, müssen alternativ zum Ribbon auch CommandBars verwendet werden.
Weniger offensichtlich ist die Beachtung von Late Binding vs Early Binding. Bei Early Binding werden die Verweise zu andere Bibliotheken zur Entwicklungszeit gesetzt. Dies hat den Vorteil, dass es
- Schneller ist als Late Binding
- Intellisense (VBE) verwendet werden kann
Nachteil ist, dass dieser Verweis auf anderen Systemen (insbesondere bei anderen Excel-Versionen) so nicht mehr gültig sein muss. Das äußert sich darin, dass Objekte und Eigenschaften auf dem anderen System bei Ausführung des Programms nicht gefunden werden.
Late Binding ist zwar in der Umsetzung aufwändiger und in der Ausführung langsamer, dafür funktionieren die Verweise, da sie erst zur Laufzeit auf dem Zielsystem erstellt werden. Statt Variablen mit einem speziellen Typ zu deklarieren, werden sie allgemein als Objekt deklariert.
Dim VariablenName as Object
Set VariablenName = CreateObject("Excel.Application")
Beispiel
Im Folgenden möchte ich Early- und Late-Binding an einem kurzem Beispiel zeigen. Es soll in einer UserForm ein TreeView-Element dargestellt werden.
Der Code der UserForm für Early-Binding sieht so aus:
Option Explicit
Private Sub UserForm_Activate()
Dim i As Long
Dim aWorkbook As Workbook
Dim aSheet As Worksheet
Dim aNode As Node
With TreeView1
For Each aWorkbook In Workbooks
i = i + 1
Set aNode = .Nodes.Add(, , "W" & i, aWorkbook.Name)
aNode.Expanded = True
For Each aSheet In aWorkbook.Sheets
Set aNode = .Nodes.Add("W" & i, tvwChild, , aSheet.Name)
Next aSheet
Next aWorkbook
End With
End Sub
Er sorgt dafür, dass das TreeView-Elememt mit Inhalt gefüllt wird. Das TreeView-Element wird, wie man es gewohnt ist, zur Entwicklungszeit in der UserForm platziert.
Der große Unterschied bei Late-Binding ist, dass das TreeView-Element nicht zur Laufzeit in der UserForm platziert werden kann, da es zur Entwicklungszeit nicht bekannt ist. Der Code ist auch geringfügig aufwändiger:
Option Explicit
Const tvwFirst = 0
Const tvwLast = 1
Const tvwNext = 2
Const tvwPrevious = 3
Const tvwChild = 4
Dim aTreeView As Object
Dim aNode As Object
Private Sub UserForm_Initialize()
Set aTreeView = UserForm1.Controls.Add("MSComctlLib.TreeCtrl")
With aTreeView
.Top = 18
.Left = 12
.Width = 198
.Height = 114
.Style = 5
End With
End Sub
Private Sub UserForm_Activate()
Dim i As Long
Dim aWorkbook As Workbook
Dim aSheet As Worksheet
On Error Resume Next
With aTreeView
For Each aWorkbook In Workbooks
i = i + 1
Set aNode = .Nodes.Add(, , "W" & i, aWorkbook.Name)
aNode.expanded = True
For Each aSheet In aWorkbook.Sheets
Set aNode = .Nodes.Add("W" & i, tvwChild, , aSheet.Name)
Next aSheet
Next aWorkbook
End With
End Sub
Zuerst definieren wir ein paar Konstanten. Dies ist optional, man kann auch die Werte direkt verwenden. Als nächstes deklarieren wir zwei Variablen als Objekte, die später das TreeView-Element und die einzelnen Knoten innerhalb des TreeView-Elements aufnehmen sollen. Während der (hier ebenfalls neuen) Initialisierung der UserForm holen wir uns zur Laufzeit den Verweis auf das TreeView-Element und bestimmen auch gleich Größe und Position. Der Rest des Codes ist nun fast identisch zum Early-Binding Beispiel.
Daran kann man auch erkennen, dass es zunächst einfacher ist nach Early-Binding (also ganz normal) zu entwickeln, und erst später alle Stellen an denen Elemente aus zusätzlich eingebundenen Bibliotheken verwendet werden nach Late-Binding umzuwandeln.
Ich hoffe dieser Artikel und die Beispiele konnten helfen.