Get Cell Value from a DataTable in C# - c#

Here is a DataTable dt, which has lots of data.
I want to get the specific Cell Value from the DataTable, say Cell[i,j]. Where,
i -> Rows and j -> Columns. I will iterate i,j's value with two forloops.
But I can't figure out how I can call a cell by its index.
Here's the code:
for (i = 0; i <= dt.Rows.Count - 1; i++)
{
for (j = 0; j <= dt.Columns.Count - 1; j++)
{
var cell = dt.Rows[i][j];
xlWorkSheet.Cells[i + 1, j + 1] = cell;
}
}

The DataRow has also an indexer:
Object cellValue = dt.Rows[i][j];
But i would prefer the strongly typed Field extension method which also supports nullable types:
int number = dt.Rows[i].Field<int>(j);
or even more readable and less error-prone with the name of the column:
double otherNumber = dt.Rows[i].Field<double>("DoubleColumn");

You probably need to reference it from the Rowsrather than as a cell:
var cellValue = dt.Rows[i][j];

You can iterate DataTable like this:
private void button1_Click(object sender, EventArgs e)
{
for(int i = 0; i< dt.Rows.Count;i++)
for (int j = 0; j <dt.Columns.Count ; j++)
{
object o = dt.Rows[i].ItemArray[j];
//if you want to get the string
//string s = o = dt.Rows[i].ItemArray[j].ToString();
}
}
Depending on the type of the data in the DataTable cell, you can cast the object to whatever you want.

To get cell column name as well as cell value :
List<JObject> dataList = new List<JObject>();
for (int i = 0; i < dataTable.Rows.Count; i++)
{
JObject eachRowObj = new JObject();
for (int j = 0; j < dataTable.Columns.Count; j++)
{
string key = Convert.ToString(dataTable.Columns[j]);
string value = Convert.ToString(dataTable.Rows[i].ItemArray[j]);
eachRowObj.Add(key, value);
}
dataList.Add(eachRowObj);
}

You can call the indexer directly on the datatable variable as well:
var cellValue = dt[i].ColumnName

If I have understood your question correctly you want to display one particular cell of your populated datatable? This what I used to display the given cell in my DataGrid.
var s = dataGridView2.Rows[i].Cells[j].Value;
txt_Country.Text = s.ToString();
Hope this helps

Related

Winforms: Error in iterating excel rows of same column

Apologies for somewhat confusing explanation. I am using Microsoft.Office.Interop.Excel. Purpose for code below is to
1) Iterate all rows in Column B of excel sheet named oSheet1
2) Iterate all rows in Column 0 of datagridview (DTG)
3) If data from Column B and Column 0 matches, then export data in Column 1 of DTG into Column C of excel.
Hence, the data in column 1 of DTG is in reference with data in Column 0 of DTG. And data in Column C of excel will eventually be in reference with Column B of excel. I've inserted some images for easy understanding
I've tried multiple codes for hours and kept getting error. Below are my codes along with errors experienced:
Error: Cannot perform in runtime binding on null reference
for (int i = 1; i <= oSheet1.Columns.Count; i++)
{
string cellvalue = oSheet1.Cells[i, 2].Value.ToString(); //error here
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if ((string)row.Cells[0].Value == cellvalue)
{
for (int j = 0; j < dataGridView1.Rows.Count; j++)
{
oSheet1.Cells[i, 3] = dataGridView1.Rows[j].Cells[1].Value.ToString();
}
}
}
Error: Exception from H result
for (int i = 1; i <= oSheet1.Columns.Count; i++)
{
object cellvalue = oSheet1.get_Range("B:B" + Convert.ToString(i));
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[0].Value == cellvalue)
{
for (int j = 0; j < dataGridView1.Rows.Count; j++)
{
oSheet1.Cells[i, 3] = dataGridView1.Rows[j].Cells[1].Value.ToString();
}
}
}
}
I would appreciate any help. Thank you!!
Try UsedRange.
var range = oSheet1.UsedRange;
int startingRowIndex = range.Row + 1; //to skip the header
for (int rowIndex = startingRowIndex; rowIndex < range.Row + range.Rows.Count; rowIndex++)
{
string cellvalue = range.Cells[rowIndex, 2].Value?.ToString();
...
}
Also, you should perform a null check against the Value property just in case the cell is empty, or uses a null-conditional operator as shown in the code above.

Add row to specific column by header name/text

I have a column named "HeaderText_Name" and in this column, I want to add a row that has the text "Row" under that column.
I attempted to write some pseudo-code for it
databaseGridView.Rows["HeaderText_Name"].Add("Row");
If I do
databaseGridView.Rows.Add("Row");
It adds it to the first column no matter what. I also can't do something like
databaseGridView.Rows.Add("","","Row");
Then it adds blanks to the first two columns and I also don't know how which index the column is. So I would be more helpful if it was by Name or text.
Here is the actual code I have so far..
for (int i = 0; i < completeInfoMatches.Count; i++) {
databaseGridView.Rows.Add();
databaseGridView.Rows[0].Cells[e.Node.Text].Value = completeInfoMatches[i].Groups[1].ToString();
}
Now, completeInfoMatches has more than 1 match because it's regex. How can I change the 0 to make it work?
UPDATE
int currentRowIndex = 0;
databaseGridView.Columns.Add(e.Node.Text.Replace(" ", string.Empty), e.Node.Text);
for (int i = 0; i < completeInfoMatches.Count; i++) {
databaseGridView.Rows.Add();
databaseGridView.Rows[currentRowIndex].Cells[e.Node.Text.Replace(" ", string.Empty)].Value = completeInfoMatches[i].Groups[1].ToString();
currentRowIndex = currentRowIndex + 1;
}
I'm getting a lot of extra blank rows because of Row.Add
Try something like this:
foreach(int i = 0; i < completeInfoMatches.Count; i++){
var index = databaseGridView.Rows.Add();
databaseGridView.Rows[index].Cells[e.Node.Text].Value = completeInfoMatches[i].Groups[1].ToString();
}
With the help of #Forlani ...
int currentRowIndex = 0;
int actualRowIndex = databaseGridView.Rows.Count;
for (int i = 0; i < completeInfoMatches.Count; i++) {
var index = 0;
if (actualRowIndex < completeInfoMatches.Count) {
index = databaseGridView.Rows.Add();
}
databaseGridView.Rows[currentRowIndex].Cells[e.Node.Text.Replace(" ", string.Empty)].Value = completeInfoMatches[i].Groups[1].ToString();
currentRowIndex = currentRowIndex + 1;
}

iteration through datagrid rows for export to excel (again)

I am trying to export dataGrid rows to an Excel sheet.
Since I am switching from a WinForms(dataGridView) to WPF
(dataGrid) and basically I have no clue about WPF so far
I need your help.
Maybe somebody can either tell me how to change my loop
or what I have to do instead to get the rows filled into
the cells of the Excel sheet.
I have read all articles on SO covering this problem but
don't seem to find a topic suiting my issue.
This is what I did for the filling of the column names, which
works perfectly:
for (int i = 1; i < dataGrid.Columns.Count + 1; i++)
{
Excel.Range BackgroundColor;
BackgroundColor = xlWorkSheet.get_Range("a9", "j9");
BackgroundColor.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.RoyalBlue);
AxlEx.Cells[9, i] = dataGrid.Columns[i - 1].Header;
}
when it comes down to the filling of the cells with rows I have tried numerous attemps to get it working
for (int i = 0; i < dataGrid.Items.Count; i++)
{
DataRowView aux = (DataRowView)dataGrid.Items[i];
for (int j = 0; j < aux.Row.ItemArray.Length; j++)
{
//Console.WriteLine(string.Format("{0}-{1}", j, aux.Row.ItemArray[j]));
AxlEx.Cells[i + 10, j + 1] = aux.Row.ItemArray[j];
}
}
throws me an exception of System.InvalidCast exception for a type mismatch
which is obvious... but I don't know how to convert, here also the fitting
Topics on SO didn't have an example which i could understand to change my code.
Before I had this:
for (int i = 0; i < dataGrid.Items.Count; i++)
{
for (int j = 0; j < dataGrid.Columns.Count; j++)
{
AxlEx.Cells[i + 10, j + 1] = dataRow.Row.ItemArray[j].ToString();
}
}
which then works for 1 row if i refer to
DataRowView dataRow = (DataRowView)dataGrid.SelectedItem;
How can I get this to work?
I do not know whether it is necessary to debug your code. However, I would like to show my work code to export data from DataGrid to MS Excel:
It is better to transfer this work from UI Thread to a ThreadPool:
using Excel = Microsoft.Office.Interop.Excel;//add this library
Task.Run(() => {
// load excel, and create a new workbook
Excel.Application excelApp = new Excel.Application();
excelApp.Workbooks.Add();
// single worksheet
Excel._Worksheet workSheet = excelApp.ActiveSheet;
// column headings
for (int i = 0; i < YourDataTable.Columns.Count; i++)
{
workSheet.Cells[1, (i + 1)] = YourDataTable.Columns[i].ColumnName;
}
// rows
for (int i = 0; i < YourDataTable.Rows.Count; i++)
{
// to do: format datetime values before printing
for (int j = 0; j < YourDataTable.Columns.Count; j++)
{
workSheet.Cells[(i + 2), (j + 1)] = YourDataTable.Rows[i][j];
}
}
excelApp.Visible = true;
});
I found the problem....
for (int i = 0; i < dataGrid.Items.Count-1; i++)
{
DataRowView aux = (DataRowView)dataGrid.Items[i];
for (int j = 0; j < aux.Row.ItemArray.Length; j++)
{
//Console.WriteLine(string.Format("{0}-{1}", j, aux.Row.ItemArray[j]));
AxlEx.Cells[i + 10, j + 1] = aux.Row.ItemArray[j];
}
}
i had to substract (dataGrid.Items.Count-1) because there was an additional blank line in the dataGrid which seemed to cause the problem.
Pobably due to a NULL field return value ???
the datagrid

C# multi-dimension array sort based on user input

How can I sort a 2D array in C#
I have looked at other answers to this question but they don't do exactly what I need.
The array is variable height * 5 across
The array holds strings
I need the array sorted based on either column, for example sort in alphabetical the third column, however all other columns must be updated.
Does anyone know of a quick and easy solution?
My code is a mess, here is a shortened version:
string[,] tmp = new string[2, 3];//this is filled with strings
string y = Console.ReadLine();
int x = Convert.ToInt32(y);
// sort tmp based on x column
How do I sort a two-dimensional array in C#? contains a possible solution to this by reading your data into a datatable and then using the object's methods to sort:
// assumes stringdata[row, col] is your 2D string array
DataTable dt = new DataTable();
// assumes first row contains column names:
for (int col = 0; col < stringdata.GetLength(1); col++)
{
dt.Columns.Add(stringdata[0, col]);
}
// load data from string array to data table:
for (rowindex = 1; rowindex < stringdata.GetLength(0); rowindex++)
{
DataRow row = dt.NewRow();
for (int col = 0; col < stringdata.GetLength(1); col++)
{
row[col] = stringdata[rowindex, col];
}
dt.Rows.Add(row);
}
// sort by third column:
DataRow[] sortedrows = dt.Select("", "3");
// sort by column name, descending:
sortedrows = dt.Select("", "COLUMN3 DESC");
So first we'll want to convert the multi-dimensional array into a sequence of single-dimensional arrays representing the rows, so that each row can be manipulated as a unit:
public static IEnumerable<T[]> GetRows<T>(T[,] array)
{
for (int i = 0; i < array.GetLength(0); i++)
{
T[] row = new T[array.GetLength(1)];
for (int j = 0; j < row.Length; j++)
{
row[j] = array[i, j];
}
yield return row;
}
}
Then we'll also need a method that does the reverse to get a multi-dimensional array back when we're done:
public static T[,] ToMultiDimensionalArray<T>(T[][] rows)
{
T[,] output = new T[rows.Length, rows[0].Length];
for (int i = 0; i < rows.Length; i++)
for (int j = 0; j < rows[0].Length; j++)
{
output[i, j] = rows[i][j];
}
return output;
}
Now we just need to sort a sequence of arrays, and Linq makes this quite easy:
tmp = ToMultiDimensionalArray(GetRows(tmp)
.OrderBy(row => row[2]).ToArray());

How to calculate average for each column in radgridview into a last row after filtering?

I would like to know how to find average of column based on row filters?
private void monthlyGridView_Click(object sender, EventArgs e)
{
List<double> everyQuestion = new List<double>();
for (int i = 5; i < monthlyGridView.Columns.Count; i++)
{
eachQuestion.Clear();
for (int j = 0; j < monthlyGridView.Rows.Count - 2; j++)
{
//mReport is DataTable which return values
string value = mReport.Rows[j][i].ToString();
eachQuestion.Add(double.Parse(value));
}
string columnAverage = String.Format("{0:0.00}", eachQuestion.Average());
monthlyGridView.Rows[monthlyGridView.Rows.Count - 1].Cells[i].Value = columnAverage;
}
}
this code only gives me average not filtered based average?
You can use the build in summary row for this functionality. More information is avaialble here

Categories