I want to rename the specified worksheet and put some processed data on it, but the following code (which looks almost the same as every example I could find on this and other websites) just won't to what I want:
try
{
xl.Worksheet = (ExcelRefer.Worksheet) xl.Workbook.Worksheets.get_Item("Sheet1");
xl.Worksheet.Name = "Smoothed result";
xl.Workbook.Save();
xl.Range = xl.Worksheet.UsedRange;
Debug.WriteLine("Saved");
}
catch(Exception exception)
{
MessageBox.Show(exception.Message);
}
The exception is never thrown, so the code doesn't contain any errors but the worksheet in the document I've opened still has the same name. Also, the
Debug.WriteLine(...)
method is called and the output is correctly displayed. It does even ask me if I want to overwrite the existing file when I tell the Workbook to save. Could anyone tell me what I'm doing wrong?
Edit:
xl is an object of a class that contains all necessary elements for working with excel.
using ExcelRefer = Microsoft.Office.Interop.Excel;
using Microsoft.Office.Tools.Excel;
using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using ZedGraph;
class XLSXMulti
{
private static List<int[]> dataPositions = new List<int[]>();
private static PointPairList measureData = new PointPairList();
private static PointPairList[] dataComparison = new PointPairList[2];
private static bool smoothing = false;
private static bool measureDataFound = false;
private static bool fileFinished = false;
private static string[] excelFilePaths;
private static string[] temp;
private static int numberOfSamples;
private static BackgroundWorker[] bwg;
private static ProgressBar pbExcel;
public static void Init(string[] filePaths, ProgressBar pb, bool smooth)
{
excelFilePaths = filePaths;
pbExcel = pb;
smoothing = smooth;
measureData.Clear();
dataPositions.Clear();
temp = Interaction.InputBox("Number of consecutive values to be used " +
"for smoothing and the iteration step. These values" +
" will be used for all selected files.\n" +
"IMPORTANT: The two values have to be separated with a ','!",
"Select grade of smoothing",
"5,1", 500, 480).Split(',');
bwg = new BackgroundWorker[Environment.ProcessorCount];
for(int i = 0; i < bwg.Length; i ++)
{
bwg[i] = new BackgroundWorker();
}
foreach(BackgroundWorker bw in bwg)
{
bw.DoWork += bwg_doWork;
bw.ProgressChanged += bwg_ProgressChanged;
bw.RunWorkerCompleted += bwg_RunworkerCompleted;
bw.WorkerSupportsCancellation = true;
bw.WorkerReportsProgress = true;
}
List<string>[] filesForWorkers = new List<string>[bwg.Length];
for(int i = 0; i < filesForWorkers.Length; i ++)
{
filesForWorkers[i] = new List<string>();
}
int filesPerWorker = filePaths.Length / bwg.Length;
int workerindex = 0;
MessageBox.Show("filesPerWorker: " + filesPerWorker + "\n" +
"filePaths: " + filePaths.Length + "\n" +
"bwg: " + bwg.Length);
for(int i = 0; i < filePaths.Length; i ++)
{
filesForWorkers[workerindex].Add(filePaths[i]);
workerindex ++;
if(workerindex == bwg.Length)
{
workerindex = 0;
}
}
for(int i = 0; i < bwg.Length; i ++)
{
bwg[i].RunWorkerAsync(filesForWorkers[i]);
}
}
private static void bwg_doWork(object sender, DoWorkEventArgs e)
{
List<string> filelist = e.Argument as List<string>;
Excelattributes xl = new Excelattributes();
foreach(string s in filelist)
{
try
{
xl.App = new ExcelRefer.Application();
xl.Workbook = xl.App.Workbooks.Open(s, 0, true, 5, "", "", true,
Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xl.Worksheet = (ExcelRefer.Worksheet)xl.Workbook.Worksheets.get_Item(1); // Zugriff auf eingegebenes Tabellenblatt
xl.Range = xl.Worksheet.UsedRange;
findMeasureData(xl);
if(xl.Workbook != null){xl.Workbook.Close(true, null, null);}
if(xl.App != null) {xl.App.Quit();}
}
catch(Exception exception)
{
MessageBox.Show(exception.Message, "Exception");
}
finally
{
if(xl.Workbook != null){xl.Workbook.Close(true, null, null);}
if(xl.App != null) {xl.App.Quit();}
}
}
}
private static void bwg_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// TODO: implement some sort of progress reporting
}
private static void bwg_RunworkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Statuslabel.label.Text = "Backgroundworker finished";
(sender as BackgroundWorker).Dispose();
}
private static void findMeasureData(Excelattributes xl)
{
// Erste 15 Zeilen durchgehen, um herauszufinden wo die Messwerte beginnen (9 + 6 Sicherheit)
// Nur bis inkl. Spalte AZ
try
{
for(int zeile = 1; zeile <= 15; zeile ++)
{
for(int spalte = 1; spalte <= 52; spalte ++)
{
// WICHTIG: (xl.Range...).Text verwenden, um Nullreferenceexception zu vermeiden [?]
Object zelleninhalt = (xl.Range.Cells[zeile, spalte] as ExcelRefer.Range).Text;
if(zelleninhalt.Equals("DATA START"))
{
dataPositions.Add(new int[2] {zeile +1, spalte +1});
measureDataFound = true;
}
else if(zelleninhalt.Equals("Number of Samples"))
{
numberOfSamples = Convert.ToInt32((xl.Range.Cells[zeile, spalte+1] as
ExcelRefer.Range).Text);
}
}
}
if(measureDataFound == true)
{
int[,] temp = new int[dataPositions.Count, 2];
for(int i = 0; i < dataPositions.Count; i ++)
{
temp[i, 0] = dataPositions.ElementAt(i).ToArray()[0];
temp[i, 1] = dataPositions.ElementAt(i).ToArray()[1];
}
readMeasureData(temp, xl);
}
}
catch(Exception exception)
{
MessageBox.Show(exception.Message, "Exception");
}
}
private static void readMeasureData(int[,] temp, Excelattributes xl)
{
int[,] zellen = temp;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for(int i = zellen[0,0]; i < (zellen[0,0] + numberOfSamples); i ++)
{
try
{
double weg = Convert.ToDouble((xl.Range.Cells[i, zellen[0,1]] as ExcelRefer.Range).Value2);
double kraft = Convert.ToDouble((xl.Range.Cells[i, zellen[1,1]] as ExcelRefer.Range).Value2);
measureData.Add(new PointPair(weg, kraft));
}
catch(Exception exception)
{
MessageBox.Show(exception.Message, "Exception");
Application.Exit();
}
}
stopwatch.Stop();
MessageBox.Show(stopwatch.ElapsedMilliseconds / 1000 + " Sekunden");
dataComparison[0] = measureData;
if(smoothing == true)
{
smoothMeasureData(xl);
}
}
private static void smoothMeasureData(Excelattributes xl)
{
if(temp != null)
{
try
{
int[] smoothParameters = new int[]{Convert.ToInt32(temp[0]), Convert.ToInt32(temp[1])};
if(smoothParameters[1] == 0) {smoothParameters[1] = 1;}
PointPairList smoothedData = new PointPairList();
MessageBox.Show("Glätte...\n" + smoothParameters[0] + " " + measureData.Count);
for(int i = (smoothParameters[0] -1); i < measureData.Count; i += smoothParameters[1])
{
double durchschnittX = 0;
double durchschnittY = 0;
for(int x = i; x > (i - (smoothParameters[0])); x --)
{
durchschnittX += measureData.ElementAt(x).X;
durchschnittY += measureData.ElementAt(x).Y;
}
durchschnittX /= (double) smoothParameters[0];
durchschnittY /= (double) smoothParameters[0];
smoothedData.Add(new PointPair(durchschnittX, durchschnittY));
}
dataComparison[0] = measureData;
dataComparison[1] = smoothedData;
writeToXLSX(smoothedData, xl);
}
catch(Exception exception)
{
MessageBox.Show(exception.Message, "Exception");
}
}
}
private static void writeToXLSX(PointPairList smoothedData, Excelattributes xl)
{
try
{
xl.Worksheet = (ExcelRefer.Worksheet) xl.Workbook.Worksheets.get_Item("Sheet1");
xl.Worksheet.Name = "Smoothed result";
xl.Workbook.Save();
xl.Workbook.Close(true, null, null);
xl.Range = xl.Worksheet.UsedRange;
Debug.WriteLine("Saved");
}
catch(Exception exception)
{
MessageBox.Show(exception.Message);
}
}
}
Have you tried closing Excel when you've finished?
I can't quite work out where you are gettng xl from but the following code works for me:
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
Workbook book = xlApp.Workbooks.Open(#"C:\test.xlsx");
Worksheet xl = book.Worksheets.get_Item("sheet1");
xl.Name = "Smoothed result";
book.Save();
book.Close();
Edit
After seeing the code you are using to open the workbook I think the issue is there. You are opening the file using:
xl.Workbook = xl.App.Workbooks.Open(s, 0, true, 5, "", "", true,
Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
The third parameter is a ReadOnly parameter which you have set to true. Try setting that to false.
Related
I am looking to store values from a CSV file with two Columns, I have the following class ReadFromCSVhandling the reading of the CSV file but I am having difficulty using this list to display the contents once a button is clicked. The code I have to read the CSV file is as follows;
namespace ELMFS
{
public class ReadFromCSV
{
static void ReadCSV(string[] args)
{
List<TextSpeak> TxtSpk = File.ReadAllLines(#"C:\textwords.csv")
.Skip(1)
.Select(t => TextSpeak.FromCsv(t))
.ToList();
}
}
public class TextSpeak
{
string Abreviated;
string Expanded;
public static TextSpeak FromCsv(string csvLine)
{
string[] TxtSpk = csvLine.Split(',');
TextSpeak textSpeak = new TextSpeak();
textSpeak.Abreviated = TxtSpk[0];
textSpeak.Expanded = TxtSpk[1];
return textSpeak;
}
}
}
I am trying to display the textSpeak.Abreviated in a message box but cannot seem to access it from the WPF window.
How do I use this list in other windows within the application?
any advice would be appreciated!
Thanks in advance!
First, ReadCSV method should return the generated List object (or you cannot use the list anywhere else).
Second, TextSpeak class should have properties so that you can access its member variables outside the class.
I.e. something like this should work:
namespace ELMFS
{
public class ReadFromCSV
{
public static List<TextSpeak> ReadCSV(string[] args)
{
List<TextSpeak> TxtSpk = File.ReadAllLines(#"C:\textwords.csv")
.Skip(1)
.Select(t => TextSpeak.FromCsv(t))
.ToList();
return TxtSpk;
}
}
public class TextSpeak
{
public string Abreviated { get; private set; }
public string Expanded { get; private set; }
public static TextSpeak FromCsv(string csvLine)
{
string[] TxtSpk = csvLine.Split(',');
TextSpeak textSpeak = new TextSpeak();
textSpeak.Abreviated = TxtSpk[0];
textSpeak.Expanded = TxtSpk[1];
return textSpeak;
}
}
}
private void Display(int count)
{
textBox1.Text = "";
for (int i = 0; i <= count ; i++)
{
textBox1.Text += ((dataGridView1.Rows[i].Cells[1].Value).ToString()) + (dataGridView1.Rows[i].Cells[2].Value.ToString()) + Environment.NewLine;
}
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
// your code here
string CSVFilePathName =Path.GetDirectoryName(Application.ExecutablePath).Replace(#"\bin\Debug", #"\NewFolder1\TEST.csv");
string[] Lines = File.ReadAllLines(CSVFilePathName);
string[] Fields;
Fields = Lines[0].Split(new char[] { ',' });
int Cols = Fields.GetLength(0);
DataTable dt = new DataTable();
//1st row must be column names; force lower case to ensure matching later on.
for (int i = 0; i < Cols; i++)
dt.Columns.Add(Fields[i].ToLower(), typeof(string));
DataRow Row;
for (int i = 1; i < Lines.GetLength(0); i++)
{
Fields = Lines[i].Split(new char[] { ',' });
Row = dt.NewRow();
for (int f = 0; f < Cols; f++)
Row[f] = Fields[f];
dt.Rows.Add(Row);
}
dataGridView1.DataSource = dt;
int count = 0;
if (dataGridView1.RowCount > 0)
{
count = dataGridView1.Rows.Count;
}
buttons = new Button[count];
for (int i = 0; i <count; i++)
{
buttons[i] = new Button();
buttons[i].Name = "buttons_Click" + i.ToString();
buttons[i].Text = "Click";
buttons[i].Click += new EventHandler(buttons_Click);
this.Controls.Add(buttons[i]);
buttons[i].Visible = false;
}
buttons[0].Visible = true;
// buttons[1].Visible = true;
}
catch (Exception ex)
{
MessageBox.Show("Error is " + ex.ToString());
throw;
}
}
private void buttons_Click(object sender, EventArgs e)
{
int count = dataGridView1.Rows.Count-1;
if(c <= count)
{
if (buttons[c].Name == "buttons_Click" + c.ToString())
{
buttons[c].Visible = false;
int j = c;
Display(j);
if (c != count)
{
c = c + 1;
buttons[c].Visible = true;
}
}
}
if (c == count)
{
buttons[0].Visible = true;
}
}
}
}
Today I was trying to chart data from project where I recieve it by transmitting from my uC via UART.
The program is just to recieve data in interrupt, process it and display.
When program goes to my ChartData method I'm getting an exception:
An unhandled exception of type 'System.InvalidOperationException'
occurred in System.Windows.Forms.dll
Additional information: Cross-thread operation not valid: Control
'chart1' accessed from a thread other than the thread it was created
on.
It is strange for me - I think that I've got one thread in my program.
I have tried charting with pure project where I create data in Form_Load event - everything works fine.
My source code is here - any idea?
public partial class Form1 : Form
{
private List<float> freqList = new List<float>();
private List<float> magList = new List<float>();
private float[] fFrequency = new float[numberOfSamples];
private float[] fMagnitude = new float[numberOfSamples];
public static int counterOfRecBytes = 0;
public static int numberOfSamples = 512;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
GetAvailablePorts();
tb_Rx.Text = "Wprowadź parametry transmisji";
// Default transmission parameters for testing
cb_BaudRate.Text = "9600";
cb_Ports.Text = "COM5";
}
/// <summary>
/// Checks avaiable serialports - for linking my device to other computers
/// </summary>
void GetAvailablePorts()
{
string[] ports = SerialPort.GetPortNames();
cb_Ports.Items.AddRange(ports);
//cb_Ports.SelectedIndex = 0;
}
private void bt_connect_Click(object sender, EventArgs e)
{
if (bt_connect.Text == "Connect")
{
if (cb_Ports.Text == "" || cb_BaudRate.Text == "" || cb_Ports.Text == "")
tb_Rx.Text = "Nie wybrano jednego z parametrów";
else
{
bt_connect.Text = "Disconnect";
SerialP.PortName = cb_Ports.Text;
SerialP.BaudRate = Convert.ToInt32(cb_BaudRate.Text);
SerialP.StopBits = StopBits.One;
SerialP.DataBits = 8;
SerialP.Parity = Parity.None;
SerialP.Handshake = Handshake.None;
SerialP.ReadBufferSize = 8 * numberOfSamples + 4;
SerialP.Open();
pb_connect.Value = 100;
tb_Rx.Clear();
cb_Ports.Enabled = false;
cb_BaudRate.Enabled = false;
}
}
else
{
SerialP.Close();
bt_connect.Text = "Connect";
pb_connect.Value = 0;
bt_connect.Enabled = true;
cb_BaudRate.Enabled = true;
cb_Ports.Enabled = true;
freqList.Clear();
magList.Clear();
pb_connect.Value = 0;
tb_Rx.AppendText(Environment.NewLine + "----Zamknięto połączenie----");
}
}
private void SerialP_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
byte[] bArray = new byte[8 * numberOfSamples+4]; // frequencies (512 samples) and magnitudes (512 values) - each is a single precision float so 4 bytes
float[] fArray = new float[2*numberOfSamples];
//bool dataStart = false;
int previouse = counterOfRecBytes;
counterOfRecBytes += sp.BytesToRead;
sp.Read(bArray, previouse, (counterOfRecBytes - previouse));
if (counterOfRecBytes == 8*numberOfSamples+4)
{
for(uint i = 1; i < 2*numberOfSamples+1; i++)
{
// if (freqList.Count == numberOfSamples) freqList.Clear();
// if (magList.Count == numberOfSamples) magList.Clear();
fArray[i-1] = ByteToFloat(bArray, i);
if (i < numberOfSamples+1) freqList.Add(fArray[i]);
else magList.Add(fArray[i-1]);
}
//ListToArray();
ChartData();
// if (counterOfRecBytes >= 8 * numberOfSamples + 4) sp.DiscardInBuffer();
counterOfRecBytes = 0;
}
}
/// <summary>
/// Changes my recieved bArray to single precision floats
/// </summary>
private float ByteToFloat(byte[] input, UInt32 i)
{
byte[] array = new[] { input[4 * i], input[4 * i + 1], input[4 * i + 2], input[4 * i + 3] };
return BitConverter.ToSingle(array, 0);
}
/// <summary>
/// Setting chart data
/// </summary>
private void ChartData()
{
for (int i = 0; i < numberOfSamples; i++)
{
chart1.Series["Widmo"].Points.AddXY(freqList[i], magList[i]);
}
}
}
Problem solved - what I had to do was putting code below in place of just calling ChartData method:
if (InvokeRequired)
{
Invoke(new MethodInvoker(ChartData));
}
else
{
ChartData();
}
My C# classes will create a GUI that takes in csv files and plot a line graph accordingly. Currently, my graphs are plotted and saved using the GUI file dialog.
What I am trying to do now is to read, plot and save the graph using command-line instead (NO GUI needed).
May I know how could I call my Read and Plot classes using the "-f" flag (file path, can have multiple csv file) and save the plotted graph using the "-o" flag (output file path, only 1 file produced)?
Thanks.
You can use this:
class Program:
static class Program
{
[System.Runtime.InteropServices.DllImport("kernel32.dll")] // ### Edit 3 ###
static extern bool AttachConsole(int dwProcessId); // ### Edit 3 ###
/// <summary>The main entry point for the application.</summary>
[STAThread]
static void Main(string[] args)
{
// redirect console output to parent process;
// must be before any calls to Console.WriteLine()
AttachConsole(-1);// ### Edit 3 ###
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//program.exe -f c:\\desktop\\1.csv -o c:\\desktop\\1.png
var inputFile = new List<string>();
string outputFile = null;
if (args.Length > 0)
{
for (int i = 0; i < args.Length; i++)
{
string a = args[i].ToLower();
switch (a)
{
case "-f":
for (i = i + 1; i < args.Length ; i++)
{
string f = args[i]; if (f.StartsWith("-")) { i--; break; }
inputFile.Add(f); //get next arg as inputFile
}
break;
case "-o":
outputFile = args[++i]; //get next arg as outputFile
break;
}
}
if (inputFile.Count > 0 && outputFile != null)
{
var form = new Form2(); //specify your form class
form.showErrorsInConsole = true; // ### Edit 3 ###
//form.Visible = true;
form.DoReadFiles(inputFile.ToArray());
form.DoPlot();
form.SavePic(outputFile);
form.Dispose();
return;
}
}
//else
Application.Run(new Form2()); //show GUI
//MessageBox.Show("Args:\r\n" + s);
}
}
Form class (the form conatining your chart, in my code it is Form2):
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
List<Read> rList = new List<Read>();
public bool showErrorsInConsole = false; //### Edit 3 ###
public void DoReadFiles(string[] fileNames)
{
try
{
rList.Clear();
foreach (String file in fileNames) //if ((myStream = ff.OpenFile()) != null)
{
Read r = new Read(file);
rList.Add(r);
}
}
catch (Exception err)
{
//Inform the user if we can't read the file
if (showErrorsInConsole) //### Edit 3 ###
Console.WriteLine("\r\n *** Error: " + err.Message); //### Edit 3 ###
else
MessageBox.Show(err.Message);
}
}
public void DoPlot(int indX = 0, int indY = 1)
{
Plot.Draw(chart, rList, indX, indY);
}
public void SavePic(string outputFile)
{
bool isPng = outputFile.EndsWith(".png", StringComparison.OrdinalIgnoreCase);
chart.SaveImage(outputFile, isPng ? ChartImageFormat.Png : ChartImageFormat.Jpeg);
}
void openToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog ff = new OpenFileDialog();
ff.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); //"C:\\";
ff.Filter = "csv files (*.csv)|*.csv|All files (*.*)|*.*";
ff.Multiselect = true;
ff.FilterIndex = 1;
ff.RestoreDirectory = true;
if (ff.ShowDialog() == DialogResult.OK)
{
try
{
DoReadFiles(ff.FileNames);
//Populate the ComboBoxes
if (rList.Count > 0)
{
string[] header = rList[0].header; //header of first file
xBox.DataSource = header;
yBox.DataSource = header.Clone(); //without Clone the 2 comboboxes link together!
}
if (yBox.Items.Count > 1) yBox.SelectedIndex = 1; //select second item
}
catch (Exception err)
{
//Inform the user if we can't read the file
MessageBox.Show(err.Message);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
DoPlot(xBox.SelectedIndex, yBox.SelectedIndex);
}
} //end class Form2
class Read:
public class Read
{
public int nLines { get; private set; }
public int nColumns { get; private set; }
public string[] header { get; private set; }
public float[,] data { get; private set; }
public string fileName { get; set; }
public string[] section { get; private set; }
public Read(string file)
{
string[] pieces;
fileName = Path.GetFileName(file);
string[] lines = File.ReadAllLines(file); // read all lines
if (lines == null || lines.Length < 2) return; //no data in file
header = lines[0].Split(','); //first line is header
nLines = lines.Length - 1; //first line is header
nColumns = header.Length;
//read the numerical data and section name from the file
data = new float[nLines, nColumns - 1]; // 1 less than nColumns as last col is sectionName
section = new string[nLines];
for (int i = 0; i < nLines; i++)
{
pieces = lines[i + 1].Split(','); // i(+1) is because first line is header
if (pieces.Length != nColumns) { MessageBox.Show("Invalid data at line " + (i + 2) + " of file " + fileName); return; }
for (int j = 0; j < nColumns - 1; j++)
{
float.TryParse(pieces[j], out data[i, j]); //data[i, j] = float.Parse(pieces[j]);
}
section[i] = pieces[nColumns - 1]; //last item
}
}
}
class Plot:
public class Plot
{
public static void Draw(Chart chart, List<Read> rList, int indX = 0, int indY = 1)
{
chart.Series.Clear(); //ensure that the chart is empty
chart.Legends.Clear();
Legend myLegend = chart.Legends.Add("myLegend");
myLegend.Title = "myTitle";
Color[] colors = new Color[] { Color.Black, Color.Blue, Color.Red, Color.Green, Color.Magenta, Color.DarkCyan, Color.Chocolate, Color.DarkMagenta };
var sectionColors = new Dictionary<string, int>();
bool separateSections = (rList.Count == 1); // #Edit: 4
int i = 0;
int iColor = -1, maxColor = -1;
foreach (Read rr in rList)
{
float[,] data = rr.data;
int nLines = rr.nLines;
int nColumns = rr.nColumns;
string[] header = rr.header;
chart.Series.Add("Series" + i);
chart.Series[i].ChartType = SeriesChartType.Line;
chart.Series[i].LegendText = rr.fileName; // #Edit: 4
if (separateSections) chart.Series[i].IsVisibleInLegend = false; // #Edit: 4
chart.ChartAreas[0].AxisX.LabelStyle.Format = "{F2}";
chart.ChartAreas[0].AxisX.Title = header[indX];
chart.ChartAreas[0].AxisY.Title = header[indY];
for (int j = 0; j < nLines; j++)
{
int k = chart.Series[i].Points.AddXY(data[j, indX], data[j, indY]);
if (separateSections) // #Edit: 4
{
string curSection = rr.section[j];
if (sectionColors.ContainsKey(curSection))
{
iColor = sectionColors[curSection];
}
else
{
maxColor++;
iColor = maxColor; sectionColors[curSection] = iColor;
}
chart.Series[i].Points[k].Color = colors[iColor];
}
}
i++; //series#
} //end foreach rr
//fill legend based on series
foreach (var x in sectionColors)
{
string section = x.Key;
iColor = x.Value;
myLegend.CustomItems.Add(colors[iColor], section); //new LegendItem()
}
}
}
If you are looking for something simple then you can just have a loop and get the values like this:
string f=null;
string o=null;
for (var i = 0; i < args.Length; i++)
{
if (args[i] == "-f") { f = args[i + 1]; }
else if (args[i] == "-o") { o = args[i + 1]; }
}
if (f != null)
{
}
if (o != null)
{
}
You can use command parser libraries. Command Line Parser ( http://commandline.codeplex.com/ ) is very easy to use.
[Option("f", "input", Required = true]
public string InputFile { get; set; }
[Option("o", "output", Required = true]
public string OutputFile { get; set; }
Hello I have a code where I inside of a datagridview generate buttons with data from sql server database. But now I want to scroll them through buttons. I tried lots of things all gives me error already saw a post about this but nothing worked for me can someone help.
<-----------------------------------My code------------------------------------->
Methods to fill the datagridview:
public void TabelaFuncionario()
{
try
{
BDfuncionarios = new DataTable();
string cmd = "My select string";
var adpt = fConexao.GetDataAdapter(cmd);
BDfuncionarios.Clear();
adpt.Fill(BDfuncionarios);
}
catch (Exception r)
{
MessageBox.Show(r.Message);
}
}
public void BotaoFuncionario()
{
try
{
TabelaFuncionario();
PosXartigo = 1;
PosYartigo = 1;
//Apagar o painel todo
dataGridView1.Controls.Clear();
foreach (DataRow row in BDfuncionarios.Rows)
{
int posicaoX = ((PosXartigo - 1) * Gap_Xartigo) + xInicial + (Largura_BotaoArtigo * (PosXartigo - 1));
if (posicaoX > maximoxArtigo)
{
PosYartigo++; PosXartigo = 1;
}
else
{
PosXartigo = PosXartigo != 1 ? PosXartigo++ : 1;
}
int PontoX = ((PosXartigo - 1) * Gap_Xartigo) + xInicial + (Largura_BotaoArtigo * (PosXartigo - 1));
int PontoY = ((PosYartigo - 1) * Gap_Yartigo) + yInicial + (Altura_BotaoArtigo * (PosYartigo - 1));
Button bt1 = new Button();
bt1.Location = new Point(PontoX, PontoY);
Mo mo = new Mo();
mo.codmo = (int)row["Something"];
mo.nome_func = (string)row["Something"];
bt1.Name = "Botao" + NBotoes.ToString();
bt1.Height = Altura_BotaoArtigo;
bt1.Width = Largura_BotaoArtigo;
bt1.BackColor = Color.Tan;
bt1.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
bt1.ForeColor = Color.Black;
bt1.Text = mo.nome_func;
bt1.Tag = mo;
bt1.FlatStyle = FlatStyle.Popup;
bt1.Click += btArtigo_click;
dataGridView1.Controls.Add(bt1);
NBotoes++;
PosXartigo++;
}
}
catch (Exception r)
{
MessageBox.Show(r.Message);
}
}
Image of my form (don't know if it helps):
http://imgur.com/f5G25nX
<--------------------------EDITED--------------------------------->
i have tried things like this :https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.rowcount(v=vs.110).aspx
Gives me out of range or something like that
And tried this just now
int row = dataGridView1.RowCount;
MessageBox.Show(row+"");
And it displays me 0; how can i have buttons inside my grid but have 0 rows?
I solved the problem using this panel instead of datagrid for what u wanted it was much better the code will be below:
Methods:
public void TabelaFuncionario()
{
try
{
BDfuncionarios = new DataTable();
string cmd = "your select";
var adpt = fConexao.GetDataAdapter(cmd);
BDfuncionarios.Clear();
adpt.Fill(BDfuncionarios);
}
catch (Exception r)
{
MessageBox.Show(r.Message);
}
}
public void BotaoFuncionario()
{
try
{
TabelaFuncionario();
PosXartigo = 1;
PosYartigo = 1;
//Apagar o painel todo
panel2.Controls.Clear();
foreach (DataRow row in BDfuncionarios.Rows)
{
int posicaoX = ((PosXartigo - 1) * Gap_Xartigo) + xInicial + (Largura_BotaoArtigo * (PosXartigo - 1));
if (posicaoX > maximoxArtigo)
{
PosYartigo++; PosXartigo = 1;
}
else
{
PosXartigo = PosXartigo != 1 ? PosXartigo++ : 1;
}
int PontoX = ((PosXartigo - 1) * Gap_Xartigo) + xInicial + (Largura_BotaoArtigo * (PosXartigo - 1));
int PontoY = ((PosYartigo - 1) * Gap_Yartigo) + yInicial + (Altura_BotaoArtigo * (PosYartigo - 1));
Button bt1 = new Button();
bt1.Location = new Point(PontoX, PontoY);
Mo mo = new Mo();
mo.codmo = (int)row["Var1"];
mo.nome_func = (string)row["Var2"];
bt1.Name = "Botao" + NBotoes.ToString();
bt1.Height = Altura_BotaoArtigo;
bt1.Width = Largura_BotaoArtigo;
bt1.BackColor = Color.Tan;
bt1.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Bold);
bt1.ForeColor = Color.Black;
bt1.Text = mo.nome_func;
bt1.Tag = mo;
bt1.FlatStyle = FlatStyle.Popup;
bt1.Click += btFuncionario_click;
panel2.Controls.Add(bt1);
NBotoes++;
PosXartigo++;
}
}
catch (Exception r)
{
MessageBox.Show(r.Message);
}
}
Now the PainelExtension class:
public static class PanelExtension
{
public static void ScrollDown(this Panel p, int pos)
{
//pos passed in should be positive
using (Control c = new Control() { Parent = p, Height = 1, Top = p.ClientSize.Height + pos })
{
p.ScrollControlIntoView(c);
}
}
public static void ScrollUp(this Panel p, int pos)
{
//pos passed in should be negative
using (Control c = new Control() { Parent = p, Height = 1, Top = pos })
{
p.ScrollControlIntoView(c);
}
}
}
The up and down button click:
private void upbt_Click(object sender, EventArgs e)
{
if (i >= 0) i = -1;
panel2.ScrollUp(i=i-30);
}
private void downbt_Click(object sender, EventArgs e)
{
if (i < 0) i = 0;
panel2.ScrollDown(i=i+20);
}
I got it to work like this maybe there were other ways to do it i choose this one.
I have an application that reads XBee frames through the serial port and displays the frame in a richtextbox. It also displays the 2 analog channels (temperature Readings) in a chart and updates it in real time.
I was having issues that the application was reading the serial port faster than the bytes were coming in so I added this line:
while (comPort.BytesToRead < (inLength + 4)) Thread.Sleep(10);
That solved that problem but now I am unable to Close the serial port or quit the application without getting the message: "An unhandled exception of type 'System.InvalidOperationException' occurred in System.dll Additional information: The port is closed."
I am suspicious that it is a multithreading issue, but how do I solve it? I saw on a similar post that using BeginInvoke instead of Invoke should resolve the issue, but I am already using that.
Here is the code:
namespace SerialTest
{
public partial class frmMain : Form
{
delegate void SetTextCallback(string text);
delegate void SetChartCallback(double a, double b);
string inRawFrame = String.Empty;
double temp1 = 0;
double temp2 = 0;
public frmMain()
{
InitializeComponent();
}
private void btnGetSerialPorts_Click(object sender, EventArgs e)
{
if(btnGetSerialPorts.Text == "Open")
{
btnGetSerialPorts.Text = "Close";
comPort.PortName = Convert.ToString(cboPorts.Text);
comPort.BaudRate = Convert.ToInt32(cboBaudRate.Text);
comPort.ReadTimeout = 4000;
comPort.WriteTimeout = 6000;
if (!comPort.IsOpen)
{
try
{
comPort.Open();
cboPorts.Enabled = false;
cboBaudRate.Enabled = false;
}
catch(UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
}
}
else if (btnGetSerialPorts.Text == "Close")
{
btnGetSerialPorts.Text = "Open";
comPort.Close();
cboPorts.Enabled = true;
cboBaudRate.Enabled = true;
}
}
private void Form1_Load(object sender, EventArgs e)
{
string[] arrayComPortsNames = null;
int index = 0;
string comPortName = null;
arrayComPortsNames = SerialPort.GetPortNames();
Array.Sort(arrayComPortsNames);
while (!((arrayComPortsNames[index] == comPortName) || (index == arrayComPortsNames.GetUpperBound(0))))
{
cboPorts.Items.Add(arrayComPortsNames[index]);
index++;
}
comPortName = arrayComPortsNames[0];
cboPorts.Text = comPortName;
cboBaudRate.Items.Add(9600);
cboBaudRate.Items.Add(14400);
cboBaudRate.Items.Add(19200);
cboBaudRate.Items.Add(38400);
cboBaudRate.Items.Add(57600);
cboBaudRate.Items.Add(115200);
cboBaudRate.Items.ToString();
cboBaudRate.Text = cboBaudRate.Items[5].ToString();
}
private void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
byte[] incByte = new byte[3];
int length = 0;
if(comPort.BytesToRead > 3)
{
comPort.Read(incByte, 0, 3);
if (incByte[0] == 0x7E)
{
length = (incByte[1] << 8) + incByte[2];
byte[] buffer = new byte[length+4];
buffer[0] = incByte[0];
buffer[1] = incByte[1];
buffer[2] = incByte[2];
ReadFrame(buffer, length, DateTime.Now);
temp1 = ReadTemp(buffer, 1);
temp2 = ReadTemp(buffer, 2);
DisplayFrame();
UpdateChart();
}
}
}
private void ReadFrame(byte[] inBuffer, int inLength, DateTime time)
{
while (comPort.BytesToRead < (inLength + 4)) Thread.Sleep(10);
comPort.Read(inBuffer, 3, (inBuffer.Length - 3));
inRawFrame = time + " " + BitConverter.ToString(inBuffer).Replace("-", " ");
}
private void DisplayFrame()
{
if (rtbIncomingData.InvokeRequired)
{
rtbIncomingData.BeginInvoke(new SetTextCallback(SetText), new object[] { inRawFrame });
}
else
{
SetText(inRawFrame);
}
}
private void SetText(string text)
{
this.rtbIncomingData.AppendText(text + Environment.NewLine);
}
private double ReadTemp(byte[] data, int channel)
{
if(data[3] == 0x92)
{
if(channel == 1)
{
return ((((data[19] << 8) + data[20]) * 1.2 / 1023) - 0.5) * 100.0;
}
else
{
return ((((data[21] << 8) + data[22]) * 1.2 / 1023) - 0.5) * 100.0;
}
}
else
return 100;
}
private void UpdateChart()
{
if (chart1.InvokeRequired)
chart1.BeginInvoke(new SetChartCallback(SetChart), new object[] { temp1, temp2 });
else
SetChart(temp1, temp2);
}
private void SetChart(double val1, double val2)
{
chart1.ChartAreas["ChartArea1"].AxisX.LabelStyle.Format = "HH:mm:ss";
chart1.ChartAreas["ChartArea1"].AxisX.MajorGrid.LineColor = Color.LightGray;
chart1.ChartAreas["ChartArea1"].AxisY.MajorGrid.LineColor = Color.LightGray;
chart1.ChartAreas["ChartArea1"].AxisX.LabelStyle.Font = new Font("Consolas", 8);
chart1.ChartAreas["ChartArea1"].AxisY.LabelStyle.Font = new Font("Consolas", 8);
chart1.ChartAreas["ChartArea1"].AxisY.Maximum = 30;
chart1.ChartAreas["ChartArea1"].AxisY.Minimum = 10;
chart1.ChartAreas["ChartArea1"].AxisY.Interval = 1;
chart1.Series[0].Name = "Temp 1";
chart1.Series[1].Name = "Temp 2";
chart1.Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
chart1.Series[0].MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Diamond;
chart1.Series[0].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime;
chart1.Series[1].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
chart1.Series[1].MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Diamond;
chart1.Series[1].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime;
chart1.Series[0].Points.AddXY(DateTime.Now, val1);
chart1.Series[1].Points.AddXY(DateTime.Now, val2);
}
}
}
If you close the serial port while ReadFrame() is still waiting for bytes, you'll end up checking BytesToRead on a closed serial port. Maybe try this version instead:
private void ReadFrame(byte[] inBuffer, int inLength, DateTime time)
{
while (comPort.IsOpen)
{
if (comPort.BytestoRead >= inLength + 4)
{
comPort.Read(inBuffer, 3, (inBuffer.Length - 3));
inRawFrame = time + " " + BitConverter.ToString(inBuffer).Replace("-", " ");
return;
}
Thread.Sleep(10);
}
}
It will exit if the serial port closes while waiting for a frame, and only checks BytesToRead if the port is still open.