Automat. Zusammenfassen von über 1500 Tabellen
Hallo!
Ich hab mich erst seit einiger Zeit mit Excelmakros beschäftigt und stoße leider schon an meine Grenzen . Bräuchte eure Hilfe.
Also ich will Labordaten aus über 1500 Exceldateien zusammenführen. Die Tabellen sehen wie folgt aus:
Ich hab mich erst seit einiger Zeit mit Excelmakros beschäftigt und stoße leider schon an meine Grenzen . Bräuchte eure Hilfe.
Also ich will Labordaten aus über 1500 Exceldateien zusammenführen. Die Tabellen sehen wie folgt aus:
A | B | C | D | |
1 | Laborident | 12.06.2007 | 06.06.2006 | 15.03.2005 |
2 | AP37 | 71 | 68 | 81 |
3 | BAS | 0 | 0.4 | 0.5 |
4 | BAS-A | 0.02 | ||
5 | BILIG | 0.8 | 0.8 | 1.0 |
usw... aber in allen Tabellen sind nicht immer die gleichen Parameter bestimmt worden.
Auch ist in einer Tabelle z.B. nur von einem Datum eine Auswertung, in einer anderen sind (wie hier im Beispiel 3 Daten ausgewertet worden)
Zum Auslesen habe ich auch Makros gefunden, das klappt auch gut, allerdings nur immer für das erste Datum (also hier in Spalte B), denn ich weiß nicht wie ich programmieren, dass auch C, D usw. ausgelesen werden, wenn sich dort Werte befinden (erkenntlich daran, dass in der ersten Zeile das Datum befindet).
Ausserdem bräuchte ich in die erste Spalte des Auswertebogens den Dateinamen, aus dem die Daten stammen.
Die Dateinamen sehen wie folgt aus:
Mustermann_Karl-Friedrich_01.02.1962.xls
Oder ist es schwierig diese Dateinamen in ihre Bestandteile aufzuteilen? Also Name in eine Spalte, in die andere Vornamen und Gebdatum?
Ich weiß ich hab sehr viele Fragen gestellt, vielen Dank im vorraus, bin nämlich schon halb am verzweifeln...
Anbei das Makro was ich bisher zum Auslesen nutze:
Sub Auslesen()
Dim oMe As Object, sSuchbegriff(), sBereich As String, iZeile As Integer, sKennz As String
Dim iSbMax As Integer, iLK As Integer, i As Integer, sWbName As String, rFound As Range, vWert As Variant
Dim oFS As Object, oDatei As Object, wsTabelle As Worksheet, bEintrag As Boolean
Set oMe = ThisWorkbook.Worksheets("Tabelle1") 'Zieltabelle (in der gerade geöffneten Datei)
iZeile = 2 'ab dieser Zeile Ergebnisse in die Zieltabelle eintragen
Const sDateiPfad As String = "E:\Labordaten\" 'Pfad für zu durchsuchende Excel-Dateien; mit Backslash am Ende
sKennz = "" 'Nur Tabellen, deren Name mit dem Kennzeichen beginnt, verarbeiten
sSuchbegriff = Array("Laborident", "BZ", "CA", "CHOL", "CRP", "EIW", "HB", "HBA1C", "K") 'Liste der
Suchbegriffe
sBereich = "A1:A100"
iSbMax = UBound(sSuchbegriff) 'Höchster Index der Suchbegriffmatrix
iLK = Len(sKennz) 'Länge des Tabellennamen-Kennzeichens
Set oFS = CreateObject("Scripting.FileSystemObject")
For Each oDatei In oFS.GetFolder(sDateiPfad).Files
sWbName = oDatei.Name
Workbooks.Open (oDatei.Path)
For Each wsTabelle In Workbooks(sWbName).Worksheets()
If StrComp(Left(wsTabelle.Name, iLK), sKennz, vbTextCompare) = 0 Then
bEintrag = False
For i = 0 To iSbMax
Set rFound = wsTabelle.Range(sBereich).Find(sSuchbegriff(i), LookIn:=xlValues)
If Not rFound Is Nothing Then
vWert = wsTabelle.Cells(rFound.Row, rFound.Column + 4).Value
oMe.Cells(iZeile, i + 3).Value = vWert
bEintrag = True
End If
Next
If bEintrag Then iZeile = iZeile + 1 'mindestens ein Eintrag erfolgt, daher neue Zeile
End If
Next
Workbooks(sWbName).Saved = True
Workbooks(sWbName).Close
Next
End Sub
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 102727
Url: https://administrator.de/forum/automat-zusammenfassen-von-ueber-1500-tabellen-102727.html
Ausgedruckt am: 16.05.2025 um 02:05 Uhr
8 Kommentare
Neuester Kommentar
Hallo inhwue und willkommen im Forum!
Einige Fragen:
Der Code zum Ermitteln der Namensteile (einzufügen nach Zeile 17) sähe etwa so aus:
Die Variablendeklarationen wären dann auch noch oberhalb zu platzieren (etwa nach Zeile 4):
Grüße
bastla
P.S.: Bitte verwende zum Posten von Programmzeilen die ...
... allerdings nur immer für das erste Datum
Die ursprüngliche Fassung des Makros hatte eine etwas andere Zielsetzung, daher wird nur jeweils eine Spalte übertragen.Einige Fragen:
- Befinden sich die Daten immer in der ersten Tabelle der jeweiligen Datei (würde das Überprüfen der restlichen Tabellen überflüssig machen - die Abfrage nach einem Kennzeichen im Tabellennamen wird ja, Deinem Code zufolge, ohnehin nicht benötigt)?
- Sollen alle Zeilen der Quelltabelle übertragen werden, oder ist es auch in diesem Fall nötig, nur bestimmte Zeilen zu suchen?
- Falls alle Zeilen benötigt werden: Hat jede Zeile einen Wert in Spalte A?
- Sollen alle Werte einer Zeile übertragen werden?
- Wo sollen die aus dem Dateinamen ermittelten Daten in der Zieltabelle genau platziert werden (welche 3 Zellen)?
Der Code zum Ermitteln der Namensteile (einzufügen nach Zeile 17) sähe etwa so aus:
aNTeile = Split(sWbName, "_")
sZuname = aNTeile(0)
sVorname = aNTeile(1)
sGebDat = Left(aNTeile(2), InStr(aNTeile(2), ".")-1)
Dim aNTeile(), sZuname As String, sVorname As String, sGebDat As String
bastla
P.S.: Bitte verwende zum Posten von Programmzeilen die ...
Mir ist noch nicht klar was du denn nachher mit der einen Tabelle anstellen möchtest, die dann aus den ca. 150 kleineren besteht.
Ich könnte mir vorstellen, dass du eigentlich meinst die Daten auf eine logische Art zu verknüpfen. Dafür wäre dann ein LIMS (Labor Informations Management System) zuständig. Dabei würde sich ein LIMS z.B. auch merken aus welcher Datei die Daten stammen, zu welchem Messgerät gehören und von welchem Mitarbeiter erstellt gemessen wurden.
Sobald die Personendaten in irgendeiner Form sich auf eine Person (Patienten?) beziehen ist auch der Datenschutz wichtig. Ein LIMS könnte beispielsweise festlegen wer diese Personen beziehbaren Daten sehen darf und protokolliert wer diese verarbeitet hat.
Das sind Funktionen die weit über Excel hinausgehen. (Wobei ich glaube fast Bastla könnte das mit einem Makro regeln. Es scheint wohl nix zu geben was Bastla nicht mal eben schnell in einem Makro macht.)
Gruß Rafiki
Ich könnte mir vorstellen, dass du eigentlich meinst die Daten auf eine logische Art zu verknüpfen. Dafür wäre dann ein LIMS (Labor Informations Management System) zuständig. Dabei würde sich ein LIMS z.B. auch merken aus welcher Datei die Daten stammen, zu welchem Messgerät gehören und von welchem Mitarbeiter erstellt gemessen wurden.
Sobald die Personendaten in irgendeiner Form sich auf eine Person (Patienten?) beziehen ist auch der Datenschutz wichtig. Ein LIMS könnte beispielsweise festlegen wer diese Personen beziehbaren Daten sehen darf und protokolliert wer diese verarbeitet hat.
Das sind Funktionen die weit über Excel hinausgehen. (Wobei ich glaube fast Bastla könnte das mit einem Makro regeln. Es scheint wohl nix zu geben was Bastla nicht mal eben schnell in einem Makro macht.)
Gruß Rafiki
Hallo inhwue!
Soll tatsächlich für jede Datei eine eigene Überschriftszeile (in Deinem Beispiel
erzeugt werden?
Ich wäre davon ausgegangen, dass alle möglichen Laboridentifikationen vorgegeben und die entsprechenden Werte in die jeweiligen Spalten eingetragen würden ...
... oder sollten ohnehin nur bestimmte Werte (lt Deinem Code wären dies, im Widerspruch zum obigen Beispiel, nur "BZ", "CA", "CHOL", "CRP", "EIW", "HB", "HBA1C" und "K") übernommen werden?
Kann davon ausgegangen werden, dass (so wie im abgebildeten Tabellenblatt) die Datumswerte immer in Zeile 1 ab Spalte E und die einzelnen Messwerte dann ab Zeile 2 angeführt sind, und dies ohne Leerzeilen, sodass als Ende des Datenblockes die Zeile mit der letzten Eintragung in Spalte A angenommen werden kann?
Grüße
bastla
P.S.: Meine Ungenauigkeit hinsichtlich der Zerlegung des 3. Namensbestandteiles hast Du erfreulicher Weise schon beseitigt - ich hatte nicht beachtet, dass für das Datum Punkte als Trennzeichen verwendet werden ...
Soll tatsächlich für jede Datei eine eigene Überschriftszeile (in Deinem Beispiel
Name Vorname Geb.datum DatumLabor AP37 BAS ...
Ich wäre davon ausgegangen, dass alle möglichen Laboridentifikationen vorgegeben und die entsprechenden Werte in die jeweiligen Spalten eingetragen würden ...
... oder sollten ohnehin nur bestimmte Werte (lt Deinem Code wären dies, im Widerspruch zum obigen Beispiel, nur "BZ", "CA", "CHOL", "CRP", "EIW", "HB", "HBA1C" und "K") übernommen werden?
Kann davon ausgegangen werden, dass (so wie im abgebildeten Tabellenblatt) die Datumswerte immer in Zeile 1 ab Spalte E und die einzelnen Messwerte dann ab Zeile 2 angeführt sind, und dies ohne Leerzeilen, sodass als Ende des Datenblockes die Zeile mit der letzten Eintragung in Spalte A angenommen werden kann?
Grüße
bastla
P.S.: Meine Ungenauigkeit hinsichtlich der Zerlegung des 3. Namensbestandteiles hast Du erfreulicher Weise schon beseitigt - ich hatte nicht beachtet, dass für das Datum Punkte als Trennzeichen verwendet werden ...
@Rafiki
Du machst mich noch ganz verlegen ...
... auf jeden Fall danke für die Blumen.
Deine Hinweise sind sicher wichtig, wobei ich eigentlich vermutet hätte, dass die entstehende Zusammenfassung ein Zwischenschritt für eine weitere Verarbeitung (in Datenbankform) wäre - deshalb auch meine Überlegung, einen einheitlichen Satzaufbau ("... alle möglichen Laboridentifikationen ...") zu verwenden ...
Grüße
bastla
Du machst mich noch ganz verlegen ...
... auf jeden Fall danke für die Blumen.
Deine Hinweise sind sicher wichtig, wobei ich eigentlich vermutet hätte, dass die entstehende Zusammenfassung ein Zwischenschritt für eine weitere Verarbeitung (in Datenbankform) wäre - deshalb auch meine Überlegung, einen einheitlichen Satzaufbau ("... alle möglichen Laboridentifikationen ...") zu verwenden ...
Grüße
bastla
Hallo inhwue!
Versuch es einmal mit folgendem Entwurf:
Zu Testzwecken sind in Zeile 19 einige ID eingetragen, aber natürlich ist die Liste noch zu vervollständigen (wobei die einzelnen ID nicht durchgängig in Großbuchstaben geschrieben werden müssen - wird im Code berücksichtigt).
Bei jedem Durchlauf wird übrigens vorweg die Zieltabelle gelöscht (um eine Anpassung an eine ev zwischenzeitlich geänderte ID-Liste zu ermöglichen).
Zeilen der Quelltabelle mit ID, welche in der oben genannten Liste nicht vorkommen, werden (kommentarlos) übergangen (ließen sich über einen "Else"-Teil nach Zeile 50 noch anzeigen/dokumentieren).
Noch ein Hinweis auf Zeile 37: Hier wird festgelegt, in welcher Tabelle die Quelldaten gesucht werden sollen (die Angabe mit Tabellenname, also "Tabelle2", wäre die sicherere Variante). Zu überlegen wäre, ob es ein eindeutiges Kennzeichen für die "richtige" Tabelle gibt - dann könnten alle Tabellen nach dieser Kennung durchsucht werden, was die Sicherheit weiter erhöhen würde.
Grüße
bastla
Versuch es einmal mit folgendem Entwurf:
Sub zfs()
Dim oMe As Object, iZielZeile As Integer, iZielSpalte As Integer, iQuellZeile As Integer, iQuellSpalte As Integer
Dim aID(), sID As String, d As Object, iSp As Integer
Dim Anteile() As String, sZuname As String, sVorname As String, sGebDat As String
Dim i As Integer, sWbName As String, vWert As Variant
Dim oFS As Object, oDatei As Object
Set oMe = ThisWorkbook.Worksheets("Tabelle1") 'Zieltabelle (in der gerade geöffneten Datei)
iZielZeile = 2 'ab dieser Zeile Ergebnisse in die Zieltabelle eintragen
Const iZielAbSpalte As Integer = 5 'ab dieser Spalte werden ID (Überschrift) und zugehörige Messwerte eingetragen
Const iQuelleAbZeile As Integer = 2 'ab dieser Zeile ID in Spalte A
Const iQuelleAbSpalte As Integer = 5 'ab dieser Spalte Datumseinträge bzw Messwerte in der jeweiligen Quelltabelle
Const sDateiPfad As String = "E:\Labor\" 'Pfad für zu durchsuchende Excel-Dateien; mit Backslash am Ende
oMe.Cells.Clear 'gesamte Tabelle löschen
oMe.Range("A1:D1").Value = Array("Name", "Vorname", "Geb.datum", "DatumLabor") 'Überschrift der ersten 4 Spalten
aID = Array("AP37", "BAS", "BAS-A", "BILIG", "BZ", "CA", "CHOL", "CRP", "EIW", "HB", "HBA1C") 'benötigte ID hier festlegen
Set d = CreateObject("Scripting.Dictionary")
For i = 0 To UBound(aID) 'alle ID durchgehen
iZielSpalte = iZielAbSpalte + i 'Spaltennummer ermitteln
oMe.Cells(1, iZielSpalte).Value = aID(i) 'Spaltenüberschrift eintragen
d.Add UCase(aID(i)), iZielSpalte 'für Vergleich in Großbuchstaben umwandeln und in "Dictionary" einfügen
Next
Set oFS = CreateObject("Scripting.FileSystemObject")
For Each oDatei In oFS.GetFolder(sDateiPfad).Files
sWbName = oDatei.Name
Anteile = Split(sWbName, "_")
sZuname = Anteile(0)
sVorname = Anteile(1)
sGebDat = Left(Anteile(2), InStr(Anteile(2), ".xls") - 1)
Workbooks.Open (oDatei.Path)
With Worksheets(2) 'immer 2. Tabelle - falls immer "Tabelle2", dann: Worksheets("Tabelle2")
iQuellSpalte = iQuelleAbSpalte
Do While .Cells(1, iQuellSpalte) <> "" 'alle Datumsspalten bearbeiten
oMe.Cells(iZielZeile, 1).Value = sZuname
oMe.Cells(iZielZeile, 2).Value = sVorname
oMe.Cells(iZielZeile, 3).Value = sGebDat
oMe.Cells(iZielZeile, 4).Value = .Cells(1, iQuellSpalte) 'Datum übertragen
iQuellZeile = iQuelleAbZeile
Do While .Cells(iQuellZeile, 1) <> "" 'alle Einträge in Spalte A durchgehen
sID = Trim(UCase(.Cells(iQuellZeile, 1))) 'ID auslesen und (für Vergleich) in Großbuchstaben umwandeln
If d.Exists(sID) Then 'ID bekannt?
iZielSpalte = d.Item(sID) 'dann zugehörige Spaltennummer ermitteln
vWert = .Cells(iQuellZeile, iQuellSpalte).Value ' Messwert auslesen
oMe.Cells(iZielZeile, iZielSpalte).Value = vWert 'und in aktuelle Zielzelle eintragen
End If
iQuellZeile = iQuellZeile + 1 'nächste Datenzeile
Loop
iQuellSpalte = iQuellSpalte + 1 'nächste Datumsspalte
iZielZeile = iZielZeile + 1 'nächste Zeile der Zieltabelle
Loop
End With
Workbooks(sWbName).Saved = True
Workbooks(sWbName).Close
Next
End Sub
Bei jedem Durchlauf wird übrigens vorweg die Zieltabelle gelöscht (um eine Anpassung an eine ev zwischenzeitlich geänderte ID-Liste zu ermöglichen).
Zeilen der Quelltabelle mit ID, welche in der oben genannten Liste nicht vorkommen, werden (kommentarlos) übergangen (ließen sich über einen "Else"-Teil nach Zeile 50 noch anzeigen/dokumentieren).
Noch ein Hinweis auf Zeile 37: Hier wird festgelegt, in welcher Tabelle die Quelldaten gesucht werden sollen (die Angabe mit Tabellenname, also "Tabelle2", wäre die sicherere Variante). Zu überlegen wäre, ob es ein eindeutiges Kennzeichen für die "richtige" Tabelle gibt - dann könnten alle Tabellen nach dieser Kennung durchsucht werden, was die Sicherheit weiter erhöhen würde.
Grüße
bastla