Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

Leeres Recordset erstellen mittels DAO

Begonnen von datekk, Juli 17, 2016, 15:36:38

⏪ vorheriges - nächstes ⏩

datekk

Hi,

ich kann mittels ADO per Code (Set rs = New ADODB.Recordset) einen leeren Recordset erstellen und darin mittels rs.fields.append neue Felder bzw. Spalten anlegen.

Wie funktioniert dies mit DAO?
Access 2016 mit SQL Server Backend. Bereits umgesetzt: Access mit MS SQL Backend,  ADODB Formularbindung, Streamen von Dateien zum SQL Server und zurück (Filestream), Drag&Drop Dateiupload zum Server, CTI / TAPI Integrierung in Access Anwendung - Nutzung auch über Remote Desktop, selbst aktualisierendes Access Frontend auf entfernten Rechnern (Upgrade). Berichte / Kreuztabellen mit SQL Server Backend, Mail Tagging, Outlook Steuerung über Access und umgekehrt // Grundwissen in .Net Core & Blazor Apps

Lachtaube

In DAO funktioniert das so nicht. DAO-Recordsets können nur über die Methode OpenRecordset eines Datenbank-Objekts erzeugt werden. Durch Angabe des Options-Arguments dbAppendOnly könnte man ein Recordsetset vom Typ Dynaset erstellen, das anfänglich keine Datensätze enthält. Das gleiche könnte man erzielen durch die Angabe einer Bedingung in Where-Klausel einer Abfrage, die als Resultat Falsch (False) liefert. SELECT ... WHERE 0;
Grüße von der (⌒▽⌒)

markusxy

in DAO musst du den Umweg über eine Tabelle gehen.
Also per VBA eine Tabelle erstellen, Recordset auf Basis der Tabelle öffnen.

Zu welchem Zweck möchtest du das machen?
LG Markus

datekk

#3
Ok danke erstmal. Ich habe mal weiter mit ADODB experimentiert.. Ich muss sagen, dass Recordsets was ganz neues für mich sind. Im Grunde möchte ich eine Tabelle in eine Variable übergeben, dort in der Variablen eine Spalte zufügen, den dann erstellten Recordset an ein Form übergeben. Hier Daten ändern, Recordset nach geänderten Daten durchsuchen und die Daten dann in die Tabelle schreiben.

Ich bin schon so weit:


Option Compare Database
Option Explicit
Dim rs As ADODB.Recordset

Private Sub Form_Load()

    Dim conn As ADODB.Connection
    Dim sql As String

    Set conn = CurrentProject.Connection
    Set rs = New ADODB.Recordset
    sql = "SELECT * FROM Tabelle ORDER BY ID"

    With rs
   
        Set .ActiveConnection = conn
        .Source = sql
        .LockType = adLockOptimistic
        .CursorLocation = adUseClient
        .CursorType = adOpenKeyset
     
    End With
   
    With rs.Fields
        .Append "YesNo", adBoolean
    End With
   
    rs.Open
   
    Set Me.Recordset = rs
    Me.chk1.ControlSource = "YesNo"
   
End Sub



Im Formular wird mir nun alles angezeigt. Leider kann ich dort im aber nix bearbeiten. Ich erhalte immer den Hinweis, dass das Formular schreibgeschützt ist...
Access 2016 mit SQL Server Backend. Bereits umgesetzt: Access mit MS SQL Backend,  ADODB Formularbindung, Streamen von Dateien zum SQL Server und zurück (Filestream), Drag&Drop Dateiupload zum Server, CTI / TAPI Integrierung in Access Anwendung - Nutzung auch über Remote Desktop, selbst aktualisierendes Access Frontend auf entfernten Rechnern (Upgrade). Berichte / Kreuztabellen mit SQL Server Backend, Mail Tagging, Outlook Steuerung über Access und umgekehrt // Grundwissen in .Net Core & Blazor Apps

markusxy

#4
Also dir fehlt noch etwas das Grundverständis zu ADO.

Schau dir mal diesen Artikel an:
https://activevb.de/tutorials/tut_adokurs/adokurs.html

Eines der Probleme bei ADO ist, dass man viele Angaben machen kann und ohne Fehlermeldung werden deine Angaben nicht umgesetzt. Nach dem Motte ich mach was geht.


z.B diese Kombi ist nicht möglich.
        .CursorLocation = adUseClient
        .CursorType = adOpenKeyset

Entweder weißt du nicht was ein Keyset ist, oder du weißt nicht was die CursorLocation bedeutet.

Felder zur Laufzeit anfügen funktioniert so auch nicht.
Um das zu erreichen gibt es drei Möglichkeiten, wenn man die Daten bearbeiten möchte:

alle Felder selbst erstellen.
Daten mittels Shape Provider abrufen und gleichzeitig Felder anfügen.
Die dritte Möglichkeit lasse ich mal weg, da sie nirgends dokumentiert ist.

Da solltest du mal die VBA Hilfe zu ADO ansehen.
Das Problem dabei. DAO kann ca. 20% von dem was ADO kann und ca 1% von dem was Ado.net kann.
Das führt dann auch zu mehr Komplexität und man muss im Gegensatz zu DAO mehr Verständnis mitbringen. Also lies dich etwas ein.
Von dem was ich neu Programmiere mache ich 80% in ADO und kenne mittlerweile die Vorteile und Tücken.

LG Markus

Edit:
man kann ein Feld natürlich auch per SQL Anweisung einbinden, so wie ein berechnetes Feld bei DAO.
Das lässt sich dann aber nur "offline bearbeiten".

Wurliwurm

Zitat von: datekk am Juli 17, 2016, 16:36:13
Im Grunde möchte ich eine Tabelle in eine Variable übergeben, dort in der Variablen eine Spalte zufügen, den dann erstellten Recordset an ein Form übergeben. Hier Daten ändern, Recordset nach geänderten Daten durchsuchen und die Daten dann in die Tabelle schreiben.

So weit ich mich erinnere, stammt das von mir, hab ich doch vor einiger Zeit mal ein kleines Beispiel dazu hier gepostet, was iirc auch funktioniert hat.

Ich verwende gerne ungebundene Recordsets als tabellenartige Datenstruktur, die nicht an ein SQL gebunden ist.

Solange Du noch nicht rs.open gesagt hast, kennt das Recordset die Felder aus dem SQL noch nicht, und nach dem rs.open kann man so weit ich weiß keine Felder mehr hinzufügen.

Jedenfalls wenn Du mit ADO einmal gut zurecht kommst (man braucht nicht allen Schnick-Schnack), bist Du nicht mehr auf DAO angewiesen.

Wurliwurm

Hier nochmal mein Beispiel. Das ist mit manuellem Erzeugen der Felder, solide Handarbeit, die aber immer funktioniert. Ich würde mir auch angewöhnen, die Erzeugung der Recordsets nicht in der Form_Load Methode direkt zu schreiben, sondern in einem Modul. Dann kannst Du die Recordsets leichter austauschen und testen, ohne immer ein Formular offen zu haben.

markusxy

@Wurliwurm
du erstellst ein ungebundenes Recordset und kopierst die Daten hinein. Das ist unnötig.
Mit einem einfachen Select auf die Tabelle und der Einbindung des zusätzlichen Feldes über die Select Anweisung erreichst du das gleiche - nur halt performant.

Wie ich bereits im letzten Kommentar erwähnt habe, sind auch Deine Angaben zum Öffnen des Recordsets unstimmig, und zeigen ein mangelndes Verständnis zu ADO.
Schau einfach mal deinen Code an und was von den Anweisungen nicht umgesetzt wird da die Kombinationen nicht möglich sind.
Ich würde dir auch empfehlen die Info zu ADO in der VBA Hilfe anzusehen.

LG Markus

Wurliwurm

Zitat von: markus888 am Juli 18, 2016, 13:06:40
Mit einem einfachen Select auf die Tabelle und der Einbindung des zusätzlichen Feldes über die Select Anweisung erreichst du das gleiche - nur halt performant.

Dafür kann man das Recordset dann frei aufbauen, und ändern etc. Es ist eine freie Datenstruktur und hat nicht die Grenzen einer SQL-Abfrage.

Zitat
Wie ich bereits im letzten Kommentar erwähnt habe, sind auch Deine Angaben zum Öffnen des Recordsets unstimmig, und zeigen ein mangelndes Verständnis zu ADO.
Schau einfach mal deinen Code an und was von den Anweisungen nicht umgesetzt wird da die Kombinationen nicht möglich sind.

Ich hoffe, daß das den Threadstarter jetzt nicht erschlägt.
Das weiß ich, daß ein Cursor bei einem lokalem Recordset nicht einschlägig ist. Meine Deklarationen sind teilweise i.d.T. überflüssig und "misleading". Allgemein bin ich aber schon vom Fach und habe sogar ein Buch nur über ADO. :-)

datekk

#9
Hallo Wurliwurm :) Das hast Du gleich richtig erkannt, dass ich an Deinem Code arbeite. Mittlerweile hab ich es geschafft die Hilfstabelle als Recordset aufzubauen und das Formular daran zu binden. 8) Es ist auch wieder in Module aufgeteilt... Nur wenn ich mich an etwas ranarbeite, dann mach ich das lieber erstmal in einer einzig Sub, um nicht ständig hin und her schalten zu müssen und um den Code zu verstehen.

Zuerst dachte ich DAO wäre fortschrittlicher. Nun habe ich das aber auf Basis von ADO erfolgreich abgewickelt. Ich erstelle zuerst ein Recordset über die Select Anbindung, dann erstelle ich ein ungebundenes Recordset und kopiere dort alles rein.

Mein Code geht Spalte für Spalte durch und kopiert den Aufbau und die Daten. Die Spalten lege ich so an:


    Dim i As Integer
   
    i = Originaltabelle.Fields.Count
       
    ' Tabellenspalten in Hilfstabelle übernehmen

    For i = 0 To i - 1
       
        Hilfstabelle.Fields.Append Originaltabelle.Fields(i).Name, adChar, 200
               
       
    Next


Wie man sieht, werden alle Felder als Textfelder eingefügt. Wie kann ich denn aus der Originaltabelle (es ist keine Tabelle sondern bereits ein eigenes RS) den Datentyp auslesen und ebenfalls beim erstellen der Hilfstabelle (auch ein RS) per Code übergeben?
Access 2016 mit SQL Server Backend. Bereits umgesetzt: Access mit MS SQL Backend,  ADODB Formularbindung, Streamen von Dateien zum SQL Server und zurück (Filestream), Drag&Drop Dateiupload zum Server, CTI / TAPI Integrierung in Access Anwendung - Nutzung auch über Remote Desktop, selbst aktualisierendes Access Frontend auf entfernten Rechnern (Upgrade). Berichte / Kreuztabellen mit SQL Server Backend, Mail Tagging, Outlook Steuerung über Access und umgekehrt // Grundwissen in .Net Core & Blazor Apps

Wurliwurm

In meinem Beispiel habe ich eine Routine erstellt, die aus einem SQL-gebundenen Recordset ein leeres ungebundenes Recordset aufbaut. Es werden die Spalten des Recordsets abgefragt und die Felder an das ungebundene Recordset angefügt:

Private Function erzeugeUngebundenesRecordset(ByRef rsOriginal As ADODB.Recordset) As ADODB.Recordset
   
    Dim i As Integer
    Dim rsUngebunden As ADODB.Recordset
    Set rsUngebunden = New ADODB.Recordset
   
    With rsUngebunden
      .CursorLocation = adUseClient
     '.CursorType = adOpenKeyset 'überflüssig
      .LockType = adLockOptimistic
    End With

    With rsUngebunden.Fields
        For i = 0 To rsOriginal.Fields.Count - 1
            If rsOriginal.Fields(i).Type < 202 Then
              .Append rsOriginal.Fields(i).Name, rsOriginal.Fields(i).Type
            Else  'Textfeld, braucht zusätzich die Länge
              .Append rsOriginal.Fields(i).Name, rsOriginal.Fields(i).Type, rsOriginal.Fields(i).DefinedSize
            End If
        Next i
    End With
   
    Set erzeugeUngebundenesRecordset = rsUngebunden

End Function


Es wird so aufgerufen:
String sql = "SELECT * FROM tblBeispiel ORDER BY Id"

rsO.Open sql, conn, adOpenForwardOnly, adLockReadOnly

Dim rsU As ADODB.Recordset
Set rsU = erzeugeUngebundenesRecordset(rsO)