zippoex
Goto Top

Skript für den Import von csv Daten in jeweils neue Spalte einer xlsm bzw xlsx Datei

Hallo zusammen,

bin neu hier und hoffe mal, dass ich nicht die Antwort auf meine Frage hier in dem Forum vielleicht übersehen habe.
Falls doch bin ich natürlich über einen Hinweis dankbar!

Zur Frage:

Eine Software gibt mir je Versuch eine .csv Datei mit jeweils einer Spalte und unterschiedlicher Zeilenanzahl in einem Ordner gesammelt aus.
Ich möchte nun, die .csv Daten so importieren, dass diese (geordnet nach aufsteigendem numerischen Namen der .csv Dateien) jeweils eine neue Spalte in einer "normalen" .xlsx/xlsm Excel-Arbeitsmappe (benutze 2013) darstellen.

Ein relativ ähnliches Problem wurde hier:
Alle CSV-Dateien in einem Ordner mit einem VBA Makro einlesen
bzw hier:
Alle CSV-Dateien in einem Ordner mit einem VBA Makro einlesen Teil 2
gelöst, jedoch kann ich den Code nicht erfolgreich ablaufen lassen. (Ja habe den Dateipfad geändert :D)

Falls mir jemand weiterhelfen könnte wäre ich sehr dankbar!


Beste Grüße!

Content-Key: 239910

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

Printed on: April 25, 2024 at 22:04 o'clock

Mitglied: 116301
Solution 116301 Jun 03, 2014, updated at Jun 05, 2014 at 10:10:32 (UTC)
Goto Top
Hallo ZippoeX!

Mit aufsteigend numerischen Namen in etwa so (Macro in *.xlsm):
Option Explicit
Option Compare Text

Const CsvFolder = "E:\Test\Csv"  

Sub CsvImport()
    Dim oFso As Object, oFile As Object, aText As Variant
    Dim ColCount As Long, i As Long
    
    Set oFso = CreateObject("Scripting.FileSystemObject")  
    
    ActiveSheet.UsedRange.ClearContents
    
    ColCount = 1
    
    For Each oFile In oFso.GetFolder(CsvFolder).Files
        If oFso.GetExtensionName(oFile.Name) Like "csv" Then  
            aText = Split(oFso.OpenTextFile(oFile.Path).ReadAll, vbNewLine)
            
            Cells(1, ColCount).Value = oFso.GetBaseName(oFile.Name)
        
            For i = 0 To UBound(aText)
                If aText(i) <> "" Then  
                    Cells(i + 2, ColCount).Value = Trim(aText(i))
                End If
            Next
            ColCount = ColCount + 1
        End If
    Next
End Sub

Grüße Dieter
Member: ZippoeX
ZippoeX Jun 03, 2014 updated at 15:56:07 (UTC)
Goto Top
Vielen Dank, das sieht sehr sehr vielversprechend aus!

Excel möchte das jetzt allerdings alles in eine Zeile schreiben (seltsamerweise mit Ausnahme von Spalte 4?!) und da die Zahlen nicht wirklich durch einen Tabstop o.ä. getrennt sind, fällt mir das Trennen schwer. Theoretisch könnte man nach dem Muster "abcdef,xy" trennen, da alle Zahlen (bis auf die Runden) zwei Nachkommastellen haben. Der Zahlenbereich davor kann für abcd auch 0 annehmen und die ganze Zahl auch negativ sein, daher fällt mir gerade nichts ein zum effektiven Trennen.

Nachtrag: Ich denke es hängt mit dem Eintrag der 1. Zeile in den csv Dateien zusammen. der ist nämlich "blablabla" für alle csv's außer für die 4. Datei wo es einfach nur blablabla ohne Anführungszeichen ist. (warum auch immer; vermutlich am einfachsten die " " zu entfernen)
Nachtrag2: Die Gänsefüße sind nur in der xlsm zu finden, das Format ist angeblich auch "Standard" in den csv's (einschließlich Nr. 4)

