Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1752to1756
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
Inhaltsverzeichnis

CSV effizient einlesen

CSV effizient einlesen
15.04.2020 23:14:24
dx145
Hallo zusammen
Ich habe aus Messungen eine Menge csv Files, die heissen alle gleich unterscheiden sich nur anhand der Nummer in Klammern. Daher lese ich zuerst die Dateinamen ein und sortiere diese Anhand der Nummern in den Klammern. Diese CSV Files haben 3 Spalten und mehrere Tausend Zeilen. Diese will ich nebeneinander in excel darstellen, dass ich nachher eine Datenauswertung machen kann. Funktioniert auch alles nicht schlecht, nur das einlesen ist Sau langsam und wenn ich viele Daten habe schmmiert das System ab. -> keine Rückmeldung... Bei drei csv Dateien dauert es so 20s. Bei 20 ewig... es können aber auch mal 100 werden...
Geht das irgendwie effiienter?
Es geht vor allem um die CSVlesen Funktion
Der Code sieht wiefolgt aus:
Const MEASUREMENT_TITLE_ROW = 20
Const FIRST_MEASUREMENT_COLUMN = 5
Const SPACE_FOR_MEASUREMENT = 4
Sub formateFile()
Call bordersAndUnionAndInput("B6", "D6", "Status:")
Call bordersAndUnionAndInput("B7", "D7", "Inactive")
Call bordersAndUnionAndInput("F6", "H6", "Status:")
Call bordersAndUnionAndInput("F7", "H7", "Inactive")
Call bordersAndUnionAndInput("F8", "H8", "Anzahl Werte zur Mittelung:")
Call bordersAndUnionWithoutInput("F9", "H9")
Call bordersAndUnionAndInput("J6", "L6", "Status:")
Call bordersAndUnionAndInput("J7", "L7", "Inactive")
Call bordersAndUnionAndInput("J8", "L8", "Anzahl Werte zur Mittelung:")
Call bordersAndUnionWithoutInput("J9", "L9")
Call bordersAndUnionAndInput("N6", "P6", "Status:")
Call bordersAndUnionAndInput("N7", "P7", "Inactive")
Call bordersAndUnionAndInput("N8", "P8", "Zu plottende Messungsnummer:")
Call bordersAndUnionWithoutInput("N9", "P9")
Cells(MEASUREMENT_TITLE_ROW, 1).Value = "Pfad der Messung:"
Cells(MEASUREMENT_TITLE_ROW, 2).Value = "Messungsnr."
Cells(MEASUREMENT_TITLE_ROW - 1, 1).Value = "Mittelung der Maximalwerte"
Cells(MEASUREMENT_TITLE_ROW - 2, 1).Value = "Mittelung DC Werte"
End Sub
Sub CSVlesenV()
Call formateFile
Range("B7").Value = "Running"
Dim i, j As Integer, arrDaten, arrDaten2, arrTmp, lngR As Long
Dim line As String
Dim arrayOfElements
Dim linenumber As Integer
Dim elementnumber As Integer
Dim element As Variant
Dim csvPath As String
Set fso = CreateObject("Scripting.Filesystemobject")
csvPath = ThisWorkbook.Path + "\Messungen"
linenumber = 0
elementnumber = 0
i = MEASUREMENT_TITLE_ROW + 1
For Each f In fso.GetFolder(csvPath).Files
If LCase(Right(f.Name, 3)) = "csv" Then
Cells(i, 1).Value = f.Path
If InStr(f.Path, "(")  0 Then
Cells(i, 2).Value = Mid(f.Path, InStr(f.Path, "(") + 1, InStr(f.Path, ")") -  _
InStr(f.Path, "(") - 1)
'Cells(i, 2).Value = 0
Else
Cells(i, 2).Value = 1
End If
i = i + 1
End If
Next
Call A_B_Sortieren(MEASUREMENT_TITLE_ROW + 1, 1, i - MEASUREMENT_TITLE_ROW - 1)
'GoTo Sprungmarke
j = FIRST_MEASUREMENT_COLUMN
i = MEASUREMENT_TITLE_ROW + 1
Do While Cells(i, 1).Value  ""
linenumber = 0
elementnumber = 0
Open Cells(i, 1).Value For Input As #1 ' Open file for input
Do While Not EOF(1) ' Loop until end of file
linenumber = linenumber + 1
Line Input #1, line
arrayOfElements = Split(line, ";")
elementnumber = 0
Cells(MEASUREMENT_TITLE_ROW, j).Value = "Messung " & i - MEASUREMENT_TITLE_ROW
For Each element In arrayOfElements
elementnumber = elementnumber + 1
Cells(MEASUREMENT_TITLE_ROW + 1 + linenumber, j - 1 + elementnumber).Value = _
element
Next
Loop
Close #1 ' Close file.
j = j + SPACE_FOR_MEASUREMENT
i = i + 1
Loop
Range("B7").Value = "Finished"
End Sub

