Anzeige
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender

Forumthread: Alle Dateien eines Ordners nacheinander abarbeiten

Alle Dateien eines Ordners nacheinander abarbeiten
05.01.2018 13:55:01
Ralf
Hallo zusammen,
erstelle als VBA-Anfänger zur Zeit mein erstes VBA für Excel 2016 Programm, sitze schon ein paar Tage dran und bin immer happy, wenn es dann Stück für Stück klappt.
Dank vieler, hilfreicher Antworten aus diesem Forum habe ich das Kernmodul nun endlich fertig.
Jetzt fehlt mir zum Schluss noch der Code für das Abarbeiten mit dem erstellten Modul auf sämtliche Excel-Dateien in einem Verzeichnis.
Jede Datei soll hintereinander (in einer Schleife?)aufgerufen, abgearbeitet und mit einer Namenserweiterung wieder in einem Unterordner des Quellordners abgelegt werden.
Aus z.B. "TabXY.xls" (es sind noch alte Excel-Dateien) soll "TabXY-1.xls" oder .xlsx werden, jeder Dateiname wird also beispielsweise um "-1" erweitert.
Habe natürlich schon einige Versuche gestartet, hat aber außer Fehlermeldungen nichts gebracht.
Die Ordnerauswahl zum Testen könnte ich mir wie folgt vorstellen:

Sub Auslesen()
OrdnerAuswahl GetFolder
End Sub

Function GetFolder() As String
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
.InitialFileName = "D:\Excel-Test\Dateientest\"
.ButtonName = "Öffnen"
.Title = "Ordnerauswahl"
.Show
If .SelectedItems.Count = 0 Then
GetFolder = ""
Else
GetFolder = .SelectedItems(1)
End If
End With
End Function

Mein Modul hat mittlerweile über 300 Befehlszeilen incl. Kommentarzeilen, würde von einem Profi sicher kürzer und schneller sein, läuft aber fehlerfrei.
Bin natürlich für jede Hilfe sehr dankbar!
Ralf
Anzeige

23
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: FSO
05.01.2018 14:48:54
Fennek
Hallo,
teste, zuerst in einer Test-Umgebung, folgenden Code:

Sub FSO_ren()
Dim FSO As Object: Set FSO = CreateObject("Scripting.FileSystemObject")
Dim FD As Object
Dim iFile As Object
Dim iPath As String
iPath = "c:\temp\daten" ' >>>>>>>>>>>
Set FD = FSO.GetFolder(iPath)
For Each iFile In FD.Files
NewNm = FSO.GetBaseName(iFile) & "-1." & FSO.GetExtensionName(iFile)
FileCopy iFile, iPath & "\" & NewNm
Kill iFile
Next iFile
End Sub
mfg
Anzeige
AW: FSO
05.01.2018 19:43:14
Ralf
Hallo Fennek,
danke für deine Antwort!
Habe deinen Code in einer Test-Umgebung mal getestet, komme allerdings nur bis
NewNm = FSO.GetBaseName(iFile) & "-1." & FSO.GetExtensionName(iFile)
Bei "NewNM =" erscheint die Fehlermeldung: "Variable nicht definiert."
Kannst du mir VBA-Anfänger da weiterhelfen?
Gruß
Ralf
Anzeige
AW: option explicit?
05.01.2018 20:00:11
Fennek
Ist diese Option gesetzt (in der ersten Zeile des Moduls)
Dann, entweder
- alle Variablen dimensionieren
- option explicit löschen
Der 2. Tip ist aber nicht zu empfehlen! o.T.
05.01.2018 20:06:15
Sepp
Gruß Sepp

AW: Nutzen?
05.01.2018 20:18:10
Fennek
Nur wenn es erkennbare Vorteile bringt (z.B. intellisense) dimensioniere ich.
Anzeige
Dein Problem! o.T.
05.01.2018 20:29:38
Sepp
Gruß Sepp

AW: option explicit?
05.01.2018 20:24:04
Ralf
Hallo Fennek,
ja, die Option Explicit ist gesetzt, fühle mich da einfach sicherer bei der Variablenvergabe.
Ich würde das auch gerne beibehalten, müsste da aber wissen, wie ich die von dir angesprochenen verschiedenen Variablen dimensionieren muss.
z.B. Dim NewNM As ? usw.
Kann verstehen, das du dir bei mir als Anfänger sicherlich die Haare aufgrund meines Minimalwissens raufst!
Wenn du aussteigen möchtest, nehme ich dir das nicht übel!
Gruß
Ralf
Anzeige
AW: FSO
05.01.2018 20:30:13
Fennek
zuerst nachsehen hat Vorteile. Da ich mit "early binding" angefangen habe, sind (für mich völlig ungewöhnlich) alle Variablen dimensioniert.
Aber:
dim NewNm as string 'einfügen

Sub FSO_ren()
Dim FSO As Object: Set FSO = CreateObject("Scripting.FileSystemObject")
Dim FD As Object
Dim iFile As Object
Dim iPath As String
iPath = "c:\temp\daten" ' >>>>>>>>>>>
Set FD = FSO.GetFolder(iPath)
For Each iFile In FD.Files
NewNm = FSO.GetBaseName(iFile) & "-1." & FSO.GetExtensionName(iFile)
FileCopy iFile, iPath & "\" & NewNm
Kill iFile
Next iFile
End Sub

Anzeige
AW: FSO
05.01.2018 20:42:58
Ralf
OK Fennek,
was ist "early binding" ?
Der Code läuft jetzt ohne Fehlermeldung durch und sieht so aus:
Option Explicit
Sub FSO_ren()
Dim FSO As Object: Set FSO = CreateObject("Scripting.FileSystemObject")
Dim FD As Object
Dim iFile As Object
Dim iPath As String
Dim NewNm As String
iPath = "C:\Temp-RL\RL-14097"
Set FD = FSO.GetFolder(iPath)
For Each iFile In FD.Files
NewNm = FSO.GetBaseName(iFile) & "-1." & FSO.GetExtensionName(iFile)
FileCopy iFile, iPath & "\" & NewNm
Kill iFile
Next iFile
End Sub
Was müsste sich denn jetzt für mich sichtbar getan haben? Der Quellordner "C:\Temp-RL\RL-14097" hat sich mit seinem Inhalt nicht geändert.
Gruß
Ralf
Anzeige
AW: keine Ahnung
05.01.2018 20:49:26
Fennek
in meiner Testumgebung hat der Code die Dateinamen geändert.
Kennst du den Einzelschritt-Modus (F8) im VBE-Editor? (öffnen mit alt-F11). Wenn man mit der Maus über die Variablen geht, kann man den Wert sehen.
AW: keine Ahnung
05.01.2018 20:58:28
Ralf
Mensch Fennek,
habe ich auf dem ersten Blick gar nicht gesehen - stimmt.
Und was nun weiter?
Wie bekomme ich die Abarbeitung meines Hauptmoduls für jede xls-Datei da rein da rein?
Oder muss da vorher noch einiges andere gemacht werden?
Gruß
Ralf
Anzeige
AW: Hauptmodul?
05.01.2018 21:07:05
Fennek
ich zitiere sehr ungern: "ich kann nicht auf deinen Rechner sehen"
Mit den bisher gegeben Infos, kann ich den letzten Kommentar nicht verstehen.
AW: Hauptmodul?
05.01.2018 21:32:56
Ralf
Hallo Fennek,
bei meiner anfangs gestellten Frage ging es mir doch um (Zitat):
"....... Jetzt fehlt mir zum Schluss noch der Code für das Abarbeiten mit dem erstellten Modul auf sämtliche Excel-Dateien in einem Verzeichnis.
Jede Datei soll hintereinander (in einer Schleife?)aufgerufen, abgearbeitet und mit einer Namenserweiterung wieder in einem Unterordner des Quellordners abgelegt werden........."
Das heißt, dass ich ein recht umfangreiches Modul für die Bearbeitung einer Excel-Datei geschrieben habe. Diesen Code (Modul) möchte ich auf alle xls-Dateien in einem Ordner anwenden.
Nach Bearbeitung dieser Dateien sollen sie mit einer Namenserweiterung in einen neuen Ordner kopiert werden.
Ich suche also, laienhaft ausgedrückt, eine Programmschleife, in deren Mitte sich mein Code befindet, die bis zum Bearbeiten der letzten Datei läuft.
Tut mir leid, wenn ich mich hier am Anfang nicht klar ausgedrückt habe, ich hoffe, das ist jetzt verständlicher.
Gruß
Ralf
Anzeige
AW: verdrängt
05.01.2018 21:37:34
Fennek
nach den Änderungen nutze
workbook.saveas "c:\neuerPfad\NeuerName"
(vielleicht wieder falsch vetstanden)
AW: verdrängt
05.01.2018 21:49:48
Ralf
Hi Fennek,
Ok, damit kann ich die im Namen geänderten Dateien in einen anderen, neuen Ordner kopieren.
Bloß weiß ich nicht, wo ich in deinem Programm die Abarbeitung meines Moduls plazieren soll, damit alle Dateien mit meinem Code vor der Namensumbenennung bearbeitet werden.
Das muss ja irgendwo in deiner Schleife eingebaut werden:
For Each iFile In FD.Files
NewNm = FSO.GetBaseName(iFile) & "-1." & FSO.GetExtensionName(iFile)
FileCopy iFile, iPath & "\" & NewNm
Kill iFile
Next iFile
Sehe ich das richtig?
Wenn ja: Wo?
Gruß
Ralf
Anzeige
AW: sorry
05.01.2018 22:05:01
Fennek
Der am Anfang gezeigte code ist so rudimentär, dass ich ihn verdängt habe. Dieser "fileDialog" ermöglicht die Auswahl von Datei(n) im Browser, danach können sie geöffnet und bearbeitet werden.
Sofern alle *.xlsx Dateien eines Ordner bearbeitet werden sollen, ist es eichfacher in etwa so:

Sub Aendern()
const iPath = "c:\temp"
dim WB as workbook
iFile = dir(iPath & "\*.xls") 'öffnet nacheinander alle xlsx
do while len(ifile)
set WB = workbooks.open(iPath & ifile)
'>>>> ansprechen mit WB.Sheets("Blatt-Name").Range(...)
newNm = replace(iFile, ".", -1.")
WB.saveas iPath & newNm
WB.close
iFile = dir
loop
end sub
Der Code ist "heruntergeschrieben", hat so nie xl gesehen.
Hilft dir das?
mfg
Anzeige
AW: sorry
05.01.2018 22:35:59
Ralf
Danke für deine Geduld, Fennek!
Ja, mit meinen Laienaugen betrachtet, könnte es so gehen.
Probiere es im Laufe des Wochenendes aus.
Melde mich dann noch mal - ich hoffe, mit einem Erfolgsergebnis.
Vielen Dank!
Ralf
AW: sorry
06.01.2018 12:08:05
Ralf
Hallo Fennek,
habe deinen Code jetzt mal versucht anzupassen und eine einfache Test-Bearbeitung für alle Dateien eingefügt:
Option Explicit
Sub Testanwendung()
'Const iPath = "c:\temp"
Dim WB As Workbook
Dim iFile As Object
Dim iPath As String
Dim NewNm As String
iPath = "C:\Temp-RL"
iFile = Dir(iPath & "\*.xls") 'öffnet nacheinander alle xls
Do While Len(iFile)
Set WB = Workbooks.Open(iPath & iFile)
'>>>> ansprechen mit WB.Sheets("Blatt-Name").Range(...)
'Beginn Bearbeitung der xls-Dateien
Dim xvar As String
xvar = "Test-Eintrag"
Range("A1").Value = xvar
'Ende Bearbeitung
NewNm = Replace(iFile, ".", "-1.")
WB.SaveAs iPath & NewNm
WB.Close
iFile = Dir
Loop
End Sub
iPath kann ich nicht Const machen, da sich die Pfadangabe ändern lassen muss und das geht doch bei Const wohl nicht?
Fehler bei:
iFile = Dir(iPath & "\*.xls")
-------------------------------------------------------
Laufzeitfehler '91':
Objektvariable oder With-Blockvariable nicht festgelegt
-------------------------------------------------------
Bezüglich deiner Anweisung:
'>>>> ansprechen mit WB.Sheets("Blatt-Name").Range(...)
Muss ich das machen, wenn alle Dateien nur ein Blatt haben, das dann ja beim Öffnen immer aktiv ist?
Innerhalb meines Bearbeitungscodes verweise ich mehrmals auf bestimmte Range()-Bereiche, muss ich trotzdem vorher irgendwelche .Range() ansprechen?
Was muss ich noch ändern?
Gruß
Ralf
Anzeige
AW: sorry
06.01.2018 12:13:40
Fennek
Das kann nicht gehen:

'Beginn Bearbeitung der xls-Dateien
Dim xvar As String
xvar = "Test-Eintrag"
Range("A1").Value = xvar
'Ende Bearbeitung
aber so:

'Beginn Bearbeitung der xls-Dateien
Dim xvar As String
xvar = "Test-Eintrag"
WB.Sheets(1).Range("A1").Value = xvar
'Ende Bearbeitung
Falls mehrere Änderungen kommen, ist ein
with WB.Sheets(1)
.Range("A1") = "Test-Eintrag"
end with
besser. Zu beachten: .Range(.cells(1,1), .cells(1,10))
Anzeige
Abarbeitungsschleife läuft nicht an
06.01.2018 12:55:17
Ralf
OK, Fennek,
habe meinen kleinen Testcode entsprechend geändert
Option Explicit
Sub Testanwendung()
'Const iPath = "c:\temp"
Dim WB As Workbook
Dim iFile As Object
Dim iPath As String
Dim NewNm As String
iPath = "C:\Temp-RL"
iFile = Dir(iPath & "\*.xls") 'öffnet nacheinander alle xls
Do While Len(iFile)
Set WB = Workbooks.Open(iPath & iFile)
'>>>> ansprechen mit WB.Sheets("Blatt-Name").Range(...)
'Beginn Bearbeitung der xls-Dateien
Dim xvar As String
xvar = "Test-Eintrag"
WB.Sheets(1).Range("A1").Value = xvar
'Ende Bearbeitung
'Falls mehrere Änderungen kommen, ist ein
' With WB.Sheets(1)
' .Range("A1") = "Test-Eintrag"
' End With
'besser. Zu beachten: .Range(.cells(1,1), .cells(1,10))
NewNm = Replace(iFile, ".", "-1.")
WB.SaveAs iPath & NewNm
WB.Close
iFile = Dir
Loop
End Sub
Allerdings immer noch keine Abarbeitung, wie vorher schon beschrieben:
Fehler bei:
iFile = Dir(iPath & "\*.xls")
-------------------------------------------------------
Laufzeitfehler '91':
Objektvariable oder With-Blockvariable nicht festgelegt
-------------------------------------------------------
Gruß
Ralf
Anzeige
AW: Dim iFile As Object -> String
06.01.2018 12:59:12
Fennek
iFile MUSS als String dimesioniert werden
AW: Dim iFile As Object -> String
06.01.2018 18:22:54
Ralf
Hallo Fennek,
Erfolg dank deiner Hilfe!
Hier der neue Code
Option Explicit
Sub Testanwendung()
'Const iPath = "c:\Temp-RL\"
Dim iPath As String
iPath = "c:\Temp-RL\"
Dim WB As Workbook
Dim iFile As String
Dim uOrdner As String
uOrdner = "Bearbeitet\"
Dim NewNm As String
If Dir(iPath & uOrdner)  "" Then
Kill iPath & uOrdner & "\*.*"  'Unterverzeichnis-Inhalt löschen
Else
MkDir iPath & uOrdner   'Unterverzeichnis erstellen
End If
iFile = Dir(iPath & "*.xls") 'öffnet nacheinander alle xls
Do While Len(iFile)
Set WB = Workbooks.Open(iPath & iFile)
'Beginn Bearbeitung der xls-Dateien
Dim xvar As String
xvar = "Test-Eintrag"
WB.Sheets(1).Range("A1").Value = xvar
'Ende Bearbeitung
NewNm = Replace(iFile, ".", "-1.")
WB.SaveAs iPath & uOrdner & NewNm
WB.Close
iFile = Dir
Loop
End Sub
Nur noch ein kleiner Schönheitsfehler:
Beim Erstellen der einzelnen Dateien wird immer der Bildschirminhalt aktualisiert = Flackern.
Habe es mit
Application.ScreenUpdating = False
Application.ScreenUpdating = True
und auch
application.displayalerts = false
application.displayalerts = true
probiert, hat aber nichts gebracht. Kennst du da einen Tipp?
Wenn dir sonst noch irgendetwas auffällt, das anders geschrieben besser wäre, kannst du dich ja bitte nochmal melden.
Baue jetzt als nächstes meine Hauptanwendung in die Schleife ein, bin mal gespannt, was dann passiert!
Dank und Gruß
Ralf
Anzeige
AW: Pfad
06.01.2018 12:34:44
Fennek
solange der iPath ohne \ definiert wird, muss

WB.SaveAs iPath & "\" & NewNm
Dies schreibt aber ins selbe Verzeichnis. Warum nicht

contst iPath = "c:\Temp-RL\"
iFile = dir(iPath & "*.xls")
WB.SaveAs iPath & "UnterOrdner\" & NewNm

Anzeige

Forumthreads zu verwandten Themen

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige

Infobox / Tutorial

VBA: Alle Dateien eines Ordners nacheinander abarbeiten


Schritt-für-Schritt-Anleitung

  1. VBA-Editor öffnen: Drücke Alt + F11, um den VBA-Editor in Excel zu öffnen.

  2. Neues Modul erstellen: Klicke mit der rechten Maustaste auf "VBAProject (Dein Dokument)" und wähle "Einfügen" > "Modul".

  3. Code einfügen: Füge den folgenden Code in das Modul ein:

    Sub Abarbeiten()
       Dim FSO As Object
       Dim FD As Object
       Dim iFile As Object
       Dim iPath As String
       Dim NewNm As String
    
       iPath = "C:\Temp-RL\" ' Dein Quellordner
       Set FSO = CreateObject("Scripting.FileSystemObject")
       Set FD = FSO.GetFolder(iPath)
    
       For Each iFile In FD.Files
           If FSO.GetExtensionName(iFile) = "xls" Then
               NewNm = FSO.GetBaseName(iFile) & "-1." & FSO.GetExtensionName(iFile)
               Workbooks.Open iFile
               ' Hier kannst du deine Bearbeitung einfügen
               ActiveWorkbook.SaveAs iPath & NewNm
               ActiveWorkbook.Close
           End If
       Next iFile
    End Sub
  4. Bearbeitung einfügen: Ersetze den Kommentar ' Hier kannst du deine Bearbeitung einfügen mit dem Code, der deine spezifischen Änderungen an den Excel-Dateien vornimmt.

  5. Ausführen: Schließe den VBA-Editor und führe das Makro aus, indem du Alt + F8 drückst, das Makro auswählst und auf "Ausführen" klickst.


Häufige Fehler und Lösungen

  • Laufzeitfehler '91': Objektvariable oder With-Blockvariable nicht festgelegt: Stelle sicher, dass iFile als String deklariert ist. Beispiel:

    Dim iFile As String
  • Dateien werden nicht bearbeitet: Überprüfe, ob die Erweiterung der Dateien korrekt angegeben ist. Stelle sicher, dass du alle Excel-Dateien mit .xls oder .xlsx verwendest.

  • Bildschirmflackern: Um das Flackern zu vermeiden, füge folgende Zeilen vor und nach dem Hauptcode ein:

    Application.ScreenUpdating = False
    ' Dein Code hier
    Application.ScreenUpdating = True

Alternative Methoden

  • Excel VBA alle Dateien in Ordner nacheinander öffnen: Du kannst auch den Dir-Befehl verwenden, um alle Dateien in einem Verzeichnis nacheinander zu öffnen:

    iFile = Dir(iPath & "*.xls")
    Do While Len(iFile) > 0
       Workbooks.Open iPath & iFile
       ' Bearbeitung hier
       iFile = Dir
    Loop
  • Excel VBA alle Dateien eines Ordners auflisten: Verwende den FileDialog, um alle Dateien in einem Ordner aufzulisten und auszuwählen.


Praktische Beispiele

Hier ist ein einfaches Beispiel, um einen Wert in die Zelle A1 jeder Excel-Datei einzufügen:

Sub Testanwendung()
    Dim iPath As String
    Dim iFile As String
    Dim WB As Workbook

    iPath = "C:\Temp-RL\"
    iFile = Dir(iPath & "*.xls")

    Do While Len(iFile) > 0
        Set WB = Workbooks.Open(iPath & iFile)
        WB.Sheets(1).Range("A1").Value = "Test-Eintrag"
        WB.Save
        WB.Close
        iFile = Dir
    Loop
End Sub

Tipps für Profis

  • Verwende Option Explicit am Anfang deines Moduls, um sicherzustellen, dass alle Variablen deklariert sind. Dies hilft, Laufzeitfehler zu vermeiden.
  • Nutze With-Anweisungen, um den Code leserlicher und effizienter zu gestalten, insbesondere bei wiederholten Zugriffen auf das gleiche Objekt:

    With WB.Sheets(1)
      .Range("A1").Value = "Test-Eintrag"
      ' Weitere Änderungen vornehmen
    End With

FAQ: Häufige Fragen

1. Wie kann ich sicherstellen, dass alle Excel-Dateien bearbeitet werden? Stelle sicher, dass der Filter im Dir-Befehl korrekt ist und die Dateien tatsächlich die erwartete Erweiterung haben.

2. Was mache ich, wenn ich mehr als eine Arbeitsblattdatei habe? Verwende WB.Sheets(i) anstelle von WB.Sheets(1), um auf spezifische Blätter zuzugreifen.

3. Was ist der Unterschied zwischen Save und SaveAs? Save speichert die Änderungen in der aktuellen Datei, während SaveAs eine neue Datei mit dem angegebenen Namen und Pfad speichert.

4. Wie kann ich den Pfad dynamisch anpassen? Du kannst eine Eingabeaufforderung zur Auswahl des Ordners verwenden, z.B. mit Application.FileDialog(msoFileDialogFolderPicker).

5. Wie kann ich sicherstellen, dass ich keine Daten überschreibe? Überprüfe, ob die Datei bereits existiert, bevor du SaveAs aufrufst, und passe den Dateinamen entsprechend an.

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige