如何在C#

时间:2017-05-24 05:38:08

标签: c# csv charts mschart

我使用.csv文件绘制了一个图表。现在用户启用选择图表区域并单击导出按钮,然后选择要写入另一个.csv文件的数据。 在这里,我想要接近这个方法。用户希望获得chart1.ChartAreas[0].CursorX.SelectionStartchart1.ChartAreas[0].CursorX.SelectionEnd然后想要读取.csv文件并删除未选择区域中的其他原始文件。 注意:用户也想选择多个图表区域。请给我一个澄清。这是winform应用程序,我使用MsChart。 我的代码如下;

 private void btnExport_Click(object sender, EventArgs e)
 {
     List<Graph> ObservingData = new List<Graph>(); // List to store all available Graph objects from the CSV
     int index = 0;
     using (StreamWriter sw = new StreamWriter(@"D:\CSVFile\NEWFile\Export\NewFile.csv"))
     {
         // Loops through each lines in the CSV
         foreach (string line in System.IO.File.ReadAllLines(pathToCsv))
         {
             // here line stands for each line in the csv file
             string[] CsvLine = line.Split(',');

             // creating an object of type Graph based on the each csv line
             // and adding them to the  List<Graph>
             Graph Instance1 = new Graph();

             if (index == 0)
             {
                 sw.WriteLine(line);
             }    
             else
             {
                 //Add the code here..
                 //  if (((chart1.ChartAreas[0].CursorX.SelectionStart))<=  && ( <= (chart1.ChartAreas[0].CursorX.SelectionEnd)))
                 {
                     sw.WriteLine(line);
                 }                       
             }
             index++; 
         }
         sw.Close();
     }
     MessageBox.Show("Data are copied to the new .CSV file");
 }

以下代码用于我的图表区域的多重选择。

        SizeF curRange = SizeF.Empty;
        List<SizeF> ranges = new List<SizeF>();
        List<int> selectedIndices = new List<int>();

      private void chart1_SelectionRangeChanged(object sender, CursorEventArgs e)
            {

                ranges.Add(curRange);
                selectedIndices.Union(collectDataPoints(chart1.Series[0],curRange.Width, curRange.Height)).Distinct();

                StripLine sl = new StripLine();
                sl.BackColor = Color.FromArgb(255, Color.LightSeaGreen);
                sl.IntervalOffset = Math.Min(curRange.Width, curRange.Height);
                sl.StripWidth = Math.Abs(curRange.Height - curRange.Width);
                chart1.ChartAreas[0].AxisX.StripLines.Add(sl);           

            }
            List<int> collectDataPoints(Series s, double min, double max)
            {
                List<int> hits = new List<int>();
                for (int i = 0; i < s.Points.Count; i++)
                    if (s.Points[i].XValue >= min && s.Points[i].XValue <= max) hits.Add(i);           
                return hits;
            }

      private void chart1_SelectionRangeChanging(object sender, CursorEventArgs e)
            {

                curRange = new SizeF((float)e.NewSelectionStart, (float)e.NewSelectionEnd);
            }

以下代码绘制图形;

  private void Output_Load(object sender, EventArgs e)
        {

            List<Graph> ObservingData = new List<Graph>(); // List to store all available Graph objects from the CSV

            // Loops through each lines in the CSV
            foreach (string line in System.IO.File.ReadAllLines(pathToCsv).Skip(1)) // .Skip(1) is for skipping header
            {
                // here line stands for each line in the csv file

                string[] InCsvLine = line.Split(',');

                // creating an object of type Graph based on the each csv line

                Graph Inst1 = new Graph();


                Inst1.Date = DateTime.ParseExact(InCsvLine[0], dateFormatString, CultureInfo.InvariantCulture); 

                Inst1.AvE = double.Parse(InCsvLine[15]);
                Inst1.AvI = double.Parse(InCsvLine[16]);

                chart1.Series["Speed"].YAxisType = AxisType.Primary;
                chart1.Series["Velocity"].YAxisType = AxisType.Secondary;
                chart1.Series["Speed"].Points.AddXY(Inst1.Date.TimeOfDay.ToString(), Inst1.AvE);
                chart1.Series["Speed"].ChartType = SeriesChartType.FastLine;
                chart1.Series["Velocity"].Points.AddXY(Inst1.Date.TimeOfDay.ToString(), Inst1.AvI);
                chart1.Series["Velocity"].ChartType = SeriesChartType.FastLine;
                ChartArea CA = chart1.ChartAreas[0];
                CA.AxisX.ScaleView.Zoomable = false;
                CA.AxisY.ScaleView.Zoomable = false;
                CA.CursorX.AutoScroll = true;
                CA.CursorX.IsUserSelectionEnabled = true;

            }
        }

This is out put of graph

1 个答案:

答案 0 :(得分:0)

以下是您可能想要学习的示例。

假设x值被添加为DateTimes;设置XValueType

eachSeries.XValueType = ChartValueType.DateTime;

它还假设您有一个要导出的sereis的班级列表:

var series2Export = new List<Series>() { chart.Series[0], chart.Series[1]};

进一步假设系列中的点是并行添加的,因此您希望将相同的范围一起导出,例如从指数33-66开始的前20或点。

现在您可以为SelectionRangeChanged事件编码(或者当然是保存 Button点击):

private void chart_SelectionRangeChanged(object sender, CursorEventArgs e)
{
    ChartArea ca = chart.ChartAreas[0];

    var d0 = (int) ca.CursorX.SelectionStart;
    var d1 = (int) ca.CursorX.SelectionEnd;
    var spoints  = series2Export[0].Points
                                   .Where(x => x.XValue >= d0  && x.XValue <= d1).ToList();
    string del1 = ";";
    string del2 = "\t";
    string fmt1 = "yyyy.MM.dd";
    string fmt2 = "#0.0";

    SaveFileDialog sfd = new SaveFileDialog();
    sfd.FileName = suggestedFilePath;
    sfd.Title =  (d1 - d0) + " points selected. Save data to..";
    if (sfd.ShowDialog() == DialogResult.OK)
    {
        StringBuilder sb = new StringBuilder();
        foreach (var dp0 in spoints)
        {
            int pi = chart.Series[0].Points.IndexOf(dp0);
            string st = "";
            foreach (var s in series2Export)
            {
                DataPoint dp = s.Points[pi];
                st +=  (DateTime.FromOADate(dp.XValue)).ToString(fmt1) +
                       del1 + dp.YValues[0].ToString(fmt2) + del2;
            }
            sb.AppendLine(st);
        }
        File.WriteAllText(sfd.FileName, sb.ToString());
    }
}

}

请注意,我已经为分隔符和数据的formts使用了字符串。你可以根据需要调整它们。

以上代码以以下格式导出所有参与系列的数据: x-value1,yvalue1 .. ;这意味着它假设......

  • 数据点包含您要导出的所有信息和
  • 您要导出每个点的x值。

如果您只想导出csv行,那么最简单的方法是将每行DataPoint存储到第一个系列中。存储它们的自然位置是Tags

以下是两个函数,用于从一行创建数据点列表并从一系列中恢复该行:

List<DataPoint> PointsFromCsvLine(string line)
{
    var parts = line.Split(',').ToList();        // use your separator
    DateTime dt = Convert.ToDateTime(parts[0]);  // add checks!
    double d1 = Convert.ToDouble(parts[1]);      // use..
    double d2 = Convert.ToDouble(parts[4]);      // ..your..
    double d3 = Convert.ToDouble(parts[9]);      // ..numbers!

    var points = new List<DataPoint>();
    points.Add(new DataPoint(  dt.ToOADate(), d1));
    points.Add(new DataPoint(  dt.ToOADate(), d2));
    points.Add(new DataPoint(  dt.ToOADate(), d3));
    points[0].Tag = line;
    return points;
}

string CsvLineFromPoint(Series series0, int index )
{
    DataPoint dp = series0.Points[index];            // check index
    string s = dp.Tag.ToString();
    return s;
}