Sub A_B_Sortieren(Ez As Long, Spalte As Long, AnzZeilen As Long)
Range(Cells(Ez, Spalte), Cells(Ez + AnzZeilen, Spalte + 1).End(xlUp)).Select
Selection.Sort key1:=Cells(Ez, Spalte + 1), order1:=xlAscending, Header:=xlGuess, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal                              'sortiert
'Range("A1").Select                                     'geht auf Zelle A1
End Sub

8
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: CSV effizient einlesen
15.04.2020 23:18:24
dx145
Hier noch ein Bild der Benutzeroberfläche.
Userbild
AW: CSV effizient einlesen
15.04.2020 23:33:14
dx145
Sorry für die vielen Posts, dachte ich könnte sie editieren.
Des weiteren möchte ich die Kurve unter Kanal B zur Zeit plotten
Dazu will ich ein Chart mit dem Namen der Messung erstellen und wenn dies bereits vorhanden ist überschreiben. Der Name der Messung kann ich auch herleiten. ("Messung " + CStr(temp)) Die information welche Messung verwendet werden soll, ist in einer Zeile unter dem Knopf.
Die Daten habe ich auch bereit zum plotten, das heisst ich weiss in wechen Zellen sie stehen.
Sub plotMeasurement()
Call formateFile
Dim i, j As Long
Dim tempValue As Double
Dim temp, temp2 As Integer
Dim diagrammExist As Boolean
If Range("N9").Value > 10000 Or Not IsNumeric(Range("N9").Value) Or Range("N9").Value  temp Then
MsgBox ("Eingabe Anzahl Werte zur Mittelung in Zelle N9 ungültig. Muss ganzzahlig  _
zwische 1 und 10000 sein!")
End If
Range("N7").Value = "Running"
i = MEASUREMENT_TITLE_ROW + 5
j = FIRST_MEASUREMENT_COLUMN + 2 + SPACE_FOR_MEASUREMENT * (temp - 1)
While IsNumeric(Cells(i, j).Value) And Not IsEmpty(Cells(i, j).Value)
i = i + 1
Wend
i = i - 1
'Cells(1, 1).Value = "Messung " + CStr(temp)
'Da habe ich schon verschiedene Sachen probiert, aber nichts mit Erfolg...
Worksheets("Tabelle1").Activate
Range("N7").Value = "Finished"
End If
End Sub

Anzeige
AW: fso.readall()
15.04.2020 23:51:07
Fennek
Hallo,
ich habe mich nur auf die "Sub CSVlesenV()" konzentriert:
Das Einlesen mit "OPEN file" und dann "line for line" ist recht langsam. Besser ist es mit FSO.OpenTextFile(f).readall das gesamte CSV-File zuerst in ein Array einzulesen.
Auch mit "OPEN file" kann man alles auf einmal einlesen.

Tx = Split(FSO.opentextfile("z:\data.txt").readall, vbCrLf)
' Tx ist eine 1-dim Array
oder

dim Readfile as string
Open Path_File For Binary As #1 'zuerst Path_File definieren
ReadFile = Space$(LOF(1))
Get #1, , ReadFile
Close #1
mfg
Anzeige
AW: fso.readall()
16.04.2020 09:13:46
dx145
Vielen Dank, läuft viel besser. Braucht jetz für 100 Files ca. 1min. das ist super.
Das Diagrammproblem konnte ich jedoch noch nicht lösen, hat mir da jemand einen Ansatz?
https://www.herber.de/forum/messages/1752769.html
Vielen dank.

Sub CSVlesenV()
Call formateFile
Range("B7").Value = "Running"
Dim i, j, k, u, arrDaten, arrDaten2, arrTmp, lngR As Long
Dim line As String
Dim arrayOfElements
Dim linenumber As Integer
Dim elementnumber As Integer
Dim element As Variant
Dim tempArray As Variant
Dim csvPath As String
Set FSO = CreateObject("Scripting.Filesystemobject")
csvPath = ThisWorkbook.Path + "\Messungen"
i = MEASUREMENT_TITLE_ROW + 1
For Each f In FSO.GetFolder(csvPath).Files
If LCase(Right(f.Name, 3)) = "csv" Then
Cells(i, 1).Value = f.Path
If InStr(f.Path, "(")  0 Then
Cells(i, 2).Value = Mid(f.Path, InStr(f.Path, "(") + 1, InStr(f.Path, ")") -  _
InStr(f.Path, "(") - 1)
'Cells(i, 2).Value = 0
Else
Cells(i, 2).Value = 1
End If
i = i + 1
End If
Next
Call A_B_Sortieren(MEASUREMENT_TITLE_ROW + 1, 1, i - MEASUREMENT_TITLE_ROW - 1)
'GoTo Sprungmarke
j = FIRST_MEASUREMENT_COLUMN
i = MEASUREMENT_TITLE_ROW + 1
Do While Cells(i, 1).Value  ""
Tx = Split(FSO.opentextfile(Cells(i, 1).Value).readall, vbCrLf)
Cells(MEASUREMENT_TITLE_ROW, j).Value = "Messung " & i - MEASUREMENT_TITLE_ROW
For k = 0 To UBound(Tx)
If (Tx(k) = "") Then
Cells(MEASUREMENT_TITLE_ROW + 1 + (k), j).Value = ""
Cells(MEASUREMENT_TITLE_ROW + 1 + (k), j + 1).Value = ""
Cells(MEASUREMENT_TITLE_ROW + 1 + (k), j + 2).Value = ""
Else
tempArray = Split(Tx(k), ";")
Cells(MEASUREMENT_TITLE_ROW + 1 + (k), j).Value = tempArray(0)
Cells(MEASUREMENT_TITLE_ROW + 1 + (k), j + 1).Value = tempArray(1)
Cells(MEASUREMENT_TITLE_ROW + 1 + (k), j + 2).Value = tempArray(2)
End If
Next k
j = j + SPACE_FOR_MEASUREMENT
i = i + 1
Loop
Range("B7").Value = "Finished"
End Sub

Anzeige
AW: Charts?
16.04.2020 10:45:03
Fennek
Hallo,
es gibt heute relativ wenige Fragen (= Unterhaltung): Auch wenn ich i.M. eher wenig am Thema "Charts" interessiert bin, lade bitte eine Beispieldatei hoch mit mindestens 2 Messreihen, ca 20 Zeilen und einem Musterchart.
Vielleicht findet sich jemand.
mfg
AW: Charts?
16.04.2020 12:42:36
dx145
So ich bin Bereits etwas weiter. Zum herausfinden ob ein Chart bereits besteht habe ich eine Funktion gefunden.

Function ChartExist(strChart As String) As Boolean
Dim cht As Chart
ChartExist = False
For Each cht In ActiveWorkbook.Charts
If cht.Name = strChart Then
ChartExist = True
End If
Next
End Function
Und ich konnte auch meine Daten die ich in 2 Arrays habe plotten.

Sub plotMeasurement()
Call formateFile
Dim i, j As Long
Dim tempValue As Double
Dim temp, temp2 As Integer
Dim xValues, yValues As Variant
Dim myChart As Chart
Dim intChartRow As Integer
If Range("N9").Value > 10000 Or Not IsNumeric(Range("N9").Value) Or Range("N9").Value  temp Then
MsgBox ("Eingabe Anzahl Werte zur Mittelung in Zelle N9 ungültig. Muss ganzzahlig  _
zwische 1 und 10000 sein!")
End If
Range("N7").Value = "Running"
i = MEASUREMENT_TITLE_ROW + 5
j = FIRST_MEASUREMENT_COLUMN + 2 + SPACE_FOR_MEASUREMENT * (temp - 1)
While IsNumeric(Cells(i, j).Value) And Not IsEmpty(Cells(i, j).Value)
i = i + 1
Wend
i = i - 1
xValues = Range(Cells(MEASUREMENT_TITLE_ROW + 5, FIRST_MEASUREMENT_COLUMN +  _
SPACE_FOR_MEASUREMENT * (temp - 1)), Cells(i, FIRST_MEASUREMENT_COLUMN + SPACE_FOR_MEASUREMENT * (temp - 1)))
yValues = Range(Cells(MEASUREMENT_TITLE_ROW + 5, FIRST_MEASUREMENT_COLUMN + 2 +  _
SPACE_FOR_MEASUREMENT * (temp - 1)), Cells(i, FIRST_MEASUREMENT_COLUMN + 2 + SPACE_FOR_MEASUREMENT * (temp - 1)))
If ChartExist("Messung_" + CStr(temp)) Then
ThisWorkbook.Charts("Messung_" + CStr(temp)).Activate
Else
With Charts.Add(After:=Worksheets(1))
.ChartType = xlLine
.Name = "Messung_" + CStr(temp)
End With
End If
'Der Variable das Objekt zuweisen
Set myChart = ThisWorkbook.Charts("Messung_" + CStr(temp))
'Löschen der bestehenden Dateinreihen
'/// Feststellen der momentan genutzten Datenreihen
intChartRow = myChart.SeriesCollection.Count
'/// Löschen der Datenreihen beginnend mit der größten
For intCounter = intChartRow To 1 Step -1
myChart.SeriesCollection(intCounter).Delete
Next intCounter
'Werte an Diagramm übergeben
With myChart.SeriesCollection.NewSeries
.xValues = xValues
.Values = yValues
End With
'Titel des Diagramms festlegen
myChart.HasTitle = True
myChart.ChartTitle.text = "Plot Messung " + CStr(temp)
myChart.ChartTitle.Font.Size = 36
'Achsenbeschriftung für die X-Achse
With myChart.Axes(xlCategory)
.HasTitle = True
.AxisTitle.text = "Zeit"
.AxisTitle.Font.Size = 20
End With
'Achsenbeschriftung für die Y-Achse
With myChart.Axes(xlValue)
.HasTitle = True
.AxisTitle.text = "Drehmoment"
.AxisTitle.Font.Size = 20
End With
Worksheets("Tabelle1").Activate
Range("N7").Value = "Finished"
End If
End Sub
Jetzt nervt mich noch die blöde X Achs Beschriftung, ich hätte gerne so 10 Werte mit Linien, wie bei der Y Achse. Beide sind für meinen geschmak noch zu klein.
Zudem ist die Legende auf der rechten Seite nicht nötig.
Könnt ihr mir da helfen?
Userbild
Anzeige
AW: Charts?
16.04.2020 12:46:17
dx145
Zudem wäre es toll wenn die Achsskalierung der X Achse auch ausserhalb wäre wie bei der Y Achse, den der Graph wird Teilweise überdekt.
AW: Charts?
16.04.2020 15:56:25
dx145
Konnte meine Probleme vorübergehend lösen. Danke euch

Sub plotMeasurement()
Call formateFile
Dim i, j As Long
Dim tempValue, xMax, xMin As Double
Dim temp, temp2 As Integer
Dim xValues, yValues As Variant
Dim myChart As Chart
Dim intChartRow As Integer
If Range("N9").Value > 10000 Or Not IsNumeric(Range("N9").Value) Or Range("N9").Value  temp Then
MsgBox ("Eingabe Anzahl Werte zur Mittelung in Zelle N9 ungültig. Muss ganzzahlig  _
zwische 1 und 10000 sein!")
End If
Range("N7").Value = "Running"
i = MEASUREMENT_TITLE_ROW + 5
j = FIRST_MEASUREMENT_COLUMN + 2 + SPACE_FOR_MEASUREMENT * (temp - 1)
If IsEmpty(Cells(i, j).Value) Then
MsgBox ("Es gibt keine Messung mit dieser Nummer")
Exit Sub
End If
While IsNumeric(Cells(i, j).Value) And Not IsEmpty(Cells(i, j).Value)
i = i + 1
Wend
i = i - 1
xValues = Range(Cells(MEASUREMENT_TITLE_ROW + 5, FIRST_MEASUREMENT_COLUMN +  _
SPACE_FOR_MEASUREMENT * (temp - 1)), Cells(i, FIRST_MEASUREMENT_COLUMN + SPACE_FOR_MEASUREMENT * (temp - 1)))
yValues = Range(Cells(MEASUREMENT_TITLE_ROW + 5, FIRST_MEASUREMENT_COLUMN + 2 +  _
SPACE_FOR_MEASUREMENT * (temp - 1)), Cells(i, FIRST_MEASUREMENT_COLUMN + 2 + SPACE_FOR_MEASUREMENT * (temp - 1)))
xMax = Cells(i, FIRST_MEASUREMENT_COLUMN + SPACE_FOR_MEASUREMENT * (temp - 1))
xMin = Cells(MEASUREMENT_TITLE_ROW + 5, FIRST_MEASUREMENT_COLUMN +  _
SPACE_FOR_MEASUREMENT * (temp - 1))
If ChartExist("Messung_" + CStr(temp)) Then
ThisWorkbook.Charts("Messung_" + CStr(temp)).Activate
Else
Charts.Add
ActiveChart.Move After:=Worksheets("Tabelle1")
ActiveChart.ChartType = xlLine
ActiveChart.Name = "Messung_" + CStr(temp)
End If
'Der Variable das Objekt zuweisen
Set myChart = ThisWorkbook.Charts("Messung_" + CStr(temp))
'Löschen der bestehenden Dateinreihen
'/// Feststellen der momentan genutzten Datenreihen
intChartRow = myChart.SeriesCollection.Count
'/// Löschen der Datenreihen beginnend mit der größten
For intCounter = intChartRow To 1 Step -1
myChart.SeriesCollection(intCounter).Delete
Next intCounter
'Werte an Diagramm übergeben
With myChart.SeriesCollection.NewSeries
.xValues = xValues
.Values = yValues
End With
myChart.ChartStyle = 342
'Titel des Diagramms festlegen
myChart.HasTitle = True
myChart.ChartTitle.text = "Plot Messung " + CStr(temp)
myChart.ChartTitle.Font.Size = 36
'Achsenbeschriftung für die X-Achse
With myChart.Axes(xlCategory)
.HasTitle = True
.AxisTitle.text = "Zeit [ms]"
.AxisTitle.Font.Size = 20
End With
'Achsenbeschriftung für die Y-Achse
With myChart.Axes(xlValue)
.HasTitle = True
.AxisTitle.text = "Drehmoment [Nm]"
.AxisTitle.Font.Size = 20
End With
With myChart.Axes(xlValue)
.MajorUnitIsAuto = True
.MinorUnitIsAuto = True
End With
myChart.Axes(xlCategory).TickLabelSpacing = (xMax - xMin) / 2
myChart.Axes(xlCategory).TickMarkSpacing = (xMax - xMin) / 2
myChart.SetElement (msoElementPrimaryCategoryGridLinesMajor)
myChart.Axes(xlCategory).TickLabels.NumberFormat = "#'##0"
myChart.Axes(xlValue).TickLabels.NumberFormat = "#'##0"
myChart.Axes(xlCategory).TickLabelPosition = xlLow
With myChart.Axes(xlCategory).TickLabels.Font
'.Bold = msoTrue
.Size = 16
End With
With myChart.Axes(xlValue).TickLabels.Font
'.Bold = msoTrue
.Size = 16
End With
myChart.HasLegend = False
Worksheets("Tabelle1").Activate
Range("N7").Value = "Finished"
End If
End Sub

Anzeige

Links zu Excel-Dialogen

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige