How we count how many multiple selection in chart area? - c#

I want to count the multiple selections in chart area.As an example user can marked multiple selection as this picture,Multiple selected chart.So how I count how many multiple selection in this chart.This is MSchart in windowsform by using C#.
my multiple selection code as follows;
SizeF rangeOfCurve = SizeF.Empty;
List<SizeF> ranges = new List<SizeF>();
List<int> selectedIndices = new List<int>();
private void chart1_SelectionRangeChanged(object sender, CursorEventArgs e)
{
ranges.Add(rangeOfCurve);
selectedIndices.Union(collectDataPoints(chart1.Series[0],rangeOfCurve.Width, rangeOfCurve.Height)).Distinct();
StripLine sl = new StripLine();
sl.BackColor = Color.FromArgb(255, Color.LightSeaGreen);
sl.IntervalOffset = Math.Min(rangeOfCurve.Width, rangeOfCurve.Height);
sl.StripWidth = Math.Abs(rangeOfCurve.Height - rangeOfCurve.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)
{
rangeOfCurve = new SizeF((float)e.NewSelectionStart, (float)e.NewSelectionEnd);
}
This is my code for export those selected data to new .csv file.In here I added button click event then selected area data to export another .csv file.but I want to say I can add multiple selection in chart area but data is exported only last selected part only.how can I got all multiple selection data.this is code for getting one selected area data to another .csv file.
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))<=index && ( index<= (chart1.ChartAreas[0].CursorX.SelectionEnd)))
{
sw.WriteLine(line);
}
}
index++;
}
sw.Close();
}
MessageBox.Show("Data are copied to the new .CSV file");
}
If you can give any help to solve this.I am so much thankful to you.

Assuming you have added StripLines to mark selections, here is an example of how you can collect the DataPoints from these StripLines:
Let's create a List<> of point list:
selectionPoints = new List<List<DataPoint>>();
Now we can collect the DataPoints like this:
List<List<DataPoint>> GetSelectedPoints(ChartArea ca, Series S)
{
selectionPoints = new List<List<DataPoint>>();
foreach (var sl in ca.AxisX.StripLines)
{
List<DataPoint> points = new List<DataPoint>();
points = S.Points.Select(x => x)
.Where(x => x.XValue >= sl.IntervalOffset
&& x.XValue <= (sl.IntervalOffset + sl.StripWidth)).ToList();
selectionPoints.Add(points);
}
return selectionPoints;
}
And now we can do things with the DataPoints like color them..:
foreach (var pointList in selectionPoints)
{
foreach (var dp in pointList) dp.Color = Color.Red;
}
.. or export them:
string filePath = "D:\\demo.csv";
StringBuilder sb = new StringBuilder();
foreach (var pointList in selectionPoints)
{
foreach (var dp in pointList)
sb.Append(dp.XValue + "," + dp.YValues[0] + ";"); // pick your format!
}
File.WriteAllText(filePath, sb.ToString());

Related

Alternating colour in listview items

