 |
| Top-Quellcodes |
|
|
| Rubriken |
|
|
| Kontakt |
|
|
| Suchen |
|
|
|
|
|
Obwohl schon sehr viele Programmierer auf das neuere ADO umgestiegen sind, gibt es sicher noch einige, die mit DAO
arbeiten. Auch ich gehöre zu jenen, die mit DAO begonnen haben und aus mehreren Gründen nicht auf ADO umsteigen wollen.
DAO bietet zum einen den Vorteil, dass es mehr oder weniger ausgereift ist, was man von ADO nicht unbedingt behaupten kann. Weiters brauchen mit DAO weit weniger Dateien ausgeliefert werden, was die
Paketgröße - auch im Zeitalter der CD-ROM in Grenzen hält. Zumal die Auslieferung von Programmen sehr häufig über das Internet abläuft - was Free- und Shareware betrifft.
Ich will hier nicht weiter auf die Vor- und Nachteile von ADO eingehen; falls Sie erst mit der Datenbankprogrammierung begonnen haben, ist es sicher sinnvoller, gleich mit ADO zu beginnen!
Übersicht:
Allgemeines
Anlegen einer Datenbank
Zugriff auf die Datenbank
Datensatz anzeigen
Editieren eines Datensatzes Hinzufügen von Datensätzen
SQL-Abfragen
Zusammenfassung
|
| Allgemeines zur Jet-Engine |
Der Begriff JET bedeutet Joint Engine Technology. Es handelt sich hierbei um eine Anzahl von Laufzeitbibliotheken - Dynamic Link Libraries (DLLs). Als Schnittstelle wird vornehmlich ACCESS verwendet,
möglich sind aber auch Xbase, Paradox, Btrieve, HTML oder ODBC.
DBEngine
Von der JET-Engine wird das vordefinierte DBEngine-Objekt automatisch erstellt. Es repräsentiert also das Datenbankmodul
Workspace-Objekt
Workspace bedeutet Arbeitsbereich. Mit dem Workspace-Objekt können Sie also neue Datenbanken anlegen, öffnen und verwalten. Wie Sie mit dem Workspace arbeiten, erfahren Sie gleich.
Database-Objekt
Beim Database-Objekt handelt es sich um ein virtuelles Abbild der Datenbank mit allen Tabellen und Abfragen (Jedoch keine Formulare, Module oder Berichte).
Recordset-Objekt
Hier geht es um das virtuelle Abbild der Tabelle(n) in der Datenbank. Allerdings können 5 verschiedene Typen verwendet werden:
1. Dynaset
2. Snapshot
3. Table
4. Forward
5. Dynamic
Dynaset und Snapshot
Dynasets sind das Resultat einer Abfrage und lassen sich editieren. Im Gegensatz dazu sind Recordsets vom Typ Snapshot ein Abbild zum Zeitpunkt der Abfrage. Sie lassen sich nicht editieren und sind
damit nur für die Anzeige und Auswertung von Daten zuständig.
Table
Hier handelt es sich um das Abbild nur einer Tabelle (mit allen Spalten).
Forward und Dynamic
Diese Datentypen sind eigentlich nur für ODBC-Datenquellen interessant und optimieren Datenbankzugriffe. Sie werden hier nicht weiter behandelt.
SQL
SQL bedeutet Structured Query Language. Es ist also die Kommunikation zwischen einem Programm und einer Datenbank.
Eine SQL-Abfrage dient dazu, die ungeordneten Datenbankeinträge in eigene "Listen" zusammenzufassen. Das Ergebnis einer solchen Abfrage wird nur temporär im Speicher abgelegt.
Es würde die Grenzen dieses Tutorials bei weitem sprengen, würde ich auch noch alle verfügbaren Parameter für SQL-Abfragen aufzählen. Deshalb wollen wir später anhand eines Beispiels auf die
wichtigsten eingehen. |
Genug der Theorie, die die meisten Programmierer sowieso nicht sehr interessieren dürften (mich eingeschlossen), aber oft sehr hilfreich sind, um den gesamten Aufbau zu begreifen.
Eine Datenbank anlegen
Was tun, wenn auf dem (Ziel-)Computer noch keine Datenbank angelegt ist, oder man eine fertig aufgebaute Datenbank nicht ausliefern will ?
Man legt selbst eine Datenbank an - mit Visual Basic ! Vergessen Sie nicht, einen Verweis (Reference) auf die DAO360.dll zu setzen. Sie dürfte sich standardmäßig im Pfad "C:\Programme\Gemeinsame
Dateien\Microsoft Shared\DAO" befinden. Der Pfad kann natürlich abweichen!
Die Datei DAO350.dll ist für Datenbanken zuständig, die mit ACCESS97 kompatibel sind, DAO360.dll harmoniert nur mit ACCESS2000.
Workspace festlegen
Sie erinnern sich ? - Ein Workspace ist ein Arbeitsbereich. Also müssen wir diesen zuerst einmal festlegen. Vorher sollten Sie aber (übersichtshalber) ein paar Begriffe deklarieren. Zum Beispiel den
Pfad zur Datenbank.
Sinnvoll ist ein Start des Programms aus einem Modul heraus.
' Modul:
' Deklarationen:
Global ws As Workspace
Global db As Database
Global dy As DAO.Recordset
Dim DatenBank
Sub Main()
Datenbank = App.Path & "\DeineDatenbank.mdb"
Set ws = DBEngine.Workspaces(0)
Falls die Datenbank noch nicht vorhanden ist, wird sie jetzt angelegt:
If Dir(datenbank) = "" Then ' Datei nicht vorhanden
Set db = ws.CreateDatabase(DatenBank, dbLangGeneral)
Call NeueTabelleAnlegen
db.Close
Set db = ws.OpenDatabase(DatenBank, False, False)
Else
Set db = ws.OpenDatabase(DatenBank, False, False)
End If
End Sub
Database / CreateDatabase
Im Sub Main haben wir einen Arbeitsbereich festgelegt und eine neue Datenbank angelegt. Die Routine zum Erstellen von Tabellen in dieser DB erfolgt im Sub NeueTabelleAnlegen.
Sub NeueTabelleAnlegen()
Dim i%
Dim td As New TableDef
Dim fld() As New field
Dim Temp As field
Dim Temp1 As field
ReDim fld(3)
td.Name = "Tabelle1" 'Tabellenname
For i = 1 To 3
fld(i).Name = Choose(i, "Nr", "Anrede", "Name")
fld(i).Type = Choose(i, DBLONG, DBTEXT, DBTEXT)
fld(i).Size = Choose(i, 10, 10, 50)
If i = 1 Then fld(i).Attributes = 16
td.Fields.Append fld(i)
Next I
Set Temp = td.CreateField("Vorname", dbText, 50)
Temp.AllowZeroLength = True
Temp.Required = False
td.Fields.Append Temp
Set Temp1 = td.CreateField("Straße", dbText)
Temp1.AllowZeroLength = True
Temp1.Required = False
td.Fields.Append Temp1
Dim ind As New Index 'Primärschlüssel Tabelle
ind.Name = "PrimaryKey"
ind.Fields = "nr"
ind.Primary = True
ind.Unique = True
td.Indexes.Append ind
db.TableDefs.Append td
End Sub
Erläuterungen:
Jede Zeile zu erklären, würde den Rahmen sprengen, deshalb hier die wichtigsten Anmerkungen:
Zuerst muß ein Verweis auf das Objekt "TableDef" gesetzt werden
Dim td as New TableDef
Dann werden die einzelnen Tabellenfelder deklariert
Dim Feld1 As field
Field.Name ist sozusagen die Spaltenbezeichnung bzw. Überschrift
Field.Type ist der Datentyp. Wollen Sie nur Text in der betreffenden Spalte speichern, wählen Sie einfach
dbText. Für Zahlen wäre dbLong passend. Ist vorauszusehen, dass der Text sehr lang wird und eventuell Daten aus einer Richtextbox enthalten wird, empfiehlt sich der Datentyp "Memo" (dbMemo).
Field.Size ist die reservierte Größe für den Spalteninhalt. Haben Sie beispielsweise "10" angegeben, können Werte (egal von welchem Typ) nicht größer
bzw länger sein.
Field.AllowZeroLength = True oder False heißt, dass Sie bestimmen, ob das betreffende Feld leer bleiben
darf oder nicht.
Mit td.Fields.Append wird die nun angelegte Spalte in die Tabelle übernommen.
Abschließend muß die gesamte Tabelle in die DB übernommen werden - mit
Db.TableDefs.Append td
Nach diesem Muster können weitere Tabellen angelegt werden, sinnvollerweise immer in einem anderen Sub.
|
| Zugriff auf die Datenbank |
Nun haben wir mit Visual Basic eine ACCESS-Datenbank mit der Dateiextension *.mdb angelegt. Sie können diese mit ACCESS2000 öffnen und überprüfen. Natürlich auch mit ACCESS ändern.
Sie wollen aber sicher auf die nun angelegte DB zugreifen, Daten anzeigen, Daten editieren, verwalten, ordnen, Abfragen erstellen, etc.
Daten aus den einzelnen Tabellen anzeigen
Um die Daten aus der Datenbank anzuzeigen, bieten sich mehrere Möglichkeiten an. Sie können das DBGrid-Control verwenden, ebenso das MSFlexGrid-Control. Meine liebste Variante ist allerdings die
Anzeige in einem ListView-Steuerelement.
Nehmen Sie für ein Beispiel eine Form (Form1) und platzieren Sie ein Listview darauf. Natürlich müssen Sie das Listview mit einem ImageList, welches die Symbole enthält, verknüpfen. Die Ansicht des
Listview stellen Sie am besten auf lvwReport.
Allgemeiner Teil (Deklarationen):
Private daoDB36 As Database
Private dy2 As DAO.Recordset
Ereignis Form_Load():
ListView1.ColumnHeaders.Add , "Col1", "NAME"
ListView1.ColumnHeaders.Add , "Col2", "Vorname"
Hier kommt es darauf an, welche Spalten aus der Tabelle angezeigt werden sollen. Es müssen nicht alle sein ! Hier kommt nämlich schon SQL ins Spiel. Anhand einer Abfrage wird also gefiltert,
welche Daten angezeigt werden sollen.
Set dy2 = db.OpenRecordset("Select * from Tabellenname")
In diesem Fall wird mit * alles ausgewählt. Wie Sie weitere SQL-Abfragen erstellen, erfahren Sie noch.
Dim itmX As ListItem
' Überprüfen, ob überhaupt Daten in der Tabelle vorhanden sind !
If dy2.EOF And dy2.BOF Then
Exit Sub
End If
Stellt den Satzzeiger auf die 1. Position
dy2.MoveFirst
In einer Schleife wird in das Listview eingelesen:
While Not dy2.EOF
Set itmX = ListView1.ListItems.Add(, "N" & CStr(dy2!nr), CStr(dy2!Name), 1, 1)
itmX.SubItems(1) = dy2!Name
itmX.SubItems(2) = dy2!Vorname
Gehe zum nächsten Datensatz:
dy2.MoveNext
Wend
Recordset wieder schließen:
Dy2.Close
Mit diesem kurzen Code haben wir erfolgreich unsere Daten aus der Tabelle eingelesen. Natürlich können auch Daten aus mehreren Tabellen angezeigt werden.
|
Was nützt eine eingelesene Datenbank mit all ihren Tabellen, wenn die Daten nicht bearbeitet werden können ?
Also müssen die Daten in Textfeldern, Comboboxes, etc. angezeigt werden.
Erstellen Sie ein neues Formular mit zwei Textboxen und einem CommandButton mit der .Caption "Speichern".
Damit dieses Bearbeitungsformular für einen beliebigen Datensatz aufgerufen werden kann, müssen wir überprüfen, welcher ListView.Item gewählt wurde.
Im Ereignis Listview1_DblClick() rufen Sie das Formular auf, zB mit "frmWork.show". Mehr muss der Aufruf nicht enthalten!
Im Load-Ereignis von frmWork passiert folgendes:
Allgemeine Deklarationen:
Private daoDB36 As Database
Private rs As DAO.Recordset
Form_Load:
Dim Anwendungspfad as String
Anwendungspfad = App.Path & "\DeineDB.mdb"
Set daoDB36 = DBEngine(0).OpenDatabase(Anwendungspfad)
Dim Abfrage As String
Dim xZahl
Dim s$
s = Form1.ListView1.SelectedItem.key
Sie erinnern sich ? - Den Key der ListviewItems haben wir beim Einlesen bereits festgelegt ! ("N" & dy!nr)
xZahl = Right(s, Len(s) - 1)
Abfrage = "SELECT * FROM DeineTabelle WHERE nr=" & xZahl
Verstehen Sie diesen sehr einfachen SQL-String ?
SELECT (Wähle) / * ( alle Daten ) / FROM DeineTabelle (von Tabelle) / WHERE nr= xZahl ( wo die Spalte "nr" XZahl ist.)
Set rs = daoDB36.OpenRecordset(Abfrage)
Doch HALT !
Wir brauchen noch etwas !
Was Sie noch nicht kennen, sind sogenannte "Bounded Controls", also gebundene Steuerelemente. Beispielsweise eine Textbox, die mit dem Data-Steuerelement verbunden sind.
Fügen Sie also das Steuerelement "Data" ein (zB Data1). Wir brauchen es nur im Hintergrund, die Eigenschaft Visible kann auf false gestellt sein. Die Eigenschaften von Data erfolgen erst zur
Laufzeit:
With Data1
.DatabaseName = App.Path & "\DeineDatenbank.mdb"
.RecordSource = Tabellenname
End With
Set Data1.Recordset = rs
Die Textboxes auf unserem "Bearbeitungsformular" müssen natürlich mit dem Data-Control verbunden sein.
Dazu setzen Sie für Text1.DataSource = Data1 und .Datafield die Bezeichnung der Spalte (nehmen wir an, Name).
Verfahren Sie mit dem zweiten Textcontrol ebenso, diesmal nehmen wir als Datafield "Vorname".
Einem Testlauf steht nichts mehr im Weg. Beim Klick auf das Listview (eine beliebige Zeile oder Item) wird der richtige Datensatz im Formular2 (im Beispiel frmWork) angezeigt.
|
| Editieren eines Datensatzes |
Sie haben zwar jetzt einen beliebigen Datensatz aufgerufen und den Namen und Vornamen angezeigt. Nun brauchen Sie aber auch eine Funktion zum Editieren des Datensatzes (Löschen, Verändern). Zum
Neuanlegen kommen wir etwas später.
In das Ereignis des CommandButton_Click () kommt:
With Data1.Recordset
.Edit
.Update
.MoveLast
End With
Wollen Sie einen Datensatz löschen, verfahren Sie ungefähr so:
Entweder Sie verweisen direkt auf das Recordset:
If rs.Updatable And rs.EditMode = dbEditNone Then
rs.Delete
rs.MoveNext
If rs.EOF And Not rs.BOF Then rs.MoveLast
End If
Oder Sie nehmen das Data-Control, wobei diese auf meinem PC nicht immer funktionierte.
With Data1.Recordset
.Delete
.MoveLast
End With
Beim Entladen der Form sollten Sie darauf achten, dies dem Data-Control mitzuteilen.
Private Sub Form_Unload ()
With Data1.Recordset
.Edit
.CancelUpdate
End With
End Sub
|
Es bieten sich zwei Möglichkeiten an:
1) Sie verwenden wieder das Data-Control oder
2) Sie kommen ohne dieses Control aus (viel interessanter)
Nehmen Sie eine neue Form (frmNew). Fügen Sie zwei Textfelder und einen CommandButton ein.
Wenn Sie mit dem DataControl arbeiten möchten, müssen Sie wieder auf die Eigenschaften eingehen, wie im vorigen Punkt beschrieben. Und Sie müssen die Textfelder an das DataControl binden.
With Data1
.Addnew
.Update
.Movelast
End With
Ohne Data-Control gibt es wieder zwei Möglichkeiten:
Entweder mit einem SQL-String oder über das DAO.Recordset.
Der SQL-String würde etwa so lauten:
Dim sqlQuery As String
sqlQuery = "UPDATE DeineTabelle SET Name = " & (Text1.Text)
db.Execute sqlQuery
Und hier mit dem DAO.Recordset:
Dim dy As DAO.Recordset
Set dy = db.OpenRecordset(DeineTabelle)
dy.AddNew
dy!Name = Text1.Text ' achten Sie auf "!", nicht "."
dy!vorname = Text2.Text
dy.Update
dy.Close
|
Anhand eines Beispiels möchte ich Ihnen zeigen, wie Sie verschiedene Abfragen erstellen und das Ergebnis in einem DBGrid-Control anzeigen. Sie könnten natürlich auch ein DBGrid anstelle des ListView
verwenden, um alle Daten einer Tabelle anzuzeigen.
Für das Abfrageformular brauchen wir eine Form (natürlich), ein DBGrid-Control welches mit einem Data-Control verbunden ist, eine Textbox (text1) und einen CommandButton ("Suchen")
Tipp: Wenn Sie die Eigenschaft DBGrid1.AllowUpdate auf True stellen, werden alle Änderungen im DBGrid wirksam. Sie ersparen sich theoretisch ein Formular zur Anzeige eines Datensatzes,
um diesen zu bearbeiten. Aber vielleicht wollen Sie nicht alle Datensätze anzeigen, oder - was noch weit wichtiger ist - Eingabefehler des Benutzers abfangen. In diesem Fall sollten Sie unser frmWork
verwenden.
Text1 soll als Eingabefeld verwendet werden. Dort kann der Suchbegriff eingegeben werden. Wenn das Feld freibleibt, werden alle vorhandenen Datensätze angezeigt.
Allgemeine Deklarationen:
Private daoDB36 As Database
Private rs As DAO.Recordset
Ereignis CommandButton_Click() - Suche / Abfrage starten
Dim Sel As String
Sel = "SELECT * FROM DeineTabelle WHERE Name LIKE " & "'" & _
Tex1.text & "*'"
Set daoDB36 = DBEngine(0).OpenDatabase(Anwendungspfad+*.mdb)
Set rs = daoDB36.OpenRecordset(Sel)
Data1.DatabaseName = App.Path & "\DeineDB.mdb"
Set Data1.Recordset = rs
Data1.Recordset.MoveLast
Anmerkung:
Wichtig sind die einfachen Anführungszeichen oben, die vor und nach dem text1.text stehen ! Sie können statt LIKE auch "=" angeben, dann werden allerdings nur genau übereinstimmende Einträge
gefunden !
Mit LIKE text1.text* (Beispiel Hall*) werden Hallo, Halle, Hallstatt, Hallein etc. gefunden. Geben Sie beispielsweise vor dem Text auch ein * an, so finden Sie
Bei * ha * cha, char, aha...
Mehr SQL:
Mit SQL-Strings können Sie nicht nur eine Abfrage / Suche verwirklichen, sondern auch Datensätze begrenzt anzeigen.
Im Formular1 haben wir mit dem Listview Daten eingelesen und zwar mit:
"SELECT * FROM Tabelle"
Damit wird alles erfasst.
Mit SELECT Name, Vorname FROM Tabelle erfassen die eben nur Namen und Vornamen; alle anderen Einträge bleiben unberücksichtigt.
Wollen Sie nur bestimmte Datensätze anzeigen, fügen Sie die WHERE-Klausel ein:
"SELECT * FROM Tabelle WHERE Name = 'HAMMER' "
Mit diesem SQL-String werden alle Einträge mit dem Namen HAMMER gefunden. Sollte jemand mit Vornamen HAMMER heissen, wird er nicht erfasst !
Weitere WHERE-Klauseln sind denkbar:
SELECT * FROM Tabelle WHERE Gehalt > 10000
Es werden alle Personen aufgelistet, die mehr als 10000 Euro verdienen.
SELECT Name FROM Tabelle WHERE Gehalt BETWEEN 100 AND 200
Zeigt alle Namen der Personen, die zwischen 100 Euro und 200 Euro verdienen. (Das Recordset filtert sozusagen nur die Spalte Namen heraus, alle anderen Einträge bleiben unberücksichtigt)
SELECT * FROM Tabelle WHERE Gehalt IS NULL
Zeigt alle Einträge von Personen, die nichts verdienen :-(
Die Beispiele ließen sich beliebig weiterführen...
|
| Zusammenfassung und Beispiel |
Natürlich hätte auch ein einfaches Beispiel zur Demonstration genügt. Man denke bloß an ein
Formular mit zwei Textboxen und einem Data-Control. Mit jedem Click auf das Data (nächster oder vorheriger Datensatz) würden die entsprechenden Einträge in den Textboxes angezeigt werden.
Ich finde jedoch, dass die Arbeit mit dem ListView übersichtlicher ist; außerdem kann schon beim Laden der Daten in das Listview eingelesen und per SQL-Anweisung gefiltert werden.
Beispielprojekt als Download (66,6 KB)
|
|