Diagramm mit Visual Basic aus Array

  • VB.NET

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von Radinator.

    Diagramm mit Visual Basic aus Array

    Servus,

    eins vorweg, ich bin kein Programmierer. Ich muss mich im Rahmen meines Studiums (Technische Physik) für ein Projekt mit Visual Basic auseinandersetzen. Also ist es durchaus möglich, dass ich mich sehr dumm anstelle :)

    Im Projekt sollen erstmal Daten in eine Datei gespeichert werden von einem Messaufbau. Die Daten landen in einer Datei mit Zeitangabe und Spannung getrennt durch ein Semikolon. Ich habe bereits die Daten aus der Datei eingelesen und an ein Array übergeben. Jetzt möchte ich gern diese Werte als simples x-y-Diagramm darstellen. Es handelt sich bei den Messwerten um periodische Signale, deshalb will ich später noch die Amplitude und die Periodendauer bestimmen. Wenn es die Motivation zulässt, möchte ich die Frequenzen analysieren (Fourier) und die einzelnen Oberwellen ebenfalls als Diagramm darstellen.

    Aktuell hänge ich aber an der grafischen Darstellung der rohen Messwerte.

    VB.NET-Quellcode

    1. Imports System.Collections
    2. Imports System
    3. Imports System.IO
    4. Imports System.Math
    5. Imports Microsoft.VisualBasic.FileIO
    6. Imports System.Windows.Forms.DataVisualization.Charting
    7. Public Class Form1
    8. Public Function Zeilenzaehlen(ByVal Filename As String) As Integer
    9. Dim Lines As Integer = 0
    10. Using oStream As New IO.FileStream(Filename, IO.FileMode.Open, IO.FileAccess.Read)
    11. ' Blockgröße
    12. Dim BlockSize As Integer = 16384
    13. Dim Bytes(BlockSize) As Byte
    14. Dim ReadSize As Integer
    15. Dim StartIndex As Integer
    16. Do
    17. ReadSize = oStream.Read(Bytes, 0, BlockSize)
    18. StartIndex = -1
    19. Do
    20. StartIndex = Array.IndexOf(Bytes, CByte(13), StartIndex + 1, ReadSize - StartIndex)
    21. If StartIndex >= 0 Then Lines += 1
    22. Loop Until StartIndex < 0
    23. Loop Until ReadSize = 0
    24. oStream.Close()
    25. End Using
    26. Return Lines
    27. End Function
    28. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    29. End Sub
    30. Private Sub cmd_Messwerteladen_Click(sender As Object, e As EventArgs) Handles cmd_Messwerteladen.Click
    31. Dim Zeilen As Integer
    32. Dim Spalten As Integer = 2
    33. Zeilen = Zeilenzaehlen("C:\Saegezahn.csv")
    34. Dim Messwerte(Zeilen, Spalten - 1) As Double
    35. Using MyReader As New TextFieldParser("C:\Saegezahn.csv")
    36. MyReader.TextFieldType = FieldType.Delimited
    37. MyReader.SetDelimiters(";")
    38. Dim currentRow As String()
    39. Dim Zelleninhalt As Double
    40. Dim Element As Integer = 0
    41. Dim Ze As Integer = 0
    42. Dim Sp As Integer = 0
    43. Dim i As Integer = 0
    44. While Not MyReader.EndOfData
    45. Try
    46. currentRow = MyReader.ReadFields()
    47. Dim currentField As String
    48. For Each currentField In currentRow
    49. Zelleninhalt = currentRow(Element)
    50. If Element = 0 Then
    51. Element = 1
    52. Else
    53. Element = 0
    54. End If
    55. Messwerte(Ze, Sp) = Zelleninhalt
    56. 'ListBox1.Items.Add(Zelleninhalt)
    57. If Sp = 0 Then
    58. Sp = Sp + 1
    59. Else
    60. Sp = 0
    61. End If
    62. If Sp = 0 Then
    63. Ze = Ze + 1
    64. End If
    65. Next
    66. Finally
    67. End Try
    68. End While
    69. End Using
    70. End Sub
    71. End Class
    @_Naitsirhc Willkommen im Forum. :thumbup:
    Sieh Dir mal dieses Beispiel an.
    Mach Dir ein neues WinForms-Projekt, zieh 3 Button, ein DataGridView und ein Chart rein und kopiere den Code aus dem Beispiel in die Form.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    _Naitsirhc schrieb:

    meine Datei
    Kannst Du die mal posten?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @_Naitsirhc Füge in mein Beispiel einen weiteren Button ein:

    VB.NET-Quellcode

    1. Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
    2. Me.InitData()
    3. For Each line In IO.File.ReadLines("C:\Temp\Saegezahn.txt")
    4. Dim parts() = line.Split(";"c)
    5. If parts.Length > 1 Then
    6. Dim newRow As DataRow = Me.table.NewRow()
    7. newRow(0) = Integer.Parse(parts(0))
    8. newRow(1) = Double.Parse(parts(1))
    9. Me.table.Rows.Add(newRow)
    10. End If
    11. Next
    12. Me.ShowData()
    13. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Es kann sein, dadurch dass du mit WPF arbeitest, diese Antwort redundant ist, dennoch kannst du dir folgendes ansehen: (besonders den GGraph)
    GChartLib - Präsentiert Daten auf eine neue moderne Art!
    Damit würdest dus auch einfach hinbekommen
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Ich sitz schon den ganzen Tag daran und verzweifel fast und du machst das in 5 Minuten, vielen Dank :D

    Es läuft zwar wie gedacht, aber verstehen tue ich das meiste nicht. Wenn ich das richtig verstehe, können die anderen Buttons und die dazugehörigen Subs wieder weg?

    Wenn ich Variablen deklariere, läuft das meist nach dem Schema "Dim x As Integer" o.ä., aber was bedeutet "Dim parts() = line.Split(";"c)"?

    Wie kann ich den Diagramm-Typ ändern von Balken auf Einzelpunkte oder Linie?

    @Gather: Das sieht auf jeden Fall sehr interessant aus und ich werde es mir mal anschauen. Nur wie bereits im Eingangspost erwähnt, meine Fähigkeiten sind sehr beschränkt (1 SWS Visual Basic und nur in diesem Semester).

    _Naitsirhc schrieb:

    Dim parts() = line.Split(";"c)
    bedeutet unter der default Nebenbedingung Option Infer On:

    VB.NET-Quellcode

    1. Dim parts() As String= line.Split(";"c)
    Was Split macht, lies in der MSDN nach, ohne dass ich Dir den Link dazu poste.
    Auf Split klicken und F1 drücken.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @_Naitsirhc: Rod's Weg funktioniert auf jeden Fall. Ich will nur eine kleine Alternative bieten. Und sofern du mit Windows Forms arbeitest ist die Verwendung der GChartLib wirklich einfach!
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    RodFromGermany schrieb:

    Zitat von _Naitsirhc: „Dim parts() = line.Split(&quot;;&quot;c)“bedeutet unter der default Nebenbedingung <code class="inlineCode">Option Infer On</code>:
    VB.NET-Quellcode (1 Zeile)Was Split macht, lies in der MSDN nach, ohne dass ich Dir den Link dazu poste.
    Auf <code class="inlineCode">Split</code> klicken und F1 drücken.…


    Also wenn ich das richtig verstehe benutzt Visual Studio mit "Option Infer On" automatisch den am ehesten zu verwendenden Datentyp vom array parts()? Und Split teilt den String beim Trennzeichen ";"? Wofür steht das c? Das line ist willkürlich von dir gewählt?
    Nicht einfach nur

    _Naitsirhc schrieb:

    den am ehesten zu verwendenden Datentyp
    , sondern den zu verwendenden Datentyp. Der Compiler fängt nämlich nicht an zu raten, was denn am besten passen könnte.
    Die String.Split-Funktion gibt einen Datentyp zurück. Der ist klar dokumentiert (siehe MSDN ;) ). Der Compiler sagt dann einfach "Die Variable bekommt den Typ des Ausdrucks, der zugewiesen wird."
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Kleiner Tipp bei MSDN: Stell auf VB um: msdn.microsoft.com/de-de/libra…cs-lang=vb#code-snippet-1
    Ok. Wie Du siehst, nimmt die Funktion ein Character-ParamArray entgegen und gibt ein 1-dimensionales String-Array zurück. ParamArray bedeutet einfach, man kann die Funktion mit einer beliebigen Anzahl an Parametern dieses Typs aufrufen. Also line.Split(";"c) splittet nur an Semikolons. line.Split(";"c, "."c, "-"c) splittet auch an Punkten und Bindestrichen.
    . Wenn ich das c entferne, scheint es auch keine Auswirkungen zu haben

    Dann hast Du Option Strict Off. Siehe hier: Visual Studio - Empfohlene Einstellungen
    "asdf" ist ein String mit der Länge 4.
    "a" ist ein String mit der Länge 1.
    "a"c ist ein Character, also nur ein einziges Zeichen. Das ist nicht das selbe, wie ein String mit der Länge 1.
    Die String.Split-Funktion erwartet als Parameter ein einziges Zeichen. Der Typ des Parameters ist Character. Deshalb funktioniert (mit Option Strict On) line.Split(";"c) schon aber line.Split(";") nicht.
    Option Strict Off erlaubt eine implizite Konvertierung von String zu Char, was hier auch gemacht wird. Dann wird vom String ";" das erste Zeichen genommen (";"c) und das wird dann als Parameter verwendet. Das funktioniert in diesem Fall. Aber das wird besonders verwirrend, wenn Du z.B. versuchst, einen Text an einem ganzen Wort zu splitten: "franz jagt im komplett verwahrlosten taxi quer durch bayern".Split("taxi") sollte eigentlich {"franz jagt im komplett verwahrlosten ", " quer durch bayern"} ergeben, aber raus kommt {"franz jag", " im komple", "", " verwahrlos", "en ", "axi quer durch bayern"}. Und dann schaut man erst mal blöd aus der Wäsche, bis man drauf kommt, dass "taxi" implizit zu "t"c konvertiert wird und dann nur an dem einen Zeichen gesplittet wird.
    Das ist sogar noch schlimmer, wenn man z.B. an Zeilenumbrüchen splitten will. Also wenn man einen mehrzeiligen Text hat und davon die einzelnen Zeilen haben will. LangerText.Split(Microsoft.VisualBasic.ControlChars.CrLf) splittet aber nur am CarriageReturn-Zeichen, nicht aber an einer Folge von CarriageReturn und LineFeed. Dann hat man in jeder Zeile außer der ersten ganz am Anfang noch ein LF-Zeichen stehen. Das sieht man meistens nicht. Wenn man dann später diese Zeilen irgendwo verwendet und ein Code crasht weil ein unerwartetes Zeichen drin ist, kann man wieder suchen gehen, wo die Zeichen überhaupt herkommen.
    Option Strict On hätte hier von vornherein darauf aufmerksam gemacht, dass das nicht funktioniert, deswegen ist es auch so wichtig, das einzuschalten.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    _Naitsirhc schrieb:

    den am ehesten zu verwendenden Datentyp
    Nein.
    Split(...) hat als Rückgabewert ein String-Array, dieser Typ wird verwendet.
    Infer On funktioniert allerdings nur innerhalb von Prozeduren, bei Klassenvariablen funktioniert das nicht.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wie gesagt, ich bin kein Programmierer und steh bei VB noch ganz am Anfang.

    Bisher kenne ich die Deklaration nur in der Form Dim x As Integer = 0. Mit Infer On würde es reichen, wenn ich Dim x = 0 schreibe? Meinst du mit "funktioniert allerdings nur innerhalb von Prozeduren, bei Klassenvariablen funktioniert das nicht." lokale und globale Variablen?

    _Naitsirhc schrieb:

    lokale und globale Variablen?
    Jein.
    Die Deklaration einer Variable in einer Klasse kann
    • Klassen-lokal (Private x as Any)
    • Assembly-lokal (Internal x as Any)
    • Projekt-global (Publix x as Any)
    erfolgen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @TE: Was mir noch auffällt: Der Code ist recht lange und lässt sich sehr einfach sehr weit verkürzen.
    In deinem Code list du zuerst die Anzahl der Zeilen aus und anschließend den Inhalt noch einmal. Das ganze lässt sich erheblich vereinfachen, wenn du einfach nur die Namespaces System.Linq und System.Collections.Generic zusätzlich importierst und über System.IO.File.ReadLines("C:\Pfad\zur\Datei") dir ein IEnumerable(Of String) erzeugst. Das kannst du dann über die Linq-Erweiterung per .ToList() in eine List(Of String) überführen. Beide kannst du dann bequem per For Each durchlaufen und dir dann mit dem Iterator deine Darstellung zusammen bauen.

    Das hat zu Folge, dass du wesentlich flexibler bist.
    So kannst du dann etwa dir dann aus dem IEnumerable(Of String) im Prinzip jedes beliebige Objekt, dessen Klasse das Interface IEnumerable(Of T) implementiert, machen kannst.
    So kannst du dann deine Liste an ein DataGridView, ListBox, ComboBox über eine BindingSource binden, du kannst es über LINQ abfragen. Kurz: Du hast wesentlich mehr möglichkeiten. Und der Code ist moderner ;D

    Lg Radinator
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Radinator“ ()