Laden...

CSV-Datei als DataSource für Chart

Erstellt von Jens91 vor 6 Jahren Letzter Beitrag vor 6 Jahren 4.155 Views
J
Jens91 Themenstarter:in
5 Beiträge seit 2017
vor 6 Jahren
CSV-Datei als DataSource für Chart

Hey,
ich lerne gerade, mit WindowsForms umzugehen und hätte da eine Frage. Habe leider kein passendes Tutorial auf Youtube gefunden. Bitte verzeiht mir meine Unkenntnis, ich programmiere erst seit 2 Monaten und auch nur hobbymäßig.

Meine Form enthält 2 Buttons. Klickt man auf Button1, wird eine von mir geschriebene exe-Datei ausgeführt. Diese rechnet diverse Dinge aus und hinterlegt eine csv-Datei im Programmordner ohne Pfadangabe.

Der Content verändert sich, sofern die Eingabe sich verändert. Die csv-Datei wird also ständig überschrieben und enthält andere Inhalte. Die Anzahl der Spalten ist aber immer gleich. Die Zeilen varrieren.
Damit die exe-Datei ausgeführt wird, musste ich einen Pfad angeben.Tu ich das, funktioniert die exe-Datei und bildet die csv-Datei wie gewünscht.


private void button1_Click(object sender, EventArgs e)
        {
            Process P = new Process();
            P.StartInfo.FileName = "C:\\Users\\Jens\\Desktop\\WindowsFormsApplication1\\Programm.exe";
            P.Start();
        }

Jetzt soll das Programm aber später auf unterschiedlichen Rechnern laufen. Wie mach ich das da mit dem Pfad?

Beim klicken auf den zweiten Button soll ein Graph gezeigt werden, der eine Spalte aus der csv-Datei als Quelle für die Y-Achse nutzt. Die x-Achse soll von 0 bis "Anzahl der Zeilen" gehen. Jetzt kann ich aber nur SQL-Datenbanken als DataSource angeben. Also bleibt nur die csv-Datei irgendwie laden, zwischenzuspeichern und dann als Eingabewert zu nutzen.

Um das ganze zu verdeutlichen, habe ich das Programm mal stark vereinfacht, aber sinngemäß ist es gleich. Hier, was die Exe macht:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace Beispiel_Exe
{
    class Program
    {
        static void Main(string[] args)
        {
            string string1 = "1.10";
            string string2 = "2.20";
            string string3 = "3.30";
            string string4 = "4.40";
            for (int i = 0; i < 5; i++)
            {
                lines.Add(string1 + "," + string2 + "," + string3 + "," + string4);
                File.WriteAllLines(@"test-csv.csv", lines);
               
                    //Es wird eine csv-Datei mit 4 Spalten und 5 Zeilen erzeugt. 
                    //Der Inhalt der Zeilen ist gleich, dass ist aber erstmal unwichtig
            }
        }
            
        static List<string> lines = new List<string>();
    }
}

Und hier die Form-Anwendung:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Die exe ausführen 
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // Die csv einlesen und z.B. Spalte 3 in einem Liniendiagramm darstellen
            // Spalte 3 auf der Y-Achse
        }
    }
}

Ist jemand so freundlich und hilft mir? Sonst, hab das auch als rar-Archiv angehangen.

MfG,
Jens

D
985 Beiträge seit 2014
vor 6 Jahren

Laut Doku geht bei Chart.DataSource mehr als nur SQL-Datenbanken

J
Jens91 Themenstarter:in
5 Beiträge seit 2017
vor 6 Jahren

Hey danke für den Tipp. Ich bin ein bisschen weiter gekommen, habs aber immer noch keine wirkliche Lösung. Ich vereinfache das ganze nochmal weiter.

Ich habe eine csv-Datei. Die besteht aus nur einer Spalte, die später die Y-Werte darstellen soll. Die X-Achse kann entweder automatisch skalieren oder ich füge eine zweite Spalte mit ganzen Zahlen mit 0,1,2,3,.... für die x-Achse hinzu. Das wäre kein Problem. In der ersten Reihe steht ein column für die y-Werte.

Jetzt lade ich die Datei in eine DataTable:


public Form1()
        {
            InitializeComponent();
            string path = "./File.csv";
            string[] str = File.ReadAllLines(path);

            DataTable datatbl = new DataTable();

            string[] temp = str[0].Split(',');

            foreach (string t in temp)
            {
                datatbl.Columns.Add(t, typeof(string));
            }
            for (int i = 1; i < str.Length; i++)
            {
                string[] t = str[i].Split(',');
                datatbl.Rows.Add(t);

            }
            chart1.DataSource = datatbl;
            chart1.DataBind();
        }

 private void chart1_Click(object sender, EventArgs e)
        {
            
        }

Wie kann ich daraus jetzt den Liniengraphen erzeugen? Ich find nicht raus, wie ich die Achsen zuweise.

Beispiel der csv:

,Value
0,5
1,3.5
2,4.5
3,5.3

P
441 Beiträge seit 2014
vor 6 Jahren

Jetzt soll das Programm aber später auf unterschiedlichen Rechnern laufen. Wie mach ich das da mit dem Pfad?

Da gibt es - wie immer - mehrere Lösungsansätze 😃

Wenn es beim Pfad bleiben soll, entweder über den Installer des Programms in der Registry hinterlegen oder in der/einer config Datei konfigurierbar machen.

Da es sich bei deinem Programm aber um ein .NET Programm zu handeln scheint könntest du auch einfach die Solution mit in dein neues VS Projekt einhängen und es mit deployen (oder sogar aus der .exe eine dll machen, dann bräuchtest du nicht mehr über das CSV Format gehen sondern kannst direkt mit Datenstrukturen arbeiten).
Alternativ könntest du es als externe Referenz einbinden.

Edit:
Wegen des CSV, hat die CSV Datei ein festes Datenformat? Dafür gibt es Parser Bibliotheken, die das passend lesen können.

J
Jens91 Themenstarter:in
5 Beiträge seit 2017
vor 6 Jahren

Hey,
das mit dem Pfad hab ich gelöst. Die CSV liegt ja immer im Programmordner selbst


File.WriteAllLines(@"CSV-File.csv", csvcontent);


string path = "./CSV-File.csv";
string[] str = File.ReadAllLines(path);

J
Jens91 Themenstarter:in
5 Beiträge seit 2017
vor 6 Jahren

Kann mir denn jemand damit helfen, mit einer simplen CSV ein Liniendiagramm zu erstellen in Windows Forms? Ich bräuchte Beispiele für Syntax.

6.911 Beiträge seit 2009
vor 6 Jahren

Hallo Jens91,

Bitte beachte [Hinweis] Wie poste ich richtig? Punkt 4.x

In der :rtfm: zum Charts-Control sind doch genug Beispiele (inkl. Code) vorhanden. Aus dem CSV kannst du die Daten lesen und -- analog den Beispielen -- die ausgelesen Daten als Datenquelle verwenden.

Wo hakt es da genau? Ein wenig selbst programmieren (und einlesen und probieren) musst du schon selber.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

P
441 Beiträge seit 2014
vor 6 Jahren

Es wird dir hier niemand eine Lösung vorkauen. Dann wäre auch dein Lerneffekt nicht gut.

Was du machen musst:1.Den Inhalt der CSV in ein Zahlenformat (z.B. double) parsen. Siehe meinen Post oben, wenn dein CSV eine immer gleichbleibende Struktur hat, gibt es dafür Bibliotheken, die dir das komplett abnehmen können. 1.Herausfinden, wie du das an das ChartControl binden kannst 1.Das Chart Control zur Anzeige bringen

J
Jens91 Themenstarter:in
5 Beiträge seit 2017
vor 6 Jahren

Ich muss mal ganz kurz was los werden.
Du weißt mich hier auf [Hinweis] Wie poste ich richtig? Punkt 4.x hin.

Ich habe nicht nach der Lösung eines Projekts gefragt, sondern nach Hilfe für eine simple, für Programmierer bestimmt lächerliche, Problemstellung. Dabei habe ich versucht, so gut wie möglich, mein Problem zu beschreiben. Aber außer Hilfe zur Selbsthilfe wird hier wohl nicht viel angeboten. Googlen kann ich auch. Ich finde nach ein paar Tagen meist auch eine Lösung. Der Gedanke, hier um Hilfe zu bitten, beruhte darauf, diese Zeit zu minimieren und damit schneller voran zu kommen.

