gerry56
Goto Top

Vba. if then schleife stürzt nach etlichen durchgängen ab

Hallo an alle Experten für VBA-Makro!

Ich bin kein Spezialist für VBA und habe deshalb ein riesen Problem.
Ich habe den Quellcode schon mehrmals auf Fehler untersucht und stundenlang im Internet gegoogelt.

Problem ist folgendes.

Ich habe zwei Tabellen
Tabelle 1 mit 3800 Zeilen (Datensätzen)
Tabelle 2 mit 3100 Zeilen (Datensätzen)

Problem ist folgendes.

Ich habe zwei Tabellen
Tabelle 1 mit 3800 Zeilen (Datensätzen)
Tabelle 2 mit 3100 Zeilen (Datensätzen)

Nun will ich aus beiden Tabellen eine Tabelle erstellen, worin sich alle Datensätze befinden, die sowohl in Tabelle 1 als auch in Tabelle 2 vorhanden sind.

Ich lese zuerst die Daten aus Tabelle 2 ein, und suche ab Zeile 2 in Tabelle 1.
Wird der Datensatz in Tabelle 1 gefunden, kopiere ich diesen in Tabelle 3 und lösche ihn danach in Tabelle 1.
Nun suche ich ab der nächsten Zeile in Tabelle 1 weiter, ob es diesen Datensatz nochmals gibt.
Nachdem alle Datensätze in Tabelle 1 durchsucht wurden, wird kontrolliert, ob der gesuchte Datensatz in Tabelle 1 gefunden wurde.
Wenn ja, wird dieser Datensatz auch in Tabelle 2 gelöscht.

Alle drei Tabellen befinden sich in der gleichen Arbeitsmappe.

Nun, das Macro funktioniert langsam, aber gut.
LEIDER schmiert das Macro nach zirka 1900 Datensätzen ab.
Fehler 1004.

Der Hinweis, in Excel den Punkt "Zugriff auf Visual Basic-Project vertrauen" anklicken, nützt natürlich nichts.

Keine Zelle ist schreibgeschützt.


Teile ich die Tabelle2 mit den Quelldatensätzen, und vergleiche nur 1000, dann gibt es keinen Absturz.
Danach kann ich die nächsten 1000 zu vergleichenden Datensätze nehmen (inklusive dem Datensatz, der vorher 1900 war), und wieder ohne Absturz vergleichen.

Ich habe auch schon versucht, in der kompletten Tabelle 2 (mit 3800 Zeilen) nicht alle, sondern zuerst nur 1500 Datensätze zu vergleichen.
Ergebnis - KEIN Absturz
Danach ändere ich die Einstellungen (Beginn der ersten Zeile für Zieltabelle 3, die Anzahl der Datensätze in Vergleichstabelle 1) und starte das Makro wieder, wobei ich sicherheitshalber nur 200 Datensätze vergleiche.

Auf diese Art kann ich die komplette Tabelle ohne Absturz durchsuchen.
Nun, das ist erstens RECHT MÜHSAM und LANGWIERIG, und AUCH NICHT DER SINN EINES MACROS.


Da ich auf diese Art und Weise einen Programmierfehler ausschließen konnte, und es auch nirgends einen Typenkonflikt geben kann, frage ich mich, ob es IRGENDWO ein Speicherproblem mit Excel geben kann.
Ich kann auch ausschließen, das es am Betriebssystem oder am Arbeitsspeicher liegt.

Ich habe dieses Problem auf meinem Stand-PC mit Win-XP SP3 und 2GB RAM, DualCore Prozessor mit 3,33GHz
und auf meinem Laptop mit Pentium Dual-Core CPU T4500, 2,30GHz und 4GB RAM.


Bitte um Hilfe der Spezialisten
Danke im voraus
Gerry

Content-ID: 184366

Url: https://administrator.de/contentid/184366

Ausgedruckt am: 19.11.2024 um 17:11 Uhr

NetWolf
NetWolf 02.05.2012 um 16:18:50 Uhr
Goto Top
Moin Moin,

nachdem ich so die Hälfte durchgelesen hatte und mir schon überlegte, dass man das mit z.B. Access ganz einfach lösen könnte, fand ich heraus, dass du von Excel sprichst. Leider ist die Version so geheim, dass Hilfe bzw. Aussagen hinsichtlich Abstürze etc. zumindest von mir nicht möglich sind.

Ich kann auch ausschließen, das es am Betriebssystem oder am Arbeitsspeicher liegt.
mutig, das sind zwei Aussagen, die ich nie und nimmer so behaupten würde!

ym2c


/edit
btw umständlicher geht es wohl nicht? Überdenke bitte mal dein Konzept.
/edit


Grüße aus Rostock
Wolfgang
(Netwolf)
76109
76109 02.05.2012 um 16:23:46 Uhr
Goto Top
Hallo gerry56!

Da Du keinen Code gepostet hast, vermute ich mal, dass Deine Schleife abschmiert, weil der Schleifenzähler beim Löschen von Zeilen nicht entsprechend angepasst wird.

Gruß Dieter
gerry56
gerry56 02.05.2012 um 18:37:10 Uhr
Goto Top
Bitte um Entschuldigung

Habe es ganz vergessen, anzugeben.
Auf dem Stand-PC befindet sich Win-XP mit SP3, das habe ich geschrieben.

Auf dem Laptop befindet sich Win-7 Ultima 32 Bit.

Da der Fehler sowohl auf dem Stand-PC mit XP als auch auf dem Laptop mit Win-7 auftritt, wage ich zu vermuten, daß es nicht am BS liegt.
Da auf dem Stand-PC 2GB RAM sind, und der Laptop mit 4GB RAM bestückt ist, schließe ich auch den RAM als Fehlerquelle aus.
Auf beiden PC's befindet sich MS Office 2003.

Das VBA-Macro wurde direkt in der Arbeitsmappe (XLS.Datei) geschrieben.

Hier nochmals der Hinweis, daß ich kein Programmierprofi bin.
Nun der Quellcode
'  
Dim Quellensenderzahl As Integer
Dim suchsenderanzahl As Integer
Dim endzeile As Integer
Dim quellsenderanzahl As Integer
Dim suchdatensatz As Integer
Dim quellzei As Integer
Dim zielzei As Integer
Dim testzeile As Integer
Dim nichtgef As Integer
Dim i As Integer
Dim suchealles1 As String
Dim suchealles2 As String
Dim sucheSender1 As String
Dim sucheSender2 As String
Dim lueschtest As String
Dim sucheFrequUndSID1 As String
Dim sucheFrequUndSID2 As String
Dim sucheFrequenz1 As String
Dim sucheFrequenz2 As String
Dim sucheSID1 As String
Dim sucheSID2 As String

' **********************************************************************************************************  

Quellensenderzahl = 3119  'Zeilennummer der letzten Zeile für Sender, die zu vergleichen sind. Senderanzahl um 1 kleiner  
suchsenderanzahl = 3779  'Zeilennummer der letzten Zeile in Vergleichstabelle 1 , Senderanzahl um 1 kleiner  

' **********************************************************************************************************  

endzeile = suchsenderanzahl      ' Zeilenanzahl variabel in Vergleichstabelle 1 mit 3779 Sendern  
quellsenderanzahl = Quellensenderzahl      ' Zeilenanzahl variabel in Quelltabelle 2 mit 3119 Sendern  
suchdatensatz = 0
quellzei = 2
zielzei = 2
testzeile = 2
nichtgef = 0

For quellzei = 2 To quellsenderanzahl
i = 2
'Einlesen Suchwert aus Quelltabelle 2  
suchdatensatz = suchdatensatz + 1

suchealles1 = ""  
suchealles2 = ""  

Sheets(i).Select    'Quelltabelle 2 mit 3119 Sendern  
suchealles1 = Range("A" & CStr(quellzei)) & Range("B" & CStr(quellzei)) & Range("C" & CStr(quellzei)) & Range("D" & CStr(quellzei)) _  
& Range("E" & CStr(quellzei)) & Range("F" & CStr(quellzei)) & Range("G" & CStr(quellzei)) & Range("H" & CStr(quellzei)) & Range("I" & CStr(quellzei)) _  
& Range("J" & CStr(quellzei)) & Range("K" & CStr(quellzei)) & Range("L" & CStr(quellzei)) & Range("M" & CStr(quellzei)) & Range("N" & CStr(quellzei))  
' Alles bei Quelle und Ziel Ident  
sucheSender1 = Range("A" & CStr(quellzei)) & Range("B" & CStr(quellzei))  
' Nur Sendername  

For zielzei = 2 To endzeile
i = 1     'Vergleichstabelle 1 mit 3779 Sendern  
Sheets(i).Select

suchealles2 = Range("E" & CStr(zielzei)) & Range("F" & CStr(zielzei)) & Range("G" & CStr(zielzei)) & Range("H" & CStr(zielzei)) _  
& Range("I" & CStr(zielzei)) & Range("J" & CStr(zielzei)) & Range("K" & CStr(zielzei)) & Range("L" & CStr(zielzei)) & Range("M" & CStr(zielzei)) _  
& Range("N" & CStr(zielzei)) & Range("O" & CStr(zielzei)) & Range("P" & CStr(zielzei)) & Range("Q" & CStr(zielzei)) & Range("R" & CStr(zielzei))  
' Alles bei Quelle und Ziel Ident  

sucheSender2 = Range("E" & CStr(zielzei)) & Range("F" & CStr(zielzei))  
' Nur Sendername  


******************************Klicke ich nach dem Absturz Debug an, wird diese Stelle markiert*********************************************
Range("Z1").Select  
ActiveCell.FormulaR1C1 = "Durchgang 1 von 3. Vergleiche " & CStr(suchdatensatz) & " von " & CStr(Quellensenderzahl - 1) & " (aktuell nur mehr " _  
& CStr(quellsenderanzahl - 1) & ") mit " & CStr(zielzei - 1) & " von " & CStr(suchsenderanzahl - 1) & " (aktuell nur mehr " & CStr(endzeile - 1) _  
& "). Ident sind " & CStr(testzeile - 2) & ". NICHT GEFUNDEN " & CStr(nichtgef) & ". " & sucheSender1 & " zu " & sucheSender2 & ".    "  

******************************Klicke ich nach dem Absturz Debug an, wird diese Stelle markiert*********************************************

    
    If suchealles1 = suchealles2 Then
       Range("Z" & CStr(zielzei)).Select     'Vergleichstabelle 1 mit 3779 Sendern  
       ActiveCell.FormulaR1C1 = "IDENT" & ". Zeile " & CStr(quellzei)   'Schreibe IDENT in Zelle Z## in Vergleichstabelle 1  
       Rows(CStr(zielzei) & ":" & CStr(zielzei)).Select                 ' Markiere Zeile mit gefundenem Sender in Vergleichstabelle 1  
       Selection.Copy
       Sheets("Ziel").Select   'Schreibe gefundene Zeile aus Vergleichstabelle 2 in die ZIELTABELLE 3 (das ERGEBNIS)  
       Rows(CStr(testzeile) & ":" & CStr(testzeile)).Select  
       ActiveSheet.Paste
       testzeile = testzeile + 1   'Erhöhe Zeilenwert um 1 für die Zieltabelle  
       i = 1
       Sheets(i).Select   'Lösche den gefundenen Sender in Vergleichstabelle 1 mit 3779 Sendern  
       Application.CutCopyMode = False
       Selection.Delete Shift:=xlUp
       endzeile = endzeile - 1    'Setze Zähler für Vergleichstabelle 1 um 1 niedriger, da jetzt 1 Datensatz weniger  
       zielzei = zielzei - 1      'Setze Zähler für Suchzeile in Vergleichstabelle 1 um 1 niedriger, da jetzt 1 Datensatz weniger  
       i = 2      'Markiere in Quelltabell 2 mit 3119 Sendern  
       Sheets(i).Select
       Range("V" & CStr(quellzei)).Select  
       ActiveCell.FormulaR1C1 = "IDENT"   'Schreibe IDENT in Zelle V## in Quelltabelle 2  
    End If
       If zielzei = endzeile Then
          i = 2      'Markiere in Quelltabell 2 mit 3119 Sendern  
          Sheets(i).Select
          lueschtest = Range("V" & CStr(quellzei))      'Wenn der letzte Vergleichsdatensatz in Vergleichstabelle 1 gelesen wurde  
          If lueschtest = "IDENT" Then                  ' Überprüfung in Quelltabelle 1, ob dieser Sender als gefunden (IDENT) markiert ist.  
             Rows(CStr(quellzei) & ":" & CStr(quellzei)).Select  
             Application.CutCopyMode = False            ' Wenn Sender in Quelltabelle 1 als IDENT markiert ist, Datensatz aus Quelltabelle löschen.  
             Selection.Delete Shift:=xlUp
             quellsenderanzahl = quellsenderanzahl - 1
             quellzei = quellzei - 1
          Else
             nichtgef = nichtgef + 1
          End If
       End If
       
       If zielzei > endzeile Then
          Exit For
       End If

   Next zielzei
   If quellzei > quellsenderanzahl Then
      Exit For
   End If
   If quellsenderanzahl < 1 Then
      Exit For
   End If

Next quellzei


Die Anzeige in Zelle Z1 habe ich deshalb, daß ich sehe, wie weit die Bearbeitung ist.
Genau an dieser Stelle schwirrt das Macro nach zirka 1900 Zeilen (Datensätzen) sowohl in Win-7 als auch in Win-XP ab.

Ich hoffe, daß ich nun alle wichtigen Infos bekannt gegeben habe.

Danke im voraus
Gerry

[Edit Biber] Codeformatierung nachgetragen[/Edit]
NetWolf
NetWolf 02.05.2012 um 22:21:51 Uhr
Goto Top
Moin Moin,

du könntest diesen Bandwurmsatz deaktivieren und testen, ob der Code dann durchläuft.
Du könntest dir die einzelnen Werte im Debugmodus ansehen um festzustellen, welcher (falsche) Wert dann den Absturz verursacht.

Tipp: teile den Bandwurmsatz mal in einzelne Teil-Sätze auf.

Die Office 2003 Version war bekannt für Ihre Speicherlecks bei größeren Aktionen. Die Problematik der Speicherlecks hat sich durch alle Programme des Paketes gezogen.
Selbst die angebotenen Servicepacks haben dieses Problem imho nicht behoben.

Grüße aus Rostock
Wolfgang
(Netwolf)
mak-xxl
mak-xxl 02.05.2012 um 23:48:41 Uhr
Goto Top
Moin Gerry,

da in Zeile 70 nicht wirklich eine Formel eingetragen wird, könntest Du als ersten Versuch dort
Selection.Value = ...
eintragen.

Wenn Du 'Debug' anklicken kannst, steht auf dieser Form eine Fehlermeldung. die Du einmal posten könntest.

Freundliche Grüße von der Insel - Mario
gerry56
gerry56 04.05.2012 um 14:17:22 Uhr
Goto Top
Vorerst bitte einmal um Entschuldigung, daß ich mich jetzt erst wieder melde.
Ich mußte leider wegfahren und habe unabhängig von Eurem Hinweis die optisch Anzeige für mich in Zelle Z1 (Quellcode Zeile 70) weggelassen.

Siehe da, sowohl auf dem Laptop mit Win7, als auch auf dem PC mit Win-XP läuft alles Problemlos ohne Absturz.

Für mich ist es eigentlich unlogisch, daß das Progi nach 1900 Durchgängen in dieser Zeile abstürzt, da ja in dieser Zeile nichts besonderes gemacht wird.
In dieser Zeile wird ja nur für den Benutzer angezeigt, wie weit die Bearbeitung erledigt ist.
Die Variablen der Anzeige werden ja an anderer Stelle gefüllt, bzw. errechnet.

Wo liegt hier das Problem und wie kann man es umgehen?

Danke im voraus

Gerry
mak-xxl
mak-xxl 04.05.2012 um 14:28:30 Uhr
Goto Top
Moin Gerry,

ich hatte es oben schon geschrieben - poste bitte den Wortlaut der Meldung, die den 'Absturz' anzeigt. Ebenfalls stand dort ein klarer Hinweis auf Änderung - ein weglassen der Zeile bringt Dich (uns) der Lösung wohl nicht näher.
Vielleicht könntest Du den Wünschen der Hilfeleistenden einmal entsprechen - das wäre zielführender und zeitsparender für uns alle.

BTW: Was für Dich unlogisch erscheinen mag, hat durchaus realen und logischen Hintergrund - wenn Du also einen zusammengesetzten String als Formel in eine Zelle schreiben willst, kann genau dieser String erst ab/in der 1.900. Zeile einen Wert annehmen, den Excel (als Formel) moniert ... Selbst die Berechnungen in dem fraglichen Konstrukt bieten genug Potenzial für Bereichsfehler in Variablen.

Ganz in diesem Sinne, freundliche Grüße von der Insel - Mario
netzwerkknecht
netzwerkknecht 04.05.2012 um 14:33:11 Uhr
Goto Top
Wahrscheinlich stammt die Rohfassung vom Makrorekorder, und der Rest ist in mühsamer Suchmaschinen-Kleinarbeit entstanden? Ich würde die gesamten .Select-, Selection und Active*-Konstruktionen vollständig eliminieren, da knallt Dir wahrscheinlich das Timing um die Ohren - sowas braucht man nur in Situationen, in denen der Anwender Eingriff nehmen soll. Hier sind Quellen und Ziele ja jeweils klar bekannt, weil selber ermittelt.

Übrigens hängen Deine jeweils kombinierten Ranges alle vollständig zusammen - da kannst Du einfach direkt einen einzigen Range erstellen (z.B. Range("A" & CStr(quellzei), "N" & CStr(quellzei)) statt Range("A" & CStr(quellzei)) & .... & Range("N" & CStr(quellzei))), und Du solltest weggehen von diesen String-Geschichten und hin zu numerischen Zeilen- und Spaltenangaben (über Cells). Bitte auch nicht Formula verwenden, wenn Value gemeint ist. Das aber nur nebenbei, es liegt da schon ziemlich viel (auch anderes) im Argen. Schauen wir aber zunächst einfach mal, dass es überhaupt läuft.

netzwerkknecht auf Windows Intune: http://bit.ly/wide12hp
gerry56
gerry56 04.05.2012 um 18:33:30 Uhr
Goto Top
Da bin ich wieder.

1.) Der Tip von Wolfgang (Netwolf) hat den Fehler eindeutig auf Zeile 70 eingegrent, da durch entfernen dieser Zeile das Macro auf Win-XP und Win-7 absturzfrei läuft.

2.) Lasse das Macro momentan mit der Änderung von Mario (02.05.2012) laufen.

Das heißt, ich habe die Zeile 70 von
ActiveCell.FormulaR1C1 = ...
auf
Selection.Value = ...
geändert.

3.) Ich werde nun gleichzeitig auf dem 2. Computer das Macro in der Erstversion laufen lassen, und die genaue Fehlermeldung aufschreiben.

4.) Das einzige, das vom Macrorecorder stammt, ist die Werteingabe in eine Zelle.
Dies habe ich vor langer, langer Zeit einmal als Macro aufgezeichnet, und den Quelltext übernommen.

Den Rest habe ich selbst zusammengeflickt.
Beim Zusammenflicken habe ich meine Uraltkenntnisse von BASIC und Clipper Summer 87 aus der DOS-Zeit (1987 - 1992) zu Hilfe genommen.
Der Rest suche in der Hilfe.


Ich werde mich gleich wieder melden, sobald auf einem der Computer eine Meldung erscheint

Danke
Gerry
netzwerkknecht
netzwerkknecht 04.05.2012 um 23:37:30 Uhr
Goto Top
Zitat von @gerry56:
Da bin ich wieder.

"Moin!" face-smile


1.) Der Tip von Wolfgang (Netwolf) hat den Fehler eindeutig auf Zeile 70 eingegrent

Nicht ganz - das hattest Du tatsächlich selber getan.


da durch entfernen dieser Zeile das Macro auf Win-XP und Win-7 absturzfrei läuft.

Defekte Funktionalität zu entfernen ist immer eine Lösung - wenn man die Funktionalität nicht braucht.

Man fragt sich dann natürlich, warum man zuvor irrig glaubte, die Funktionalität zu brauchen.

Eine andere Motivationslage könnte durchaus auch dazu führen, die Funktionalität zum Arbeiten zu bringen.


Das heißt, ich habe die Zeile 70 von
ActiveCell.FormulaR1C1 = ...
auf
Selection.Value = ...
geändert.

Für den Privatgebrauch - warum nicht.

netzwerkknecht auf Windows Intune: http://bit.ly/wide12hp
gerry56
gerry56 05.05.2012 um 11:29:42 Uhr
Goto Top
Ein schönes Wochenende.

Soeben wurde ein Testdurchgang fertig.

Leider hat die Änderung von
ActiveCell.FormulaR1C1 = ...
auf
Selection.Value = ...
keine Verbesserung gebracht.

Solange das Makro funktionierte, wurde in Zelle Z1 der Bearbeitungsfortschritt angezeigt.

Nach 1719 Schleifendurchgängen kam es wieder zum Absturz.
KEINE Anzeige in Zelle Z1

Ein Fenster mit der Überschrift "Microsoft Visual Basic" erscheint.
Der Fehlertext lautet.

Laufzeitfehler 1004
Anwendungs oder objectdefinierter Fehler.

Die Schaltfläschen "Beenden" "Debuggen" "Hilfe" werden angezeigt.

Betätige ich die Schaltfläche "Debuggen", verschwindet das Fehlerfenster und der Quelltext wird angezeigt.
Im Quelltext wird die Zeile 70, wo der Bearbeitungsfortschritt in Zelle Z1 angezeigt werden soll, gelb markiert.


Netzwerkknecht schrieb, daß ich alle Ranges zusammenhängen kann.
Dies werde ich nun als nächstes Testen.

In diesem zusammenhang habe ich eine Frage.

Netzwerkknecht schrieb auch, daß ich zu numerischen Zeilen- und Spaltenangaben wechseln soll.
Wo liegt da der Unterschied für VBA?

Danke
Gerry
mak-xxl
mak-xxl 05.05.2012 um 11:41:31 Uhr
Goto Top
Moin Gerry,

mit der Umstellung auf 'numerische' Werte ist gemeint, eine Zelle über Zeilen- und Spaltennummer anzusprechen, da hierbei Referenzumrechnungen ('A' -> 1 oder 'Z' -> 26) wegfallen.

In Deinem Beispiel bedeutet das (u.a.), Zeile 69 ersatzlos zu eliminieren und in Zeile 70 zu schreiben:
Cells(1, 26).Value = ...

Zusätzlich solltest Du prüfen, welche Zeilen in Quelle und Ziel beim 1.719. Durchlauf tatsächlich referenziert werden, eventuell steckt dort auch noch ein (Format-)Fehler. Damit ein Durchlauf zur Fehlersuche schneller geht, kannst Du die Startzeilen hochsetzen (Zeile 34+35).

Ebenfalls ein schönes Wochenende und freundliche Grüße von der Insel - Mario
gerry56
gerry56 05.05.2012 um 12:23:13 Uhr
Goto Top
Malzeit.

1.) Wenn ich das ganze richtig verstehe, arbeitet VBA in wirklichkeit mit Zeilennummern und Spaltennummern.
Verwende ich im Quelltext Range("a" & CStr(quellzei)), so vergewaltige ich VBA dazu, das ganze intern in Zeilennummern und Spaltennummern umzurechnen.
Daher benötigt das Progi mehr Arbeitsspeicher und wird langsamer.

