Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1092to1096
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
Makro ist sehr langsam
Susanne
Hallo Forum,
ich hoffe auf eure kompetente Unterstützung. Ich habe ein Makro, das zwar macht was es soll, jedoch braucht es ca 4 Minuten pro Datei im Verzeichnis. Habt ihr eine Idee wie man das ganze beschleunigen könnte?
Kurz zur Erklärung: Der Code soll in einer Auswertungsmappe eine Tabelle aus einer anderen Mappe einfügen, diese kopieren und unter die letzte beschriebene Zeile einfügen und dann alle Verknüpfungen ersetzen. Das macht er für jede Datei im angegebenen Verzeichnis. ZUm Schluss löscht es die Ausgangstabelle, da diese nur als Basis für die Ersetzungen dient, und blendet alle Zellen mit dem Wert null aus. Hier der Code:

Sub MitarbeiterEinfügen()
Dim rngCell As Range
Dim row As Long, i As Long
Dim rngRange As Range
Dim Wert As Date
Dim Cell As Range
Dim FileArr As Variant
Dim PathStr As String
Dim FileStr As String
With Application
.ScreenUpdating = False 'ausschalten der Bildschirmaktualisierung
.Calculation = xlCalculationManual
End With
Worksheets("Daten_Controlling").Activate
' Ausgeblendete Zeilen wieder einblenden
Cells.EntireRow.Hidden = False
'Alles löschen ab Zeile 6
Range(Range("A6"), _
Range("A6").End(xlDown)).EntireRow.Delete
'aus Basisdatei Grundlage kopieren
Workbooks("Zeiterfassung_Auswertung_Grundlage3").Worksheets("Basis").Range("A6:M365").Copy
Workbooks("Zeiterfassung_Auswertung_Controlling").Worksheets("Daten_Controlling").Range("A6") _
.Insert
'Anpassen----------------------------------------
PathStr = ActiveSheet.Range("B1").Value     'wenn Pfad gleichbleibend"
'Verzeichnis holen
'------------------------------------------------------------------------------------------- _
VerzeichnisHolen:
If PathStr = "" Then PathStr = GetPath()
If PathStr = "" Then
MsgBox "Es wurde weder ein Pfad angegeben noch ausgewählt!"
Exit Sub
End If
'Dateien aus Verzeichnis holen
'------------------------------------------------------------------------------------------- _
With Application.FileSearch
.LookIn = PathStr
.FileType = msoFileTypeExcelWorkbooks
If .Execute = 0 Then
If MsgBox("Verzeichnis ist leer!" & vbLf & "Wollen Sie ein anderes wählen?",  _
vbYesNo) = vbYes Then
PathStr = ""
GoTo VerzeichnisHolen
Else
Exit Sub
End If
Else
ReDim FileArr(1 To .FoundFiles.Count)
For i = 1 To .FoundFiles.Count
FileArr(i) = .FoundFiles(i)
Next
End If
End With
'neuen Mitarbeiter einfügen
'------------------------------------------------------------------------------------------- _
For i = 1 To UBound(FileArr)
PathStr = Left(FileArr(i), Len(FileArr(i)) - Len(Dir(FileArr(i))))
FileStr = Dir(FileArr(i))
Range("A6:M365").Copy
Cells(Cells(Rows.Count, 1).End(xlUp).row + 1, 1).Select
ActiveSheet.Paste
Selection.Replace What:="C:\Beispielpfad\[Kostenstelle_Name_Vorname.xls]", Replacement:= _
PathStr & "[" & FileStr & "]", _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:= _
False, ReplaceFormat:=False
Next
'Grundlage wieder löschen
Range("A6:A365").EntireRow.Delete
'Zeilen mit Null Zeit ausblenden
'------------------------------------------------------------------------------------------- _
For Each Cell In Range(Range("K6"), Range("K6").End(xlDown))
Wert = Cell.Value
If Wert = "0:00:00" Then Cell.EntireRow.Hidden = True
Next Cell
With Application
.ScreenUpdating = True 'ausschalten der Bildschirmaktualisierung
.Calculation = xlCalculationAutomatic
End With
End Sub

Private Function GetPath() As String
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
.Title = "Ordner auswählen"
.Show
If .SelectedItems.Count  1 Then
Exit Function
Else
GetPath = .SelectedItems(1)
End If
End With
End Function
Vielen Dank allen, die sich meinem Problem annehmen!
Liebe Grüße,
Susanne
AW: Makro ist sehr langsam
03.08.2009 17:24:03
Daniel
Hi
ich sehe momentan 2 Bremsen in deinem System:
1. Bremse ist die Stelle, wo in Formeln mit Fernbezug dieser Fernbezug verändert wird:
Selection.Replace What:="C:\Beispielpfad\[Kostenstelle_Name_Vorname.xls]", Replacement:= _
PathStr & "[" & FileStr & "]", _...

hier wäre es hilfreich, wenn die Datei, auf die sich die geänderten Formeln beziehen sollen (PathStr,FileStr), geöffnet wäre, weil dann die Datenaktualisierung und Neuberechnung wesentlich schneller funktioniert als wenn auf ein geschlossene Datei zugegriffen werden muss.
2. Bremse könnte je nach Anzahl der Zeilen das Ausblenden der Zeilen mit "0:00:00" sein.

For Each Cell In Range(Range("K6"), Range("K6").End(xlDown))
Wert = Cell.Value
If Wert = "0:00:00" Then Cell.EntireRow.Hidden = True
Next Cell

solche Schleifen sind generell langsam, hier würde ich den Autofilter verwenden.
falls die Autofiltermarker stören, kann man diese auch ausblenden über die Eigenschaft: "VisibleDropDown:=False".
(hierzu mal in der Hilfe zum Autofilter nachsehen). Diese Option steht nur zur Verfügung, wenn der Autofilter über Makros gesetzt wird.
Gruß, Daniel
Anzeige
AW: Makro ist sehr langsam
04.08.2009 08:46:30
Susanne
Hallo Daniel,
das Öffnen der Sheets ist eher keine Option, da sich schon mehr als 20 Dateien in einem Verzeichnis befinden können.
Wie könnte ich den Autofilter umsetzten? Erstmal am Anfang statt "Cells.EntireRow.Hidden=False" "ActiveSheet.AutoFilterMode=False"? Oder wie kann ich ausschließen, dass schon ein Filter gesetzt ist? Mein Ansatz für dem Filter wäre:
ActiveSheet.Cells(6,11).Autofilter _
field:= 11, _    'für Spalte K oder muss hier 1 hin?
criterial:= 00:00:00 'müssen Anführungszeichen gesetzt werden?

Vielen Dank für deine Hilfe!
Anzeige
AW: Makro ist sehr langsam
04.08.2009 11:31:37
Daniel
Hi
wahrscheinlich 11, denn Excel erweitert beim Setzen des Autofilters mit nur einer Zelle den Zellbereich automatisch auf die umliegende Tabelle.
Sollte allerdings die Spalte A leer sein, dürfte hier nur 10 eingetragen werden.
Das Kriterum muss als String eingegeben werden, also mit Anführungszeichen (da hilft der Makrorecorder)
allerdings ist die Frage, wie die "0:00:00" zustande kommen, steht das so als Wert in der Zelle oder ist das ein Zeitformat mit dem Wert 0 und der Formatierung "hh:mm:ss"
um sicherzustellen,daß alles eingeblendet ist, kann man folgendes verwenden:
If ActiveSheet.AutoFilterMode Then ActiveSheet.ShowAllData
Gruß, Daniel
Anzeige
AW: Makro ist sehr langsam
04.08.2009 11:57:58
Susanne
Hi Daniel,
das 00:00:00 kommt durch das Zeitformat hh:mm:ss mit dem Wert 0 zustande.
Mit:

ActiveSheet.Cells(6, 11).AutoFilter _
field:=11, _
criterial:="00:00:00"
kommt der Laufzeitfehler 1004, aber das könnte vielleicht auch daran liegen, dass ich nur den Teil über Einzelschritte im Debugger ausprobieren wollte, dann aber automatisch das Tabellenblatt nicht aktiv ist. Ich hab das Zeilen ausblenden auch mal einzeln durchgeführt, das dauert bei 8 Dateien aus dem Verzeichnis nur 10-15 Sek. Daran kann es also eigentlich nicht liegen, dass insgesamt 4-5 Min pro Datei gebraucht werden.
Hast du vielleicht beim Ersetzen-Teil eine Idee, wie man das select/Selection wegbekommt, vielleicht wird das Makro dann schneller?
Anzeige
AW: Makro ist sehr langsam
04.08.2009 11:59:38
Susanne
Hi Daniel,
das 00:00:00 kommt durch das Zeitformat hh:mm:ss mit dem Wert 0 zustande.
Mit:

ActiveSheet.Cells(6, 11).AutoFilter _
field:=11, _
criterial:="00:00:00"
kommt der Laufzeitfehler 1004, aber das könnte vielleicht auch daran liegen, dass ich nur den Teil über Einzelschritte im Debugger ausprobieren wollte, dann aber automatisch das Tabellenblatt nicht aktiv ist. Ich hab das Zeilen ausblenden auch mal einzeln durchgeführt, das dauert bei 8 Dateien aus dem Verzeichnis nur 10-15 Sek. Daran kann es also eigentlich nicht liegen, dass insgesamt 4-5 Min pro Datei gebraucht werden.
Hast du vielleicht beim Ersetzen-Teil eine Idee, wie man das select/Selection wegbekommt, vielleicht wird das Makro dann schneller?
Anzeige
AW: Makro ist sehr langsam
04.08.2009 13:20:40
Daniel
Hi
wenn es so ist dann darfts du nur "0" filtern, denn 0 ist auch der Wert der tatsächlich in der Zelle drinsteht.
ansonsten probier mal an dieser Stelle den Makrorecorder, um die genaue befehlsyntax für den Autofilterbefehl zu bekommen, oder lies mal dazu in der Hilfe nach.
das select bekommst du an dieser Stelle so weg:

With Cells(Cells(Rows.Count, 1).End(xlUp).Row + 1, 1)
Range("A6:M365").Copy Destination:=.Cells
.Resize(360, 13).Replace ....
End With
allerdings bleibe ich bei meiner Vermutung, der Zeitfresser sind die externen Zellbezuge auf geschlossene Dateien.
Gruß, Daniel
Anzeige
AW: Makro ist sehr langsam
04.08.2009 14:17:17
Susanne
Hi,
danke dir schon mal für deinen Alternativvorschlag zu select. Könntest du mir kurz erklären, was genau das resize macht und wofür man das hier braucht. Es soll ja immer der gleiche, feststehende Bereich kopiert und in die erste freie Zelle eingefügt werden. Danke dir!
Liebe Grüße,
Susanne
AW: Makro ist sehr langsam
04.08.2009 15:59:09
Daniel
Hi
naja, du willst ja nach dem Einfügen der Formeln diese überarbeiten, dazu muss der ganze neueingefügte Zellbereich angesprochen werden.
im alten Fall nach "ActiveSheet.Paste" war dieser neue Zellbereich automatisch selektiert und mit "Selection.Replace" wurden alle neuen Zellen überarbeitet.
in der neuen Situation ist es ja so, daß zunächst einmal nur die linke obere Zelle des neuen Zellbereichs bekannt ist, aber nicht der ganze neue Zellbereich. (die Zelle, die mit WITH definiert wird)
um jetzt den ganzen neuen Zellbereich anzusprechen, vergrössere die ich bekannte linke obere Zelle mit der RESIZE-Funtkion zu einem Zellbereich, der 13 Spalten breit und 360 Zeilen hoch ist. Dies entspricht dem neu eingefügten Zellbereich.
die Anzahl der Zeilen und Spalten kann ich mir aus dem Kopierbereich ableiten (A-M = 13 Spalten, 6-365 = 360 Zeilen.
Gruß, Daniel
Anzeige
AW: Makro ist sehr langsam
04.08.2009 16:49:38
Susanne
Hallo Daniel,
danke für die Erklärung, klingt logisch. Ich werd das mal ausprobieren und melde mich dann wieder, ob das zeitlich was gebracht hat.
AW: Makro ist sehr langsam
05.08.2009 09:43:15
Susanne
Hallo Daniel,
die Änderung der Schleife hat nur eine unwesentliche Verbesserung gebracht, aber ich habs jetzt mal ausprobiert, wenn alle Dateien offen sind und du hattest Recht, es liegt daran. Jetzt hat es nicht mal eine Minute gedauert (für alle Dateien). Wie könnte denn der Befehl aussehen, wenn ich alle Dateien im Filearray im Makro öffnen und nach der Ausführung wieder schließen lassen möchte?
Vielen vielen Dank für deine Hilfe!
Anzeige
AW: Makro ist sehr langsam
05.08.2009 13:24:02
Daniel
Hi
ich würde es hier einbauen:
Dim WB as Workbook
Application.ScreenUpdating=False 'schaltet das Flackern des Bildschirms ab
For i = 1 To UBound(FileArr)
PathStr = Left(FileArr(i), Len(FileArr(i)) - Len(Dir(FileArr(i))))
FileStr = Dir(FileArr(i))
Set WB = Workbooks.Open(FileArr(i), Readonly:=True)
Range("A6:M365").Copy
Cells(Cells(Rows.Count, 1).End(xlUp).row + 1, 1).Select
ActiveSheet.Paste
Selection.Replace What:="C:\Beispielpfad\[Kostenstelle_Name_Vorname.xls]",  _
Replacement:= _
PathStr & "[" & FileStr & "]", _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=  _
_
False, ReplaceFormat:=False
WB.Saved=True
WB.Close
Next
Application.Screenupdating = True

ich hab jetzt deinen ersten Code verwendet, um zu zeigen wie es geht.
die anderen Optimierungen musst du natürlich auch einbauen.
Gruß, Daniel
PS, nicht getestet, im FileArr sollten die vollständigen Dateinamen der entsprechenden Dateien stehen (Pfad und Datei)
Anzeige
AW: Makro ist sehr langsam
05.08.2009 13:48:00
Susanne
Hallo Daniel,
der Teilcode sieht jetzt so aus:
    For i = 1 To UBound(FileArr)
PathStr = Left(FileArr(i), Len(FileArr(i)) - Len(Dir(FileArr(i))))
FileStr = Dir(FileArr(i))
Set WB = Workbooks.Open(FileArr(i), ReadOnly:=True)
With Cells(Cells(Rows.Count, 1).End(xlUp).row + 1, 1)
Range("A6:M365").Copy Destination:=.Cells
.Resize(360, 13).Replace What:="C:\Beispielpfad[Kostenstelle_Name_Vorname_P.xls]",  _
Replacement:=PathStr & "[" & FileStr & "]", _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:= _
False, ReplaceFormat:=False
End With
WB.Saved = True
WB.Close
Next
Leider kommt jetzt der Laufzeitfehler 1004, weil die Verknüpfungen sich auf schreibgeschützte Zellen beziehen. Kann man das mit WB.Saved=False umgehen, in den Dateien aus dem Filearray soll ja nichts geändert werden also müssen sie auch nicht gespeichert werden, oder?
Danke danke danke für deine Hilfe!
AW: Makro ist sehr langsam
05.08.2009 15:59:59
Daniel
HI
wo und in welcher Zeile kommt denn der Laufzeitfehler?
wenn die Zellen schreibgeschützt sind, müsste das Problem doch auch schon früher bestanden haben.
Das "WB.Saved = True" speichert eigentlich nichts, sondern setzt nur die Kennung, daß die Datei gespeichert wurde. Diese Kennung beeinflusst nur die automatische Abfrage vor dem Schließen "wollen Sie die Änderungen speichern?". Durch das setzen dieser Kennung wird die Abfrage vermieden.
Eigentlich dürfte die Abfrage nicht kommen, weil das Makro nichts an der Datei ändert, aber nich nehme es einfach immer Standardmäßig hinzu.
wenn du meinst, daß es den Fehler verursacht, dann kannst du es einfach mal weglassen (löschen oder auskommentieren)
Gruß, Daniel
AW: Makro ist sehr langsam
05.08.2009 16:29:38
Susanne
Hallo Daniel,
der Debugger markiert diese Zeile:
Range("A6:M365").Copy Destination:=.Cells
und das Problem ist, dass es die Datei im Verzeichnis schreibgeschützt öffnet, wenn ich sie manuell vorher öffne ist sie nicht schreibgeschützt. Hast du eine Idee, was man dagegen machen kann?
Liebe Grüße,
Susanne
AW: Makro ist sehr langsam
05.08.2009 16:39:10
Susanne
Hallo Daniel,
ich habs. Hab ja die Zeile:
 Set WB = Workbooks.Open(FileArr(i), ReadOnly:=True)
drin, bei dem gesagt wird nur lesen erlaubt. Kann ich das ReadOnly einfach rauslöschen oder muss ich es auf False setzen?
Liebe Grüße,
Susanne
AW: Makro ist sehr langsam
05.08.2009 17:11:03
Daniel
Hi
kannst du rauslöschen, dieser Parameter ist Optional.
Er soll eigentlich nur vermeiden, daß es Probleme gibt, wenn die zu öffnende Datei grad von jemand anders bearbeitet wird.
Gruß, Daniel
AW: Makro ist sehr langsam
05.08.2009 18:22:01
Susanne
Hallo,
mein Computer spinnt grad total, ich probiere es morgen aus, ob es jetzt funktioniert und melde mich dann noch mal.
Schönen Feierabend und liebe Grüße,
Susanne
AW: Makro ist sehr langsam
06.08.2009 08:23:25
Susanne
Guten Morgen Daniel,
das Problem lag daran, dass durch das Öffnen der Dateien aus dem Verzeichnis die Auswertungsmappe, in der das Kopieren und Ersetzen stattfindet, nicht mehr aktiv war. Ich hab das jetzt einfach ganz unelegant mit Activate gelöst und jetzt funktioniert alles:
    For i = 1 To UBound(FileArr)
PathStr = Left(FileArr(i), Len(FileArr(i)) - Len(Dir(FileArr(i))))
FileStr = Dir(FileArr(i))
Set WB = Workbooks.Open(FileArr(i), ReadOnly:=False) 'öffnet die Dateien im Verzeichnis
Workbooks("Zeiterfassung_Auswertung_Controlling").Worksheets("Daten_Controlling"). _
Activate
With Cells(Cells(Rows.Count, 1).End(xlUp).row + 1, 1)
Range("A6:M365").Copy Destination:=.Cells
.Resize(360, 13).Replace What:="C:\Beispielpfad\[Kostenstelle_Name_Vorname.xls]",  _
Replacement:=PathStr & "[" & FileStr & "]", _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:= _
False, ReplaceFormat:=False
End With
WB.Saved = True
WB.Close        'schließt die Dateien wieder
Next
Ich danke dir vielmals für deine kompetente Hilfe, ohne dich wäre ich sicher nicht so weit gekommen. Danke Danke Danke!
Liebe Grüße,
Susanne
AW: Makro ist sehr langsam
06.08.2009 12:48:47
Daniel
Hi
stimmt, hatte ich vergessen.
wenn eine Datei geöffnet wird, ist zunächst mal diese aktiv.
da hatte ich nicht dran gedacht, da ich normalerweise beim hantieren mit mehreren Dateien die Verwendeten Sheets immer in Variablen ablege und diese bei der Referenzierung verwende, so daß es für den Programmablauf egal ist, welche Datei und welches Sheet grade aktiv ist.
das sieht dann so aus:
dim shContr
Set shContr = thisworkbook.Sheets("Daten_Controlling")
For i = 1 To UBound(FileArr)
PathStr = Left(FileArr(i), Len(FileArr(i)) - Len(Dir(FileArr(i))))
FileStr = Dir(FileArr(i))
Set WB = Workbooks.Open(FileArr(i), ReadOnly:=False) 'öffnet die Dateien im Verzeichnis
With shContr.Cells(shContr.Cells(Rows.Count, 1).End(xlUp).row + 1, 1)
shContr.Range("A6:M365").Copy Destination:=.Cells
.Resize(360, 13).Replace What:="C:\Beispielpfad\[Kostenstelle_Name_Vorname.xls]",  _
Replacement:=PathStr & "[" & FileStr & "]", _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:= _
False, ReplaceFormat:=False
End With
WB.Saved = True
WB.Close        'schließt die Dateien wieder
Next
Gruß, Daniel
AW: Makro ist sehr langsam
06.08.2009 14:39:11
Susanne
Hallo Daniel,
ich hab das bei mir geändert, leider meint es dann wieder irgendetwas in den geöffneten Dateien machen zu müssen und es kommen ein Haufen Abfrageboxen, die man wegklicken muss. Ich lass einfach das Activate, so funktioniert es ausgezeichnet (never change a running system ;-)). Trotzdem danke für den Verbesserungsvorschlag, das mit den Variablen anlegen und damit Referenzieren werde ich mir für die Zukunft merken!
Liebe Grüße,
Susanne
AW: Makro ist sehr langsam
04.08.2009 15:59:09
Daniel
Hi
naja, du willst ja nach dem Einfügen der Formeln diese überarbeiten, dazu muss der ganze neueingefügte Zellbereich angesprochen werden.
im alten Fall nach "ActiveSheet.Paste" war dieser neue Zellbereich automatisch selektiert und mit "Selection.Replace" wurden alle neuen Zellen überarbeitet.
in der neuen Situation ist es ja so, daß zunächst einmal nur die linke obere Zelle des neuen Zellbereichs bekannt ist, aber nicht der ganze neue Zellbereich. (die Zelle, die mit WITH definiert wird)
um jetzt den ganzen neuen Zellbereich anzusprechen, vergrössere die ich bekannte linke obere Zelle mit der RESIZE-Funtkion zu einem Zellbereich, der 13 Spalten breit und 360 Zeilen hoch ist. Dies entspricht dem neu eingefügten Zellbereich.
die Anzahl der Zeilen und Spalten kann ich mir aus dem Kopierbereich ableiten (A-M = 13 Spalten, 6-365 = 360 Zeilen.
Gruß, Daniel

20 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige