Access & ADO: Recordset.Sort

Hallo!
Ich möchte ein Recordset sortieren, aber so (siehe Code) funktioniert das nicht: „Der aktuelle Provider unterstützt nicht die erforderliche Schnittstelle für die Sortier- bzw. Filterfunktion“ Ist es wirklich so, dass Access das nicht beherscht?

Nachstehender Code steht im Modul eines Formulars. „Kunden“ ist eine gelinkte Tabelle aus einer anderen Access-DB.

Private Sub fldKunde_Exit(Cancel As Integer)
Dim rs As New ADODB.Recordset
rs.Open „Kunden“, CurrentProject.Connection, adOpenStatic, adLockReadOnly
rs.Sort = „Firma“

Danke für eure Hinweise…
Stefan

Hallo Stefan,

Ich möchte ein Recordset sortieren, aber so (siehe Code)
funktioniert das nicht:

das ist ja auch richtig, du erstellst mit diesem Code eine neue Verknüpfung auf die selbe Datenbank. Rekursive Verknüpfungen kann kein Datenbankprogramm.

Ist es wirklich so, dass Access das nicht beherscht?

du kannst in keinem Datenbankprogramm der Welt die selbe Tabelle zweimal einbinden.

versuche es mal so:

Private Sub fldKunde_Exit(Cancel As Integer)

Dim DB As Database
Dim rs As Recordset

Set DB = CurrentDb
Set rs = DB.OpenRecordset(„SELECT Kunden.Firma FROM KUNDEN ORDER BY KUNDEN.FIRMA;“)

Hallo Netwolf
Vielen Dank für deine Antwort! Ich hoffe ich kann dein Interesse noch einmal wecken: Ich bin nicht sicher ob du bemerkt hast, dass ich bislang ADO und nicht DAO verwende. Ich habe dafür einen trivialen Grund: Das Buch mit dem ich begonnen habe hat damit gearbeitet… Ist es unvernünftig oder sogar falsch ADO für Automatisierungsaufgaben in Accessdatenbanken zu verwenden?

Es funktioniert bislang eigentlich ganz gut: Ich habe ADO vorwiegend zum Ausführen von in Access definierten Abfragen und Aktionsabfragen mit Parametern verwendet.

das ist ja auch richtig, du erstellst mit diesem Code eine
neue Verknüpfung auf die selbe Datenbank. Rekursive
Verknüpfungen kann kein Datenbankprogramm.

Habe ich Dich richtig verstanden: Ich darf also nicht mehrere Cursor auf derselben Tabelle öffnen? Es funktioniert nämlich: Auslesen von Daten aus dem Recordset hat geklappt. Für DAO bin ich mit Dir einer Meinung: mit recordset.open „Firma“ würe das Recordset doppelt in die Recordsets-Auflistung aufgenommen, was natürlich Unsinn ist.

Deine Lösung mit dem SQL-String (Analog in ADO realisiert) funktioniert eigentlich ohne rs.sort - allerdings nur für ein bestimmtes Sortierkriterium. Möchte ich nachträglich nach einem anderen Kriterium sortiern, müsste ich entweder eine neue Abfrage machen oder aber rs.sort verwenden. Aber die Eigenschaft rs.sort lässt sich auch auf ein so geöffnetes Recordset nicht einstellen. Wieso nicht?

’ Lösung mit zwei mal rs.open
Private Sub fldKunde_Exit(Cancel As Integer)
Dim rs As New ADODB.Recordset
rs.Open „SELECT * FROM Kunden ORDER BY Kunden.Firma;“, CurrentProject.Connection, adOpenStatic, adLockReadOnly

[code …]
rs.close
rs.Open „SELECT * FROM Kunden ORDER BY Kunden.Firm_ID;“, CurrentProject.Connection, adOpenStatic, adLockReadOnly

[code …]

’ Lösung mit zwei mal rs.sort
Private Sub fldKunde_Exit(Cancel As Integer)
Dim rs As New ADODB.Recordset
rs.Open „SELECT * FROM Kunden“, CurrentProject.Connection, adOpenStatic, adLockReadOnly
rs.sort = „Firma“

[code …]
rs.sort = „Firm_ID“

[code …]

Hallo Stefan,

Ich bin nicht sicher ob du bemerkt hast, dass ich bislang ADO und nicht DAO verwende.

doch, das habe ich bemerkt :smile:

Ich habe dafür einen trivialen Grund: Das Buch mit dem ich
begonnen habe hat damit gearbeitet… Ist es unvernünftig oder
sogar falsch ADO für Automatisierungsaufgaben in
Accessdatenbanken zu verwenden?

DAO bzw. ADO sind Öffnungsmechanismen einer MDB (Datenbank)
Diese Mechanismen sind dann wichtig, wenn du per Programmiersprache auf eine MDB zugreifen willst, oder auf „fremde“ SQL-Datenbanken zugreifen willst.
Ich vermute mal du hast da ein VB-Buch?

Arbeitest du aber in Access, und hast z.B. eine Frontend- und Backenddatenbank kannst du es ignorieren. Arbeitest du nur mit einer MDB kannst du es generell ignorieren.
Leider schreibst du nicht, wie es bei dir aufgebaut ist :frowning:

Es funktioniert bislang eigentlich ganz gut: Ich habe ADO
vorwiegend zum Ausführen von in Access definierten Abfragen
und Aktionsabfragen mit Parametern verwendet.

überflüssig, wenn du unter Access arbeitest.

Habe ich Dich richtig verstanden: Ich darf also nicht mehrere
Cursor auf derselben Tabelle öffnen?

klar, auf ein TABELLE ja. Aber auf die gleiche DATENBANK mit Tabelle nicht, das wäre rekursiv.

Aber die Eigenschaft rs.sort lässt sich auch auf ein so geöffnetes
Recordset nicht einstellen. Wieso nicht?

’ Lösung mit zwei mal rs.open
Private Sub fldKunde_Exit(Cancel As Integer)
Dim rs As New ADODB.Recordset

hier dimensionierst du nur!!!

es fehlt:
SET rs As New ADODB.Recordset

außerdem bei ADO - Verknüpfungen wichtig:
rst.CursorLocation = adUseClient

siehe die Hilfe in Access:
Remarks
This property requires the CursorLocation property to be set to adUseClient. A temporary index will be created for each field specified in the Sort property if an index does not already exist.

The sort operation is efficient because data is not physically rearranged, but is simply accessed in the order specified by the index.

Setting the Sort property to an empty string will reset the rows to their original order and delete temporary indexes. Existing indexes will not be deleted.

rs.Open „SELECT * FROM Kunden ORDER BY Kunden.Firma;“,
CurrentProject.Connection, adOpenStatic, adLockReadOnly

[code …]
rs.close
rs.Open „SELECT * FROM Kunden ORDER BY Kunden.Firm_ID;“,
CurrentProject.Connection, adOpenStatic, adLockReadOnly

[code …]

’ Lösung mit zwei mal rs.sort
Private Sub fldKunde_Exit(Cancel As Integer)
Dim rs As New ADODB.Recordset
rs.Open „SELECT * FROM Kunden“, CurrentProject.Connection,
adOpenStatic, adLockReadOnly
rs.sort = „Firma“

[code …]
rs.sort = „Firm_ID“

[code …]

Grüße aus Essen
Wolfgang

Hallo Wolfgang
Du hast mir schon viel geholfen, Danke! Aber ich habe immer noch ein paar Fragen…

Ich vermute mal du hast da ein VB-Buch?

Es war ein VBA-Buch. Aber ein schlechtes wie ich schon mehrfach festgestellt habe… Ist ne weile her und ich habs glaube ich entsorgt.

Leider schreibst du nicht, wie es bei dir aufgebaut ist :frowning:

Es geht um eine Auftragsabwicklungssystem in Access. Ich habe zwei Backend-DB (Produktionsdaten und Stammdaten). Dazu mehere Frontend (Rechnungswesen, Lieferwesen, AVOR, etc.)

Es funktioniert bislang eigentlich ganz gut: Ich habe ADO
vorwiegend zum Ausführen von in Access definierten Abfragen
und Aktionsabfragen mit Parametern verwendet.

überflüssig, wenn du unter Access arbeitest.

Das hatte ich befürchtet… Ich habe einige Funktionen in folgender Form: Die Funktion ruft eine Abfrage oder Aktionsabfrage auf und übergibt ihr die erforderlichen Parameter, welche sie selbst als Parameter erhalten hat (neue Daten, Kriterien, etc.). Bei Abfragen gibt sie den gesuchten Wert zurück. Als Beispiel eine simple Abfrage:

Public Function existsBestNr(BestNr As String, firmid As String) As 
Integer
 Dim rs As New ADODB.Recordset
 Set cmd = cat.Procedures("abfExistsBestNr").Command
 cmd.Parameters("BestNr") = BestNr
 cmd.Parameters("FirmId") = firmid
 rs.Open cmd, , adOpenDynamic, adLockPessimistic
 If Not (rs.EOF And rs.BOF) Then
 rs.MoveFirst
 existsBestNr = rs("anzahl")
 Else
 existsBestNr = 0
 End If
 rs.Close
End Function

Wie mache ich das ähnlich flexibel (ich möchte die Aktionsabfrage mit Parametern realisieren und nicht die Werte direkt aus den Formularfeldern abfragen) aber ohne ADO/DAO?

Abschliessend zum .Sort Problem:

> > ' Lösung mit zwei mal rs.open  
> > Private Sub fldKunde\_Exit(Cancel As Integer)  
> > Dim rs As New ADODB.Recordset

hier dimensionierst du nur!!!

es fehlt:
SET rs As New ADODB.Recordset

Hm… Du meinst wohl

Dim rs As ADODB.Recordset
SET rs = New ADODB.Recordset

Ist das nicht Äquivalent zu

Dim rs As New ADODB.Recordset

?

außerdem bei ADO - Verknüpfungen wichtig:
rst.CursorLocation = adUseClient

Ja, das hat gefehlt! DANKE!

Grüsse aus Bern
Stefan

Hallo Stefan,

diese Funktion:

Public Function existsBestNr(BestNr As String, firmid As
String) As
Integer
Dim rs As New ADODB.Recordset
Set cmd = cat.Procedures(„abfExistsBestNr“).Command
cmd.Parameters(„BestNr“) = BestNr
cmd.Parameters(„FirmId“) = firmid
rs.Open cmd, , adOpenDynamic, adLockPessimistic
If Not (rs.EOF And rs.BOF) Then
rs.MoveFirst
existsBestNr = rs(„anzahl“)
Else
existsBestNr = 0
End If
rs.Close
End Function

kannst du einfach mit der VBA Funktion DLOOKUP erledigen.

Public Function existsBestNr(xBestNr As String, xfirmid As String)

existsBestNr = iif(val((DLookup(„BestNr“, „Tabelle“, "[BestNr] = " & xBestNr & " and [FirmID]= " & xFirmID))> 0, TRUE, FALSE)

end Function

Das x vor den Variablen vermeidet Missverständnisse mit Tabellenfeldern. Die Rückgabe wäre dann TRUE oder False.

Abschliessend zum .Sort Problem:

’ Lösung mit zwei mal rs.open
Private Sub fldKunde_Exit(Cancel As Integer)
Dim rs As New ADODB.Recordset

hier dimensionierst du nur!!!

es fehlt:
SET rs As New ADODB.Recordset

Hm… Du meinst wohl

Dim rs As ADODB.Recordset
SET rs = New ADODB.Recordset

ja, richtig

Ist das nicht Äquivalent zu

Dim rs As New ADODB.Recordset

?

nein, eben nicht

Grüße aus Essen
Wolfgang

Hallo Wolfgang
Ich habe mich noch ein wenig in die Thematik eingelesen,

Public Function existsBestNr(xBestNr As String, xfirmid As
String)

existsBestNr = iif(val((DLookup(„BestNr“, „Tabelle“, "[BestNr]
= " & xBestNr & " and [FirmID]= " & xFirmID))> 0, TRUE,
FALSE)

end Function

und komme zum Schluss, dass es für Abfragen wesentlich einfachere Wege gibt (Wie deinen). Für Aktionsabfragen die Parameter verwenden scheint ADO/DAO aber schon das geeignete Mittel zu sein, selbst wenn ich nur Access verwende.

Private Sub fldKunde_Exit(Cancel As Integer)
Dim rs As New ADODB.Recordset

hier dimensionierst du nur!!!

es fehlt:

Dim rs As ADODB.Recordset
SET rs = New ADODB.Recordset

Ist das nicht Äquivalent zu

Dim rs As New ADODB.Recordset

?

nein, eben nicht

Nun scheinbar Doch. Siehe VBA-Hilfe zum Thema Dim:
Wenn Sie New bei der Deklaration der Objektvariablen verwenden, wird eine neue Instanz des Objekts aufgrund des ersten Verweis darauf erstellt, so daß Sie die Set-Anweisung für die Zuweisung des Objektverweises nicht verwenden müssen.

Gruss und Danke aus Bern
Stefan

Hallo Stefan,

und komme zum Schluss, dass es für Abfragen wesentlich
einfachere Wege gibt (Wie deinen).

ja, das stimmt

Für Aktionsabfragen die
Parameter verwenden scheint ADO/DAO aber schon das geeignete
Mittel zu sein, selbst wenn ich nur Access verwende.

ADO/DAO benötigst du nur, wenn du eine externe MDB mit den Tabellen nutzen willst.

Hast du ein Frontend / Backend Programm (was immer sinnvoll ist), gehst du im Frontend auf Datei / externe Daten / Tabellen verknüpfen. Somit sind die externen Tabellen aus externen Datenbanken verknüpft. D.h. ab dann benötigst du kein ADO/DAO mehr, weil alles schon mit dem Frontend verbunden ist.

Nun scheinbar Doch. Siehe VBA-Hilfe zum Thema Dim:
Wenn Sie New bei der Deklaration der
Objektvariablen verwenden, wird eine neue Instanz des Objekts
aufgrund des ersten Verweis darauf erstellt, so daß Sie die
Set-Anweisung für die Zuweisung des Objektverweises nicht
verwenden müssen.

stimmt, das hatte ich übersehen, „alte“ Programmiertechniken sind schwer loszuwerden :smile:

Grüße aus Essen
Wolfgang