Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Achtung: Dies ist nicht der vollständige Artikel, sondern nur ein paar Seiten davon. Wenn Sie hier nicht erfahren, was Sie wissen möchten, finden Sie am Ende Informationen darüber, wie Sie den ganzen Artikel lesen können.

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

Bitte teilen Sie uns Ihre Anrede, Ihren Namen und Ihre E-Mail-Adresse mit:

Anrede:
Vorname:
Nachname:
E-Mail:

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 3/2018.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

SVG als Grafikkomponente

In zwei Beiträgen rund um das Thema 'HTML5 als Grafikkomponente' erfuhren Sie, wie Sie mithilfe des Webbrowser-Steuerelements und HTML5 programmgesteuert Grafiken erzeugen. Über eine andere Schnittstelle, nämlich SVG, lässt sich dasselbe erreichen, wobei hier nicht Pixel-, sondern Vektorgrafiken erzeugt werden, die deutlich mehr Interaktivität zulassen und nachträglich bearbeitbar sind.

Referenz

Die Ausführungen dieses Beitrags setzen jene aus dem Artikel HTML5 als Grafikkomponente in der Ausgabe 01/2018 fort. Dort sind die Grundlagen zum Einsatz des Webbrowser-Steuerelements im Verein mit HTML5 beschrieben, auf die hier deshalb nicht noch einmal eingegangen wird.

SVG als Alternative zu HTML5

Über HTML5 können Sie unter Access im Webbrowser-Steuerelement Bilder anlegen, indem Sie dessen zugrundeliegendes HTML-Objektmodell steuern. Als Ergebnis erhalten Sie eine Pixelgrafik als Summe der Grafikoperationen, deren Schritte sich nicht mehr rückgängig machen oder bearbeiten lassen.

Lediglich das Abspeichern als Bilddatei oder im BLOB-Feld einer Tabelle steht Ihnen dann noch offen. Ganz anders bei SVG, wo die Grafik im Vektorformat entsteht, auf deren einzelne Elemente jederzeit zugegriffen werden kann. Solche Grafiken rendert der Browser dann zur Laufzeit.

Es verwundert eigentlich, dass diese flexible Lösung noch von niemand aufgegriffen und umgesetzt wurde – dachte ich! Tatsächlich findet, während ich dies zu Papier bringe, in Wien die zweite Access-DevCon statt, eine internationale Entwicklerkonferenz, welche unter anderem Vorträge von Experten zu verschiedenen Themenstellungen rund um Access anbietet. Und der litauische Entwickler Alexandru Tofan, ein bisher weitgehend unbeschriebenes Blatt, demonstriert dort ebenfalls seine Lösungen zum Einsatz von SVG als Grafik-Engine. Ich bin gespannt, welche Ähnlichkeit seine Ausführungen zu den hier ganz unabhängig vorgestellten haben werden, falls sie veröffentlicht werden...

Der Hauptgrund dafür, dass eine Implementierung von SVG im Webbrowser Control noch nicht stattfand, ist wohl darin zu suchen, dass Microsoft dem Internet Explorer erst spät den Umgang mit diesem Format beibrachte. Und da das Webbrowser-Steuerelement im Rohzustand nur die Version 7 des Browsers emuliert, welche noch kein SVG kannte, laufen die sehr wohl im HTML-Objektmodell enthaltenen zugehörigen Methodenaufrufe ins Leere. Erst die Modifikation des Webbrowsers über die VBA-Routine PrepareBrowser, die, wie im oben angeführtem Beitrag, schon mehrmals erläutert wurde, lässt ihn im Gewand des IE 11 erscheinen. Danach akzeptiert er anstandslos auch alle SVG-Methoden.

SVG als Format

SVG (Scalable Vector Graphics) ist an sich ein auf XML basierendes Dateiformat, welches seit dem Jahr 2001 existiert und kontinuierlich weiterentwickelt wurde. Dateien mit der Endung .svg können etwa mit dem Open Source-Programm Inkscape angezeigt oder erstellt werden, welches sich fast schon zum Standard gemausert hat. Aber auch andere Vektorzeichenprogramme beherrschen meist den Export in dieses Format.

Inzwischen hat es sich aber vor allem im Web als wichtigste Schnittstelle zur Anzeige von Vektorgrafiken etabliert. Der Vorteil von Vektorgrafiken gegenüber Pixelbildern ist ja die verlustfreie Skalierbarkeit, denn solche Grafiken werden grundsätzlich erst zur Laufzeit beim Rendern in Pixel übersetzt. Bei technischen Zeichnungen, Organigrammen, Charts oder Karten ist es deshalb das Format der Wahl.

Einst ging es in erster Linie um die Anzeige solcher SVG-Grafikdateien, für die bis dahin nur ein spezielles in die Website eingebettetes Adobe-ActiveX-Steuerelement infrage kam. Doch seit der Implementierung direkt im Browser kam auch die dynamische Steuerung der einzelnen Elemente der Grafik hinzu.

So lassen sich SVG-Grafiken nun auch ohne jeglichen Bezug zu einer Datei etwa über Javascript anlegen und beeinflussen. Und glücklicherweise hat Microsoft im HTML-Objektmodell des Internet Explorers alle Elemente von Javascript nach COM übersetzt, womit auch unter VBA Zugriff auf die entsprechenden Klassen und Methoden besteht, ohne dass Sie sich mit einer anderen Skriptsprache beschäftigen müssen.

Die SVG-Grafiken stellen nun einfach eine Folge von Grafikanweisungen dar, die im XML-Format abgelegt sind. Der Browser interpretiert diese und rendert sie anhand der übergebenen Parameter. Dafür gibt es das neue Tag svg, welches allerdings nur dann korrekt interpretiert wird, wenn ein bestimmtes Namespace-Attribut mit xmlns hinzugefügt wird:

<svg xmlns="http://www.w3.org/2000/svg"> (Inhalt) <svg>

Innerhalb dieses Tags befinden sich dann die Anweisungen. Das können Linien sein, Rechtecke, Kreise, Ellipsen, Polygone, Bezier-Kurven, Text, Füllungen, Pixeldaten oder Verweise auf Bilddateien. All diese Elemente können über Attribute mit diversen Parametern versehen werden, die deren Gestalt bestimmen. Der Clou aber sind mehrere Grafikfilter, die Sie auf einfache Weise anlegen und nach Belieben auf diese Elemente anwenden können. So kann etwa gefüllter Kreis mit einem Blur-Filter verwaschen werden, dessen Parameter Sie ebenfalls steuern können.

Eine einfache Line erzeugen Sie etwa über dieses Konstrukt:

<svg xmlns="http://www.w3.org/2000/svg"
     height="300" width="500">
<line x1="0" y1="0" x2="200" y2="200"
     style="stroke:black;stroke-width:2"/>
</svg>

Hier sind dem svg-Tag gleich die Attribute width und height zugeordnet, die die Abmessungen der Grafikfläche (500x300 Pixel) festlegen. Die Linie erzeugen Sie über das line-Tag. Die Koordinatenpunkte der Linie sind über die Werte der Attributparameter x1, y1, x2, y2 definiert. Das Aussehen der Linie bestimmt nun das style-Attribut, welches seinerseits eine Menge weiterer Definitionen aufnehmen kann, die sich aus dem Fundus der HTML-Styles ableiten, die Sie eventuell auch abseits von SVG kennen. So gibt stroke etwa an, welche Farbe die Line haben soll, was hier auf Schwarz (black) festgelegt ist.

Natürlich sind hier auch beliebige andere über Hexadezimalwerte definierte Farben möglich, wie #A0A0A0, oder über die rgb-Funktion ermittelte:

stroke:rgb(40,20,105)

Die Breite der Linie steht schließlich im Parameter stroke-width (2 Pixel).

Übrigens können Sie innerhalb des svg-Tags wiederum ein oder mehrere svg-Tags einbetten, was zu verschachtelten Zeichenflächen führt.

SVG dynamisch unter VBA erzeugen

Der Witz am HTML-Objektmodell ist aber ja, dass Sie den HTML-Text nicht unbedingt per String-Verkettung generieren müssen, sondern sich der passenden HTML-Klassen bedienen, deren Eigenschaften Sie dann einstellen. So gibt es zur Linie etwa das Element SVGLineElement, welches Sie so erzeugen:

Dim oDoc As HTMLDocument
Dim oSVGLine As SVGLineElement
Set oDoc = WebCtl.Object.Document 
Set oSVGLine = oDoc.createElementNS( _
                "http://www.w3.org/2000/svg", "line")

Das HTML-Dokument oDoc erhalten Sie hier über die Document-Eigenschaft des Webbrowser-Steuerelements WebCtl. Normalerweise reicht die Methode createElement aus, um auf der Website ein neues HTML-Element zu erzeugen. Hier allerdings wird die Alternative createElementNS benötigt, weil auf den SVG-Namespace Bezug genommen werden muss, damit der Webbrowser erkennt, um welches line-Element es sich genau handelt.

So erzeugt stellen Sie nun die Eigenschaften des SVGLineElements ein:

oSVGLine.x1 = 0: oSVGLine.y1 = 0
oSVGLine.x2 = 200: oSVGLine.y2 = 200

Leider sind das auch schon alle Eigenschaften, die diese Klasse bei Microsoft direkt anbietet. Alle anderen müssen Sie über die Methode setAttribute belegen:

oSVGLine.setAttribute "stroke", "black"
oSVGLine.setAttribute "stroke-width", "2"

Die Methode setAttribute finden Sie im Objektkatalog nicht unter der Klasse SVGLineElement, und trotzdem funktioniert sie. Das liegt daran, dass sich ein SVGLineElement versteckt vom allgemeineren IHTMLElement ableitet, welches diese Methode aufweist.

SVG-Grafik-Beispiel

Das Formular frmSVGTest der Demodatenbank vereint die wesentlichen Techniken, die für den Einsatz von SVG als Grafikgenerator zum Zuge kommen. Bild 1 zeigt es zur Laufzeit, nachdem auf die Schaltfläche SVG erzeugen geklickt wurde.

Eine im Webbrowser-Steuerelement per VBA generierte SVG-Grafik

Bild 1: Eine im Webbrowser-Steuerelement per VBA generierte SVG-Grafik

Das Formular enthält lediglich ein Webbrowser-Steuerelement mit dem Namen ctlIE, dessen Steuerelementinhalt im Entwurf auf "=about:blank" festgelegt ist und einen Button, der die Anlage der SVG-Grafik auslöst. Damit das Webbrowser-Control mit SVG umgehen kann, muss zuvor die Routine PrepareBrowser des Moduls mdlWebControl aufgerufen worden sein, welche Einstellungen der Registry modifiziert, wie dies bereits erschöpfend in den Beiträgen zu HTML5 erläutert wurde.

Der Klick auf den Button cmdCreate lässt die Ereignisprozedur in Listing 1 ablaufen. Hier kommt es zunächst zum Aufruf der Hilfsroutine NavigateBlank, die weiter unten abgebildet ist. Sie stellt per Navigate2-Methode sicher, dass im Webbrowser ctlIE ein leeres Dokument angelegt ist. Nachdem dieses erfolgreich fertiggestellt ist, was die Do-Loop-Schleife mit Abfrage der ReadyState-Eigenschaft kontrolliert, kann die modulweit deklarierte Objektvariable oDoc auf dieses Dokument gesetzt werden. Das WithEvents in der Deklaration ermöglicht, dass auf Ereignisse der gesamten Website, wie Mausklicks, reagiert werden kann.

