Anzeige
Archiv - Navigation
1728to1732
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

lange Datensätze aus Excel in Access übertragen

lange Datensätze aus Excel in Access übertragen
11.12.2019 06:24:06
Klaus
Hallo Forum,
mit diesem Makro übertrage ich Datensätze in eine Access Datenbank:
Option Explicit
'Verweis auf Microsoft ActiveX Data Objects 2.5 Library  !
Const pfad As String = "C:\Herber\Access"        'Access DB PFad
Const myAccessDB As String = "Datenbank.accdb"   'Access DB Dateiname
Const myDB As String = "ScanArchiv"              'DB-Tabellenname im Access
Const myTable As String = "Tabelle2"             'in diese Tabelle
Sub Station_Aktualisieren(myRow As Long)
On Error GoTo hell
Const APPNAME = "mod_Access / Station_Aktualisieren"
Dim crm As Long
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Dim ws As Worksheet
Set ws = Sheets(myTable)
Set con = New ADODB.Connection
con.Open ConnectionString:= _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & pfad & "\" & myAccessDB & ";" & _
"Mode=Share Exclusive"
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseServer
rs.Open Source:=myDB, _
ActiveConnection:=con, _
CursorType:=adOpenStatic, _
LockType:=adLockPessimistic, _
Options:=adCmdTableDirect
rs.Index = "PrimaryKey"
crm = ws.Cells(myRow, 1).Value
rs.Seek KeyValues:=crm, SeekOption:=adSeekFirstEQ
If rs.EOF Then
rs.AddNew
rs!crm = crm
End If
rs!Model = ws.Cells(myRow, 2)
rs!ProductRange = ws.Cells(myRow, 3)
rs!RepairArticle = ws.Cells(myRow, 4)
rs!ProductClass = ws.Cells(myRow, 5)
rs.Update
'*** Fehlerbehandlung
Err.Clear
hell:
If Err.Number = -2147467259 Then Resume     'Datenbank wird bereits verwendet
If Err.Number  0 Then MsgBox "Fehler in Sub """ & APPNAME & """" & vbCrLf _
& "Fehlernummer: " & Err.Number & vbLf & Err.Description
rs.Close
Set rs = Nothing
con.Close
Set con = Nothing
End Sub
Das geht auch recht gut, aber das repetive Schreiben der Tabellenköpfe nervt mich:
rs!Model = ws.Cells(myRow, 2)
rs!ProductRange = ws.Cells(myRow, 3)
rs!RepairArticle = ws.Cells(myRow, 4)
rs!ProductClass = ws.Cells(myRow, 5)

Für 5-10 Spalten ist das ja gut machbar, aber was ist wenn ich 50 oder 500 Spalten übertragen will? Dann tippe ich mich ja tot!
Was ich möchte, sähe in Pseudocude so aus:
For i = 2 To 500
rs!Überschrift(i) = ws.Cells(myRow, i)
Next i

Wer kann mir helfen, dafür den richtigen Code zu finden?
LG,
Klaus M.

12
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: lange Datensätze aus Excel in Access übertragen
11.12.2019 08:30:38
ChrisL
Hi Klaus (wieder einmal ;)
Anstelle der Schreibweise rs!Feldname kannst du auch rs.Fields("Feldname") verwenden.
Wenn du die Feldnamen z.B. in Zeile 1 (oder in ein Arrray, Hilfstabelle etc.) schreibst, dann solltest du eine Schleife verwenden können.
beispielhaft:
For i = 1 To 500
rs.Fields(Cells(1, i)) = Cells(myRow, i)
Next i
Alternativ kannst du dir einen SQL-Textstring per Schleife zusammenstellen. Bei 500 Datenfelder könnte der String allerdings (zu) lang und unübersichtlich werden. Zudem erfordert es eine Typenkonvertierung in Text d.h. z.B. WAHR/FALSCH müsste als String verwendet in der richtigen Sprache sein, Decimaltrennzeichen, Datumsformate etc. beachten.
cu
Chris
Anzeige
AW: lange Datensätze
11.12.2019 09:57:01
Klaus
Super, danke Chris!
AW: lange Datensätze aus Excel in Access übertragen
11.12.2019 11:42:53
volti
Hallo Klaus,
neben dem gangbaren Weg gezeigt durch Chris hier noch ein Tipp, wie Du aus einer Exceldatei den gesamten (Teil)Inhalt einer Exceltabelle in einem Rutsch einlesen könntest, falls das in diesem Fall bei Dir zutrifft.
Hier ein Beispiel der möglichen Vorgehensweise. Vielleicht bringt Dich das ja weiter...
Sub ImportExcelToAccess()
'Einlesen eines Datenbereiches einer Exceldatei in ACCESS (Beispiel, ungetestet)
 Set accApp = CreateObject("ACCESS.Application")
 accApp.Visible = True
 Call accApp.OpenCurrentDatabase(MeineMDB, False, "MeinPasswort")   'Datenbank öffnen, Passwort ist optional
 Set accDB = accApp.CurrentDb
 'Die 10 kann auch wegelassen werden, das ist der AcSpreadSheetType 10=Excel10 ff, ggf. auch 9 nehmen
 accApp.DoCmd.TransferSpreadsheet acImport, 10, MeineTabelle, MeineQuelldatei, True, "MeinBlattname!A5:IU" 'acImport=0
 accApp.DoCmd.CloseDatabase
 accApp.Quit
 Set accDB = Nothing
 Set accApp = Nothing
End Sub

viele Grüße
Karl-Heinz

Anzeige
AW: lange Datensätze
11.12.2019 13:56:28
Klaus
Hallo Karl-Heinz,
steigt schon in der ersten Zeile aus:
Set accApp = CreateObject("ACCESS.Application")
accApp - Variable nicht definiert.
Wenn ich Option Explicit auskommentiere (was ich eigentlich nur ungern tue), öffnet es mir eine Access-Anwendung. Als was müsste ich accApp denn sauber deklarieren, und sag bitte nicht variant?
Die nächste Zeile:
Call accApp.OpenCurrentDatabase(pfad & "\" & myAccDB, False)
öffnet die Datenbank.
In der Datenbank habe ich eine Tabelle names "myTestTable" erstellt.
accApp.DoCmd.TransferSpreadsheet acImport, 10, myTestTable, ActiveWorkbook.FullName, True, "Tabelle2!A1:J50"' acImport = 0
Hier sagt er mir "Für diese AKtion bzw. Methode muss das Argument "Tabellenname" angegeben werden"
Tabellenname ist doch "myTestTable", oder?
Kannst du nochmal helfen?
LG,
Klaus M.
Anzeige
AW: lange Datensätze
11.12.2019 14:34:37
volti
Hallo Klaus,
schön, dass Du diese Variante mal probieren möchtest:
Also ich deklariere accApp einfach als Object, weil ich mit meistens auch mit Late Binding arbeite, also ohne Verweis auf die entsprechende DLL. Deshalb stehen dann auch die Konstanten wie z.B. acImport hier nicht zur Verfügung. Aber da kann man ja Googlen und einfach die Werte verwenden.
Zum zweiten Problem:
accApp.DoCmd.TransferSpreadsheet acImport, 10, "myTestTable", ActiveWorkbook.FullName, True, "Tabelle2!A1:J50"
Das ist ja dein Tabellenname und keine Variable, oder.
viele Grüße
Karl-Heinz
Anzeige
AW: lange Datensätze
12.12.2019 14:25:25
Klaus
Ui, die Gänsefüschen. Das war jetzt aber ein Newbie-Fehler :-)
So gehts leider immer noch nicht:
Option Explicit
Sub ImportExcelToAccess()
'Einlesen eines Datenbereiches einer Exceldatei in ACCESS (Beispiel, ungetestet)
Dim accApp As Object
Dim accDB As Object
'Dim acImport As Variant
Set accApp = CreateObject("ACCESS.Application")
accApp.Visible = True
Call accApp.OpenCurrentDatabase(pfad & "\" & myAccessDB, False)   'Datenbank öffnen, Passwort  _
ist optional
Set accDB = accApp.CurrentDb
'Die 10 kann auch wegelassen werden, das ist der AcSpreadSheetType 10=Excel10 ff, ggf. auch 9  _
nehmen
accApp.DoCmd.TransferSpreadsheet acImport, 10, "myTestTable", ActiveWorkbook.FullName, True, " _
Tabelle2!A1:A50" ', acImport = 0
accApp.DoCmd.CloseDatabase
accApp.Quit
Set accDB = Nothing
Set accApp = Nothing
End Sub

AcImport ist nicht definiert. Was soll de da stehen, 0?
accApp.DoCmd.TransferSpreadsheet 0, 10, "myTestTable", ActiveWorkbook.FullName, True, "Tabelle2!A1:A50"
geht schon mal nicht, da sagt er mir:
"Das Feld 50 ist in der Zieltabelle "MyTestTable" nicht vorhanden"
LG,
Klaus
Anzeige
AW: lange Datensätze
12.12.2019 15:41:48
volti
Hi KLaus,
ich hätte die Deklarationen auch mit reinpacken sollen :-)
Wollte aber auch nur ein kleines Beispiel als Anregung zeigen.
acImport hat den Wert 0. Kleiner Hinweis in grün hinter dem Code der Zeile...
Also einfach nur deklarieren.
Lösch mal Deine Tabelle aus der Datenbank und probiere noch mal. Ich meine nämlich, dass diese auch angelegt wird, wenn sie nicht da ist.
Falls die Köpfe dann nicht stimmen sollten, kann man die ja anschließend austauschen.
Sollte es dann auch nicht funktionieren, muss ich mir mal meine Altlasten anschauen...
viele Grüße
Karl-Heinz
Anzeige
AW: lange Datensätze
12.12.2019 16:45:35
volti
Hallo Klaus,
habe mir jetzt doch mal 'ne Leerdatenbank angelegt mit nix drin und einen Tabellenbereich importiert.
Funzt sofort.
Allerdings werden beim zweiten und xtenmal die Daten immer wieder angehängt. Das erfordert dann ggf. eine Tabellenlöschung.
Sub ImportExcelToAccess()
'Einlesen eines Datenbereiches einer Exceldatei in ACCESS (Beispiel, ungetestet)
 Dim accApp As Object, accDB As Object, acImport As Integer, acTable As Integer
 Dim sDB As String, sDatei As String
 Dim sTabelle As String
 acImport = 0: acTable = 0
 sDB = "C:\Users\voltm\Desktop\MeineTestdatenbank1.accdb"
 sDatei = "C:\Users\voltm\Desktop\MeineACCESSDaten.xlsx"
 sTabelle = "MyTestTable"
 Set accApp = CreateObject("ACCESS.Application")
 accApp.Visible = True
 Call accApp.OpenCurrentDatabase(sDB, False)   'Datenbank öffnen, Passwort ist optional
 Set accDB = accApp.CurrentDb
'Tabelle für neuen Input löschen
 On Error Resume Next
 With accApp.DoCmd
   .SetWarnings False
   .DeleteObject acTable, sTabelle
   .SetWarnings True
 End With
 On Error GoTo 0
 
 'Die 10 kann auch wegelassen werden, das ist der AcSpreadSheetType 10=Excel10 ff, ggf. auch 9 nehmen
 accApp.DoCmd.TransferSpreadsheet acImport, 10, sTabelle, sDatei, True, "Tabelle2!A1:A50"
 accApp.DoCmd.CloseDatabase
 accApp.Quit
 Set accDB = Nothing
 Set accApp = Nothing
End Sub

viele Grüße
Karl-Heinz

Anzeige
AW: lange Datensätze
13.12.2019 13:30:09
Klaus
Hallo Karl-Heinz,
erstmal vielen Dank, ich habe das Makro zum laufen bekommen. Aber ganz sinnvoll ist es in meinen Augen nicht. Ich poste mal zum Vergleich "dein" und "mein" Makro:

Sub Viele_Artikel_in_DB_Schreiben()
Dim t
t = Timer
Application.ScreenUpdating = False
On Error GoTo hell
Const APPNAME = "mod_Access / Viele_Artikel_In_DB_schreiben"
Dim con As ADODB.Connection
Dim datei As String
Dim rs As ADODB.Recordset
Dim ws As Worksheet
Dim ze As Long
Set ws = Tabelle2
datei = "V:\ODE\rrc\ALL\AV-Dateien\Datenbanken\MyDataTest.accdb"
Set con = New ADODB.Connection
con.Open ConnectionString:= _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & datei & ";" & _
"Mode=Share Exclusive"
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseServer
rs.Open Source:="MyTestTable", _
ActiveConnection:=con, _
CursorType:=adOpenStatic, _
LockType:=adLockPessimistic, _
Options:=adCmdTableDirect
'rs.Index = "Primarykey"
ze = 2
Do Until ze = 500000 'IsEmpty(ws.Cells(ze, 1))
rs.AddNew
rs!alpha = ws.Cells(ze, 1)
rs!bravo = ws.Cells(ze, 2)
rs!charlie = ws.Cells(ze, 3)
rs!hotel = ws.Cells(ze, 4)
rs!xxx = ws.Cells(ze, 5)
rs!yyy = ws.Cells(ze, 6)
rs!zzz = ws.Cells(ze, 7)
rs!aaa = ws.Cells(ze, 8)
rs!bbb = ws.Cells(ze, 9)
rs!ccc = ws.Cells(ze, 10)
rs.Update
ze = ze + 1
Loop
'*** Fehlerbehandlung
Err.Clear
hell:
If Err.Number = -2147467259 Then Resume     'Datenbank wird bereits verwendet
If Err.Number  0 Then MsgBox "Fehler in Sub """ & APPNAME & """" & vbCrLf _
& "Fehlernummer: " & Err.Number & vbLf & Err.Description
rs.Close
con.Close
Set rs = Nothing
Set con = Nothing
MsgBox Timer - t
Application.ScreenUpdating = True
End Sub
'73 sek für 500.000
Sub ImportExcelToAccess()
Dim t
t = Timer
Application.ScreenUpdating = False
'Einlesen eines Datenbereiches einer Exceldatei in ACCESS (Beispiel, ungetestet)
Dim accApp As Object, accDB As Object, acImport As Integer, acTable As Integer
Dim sDB As String, sDatei As String
Dim sTabelle As String
acImport = 0: acTable = 0
sDB = "V:\ODE\rrc\ALL\AV-Dateien\Datenbanken\MyDataTest.accdb"
sDatei = "H:\Excel VBA\EineMillionDatensaetze.xlsm"
sTabelle = "MyTestTable"
Set accApp = CreateObject("ACCESS.Application")
accApp.Visible = True
Call accApp.OpenCurrentDatabase(sDB, False)   'Datenbank öffnen, Passwort ist optional
Set accDB = accApp.CurrentDb
'Tabelle für neuen Input löschen
On Error Resume Next
With accApp.DoCmd
.SetWarnings False
.DeleteObject acTable, sTabelle
.SetWarnings True
End With
On Error GoTo 0
'Die 10 kann auch wegelassen werden, das ist der AcSpreadSheetType 10=Excel10 ff, ggf. auch 9  _
nehmen
accApp.DoCmd.TransferSpreadsheet acImport, 10, sTabelle, sDatei, True, "Tabelle2!A1:J500000"
accApp.DoCmd.CloseDatabase
accApp.Quit
Set accDB = Nothing
Set accApp = Nothing
MsgBox Timer - t
Application.ScreenUpdating = True
End Sub
"Viele_Artikel_in_DB_schreiben" braucht für 1000 Zeilen 0,5 Sekunden, für 500.000 Zeilen braucht es 75 Sekunden.
"ImportExcelToAccess" braucht für 1000 Zeilen ganze 5 Sekunden. OK, so ein mächtiges Makro ist vielleicht auch nicht das richtige für einen kleinen Datensatz. Also lassen wir es mal auf die 500.000 los. Leider:
Userbild
Mit einer Million Datensätzen habe ich es gar nicht erst probiert.
Insofern: Vielen Dank, akademisch interessant aber imho nicht sinnvoll nutzbar.
LG,
Klaus M.
Anzeige
AW: lange Datensätze
13.12.2019 15:04:52
volti
Alles klar Klaus.
Ein Versuch war es sicher wert, da man sieht, dass es immer mehrere Möglichkeiten gibt.
Ich hatte diese Methode (war aber auch ein wenig umfangreicher) für Dateien um die 300.000 Zeilen für einige Jahre verwendet..
Zum angezeigten Fehler kann ich nichts sagen. Man kann die Einschränkung aber auch weglassen, wenn man die ganze Tabelle einlesen will oder so "Tabelle2!A1:J". Vielleicht liegt es daran, dass keine 500.000 Zeilen vorhanden sind..
Und zur Zeit: Gehe mal davon aus, dass es hauptsächlich die Ladezeit der XLS-Datei ist, weil das nicht aus einer geöffneten Datei importiert wird. Deine Methode greift ja auf eine schon geladene Datei zu...
viele Grüße
Karl-Heinz
Anzeige
AW: lange Datensätze
14.12.2019 09:01:38
Klaus
Hallo Karl-Heinz,
sorry gestern konnte ich nicht mehr antworten - als am Freitag um 14:00 Uhr die Schicht gegangen ist (wir fangen alle um 06:00 an) dachte ich mir, super da kann ich noch fix zwei Änderungen an der Produktionsdatenbank programmieren dann ist Montag früh gleich alles auf dem Stand. Dann kam eins zum anderen und um 16:30 hat gar nichts mehr funktioniert :-( bis 17:00 hatte ich es dann wieder auf dem Stand von 14:00 zurück setzten können, ein Glück hatte ich Backups! Aber an dem Freitag hatte ich abends gar keinen Bock mehr privat an den Computer zu gehen :-)
Meine Musterdatei hatte über eine Million Datensätze, daran kann es nicht gelegen haben. Das öffnen der Exceldatei eigentlich auch nicht, die war offen. Was ich aber beobachte: "mein" Makro läuft einfach ohne viel Bildschirmaktualisierung durch, "dein" Makro öffnet erstmal sichtbar Access, dann sichtbar eine Tabelle usw ... ich nehme an das ist der Zeitfresser.
Ich habe zwar erstmal keine Verwendung dafür, werde dein Makro aber auf jedem Fall in meinem Archiv behalten. Wer weiss, vielleicht muss ich ja mal geschlossene Tabellen auslesen? Ist mir in dem Moment gar nicht aufgefallen. Ob ganze Spalten funktionieren muss ich noch probieren, auf eine geschlossene Tabelle kann ich ja nicht "Userrange.Rows.Count" anwenden.
Auf jedem Fall ein dickes Plus für dein Makro: Ich muss die exakten Spaltenbezeichnungen nicht kennen, das Makro erstellt sie einfach! "Meins" läuft in einen Fehler, wenn mal eine Spalte in Access umbenannt ist. Allein dafür ist es Wert, das Makro im Archiv zu haben.
Nochmal vielen Dank, dir ein schönes Restwochenende (falls du das heute liest) oder je nachdem einen ruhigen Montag!
LG,
Klaus M.
AW: lange Datensätze
11.12.2019 14:43:24
mmat
Hallo Klaus
1. wie der Name ("CreateObject") schon sagt, ist object ein geeigneter Datentyp.
2. Hier sind Gänsefüße vielleicht hilfreich: ... 10, "myTestTable", ActiveWorkbook ...
vg, MM

303 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige