Frontend-Alternativen für Datenbanklösung 2 - HTA-Dateien als Benutzeroberfläche

15.10.2006 von Helma  Spona
Seit dem Internet Explorer 5 gibt es eine spezielle Form von Anwendungen, die innerhalb des Browsers laufen. Sie besteht aus HTML- und Skriptcode, wobei zwischen JScript und VBScript gewählt werden kann. Diese Anwendungen, HTA-Dateien genannt, können Sie sehr gut auch als Benutzeroberfläche für Datenbankanwendungen einsetzen. Der Aufwand hält sich in Grenzen, und die Lösung ist äußerst preiswert.

HTA ist die Abkürzung für Hypertext-Application. Dabei handelt es sich um Dateien, die im Aufbau einer HTML-Datei sehr ähnlich sind.

Diese Dateien werden mit einem normalen HTML- oder Texteditor erstellt und unterscheiden sich von reinen HTML-Dateien dadurch, dass einige, aber nicht alle Sicherheitseinstellungen des Internet Explorer außer Kraft gesetzt werden, die für HTML-Seiten gelten. Dadurch wird es möglich, HTML-Seiten mit Hilfe von VBScript-Code zu erstellen, der auch Datenbankabfragen und Datenbankzugriffe ermöglicht. Gleichzeitig können aber die Elemente von HTML genutzt werden, um Formulare für die Dateneingabe oder Tabellen und Listen für die Ausgabe zu erzeugen.

Voraussetzungen

Voraussetzung für die Nutzung von HTA-Dateien ist in jedem Fall der Internet Explorer 5 oder höher unter Windows. Die Mac-Version sowie frühere Versionen des Internet Explorer können mit HTA-Dateien wenig anfangen.

Für den Datenbankzugriff benötigen Sie, genauwie zum Zugriff aus Excel oder Word heraus, die MDAC-Bibliotheken. Sie sind notwendig, wenn Sie nicht per ODBC-Datenquelle, sondern direkt mit ADO auf die Datenbank zugreifen möchten. Bei älteren Windows-Versionen ist das jedoch auch kein Problem, da die aktuelle MDAC-Bibliothek auf der Webseite von Microsoft heruntergeladen werden kann. Suchen Sie dazu auf der Download-Seite von Microsoft nach „MDAC“.

Außerdem sollten Sie Ihren Virenscanner so eingestellt haben, dass er die Ausführung von VBScript im Browser und in HTA-Dateien nicht unterbindet. Dann steht einer Nutzung von HTADateien als Frontend für Ihre Datenbankanwendung nichts mehr im Wege.

Aufbau einer HTA-Datei

Eine HTA-Datei ist zunächst eine HTML-Datei, die mit der Dateinamenserweiterung .HTA erstellt wurde. Im <head>-Element der Datei muss außerdem ein <hta:application>-Tag eingefügt werden. Es beschreibt die Anwendung, die über bestimmte Attribute, Eigenschaften der Anwendung definiert wird. Neben den in Listing 1 genannten Attributen gibt es noch eine ganze Reihe anderer. Eine vollständige Liste enthält Tabelle 1.

Tabelle 1: Verfügbare Attribute für das <hta>-Element.

Attribut

Beschreibung

ApplicationName

Legt den Namen der Anwendung fest. Er wird benötigt, wenn gleichzeitig das Attribut singleInstance auf true gesetzt wird. Dann prüft der Browser nämlich vor dem Starten, ob es eine laufende Anwendung dieses Namens schon gibt. Wenn Sie also zwei HTA-Dateien erstellen, die den gleichen Wert für applicationName haben und deren singleInstance- Attribut den Wert true hat, kann immer nur eine ausgeführt werden.

Border

Legt den Rahmentyp des Fensters fest. Dazu stehen die Werte thick (normaler Rahmen), dialog (Dialog), none (kein Rahmen) und thin (dünner Rahmen) zur Verfügung. Allerdings scheinen die Werte nicht korrekt angewendet zu werden. Entweder ist dies ein Bug des IE oder eine Einstellung, die vom IE 5 und 6 noch nicht unterstützt wird.

BorderStyle

Legt die Darstellung des Fensterrandes fest. Dazu stehen die Werte normal, complex, raised, static und sunken zur Verfügung.

caption

Legt über die Werte yes und no fest, ob der Fenstertitel für die Anwendung angezeigt werden soll. Ohne Fenstertitel hat der Anwender keine Möglichkeit, das Fenster zu verschieben oder mit der Maus zu schließen.

contextMenu

Gibt an, ob das Kontextmenü verfügbar sein soll (yes) oder nicht (no ).

icon

Legt eine ICO-Datei als Icon für die Anwendung fest. Als Wert ist ein relativer oder absoluter Pfad zur ICO-Datei zulässig.

innerBorder

Gibt an, ob der innere 3-D-Rahmen angezeigt werden soll.

maximizeButton

Bestimmt, ob der Maximieren-Button des Fensters angezeigt werden soll (yes) oder nicht (no).

minimizeButton

Bestimmt, ob der Minimieren-Button des Fensters angezeigt werden soll (yes) oder nicht (no).

navigable

Bestimmt, ob Zielseiten von Links im gleichen (yes) oder einem neuen (no) Fenster geöffnet werden. Bei Angabe von no wird jedoch beim Link auf eine HTA-Datei nachgefragt, ob die Datei ausgeführt oder heruntergeladen werden soll.

scroll

Gibt an, ob die Scrollleisten angezeigt werden sollen oder nicht. Dazu stehen die Werte yes (Scrollleisten werden immer angezeigt), no (Bildlaufleisten werden nie angezeigt) und auto (Bildlaufleisten werden angezeigt wenn notwendig) zur Verfügung.

scrollFlat

Gibt an, ob die Bildlaufleisten flach (yes) oder im 3-D-Stil (no) angezeigt werden sollen.

selection

Gibt an, ob der Inhalt markiert (yes) oder nicht markiert (no) werden kann.

showInTaskBar

Bestimmt, ob die Anwendung in der Taskleiste von Windows aufgeführt wird (yes)oder nicht (no).

singleInstance

Beim Wert yes kann maximal eine Anwendung dieses Namens ausgeführt werden, beim Wert no beliebig viele.

sysMenu

Gibt an, ob das Systemmenü des Fensters angezeigt werden soll (yes) oder nicht (no).

version

Bestimmt die Versionsnummer der Anwendung.

windowState

Bestimmt, ob das Fenster minimiert (minimize), maximiert (maximize) oder normal (normal) geöffnet werden soll.

Kopf der HTA-Datei

<html>
<head>
<hta:application
id="oHTA"
applicationname="leereAnwendung"
singleinstance="Yes"
windowstate="maximize"
border="yes"
maximize="no"
caption="Titel"
showintaskbar="yes"
sysmenu="yes">
<title>Leere HTA-Datei</title>
</head>
<body>
...
</body>
</html>

Skripts können Sie wahlweise im <head>-Element oder im <body>-Element definieren. Das hängt davon ab, was Sie erreichen möchten und wie Sie die Skripts aufrufen.

Um Zugriff auf die Attribute des <hta>-Elements und sonstige Eigenschaften der Anwendungzu haben, sollten Sie außerdem ein id- Attribut definieren. Als Wert muss eine Zeichenkette angegeben werden, die später auch für den Zugriff auf die Attribute genutzt wird. Wenn Sie beispielsweise id="oHTA" angeben, können Sie mit oHTA.version auf den Wert des Attributs version zugreifen. Dies setzt aber voraus, dass das Skript nach dem <hta>-Element definiert wird.

Sinn macht eine HTA-Datei als Benutzeroberfläche natürlich nur, wenn Sie damit auch Skripts ausführen oder Skriptdateien aufrufen können. Dazu gibt es prinzipiell mehrere Möglichkeiten.

Gerade bei komplexeren HTA-Anwendungen sollten Sie die Anwendung ebenso wie in Access modular aufbauen. Allerdings ist das nicht so ganz einfach. Der Internet Explorer bindet zwar den Code einer externen Datei ein, führt ihn dann aber nur teilweise aus. Dies ist allerdings auch von der Version des Internet Explorer und dem Service-Pack von Windows abhängig. In manchen Installationen funktioniert die Referenzierung externer Dateien problemlos, in anderen nicht. Daher sollten Sie den Code direkt in der HTA-Datei definieren, indem Sie ihn in <script> und </script> einfassen. Dazwischen steht dann der Code der aus Funktionen, Prozeduren und Deklarationen bestehen kann.

Der Datenbankaufbau

Damit das Beispiel funktioniert, benötigen Sie eine Access-Datenbank mit dem Namen Telefonliste00. mdb, die eine Tabelle TelMitarbeiter enthält. Diese Tabelle muss vier Textfelder haben mit den Namen

und sollte für Testläufe ein paar Datensätze enthalten.

Verbindung zur Datenbank herstellen

Die Beispielanwendung soll zunächst einmal nichts weiter tun, als einen Suchbegriff über ein Formular entgegenzunehmen und beim Klicken auf den Suchen-Button im Feld Nachname der Datenbanktabelle nach dem Suchbegriff zu suchen. Alle gefundenen Datensätze sollen dann als Liste ausgegeben werden (Bild 1).

Bild 1: Suchanfrage und Ergebnis.

<script type="text/vbscript">
'Enthält benötigte Funktionen und Prozeduren

</script>

Für diese Aufgabe benötigen Sie also eine Funktion, die die Datenbankverbindung aufbaut und zurückgibt. Sie brauchen eine weitere Prozedur oder Funktion, die die Daten abruft, und eine, die das Ergebnis der SQL-Abfrage ausgibt. Alle diese Funktionen zeigt Listing 3 zusammen mit den dazu notwendigen Deklarationen.

Dim strSuchbegriff
Dim arrDaten
Dim objFSO
Const DBName="Telefonliste00.mdb"
Const TbName="TelMitarbeiter"
Dim objCon 'connection-Objekt
Sub verbinden()
Dim objFSO
Dim strPfad
Dim strCon
Err.Clear
set objFSO=CreateObject("Scripting.FileSystemObject")
'Pfad ermitteln
strPfad=objFSO.GetParentFolderName(oHTA.CommandLine)
If mid(strPfad,1,1)="""" Then
strPfad=mid(strPfad,2)
End If
strPfad=objFSO.BuildPath(strPfad,dbName)
'Verbindung aufbauen
On Error Resume Next
strCon="Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=" & strPfad
set objCon=CreateObject("ADODB.Connection")
objCon.ConnectionString=strCon
objCon.CursorLocation=3
objCon.Open
If Err.Number <>0 Then
MsgBox "Datenbankverbindung nicht möglich!",vbInformation
Err.Clear
End If
set objFSO=nothing
End Sub
Sub trennen()
On Error Resume Next
objCon.Close
set objCon=nothing
End Sub
Function Suchen(strSB)
Dim arrD()
Dim rsDaten 'Recordset mit den Daten
Dim strSQL
Dim strTemp
Dim objFeld
Dim lngI
Dim lngZ
strSQL="SELECT * FROM " & TbName & "WHERE Nachname = """ & _
strSB & """;"
set rsDaten=CreateObject("ADODB.Recordset")
rsDaten.Open strSQL, objCon
Redim arrD (rsDaten.RecordCount, _
rsDaten.Fields.Count-1)
'Spaltennamen auslesen
If rsDaten.recordcount>0 Then
rsDaten.MoveFirst
for lngI=0 to rsDaten.fields.count-1
arrD(0,lngI)= _
rsDaten.fields(lngI).name
next
End If
'Werte ausgeben
lngZ=1
Do While rsDaten.eof=false
for lngI=0 to rsDaten.fields.count-1
arrD(lngZ,lngI)= _
rsDaten.fields(lngI).value
next
lngZ=lngZ+1
rsDaten.MoveNext
Loop
rsDaten.Close
set rsDaten=nothing
Suchen=arrD
End Function
Function Ausgabe(arrD)
Dim lngZeile
Dim strAusgabe
Dim lngSpalte
For lngZeile=lbound(arrD,1) to ubound(arrD,1)
strAusgabe=strAusgabe & "<tr>"
for lngSpalte=lbound(arrD,2) to ubound(arrD,2)
strAusgabe=strAusgabe & _
"<td>" & arrD(lngZeile,lngspalte) & "</td>"
next
strAusgabe=strAusgabe & "</tr>"
Next
If strAusgabe="" Then
strAusgabe="<tr><td>Keine Datensätze gefunden!</td></tr>"
End If
Ausgabe=strAusgabe
End Function

Besonderheiten gegenüber der VBA-Programmierung

Besonderheiten gegenüber der VBA-Programmierung gibt es nur wenige. Statt das Objektmodell der Anwendung zu nutzen, die den Code ausführt, nutzen Sie hier das FileSystemObject- Objekt sowie bei Bedarf auch das WSH-Objektmodell. Variablen haben in VBScript keine Datentypen, sodass nur die Angabe des Datentyps Variant möglich ist, die daher auch ganz entfallen kann.

Letzteres wird allerdings im Beispiel nicht verwendet. Damit die Datenbank im gleichen Verzeichnis wie die HTA-Datei gesucht werden kann, ermittelt die Prozedur verbinden zunächst über die CommandLine-Eigenschaft der HTADatei deren vollständigen Pfad und dann daraus mit der GetParentFoldername-Eigenschaft des FileSystemObject-Objekts den übergeordneten Order. Den so ermittelten Pfad können Sie dann um den Wert der Konstanten DBName ergänzen und mit der BuildPath-Methode zu einem neuen Pfad zusammensetzen.

Der Verbindungsaufbau erfolgt dann prinzipiell wie in Excel oder Access auch, indem ein Connection-Objekt erzeugt wird. Es wird der Variablen objCon zugewiesen, über die dann alle anderen Prozeduren Zugriff auf die Datenbankverbindung haben. Die Prozedur Trennen sorgt dafür, dass die geöffnete Verbindung wieder geschlossen wird.

Bild 2: Das Eingabeformular für die Erfassung der Datensätze.

Mit Hilfe der Prozedur Suchen wird der Suchbegriff, der als Parameter übergeben wird, in der Tabelle gesucht und die ermittelten Datensätze als Array zurückgegeben. Dieses wird dann von der Prozedur Ausgabe durchlaufen, die ihrerseits dafür den HTML-Code für die tabellarische Darstellung der Daten erzeugt und ihn zurückgibt. Nachdem Sie alle Hilfsfunktionen erstellt haben, benötigen Sie noch eine Funktion, die diese Funktionen nacheinander aufruft und den Suchbegriff aus dem Formular ermittelt und übergibt (Listing 4).

Function skriptstarten()
Dim strHTML
strSuchbegriff=trim(document.forms(0).txtName.value)
verbinden
arrDaten=Suchen(strSuchbegriff)
strHTML=Ausgabe(arrDaten)
strHTML="<table>" & strHTML & "</table>"
trennen
document.all("ausgabe").innerHTML=strHTML
End Function

Auf die Steuerelemente des HTML-Formulars greifen Sie über das Objektmodell des Internet Explorer zu, dessen oberstes Objekt das document- Objekt ist. Über document.forms(0) greifen Sie also auf das erste Formular mit dem Index 0 zu. Dahinter geben Sie einfach den Namen des Formularsteuerelements an. Im Feld txtName steht der Suchbegriff, den Sie über die Eigenschaft Value ermitteln können.

Den Rückgabewert der Funktion Suchen übergibt die Funktion dann an die Funktion Ausgabe und fügt deren Rückgabewert in ein <table>-Element ein, das wiederum über die Eigenschaft innerHTML dem Element mit der ID "ausgabe" zugewiesen wird. Diese Funktion rufen Sie auf, wenn der Benutzer auf den Suchen-Button klickt. Diesen und das notwendige Formular müssen Sie noch erstellen, und zwar im <body>-Element der Seite. Die Tabellendefinition mit dem <table>-Element dient lediglich der Anordnung der Seitenelemente. Sie ist nicht für das Funktionieren der Anwendung wesentlich. Die dafür wichtigen Elemente werden daher im Listing fett hervorgehoben.Sie müssen Sie auf jeden Fall in das <body>- Element einfügen.

Damit die Funktion ausgeführt wird, wenn der Benutzer auf den mit <input type="button"> definierten Button klickt, ist das Attribut onclick notwendig. Es legt den Namen der auszuführenden Funktion fest.

Daten eingeben

Natürlich können Sie auf diese Weise nicht nur Daten ausgeben und suchen, sondern auch eine Eingabe ermöglichen. Dies soll abschließend noch an einem kurzen Beispiel demonstriert werden.

Sie benötigen zunächst ein zweites Formular innerhalb der HTA-Datei, die für jedes Tabellenfeld ein Eingabefeld vorsieht (Listing 6). Außerdem sind noch zwei Funktionen zu erstellen:eine, die die SQL-Anweisung aus den Anweisungen zusammensetzt, und eine zweite, der Sie die SQL-Anweisung übergeben, um sie mit der Execute-Methode des Connection-Objekts auszuführen (Listing 7).


<form>
<table width="80%">
<tr>
<td>Abteilung:</td>
<td>
<input type="text" id="txtAbteilung">
</td>
</tr>
<tr>
<td>Nachname:</td>
<td>
<input type="text" id="txtNachname">
</td>
</tr>
<tr>
<td>Vorname:</td>
<td>
<input type="text" id="txtVorname">
</td>
</tr>
<tr>
<td>Telefon:</td>
<td>
<input type="text" id="txtTelefon">
</td>
</tr>
<tr>
<td colspan="2">
<input type="button" value="Speichern" onclick="einfuegenstarten()">
</td>
</table>
</form>
<hr>
<div id="ausgabe">
</div>
</body>

Function einfuegen(strSQL)
Dim lngAnzahl
verbinden
Err.Clear
On Error Resume Next
lngAnzahl = objCon.Execute(strSQL)
If Err.Number = 0 Then
If lngAnzahl > 0 Then
einfuegen = "Der Datensatz wurde eingefügt!"
End If
End If
trennen
End Function
Function einfuegenstarten()
Dim strHTML
Dim strSQL
strSQL="INSERT INTO telMitarbeiter VALUES(""" & _
trim(document.forms(1).txtAbteilung.value) & """,""" & _
trim(document.forms(1).txtNachname.value) & """,""" & _
trim(document.forms(1).txtVorname.value) & """,""" & _
trim(document.forms(1).txtTelefon.value) & """)"
strHTML=strSQL & "<br>" & einfuegen(strSQL)
document.all("ausgabe").innerHTML=strHTML
End Functio

Um die SQL-Anweisung zusammenzusetzen, müssen Sie nur die Werte aus den Eingabefeldern auslesen. Dazu greifen Sie diesmal über den Index 1 auf das zweite Formular zu.

Mit der Funktion einfuegen können Sie freilich nicht nur Datensätze einfügen, sondern auch Änderungen durchführen, Datensätze löschen und vieles mehr. Sie müssen dazu nur eine andere SQL-Anweisung übergeben.

Wie geht es weiter?

HTA-Dateien sind eine preiswerte und sehr flexible Lösung, wenn es darum geht, ein Frontend für Access-Datenbanken zu erstellen. Problemlos ohne weitere Installationsschritte funktionieren solche Anwendungen auf fast jedem Rechner. Aber es gibt immer noch eine dritte Alternative: PHP. Wie das funktioniert, lesen Sie im abschließenden Teil dieser Artikelfolge.