Join zweier Excel Sheets

Hallo WWW-Gemeinde!

hab kürzlich ne Join (inner und outer) Funktion in VBA geschrieben, sind zwar nur ca 20 zeilen code, aber dafür bei 2 sheets mit 300 und 3200 Datensätzen, sowie 3 schlüsseln je sheet dauert der durchlauf ca 27 sekunden, was einfach zu lang is.
für VBA to Access gibts ja möglichkeiten direkt SQL einzusetzen. gibts da auch ne performante übersichtliche lösung für VBA to Excel?

aktuell schreib ich immer einen datensatz des einen sheets in ein variant array und einen datensatz des anderen sheets in ein aderes variant array, vergleich die auf übereinstimmung in den 3 attributen und kopier wenn true, nehm die nächste zeile wenn false.
übel umständilch ich weiß.
macht vielleicht auch je ein array pro sheet das alle seine datensätze enthält sinn? so dass man ned jedesmal das array neu füllt, sondern einfach nur drin suchen muss?

thx und greetz

Hallo Mole,

hab kürzlich ne Join (inner und outer) Funktion in VBA
geschrieben,

hat das was damit zu tun:
http://www.wer-weiss-was.de/article/6667376
Übrigens, Feedback zu Antworten werden in jedem Forum sehr gerne gesehen.

sind zwar nur ca 20 zeilen code, aber dafür bei 2
sheets mit 300 und 3200 Datensätzen, sowie 3 schlüsseln je
sheet dauert der durchlauf ca 27 sekunden, was einfach zu lang
is.

Und nun? Soll ich mir deinen Code erdenken und ihn dann versuchen zu beschleunigen?

Gruß
Reinhard

Hallo mole.

macht vielleicht auch je ein array pro sheet das alle seine
datensätze enthält sinn? so dass man ned jedesmal das array
neu füllt, sondern einfach nur drin suchen muss?

Grundsätzlich gesehen ist ja ein Excel-Sheet schon ein Array. Das würde bedeuten, das Du da direkt drin suchen und vergleichen könntest. Es gibt bestimmt eine oder mehrere passende WorksheetFunction(nen), mit denen Du arbeiten könntest, z.B. in der Funktionen-Rubrik Matrix. Diese ohnehin eingebauten Funktionen sind auch sehr viel schneller (das hab’ ich hier gelesen).

VG
Carsten

So sorry Reinhard,
bin mittlerweile so zerstreut, dass ich nicht mal mehr weiß ob ich n thema ned schon erfragt hab. tut mir sehr leid! hab wohl auch übersehen das zu abbonieren und dass da ne antwort drin steht. nochmal entschuldigung! funktionieren tut die methode im anderen post mittlerweile, aber hald seeeehr ressourcenfressend.

hab nach meinem ersten post zu dem thema eine funktion gebaut, die ich nur textuell erklären wollte, weil sie performance technisch, nicht weiter zu optimieren ist und die erklärung zu lange dauert. was da so performance kostet ist eben dass jede zeile immer einzelnd in ein array geschrieben mit dem anderen array verglichen wird und wenn nicht übereinstimmt das array wieder neu befüllt wird.

bin grad an einer lösung dran, beide komplette sheet in je ein 2D array zu schreiben. in denen dann zeile für zeile zu vergleichen.

meine frage war eben nur nach einer standardmethode ala SQL Join die in VBA sicher ned nur von mir gebraucht werden könnte :smile:

danke und sorry nochmal!

Grüezi Mole

hab kürzlich ne Join (inner und outer) Funktion in VBA
geschrieben, sind zwar nur ca 20 zeilen code, aber dafür bei 2
sheets mit 300 und 3200 Datensätzen, sowie 3 schlüsseln je
sheet dauert der durchlauf ca 27 sekunden, was einfach zu lang
is.
für VBA to Access gibts ja möglichkeiten direkt SQL
einzusetzen. gibts da auch ne performante übersichtliche
lösung für VBA to Excel?

Wenn Du aus einer zweiten Mappe auf die Daten der ersten Mappe zugreifst, dann kannst Du das mit MS-Query (dem Abfrage-Editor) direkt mit den Standard-SQL Befehlen tun.

Wenn es in derselben Mappe auf ein drittes Tabellenblatt gehen soll, dann könntest Du mit ADO auf die anderen Tabellenblätter zugreifen und ebenfalls über SQL-Befehle die Joins ausführen lassen.
Das dürfte dann in aller Regel schneller laufen als ‚handgestrickter‘ VBA-Code.
Voraussetung ist dann allerdings, dass die Daten sauber mit Spaltenüberschriften versehen sind und dass sie in A1 beginnen.

Mit freundlichen Grüssen

Thomas Ramel

  • MVP für MS-Excel -

Hallo Mole,

nochmal entschuldigung!

ist vom Tisch, und es lag nahezu nichts auf dem Tisch :smile:)

funktionieren tut die methode
im anderen post mittlerweile, aber hald seeeehr
ressourcenfressend.

Okay, dann zeige nochmals den jetzt existierenden Code.

hab nach meinem ersten post zu dem thema eine funktion gebaut,
die ich nur textuell erklären wollte, weil sie performance
technisch, nicht weiter zu optimieren ist

Das sagst du, ich weiß das nicht, zeig bitte auch diese Funktion.

Von SQL, ADO, ich glaub DAO oder sowas gibt es auch noch bei Datentransfer, datenbankabfragen usw., kenne ich mich nicht so aus da äußerst selten mal benutzt.

Insofern kann ich maximal versuchen den „handgestrickten“ :smile: vba -Code zu optimieren.
Wenn ich oder ein anderer dann das Ende der Fahnenstange erreicht haben so geht wohl nur noch das was Thomas gesagt hat.
Ohne Recherche wüßte ich gar nicht wie ich das nun umsetzen müßte.
Aber das ist mir egal, ich kenne genug Dinge in VBa die ich nicht weiß.

Andererseits, wenn du es so umsetzen willst und weißt nicht genau wie das geht, dann löcher Thomas, ich lese dann begeistert mit *gg*

bin grad an einer lösung dran, beide komplette sheet in je ein
2D array zu schreiben. in denen dann zeile für zeile zu
vergleichen.

In „zeile für zeile“ steckt schon das was es langsam macht.
Das hält auf wenn man das mit der Interpretersprache Vba macht.
Gibt da schnellere maschinennähere Sprachen und Datenbanksysteme.

Carsten hat ja sehr Recht wenn er sagt daß eingebaute Excelfunktionen schneller sind als Vba-Code, gar noch Code der die Zellen/zeilen einzeln abklappert.
Im Internet lese ich von 1000 mal schneller und mehr.
Das Gleiche wird ja wohl auch für SQL-Befehle usw. gelten.

meine frage war eben nur nach einer standardmethode ala SQL
Join die in VBA sicher ned nur von mir gebraucht werden könnte

)

Ich kenne nur das Join aus Vba, ist auch was zusammenführendes aber m.E. etwas anderes als das was du mit SQL-Join meinst.
Und Inner und outer kenne ich nur vom ZUgriff per Vba auf Html-Seiten.
Aber das sind nur unwichtige Begriffsdeklarationen, nicht wichtig,
wichtig ist daß du dein problem verständlich rüberbringst und das hast du.

Gruß
Reinhard

Genau an sowas hab ich gedacht!
super, dann werd ich die ADO und MAtrix geschichte mal ausprobieren.

wobei ich sagen muss, hab die methode mit array je sheet mit dessen gesamtem inhalt grad getestet. der InnerJoin läuft bei 3000 zeilen im nicht messbaren bereich ab, sehr nice.
für den outer müsste ich wohl allerdings noch ein drittes array bauen, in dem die zeilen der treffer festgehalten werden, um im anschluss auch den outer-join machen zu können.
Der schlüssel ist im zielsheet nicht eineindeutig, deswegen kommts vor dass ein quelldatensatz mehrfach in den zieldatensatz übertragen wird (löschen im quellsheet nach vergleich = true geht damit ned)

danke für die hilfe!

thema is für mich damit vorerst wohl erledigt

Super Reinhard, auch dir vielen Dank!!!

der Vollständigkeit halber, hier ist mein eben gebauter InnerJoin:
befürchte aber dass ohne weitere erklärung die variablen recht schlecht einzuordnen sind oder? also ich hab da zumindest immer ziemliche probs bei fremdem code.

For i = selRow To tarMaxRows
For f = 1 To tarMaxCols
DataSet3(i, f) = Sheets(tarTable).Cells(i, f).value
Next
Next

For i = compRow To srcMaxRows
For f = 1 To srcMaxCols
DataSet4(i, f) = Sheets(srcTable).Cells(i, f).value
Next
Next

For i = selRow To tarMaxRows
For f = compRow To srcMaxRows
For k = LBound(TarKeyColsNumbers) To UBound(TarKeyColsNumbers)
If DataSet3(i, TarKeyColsNumbers(k)) DataSet4(f, SrcKeyColsNumbers(k)) Then
Exit For
Else
equalCounter = equalCounter + 1
If equalCounter = UBound(SrcKeyColsNumbers) Then
For h = 1 To srcMaxCols
Sheets(tarTable).Cells(i, tarMaxCols + h) = DataSet4(f, h)
Next
ReDim Preserve InnerJoinData(1 To (UBound(InnerJoinData)) + 1)
InnerJoinData(UBound(InnerJoinData)) = f
equalCounter = 0
End If
End If
Next
Next
Next

'Bereitet Quellsheet auf OuterJoin vor, indem die im InnerJoin erfolgreich gejointen Datensätze gelöscht werden
For i = LBound(InnerJoinData) To UBound(InnerJoinData)
Sheets(srcTable).Rows(i).EntireRow.Delete
Next

Nur die sammlung der im InnerJoin bereits getroffenen Datensätze hab ich noch ned getestet. der innerJoin an sich geht sau schnell.

Für den Outer würd ich wohl beim alten code bleiben:

'Führt Outer-Join durch
For i = selRow To srcMaxRows
DataSet2 = DataSetArray(srcTable, i)
For k = LBound(DataSet2) To UBound(DataSet2)
Sheets(tarTable).Cells(tarMaxRows + i, tarMaxCols + k) = DataSet2(k)
Next
For f = LBound(TarKeyColsNumbers) To UBound(TarKeyColsNumbers)
Sheets(tarTable).Cells(tarMaxRows + i, TarKeyColsNumbers(f)) = Sheets(srcTable).Cells(i, SrcKeyColsNumbers(f))
Next
Next

Hey Carsten,

wenn ich das richtig weiter recherchiert hab, handelt es sich bei den matrixfunktionen um formeln ausserhalb von vba (die man natürlich auch per vba in zellen einfüllen könnte), das wäre nicht mein weg.
versuche, wie man am quelltext evtl sieht, das ganze so „generisch“ wie möglich zu halten. und deshalb die zugriffe, einträge und umformungen möglichst im code und möglichst wenig in den zellen zu machen :smile:

THX! und danke für den tipp!

Hallo Mole.

wenn ich das richtig weiter recherchiert hab, handelt es sich
bei den matrixfunktionen um formeln ausserhalb von vba (die
man natürlich auch per vba in zellen einfüllen könnte), das
wäre nicht mein weg.
versuche, wie man am quelltext evtl sieht, das ganze so
„generisch“ wie möglich zu halten. und deshalb die zugriffe,
einträge und umformungen möglichst im code und möglichst wenig
in den zellen zu machen :smile:

Ich habe mir keinen Quelltext angesehen. Vielleicht noch ein Hinweis, wie ich das gemeint habe: Man braucht die Funktionen nicht per VBA in die Zellen eintragen, man kann einfach in VBA damit rechnen :wink:

VG
Carsten

Hallo Mole,

der Vollständigkeit halber, hier ist mein eben gebauter
InnerJoin:

was bitteschön ist daran vollständig?

befürchte aber dass ohne weitere erklärung die variablen recht
schlecht einzuordnen sind oder?

geht so.

also ich hab da zumindest
immer ziemliche probs bei fremdem code.

Dito, hängt auch davon ab wie „vorbereitet“ die Codes sind daß sie auch andere lesen können.

For i = selRow To tarMaxRows
For f = 1 To tarMaxCols
DataSet3(i, f) = Sheets(tarTable).Cells(i, f).value
Next
Next

So eine Schleife, egal jetzt bei deinem inner oder outer Kram, ist natürlich lahm.

Gruß
Reinhard

was bitteschön ist daran vollständig?

deswegen vorhin, ich zitiere mich selbst „beschreib ich den code textuell“, hätte mich wohl daran halten sollen.

geht so.

siehe oben

Dito, hängt auch davon ab wie „vorbereitet“ die Codes sind daß sie auch andere lesen können.

siehe oben

For i = selRow To tarMaxRows
For f = 1 To tarMaxCols
DataSet3(i, f) = Sheets(tarTable).Cells(i, f).value
Next
Next
So eine Schleife, egal jetzt bei deinem inner oder outer Kram, ist :natürlich lahm.

beschreibt ein Array mit inhalten aus 30 Spalten und ca 3500 Zeilen innerhalb von millisekunden. da ich mit VBA keine realtime sachen mach ^^ reicht mir das…
wenn es einen schnelleren weg gibt, ein komplettes sheet in ein array zu schreiben oder gleich eine völlig andere methode zu nehmen um einen eigentlich simplen join zu machen (den ich in vba nun mal mangels vba erfahrung ned hinbekomme) dann gern.

denke die funktionalität eines Joins muss ich ned weiter erklären um klar zu machen was ich will.

hätte einfach dabei bleiben sollen, eine rein textuelle beschriebung abzugeben - sorry für die verwirrung…

/closed

Man braucht die Funktionen nicht per VBA in die Zellen eintragen, man kann einfach in VBA damit rechnen :wink:

awesome!
das is mir leider auch neu…hätte wohl bisher einiges erspart :wink:

gleich mal testen

cheers!