Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1196to1200
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

Recordset Type Date

Recordset Type Date
Andi
Hallo Zusammen,
ich erstelle einer Excelübersicht. Die Daten werden auf vielen "Excel Formularen" erstellt.
Hier werden Daten des Types long, date und string verarbeitet. Die "Formulare" sind gesammelt in Ordner an verschieden Server Orten.
Um die Daten auszulesen, bediente ich mich der Methode jedes Excelfile via VBA zu öffnen und die Daten in ein array des Types variant einzulesen. Mittlerweile benötigt ein Update ca. 9 min Laufzeit!
Die 9 min sind mir zu lang und gewiss langfristig keine Killer Application.
Eine neue Methode mußte her.
Da eine Excel Datei nichts anderes als eine "Mini" Datenbank ist, dachte ich mir die Daten über eine fertige VB Datenbankschnittstelle "ADODB" zu ziehen.
Das funktioniert alles wunderbar, Update Laufzeit nur noch 1:22 min ;-)).
Aber vorhandene Excel Daten vom Type Date erhalten im Recordset field F6 den Wert "Leer".
Werte vom Typ Datum werden übertragen als "Leer". Wäre nichts da, würde der Wert "Null" angezeigt werden.
Kann man einen Recordset als variant deklarien?
Danke.
Gruß Andi
Anbei Code:
Function ADOExcel(ByRef ExcelPath As String, ByRef Tabelle As String, Optional Countrows As  _
Long = 500) As Variant
Dim rs As New ADODB.Recordset
Dim arrADO() As Variant
Dim arrEXC() As Variant
Dim n, m, k, i, Max As Long
Set rs = ExcelTable(ExcelPath, Tabelle)
rs.MoveFirst
Erase arrADO
arrADO = rs.GetRows(Countrows)
arrEXC = TransposeArray(arrADO)
Erase arrADO
arrADO = arrEXC
Erase arrEXC
ReDim arrEXC(1 To UBound(arrADO) + 1, 1 To UBound(arrADO, 2) + 1)
For m = LBound(arrADO) To UBound(arrADO)
For n = LBound(arrADO, 2) To UBound(arrADO, 2)
arrEXC(m + 1, n + 1) = arrADO(m, n)
Next
Next
Erase arrADO
ReDim arrADO(1 To UBound(arrEXC) + 1, 1 To UBound(arrEXC, 2))
rs.MoveFirst
For m = LBound(arrEXC) To UBound(arrEXC) + 1
For n = LBound(arrEXC, 2) To UBound(arrEXC, 2)
If m = 1 Then
For i = 0 To rs.Fields.Count - 1
arrADO(m, i + 1) = rs.Fields(i).Name
Next
Else
arrADO(m, n) = arrEXC(m - 1, n)
End If
Next
Next
rs.Close
ADOExcel = arrADO
End Function
Function ExcelTable(ByRef ExcelPath As String, ByRef Tabelle As String) As ADODB.Recordset
Dim excelfile As New ADOX.Catalog
Dim cn As New ADODB.Connection
Dim SQL As String
Dim Con As String
SQL = "select * from [" & Tabelle & "$]"
Con = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Extended Properties=Excel 8.0;" & "Data Source=" &  _
ExcelPath & ";"
Call cn.Open(Con)
'ADOX Anzahl Tabellen
Set excelfile.ActiveConnection = cn
'MsgBox excelFile.Tables.Count
AnzahlTab = 0
For i = 0 To excelfile.Tables.Count - 1
If Right(excelfile.Tables(i).Name, 1) = "$" Then
AnzahlTab = AnzahlTab + 1
End If
Next
ThisWorkbook.Sheets("Optional").Cells(1, 2) = AnzahlTab
Set ExcelTable = New ADODB.Recordset
ExcelTable.Open SQL, Con, adOpenKeyset, adLockOptimistic
cn.Close
End Function
Function TransposeArray(v As Variant) As Variant
Dim X, Y, Xupper, Yupper As Long
Dim tempArray() As Variant
Xupper = UBound(v, 2)
Yupper = UBound(v, 1)
ReDim tempArray(Xupper, Yupper)
For X = 0 To Xupper
For Y = 0 To Yupper
tempArray(X, Y) = v(Y, X)
Next
Next
TransposeArray = tempArray
End Function

3
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Benutzer
Anzeige
AW: Recordset Type Date
09.02.2011 01:25:03
Roland
Hallo Andi, mal ein Versuch:
1. In deinem Code würde ich unabhängig von der Fragestellung die Deklarationen überarbeiten. Wenn Du schreibst: Dim n, m, k, i, Max As Long, wird unter VBA nur Max als Long interpretiert, n, m, k, und i jedoch als Variant. Aus deinem Code ist ersichtlich, dass du das aber nicht willst. Schreibe also Dim n As Long, m As Long, k As Long, i As Long, Max As Long
2. Dein Recordset ist richtig deklariert; wenn du ihn als Variant versuchst zu deklarieren, wird das VBA entweder korrekt umwandeln oder abstürzen. Im besten Falle baust du dir damit nur eine Bremse ein. Da du nichts über Fehlermeldungen schreibst, wird auch der richtige Verweis gesetzt sein und es damit zur (zeitaufwendigen) Umwandlung kommen.
3. In der Funktion Function ExcelTable öffnest und schließt zwar am Ende auch die Verbindung, machst aber kein anschliessendes Set cn = Nothing. Das wird dir irgendwann auf die Füsse fallen und dann debuggst du dir einen Wolf dran.
4. Dein Ausgangsproblem kann ich nicht nachvollziehen: wenn Du mit Recordsets (und den damit verbundenen zeitaufwendigen Erstellen einer Connection) deutlich schneller als mit dem simplen (ggfs. schreibgeschützten) Öffnen sein willst, dann kann das entweder an Programmierfehlern liegen oder du schaltest irgendwelche Aktualisierungsgeschichten in den Excelfiles nicht aus. Letzteres kannst du testen, indem du zu Beginn der "9-Minuten-Routine" mal Application.AskToUpdateLinks= False setzt und am Ende wieder auf True.
Ich habe mal so was realisert und brauche für rd. 500.000 Datensätze aus diversen Excel- und Text-Dateien keine 20 Sekunden.
5. Das Problem mit dem Recordset liegt darin, dass an einer Stelle deiner verschachtelten Umwandlungsorgie entweder die Jet-Engine oder VBA die Datümer in den ausgelesenen Exceldateien "niedermachen" und Du einen Leerstring (-> DBNULL ?!) bekommst.
Beim Auslesen von Datenbanken (NICHT Excel-Dateien) habe ich mit Konstruktionen wie arrADO = rs.GetRows(Countrows) zum schnellen Übertragen eines Recordsets in ein Array auch schlechte Erfahrungen gemacht und mir dazu folgende Funktion zurechtgebastelt:
Option Explicit
' Function zum Befüllen eines Arrays mit Werten eines Recordsets
' Parameter
' r : der Recordset
' strSQL : der SQL-Befehl als Ordinalstring
' v : das zu befüllende Array
' lngUbound : Ubound der 2. Dimension des Arrays
' lngField : die Anzahl der letzten Spalten des Recordsets, die NICHT ins Array sollen
' blnClose : entscheidet über das Weiterbestehen des Recordsets nach Befüllung des Arrays
'
' Rückgabe : true bei Erfolg,
' false, wenn der Rekordset nicht enthielt
Public Function Array_To_Recordset(ByRef r As ADODB.Recordset, _
ByRef strSQL As String, _
ByRef v As Variant, _
ByRef lngUbound As Long, _
ByRef lngField As Long, _
ByRef blnClose As Boolean) _
As Boolean
Dim l As Long, m As Long, f As Long
With r
.Open strSQL, cn, adOpenDynamic, adLockOptimistic
If Not .BOF Then
.MoveFirst
Else
Array_To_Recordset = False
Set v = Nothing
Exit Function
End If
Do Until .EOF
l = l + 1
r.MoveNext
Loop
ReDim v(1 To l, 1 To lngUbound)
.MoveFirst
Do Until .EOF
m = m + 1
For f = 0 To .Fields.Count - lngField
If .Fields(f).Value  "NULL" Then
v(m, f + 1) = .Fields(f).Value
Else
v(m, f + 1) = ""
End If
Next f
.MoveNext
Loop
End With
If blnClose Then
r.Close
Set r = Nothing
End If
End Function
Damit schaufelst Du direkt das Recordset je nach Gusto ganz oder teilweise in ein Variant-Array, transponierst das Ganze auch in einem Rutsch und brauchst so keine Function TransposeArray mehr.
Falls Dich das jetzt mehr verwirrt als informiert: ich würde als erstes hingehen, mir die 9-Minuten Routine schnappen und die mal auf Bremsen untersuchen. Richtig gemacht geht das mit Sicherheit schneller als so eine hier unnötige und nur verkomplizierende Datenbankgeschichte.
Gute Nacht aus Berlin
Roland Hochhäuser
Anzeige
Recordset ignores married Cells
09.02.2011 13:53:17
Andi
Hallo Roland,
hau nicht so auf den Putz ;-)!
Danke für deine Antworten. Dein Code ist "auch" Dirty.
Der Funktion übergibts Du den Recordset und gibst die Anweisung den Recordset nochmal zu öffnen usw.
Confussed?!? Egal, ich habe aber Deine Methode über den Do Until ... Loop kopiert und getestet. Gleiches Ergebnis.
Fakt ist, eine DB Connection kann keine verbundene Excel Zellen einer Tabelle lesen.
Habe zwei Engines (Microsoft Excel Driver (*.xls); Microsoft.Jet.OLEDB.4.0) getested. So what?
Die Methode Open anstelle ADO ist langsamer, trotz Verwendung von GetMoreSpeed (Kannst mal Goog**)!
Dateigöße und Rechnerperformance können die Laufzeit erheblich beeinflussen.
LapTop ca 9min
FestStation ca 3min
FestStation 1:26 min (ADO Methode)
Gruß
Andi
Anzeige
Recordset ignores MergeCells
09.02.2011 14:02:24
Andi
MergeCells

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige