Untitled

Werbung
Ralf Albrecht, Natascha Nicol
Access 2003 programmieren
Professionelle Anwendungsentwicklung
mit Access und VBA
eBook
Die nicht autorisierte Weitergabe dieses eBooks
ist eine Verletzung des Urheberrechts!
An imprint of Pearson Education
München • Boston • San Francisco • Harlow, England
Don Mills, Ontario • Sydney • Mexico City
Madrid • Amsterdam
Datenzugriff mit Recordsets
Sub RecordsetOhneFilter()
Dim db As DAO.Database
Dim rst As DAO.Recordset
Set db = CurrentDb()
Set rst = db.OpenRecordset("Select * From _
qryAnzahlCocktailZutaten Where Cocktail Like 'C*'")
' Wiederhole bis zum Ende des Recordsets
While Not rst.EOF
Debug.Print rst!Cocktail;
Debug.Print " mit "; rst("Anzahl von ZutatenNr");
Debug.Print " Zutaten"
rst.MoveNext
Wend
rst.Close
End Sub
Eine interessante Methode im Zusammenhang mit Filtern ist BuildCriteria()
zum Zusammenstellen einer Filterbedingung (siehe 14.2.6).
11.4.5
Sortieren von Recordsets
Bei der Sortierung von Recordsets müssen wiederum die Recordset-Typen Table,
Dynaset und Snapshot unterschieden werden.
Sortierte Table-Recordsets
Nach dem Öffnen eines Recordsets vom Typ Table sind die Datensätze nach dem
Primärschlüssel der zugrunde liegenden Tabelle geordnet. Um die Sortierung zu
ändern, muss im Programm die Eigenschaft Index des Recordsets eingestellt
werden, so wie dies schon im Abschnitt 11.4.4, »Suchen von Datensätzen«, beschrieben wurde. Diese Eigenschaft kann nur für Table-Recordsets eingestellt
werden, anderenfalls kommt es zu einer Fehlermeldung. Durch Setzen der IndexEigenschaft, z. B. in der Form
Dim rstTable As DAO.Recordset
Set rstTable = CurrentDb().OpenRecordset("tblCocktailLokal")
rstTable.Index "Cocktail"
liegen die Datensätze nach »Cocktail« sortiert vor.
343
11 Datenzugriff mit DAO
Sortieren in Dynasets und Snapshots
Es stehen Ihnen für die Sortierung von Dynasets und Snapshots zwei unterschiedliche Verfahren zur Verfügung:
§ Sortieren durch eine ORDER BY-Klausel in der SQL-Abfrage oder
§ sortieren mit der Sort-Eigenschaft des Recordsets.
Für beide Varianten gelten im Prinzip die gleichen Aussagen, wie wir sie in
Abschnitt 11.4.4, »Suchen von Datensätzen«, für die Filter-Eigenschaft getroffen
haben. Verwenden Sie nach Möglichkeit immer ORDER BY und verzichten Sie auf
den Einsatz der Eigenschaft Sort.
11.4.6
Lesezeichen
Oft ist es in Programmen notwendig, sich die Position bestimmter Datensätze zu
merken, um später darauf zurückkommen zu können. Access arbeitet mit so genannten Lesezeichen, englisch Bookmarks. Access führt für jeden Datensatz eines
Recordsets eine eindeutige Markierung. Diese Markierung kann in einer eigenen
Variablen gespeichert werden, um so später als Sprungadresse zu dienen.
Lesezeichen sind nicht mit den Datensatznummern von dBase oder anderen Produkten vergleichbar, denn ihre Gültigkeit ist auf die Lebensdauer des Recordsets
beschränkt. Ein Bookmark besitzt den Typ String, den Sie allerdings nicht beachten sollten, da er Access-intern festgelegt wird und sich in späteren Versionen
ändern kann.
Nicht alle Recordsets ermöglichen das Setzen von Lesezeichen. Die Eigenschaft
Bookmarkable des Recordsets zeigt die Lesezeichenunterstützung an.
Das folgende Programmfragment weist das Lesezeichen des aktuellen Datensatzes einer Variablen zu und setzt am Ende die Position des aktuellen Datensatzes
auf den Datensatz, zu dem das gespeicherte Lesezeichen gehört.
Dim strLesezeichen As String
...
' Speichern des Lesezeichens
strLesezeichen = rst.Bookmark
...
rst.MoveFirst
...
' Sprung zurück
rst.Bookmark = strLesezeichen
344
Datenzugriff mit Recordsets
11.4.7
Recordset-Daten bearbeiten
In Recordsets vom Typ Table und in bearbeitbaren Dynasets können Sie Veränderungen an den Daten vornehmen bzw. neue Datensätze hinzufügen.
Ob ein Dynaset bearbeitbar ist, können Sie mit der Eigenschaft Updatable des
Recordsets ermitteln. Nicht bearbeitbare Dynasets und Snapshots liefern für
Updatable den Wert False zurück.
Wir möchten in diesem Abschnitt nicht die Besonderheiten von Multiuser-Zugriffen auf Daten besprechen, da alle Fragen, die sich mit dem Sperren (Locking) von
Daten beschäftigen, in Kapitel 18, »Multiuser-Zugriffe«, behandelt werden.
Verändern von Daten
Um den aktuellen Datensatz zu ändern, kopieren Sie mithilfe der Methode Edit
die Daten in einen internen Puffer. Sind die Daten bearbeitet, wird die Änderung
mit der Update-Methode geschrieben. Erst nach dem Update sind die Bearbeitungen dauerhaft gespeichert. Bewegen Sie vor dem Update den Positionszeiger zu
einem anderen Datensatz, werden die Änderungen verworfen.
Das folgende Programm durchläuft die Datensätze und ändert überall den Inhalt
des Feldes CocktailGeändert auf das aktuelle Datum.
Sub EditMethode()
Dim db As DAO.Database
Dim rst As DAO.Recordset
Set db = CurrentDb()
Set rst = db.OpenRecordset("tblCocktail")
With rst
If .Updatable Then
While Not .EOF
.Edit
!CocktailGeändert = Now()
.Update
.MoveNext
Wend
End If
End With
rst.Close
End Sub
345
11 Datenzugriff mit DAO
Wenn Sie versuchen, die Methode Edit auf ein Recordset anzuwenden, dessen
Eigenschaft Updatable den Wert False hat, erhalten Sie eine Fehlermeldung.
Neue Datensätze hinzufügen
Mithilfe der AddNew-Methode wird dem Recordset ein neuer Datensatz hinzugefügt. Durch den Aufruf von AddNew wird im internen Puffer ein leerer Datensatz
erzeugt. Leer heißt, dass alle Felder den Wert NULL erhalten.
Anschließend können den Feldern Werte zugewiesen werden. Nach einem
Update werden die Daten in die zugrunde liegenden Tabellen geschrieben.
Sub AddNewMethode()
Dim db As DAO.Database
Dim rst As DAO.Recordset
Set db = CurrentDb()
Set rst = db.OpenRecordset("tblCocktailLokal")
With rst
If .Updatable Then
.AddNew
!Cocktail = "Klare Sache"
!Alkoholgehalt = 0#
!Zubereitung = "Eiswürfel ins Glas geben, " & _
"Mineralwasser darübergießen, nicht umrühren."
.Update
End If
End With
rst.Close
End Sub
Die Eigenschaft LastModified
Nach dem Bearbeiten eines Datensatzes mit Edit oder dem Hinzufügen mit AddNew steht der Positionszeiger nach der Ausführung von Update auf dem zuletzt
aktuellen Datensatz. Möchten Sie später im Programm, wenn Sie den Positionszeiger weiterbewegt haben, zu dem zuletzt bearbeiteten Datensatz zurückspringen, können Sie dies mit
rst.Bookmark = rst.LastModified
durchführen. Alternativ können Sie auch folgenden Befehl verwenden:
rst.Move 0, rst.LastModified
346
Datenzugriff mit Recordsets
Status der Bearbeitung
Es kann sinnvoll sein, den Status der Bearbeitung abzufragen. Mithilfe der Eigenschaft EditMode können Sie den aktuellen Stand erfahren. Die folgende Tabelle
führt die Werte auf, die die Eigenschaft annehmen kann.
Tabelle 11.6: Konstanten für den Bearbeitungsstatus
Option
Beschreibung
dbEditNone
gibt an, dass keine Bearbeitung eines Datensatzes
durchgeführt wird.
dbEditInProgress
gibt an, dass der aktuelle Datensatz mit Edit bearbeitet wird, aber noch nicht gespeichert ist.
dbEditAdd
gibt an, dass ein neuer Datensatz hinzugefügt wurde,
aber noch nicht gespeichert ist.
Datensätze löschen
Sie können den aktuellen Datensatz mithilfe der Methode Delete löschen. Der
Positionszeiger verbleibt nach dem Löschvorgang auf dem gleichen, jetzt
gelöschten Datensatz.
Löschen ist in Access endgültig, ein per Programm gelöschter Datensatz kann
nicht wiederhergestellt werden. Es besteht allerdings eine Ausnahme, wenn Sie
mit Transaktionen arbeiten, denn solange eine Transaktion nicht abgeschlossen
ist, kann eine Löschung, die innerhalb der Transaktion stattfand, rückgängig
gemacht werden. Mehr zu Transaktionen erfahren Sie in Kapitel 18, »MultiuserZugriffe«.
Oder doch besser SQL?
Wir möchten Ihnen zu bedenken geben, dass sich alle Änderungen an Datensätzen auch mit SQL vornehmen lassen. Der SQL-Befehl UPDATE ermöglicht die
schnelle Änderung von Datensatzgruppen, mit INSERT INTO können Sie neue
Datensätze aufnehmen. In Abschnitt 11.5.4, »Parameterabfragen«, finden Sie die
Funktion Alkoholgehalt(), die einmal mit Move-Befehlen und einmal mit SQL
gelöst wurde.
Insbesondere wenn Sie vorher mit dBase, FoxPro oder ähnlichen Datenbanken
gearbeitet haben, sollten Sie sich mit den Möglichkeiten von SQL vertraut machen.
347
11 Datenzugriff mit DAO
11.4.8
Weitere Recordset-Methoden
In diesem Abschnitt möchten wir Ihnen weitere Recordset-Methoden vorstellen.
Die Methode GetRows( )
Mithilfe der Recordset-Methode GetRows() kann die Ergebnismenge eines
Recordsets ganz oder teilweise in ein zweidimensionales Feld übertragen
werden. Dabei wird GetRows() als Parameter die Anzahl der in das Array
aufzunehmenden Zeilen übergeben. Ist die Zahl höher als die Anzahl der
Datensätze im Recordset, wird das Array entsprechend dimensioniert. Durch
UBound(var,2) + 1 kann die tatsächlich übertragene Anzahl bestimmt werden.
Damit die Funktion UBound() die korrekte Anzahl von Zeilen des zweidimensionalen Arrays zurückgibt, muss als zweiter Parameter die Anzahl der
Dimensionen des Arrays übergeben werden, so wie es unten im Beispiel durch
die Konstante conDimension durchgeführt wird.
Sub FillArray()
Const conDimension = 2
Dim db As DAO.Database
Dim rec As DAO.Recordset
Dim varArr As Variant
Dim intCount As Integer
Set db = CurrentDb()
Set rec = db.OpenRecordset("qryAnzahlCocktailZutaten", dbOpenSnapshot)
' Einlesen des kompletten Recordsets, Aktualisieren von RecordCount
rec.MoveLast
' Zurück zum ersten Datensatz
rec.MoveFirst
' Anfordern der Ergebnismenge des Recordsets
varArr = rec.GetRows(rec.RecordCount)
MsgBox Str(UBound(varArr, conDimension) + 1) " Zeilen eingelesen."
rec.Close
End Sub
Beachten Sie beim Übertragen von Daten, dass insbesondere Memo- und OLEObjekt-Felder große Datenmengen beinhalten können, die dann mit GetRows() in
den Hauptspeicher aufgenommen werden.
Versucht die GetRows()-Methode auf einen Datensatz zuzugreifen, der zwischenzeitlich gelöscht wurde, bricht GetRows() ab, d. h., nicht alle angeforderten Datensätze werden übertragen. Überprüfen Sie daher mit
348
Datenzugriff mit Recordsets
If UBound(varArr, conDimension) + 1 <> rec.RecordCount Then
' Nicht alle Datensätze eingelesen
End If
ob tatsächlich alle Datensätze im Array angekommen sind.
Die Methode Clone( )
Die Clone()-Methode erstellt eine identische Kopie eines Recordsets. Dies ist
beispielsweise hilfreich, wenn Sie Daten zweier Datensätze des Recordsets gleichzeitig verarbeiten müssen. Im folgenden Beispiel wird ein Recordset rec Datensatz für Datensatz durchlaufen. Für jeden Datensatz wird in einer Kopie des
Recordsets, also in der gleichen Ergebnismenge, nach Datensätzen gesucht, die
die gleiche Kategorie wie der Datensatz des Original-Recordsets haben.
Sub TestRecordsetClone()
Dim db As DAO.Database
Dim rec As DAO.Recordset
Dim recClone As DAO.Recordset
Set db = CurrentDb()
' recordset enthält zwei Spalten: "CocktailNr" u. "KategorieNr"
Set rec = db.OpenRecordset("tblCocktailKategorie", dbOpenSnapshot)
' Recordset klonen
Set recClone = rec.Clone()
While Not rec.EOF
With recClone
.FindFirst "KategorieNr = " & rec!KategorieNr
While Not .NoMatch
Debug.Print rec!CocktailNr _
& " hat die gleiche Kategorie wie " _
& !CocktailNr
.FindNext "KategorieNr = " & rec!KategorieNr
Wend
.MoveFirst
End With
rec.MoveNext
Wend
rec.Close
End Sub
Die Methode Clone() bietet einen weiteren Zugriff auf die gleichen Daten, Sie
erhalten aber eine weitere aktuelle Zeile und ein weiteres Lesezeichen (Bookmark).
349
11 Datenzugriff mit DAO
Die Lesezeichen von Original und Klon sind austauschbar, d. h., eine Zuweisung
wie recClone.Bookmark = rec.Bookmark ist zulässig.
Die Methode Clone() ist eng verwandt mit der Methode RecordsetClone() für
Formulare. In Kapitel 14, »Formulare«, beschreiben wir den Einsatz von RecordsetClone().
11.5
Arbeiten mit QueryDefs
Mit der OpenRecordset-Methode lassen sich, wie beschrieben, gespeicherte Auswahlabfragen öffnen oder SQL-Zeichenfolgen direkt eingeben. Für die Bearbeitung von Aktions-, Kreuztabellen-, Datendefinitions- und Parameterabfragen
benötigen Sie QueryDef-Objekte.
11.5.1
Arbeiten mit QueryDef-Objekten
Wir möchten Ihnen an einem kurzen Beispiel den Einsatz einer Aktualisierungsabfrage in einem Programm erläutern. Auf die entsprechende gespeicherte
Abfrage wird über ihren Namen zugegriffen. Jede gespeicherte Abfrage ist
Bestandteil der QueryDefs-Auflistung. Liefern Abfragen keine Datensätze zurück,
sondern führen sie eine Aktion durch, werden sie mit der Methode Execute
ausgeführt.
Sub Aktionsabfragen()
Dim db As DAO.Database
Dim qry As DAO.QueryDef
Dim rst As DAO.Recordset
Set db = CurrentDb()
' Die Aktualisierungsabfrage "qupdAlkoholgehalt" bringt den
' Alkoholgehalt der Cocktails auf den neusten Stand
Set qry = db.QueryDefs("qupdAlkoholgehalt")
' Ausführen der Abfrage
qry.Execute
Debug.Print "Betroffene Datensätze: "; qry.RecordsAffected
End Sub
350
Arbeiten mit QueryDefs
Versuchen Sie Auswahl-, Kreuztabellen- oder Union-Abfragen mit der Methode
Execute auszuführen, erhalten Sie eine abfangbare Fehlermeldung. Das folgende
Programm zeigt, wie aufgrund des Typs der Abfrage verzweigt werden kann.
Sub Abfragen()
Dim db As DAO.Database
Dim qry As DAO.QueryDef
Dim rst As DAO.Recordset
Dim fld As DAO.Field
Dim strQry As String
Set db = CurrentDb()
strQry = InputBox("Name der Abfrage")
Set qry = db.QueryDefs(strQry)
If qry.Type = dbQSelect Or qry.Type = dbQSetOperation _
Or qry.Type = dbQCrosstab Then
Set rst = qry.OpenRecordset()
While Not rst.EOF
For Each fld In rst.Fields
Debug.Print fld;
Next
Debug.Print
rst.MoveNext
Wend
rst.Close
Else
qry.Execute
Debug.Print "Betroffene Datensätze: "; qry.RecordsAffected
End If
End Sub
Der Methode Execute kann ein Parameter mitgegeben werden, der die Aktionsabfrage steuert. Die folgende Tabelle zeigt die entsprechenden Konstanten.
351
11 Datenzugriff mit DAO
Tabelle 11.7: Konstanten für Aktionsabfragen
Eigenschaft
Beschreibung
dbDenyWrite
verhindert, dass andere Benutzer während der Abfrage
schreibend auf die der Abfrage zugrunde liegenden Tabellen
zugreifen können.
dbInconsistent
führt auch inkonsistente Aktualisierungen durch. Dieses ist die
Standardeinstellung.
dbConsistent
erzwingt konsistente Aktualisierungen.
dbSQLPassThrough
sorgt dafür, dass die SQL-Anweisung zur Verarbeitung an
eine ODBC-Datenbank weitergereicht wird.
dbFailOnError
setzt Aktualisierungen zurück, wenn ein Fehler auftritt.
dbSeeChanges
löst einen Laufzeitfehler aus, wenn ein anderer Benutzer
Daten ändert, die von der Abfrage bearbeitet werden.
Wichtig ist insbesondere die Konstante dbFailOnError. Durch sie werden beim
Auftreten eines Fehlers alle Änderungen, die die Aktionsabfrage bis zum Zeitpunkt des Fehlers durchgeführt hat, wieder zurückgesetzt.
Direkter Einsatz
Eine Aktionsabfrage lässt sich direkt ausführen, d. h., Sie geben dazu der Methode Execute() die in SQL formulierte Abfrage als Parameter mit. Es handelt
sich hierbei allerdings um eine Methode der Datenbank, nicht um die eines
QueryDef-Objektes.
Im folgenden Beispiel werden alle Datensätze gelöscht, für die die angegebene
Bedingung zutrifft.
Sub DirekteAktionsabfrage()
Dim db As DAO.Database
Set db = CurrentDb()
db.Execute( "DELETE * FROM tblCocktail WHERE CocktailNr > 1000;")
End Sub
Erweiterte Löschabfrage
Das nächste Beispiel führt eine Löschabfrage aus. Die Besonderheit der Subroutine liegt in der Verwendung einer benutzerdefinierten Eigenschaft. In dieser soll
abgelegt werden, wann die Löschabfrage zuletzt durchgeführt wurde. An die
352
Copyright
Daten, Texte, Design und Grafiken dieses eBooks, sowie die eventuell angebotenen
eBook-Zusatzdaten sind urheberrechtlich geschützt.
Dieses eBook stellen wir lediglich als Einzelplatz-Lizenz zur Verfügung!
Jede andere Verwendung dieses eBooks oder zugehöriger Materialien und
Informationen, einschliesslich der Reproduktion, der Weitergabe, des Weitervertriebs,
der Platzierung im Internet, in Intranets, in Extranets anderen Websites, der
Veränderung, des Weiterverkaufs und der Veröffentlichung bedarf der schriftlichen
Genehmigung des Verlags.
Bei Fragen zu diesem Thema wenden Sie sich bitte an:
mailto:[email protected]
Zusatzdaten
Möglicherweise liegt dem gedruckten Buch eine CD-ROM mit Zusatzdaten bei. Die
Zurverfügungstellung dieser Daten auf der Website ist eine freiwillige Leistung des
Verlags. Der Rechtsweg ist ausgeschlossen.
Hinweis
Dieses und andere eBooks können Sie rund um die Uhr
und legal auf unserer Website
(http://www.informit.de)
herunterladen
Herunterladen