Besten Dank aber auf jeden Fall für das Skript schon soweit!
Mitglied: 116301
116301 Jun 03, 2014 at 16:29:13 (UTC)
Goto Top
Hallo ZippoeX!

Eine Software gibt mir je Versuch eine .csv Datei mit jeweils einer Spalte und unterschiedlicher Zeilenanzahl in einem Ordner gesammelt aus.
Darunter verstehe ich etwas in dieser Art:
Wert_Zeile1
Wert_Zeile2
...
Wenn es so aufgebaut ist:
Wert1;Wert2;Wert...
Dann sind das mehrere Spalten?

Grüße Dieter
Member: ZippoeX
ZippoeX Jun 03, 2014 at 16:58:41 (UTC)
Goto Top
Ja deine Ansicht stimmt auf jeden Fall!
In den csv's ist jeweils eine Spalte mit jeweils einem Datenpunkt je Zeile (Muss also nicht mit Text in Spalten aufgetrennt werden!) Diese eine Spalte möchte ich quasi einfach nur kopieren: dh A:A aus csvnr1 wird A:A in der xslm; A:A aus csvnr2 wird B:B in der xslm usw...

Momentan sieht das für alle csv's außer csvnr4 leider so aus.

01. Wert_Zeile1WertZeile2WertZeile3....
02. leer

d.h. das Skript schreibt mir beispielsweise die Spalte aus csvnr1 in A2 und gibt mir die Spalte aus csvnr2 in Zeile B2 aus. Das seltsame ist nur, dass es das nicht für csvnr4 tut, wo die Spalte aus csvnr4 (A:A) perfekt in D:D der xlsm abgebildet wird. Die Ausgabe Specimen mit csvnr funktioniert für alles csv's wunderbar, d.h. ist in den Spalten jeweils in Zeile 1.

Vielleicht liegt es an meinen Excel-Einstellungen?
Mitglied: 116301
116301 Jun 03, 2014 at 18:09:47 (UTC)
Goto Top
Hallo ZippoeX!

