1k Aufrufe
Gefragt in Tabellenkalkulation von
Ein Freund hat mir 2 Makros geschrieben womit man Zahlen in allen Spalten in bestimmter Reihenfolge unter Millionen von Zahlen findet.
Da die Zahlen öfters in richtiger Reihenfolge vorkommen werden Sie dann in einem eigenen Tabellenblatt angezeigt.

Es sieht dann so Aus:

In Blatt 1 sind meine Zahlen (Mehrere Millionen)
In Blatt 2 werden die gesuchten Zahlen eingegeben
In Blatt 3 werden die gefunden Zahlen kopiert und Farblich angezeigt

Korrekt abgelaufes Makro sah dann z.B so aus

18
47
95
18

Die 4 Nummern wurden in Blatt 2 eingegen zum Suchen


-----------------------------------------------------------------

Nach dem durchsuchen von den Millionen von Zahlen wurde im Blatt 3 dies angezeigt.

32
85 Die 3 Vornummer
82

18
47
95 Die 4 Nummer wurden in Blatt 2 eingegen zum Suchen
18

41
17
96
99 Die 8 Nachnummern
64
72
87
43

Angezeigt werden die 4 gesuchten Nummern inklusive
3 Vor und 8 Nachnummern

--------------------------------------------------------------------

Da wir nun Verschiedener Meinung sind hat er mir die Makros ohne mein Wissen so umgeschrieben das sie nun bedingt
richtig Arbeiten.

Mann kann jetzt nur 3 Nummern suchen und nicht mehr 4 oder Mehr.
Er zeigt mir zwar die gefundenen Zahlen an aber nicht mehr alle sondern kopiert das Ergebniss x-mal(unsinniger Weise) in Blatt 3


Könnte sich vielleicht jemand die Makros anschauen und Sie wieder "entsperren" das sie korrekt arbeiten.

Das korrekt Makro müsste so ablufen.

Durchsucht Blatt 1 nach den eingebeben Such-Zahlen aus Blatt 2
Wenn Zahlen in richtiger Reihenfolge gefunden werden (auch mehrere)
dann in Blatt 3 angezeigt mit 3 Vor und 8 Nachnummern.
--------------------------------------------------------------------------
Hier die Makros-
Option Explicit

Sub SetStrings()
Dim rng As Range
Dim iCol As Integer
Dim lRow As Long, lRowL As Long
Dim iColT As Integer, iCount As Integer

On Error GoTo ERRORHANDLER
Application.EnableCancelKey = xlErrorHandler
Application.Calculation = xlCalculationManual

Set rng = Worksheets(2).Range("A1").CurrentRegion
iCount = rng.Rows.Count

iCol = 1
Do While WorksheetFunction.CountA(Columns(iCol)) > 0
Columns(52 + iCol).ClearContents
If Not IsEmpty(Cells(1048576, iCol)) Then
lRowL = 1048576 - iCount + 1
Else
lRowL = Cells(Rows.Count, iCol).End(xlUp).Row - iCount + 1
End If

Cells(1, 52 + iCol).FormulaR1C1 = "=RC" & CStr(iCol) & "&"";""&R[1]C" & CStr(iCol) & "&"";""&R[2]C" & CStr(iCol)
With Range(Cells(1, 52 + iCol), Cells(lRowL, 52 + iCol))
.FillDown
.Calculate
.Value = .Value
End With
iCol = iCol + 1
Loop

Call TransferData
ERRORHANDLER:
Application.Calculation = xlCalculationAutomatic
Application.StatusBar = False
End Sub
-----------------------------------------------------------------------------------
Sub TransferData()
Dim wksA As Worksheet, wksB As Worksheet
Dim rng As Range
Dim vColor As Variant
Dim lStart As Long, lEnd As Long
Dim iCol As Integer, iRow As Integer, iCount As Integer, iColT As Integer
Dim sTxt As String, sAddress As String

Set wksA = Worksheets(2)
Set wksB = Worksheets(3)

wksB.Cells.Clear

iCount = WorksheetFunction.CountA(wksA.Columns(1))
If iCount = 3 Then vColor = vbYellow Else vColor = vbCyan

For iRow = 1 To iCount
sTxt = sTxt & wksA.Cells(iRow, 1).Value & ";"
Next iRow

sTxt = Left(sTxt, Len(sTxt) - 1)
iCol = 53

Do While WorksheetFunction.CountA(Columns(iCol)) > 0
Set rng = Cells(1, iCol)
Set rng = Columns(iCol).Find( _
what:=sTxt, _
lookat:=xlWhole, _
LookIn:=xlValues, _
MatchCase:=False, _
after:=rng)

If Not rng Is Nothing Then
sAddress = rng.Address

If rng.Row < 4 Then lStart = 1 Else lStart = rng.Row - 3
If rng.Row > 1048576 - 13 Then lEnd = 1048576 Else lEnd = rng.Row + iCount + 7

iColT = WorksheetFunction.CountA(wksB.Rows(1)) + 1
wksB.Range(wksB.Cells(1, iColT), wksB.Cells(lEnd - lStart + 1, iColT)).Value = Range(Cells(lStart, iCol - 52), Cells(lEnd, iCol - 52)).Value
wksB.Range(wksB.Cells(4, iColT), wksB.Cells(4 + iCount - 1, iColT)).Interior.Color = vColor
Range(Cells(rng.Row, iCol - 52), Cells(rng.Row + iCount - 1, iCol - 52)).Interior.Color = vColor


rng.Offset(1).Select

Do
Columns(iCol).FindNext(after:=ActiveCell).Activate
If ActiveCell.Address = sAddress Then
Columns(iCol).ClearContents
Exit Do
End If
iColT = WorksheetFunction.CountA(wksB.Rows(1)) + 1

If ActiveCell.Row < 4 Then lStart = 1 Else lStart = rng.Row - 3
If ActiveCell.Row > 1048576 - 13 Then lEnd = 1048576 Else lEnd = rng.Row + iCount + 7


wksB.Range(wksB.Cells(1, iColT), wksB.Cells(lEnd - lStart + 1, iColT)).Value = Range(Cells(lStart, iCol - 52), Cells(lEnd, iCol - 52)).Value
wksB.Range(wksB.Cells(4, iColT), wksB.Cells(4 + iCount - 1, iColT)).Interior.Color = vColor

Range(Cells(ActiveCell.Row, iCol - 52), Cells(ActiveCell.Row + iCount - 1, iCol - 52)).Interior.Color = vColor
Loop

End If

Columns(iCol).ClearContents
iCol = iCol + 1
Loop

Range("A1").Select
Application.Goto wksB.Range("A1"), True
End Sub
---------------------------------------------------------
Vielleicht kann mir ja jemand weiterhelfen

lg
Andi

9 Antworten

0 Punkte
Beantwortet von m-o Profi (22.8k Punkte)
Hallo Andi,

versuche mal meine Version:
Sub suchen()

Dim lngLetzte1 As Long
Dim lngLetzte2 As Long
Dim lngLetzte3 As Long
Dim lngZeile As Long
Dim lngSpalte As Long
Dim lngSpalteL As Long
Dim wksBlatt1 As Worksheet
Dim wksBlatt2 As Worksheet
Dim wksBlatt3 As Worksheet
Dim Suchtxt As String
Dim Vgltxt As String
Dim lngZaehler As Long
Dim lngAnfang As Long
Dim lngEnde As Long
Dim lngFarbe As Long

'Bildschirmaktualisierung ausschalten:
Application.ScreenUpdating = False

'Arbeitsblätter festlegen
Set wksBlatt1 = ThisWorkbook.Worksheets(1) 'Tabelle mit den Zahlen
Set wksBlatt2 = ThisWorkbook.Worksheets(2) 'Tabelle mit den zu suchenden Zahlen
Set wksBlatt3 = ThisWorkbook.Worksheets(3) 'Tabelle in die die Suchergebnisse einfügt werden

'Anzahl der zu suchenden Zahlen ermitteln
lngLetzte2 = wksBlatt2.Cells(Rows.Count, 1).End(xlUp).Row

'in Zieltabelle für Suchergebnisse ggf. vorhandene Daten löschen
wksBlatt3.Cells.Clear

'zu suchende Zahlen in Suchtext umwandeln
For lngZeile = 1 To lngLetzte2
Suchtxt = Suchtxt & wksBlatt2.Cells(lngZeile, 1) & ";"
Next lngZeile
'letztes Semikolon abschneiden
Suchtxt = Left(Suchtxt, Len(Suchtxt) - 1)

