20 | 09 | 2017
Hauptmenü
www.checkdive.eu
auf

ExcelImplementierung.zip

Dateiname:
ExcelImplementierung.zip
Dateigröße:31.38 kB
Datum:21. November 2010

CheckDive selber ist mittlerweile vollständig in Microsoft® Visual Basic geschrieben.

In einer früheren Version von CheckDive waren nur die Masken und Programmlogik in Visual Basic geschrieben, die Ein- und Ausgabe von Daten hingegen wurde über Excel gesteuert, das über die COM Schnittstelle von CheckDive angesteuert wurde.

Excel lässt sich von außen über die COM Schnittstelle umfassend steuern. In der ersten Version von CheckDive wurde diese COM Schnittstelle exzessiv genutzt, um Daten in Excel zu schreiben, wieder zu lesen und auch die gesamte Formatierung über die Schnittstelle durchzuführen. Diese Schnittstelle ist nicht sonderlich performant und für die Darstellung von durchschnittlich 4.000 - 6.000 Floatwerten völlig ungeeignet - noch dazu, wenn Werte nicht nur geschrieben, sonder zu einem späteren Zeitpunkt auch gelesen werden müssen.

Die Art der "Datenverwaltung" musste also umgeschrieben werden.

Die Anforderungen dafür waren:

  • Beibehalten der Schnittstelle, d. h.
  • Zellen organisiert in einer Matrix
  • Zellen mit Werten belegen
  • Werte aus Zellen auslesen
  • Zelleninhalte selektiv formatieren (hier Fettdruck)
  • Zellen selektiv einfärben
  • Keine Seiteneffekte in der Umsetzung

Das Beibehalten der Schnittstelle war von besonderer Bedeutung. In der ursprünglichen Umsetzung wurden Zellen gezielt durch die Angabe von Zeile und Spalte angesprochen. Diese Form der Ansprache einzelner Zellen sollte beibehalten werden, da nur so zu vermeiden war, das Programm in tragenden Teilen neu zu schreiben.

Die hier genutzte Excelleistung besteht im Wesentlichen in der Nutzung einer Matrix, bestehend aus Zellen.

Das lässt sich in VB objektorientiert sehr ähnlich umsetzen. Dazu wird eine Klasse Matrix eingeführt, deren Aufgabe darin besteht, einzelne Zellen anzulegen, zu verwalten (s. oben - Wert, Font, Farbe) und anschließend die Zellen wieder freizugeben.

Die Zellen werden über eine eigene Klasse Zelle realisiert, die im Wesentlichen die Eigenschaften trägt:

Private myValue As Object
Private myColorIndex As Integer
Private myBoldFont As Boolean

Schreiben und Lesen der Eigenschaften geschieht über Properties, also z.B.

zell(s, z).Value = val
getValue = zell(s, z).Value

zell” im Beispiel oben ist eine Instanz der Klasse Zelle. Die Instanzen werden selbstverständlich nicht direkt angesprochen. Dafür ist die Instanz der Klasse Matrix zuständig. Dazu stellt Matrix öffentliche Zugriffsmethoden zur Verfügung, über die z. B. das Setzen und Lesen von Zell-Eigenschaften geschieht.

Das hat verschiedene Vorteile.
So können sämtliche Interna, wie z.B. Speicherallokierung gekapselt werden. CheckDive benötigt eine fixe Anzahl an Spalten. Die Anzahl der benötigten Zeilen ist jedoch unbekannt und variiert mit der Art des Tauchgangprofils. Daher wird in Matrix ein 2-dimensionales Array von Zellen angelegt (nomen est omen).

Private zell(MAXSPALTEN, STARTROW) As Zelle

MAXSPALTEN ist vorbelegt mit 99, STARTROW mit 1. Da ich eingangs die Anzahl der Zeilen also nicht kenne, wird das Array bei Bedarf dynamisch erweitert

ReDim Preserve zell(MAXSPALTEN, z)

Da bei einem mehrdimensionalen Array immer nur die letzte Dimension erweitert werden kann, müssen im Array Zeilen und Spalten vertauscht werden. Während Excel nach unten wächst (zeilenweise), wächst das Array nach rechts, also spaltenweise (transponieren).

An dieser Stelle finden wir einen weiteren Vorteil der Kapselung der Zellen. Über die Schnittstelle, die Matrix zur Verfügung stellt, werden Zeilen und Spalten wieder vertauscht, sodass die einzelne Zelle wie in Excel angesprochen werden kann.

xlBlatt.Cells(z, s).value = wort(i)

xlBlatt ist die Referenz auf das geöffnete Excel Worksheet. Über den Ausdruck oben wird also ein Wert direkt in die Zelle mit Zeile z und Spalte s geschrieben.

Das Pendant dazu:

mat.addValue(z, s, wort(i))

Hier wird die Methode addValue der Matrixinstanz mat aufgerufen und drei Parameter übergeben, nämlich Zeile z, Spalte s und der Wert.
Da der Speicher dynamisch nur dann vergeben wird, wenn er auch benötigt wird, prüft die Mehtode addValue zunächst, ob die benötigte Zeile (eigentlich Spalte in der Matrix) bereits allokiert ist, andernfalls wird der Speicher für die Zeile zuerst angelegt.

Der Unterschied zwischen beiden Ausdrücken oben liegt letztlich darin, das einmal über die COM Schnittstelle auf eine Excelzelle zugegriffen wird (xlBlatt), im anderen Fall wird über mat auf eine „lokale Zelle“ zugegriffen.

Ähnlich verhält es sich mit dem Lesen der Werte aus den Zellen heraus.
Im hier beschriebenen Beispielprogramm wird ein Beispieltext in eine vom User festzulegende Anzahl von Zeilen / Spalten geschrieben. Wörter mit einem Punkt am Ende (Satzende) sollen fettgedruckt werden, Wörter mit einem Komma am Ende werden in Zellen geschrieben, die grün gefärbt werden.

If Punkt = Strings.Right(mat.getValue(z, s), 1) Then
      mat.addBoldFont(z, s, True)
ElseIf Komma = Strings.Right(mat.getValue(z, s), 1) Then
      mat.addColorIndex(z, s, 4)

If Punkt = Strings.Right(xlBlatt.Cells(z, s).value, 1) Then
       xlBlatt.Cells(z, s).font.bold = True
ElseIf Komma = Strings.Right(xlBlatt.Cells(z, s).value, 1) Then
       xlBlatt.Cells(z, s).interior.colorindex = 4

Sicherlich würde in einer ernsthaften Anwendung ein Wert nicht aus einer Zelle gelesen (besonders nicht über die COM Schnittstelle), der dieser Zelle gerade erst zugewiesen wurde ...

Nachdem nun alle Werte korrekt in Zellen geschrieben sind, bleibt nur noch die Frage, wie die Daten in Excel übertragen werden.

Hier muss nun doch noch mal die COM Schnittstelle bemüht werden. Über diese können Datenarrays übergeben werden.
Dazu wird die Instanz der Klasse Matrix zunächst aufgefordert (sehr förmlich …), das Zellarray in drei Wertearrays umzuwandeln. So entsteht also je ein Array für Werte, Farben und Fonts.
Diese drei Arrays werden durch folgenden Aufruf an eine öffentliche Prozedur in Excel übergeben

xlApp.Run("ausgabeMatrix", mat.werteArray, mat.farbenArray, mat.boldFontArray, 1, mat.getAnzZeilen, spalten)

Hier der Empfänger in Excel:

Public Sub ausgabeMatrix(ByVal wAr As Variant, ByVal fAr As Variant, ByVal bfAr As Variant, ByVal srow%, ByVal maxZeile%, ByVal maxspalten%)

Wichtig ist, dass die Arrays an den Datentyp Variant übergeben werden.
Der Excelprozedur „ausgabeMatrix“ kommt nun die Aufgabe zu, die Daten darzustellen und in diesem Fall auch zu formatieren.

 Die Klassen Matrix und Zelle stehen im Download im Sourcecode zur Verfügung, eingebunden in eine einfache Konsolenapplikation (ebenfalls im Sourcecode).

Eingebunden in ein eigenes VB-Projekt lassen sich diese kompilieren .

Damit das .exe-File funktioniert, muss das mitgelieferte Excelfile im Binary-Verzeichnis des Projektes liegen, in dem auch die fertige Konsolenapplikation abgelegt wird (Debug / Release), da das Beispielprogramm im gleichen Verzeichnis nach dem Excelfile sucht.
Kurze Erläuterung zum Handling des Programmes (das lauffähige exe-Programm befindet sich ebenfalls im Download).

Eingegeben werden müssen die Anzahl Zeilen und Spalten, in denen die Ausgabe erfolgen soll, gefolgt von der Entscheidung, ob die Ausgabe in die Matrix geschrieben werden soll, (Eingabe 0) oder direkt in Excel (Eingabe 1).

Jede Eingabe wird durch ENTER abgeschlossen. ENTER ohne Eingabe beendet das Programm. Nach Programmlauf wird die benötigte Zeit angezeigt (sehr interessant).

Downloads:62 x

 

Powered by Phoca Download