Und in den Zeilen in der Art
Wert_Zeile1WertZeile2WertZeile3
gibt es keine String-Quoten (") oder sonstiges konstantes Muster z.B ein Komma mit immer gleicher Stellenanzahl o.ä.?

Grüße Dieter
Member: ZippoeX
ZippoeX Jun 03, 2014 at 18:30:19 (UTC)
Goto Top
Nope, das einzig (in den meisten Fällen) wiederkehrende Muster ist, dass die Zahlen zwei Nachkommastellen haben...
Was mich wie schon vorhin erwähnt sehr verwundert ist der Umstand, dass nur für csvnr4 in der 2. Zeile: YG-584 ohne Anführungszeichen anzeigt und der Rest dann in den kommenden Zeilen angezeigt wird und beim Rest der csvs in der xsml: "YG-584"Wert1.1_Wert1.2_Wert1.3 usw...
Mitglied: 116301
116301 Jun 03, 2014, updated at Jun 04, 2014 at 07:51:37 (UTC)
Goto Top
Hallo Zippoe!

Deine Kommentare kann ich nach Tests mit Deinen Csv-Dateien nicht nachvollziehen, denn alle Csv-Dateien enthalten tatsächlich nur eine Spalte (siehe Text-Editor mit Zeilenumbruch). Allerdings sind die Dateinamen sehr lang und die Spaltenbreiten müssten dementsprechend angepasst werden. Brauchst Du in der 1. Zeile den ganzen Dateinamen oder reicht ein Teil zwischen den (_)-Zeichen?

Die 1. Zeile der Csv-Dateien mit "YG-585-A" kann man, sofern sie nicht benötigt wird, einfach überspringen?

Da die Csv.Dateien allerdings außer Zahlen im Format '1234.12' auch Werte wie z.B. '25. Mai' oder 'Apr 15' beinhalten, stellt sich mir die Frage, ob diese Csv-Dateien per Excel erstellt wurden und die Zellen nicht als Zahlen formatiert waren/sind, was dann zu Fehlinterpretationen mit Datumswerten führt?

Außerdem sind die Zahlenwerte in den Csv-Dateien unterschiedlich d. h. mal mit Punkt und mal mit Komma (siehe Datei 4), was ja auch nicht so optimal ist?

Grüße Dieter
Member: ZippoeX
ZippoeX Jun 04, 2014 updated at 09:48:44 (UTC)
Goto Top
Ich benötige den Dateinamen eigentlich gar nicht zwingend, solange die csvs in der richtigen Reihenfolge gelistet sind.

Habe in csvnr4 punkte durch kommata ersetzt! (wollte ich eigentlich nicht abspeichern) Habe so viele Daten gestern angeschaut, dass es mir garnicht mehr aufgefallen ist. Also muss ich vermutlich meinem Excel nur beibringen dass ich das englische Format mit Kommata/Punkten nehme und dann sollte dein Skript funktionieren!

Das ist vermutlich tatsächlich das hüpfende Komma mit der Zahlenerkennung...

Nachtrag: Gerade getestet...funktioniert nicht :/
Mitglied: 116301
116301 Jun 04, 2014 at 10:30:17 (UTC)
Goto Top
Hallo ZippoeX!

Also muss ich vermutlich meinem Excel nur beibringen dass ich das englische Format mit Kommata/Punkten nehme und dann sollte dein Skript funktionieren!
Die Punkte durch Komma zu ersetzen wäre beim importieren nicht das Problem, sondern eher die Zeilen, in denen beim Export in die Csv-Dateien verschiedene Zahlenwerte mit Punkt als Datum ('Apr 15' oder '31. Mai') interpretiert worden sind.

Wenn also in einer deutschen Excel-Version die Zellen vor dem Einfügen ein Standardformat haben, dann werden z.B. Werte wie 4.15 als 'Apr 15' oder 31.5 als '31. Mai' übernommen, was wiederum bedeutet, dass der interne Zellwert (cell.Value) einen ganz anderen Wert enthält und zwar '42095' (=01.04.2015) anstatt '4.15' und '41790' (=31.05.2014) anstatt 31.5...

Grüße Dieter
Member: ZippoeX
ZippoeX Jun 04, 2014 updated at 11:51:50 (UTC)
Goto Top
Mh okay, da es ja in meinem Fall relativ viele Datenpunkte gibt, könnte ich die Datumsangaben auch einfach ausklammern, da ich keinen Weg sehe wie das anders in die csv geschrieben werden sollte...

Bliebe trotzdem noch das Zeilenproblem :/

EDIT: ALSO habe mir die csvs ohne den YG header ausgeben lassen und das Format der Zahlenerkennung umgestellt. Habe jetzt keine Datumsangaben mehr in den csvs. Import klappt auch reibungslos.
ABER: Das VBA-Skript schreibt weiterhin leider nur alles in Zeile 2
Mitglied: 116301
Solution 116301 Jun 04, 2014, updated at Jun 05, 2014 at 13:39:58 (UTC)
Goto Top
Hallo ZippoeX!

OK, ich hatte angenommen das die Csv-Dateien eventuell per Excel erstellt worden sind und dann hätte man an dieser Stelle etwas ändern müssen...

Hier mal ein Code, der zum einen die Punkte durch Komma und die Datumswerte durch Zahlenwerte ersetzt. Die erste Zeile mit den Dateinamen lasse ich jetzt mal in gekürzter Form ala 'Csv-001' drinn und die erste Zeile der Csv-Datei mit "YG-585-A" wird übersprungen:
Option Explicit
Option Compare Text

Const CsvFolder = "E:\Test\Csv"  

Public Sub CsvImport()
    Dim oFso As Object, oFile As Object
    Dim aTemp As Variant, aText As Variant
    Dim sText As String, sValue As String
    Dim dValue As Double, iColCount As Long, iRowStart As Long, i As Long
    
    Set oFso = CreateObject("Scripting.FileSystemObject")  
    
    ActiveSheet.UsedRange.ClearContents
    
    Application.ScreenUpdating = False
    
    iColCount = 1
    
    For Each oFile In oFso.GetFolder(CsvFolder).Files
        If oFso.GetExtensionName(oFile.Name) Like "csv" Then  
            sText = oFso.OpenTextFile(oFile.Path).ReadAll
            aText = Split(Replace(sText, vbCr, ""), vbLf)  
            
            aTemp = Split(Split(oFso.GetBaseName(oFile.Name), ".")(0), "_")  
            
            Cells(1, iColCount).Value = "Csv-" & aTemp(UBound(aTemp))  
        
            iRowStart = IIf(IsNumeric(aText(0)), 2, 1)
            
            For i = 2 - iRowStart To UBound(aText)
                sValue = aText(i)
                If sValue <> "" Then  
                    If IsNumeric(sValue) Then
                        dValue = CDbl(Replace(sValue, ".", ","))  
                    Else
                        dValue = GetDoubleValue(sValue)
                    End If
                    
                    Cells(iRowStart + i, iColCount).Value = dValue
                End If
            Next
            iColCount = iColCount + 1
        End If
    Next

    ActiveSheet.UsedRange.NumberFormat = "#,##0.00"  
    
    Application.ScreenUpdating = True
End Sub

'Konvertiert Formate wie '15. Mai' oder 'Apr 15' in Zahlenwerte  
Private Function GetDoubleValue(ByVal sValue As String) As Double
    Dim aTemp As Variant, aMonths As Variant
    
    aTemp = Split(sValue)
    
    If UBound(aTemp) = 0 Then
        aTemp = Split(sValue, ".")  
    End If
    
    If UBound(aTemp) = 1 Then
        aMonths = Array("jan", "feb", "mrz", "apr", "mai", "jun", "jul", "aug", "sep", "okt", "nov", "dez")  
        
        With WorksheetFunction
            If Not IsNumeric(aTemp(0)) Then
                GetDoubleValue = CDbl(.Match(Trim(aTemp(0)), aMonths, 0) & "," & aTemp(1))  
            ElseIf Not IsNumeric(aTemp(1)) Then
                GetDoubleValue = CDbl(aTemp(0) & "," & .Match(Trim(aTemp(1)), aMonths, 0))  
            End If
        End With
    End If
End Function

EDIT: ALSO habe mir die csvs ohne den YG header ausgeben lassen und das Format der Zahlenerkennung umgestellt. Habe jetzt keine Datumsangaben mehr in den csvs. Import klappt auch reibungslos. ABER: Das VBA-Skript schreibt weiterhin leider nur alles in Zeile 2
Kann ich irgendwie nicht nachvollziehen, mein Ergebnis anhand Deiner Csv-Dateien sieht bei mir in etwa so aus:
80296cbfb33c18b9b362e4e1f0c581d8

Grüße Dieter

[edit]
Code insoweit geändert, das der Import der Csv-Dateien in Abhängigkeit davon, ob sich in der 1. Zeile ein Zahlenwert oder ein Text befindet, entweder ab der 1. Zeile oder ab der 2.Zeile beginnt.
[/edit]
[edit2]
Code insoweit geändert, dass sowohl vbCrLf als auch (nur) vbLf als Zeilenumbrüche erkannt werden
[/edit2]
Mitglied: 116301
116301 Jun 04, 2014 updated at 18:04:12 (UTC)
Goto Top
Hallo ZippoeX!

Also, die Csv-Dateien die Du mir zuletzt zugeschickt hast, werden bei mir genauso einwandfrei importiert, wie die vorhergehenden. Einziger Unterschied ist, dass die neueren Dateien im Gegensatz zu den anderen Dateien in der 1. Zeile keinen Text in der Form 'YG-585-A' haben, also bereits mit einem Zahlenwert beginnen.

Von daher habe ich den letzten Code insoweit geändert,dass je nach Inhalt der 1. Zeile (Zahl oder Text), die Csv-Dateien entweder ab der 1. Zeile oder ab der 2. Zeile importiert werdenface-wink

Ob die Csv-Dateien nun Punkt, Komma oder Datumswerte enthalten oder nicht ist im Prinzip egal. D.h in beiden Fällen sollten die Daten richtig verarbeitet werden...

Grüße Dieter