'Im Suchblatt letzte Spalte ermitteln
lngSpalteL = wksBlatt1.Cells(1, Columns.Count).End(xlToLeft).Column

'Schleife, um alle Spalten im Suchblatt zu durchlaufen
For lngSpalte = 1 To lngSpalteL
'letzte beschriebene Zeile für Spalte ermitteln
lngLetzte1 = wksBlatt1.Cells(Rows.Count, 1).End(xlUp).Row
For lngZeile = 1 To lngLetzte1
'Variable ggf. leeren
Vgltxt = ""
'Vergleichstext generieren
For lngZaehler = 0 To lngLetzte2 - 1
Vgltxt = Vgltxt & wksBlatt1.Cells(lngZeile + lngZaehler, lngSpalte) & ";"
Next lngZaehler
Vgltxt = Left(Vgltxt, Len(Vgltxt) - 1)

'Vergleichen
If Vgltxt = Suchtxt Then
'falls Übereinstimmung dann Anfang und Ende des zu kopierenden Bereichs festlegen
lngAnfang = lngZeile - 3
lngEnde = lngZeile + 8
'Anfang und Ende prüfen, ob diese im zulässigen Bereich liegen
If lngAnfang < 1 Then lngAnfang = 1
If lngEnde > wksBlatt1.Rows.Count Then lngEnde = wksBlatt1.Rows.Count
'Zeile für das Einfärben der gefundenen Übereinstimmungen ermitteln
lngFarbe = lngZeile - lngAnfang
'Daten kopieren
With wksBlatt1
.Range(.Cells(lngAnfang, lngSpalte), .Cells(lngEnde, lngSpalte)).Copy
End With
'letzte Zeile in Einfügespalte = Suchspalte ermitteln
lngLetzte3 = wksBlatt3.Cells(Rows.Count, lngSpalte).End(xlUp).Row + 2
'Einfügezeile ggf. korrigieren
If lngLetzte3 = 3 Then lngLetzte3 = 1
'Inhalte einfügen
With wksBlatt3.Cells(lngLetzte3, lngSpalte)
.PasteSpecial Paste:=xlPasteValues
End With
Application.CutCopyMode = False
'Suchzahlen in gefundener Reihe einfärben
With wksBlatt3
.Range(.Cells(lngLetzte3 + lngFarbe, lngSpalte), .Cells(lngLetzte3 + lngFarbe + lngLetzte2 - 1, lngSpalte)).Interior.Color = vbCyan
End With
End If
Next lngZeile
Next lngSpalte

'Auf Blatt 3 mit den gefundenen Daten wechseln
With wksBlatt3
.Activate
.Range("A1").Select
End With

'Bildschirmaktualisierung einschalten:
Application.ScreenUpdating = True

End Sub

Die übereinstimmenden Zahlenreihen werden immer in die Spalten eingetragen, in der sie auch gefunden wurden.
Deine zu suchenden Zahlen müssen in Spalte A in deinem 2. Blatt stehen. Die Anzahl ist dabei egal.

Gruß

M.O.
0 Punkte
Beantwortet von
Sehr geehrter Herr M.O

Ich muss mich 1000-fach bedanken es läuft wie ich das vom "alten" Makro gewohnt war.

2 Fragen hätte ich noch.

Da wir sehr viele Zahlen zum suchen haben (Firmenbedingt) sehe ich keinen Fortschrittsbalken
oder etwas ähnliches.(War aber beim alten Makro auch so)

Es kommt nur die Sanduhr und nach einer Zeit werden dann die Zahlen angezeigt die gefunden wurden.
Kann man den Status der Bearbeitung Anzeigen lassen um zu überprüfen ob das Makro noch läuft oder vielleicht abgestürzt ist
bei sovielen Zahlen kann das finden ja etwas Dauern und man weiss ja nicht obs noch läuft.

Und kann man das Makro mit einem Tastenkürzel oder Ähnlichem abbrechen wenn einmal gestartet?

Aber eins vorweg das Makro läuft Perfekt und das andere wäre nur noch die Draufgabe.

mfg
Andi
0 Punkte
Beantwortet von m-o Profi (22.8k Punkte)
Hallo Andi,

auf die Anrede "Herr" kannst du im Forum verzichten. Hier wird nur geduzt ;-).

Für einen Fortschritsbalken gibt es mehrere Möglichkeiten. Ich habe dir den Code so geändert, dass im Statusfenster unten angezeigt, welche Spalte er durchsucht:

Sub suchen()

Dim lngLetzte1 As Long
Dim lngLetzte2 As Long
Dim lngLetzte3 As Long
Dim lngZeile As Long
Dim lngSpalte As Long
Dim lngSpalteL As Long
Dim wksBlatt1 As Worksheet
Dim wksBlatt2 As Worksheet
Dim wksBlatt3 As Worksheet
Dim Suchtxt As String
Dim Vgltxt As String
Dim lngZaehler As Long
Dim lngAnfang As Long
Dim lngEnde As Long
Dim lngFarbe As Long

'Bildschirmaktualisierung ausschalten:
Application.ScreenUpdating = False

'Arbeitsblätter festlegen
Set wksBlatt1 = ThisWorkbook.Worksheets(1) 'Tabelle mit den Zahlen
Set wksBlatt2 = ThisWorkbook.Worksheets(2) 'Tabelle mit den zu suchenden Zahlen
Set wksBlatt3 = ThisWorkbook.Worksheets(3) 'Tabelle in die die Suchergebnisse einfügt werden

'Anzahl der zu suchenden Zahlen ermitteln
lngLetzte2 = wksBlatt2.Cells(Rows.Count, 1).End(xlUp).Row

'in Zieltabelle für Suchergebnisse ggf. vorhandene Daten löschen
wksBlatt3.Cells.Clear

'zu suchende Zahlen in Suchtext umwandeln
For lngZeile = 1 To lngLetzte2
Suchtxt = Suchtxt & wksBlatt2.Cells(lngZeile, 1) & ";"
Next lngZeile
'letztes Semikolon abschneiden
Suchtxt = Left(Suchtxt, Len(Suchtxt) - 1)

'Im Suchblatt letzte Spalte ermitteln
lngSpalteL = wksBlatt1.Cells(1, Columns.Count).End(xlToLeft).Column

'Schleife, um alle Spalten im Suchblatt zu durchlaufen
For lngSpalte = 1 To lngSpalteL
'Meldung in Statusbar schreiben, welche Spalte durchsucht wird
Application.StatusBar = "Spalte " & lngSpalte & " von " & lngSpalteL & "wird durchsucht"
'letzte beschriebene Zeile für Spalte ermitteln
lngLetzte1 = wksBlatt1.Cells(Rows.Count, 1).End(xlUp).Row
For lngZeile = 1 To lngLetzte1
'Variable ggf. leeren
Vgltxt = ""
'Vergleichstext generieren
For lngZaehler = 0 To lngLetzte2 - 1
Vgltxt = Vgltxt & wksBlatt1.Cells(lngZeile + lngZaehler, lngSpalte) & ";"
Next lngZaehler
Vgltxt = Left(Vgltxt, Len(Vgltxt) - 1)

'Vergleichen
If Vgltxt = Suchtxt Then
'falls Übereinstimmung dann Anfang und Ende des zu kopierenden Bereichs festlegen
lngAnfang = lngZeile - 3
lngEnde = lngZeile + 8
'Anfang und Ende prüfen, ob diese im zulässigen Bereich liegen
If lngAnfang < 1 Then lngAnfang = 1
If lngEnde > wksBlatt1.Rows.Count Then lngEnde = wksBlatt1.Rows.Count
'Zeile für das Einfärben der gefundenen Übereinstimmungen ermitteln
lngFarbe = lngZeile - lngAnfang
'Daten kopieren
With wksBlatt1
.Range(.Cells(lngAnfang, lngSpalte), .Cells(lngEnde, lngSpalte)).Copy
End With
'letzte Zeile in Einfügespalte = Suchspalte ermitteln
lngLetzte3 = wksBlatt3.Cells(Rows.Count, lngSpalte).End(xlUp).Row + 2
'Einfügezeile ggf. korrigieren
If lngLetzte3 = 3 Then lngLetzte3 = 1
'Inhalte einfügen
With wksBlatt3.Cells(lngLetzte3, lngSpalte)
.PasteSpecial Paste:=xlPasteValues
End With
Application.CutCopyMode = False
'Suchzahlen in gefundener Reihe einfärben
With wksBlatt3
.Range(.Cells(lngLetzte3 + lngFarbe, lngSpalte), .Cells(lngLetzte3 + lngFarbe + lngLetzte2 - 1, lngSpalte)).Interior.Color = vbCyan
End With
End If
Next lngZeile
Next lngSpalte

'Auf Blatt 3 mit den gefundenen Daten wechseln
With wksBlatt3
.Activate
.Range("A1").Select
End With

Application.StatusBar = False

'Bildschirmaktualisierung einschalten:
Application.ScreenUpdating = True

End Sub


Die andere Möglichkeit wäre eine entsprechende Userform in die Datei einzubauen, die dann während des Makros eingeblendet wird und damit besser sichtbar ist, als die Info im Statusfenster.

Ein laufendes Makro kann mit der Tastenkombination <Strg> + <Pause|Untbr> abbrechen.

Die Tastenkombination kannst du selbst zuweisen. Gehe dazu in das Menüband Entwicklertools - Makros und wähle im sich öffnenden Fenster das Makro aus. Klicke auf Optionen. Im nächsten Fenster kannst du dann eine Tastenkombination für das Makro festlegen.
Hier gibt es dazu eine bebilderte Anleitung: KLICK MICH!


Gruß

M.O.
0 Punkte
Beantwortet von
Guten Tag M.O

also ich kann mich nur nochmals Bedanken du hast uns viele Schwierigkeiten und Ärger erspart also Hut ab.

Jetzt eine rein technische Frage
Da wir als kleines Unternehmen schon zig Millionen an Daten von unseren Kunden im Execl gespeichert haben
und es stetig mehr werden dauert das suchen natürlich seine Zeit
Zu Beginn erschien uns Excel als beste Lösung da aber die Daten immer mehr werden weiss ich nicht mehr.
Ist das überhaupt Sinnvoll soetwas im Excel zu machen?

Da du das Makro kennst und weisst was es tun soll meine Frage.
Kann man den Suchprozess irgenwie Beschleunigen oder spürbar verbessern
Nicht falsch verstehen ich bin mit deinem Makro Überglücklich da wir weiter Arbeiten können, aber der Speedfaktor
wird immer mehr zum Zeitproblem.
Hast du vielleicht eine Idee wie man das schneller Lösen kann?

Lg
Andi
0 Punkte
Beantwortet von m-o Profi (22.8k Punkte)
Hallo Andi,

Excel ist eigentlich nicht für große Datenmengen gemacht. Da ist Access oder ggf. eine andere Lösung besser geeignet.
Ich habe das Makro noch einmal etwas überarbeitet. Schau mal, ob es etwas schneller läuft.

Sub suchen2()

Dim lngLetzte1 As Long
Dim lngLetzte2 As Long
Dim lngLetzte3 As Long
Dim lngZeile As Long
Dim lngSpalte As Long
Dim lngSpalteL As Long
Dim wksBlatt1 As Worksheet
Dim wksBlatt2 As Worksheet
Dim wksBlatt3 As Worksheet
Dim lngZaehler As Long
Dim lngAnfang As Long
Dim lngEnde As Long
Dim lngFarbe As Long
Dim arrSuch() As Variant
Dim i As Long

'Bildschirmaktualisierung ausschalten:
Application.ScreenUpdating = False

'Arbeitsblätter festlegen
Set wksBlatt1 = ThisWorkbook.Worksheets(1) 'Tabelle mit den Zahlen
Set wksBlatt2 = ThisWorkbook.Worksheets(2) 'Tabelle mit den zu suchenden Zahlen
Set wksBlatt3 = ThisWorkbook.Worksheets(3) 'Tabelle in die die Suchergebnisse einfügt werden

'Anzahl der zu suchenden Zahlen ermitteln
lngLetzte2 = wksBlatt2.Cells(Rows.Count, 1).End(xlUp).Row

'Array Re-Dimensionieren (fängt mit 0 an) und Zahlen in Array schreiben
ReDim arrSuch(lngLetzte2 - 1)
arrSuch = wksBlatt2.Range(Cells(1, 1), Cells(lngLetzte2, 1))

'in Zieltabelle für Suchergebnisse ggf. vorhandene Daten löschen
wksBlatt3.Cells.Clear

'Im Suchblatt letzte Spalte ermitteln
lngSpalteL = wksBlatt1.Cells(1, Columns.Count).End(xlToLeft).Column

'Schleife, um alle Spalten im Suchblatt zu durchlaufen
For lngSpalte = 1 To lngSpalteL
'Meldung in Statusbar schreiben, welche Spalte durchsucht wird
Application.StatusBar = "Spalte " & lngSpalte & " von " & lngSpalteL & "wird durchsucht"
'letzte beschriebene Zeile für Spalte ermitteln
lngLetzte1 = wksBlatt1.Cells(Rows.Count, 1).End(xlUp).Row
For lngZeile = 1 To lngLetzte1
'Zaehler auf Null setzen
lngZaehler = 0
'Vergleich
For i = 1 To lngLetzte2
If wksBlatt1.Cells(lngZeile + i - 1, lngSpalte) = arrSuch(i, 1) Then
lngZaehler = lngZaehler + 1
Else
Exit For
End If
Next i
'Falls Übereinstimmung, dann kopieren
If lngZaehler = lngLetzte2 Then
'falls Übereinstimmung dann Anfang und Ende des zu kopierenden Bereichs festlegen
lngAnfang = lngZeile - 3
lngEnde = lngZeile + 8
'Anfang und Ende prüfen, ob diese im zulässigen Bereich liegen
If lngAnfang < 1 Then lngAnfang = 1
If lngEnde > wksBlatt1.Rows.Count Then lngEnde = wksBlatt1.Rows.Count
'Zeile für das Einfärben der gefundenen Übereinstimmungen ermitteln
lngFarbe = lngZeile - lngAnfang
'Daten kopieren
With wksBlatt1
.Range(.Cells(lngAnfang, lngSpalte), .Cells(lngEnde, lngSpalte)).Copy
End With
'letzte Zeile in Einfügespalte = Suchspalte ermitteln
lngLetzte3 = wksBlatt3.Cells(Rows.Count, lngSpalte).End(xlUp).Row + 2
'Einfügezeile ggf. korrigieren
If lngLetzte3 = 3 Then lngLetzte3 = 1
'Inhalte einfügen
With wksBlatt3.Cells(lngLetzte3, lngSpalte)
.PasteSpecial Paste:=xlPasteValues
End With
Application.CutCopyMode = False
'Suchzahlen in gefundener Reihe einfärben
With wksBlatt3
.Range(.Cells(lngLetzte3 + lngFarbe, lngSpalte), .Cells(lngLetzte3 + lngFarbe + lngLetzte2 - 1, lngSpalte)).Interior.Color = vbCyan
End With
End If

Next lngZeile
Next lngSpalte

'Auf Blatt 3 mit den gefundenen Daten wechseln
With wksBlatt3
.Activate
.Range("A1").Select
End With

Application.StatusBar = False

'Bildschirmaktualisierung einschalten:
Application.ScreenUpdating = True

End Sub

Gruß

M.O.
0 Punkte
Beantwortet von
Hi M.O

Ich bekomme in der Array Zeile einen Laufzeitfehler 1004

Die Methode Range ist Fehlgeschlagen.

Kannst du dir das bitte nochmal anschauen

lg
Andi
0 Punkte
Beantwortet von m-o Profi (22.8k Punkte)
Hallo Andi,

ersetze die Zeile
arrSuch = wksBlatt2.Range(Cells(1, 1), Cells(lngLetzte2, 1))

durch
With wksBlatt2
arrSuch = .Range(.Cells(1, 1), .Cells(lngLetzte2, 1))
End With

Gruß

M.O.
0 Punkte
Beantwortet von
Hi M.O

Wow das ist mal ein Geschwindigkeitsunterschied

Altes Makro
10 Millionen Zahlen
Suchzeit: 6 Minuten

Neues Makro
10 Millionen Zahlen
Suchzeit: 1 Minute

Ich schätze da ist das Optimum erreicht, du bist echt der Hammer

Da kann ich den Umstieg auf Access eine Zeit lang verschieben.

Nochmals Vielen Dank für deine Hilfe

lg
Andi
0 Punkte
Beantwortet von m-o Profi (22.8k Punkte)
Hallo Andi,

freut mich, dass das Makro so funktioniert, wie du willst.

Gruß

M.O.
...