What i am trying to do here is loop a bunch of .csv files split the data, and then put the data in a listview, this is all working fine:
private void BtnRun_Click(object sender, EventArgs e)
{
try {
RunExtraction();
listViewMain.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
} catch (Exception ex) {
Helpers.DebugLogging("[" + DateTime.Now + "]-[" + ex.ToString() + "]");
}
}
private void ProcessCsvFile(string CsvLocation, string CsvFile) {
try {
string[] lines = File.ReadAllLines(#"backlinks\data.txt");
string[] hosts_list = new string[lines.Length];
for (int i = 0; i < lines.Length; i++)
{
hosts_list[i] = (lines[i].Split('|')[0]);
}
using (var reader = new StreamReader(CsvLocation))
{
while(reader.Peek() != -1) {
string line = reader.ReadLine();
List<string> lineValues = line.Split(',').ToList();
if (!lineValues[0].StartsWith("Time")) {
ListViewItem lv = new ListViewItem(lineValues[0].Replace(#"""", " "));
lv.SubItems.Add(lineValues[1].Replace(#"""", " "));
lv.SubItems.Add(lineValues[2]);
listViewMain.Items.Add(lv);
}
}
countToolStrip.Text = listViewMain.Items.Count.ToString() + " extracted ...";
}
} catch (Exception ex) {
Helpers.DebugLogging("[" + DateTime.Now + "]-[" + ex.ToString() + "]");
}
}
What i don't know how to do is alternate the colour between say green and pink for example, like this in the listview:
csv data = green
csv data = pink
csv data = green
csv data = pink
etc
In the listview, i don't need every row alternate, but every csv file block of information imported, they are different sizes in length, I cannot think of a way to do it, any help would be appreciated.
Since you haven't shared some parts of your code, I assume RunExtraction is calling ProcessCsvFile in a loop over csv files. Just add a new argument color to ProcessCsvFile. In RunExtraction, alternate it before calling ProcessCsvFile. Pseudocode below:
RunExtraction()
{
var colors = new List<Color>() { Colors.Green, Colors.Pink }; // add more if you want
var colorIndex = 0;
var csvLocation = "<some-path>";
foreach (var csvFile in csvFiles) {
var color = colors[colorIndex % colors.Count]; // allows you use more than two colors to alternate
ProcessCsvFile(csvLocation, color); // CsvFile is not used, so it is removed
colorIndex++;
}
}
You may just use a simple counter inside the loop and check if it's even/odd
var counter = 1;
while (/* ... */)
{
// ...
if (counter%2 == 0) lv.ForeColor = Color.Green;
// ...
counter++;
}
You can loop through GridView using DataGridViewRow and check if the row is even then Green else Pink for odd rows. Just like this:
foreach (DataGridViewRow row in GridView1.Rows)
if (row.Index % 2==0 )
{
row.DefaultCellStyle.BackColor = Color.Green;
}
else{
row.DefaultCellStyle.BackColor = Color.Pink;
}

Adding data to second column of Datagrid

I have a datagrid DGV. That gridview has a column of "File Name" and is populated by the name of the files you've selected in an openfildialog. After performing the calculations I was putting the results in a second datagrid DGV2 which you'll see I've commented out below as I'd like to instead put them on a second column next to their corresponding "File Name" on DGV and just use one gridview. However this is just taking the last calculation and duplicating it on each row rather than the individual calculations (as they should all be diff)
So it should look like:
File1 4.5
File2 3.5
Instead its just doing
File1 3.5
File2 3.5
I know I'm causing it, I've done something wrong here I'm just not sure how to fix it.
private void btnCalculate_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in DGV_Hidden.Rows)
{
FileInfo info = new FileInfo();
{
var lines = File.ReadAllLines(row.Cells["colfilelocation"].Value.ToString());
var data = lines.Where(line => (!line.Contains(Data_Start_Point_Identifier) && !line.Contains(FSD__Line_Identifier) && !line.EndsWith("0.00"))).ToList();
if (data.Count > 1)
{
var line = data[0];
var firstsplit = data[1].Split(splitter);
info.startvalue = Convert.ToDouble(firstsplit[0]);
var secondsplit = data[data.Count - 1].Split(splitter);
info.endvalue = Convert.ToDouble(secondsplit[0]);
}
info.finalnum = info.startvalue - info.endvalue;
}
//DGV2.Rows.Add(info.finalnum);
for (int i = 0; i < DGV.Rows.Count; i++)
{
DGV.Rows[i].Cells["colfiledata"].Value = info.finalnum;
}
}
}
ok,
As you said you have similar data /number of rows, You just need to set the value while looping through your hidden grid. use the row index of the looping variable to get the correct row.
private void btnCalculate_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in DGV_Hidden.Rows)
{
FileInfo info = new FileInfo();
{
var lines = File.ReadAllLines(row.Cells["colfilelocation"].Value.ToString());
var data = lines.Where(line => (!line.Contains(Data_Start_Point_Identifier) && !line.Contains(FSD__Line_Identifier) && !line.EndsWith("0.00"))).ToList();
if (data.Count > 1)
{
var line = data[0];
var firstsplit = data[1].Split(splitter);
info.startvalue = Convert.ToDouble(firstsplit[0]);
var secondsplit = data[data.Count - 1].Split(splitter);
info.endvalue = Convert.ToDouble(secondsplit[0]);
}
info.finalnum = info.startvalue - info.endvalue;
}
//set your value here
DGV.Rows[row.Index].Cells["colfiledata"].Value = info.finalnum;
}
}

How to get selected chart area data in C#

I plotted a graph by using .csv file.Now user enable to select the chart area and clicking export button then selected data want to write another .csv file.
In here I want to approach this methods.User want to get chart1.ChartAreas[0].CursorX.SelectionStart,chart1.ChartAreas[0].CursorX.SelectionEndthen want to read .csv file and deleting others raw that in not selected area.
Note:the user want to select multiple chart area also.Please give me a clarification about this.This is winform application and I use MsChart.
my code as follows;
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");
}
Following code for my multiple selection for chart area.
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);
}
Following code is plotted graph;
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
Here is an example you may want to study.
It assumes that the x-values are added as DateTimes; set the XValueType!
eachSeries.XValueType = ChartValueType.DateTime;
It also assumes that you have a class level List of sereis to be exported:
var series2Export = new List<Series>() { chart.Series[0], chart.Series[1]};
It assumes further that the points in the series are added in parallel, so that you want to export the same range together, e.g. to first 20 or points from index 33-66..
Now you can for example code the SelectionRangeChanged event (or, of course a Save Button click):
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());
}
}
}
Note that I have used strings for both the delimiters and the formts of the data. You can adapt them as needed..
The above code is exporting the data from all participating series in the format: x-value1, yvalue1..; this means it assumes that..
the datapoints contain all the information you want to export and
you want to export the x-values for each point.
If you want to export just the csv line as you had read it in, the simplest way is to store that line with each DataPoint, of, say the 1st series. The natural spot to store them in are the Tags.
Here are two functions to create a list of data points from a line and to restore that line from a series:
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;
}

How can I make 1 button click fill out 2 different text boxes

I need help making this program fill out 2 different text boxes. It works if I only use it to fill out 1 text box using a First name. But when I try and add another text box to generate a random Last name it just seems to do fail.
private void button1_Click(object sender, EventArgs e)
{
Random r = new Random();
int currentLine = 1;
string pick = null;
foreach (string line in File.ReadLines("C:\\First Names.txt"))
{
if (r.Next(currentLine) == 0)
{
pick = line;
}
++currentLine;
textBox1.Text = pick;
}
Random n = new Random();
int currentLine1 = 1;
string pick1 = null;
foreach (string line1 in File.ReadLines("C:\\Last Names.txt"))
{
if (n.Next(currentLine1) == 0)
{
pick1 = line1;
}
++currentLine1;
textBox2.Text = pick1;
}
}
}
}
Check whether the path for the file is appropriate.
You need not create two objects for the same class and access them differently.One object is enough.
3.Check whether data is there in the file or not.`Random r = new Random();
int currentLine = 1;
string pick = null;
foreach (string line in File.ReadLines("C:\\First Names.txt"))
{
if (r.Next(currentLine) == 0)
{
pick = line;
}
++currentLine;
textBox1.Text = pick;
}
currentLine=0;pick=0;
foreach (string line in File.ReadLines("C:\\Last Names.txt"))
{
if (r.Next(currentLine) == 0)
{
pick = line;
}
++currentLine;
textBox2.Text = pick;
}
}`
If the first iteration gets the value, then the second must also get. Else there is some problem with Text file or the 'textBox2' is not the correct ID you are looking for.

Remove a checkbox that is being created dynamically in a loop

I have a bunch of code that dynamicly creates some controls. It looks in a folder and lists the filenames in it. For each file in the folder it creates a checklistbox item, listbox item and two checkboxes. This is working great and as intended:
private void getAllFiles(string type)
{
try
{
string listPath = "not_defined";
if (type == "internal_mod")
{
int first_line = 76;
int next_line = 0;
int i = 0;
CheckBox[] chkMod = new CheckBox[100];
CheckBox[] chkTool = new CheckBox[100];
listPath = this.internalModsPath.Text;
string[] filesToList = System.IO.Directory.GetFiles(listPath);
foreach (string file in filesToList)
{
if (!internalModsChkList.Items.Contains(file))
{
internalModsChkList.Items.Add(file, false);
string fileName = Path.GetFileName(file);
internalModNameList.Items.Add(fileName);
//-----------------
// Draw Checkboxes
//-----------------
chkMod[i] = new CheckBox(); chkTool[i] = new CheckBox();
chkMod[i].Name = "modChk" + i.ToString(); chkTool[i].Name = "modChk" + i.ToString();
//chkMod[i].TabIndex = i; //chkTool[i].TabIndex = i;
chkMod[i].Anchor = (AnchorStyles.Left | AnchorStyles.Top); chkTool[i].Anchor = (AnchorStyles.Left | AnchorStyles.Top);
chkMod[i].Checked = true; chkTool[i].Checked = false;
chkMod[i].AutoCheck = true; chkTool[i].AutoCheck = true;
chkMod[i].Bounds = new Rectangle(549, first_line + next_line, 15, 15); chkTool[i].Bounds = new Rectangle(606, first_line + next_line, 15, 15);
groupBox7.Controls.Add(chkMod[i]); groupBox7.Controls.Add(chkTool[i]);
//-----------------
next_line += 15;
i++;
}
}
}
Now my problem is that I also want the user to be able to delete all these thing again based on the checklistbox' checked items.. I have no problems deleting the items in the checklistbox or the items in the listbox, but I want to remove the two checkboxes I create too ..
This is what I got to remove the items in the checklistbox, and the listbox
private void internalModListDel_btn_Click(object sender, EventArgs e)
{
int count = internalModsChkList.Items.Count;
for (int index = count; index > 0; index--)
{
if (internalModsChkList.CheckedItems.Contains(internalModsChkList.Items[index - 1]))
{
internalModsChkList.Items.RemoveAt(index - 1);
internalModNameList.Items.RemoveAt(index - 1);
groupBox7.Controls.Remove(modChk[index - 1]);
}
}
}
As you can see I have also tried to write something to remove the checkbox but it doesn't work and I have no idea how to make it work
Can you assist ?
Try using UserControls.
Use the ListBox controller to show those UserControls,
The user control can be built with those checkboxes, and the labels you want .
Another suggestion is to bind this list to an ObservableCollection which will contain the UserContorols you have created.
This way, it will be much more simlpe to add/remove/change the items inside.

Categories

Resources