Private WithEvents oDoc As HTMLDocument
Private WithEvents oSVG As SVGSVGElement
Private oEvent As IHTMLEventObj
Private Sub cmdCreate_Click()
     Dim oSVGElement As SVGCircleElement
     Dim oElement As IHTMLElement
     
     NavigateBlank
     oDoc.head.innerHTML = "<head><meta http-equiv=""X-UA-Compatible""/></head>"
     
     Set oSVG = oDoc.createElementNS("http://www.w3.org/2000/svg", "svg")
     With oSVG
         .Width.baseVal.Value = 300
         .Height.baseVal.Value = 250
         .Style.backgroundColor = "#e0e0e0"
     End With
     
     Set oSVGElement = oDoc.createElementNS("http://www.w3.org/2000/svg", "circle")
     With oSVGElement
         .setAttribute "id", "Kreis"
         .setAttribute "cx", "50"
         .setAttribute "cy", "50"
         .setAttribute "r", "40"
         .setAttribute "stroke", "darkblue"
         .setAttribute "stroke-width", "4"
         .setAttribute "fill", "red"
     End With
     oSVG.appendChild oSVGElement
     
     oDoc.body.appendChild oSVG
     Debug.Print oDoc.all(0).outerHTML
End Sub
Sub NavigateBlank()
     ctlIE.Object.Navigate2 "about:blank"
     Do
         DoEvents
     Loop Until ctlIE.Object.ReadyState = 4
    Set oDoc = ctlIE.Object.Document
End Sub

Listing 1: Der wesentliche Code-Teil des Formulars frmSVGTest erzeugt im Click-Ereignis die Grafik

Im Header des Dokuments muss anschließend eine meta-Eigenschaft hinterlegt werden, die X-UA-Compatible lautet, damit der Browser die SVG-Anweisungen auch umsetzt. Dies geschieht durch Beschreiben des Tags über die Methode innerHTML des head-Objekts.

Und nun kann bereits die SVG-Zeichenfläche im Dokument mit createElementNS angelegt werden, wobei hier das Element-Tag svg als String übergeben wird. Das Element landet in der Objektvariablen oSVG vom Typ SVGSVGElement, die ebenfalls im Kopf des Moduls mit WithEvents deklariert ist, damit auf Ereignisse speziell der Zeichenfläche reagiert werden kann.

Die Zeichenfläche ist damit zwar erstellt, hat bislang jedoch noch keine definierten Abmessungen. Dies holt der folgende With-Block auf die Objektvariable nach. Um die Breite des svg-Elements einzustellen, können Sie zwei Methoden einsetzen. Die eine ist das Setzen des width-Attributs über die Methode setAttribute, die andere die Nutzung der eingebauten Eigenschaft Width der Objektklasse. Letztes geschieht hier. Allerdings handelt es sich bei Width nicht etwa um einen Integer-Wert, sondern um einen speziellen zusammengesetzten SVG-Datentyp, dessen Eigenschaft baseVal.Value verwendet werden muss. Sie bekommt den Wert 300 Pixel zugewiesen. Ähnliches erfolgt für die Höhe der Fläche und Height. Und dann erhält die Zeichenfläche noch eine Hintergrundfarbe, die über das Style-Attribut backgroundColor mit einem hexadezimalen Grau-Wert versehen wird. Das SVG-Objekt wird erst in das Dokument geschrieben und damit sichtbar, wenn es am Ende der Routine über appendChild an den Body oDoc.body angehängt wird. Zuvor muss jedoch noch der SVG-Kreis erzeugt und an das SVG-Objekt selbst angehängt sein.

Deshalb generiert createElementNS nun ein Element circle und weist es als Objekt der Variablen oSVGElement vom MSHTML-Typ SVGCircleElement zu. Sie verweist nun auf ein abstraktes Kreis-Objekt, dessen Eigenschaften erst noch eingestellt werden müssen. Der folgende With-Block mit den setAttribute-Anweisungen übernimmt dies. Die Mittelpunktkoordinate wird mit cx und cy festgelegt, der Radius in r – ohne dezidierte Angabe von Einheiten geht der Browser dabei von Pixeln aus. Dem Element wird ein eindeutiger Bezeichner Kreis über die id spendiert, damit es später identifizierbar und damit sogar auch dynamisch bearbeitbar ist. Die Farbe des Kreises steht in stroke, die Linienbreite in stroke-width und die Füllfarbe im Attribut fill. Das Kreiselement wird schließlich mit appendChild an das SVG-Flächenelement oSVG angehängt, welches selbst dann in den Body geschrieben wird. Ab nun ist die Grafik tatsächlich sichtbar.

Obwohl wir nur mit MSHTML-Objekten hantieren und keinerlei String-Bearbeitung einsetzen, übersetzt sich das Ganze automatisch in gültigen HTML-Text. Die Debug.Print-Anweisung verdeutlicht, was dabei herauskommt und gibt im VBA-Direktfenster diesen String aus, der hier der Übersicht halber mit Einrückungen formatiert wurde:

<html>
   <head><meta http-equiv="X-UA-Compatible""/></head>
     <body>
       <svg xmlns="http://www.w3.org/2000/svg"
         style="background-color: rgb(224, 224, 224);"
         width="300" height="250">
           <circle id="Kreis" 
             fill="red" stroke="darkblue" stroke-width="4"
             cx="50" cy="50" r="40" />
       </svg>
     </body>
</html>

SVG Knowledgebase

Es liegt weit außerhalb des Radius dieses Beitrags, alle SVG-Elemente mit ihren Parametern darzustellen. Empfehlung: Schauen Sie sich etwa auf der deutschen Seite SELFHTML um, die unter der Rubrik SVG mit vielen Beispielen erschöpfend Auskunft gibt. Dort sind die möglichen Elemente und ihre Attribute gut erläutert. Das Vorgehen zur Übersetzung der HTML-Tags nach VBA ist dann immer dasselbe. Sie erzeugen ein Element über die Funktion createElementNS unter Angabe des Element-Tags, weisen es einer Objektvariablen zu, die den generellen Typ SVGElement haben kann – oder auch schlicht Object –, und setzen dessen Eigenschaften am besten über setAttribute-Anweisungen innerhalb eines With-Blocks.

SVG-Filter

Das Formular frmSVGTest enthält noch eine weitere Schaltfläche Komplexes SVG, deren Betätigung zur Grafik in Bild 2 führt. Hier sind genau zwei SVG-Elemente angelegt, nämlich ein gelber Kreis mit grüner Umrandung und das Bild einer Tulpe aus einer JPG-Datei. Auf das Bild wird aber ein Weichzeichnenfilter angewandt, auf den Kreis ein Turbulenzfilter. Hier kommen neue Techniken ins Spiel.

Einsatz von Filtern für die komplexere SVG-Grafik per VBA

Bild 2: Einsatz von Filtern für die komplexere SVG-Grafik per VBA

Das Prinzip ist allerdings das gleiche, wie im vorigen Beispiel. Ein SVG-Element wird angelegt und an den Body des über about:blank erzeugten Dokuments gehängt. Das Vorgehen, um die Bilddatei in die Grafik zu bekommen, ist hier nicht trivial. Zwar könnte man das Attribut href des image-Elements mit dem absoluten Pfad zur Datei belegen, doch beim Verschieben der Datenbank und der Bilddatei tulpe.jpg in ein anderes Verzeichnis wäre der Bezug verloren. Deshalb wird aus der Bilddatei ein sogenanntes binäres data-URI erzeugt und dessen Inhalt dem Bildelement unmittelbar übergeben. Hintergrund dafür ist zusätzlich, dass sich so auch Dateien, die etwa in OLE-Feldern von in Tabellen abgespeichert sind, ebenfalls zur Ansicht bringen lassen. Das data-URI kommt dabei als base64-kodierter String in das Dokument. Diese Funktionalität kam bereits im früheren Beitrag zum Zeichnen und Malen mit HTML5 zum Einsatz.

Einen Teil der Ereignisprozedur cmdCreateComplex_Click zeigt Listing 2. Die Bilddatei wird zuerst mit der Open-Anweisung in das Byte-Array bin eingelesen. Dann wird das leere SVG-Bildelement über das Tag image erzeugt.

...
     Open CurrentProject.Path & "\tulpe.jpg" For Binary Access Read As #1
     ReDim bin(LOF(1) - 1)
     Get #1, , bin
     Close #1
     
     Set oSVGElement = oDoc.createElementNS("http://www.w3.org/2000/svg", "image")
     With oSVGElement
         .setAttribute "id", "dataimage"
         .setAttribute "width", "200"
         .setAttribute "height", "200"
         .setAttribute "href", "data:image/jpeg;base64," & EncodeBase64(bin)
         .setAttribute "crossOrigin", "anonymous"
         .setAttribute "filter", "url(#blur)"
     End With
     oSVG.appendChild oSVGElement
...

Listing 2: Einlesen der Bilddatei in ein Byte-Array und Übergeben desselben an das SVG-image-Element

Es bekommt die id dataimage, die Breite und Höhe 200px (width, height), und die Bilddaten über href aus einem Hexadezimal-String, der mittels der Hilfsfunktion EncodeBase64 im Modul mdlHelper aus dem Array erzeugt wird. Der Internet Explorer zeigt das Bild dann allerdings aus Sicherheitsgründen erst an, wenn zusätzlich die Eigenschaft crossOrigin auf anonymous gesetzt wird, weil sonst die Herkunft der Binärdaten für ihn ungeklärt ist.

Das Weichzeichnen kommt schließlich zustande, indem Sie der filter-Eigenschaft den Ausdruck url(#blur) übergeben. Darin verweist der Bezeichner blur auf einen SVG-Filter, der allerdings schon eigenständig angelegt sein muss. Auch dies lässt sich über SVG-Objekte bewerkstelligen. Im ersten Schritt wird das Filter-Objekt erzeugt:

Set oSVGFilter = oDoc.createElementNS( _
     "http://www.w3.org/2000/svg", "filter")
oSVGFilter.setAttribute "id", "blur"

Er bekommt als Eigenschaft lediglich die id blur. Denn das Filter-Objekt bewirkt selbst noch keinen Filtereffekt und stellt nur einen Container für einen oder mehrere Effekte dar. Ein SVG-Element kann nur über diesen etwas umständlichen Weg mit einem Bildeffekt versehen werden. Dem Element muss im Attribut filter der Name des Filters übergeben werden, wobei die Syntax url(#) verwendet wird. Das Filter-Element wiederum benötigt als Kindelement ein Filtereffekt-Element.

Das geschieht in der Prozedur so:

Set oSVGEffect = oDoc.createElementNS( _
     "http://www.w3.org/2000/svg", "feGaussianBlur")
oSVGEffect.setAttribute "in", "SourceGraphic"
oSVGEffect.setAttribute "stdDeviation", "10"
oSVGFilter.appendChild oSVGEffect
oSVG.appendChild oSVGFilter

Das SVG-Element ist hier vom Typ feGaussianBlur und erzeugt einen Gaussschen Weichzeichner. Seine Eigenschaft stdDeviation bestimmt den Radius des Weichzeichnens – je höher, desto verwischter. Das Attribut in gibt an, woher die Ausgangsgrafik kommt. Mit dem Wert sourceGraphic bestimmen Sie, dass das SVG-Element selbst dafür herangezogen wird. Das Effektobjekt hängen Sie schließlich an das Filterobjekt an und dieses selbst an das SVG-Objekt, also die generelle SVG-Fläche.

Dabei spielt es keine Rolle, in welcher Reihenfolge Sie vorgehen. Sie können erst das Filterobjekt erzeugen und dann das SVG-Zeichenelement, oder umgekehrt. MSHTML analysiert die Sache selbst und generiert aus den Objekten die funktionierenden HTML-Anweisungen.

Sie haben das Ende des frei verfügbaren Teils des Artikels erreicht. Lesen Sie weiter, um zu erfahren, wie Sie den vollständigen Artikel lesen und auf viele hundert weitere Artikel zugreifen können.

Sind Sie Abonnent?Jetzt einloggen ...
 

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

Bitte teilen Sie uns Ihre Anrede, Ihren Namen und Ihre E-Mail-Adresse mit:

Anrede:
Vorname:
Nachname:
E-Mail:

© 2003-2018 André Minhorst Alle Rechte vorbehalten.