I have a problem.
I have two loops (one for row, one for column) for creating data in DataTable. I want to check if cell is empty for column named "Name" and if it is empty just don't add this row. And here is a question: How to cancel adding row?
Got some code:
for (int i = 0; i < data.Count(); i++)
{
cell = data.ElementAt(i);
DataRow row;
row = dataTable.NewRow();
foreach (string column in columns)
{
if (row["Name"] == "")
{
row = null;
}
else
{
row[column] = cell;
}
}
if (row != null)
{
dataTable.Rows.Add(row);
}
}
But after next loop is starting it throws NullException: Object reference not set to an instance of an object.
Generally I want to add Rows to DataTable only those where value of cell is not empty at column called "Name" (i mean where is "").
What is the best way or easiest way to do it right?
Change it as:
....
foreach (string column in columns)
{
if (row["Name"] == "")
{
row = null;
break; //--> Add this line
}
else
{
row[column] = cell;
}
}
....
Related
I need to iterate over a DataRow in gridview, to compare the values from the current row and previous row. Appreciate if someone could help on this issue. I'm new
I am currently iterating like this, but i dont know how to continue:
//Check if current row ACTIVITY = LOAD_A and previous row ACTIVITY = LOAD_B is true , then store the
value and do the sum calculation.
foreach (DataRow sda in dt.Rows)
{
if (sda.Field<string>("ACTIVITY") == "LOAD_A")
{
}
}
As devNull already mentioned you can use a variable to hold the value of the previous iteration of the foreach loop.
This could look like this:
DataRow previousDr = null;
foreach (DataRow sda in dt.Rows)
{
if (previousDr != null)
{
if (sda.Field<string>("ACTIVITY") == "LOAD_A" &&
previousDr.Field<string>("ACTIVITY") == "LOAD_B")
{
//Store value und do calculation.
}
}
previousDr = sda;
}
You can use for statement and indexer property of DataRow to accomplish this
DataColumn column = table.Columns["ACTIVITY"];
for (int index = 1; index < table.Rows.Count; ++index)
{
if (table.Rows[index - 1].Field<string>(column) == "LOAD_B" && // previous row
table.Rows[index].Field<string>(column) == "LOAD_A") // current row
{
// do somthing
}
}
Using openxml to read an excel file and write data into a database.
Data from the spreadsheet is stored in a data table and then mapped into a object array. The problem is: if a user deletes a row in the excel file I get the exception 'Specified argument was out of the range of valid values.
Parameter name: index' when reading the file.
To counter this, I have tried checking if the cell value is null, if so then take it as an empty string. However, the error occurs when I reach the 9th column in the last "deleted" row (8 columns out of 10 are taken as an empty string).
IEnumerable<Row> rows = sheetData.Descendants<Row>();
foreach (Row row in rows)
{
DataRow tempRow = dt.NewRow();
for (int i = 0; i < tempRow.ItemArray.Count(); i++)
{
//I get the exception here
Cell c = row.Descendants<Cell>().ElementAt(i);
if (c.CellValue != null)
{
tempRow[i] = GetCellValue(spreadSheetDocument, row.Descendants<Cell>().ElementAt(i));
}
else if (c.CellValue == null )
{
tempRow[i] = "";
}
}
dt.Rows.Add(tempRow);
}
Solved by checking if we are within the range of the available columns in the row. Also checking if the first cell in the row is empty, discarding it if it is.
foreach (Row row in rows)
{
bool isEmpty = false;
DataRow tempRow = dt.NewRow();
for (int i = 0; i < tempRow.ItemArray.Count(); i++)
{
if (i < row.Descendants<Cell>().Count())
{
Cell c = row.Descendants<Cell>().ElementAt(i);
if (c.CellValue != null)
{
tempRow[i] = GetCellValue(spreadSheetDocument, row.Descendants<Cell>().ElementAt(i));
}
else
{
if (i == 0)
{
isEmpty = true;
break;
}
else tempRow[i] = "";
}
}
else
{
tempRow[i] = "";
}
}
if (isEmpty) continue;
dt.Rows.Add(tempRow);
}
I have some text and a datagridview with 5 columns. How can I find this text in the first column and get values from other columns in the same row?
I think the code lines will give you the datagridview row index for the value:
String searchValue = "somestring";
int rowIndex = -1;
foreach(DataGridViewRow row in DataGridView1.Rows)
{
if(row.Cells[1].Value.ToString().Equals(searchValue))
{
rowIndex = row.Index;
break;
}
}
then you can do:
dataGridView1.Rows[rowIndex].Selected = true;
It would be :
List<string> Values = new List<string>();
foreach (DataRow row in YourDataTable.Rows)
{
if (row["firstColumn"].ToString() == yourText)
{
Values.Add(row["firstColumn"].ToString());
Values.Add(row["secondColumn"].ToString());
Values.Add(row["thirdColumn"].ToString());
Values.Add(row["fourthColumn"].ToString());
Values.Add(row["fifthColumn"].ToString());
}
}
I have a method that stores each line in a gridview into the database, then if the save is successful, removes the row; but if it isn't successful (cannot be stored in the db) it does not remove the row. Unfortunately, I can't get the row-removal to work properly.
This is my current code:
public static void SavePAC(PlantAreaCode_CreateView CView)
{
List<int> removeRows = new List<int>();
// For each cell in the DataGrid, stores the information in a string.
for (rows = 0; rows < CView.dataGridView1.Rows.Count; rows++)
{
correctSave = false;
if (CView.dataGridView1.Rows[rows].Cells[col].Value != null)
{
// Creates a model, then populates each field from the cells in the table.
PModel = new PlantAreaCode_Model();
PModel.AreaCode = Convert.ToString(CView.dataGridView1.Rows[rows].Cells[0].Value);
PModel.AreaName = Convert.ToString(CView.dataGridView1.Rows[rows].Cells[1].Value);
PModel.Comments = Convert.ToString(CView.dataGridView1.Rows[rows].Cells[2].Value);
// Passes the model into the Database.
Database_Facade.Operation_Switch(OPWRITE);
}
if (correctSave == true) // correctSave is set in the database insert method.
{
removeRows.Add(rows);
}
}
foreach (int i in removeRows)
{
CView.dataGridView1.Rows.RemoveAt(0); // Deletes all bar the last row, including any rows that cause errors
}
}
I have also tried:
foreach (int i in removeRows)
{
CView.dataGridView1.Rows.RemoveAt(i);
}
But that crashes at halfway, because the Rows index keeps changing each time a row is removed.
How can I achieve this? How can I remove a row if the save is successful, but keep it if there is an error?
May this help:
1] Make sure correctSave is being modified correctly.
2] Revert the loop flow, Looping backward allow to remove the row processed by the loop without affecting the index of the next row to process.
for (rows = CView.dgvCreate.Rows.Count - 1; rows >= 0 ; rows--)
3] Use CView.dataGridView1.Rows.RemoveAt(rows);
Try to populate collection of rows for removing with DataGridViewRow not with index. This works for me.
public void SavePAC(PlantAreaCode_CreateView CView)
{
List<DataGridViewRow> removeRows = new List<DataGridViewRow>();
foreach (DataGridViewRow row in CView.dataGridView1.Rows)
{
correctSave = false;
if (row.Cells[col].Value != null)
{
// Creates a model, then populates each field from the cells in the table.
PModel = new PlantAreaCode_Model();
PModel.AreaCode = Convert.ToString(row.Cells[0].Value);
PModel.AreaName = Convert.ToString(row.Cells[1].Value);
PModel.Comments = Convert.ToString(row.Cells[2].Value);
// Passes the model into the Database.
Database_Facade.Operation_Switch(OPWRITE);
}
if (correctSave == true) // correctSave is set in the database insert method.
{
removeRows.Add(row);
}
}
foreach (DataGridViewRow rowToRemove in removeRows)
{
CView.dataGridView1.Rows.Remove(rowToRemove);
}
}
You have to sort removeRows in descending order.
List<int> removeRowsDesc = removeRows.OrderByDescending(i => i);
Then use the foreach loop
foreach (int i in removeRowsDesc)
{
CView.dataGridView1.Rows.RemoveAt(i);
}
This way the reindexing wont affect the deletion.
I have a simple function in my program that selects the current cell, then it (FillsDown) copies the current cell into ALL the cells below it.
However my simple function places the value in the Row at the bottom which is the new row and I do not want the value to be populated here.
Heres the current code. (Where COLINDEX is just the column im referring to in my grid)
string replacestring = row.Cells[COLINDEX].Value.ToString();
foreach (DataGridViewRow row in dataGrid1.Rows)
{
if (row.Index > startrow)
{
row.Cells[COLINDEX].Value = replacestring;
}
}
Is there a simeple method/property I can check against so I dont accidently populate the last row ?
My example below uses a fake property (.Exist)
foreach (DataGridViewRow row in dataGrid1.Rows)
{
if ((row.Index > startrow) && row.Exist)
{
row.Cells[COLINDEX].Value = replacestring;
}
}
DataGridViewRow has a property called IsNewRow
And try to walk the Rows collection using the index
for(int x = startRow + 1; x < dataGrid1.Rows.Count; x++)
{
DataGridViewRow row = dataGrid1.Rows[x];
if (row.IsNewRow == false)
{
row.Cells[COLINDEX].Value = replacestring;
}
}