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

Stammdaten überspielen - die Zweite

Stammdaten überspielen - die Zweite
26.10.2016 12:48:47
nihil
Hallo zusammen,
ich arbeite mit einer Accessdatei, die ca. 20.000 Datensätze umfasst.
Diese Datenbank mit einem beispielhaften Ausschnitt ist in Tabellenblatt „Datenbasis“ der Testdatei hinterlegt:
https://www.herber.de/bbs/user/109028.xlsm
Eindeutig zuzuordnen sind diese Datensätze über die „ID“, welche als Identifikationsnummer für den jeweiligen Kontakt dient.
Nun wird diese Datenbasis regelmäßig exportiert und im Zuge unterschiedlicher Excel-Arbeitsdateien verwendet und auch modifiziert.
Eines von vielen Anwendungsbeispielen wäre z.B. eine Außendienstliste (Tab „Beispiel1“).
Der zuständige Außendienstmitarbeiter hätte die Aufgabe seinen Zuständigkeitsbereich im Hinblick auf die Besuchszeiten der Kunden zu bearbeiten, die Spalten B und C als nicht in der Datenbasis befindliche Informationen wären also der Bearbeitungsfokus.
Im Zuge der Bearbeitung würden aber dennoch vereinzelt Stammdatenänderung vorgenommen (z.B. aus dem Gespräch resultierend Änderungen der Anschrift oder Telefonnummer), die für die "Datenbasis" relevant sind.
Diese Informationen würden dann von mir nach abgeschlossener AD-Recherche via Import wieder in die Datenbasis eingespielt.
Ich habe das bisher immer mit einem Sverweis auf die „ID“-Spalte gemacht, was aber einen enormen manuellen Aufwand bedeutet und im Hinblick auf die Größe der Datenbasis außerdem fehleranfällig ist.
Zu schnell ist mal ein falscher Datensatz überschrieben, was leider oft erst viel später auffällt, wenn es zu spät ist.
Ich suche nun nach einer Möglichkeit, Arbeitstabellen wie „Beispiel1“ mit einem Makro direkt in die „Datenbasis“ einspielbar zu machen.
Diese Routine würde dann also einen Bezug beider Datensätze mit der „ID“-Spalte herstellen und die Datensätze der modifizierten Stammdatenspalten in die Datenbasis einspielen.
Hierbei würden sowohl geänderte Datenfelder übernommen, als auch unveränderte Datenfelder im Originalzustand belassen.
Einheitliches Merkmal ist, wie gesagt, die „ID“ - weiterhin würden die Spaltenüberschriften der Datenbasis auch in den Arbeitstabellenblättern zu finden sein, das ermöglicht ggf. einen zusätzlichen Bezug.
Vor ein paar Wochen wurde mir im Hinblick auf die Problemstellung von Rudi in diesem Forum mit dem nachfolgenden Makro bereits sehr geholfen:
Sub UpdateDatenBasis()
Dim arrADMA, i As Long, j As Long, wksDB As Worksheet
Dim vntRow As Long, vntCol As Long
Application.ScreenUpdating = False
Set wksDB = Worksheets("Datenbasis")
If Not ActiveSheet Is wksDB Then
arrADMA = Cells(1, 1).CurrentRegion
For i = 2 To UBound(arrADMA)
vntRow = Application.Match(arrADMA(i, 1), wksDB.Columns(2), 0)
If Not IsError(vntRow) Then
For j = 4 To UBound(arrADMA, 2)
vntCol = Application.Match(arrADMA(1, j), wksDB.Rows(1), 0)
If Not IsError(vntCol) Then
wksDB.Cells(vntRow, vntCol) = arrADMA(i, j)
End If
Next j
End If
Next i
End If
End Sub
Wie sich erst im Nachhinein herausgestellt hat, läuft das Makro aber dann auf einen Laufzeitfehler, wenn die Arbeitsdatei anders aufgebaut ist, oder weitere, mit „Datenbasis“ übereinstimmende Spaltenüberschriften aufweist, als exemplarisch im Tabellenblatt „Beispiel 1“.
Das kommt ziemlich häufig vor, die Anordnung mit den kongruenten Spalten „Adresse“, „PLZ“, „Ort“, „Telefon“ in dieser Anordnung und Auswahl ist wie gesagt nur ein mögliches Beispiel.
Idealerweise arbeitet das Makro so ab, dass die Zelleninhalte unter den mit der mit der „Datenbasis“ kongruenten Spaltenüberschriften in „Beispiel 1“ unabhängig von der Anordnung und Auswahl identifiziert und in der Datenbasis ersetzt werden.
Ist das möglich, oder ist diese Funktionalität nicht automatisiert über ein Makro abbildbar?
Nochmals vielen Dank und viele Grüße
Nils

5
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Stammdaten überspielen - die Zweite
28.10.2016 14:37:44
Michael
Hi Nils,
im Prinzip schaut Rudis Code ja bei jedem Wert aus "Beispiel1" in der Datenbank nach,
- zunächst, ob die ID vorhanden ist und
- dann, ob die Spalte übereinstimmt.
Insofern wäre es interessant, in welcher Zeile das Makro mit welcher Fehlermeldung stehenbleibt.
Allerdings würden mir schon Optimierungsmöglichkeiten einfallen:
- zuallererst die übereinstimmenden Spalten ermitteln und in einem Array festhalten, in etwa so:
           ID Ort
Blatt 1:  1   6
Blatt 2:  2   6
usw.
Dann muß man nicht bei einzelnen Wert erneut die Spalte suchen; außerdem braucht man nicht übereinstimmende Spalten gar nicht erst zu durchlaufen.
- überprüfen, ob überhaupt eine Änderung vorliegt und damit Schreibzugriffe minimieren
- die Ermittlung der Zeile in der DB kann deutlich beschleunigt werden, indem man anstelle des wiederholten application.match die komplette ID-Spalte in ein Dictionary einliest, mit der ID als "key" und der Zeilennummer als "item".
Das würde dann etwa so aussehen:
Sub UpdateDB()
Dim o As Object
Dim ad, aa, ueb ' array DB, array Activesheet, array Ueberschriften
Dim i As Long, j As Long, k As Long, z As Long
Dim wksDB As Worksheet
If ActiveSheet.Name  "Datenbasis" Then
Set wksDB = Worksheets("Datenbasis")
aa = Intersect(ActiveSheet.UsedRange, Rows(1))
With wksDB: ad = Intersect(.UsedRange, .Rows(1)): End With
i = WorksheetFunction.Min(UBound(aa, 2), UBound(ad, 2))
ReDim ueb(i - 1, 2) ' Spalten: 0-Name, 1-aus DB, 2-aus activesheet
For j = 1 To UBound(aa, 2)
For i = 1 To UBound(ad, 2)
If aa(1, j) = ad(1, i) Then
If aa(1, j) = "ID" Then
ueb(0, 0) = ad(1, i): ueb(0, 1) = i: ueb(0, 2) = j
Else
k = k + 1
ueb(k, 0) = ad(1, i): ueb(k, 1) = i: ueb(k, 2) = j
End If
End If
Next
Next
' k enthält jetzt den (max.) Wert für übereinstimmende Spalten,
' Spalte 0 ist die ID...
' Die nächste Zeile nur zur Illustration; bitte auskommentieren...
Sheets("Temp").Range("k2").Resize(UBound(ueb) + 1, UBound(ueb, 2) + 1) = ueb
' Die Namen sind für das Makro ja so ziemlich wurscht...
With wksDB: ad = Intersect(.UsedRange, .Columns(ueb(0, 1))): End With
Set o = CreateObject("scripting.dictionary")
For i = 2 To UBound(ad): o(ad(i, 1)) = i: Next
' Dictionary enthält IDs und Zeilennummern
aa = Cells(1, 1).CurrentRegion
Stop
For i = 2 To UBound(aa)
If o.exists(aa(i, ueb(0, 2))) Then
z = o(aa(i, ueb(0, 2))) ' z wie Zeile in DB
For j = 1 To k
If wksDB.Cells(z, ueb(j, 2))  aa(i, ueb(j, 1)) Then _
wksDB.Cells(z, ueb(j, 2)) = aa(i, ueb(j, 1))
Next
Else
MsgBox "ID " & aa(i, ueb(0, 1)) & " nicht in DB gefunden."
' hier ggf. irgendwohin wegschreiben zur späteren Bearb.
' anstatt mgsbox,
' z.B. string nv: nv = nv & "," & aa(i, ueb(0, 1))
End If
Next
End If
End Sub
Die Datei: https://www.herber.de/bbs/user/109078.xlsm
Schöne Grüße,
Michael
Anzeige
AW: Stammdaten überspielen - die Zweite
31.10.2016 12:50:14
nihil0815
Hallo Michael,
zunächst einmal vielen lieben Dank für Deine Mühe!
Das Auslesen/Überspielen funktioniert einwandfrei, solange ich die Spaltenanordnung beider Tabellenblätter nicht verändere.
Nehme ich allerdings eine Veränderung z.B durch Einfügen einer beliebigen anderen Spalte aus der Datenbasis in die Beispieldatei vor, so überschreibt das Makro die Daten in die falschen Spalten.
Exemplarisch habe ich die Spalte mit dem "Namen" in der Beispieldatei vorangestellt und das Makro durchlaufen lassen:

Die Datei https://www.herber.de/bbs/user/109118.xlsm wurde aus Datenschutzgründen gelöscht


Ergänze ich Spalten rechts im Beispieltabellenblatt, so wird ein Laufzeitfehler 9 (Index außerhalb des gültigen Bereichs) erzeugt, der Debugger läuft auf den Fehler bei
If wksDB.Cells(z, ueb(j, 2)) aa(i, ueb(j, 1)) Then _
Was mache ich falsch? Ich habe bereits versucht, die Spaltenzuordnung beider Tabellenblätter vorab im temporären Arbeitsblatt manuell festzuschreiben, das ist aber nicht zielführend.
Der Inhalt des Temp-Blattes wird offenbar automatisch erzeugt und im Zuge des Durchlaufs "UpdateDB" jedesmal überschrieben.
Viele Grüße
Nils
Anzeige
AW: Stammdaten überspielen - die Zweite
31.10.2016 15:00:34
Michael
Hi Nils,
Du machst gar nichts falsch, das war mein Fehler: in den Zeilen (hier die falsche Version)
If wksDB.Cells(z, ueb(j, 2))  aa(i, ueb(j, 1)) Then _
wksDB.Cells(z, ueb(j, 2)) = aa(i, ueb(j, 1))

war jeweils das ,1 und ,2 vertauscht - das war's auch schon.
Das hat einerseits dazu geführt, daß die falschen Spalten verglichen/ausgetauscht wurden und erklärt in dem Zusammenhang auch die Fehlermeldung mit dem "außerhalb Index", weil ja beide Tabellen unterschiedlich viele Spalten haben.
Allerdings habe ich, weil ich schon dabei war, die "usedrange" durch "currentregion" ersetzt.
Datei mit jetzt hoffentlich bravem Makro und einer weiteren Spalte getestet:
https://www.herber.de/bbs/user/109120.xlsm
Schöne Grüße,
Michael
Anzeige
AW: Stammdaten überspielen - die Zweite
31.10.2016 18:37:48
nihil0815
Hallo Michael,
klasse, nun funktioniert alles wie gewünscht!
Für mich ist das bei den Stammdatenroutinen so eine enorme Hilfe.
Tausend Dank nochmals und einen schönen Abend
Nils
gerne, vielen Dank für die Rückmeldung
31.10.2016 19:23:19
Michael
Hi Nils,
freut mich, wenn es jetzt geht - ich hatte schon fast an mir gezweifelt...
Dann viel Spaß und schöne Grüße,
Michael

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige