C# Insert value into DataGridView - c#

I have a problem with a DataGridView, as you can see from down here, when I enter a value (LOL) within the cells is actually only it appears in the last line
Code:
private void CaricaNoteLavaggio()
{
using (DatabaseConnection db = new DatabaseConnection())
{
const string query = "" // My query
using (MySqlDataReader reader = db.ExecuteReader(query))
{
if (reader.HasRows)
{
while (reader.Read())
{
DataGridViewRow row = new DataGridViewRow();
dataGridNoteLavaggio.Rows.Add(row);
foreach (DataGridViewCell cell in dataGridNoteLavaggio.Rows[dataGridNoteLavaggio.NewRowIndex].Cells)
{
cell.Value = "LOL";
}
}
}
}
}
}
The columns of the DataGridView I create dynamically using this piece of code (if that can be useful)
DataGridViewTextBoxColumn txtId = new DataGridViewTextBoxColumn();
txtId.HeaderText = "ID";
txtId.Name = "id";
txtId.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
txtId.Visible = false;
dataGridNoteLavaggio.Columns.Add(txtId);
// Function that returns the list of languages (EN, FR, ES, etc. ...)
List<string> lingue = DatabaseFunctions.GetLingue();
foreach (var lingua in lingue)
{
DataGridViewTextBoxColumn txtDesc = new DataGridViewTextBoxColumn();
txtDesc.HeaderText = lingua;
txtDesc.Name = lingua;
txtDesc.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
dataGridNoteLavaggio.Columns.Add(txtDesc);
}
I tried it with debugging to follow the indices in the cycle are correct but despite the result is wrong.

Because you insert data in the new row and new row always added to last of all.
for change data from first row after adding row you must change this code:
dataGridNoteLavaggio.Rows[dataGridNoteLavaggio.NewRowIndex].Cells
to
dataGridNoteLavaggio.Rows[index].Cells
and index set from Rows.Add() method. and your codes should like this:
private void CaricaNoteLavaggio()
{
using (DatabaseConnection db = new DatabaseConnection())
{
const string query = "" // My query
using (MySqlDataReader reader = db.ExecuteReader(query))
{
if (reader.HasRows)
{
while (reader.Read())
{
DataGridViewRow row = new DataGridViewRow();
var index = dataGridNoteLavaggio.Rows.Add(row);
foreach (DataGridViewCell cell in dataGridNoteLavaggio.Rows[index].Cells)
{
cell.Value = "LOL";
}
}
}
}
}
}

Related

I'm trying to pass DataTable to Class and I get this message: Input string was not in a correct format

I am taking an excel file to read the fields and pass it to a class, to be able to enter the DB, when I pass dt.AsEnumerable, it is giving me an error in the "Linea" field. This cell sometimes comes with the $ sign. I think that is what is generating the error, so i am trying to replace the character and then convert it to int, since it is an amount field.
using (var streamExcel = System.IO.File.Create(combineFilePath))
{
await file.CopyToAsync(streamExcel);
}
using (var excelWorkbook = new XLWorkbook(combineFilePath))
{
IXLWorksheet workSheet = excelWorkbook.Worksheet(2);
workSheet.Clear(XLClearOptions.AllFormats);
DataTable dt = new DataTable();
bool firstRow = true;
foreach (IXLRow row in workSheet.Rows())
{
//for row number check
if (firstRow)
{
foreach (IXLCell cell in row.Cells())
{
dt.Columns.Add(cell.Value.ToString());
}
firstRow = false;
}
else
{
//Add rows to DataTable.
dt.Rows.Add();
int i = 0;
foreach (IXLCell cell in row.Cells(1, 50))
{
if (cell.Address.ColumnNumber == 11)
{
workSheet.Cell(11, 11).Style.NumberFormat.Format = "#,##0";
cell.SetDataType(XLDataType.Number);
}
dt.Rows[dt.Rows.Count - 1][i] = cell.CachedValue.ToString();
i++;
}
}
}
try
{
var companys = dt.AsEnumerable().Select(row => new Company
{
Name = row.Field<string>("Nombre"),
Rut = row.Field<string>("Rut"),
Address = row.Field<string>("Dirección"),
AddressNumber = row.Field<string>(#"Nº"),
Location = row.Field<string>("Comuna"),
Region = row.Field<string>("Región"),
Giro = row.Field<string>("Giro Cliente"),
Linea = Convert.ToInt32(row.Field<string>("Monto línea Aprobada").Trim().TrimEnd().Replace(#"$", "")),
Observations = row.Field<string>("Observaciones Comité"),
}).ToList();
UserId = _companyService.AddList(companys);
}
catch (Exception e)
{
}
To visualize where it's failing, you could do something like this:
try{
var companysB = dt.AsEnumerable().Select(row => new
{
Name = row.Field<string>("Nombre"),
LineaRaw = row.Field<string>("Monto línea Aprobada"),
LineaProcessed = row.Field<string>("Monto línea Aprobada").Trim().TrimEnd().Replace(#"$", ""),
})
.ToList();
}
Put a breakpoint on 'companysB' and inspect after it's filled. One or more of the LineaRaw / LineaProcessed will not be a number.
The error was when the "Monto línea Aprobada" cell had a blank value, I did this:
var n = 0;
string cellEmty = "";
foreach (DataRow rowEmpty in dt.Rows)
{
cellEmty = rowEmpty["Monto línea Aprobada"].ToString();
if (string.IsNullOrEmpty(cellEmty))
{
cellEmty = "0";
dt.Rows[n].SetField("Monto línea Aprobada", cellEmty);
}
n++;
}

C# Reading CSV to DataTable and Invoke Rows/Columns

i am currently working on a small Project and i got stuck with a Problem i currently can not manage to solve...
I have multiple ".CSV" Files i want to read, they all have the same Data just with different Values.
Header1;Value1;Info1
Header2;Value2;Info2
Header3;Value3;Info3
While reading the first File i Need to Create the Headers. The Problem is they are not splited in Columns but in rows (as you can see above Header1-Header3).
Then it Needs to read the Value 1 - Value 3 (they are listed in the 2nd Column) and on top of that i Need to create another Header -> Header4 with the data of "Info2" which is always placed in Column 3 and Row 2 (the other values of Column 3 i can ignore).
So the Outcome after the first File should look like this:
Header1;Header2;Header3;Header4;
Value1;Value2;Value3;Info2;
And after multiple files it sohuld be like this:
Header1;Header2;Header3;Header4;
Value1;Value2;Value3;Value4;
Value1b;Value2b;Value3b;Value4b;
Value1c;Value2c;Value3c;Value4c;
I tried it with OleDB but i get the Error "missing ISAM" which i cant mange to fix. The Code i Used is the following:
public DataTable ReadCsv(string fileName)
{
DataTable dt = new DataTable("Data");
/* using (OleDbConnection cn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"" +
Path.GetDirectoryName(fileName) + "\";Extendet Properties ='text;HDR=yes;FMT=Delimited(,)';"))
*/
using (OleDbConnection cn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
Path.GetDirectoryName(fileName) + ";Extendet Properties ='text;HDR=yes;FMT=Delimited(,)';"))
{
using(OleDbCommand cmd = new OleDbCommand(string.Format("select *from [{0}]", new FileInfo(fileName).Name,cn)))
{
cn.Open();
using(OleDbDataAdapter adapter = new OleDbDataAdapter(cmd))
{
adapter.Fill(dt);
}
}
}
return dt;
}
Another attempt i did was using StreamReader. But the Headers are in the wrong place and i dont know how to Change this + do this for every file. the Code i tried is the following:
public static DataTable ReadCsvFilee(string path)
{
DataTable oDataTable = new DataTable();
var fileNames = Directory.GetFiles(path);
foreach (var fileName in fileNames)
{
//initialising a StreamReader type variable and will pass the file location
StreamReader oStreamReader = new StreamReader(fileName);
// CONTROLS WHETHER WE SKIP A ROW OR NOT
int RowCount = 0;
// CONTROLS WHETHER WE CREATE COLUMNS OR NOT
bool hasColumns = false;
string[] ColumnNames = null;
string[] oStreamDataValues = null;
//using while loop read the stream data till end
while (!oStreamReader.EndOfStream)
{
String oStreamRowData = oStreamReader.ReadLine().Trim();
if (oStreamRowData.Length > 0)
{
oStreamDataValues = oStreamRowData.Split(';');
//Bcoz the first row contains column names, we will poluate
//the column name by
//reading the first row and RowCount-0 will be true only once
// CHANGE TO CHECK FOR COLUMNS CREATED
if (!hasColumns)
{
ColumnNames = oStreamRowData.Split(';');
//using foreach looping through all the column names
foreach (string csvcolumn in ColumnNames)
{
DataColumn oDataColumn = new DataColumn(csvcolumn.ToUpper(), typeof(string));
//setting the default value of empty.string to newly created column
oDataColumn.DefaultValue = string.Empty;
//adding the newly created column to the table
oDataTable.Columns.Add(oDataColumn);
}
// SET COLUMNS CREATED
hasColumns = true;
// SET RowCount TO 0 SO WE KNOW TO SKIP COLUMNS LINE
RowCount = 0;
}
else
{
// IF RowCount IS 0 THEN SKIP COLUMN LINE
if (RowCount++ == 0) continue;
//creates a new DataRow with the same schema as of the oDataTable
DataRow oDataRow = oDataTable.NewRow();
//using foreach looping through all the column names
for (int i = 0; i < ColumnNames.Length; i++)
{
oDataRow[ColumnNames[i]] = oStreamDataValues[i] == null ? string.Empty : oStreamDataValues[i].ToString();
}
//adding the newly created row with data to the oDataTable
oDataTable.Rows.Add(oDataRow);
}
}
}
//close the oStreamReader object
oStreamReader.Close();
//release all the resources used by the oStreamReader object
oStreamReader.Dispose();
}
return oDataTable;
}
I am thankful for everyone who is willing to help. And Thanks for reading this far!
Sincerely yours
If I understood you right, there is a strict parsing there like this:
string OpenAndParse(string filename, bool firstFile=false)
{
var lines = File.ReadAllLines(filename);
var parsed = lines.Select(l => l.Split(';')).ToArray();
var header = $"{parsed[0][0]};{parsed[1][0]};{parsed[2][0]};{parsed[1][0]}\n";
var data = $"{parsed[0][1]};{parsed[1][1]};{parsed[2][1]};{parsed[1][2]}\n";
return firstFile
? $"{header}{data}"
: $"{data}";
}
Where it would return - if first file:
Header1;Header2;Header3;Header2
Value1;Value2;Value3;Value4
if not first file:
Value1;Value2;Value3;Value4
If I am correct, rest is about running this against a list file of files and joining the results in an output file.
EDIT: Against a directory:
void ProcessFiles(string folderName, string outputFileName)
{
bool firstFile = true;
foreach (var f in Directory.GetFiles(folderName))
{
File.AppendAllText(outputFileName, OpenAndParse(f, firstFile));
firstFile = false;
}
}
Note: I missed you want a DataTable and not an output file. Then you could simply create a list and put the results into that list making the list the datasource for your datatable (then why would you use semicolons in there? Probably all you need is to simply attach the array values to a list).
(Adding as another answer just to make it uncluttered)
void ProcessMyFiles(string folderName)
{
List<MyData> d = new List<MyData>();
var files = Directory.GetFiles(folderName);
foreach (var file in files)
{
OpenAndParse(file, d);
}
string[] headers = GetHeaders(files[0]);
DataGridView dgv = new DataGridView {Dock=DockStyle.Fill};
dgv.DataSource = d;
dgv.ColumnAdded += (sender, e) => {e.Column.HeaderText = headers[e.Column.Index];};
Form f = new Form();
f.Controls.Add(dgv);
f.Show();
}
string[] GetHeaders(string filename)
{
var lines = File.ReadAllLines(filename);
var parsed = lines.Select(l => l.Split(';')).ToArray();
return new string[] { parsed[0][0], parsed[1][0], parsed[2][0], parsed[1][0] };
}
void OpenAndParse(string filename, List<MyData> d)
{
var lines = File.ReadAllLines(filename);
var parsed = lines.Select(l => l.Split(';')).ToArray();
var data = new MyData
{
Col1 = parsed[0][1],
Col2 = parsed[1][1],
Col3 = parsed[2][1],
Col4 = parsed[1][2]
};
d.Add(data);
}
public class MyData
{
public string Col1 { get; set; }
public string Col2 { get; set; }
public string Col3 { get; set; }
public string Col4 { get; set; }
}
I don't know if this is the best way to do this. But what i would have done in your case, is to rewrite the CSV's the conventionnal way while reading all the files, then create a stream containing the new CSV created.
It would look like something like this :
var csv = new StringBuilder();
csv.AppendLine("Header1;Header2;Header3;Header4");
foreach (var item in file)
{
var newLine = string.Format("{0},{1},{2},{3}", item.value1, item.value2, item.value3, item.value4);
csv.AppendLine(newLine);
}
//Create Stream
MemoryStream stream = new MemoryStream();
StreamReader reader = new StreamReader(stream);
//Fill your data table here with your values
Hope this will help.

Select Values from checked DataGridView Items

I have my code as follows:
DataGridViewCheckBoxColumn chk = new DataGridViewCheckBoxColumn();
actGrid.Columns.Add(chk);
chk.HeaderText = "Select";
chk.Name = "select";
chk.ReadOnly = false;
DataGridViewTextBoxColumn mc_no = new DataGridViewTextBoxColumn();
actGrid.Columns.Add(mc_no);
mc_no.HeaderText = "M/C Number";
mc_no.Name = "mc_no";
mc_no.Width = 200;
mc_no.ReadOnly = true;
DataGridViewTextBoxColumn act_name = new DataGridViewTextBoxColumn();
actGrid.Columns.Add(act_name);
act_name.HeaderText = "Name";
act_name.Name = "member";
act_name.Width = 262;
act_name.ReadOnly = true;
while (DR.Read())
{
actGrid.Rows.Add(true, DR.GetInt32(0).ToString(), DR.GetString(2) + " " + DR.GetString(1));
}
Which produces the following output:
And now I want to perform some actions based on which accounts were selected (by toggling the trailing checkboxes), especially M/C Number.
// iterate over DataGridView rows
foreach (DataGridViewRow row in actGrid.Rows)
{
// check, if row is selected by checkbox
if (Equals(row.Cells["select"].Value, true))
{
// get values for selected row
var mc_no_Value = (string)row.Cells["mc_no"].Value;
var member_Value = (string)row.Cells["member"].Value;
// do smth with values here
}
}

how to resize columns in datagridview in C#

I am using following method to fill datagridview from SQL
public bool _MFillGridView(string pQuery, ref DataGridView _pDgv)
{
using (DataTable dt = new DataTable())
{
using (SqlConnection con = new SqlConnection(_CObjectsofClasses._obj_CConnectionString._MGetConnectionString()))
{
using (SqlCommand cmd = new SqlCommand(pQuery, con))
{
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
_pDgv.DataSource = dt;
_pDgv.Cursor = System.Windows.Forms.Cursors.Default;
}
}
}
foreach (DataColumn DC in dt.Columns)
{
_pDgv.Columns[DC.ColumnName].SortMode = DataGridViewColumnSortMode.NotSortable;
if (DC.DataType == typeof(DateTime))
{
_pDgv.Columns[DC.ColumnName].DefaultCellStyle = new DataGridViewCellStyle { Format = _pDateFormat };
_pDgv.Columns[DC.ColumnName].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}
else if (DC.DataType == typeof(decimal))
{
_pDgv.Columns[DC.ColumnName].DefaultCellStyle = new DataGridViewCellStyle { Format = _CObjectsofClasses._obj_CNumbricFunction._MFormatNo("0") };
}
}
}
return true;
}
and here I am using like this;
_MFillGridView("My SQL query here", ref MydatagridviewToFill);
above code works perfectly but I am facing column width problems. I want to to pass column index and DataGridViewAutoSizeColumnMode and column width to resize columns like
coloumn[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
coloumn[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
coloumn[2].Width = 200;
and all other columns which are not provided should be set to AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet;
please suggest me to what I change in code.
Based on my understanding of your question above, I believe this is what you want?
private void ResizeColumns(DataGridView gridview, int column, int width, DataGridViewAutoSizeColumnMode mode)
{
for (int i = 0; i < gridview.ColumnCount; i++)
{
if (i.Equals(column))
{
gridview.Columns[i].AutoSizeMode = mode;
gridview.Columns[i].Width = width;
}
else
{
gridview.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
}
}
}
Update
Ok still not sure I understand what you are after but I think this may point you in the right direction
public bool _MFillGridView(string pQuery, ref DataGridView _pDgv, int columnIndex, int width)
{
using (var dt = new DataTable())
{
// ... Code to retrieve data from Database ...
for (var i = 0; i < dt.Columns.Count; i++)
{
var column = dt.Columns[i];
if (column.DataType == typeof (DateTime))
_pDgv.Columns[column.ColumnName].DefaultCellStyle = new DataGridViewCellStyle {Format = _pDateFormat};
else if (column.DataType == typeof (decimal))
_pDgv.Columns[column.ColumnName].DefaultCellStyle = new DataGridViewCellStyle {Format = _CObjectsofClasses._obj_CNumbricFunction._MFormatNo("0")};
// Do your DataGridView formatting here
if (_pDgv.Columns[column.ColumnName].Index.Equals(columnIndex)) // Check your Column index on the control
{
_pDgv.Columns[column.ColumnName].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}
else
{
_pDgv.Columns[column.ColumnName].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
_pDgv.Columns[column.ColumnName].Width = width;
}
}
}
return true;
}
I solved my problem using #Mo Patel i just change int columnIndex, int width to List columnIndex, List width

Script to parse CSV values

I'm using this code to parse the values and store them in List. The first row has names which are getting stored fine. But when storing values, only the second row is bring saved. I'm not sure what edit I need to make so that it parses all other rows as well.
Please see image and code below.
List<string> names = new List<string>(); // List to store Key names
List<string> values = new List<string>(); // List to store key values
using (StreamReader stream = new StreamReader(filePath))
{
names = stream.ReadLine().Split(',').ToList(); // Seperate key names and store them in a List
values = stream.ReadLine().Split(',').ToList(); // Seperate key values and store them in a list
}
See if something like this works better:
// List to store Key names
List<string> names = new List<string>();
// List to store key values
List<List<string>> values = new List<string>();
using (StreamReader stream = new StreamReader(filePath))
{
if(!stream.EndOfStream)
{
// Seperate key names and store them in a List
names = stream.ReadLine().Split(',').ToList();
}
while(!stream.EndOfStream)
{
// Seperate key values and store them in a list
values.Add(stream.ReadLine().Split(',').ToList());
}
}
This changes your values list to be a list of a list of strings so that each row will a list of string
While this probably isn't the best way to parse a .csv, if your data is consistent and the file format is strongly consistent you can probably get away with doing it like this. As soon as you try this with odd values, quoted strings, strings with commas, etc., you'll need a different approach.
i have written the code for grid view make changes it to a list.I think it will help
protected void Button1_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
{
string s = FileUpload1.FileName.Trim();
if (s.EndsWith(".csv"))
{
FileUpload1.PostedFile.SaveAs(Server.MapPath("~/data/" + s));
string[] readText = File.ReadAllLines(Server.MapPath("~/data/" + s));
DataSet ds = new DataSet();
DataTable dt = new DataTable();
// Array.Sort(readText);
for (int i = 0; i < readText.Length; i++)
{
if (i == 0)
{
string str = readText[0];
string[] header = str.Split(',');
dt.TableName = "sal";
foreach (string k in header)
{
dt.Columns.Add(k);
}
}
else
{
DataRow dr = dt.NewRow();
string str1 = readText[i];
if (readText[i] == ",,,,")
{
break;
}
string[] rows = str1.Split(',');
if (dt.Columns.Count == rows.Length)
{
for (int z = 0; z < rows.Length; z++)
{
if (rows[z] == "")
{
rows[z] = null;
}
dr[z] = rows[z];
}
dt.Rows.Add(dr);
}
else
{
Label1.Text = "please select valid format";
}
}
}
//Iterate through the columns of the datatable to set the data bound field dynamically.
ds.Merge(dt);
Session["tasktable"] = dt;
foreach (DataColumn col in dt.Columns)
{
BoundField bf = new BoundField();
bf.DataField = col.ToString();
bf.HeaderText = col.ColumnName;
if (col.ToString() == "Task")
{
bf.SortExpression = col.ToString();
}
GridView1.Columns.Add(bf);
}
GridView1.DataSource = ds;
GridView1.DataBind();
}
else
{
Label1.Text = "please select a only csv format";
}
}
else
{
Label1.Text = "please select a file";
}
}

Categories

Resources