inhwue
Goto Top

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:

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

Content-Key: 102727

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

Printed on: April 16, 2024 at 10:04 o'clock

Member: bastla
bastla Nov 26, 2008 at 13:37:51 (UTC)
Goto Top
Hallo inhwue und willkommen im Forum!
... 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)  
Die Variablendeklarationen wären dann auch noch oberhalb zu platzieren (etwa nach Zeile 4):
Dim aNTeile(), sZuname As String, sVorname As String, sGebDat As String
Grüße
bastla

P.S.: Bitte verwende zum Posten von Programmzeilen die ...
Member: inhwue
inhwue Nov 26, 2008 at 14:07:06 (UTC)
Goto Top
Hallo Bastla!

Vielen Dank für deine schnelle Antwort!
Das mit den Namen, Vornamen und Gebdatum eintragen klappt!!

Also zu deinen Fragen:


Die Daten finden sich alle in Tabelle2 (wieso auch immer, Tabelle1 ist leer)

Zu der zweiten Frage: Die Sache ist, dass nicht zu bei jeder Person alle Werte im Labor ermittelt wurden, von daher ist jede Tabelle also solche individuell. Daher gibt es in Spalte A die Laboridentifikation: z.B. AP37, BAS, BZ usw... um zu wissen was für Werte sich in den darauffolgenden Spalten befinden!

Die Übertragung der Werte stelle ich mir so vor (um es zu veranschaulichen)

.

Das Problem ist aber leider das die Anzahl der Labore ganz unterschiedlich ist, manche haben nur eines, manche haben 10 verschiedene Daten, an den Labor abgenommen wurde

Name Vorname Geb.datum DatumLabor AP37 BAS
Mustermann Max 01.01.1950 12.06.2007 71 0
Mustermann Max 01.01.1950 06.06.2006 68 0.4

das Beispiel ist bezogen auf Werte der Tabelle ganz oben. Dateiname wäre Name_Vorname_01.01.1950.xls

Nochmal das Makro jetzt übersichtlicher (neu überarbeitet!):
Sub zfs()


Dim oMe As Object, sSuchbegriff(), sBereich As String, iZeile As Integer, sKennz As String
Dim Anteile() As String, sZuname As String, sVorname As String, sGebDat 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:\Labor\" '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

Anteile = Split(sWbName, "_")  
sZuname = Anteile(0)
sVorname = Anteile(1)

sGebDat = Left(Anteile(2), InStr(Anteile(2), ".xls") - 1)  

oMe.Cells(iZeile, 1).Value = sZuname
oMe.Cells(iZeile, 2).Value = sVorname
oMe.Cells(iZeile, 3).Value = sGebDat


    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 + 4).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

Vielen Dank!

P.S. So sieht eine Originaldatei aus, wo es 2 Labore gab:
27de42942ff2c78fd876ebef24da70b7-excel_tabelle
Member: Rafiki
Rafiki Nov 26, 2008 at 17:55:42 (UTC)
Goto Top
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
Member: bastla
bastla Nov 26, 2008 at 17:57:19 (UTC)
Goto Top
Hallo inhwue!

Soll tatsächlich für jede Datei eine eigene Überschriftszeile (in Deinem Beispiel
 Name 	 Vorname 	 Geb.datum 	 DatumLabor 	 AP37 	 BAS 	 ...
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 ...
Member: bastla
bastla Nov 26, 2008 at 18:07:16 (UTC)
Goto Top
@Rafiki
Du machst mich noch ganz verlegen ...
... auf jeden Fall danke für die Blumen. face-smile

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
Member: inhwue
inhwue Nov 26, 2008 at 19:16:09 (UTC)
Goto Top
Hallo!

Vielen Dank für die große Resonanz! und auch so schnell...

@bastla:
Nein, so hatte ich das nicht gedacht, es soll insgesamt nur eine Überschriftenzeile geben:

Also

NameVornameGebdat.LabdatWert1Wert2Wert3...Wert70
MustermannMax04.12.6023.06.08562...2
MustermannMax04.12.6014.07.06125...4
Beispiel2NN01.01.4013.03.081 4...6
Beispiel3MM04.04.6615.07.06125...
Beispiel3MM04.04.6618.07.0612.55...5

Herr Mustermann ist der von dem jpeg-Bild. Man sieht da auch 2 Labore, nämlich vom 23.06.08 und vom 14.07.06. Im Gegesatz zu Beispiel2 hier gabs nur 1 Labor, d.h. bei seiner xls-file waren nur Werte in der Spalte E, Spalte F(wo ein 2tes Labor gewesen wäre) ist schon leer.
Beispiel 3 hat wiederrum 2 Labor, also sieht seine ursprüngliche xls-File aus wie die auf dem jpeg.

Ich hoffe ich habs einigermaßen verständlich gemacht. Das Problem liegt jetzt eindeutig darin, eine Schleife (oder wie man so was nennt, bin beim Programmieren ein ganz ganz blutiger Anfänger) zu programmieren, die die schaut, wieviel Labors gemacht wurden (am Besten bis wohin in der ersten Zeile ein Datum steht!!!).
Dementsprechend bei 2 Labors (=Datum in E1 und F1) 2 neue Zeilen in die zusammenfassende neue Datei schreibt, bzw wie bei Beispiel2 (nur Datum in E1, F1 ist schon frei...) nur eine Zeile, da es nur 1 Labor gab.

Es sollen fast alle Werte rausgelesen werden, so an die 90 - 100 Stück (kann aber in mehreren Teilen erfolgen)!

Ja der Datenblock ist dann zu Ende, wenn in der letzten Zeile in Spalte A nichts mehr steht.

@Rafiki: Es soll nacher (wie hoffentlich oben beschrieben) eine einzige Tabelle werden. Es sollen dann auch noch andere Werte reingenommen werden.

Also nochmal vielen vielen Dank!!!!
Member: bastla
bastla Nov 26, 2008 at 22:33:16 (UTC)
Goto Top
Hallo inhwue!

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
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
Member: inhwue
inhwue Dec 01, 2008 at 00:58:35 (UTC)
Goto Top
Hallo bastla!

Hat alles wunderbar ohne jegliche Probleme geklappt ! Danke, hast mir viel Zeit, Umstände und Grübelei erspart.

Gruss,
inhwue