Ist meine Vermutung richtig?

2.) Ich wollte den Rat befolgen, und alle Ranges in einem zusammenfassen.
suchealles1 = Range("A" & CStr(quellzei), "B" & CStr(quellzei), "C" & CStr(quellzei), "D" & CStr(quellzei))

Leider kommt sofort bei der Ausführung des Makros folgende Fehlermeldung

Fehler beim Kompilieren:
Falsche Anzahl an Argumenten oder ungültige Zuweisung zu einer
Eigenschaft

Das Wort "RANGE" wird blau hinterlegt.

Verknüpfe ich nur zwei Zellen
suchealles1 = Range("A" & CStr(quellzei), "B" & CStr(quellzei))
wird KEIN FEHLER angezeigt.

Vielleicht ist es für Euch wichtig.
Das Makro starte ich immer aus dem "Visual Basic-Editor " über "Ausführen" "Sub/UserForm ausführen".
mak-xxl
mak-xxl 05.05.2012 um 12:34:25 Uhr
Goto Top
Moin Gerry,

1. Deine Vermutung ist richtig - es gibt aber noch mehr Range-Probleme, - später ...

2. Diese Suchbereiche lässt Du vorerst unangetastet - ersteinmal geht es um die Suche des eigentlichen Fehlers, - da sind größere Codeumstellungen immer kontraproduktiv.

Ansonsten gilt immer noch:
Zusätzlich solltest Du prüfen, welche Zeilen in Quelle und Ziel beim 1.719. Durchlauf tatsächlich referenziert werden, eventuell steckt dort auch noch ein (Format-)Fehler. Damit ein Durchlauf zur Fehlersuche schneller geht, kannst Du die Startzeilen hochsetzen (Zeile 34+35).

Freundliche Grüße von der Insel - Mario
gerry56
gerry56 05.05.2012 um 19:50:22 Uhr
Goto Top
Einen schönen Nachmittag!

In der Zwischenzeit ist auch der Stand-PC mit Win-XP SP3 und 2GB RAM zum Absturzpunkt gelangt.

Mit
ActiveCell.FormulaR1C1 = ...
in Zeile 70 (Jene Zeile, die bei DEBUG als Fehlerzeile markiert wird)

Dieses Mal bei Schleifendurchlauf 1581.

Es kommt genauso wie vorher beim Laptop mit Win-7 Ultima 32 Bit und 4GB RAM die gleiche Fehlermeldung.
Solange das Makro funktionierte, wurde in Zelle Z1 der Bearbeitungsfortschritt angezeigt.

Nach 1581 (beim Laptop 1719) Schleifendurchgängen kam es wieder zum Absturz.
KEINE Anzeige in Zelle Z1

Ein Fenster mit der Überschrift "Microsoft Visual Basic" erscheint.
Der Fehlertext lautet.

Laufzeitfehler 1004
Anwendungs oder objectdefinierter Fehler.

Die Schaltfläschen "Beenden" "Debuggen" "Hilfe" werden angezeigt.

Betätige ich die Schaltfläche "Debuggen", verschwindet das Fehlerfenster und der Quelltext wird angezeigt.
Im Quelltext wird die Zeile 70, wo der Bearbeitungsfortschritt in Zelle Z1 angezeigt werden soll, gelb markiert.

Momantan läuft das Macro auf dem Laptop mit dem 1011 Durchlauf PROBLEMLOS.
Start war jedoch nicht der erste Datensatz in Zeile 2, sondern Zeile 1550.
Das bedeutet, daß jener Datensatz der zuvor in Win-XP auf dem Stand-PC, bzw. jener Datensatz, der zuvor auf dem Laptop beim Absturz bearbeitet wurde,
jetzt Problemlos abgearbeitet wurde.

Das bestätigt meine Vermutung von Eingangspost.
Ich hatte ja schon vor dem posten meines Beitrages einiges versucht.

Mit
ActiveCell.FormulaR1C1 = ...
in Zeile 70 (Jene Zeile, die bei DEBUG als Fehlerzeile markiert wird)

Teile ich die Tabelle2 mit den Quelldatensätzen, und vergleiche nur 1000, dann gibt es keinen Absturz.
Danach kann ich die nächsten 1000 zu vergleichenden Datensätze nehmen (inklusive dem Datensatz, der vorher 1900 war), und wieder ohne Absturz vergleichen.

Ich habe auch schon versucht, in der kompletten Tabelle 2 (mit 3800 Zeilen) nicht alle, sondern zuerst nur 1500 Datensätze zu vergleichen.
Ergebnis - KEIN Absturz
Danach ändere ich die Einstellungen (Beginn der ersten Zeile für Zieltabelle 3, die Anzahl der Datensätze in Vergleichstabelle 1) und starte das Makro wieder, wobei ich sicherheitshalber nur 200 Datensätze vergleiche.

Das bedeutet für mich, daß es egal ist, ob ich

ActiveCell.FormulaR1C1 = ...
ODER
Selection.Value = ...
in Zeile 70 verwende.
Der Absturz bleibt leider.
netzwerkknecht
netzwerkknecht 05.05.2012 um 23:18:10 Uhr
Goto Top
Zitat von @gerry56:
Einen schönen Nachmittag!

N'abend! face-smile


Das bedeutet für mich, daß es egal ist, ob ich

ActiveCell.FormulaR1C1 = ...
ODER
Selection.Value = ...
in Zeile 70 verwende.
Der Absturz bleibt leider.

Das wundert mich nicht allzu sehr - was bleibt ist nämlich auch meine Empfehlung: "Ich würde die gesamten .Select-, Selection und Active*-Konstruktionen vollständig eliminieren, da knallt Dir wahrscheinlich das Timing um die Ohren [...]". Ich schwöre nicht, dass das Dein konkretes Problem ist (da sind so viele Dinge, die im Idealfall so nicht sein sollten), aber ich bin durchaus kurz davor. Das sind Interaktionselemente, die auf reinen Code sehr oft sehr unfreundlich reagieren (in wenigen Fällen geht es nicht anders, weil bestimmte Excel-Funktionalitäten sich z. B. auf markierte Bereiche beziehen, aber das ist dann der Notfall, bei dem man die Daumen drückt und nach Alternativen sucht).

Vorschlag zur Güte (die Fehlerstelle muss nicht zwingend auch die verursachende Stelle sein - schon gar nicht bei Timingproblemen, überwiegend aber ist es so): Teste es in der ursprünglichen Zeile 70 mit der Erklärung von Mario (vorausgesetzt, der Code steht im Modul des Worksheets, in dem besagte Zelle Z1 liegt, anderenfalls noch den passenden Worksheet-Objektbezeichner davorsetzen):

Cells(1,26).Value = ...

1.) Wenn ich das ganze richtig verstehe, arbeitet VBA in wirklichkeit mit Zeilennummern und Spaltennummern.
Verwende ich im Quelltext Range("a" & CStr(quellzei)), so vergewaltige ich VBA dazu, das ganze intern in Zeilennummern und Spaltennummern umzurechnen.
Daher benötigt das Progi mehr Arbeitsspeicher und wird langsamer.

Ist meine Vermutung richtig?

Das ist dem Grunde nach richtig, gehört aber in die Ecke der letzten Optimierungen. Die Unterschiede sind marginal und werden erst im Hochlastfall interessant. Natürlich ist es trotzdem besser, wenn man solche Schwachstellen gleich vermeidet, aber viel wichtiger ist: Diese String-Geschichten sind neben ihrer Ineffizienz vollkommen unübersichtlich und verführen gerade Einsteiger zu merkwürdigen Programmierwegen - ich bin mir dessen bewusst, dass man das als Einsteiger anders sieht, und insofern könnte ich verstehen, wenn Du dem widersprechen würdest.

2.) Ich wollte den Rat befolgen, und alle Ranges in einem zusammenfassen.
suchealles1 = Range("A" & CStr(quellzei), "B" & CStr(quellzei), "C" & CStr(quellzei), "D" & CStr(quellzei))

Leider kommt sofort bei der Ausführung des Makros folgende Fehlermeldung

Das bedeutet, dass VBA noch funktioniert. Das ist eine gute Nachricht. face-wink
Ich hatte den folgenden Vorschlag gemacht:

suchealles1 = Range("A" & CStr(quellzei), "N" & CStr(quellzei))  


Viel Erfolg und einen schönen Restabend

netzwerkknecht auf Windows Intune: http://bit.ly/wide12hp
76109
76109 06.05.2012 um 14:40:31 Uhr
Goto Top
Hallo @all!

@netzwerkknecht
suchealles1 = Range("A" & CStr(quellzei), "N" & CStr(quellzei))
Mal davon abgesehen, dass dies kein Range-Object ist, wird es Dir nicht gelingen, einem String ein Range-Array zuzuweisenface-wink

Insofern, ist es schon richtig, die einzelnen Ranges zu einem String zu verketten. Andernfalls wäre es natürlich möglich, dass ganze Range-Object in ein Array zu packen und per Schleife einen Array-Vergleich durchzuführen, was den Vorteil hätte den Vergleich schon bei Ungleichheit eines Wertes vorzeitig zu beenden, was wiederum der Performance zu Gute kommen würde.

Mit dieser Variante ist schonmal ein enormer Geschwindigkeitsgewinn zu erwarten:
    Dim WksQ As Worksheet, WksS As Worksheet, ValuesQ As Variant, ValuesS As Variant
    Dim q As Long, s As Long, i As Integer
    
    Set WksQ = Sheets(2):  Set WksS = Sheets(1)

    Application.ScreenUpdating = False  

    'For q = 2 To Anzahl  
    
        ValuesQ = Range(WksQ.Cells(q, "A"), WksQ.Cells(q, "N")).Value  
        
        '......  
        
        'For s = Anzahl To 2 Step -1  'Wenn Zeilen gelöscht werden, dann bei letzter Zeile beginnen  
            ValuesS = Range(WksS.Cells(s, "E"), WksS.Cells(s, "R")).Value  
        
            For i = 1 To UBound(ValuesQ, 2)
                If ValuesQ(1, i) <> ValuesS(1, i) Then Exit For
            Next
            
            If i > UBound(ValuesQ, 2) Then
                'Ist Gleich..."  
            End If
        
            '......  
        'Next  

        '.....  
    'Next  
    
    Application.ScreenUpdating = True
Und mit dieser Variante sollte der Gesamt-Durchlauf nur zwischen 3-5 Sekunden dauern:
    Dim WksQ As Worksheet, WksS As Worksheet, ValuesQ As Variant, ValuesS As Variant
    Dim Found As Range, q As Long, i As Integer
    
    Set WksQ = Sheets(2):  Set WksS = Sheets(1)

    Application.ScreenUpdating = False  

    'For q = 2 To Anzahl  
    
        ValuesQ = Range(WksQ.Cells(q, "A"), WksQ.Cells(q, "N")).Value  
        
        '......  
        
        Set Found = WksS.Columns("E").Find(ValuesQ(1, 1), LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)  
            
        If Not Found Is Nothing Then
            ValuesS = Range(WksS.Cells(Found.Row, "E"), WksS.Cells(Found.Row, "R")).Value  
        
            For i = 2 To UBound(ValuesQ, 2)
                If ValuesQ(1, i) <> ValuesS(1, i) Then Exit For
            Next
            
            If i > UBound(ValuesQ, 2) Then
                'Ist Gleich..."  
            End If
        
            '......  
        End If
        
        '.....  

    'Next  

     Application.ScreenUpdating = True

Gruß Dieter
netzwerkknecht
netzwerkknecht 06.05.2012 um 17:52:02 Uhr
Goto Top
Zitat von @76109:
> suchealles1 = Range("A" & CStr(quellzei), "N" & CStr(quellzei))
Mal davon abgesehen, dass dies kein Range-Object ist, wird es Dir nicht gelingen, einem String ein Range-Array zuzuweisenface-wink

Uuuuah - das soll tatsächlich ein String sein - in dem Fall natürlich Kommando zurück. In einem solchen Szenario Strings zu verketten und zu vergleichen lag derart weit entfernt von meiner Vorstellungswelt, dass ich da erfasst habe, was mein Hirn mir vorgetäuscht hat... Danke für die Richtigstellung!

netzwerkknecht auf Windows Intune: http://bit.ly/wide12hp
gerry56
gerry56 07.05.2012 um 01:04:33 Uhr
Goto Top
Hallo an Alle!

Ich konnte mich in den letzten Stunden nicht melden, da beide Computer belegt waren.

Kurze Zusammenfassung.
1.) Ich habe alle Range("A" & CStr(quellzei)) in Cells(zeile, spalte) umgeändert.

2.) Den Rat, die Quelle nicht ab Zeile 2 einzulesen, sondern ab der Mitte, habe ich befolgt.
Wie von mir vermutet, schluckte das Macro in diesem Fall jene Quellzeilen anstandslos, bei denen es vorher zum Absturz kam.
Dafür stürzte das Macro bei einer späteren Quellzeile ab - eben nach zirka 1.700 Schleifendurchgängen.

3.) Ich habe die Informationsausgabe in Zelle Z1 (Quelltext Zeile 70) gekürzt.

Cells(1, 26).Value = "Durchgang 1 von 3. Vergleiche " & CStr(suchdatensatz) & " von " & CStr(Quellensenderzahl - 1) & " (aktuell nur mehr " _
& CStr(quellsenderanzahl - 1) & ") mit " & CStr(zielzei - 1) & " von " & CStr(suchsenderanzahl - 1) & " (aktuell nur mehr " & CStr(endzeile - 1)

Den folgenden Infoteil habe ich weggelassen
& "). Ident sind " & CStr(testzeile - 2) & ". NICHT GEFUNDEN " & CStr(nichtgef) & ". " & sucheSender1 & " zu " & sucheSender2 & ". "

Auf diese Art funktioniert das Macro ohne Absturz.

4.) Ich werde auf jeden Fall den Vorschlag von Dieter ausprobieren.

Danke nochmals an alle
Gerry