Für die Nachwelt dann noch die Lösung, die ich jetzt verwende:

  1. Eine CSV-Datei wird im Programmordner gespeichert

File.WriteAllLines(@"CSVFile", csvcontent);   //csvcontent ist ein Array 

2.Die csv-Datei in eine DataTable einlesen


            string path = "./CSVFile.csv";  //CSVFile muss im Programmordner sein!
            string[] content = File.ReadAllLines(path);

            DataTable dt = new DataTable();
            
             

            string[] temp = content[0].Split(',');

            foreach (string k in temp)
            {
                dt.Columns.Add(k, typeof(string));
            }
            for (int i = 1; i < content.Length; i++)
            {
                string[] k = content[i].Split(',');
            
                dt.Rows.Add(k);
            }

  1. Diese in einem Graphen darstellen (direkt hinter dt.Rows.Add(k) einfügen)

chart1.DataSource = dt;
                chart1.Series[0].XValueMember = "ColumnNameX";    //Hier den Column Name der x-Spalte eintragen
                chart1.Series[0].YValueMembers = "ColumnNameY";   //Hier den Column Name der y-Spalte eintragen
                chart1.DataBind();

Ergebnis ist ein Liniendiagramm mit den Werten aus der csv

6.911 Beiträge seit 2009
vor 6 Jahren

Hallo Jens91,

wie du an der Lösung wohl selbst erkennen kannst war das letztlich ja nicht so schwer und jeder Programmierer, der über die Grundlagen-Hürde drüber ist, wird diese Aufgabe eher als trivial abtun.

Insofern sehen wir es, aus Erfahrung, für sinnvoll an, wenn sich zuerst die Grundlagen angeeignet werden bevor "programmiert" wird. Es ist eben der falsche Weg für triviale Aufgaben sich fertige Lösungen vorkauen zu lassen.

Außerdem bietet jeder Helfer seine Hilfe in seiner freien Zeit an und da ist nur fair und zeigt auch die Wertschätzung gegenüber Helfenden, dass man sich mit den grundlegendsten Dingen selbst beschäftigt.

Ich behaupte auch, dass durch das Aneignen der Grundlagen schneller ein brauchbares Ergebnis zu stande kommt, als wenn mittels Google nach ein paar Tagen eine Lösung gefunden wird.

Und das sind mit Gründe dafür dass es eben diesen Punkt 4 gibt.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

5.299 Beiträge seit 2008
vor 6 Jahren

Hmm - also ich finde Jens91' Lösung alles annere als trivial. Klar - elegante Lösungen sehen am Ende immer fast trivial aus - aber lass ma gucken:
Er geht sehr geschickt mit DataTable um, und er hat sich ganz spezifische Eigenarten des Chart-Controls selbst erarbeitet:
.DataSource, .Datebind() und die Series-Collection mit ihren verschiedenen ValueMember-Eigenschaften - da muss man erstmal drauf kommen, was das alles zu bedeuten hat, und wie's ineinander greift und zusammenspielt! 👍
/OT

@Jens91
Eigentümlich und fragwürdig finde ich, dass es funktioniert.
Imo müsste deine DataTable nach dieser Konfiguration nur Columns mit DataType.String aufweisen, und deshalb ist mir verwunderlich, dass das ChartControl das akzeptiert, denn die XYValues sollen doch wohl numerisch sein, oder?

Imo hättest du die DataColumns auf DataType.Double konfigurieren müssen, und beim Einlesen die csv-Strings mit Double.Parse() in eben diesen Datentyp konvertieren.


Ach - ich hab übrigens mal ein klein Tut gemacht zum Chart-Control, und was man da alles im Designer dran drehen kann, und wo die Doku dazu ühaupt zu finden ist:
ChartSample
Ist auch bisserl Code dabei, und der ist (leider?) auf VB, aber die Designer-Geschichten sind in c# ja dieselben, und einiges andere dürfte für dich auch interessant sein, wenn du dich mittm ChartControl auseinandersetzst.

Der frühe Apfel fängt den Wurm.