PDA

Vollständige Version anzeigen : Access > Excel, aber wie wenn 1:n Beziehung


schnolli
25.09.2003, 19:59
Hallo,

habe hier im Forum diesen Code gefunden, der Daten von Access nach Excel übergibt, funktioniert soweit auch ganz gut.
Dim ExApp As Excel.Application
Dim wb As Excel.Workbook
Dim ws As Excel.Worksheet
Set ExApp = CreateObject("Excel.Application")
ExApp.Workbooks.Open "C:\Dokumente und Einstellungen\Oliver\Desktop\Access.xls"
ExApp.Visible = True
'oder, falls neue Mappe gewünscht:
'ExApp.Workbooks.Add
Set wb = ExApp.ActiveWorkbook
'Set ws = wb.Worksheets("MeinBlatt")
Set ws = wb.ActiveSheet
With ws
.Cells(1) = Nachname
.Cells(2) = Vorname
.Cells(3) = Straße
.Cells(4) = PLZ
.Cells(5) = Ort
'wb.Save
Set ws = Nothing
Set wb = Nothing
Set ExApp = Nothing
End With
Es gibt zwei Tabellen die eine 1:n Beziehung haben, in meinem Haupt_frm ist ein UFO eingebunden, in diesem UFO stehen die Verträge zum Kunden, jeder Kunde hat also eine Verschiedene Anzahl von Verträgen.

Wie müsste den der Code ergänzt werden, dass Access weiss, dass auch die dazugehörigen Verträge (Felder: VS-Nummer, Vertragsart, Gesellschaft, Beginn, Ablauf, JBP, untereinander in die Zellen übergeben werden sollen?

Habe leider nichts zu einem ähnlichem Problem hier im Forum gefunden.

MarioR
26.09.2003, 07:00
Hallo,

ich vermute mal "Nachname", "Vorname" usw. sind Formularfelder aus dem HF, oder? Ich würde an Deiner Stelle nicht die Formularfelder auslesen, sondern ein Recordset öffnen, dort DS für DS durchgehen und die Daten dabei nach Excel schreiben. Das könnte ungefähr so aussehen:

...
Dim ws As Excel.Worksheet
Dim rs As DAO.Recordset
Dim strSQL As String
strSQL = "SELECT Tabelle1.*, Tabelle2.* FROM Tabelle1 INNER JOIN Tabelle2 " & _
"ON Tabelle1.KundenNr = Tabelle2.KundenNr WHERE ID = " & Me.Formularfeld_ID
Set rs = CurrentDb.OpenRecordset(strSQL, DAO.dbOpenForwardOnly)
If Not rs.EOF Then
Set ExApp = CreateObject("Excel.Application")
...
Set ws = wb.ActiveSheet
With ws
.Cells(1) = rs!Nachname
.Cells(2) = rs!Vorname
.Cells(3) = rs!Straße
.Cells(4) = rs!PLZ
.Cells(5) = rs!Ort
Do While Not rs.EOF
.Cells(x) = rs!VS-Nummer
.Cells(y) = rs!Vertragsart
...
rs.MoveNext
Loop
End With
Set ws = Nothing
Set wb = Nothing
Set ExApp = Nothing
End If
rs.Close
Set rs = Nothing

"Tabelle1" und "Tabelle2" musst Du durch die richtigen Namen ersetzen.
"KundenNr" ist das Verknüpfungsfeld zwischen beiden Tabellen und muss ebenfalls durch die richtige(n) Bezeichnung(en) ersetzt werden.
Mit WHERE ID = " & Me.Formularfeld_ID im SQL-Code wird die Auswahl im Recordset auf den Kunden begrenzt, der momentan im HF dargestellt wird. "ID" wäre dabei ein eindeutiges Feld in Tabelle1 vom Typ Zahl (gewöhnlich ein Autowert-Feld) und "Formularfeld_ID" das zugehörige Formularfeld. Die Bezeichnungen musst Du wieder anpassen.
In .Cells(x) usw. werden dann die Daten aus Tabelle2 geschrieben. Das musst Du natürlich auch noch anpassen, damit nicht jeder DS aus Tabelle2 immer wieder in die gleichen Zellen geschrieben wird

HTH

schnolli
26.09.2003, 08:40
Hallo,

erstmal danke für deine Antwort. Habe nun mal versucht deinen Code anzupassen, funzt aber nicht, bekomme die Fehlermeldung Laufzeitfehler '3131' Syntaxfehler in FROM-Klausel.

Dim ws As Excel.Worksheet
Dim rs As DAO.Recordset
Dim strSQL As String
strSQL = "SELECT tblKunden.*, tblVerträge zum Kunden.* FROM tblKunden INNER JOIN tblVerträge zum Kunden " & _
"ON tblKunden.Kundennummer = tblVerträge zum Kunden.Kundennummer WHERE Kundennummer = " & Me.Kundennummer
Set rs = CurrentDb.OpenRecordset(strSQL, DAO.dbOpenForwardOnly)
If Not rs.EOF Then
Set ExApp = CreateObject("Excel.Application")
ExApp.Workbooks.Open "C:\Dokumente und Einstellungen\Oliver\Desktop\Access.xls"
ExApp.Visible = True
Set wb = ExApp.ActiveWorkbook
Set ws = wb.ActiveSheet
With ws
.Cells(1) = Nachname
.Cells(2) = Vorname
.Cells(3) = Straße
.Cells(4) = PLZ
.Cells(5) = Ort
Do While Not rs.EOF
.Cells(6, 1) = VS - Nummer
.Cells(6, 2) = Vertragsart
.Cells(6, 3) = Gesellschaft
.Cells(6, 4) = Beginn
.Cells(6, 5) = Ablauf
.Cells(6, 6) = JBP
rs.MoveNext
Loop
End With
Set ws = Nothing
Set wb = Nothing
Set ExApp = Nothing
End If
rs.Close

Wenn ich dann den Debugger starte unterstreicht er mir diese Zeile gelb.
Set rs = CurrentDb.OpenRecordset(strSQL, DAO.dbOpenForwardOnly)

Was habe ich falsch gemacht :confused:

MarioR
26.09.2003, 08:51
Bezeichnungen mit Leer- und Sonderzeichen müssen immer geklammert werden.
... [tblVerträge zum Kunden] " & _

Weiterhin muss der Bezug auf das Feld "Kundennummer" eindeutig sein. Sollte es vom Typ Text ist, dann müssen da übrigens noch Hochkommas rundrum (hab ich vorhin vergessen zu erwähnen).
Also bei Zahl:
... WHERE tblKunden.Kundennummer = " & Me.Kundennummer
Oder bei Text:
... WHERE tblKunden.Kundennummer = '" & Me.Kundennummer & "'"

Weiter unten fehlt auch der Bezug auf das Recordset. Also bei Nachname, Vorname usw. immer ein rs! davor:
.Cells(1) = rs!Nachname

Lothi
26.09.2003, 08:58
Hallo Schnolli

strSQL = "SELECT tblKunden.*, tblVerträge zum Kunden.* FROM tblKunden INNER JOIN tblVerträge zum Kunden " & _
"ON tblKunden.Kundennummer = tblVerträge zum Kunden.Kundennummer WHERE Kundennummer = " & Me.Kundennummer

Bei Feld oder Tabellennamen mit Sonder- oder Leerzeichen musst du den Namen in Eckige klammern setzten: [tblVerträge zum Kunden]

Beim rest vom Code sieh noch mal den Code von Mario an
das rs! Feldname fehlt.

und wie Mario schon sagte wird dir so wie du es jetzt hast der nächste datensatz in die gleiche Zelle geschrieben wie der vorhergehende. Du musst bei jedem Schleifendurchgang den Zeilenwert um 1 erhöhen.

Zuspät aber wenigsten das gleiche wie Mario :D

schnolli
26.09.2003, 09:45
Es ist doch zum verzweifeln :bawling:, habe nun die Tabellen in Klammern gesetzt, aber es funktioniert immer noch nicht. Bekomme nun den Laufzeitfehler '3075' fehlender Operator. Wenn einer von euch mal meinen Code anschauen könnte und mir sagen könnte was falsch ist, wäre das sehr nett.

MarioR
26.09.2003, 09:59
Ich hab hier kein A2k, muss jetzt aber auch weg.

Vielleicht kann sich Jemand der Sache mal annehmen ... :rolleyes:

schnolli
26.09.2003, 10:03
Ups, sorry, habe vergessen die DB zu konvertieren. Hier nun Access97 Format.

Lothi
26.09.2003, 10:14
Hallo Schnolli

Hier die der funktionierende SQL Code
strSQL = "SELECT tblKunden.*, [tblVerträge zum Kunden].*, tblKunden.Kundennummer " & _
"FROM tblKunden " & _
"INNER JOIN [tblVerträge zum Kunden] " & _
"ON tblKunden.Kundennummer = [tblVerträge zum Kunden].Kundennummer " & _
"WHERE tblKunden.Kundennummer = " & Me.Kundennummer

Einde andere frage:

Du willst jetzt die zuerst die Namen in die Exeltabelle schreiben und dann unterhalb zu jedem dazugehörigen Name die verträge?

Beispiel:
Name Vorname
1
2
3
Name Vorname
1
2

Wenn ja funktioniert dein aufbau des Codes nicht weil alle Datensätze in einer zeile dargestellt werd.

schnolli
26.09.2003, 10:54
Hallo Lothi,
Original geschrieben von Lothi
Du willst jetzt die zuerst die Namen in die Exeltabelle schreiben und dann unterhalb zu jedem dazugehörigen Name die verträge?
Jepp, es soll zuerst der Name+Adresse in Zellen geschrieben werden, dann Zeilen darunter sollen dann die Verträge aufgelistet werden, so das ich eine komplette übersicht des Kunden habe.

Lothi
26.09.2003, 11:07
Hallo

Da hab ich etwas gebastelt in der zwischenzeit

Private Sub Befehl170_Click()
Dim ws As Excel.Worksheet
Dim rs As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim strSQL As String
Dim strSQL2 As String
Dim i As Integer
strSQL = "SELECT tblKunden.*" & _
"FROM tblKunden " & _
"WHERE Kundennummer = " & Me.Kundennummer

strSQL2 = "SELECT [tblVerträge zum Kunden].* " & _
"FROM [tblVerträge zum Kunden] " & _
"WHERE Kundennummer = " & Me.Kundennummer

Debug.Print strSQL

Set rs = CurrentDb.OpenRecordset(strSQL, DAO.dbOpenForwardOnly)
Set rs2 = CurrentDb.OpenRecordset(strSQL2, DAO.dbOpenForwardOnly)
If Not rs.EOF Then
Set ExApp = CreateObject("Excel.Application")
ExApp.Workbooks.Open "C:\Dokumente und Einstellungen\Oliver\Desktop\Access.xls"
ExApp.Visible = True
Set wb = ExApp.ActiveWorkbook
Set ws = wb.ActiveSheet
With ws
.Cells(1) = rs!Nachname
.Cells(2) = rs!Vorname
.Cells(3) = rs!Straße
.Cells(4) = rs!PLZ
.Cells(5) = rs!Ort
End With
With ws
Do While Not rs2.EOF
.Cells(1, 5 + i) = rs2![VS-Nummer]
.Cells(2, 5 + i) = rs2!Vertragsart
.Cells(3, 5 + i) = rs2!Gesellschaft
.Cells(4, 5 + i) = rs2!Beginn
.Cells(5, 5 + i) = rs2!Ablauf
.Cells(6, 5 + i) = rs2!JBP
rs2.MoveNext
i = i + 1
Loop
End With
Set ws = Nothing
Set wb = Nothing
Set ExApp = Nothing
End If
rs.Close
rs2.Close
End Sub

schnolli
26.09.2003, 11:25
Juhuuu, :D

echt klasse von Dir, funzt einwandfrei. Könntest Du mir noch bitte erklären was das + i im Code heisst.
.Cells(1, 5 + i) = rs2![VS-Nummer]
.Cells(2, 5 + i) = rs2!Vertragsart
.Cells(3, 5 + i) = rs2!Gesellschaft
.Cells(4, 5 + i) = rs2!Beginn
.Cells(5, 5 + i) = rs2!Ablauf
.Cells(6, 5 + i) = rs2!JBP

Merci.

Lothi
26.09.2003, 11:38
Hallo

Ja kann ich

Mit der Schleife

Do While Not rs2.EOF
.Cells(1, 5 + i) = rs2![VS-Nummer]
.Cells(2, 5 + i) = rs2!Vertragsart
.Cells(3, 5 + i) = rs2!Gesellschaft
.Cells(4, 5 + i) = rs2!Beginn
.Cells(5, 5 + i) = rs2!Ablauf
.Cells(6, 5 + i) = rs2!JBP
rs2.MoveNext
i = i + 1
Loop

rs2 liest den ersten Datensatz ein. Wenn der erste datensatz in die geschrieben wurde wird die Variable i um 1 erhöht das wird dann der Spalte hinzugezählt so kommt als nächstes die Spalte 6 dann 7 u.s.w
Sonst wird jeder Datensatz in die gleiche Spalte geschrieben.

schnolli
26.09.2003, 11:49
Hallo,

danke für Deine Erklärung. :hands:

Da jetzt alles soweit läuft wie ich es möchte :dance:, kann ich beruhigt in die Pause gehen.

Und nochmals Merci.

Mahlzeit. :mrcool: