How to get the name of the element in an array - c#

I have a data table as part of a step in spec-flow. I want to 'read' the values put into the table and record the value as well as the column/row of the table it was entered in.
I have saved each cell of the table and created a string array with all boxes, and used the following code to check if anything exists in the table:
foreach (int value in tableInfo)
{
if (value > 0)
{
int number = value;
}
}
I have stored the number entered in the table as number, I also want to store the name of the element in the array that contains the number so I can search it against another list and assign the number to that.

I think you're looking for a dictionary. A dictionary is essentially a key value pair. The key would be your cell number or cell name, and the value, the value that was in your cell. Let's say that the key is a string and the value is an int. This is how you will initialize your dictionary:
Dictationary<string, int> myDictionary = new Dictionary<string, int>();
Then as you go through that table, you add entries to the dictionary. You can use the add method, or just assign it.
myDictionary.Add("MyCellName", 20);
or
myDictionary["MyCellName"] = 20;
Later in your code, if you need to retrieve the value for cell 'xyz', you would just use:
var myValue = myDictionary["xyz"];

If u have a DataTable u can use this loop:
foreach (DataRow dtRow in tableInfo.Rows)
{
foreach(DataColumn dc in tableInfo.Columns)
{
var field = dtRow[dc].ToString();
}
}

Related

Count the frequency of each elements in a DataGridView in .Net Windows Application Form

I have some datasets that I read from csv files into DataGridViews and I need to plot some charts where I count the frequency of each different variable on each column.
I found a code that count the frequency of array elements and then print them, I tried using the same logic on my datagrid.
I started with a column ("SEX" column) that has only 2 values (2.0 or 1.0), but when I try to view the count result I always get 1 (which means it didn't count a thing). It's supposed to show the count of the last different value found in the column (in my case 2.0 which has 140ish occurence).
Edit: I tried appending the count result to the textbox and I see that I end up with 1 for each loop, while I am supposed to get only 2 values (which are the count 2.0and then the count of 1.0)
I also need to plot the output, so I am guessing I could use a dictionary where I store the variable name + the frequency.
public void countFreq() //function to count the frequency of each var in a column -not working yet-
{
var n = dataGridView1.RowCount;
var visited = new bool[n];
// Traverse through array elements and
// count frequencies
for (var i = 0; i < n; i++)
{
// Skip this element if already processed
if (visited[i] || dataGridView1.Rows[i].Cells["SEX"].Value
== null)
continue;
// Count frequency
var count = 1;
for (var j = i + 1; j < n; j++)
if (dataGridView1.Rows[i].Cells["SEX"].Value == dataGridView1.Rows[j].Cells["SEX"].Value)
{
visited[j] = true;
count++;
}
textFile.Text += count.ToString(); //for testing purposes I used a textfield to print the last count value
}
}
I know that for a column where the values are explicit I can just loop on my datagrid rows and use the count method (which I did) but for most my data I don't explicitly know the values in each row so I needed to find a way to do that.
I am not sure if this is what you are looking for. In addition, the code below loops through the rows in the grid, however, if the grid has a data source I suggest looping though that collection instead of the grid rows.
Below is a method that takes a column index and returns a Dictionary<string, int>. A simple loop through each cell in the given column and if the cell's Value is not in the dictionary, we will add it. If the cells value is already in the dictionary will simply increment its int Value. After the loop finishes, the dictionary is returned. Something like…
private Dictionary<string, int> GetCountOfValues(string columnName) {
string curKey = "";
Dictionary<string, int> valuesAndCounts = new Dictionary<string, int>();
foreach (DataGridViewRow row in dataGridView1.Rows) {
if (!row.IsNewRow) {
if (row.Cells[columnName].Value != null) {
curKey = row.Cells[columnName].Value.ToString();
if (valuesAndCounts.ContainsKey(curKey)) {
valuesAndCounts[curKey]++;
}
else {
valuesAndCounts.Add(curKey, 1);
}
}
}
}
return valuesAndCounts;
}
Usage may look something like…
Dictionary<string, int> column0Counts = GetCountOfValues("Col0");
Dictionary<string, int> column1Counts = GetCountOfValues("Date");
You should really load your CSV data into a datatable and then query that
var dt = SomeFunctionThatReadsCsvIntoDatatable(..);
yourDataGridView.DataSource = dt;
Your query is then answered, simply, by grouping the datatable using linq;
(yourDataGridView.DataSource as DataTable).Rows
.Cast<DataRow>()
.GroupBy(r => r["someColumn"])
.Select(g => new { K = g.Key, C = g.Count() });
"someColumn" would be "SEX"
K would end up as an object holding whatever Type the data is ` - it's hard to tell from the information posted whether you've just got your csv as strings or whether they're eg doubles, dates etc
If you want to do it for all columns, it would probably be easiest to do it in a loop on the datatable Columns collection. DataColumn.ColumnName provides the "someColumn"

How to get columns with values from second list which is contain in first list?

I have two list. First list has matched column which is available in second list.
I want to show matched columns with values from second list.
List<string> _filtredData = new List<string>();
_filtredData.Add("Broker");
_filtredData.Add("Loaction");
_filtredData.Add("StandardLineItem");
_filtredData.Add("Section");
foreach (DataColumn _dtCol in FinalDiffData.Columns)
{
if (matchedItems.Contains(_dtCol.ToString()))
{
_filtredData.Add(_dtCol.ToString());
}
}
_filtredData -> contains matched columns which available in Second list.
FinalDiffData.AsEnumerable() -> this is secondlist.
List<string> _filtredData = new List<string>();
_filtredData.Add("Broker");
_filtredData.Add("Loaction");
_filtredData.Add("StandardLineItem");
_filtredData.Add("Section");
foreach (DataColumn _dtCol in FinalDiffData.Columns)
{
if (matchedItems.Contains(_dtCol.ToString()))
{
_filtredData.Add(_dtCol.ToString());
}
}
var shortedListMismatchElementLocal = _filtredData;
var result = FinalDiffData.AsEnumerable().Where(p =>
shortedListMismatchElementLocal.Any());
Please help me with proper answer.
Edit from your last comment
FinalDiffData.AsEnumerable() list has column like
Broker, Loaction, StandardLineItem, Section, 2Q2019E, 3Q2019E, 4Q2019E, 2019E, 1Q2020E
etc as earning order. _filtredData list has
Broker, Loaction, StandardLineItem, Section, 2Q2019E, 3Q2019E, 4Q2019E,
I want to get matched column with value from FinalDiffData.AsEnumerable() which available in _filtredData list
You need to compare a List<string> with a DataTable. You're only interested in one column in the datatable (I'll assume the column name is "Data").
The following query will get all rows in column "Data" matching _filteredData.
var result = FinalDiffData
.AsEnumerable()
.Where(p => _filtredData.Contains(p["Data"])); // use the actual column name here

To assign datarow with new value in C#

iam looking into datatable and fetching line by line,
iam having 50 length values. i want to assign 10th length value as "text".
but it is not stored in datarow after assigned
foreach (DataRow row in dtSource.Rows)
{
if (row.ItemArray[17].ToString().Length > 32)
{
string ss= "text";
row.ItemArray[17] = ss; // here it is not added in itemarray
}
}
DataRow.ItemArray creates a new array on the fly that contains all fields. So when you modify this array you won't modify the DataRow itself. You should use the DataRow indexer:
row[17] = ss;
You can use ItemArray when you need all objects in an array or when you want to assign the whole row's fields at once by assigning an array to this property.

c# adding row that already belongs to a datatable

I have a datatable DTgraph, that datatable has a column named Campaign. that column could have one of three unique values, which are IVR, City, City2`. So the rows are like this:
I have a datatable has data like this format
........ IVR........
.........IVR........
**.........IVR........**
.........City1......
.........City1......
**.........City1......**
.........City2......
.........City2......
**.........City2......**
I want to take the last row of each unique value for that column, In other words, I want to take the rows that are bold. I did almost everything like this:
var cRows = new Dictionary<string, DataRow>(StringComparer.InvariantCultureIgnoreCase);
foreach (DataRow oRow in DTgraph.Rows)
{
var sKey = oRow["Campaign"].ToString();
if (!cRows.ContainsKey(sKey))
{
cRows.Add(sKey, oRow);
}
else
{
cRows[sKey] = oRow;
}
}
var oNewTable = DTgraph.Clone();
foreach (var oRow in cRows.Values)
{
oNewTable.Rows.Add(oRow);
}
As you see, I put the data in dictionary and transferred the dictionary to a datatable at the end.
My problem is that on this line:
cRows.Add(sKey, oRow);
I get an error:
The row is already belongs to another datatable
Note: I need to solve that exception, I don't need a new way of doing my goal
Note: I was wrong, the exception is on this line
oNewTable.Rows.Add(oRow);
To be honest I don't 100% understand your question, however to fix the exception:
The row is already belongs to another datatable.
Change:
oNewTable.Rows.Add(oRow);
To:
oNewTable.ImportRow(oRow);
Alternatively create a new row and clone the ItemArray.
foreach (var oRow in cRows.Values)
{
var newRow = oNewTable.NewRow();
newRow.ItemArray = oRow.ItemArray.Clone() as object[];
oNewTable.Rows.Add(newRow);
}
Use NewRow() function of the new table and then use oRow.ItemArray property to get values from the source row and copy them the newly created row's ItemArray. An example would be:
Array.Copy(oRow.ItemArray, oNewTable.NewRow().ItemArray, oRow.ItemArray.Length)
However, remember that this would not preserve original values and current state from the source row (which I don't think you're using here anyway). If those things matter, go for ImportRow() solution which preserves source row's state when copying.

How to get column name from gridview?

I would like to know how can I get a column name from a gridview? by its number not by name.
like : Name|Age|Birthday: ( so name=0 , age=1 etc...)
thanks.
You can get it like this :
gv.HeaderRow.Cells[i].Text
Or like this :
gv.Rows[0].Cells[i].Text
Rows[0] should be your header row.
//// Header column names
int gridViewCellCount = yourGridView.Rows[0].Cells.Count;
// string array to hold grid view column names.
string[] columnNames = new string[gridViewCellCount];
for (int i = 0; i < gridViewCellCount; i++)
{
columnNames[i] = ((System.Web.UI.WebControls.DataControlFieldCell)(yourGridView.Rows[0].Cells[i])).ContainingField.HeaderText;
}
simply
GridView1.Rows[0].Cells[0].Text;
try this if you want to all the cells value from each of the rows
foreach (GridViewRow r in GridView1.Rows)
{
string s = r.Cells[0].Text;
string y = r.Cells[1].Text;
}
update:
try this
foreach (TableCell Tc in GridView1.HeaderRow.Cells)
{
//if you are not getting value than find childcontrol of TabelCell.
string sssb = Tc.Text;
foreach (Control ctl in Tc.Controls)
{
//Child controls
Label lb = ctl as Label;
string s = lb.Text;
}
}
Revisiting this old question.... it's possible to get the field names of the data bound to a GridView with this kind of code. This makes a dictionary of colnum and field name.
private static IDictionary<int, string> GetGridViewFieldNames(object grid)
{
var names = new Dictionary<int, string>();
var view = grid as GridView;
if (view != null) {
for (var i = 0; i < view.Columns.Count; i++) {
var field = view.Columns[i] as BoundField;
if (field != null) {
names.Add(i, field.DataField);
}
}
}
return names;
}
This is not the answer to the question. It is only the answer if you never change the header text in the gridview. The asker of the question wanted to get the database field name by index.
I've seen a number of "answers" which only provide the text in the selected row of a gridview, or the header text which both do not answer the question that was asked...
You may ask why? If you were going to do audits of updates in a system and wanted to compare old values and new values and only update if they change and want to indicate which field was updated how do you show the database table field name at the index of the loop.
For instance:
Protected Sub gv_RowUpdating(sender As Object, e As System.Web.UI.WebControls.GridViewUpdateEventArgs)
Dim intValCount As Integer = Integer.Parse(e.NewValues.Count)
If intValCount > 0 Then
Dim i As Integer = 0
For i = 0 To intValCount - 1
If Not e.OldValues(i).Equals(e.NewValues(i)) Then
' values have changed, audit the change
Sys.Audits.General(intID, "the_database_table", <the table field by index(i)>, e.OldValues(i).ToString, e.NewValues(i).ToString)
End If
i += 1
Next
End If
End Sub
So the questions is how do you get the database table field name by index via code behind? I too have been searching for this and all the "answers" that I've seen are not the answers I think some of us are really looking for. All the mentioned methods I've seen here are not bullet proof references to a database tables field name.
Its easy: Here i read the gridview header text for each header cell and add them as new columns to a data table.
DataTable dt = new DataTable();
foreach(DataControlFieldHeaderCell column in yourGridview.HeaderRow.Cells)
{
dt.Columns.Add(column.Text.Trim().Replace(" ", ""));
}
//Make sure you do all this after yourGridview.DataBind();
//If you do not want to bind data first simply bind an empty list like so:
/* yourGridview.DataSource = new List<string>();
yourGridview.DataBind(); */

Categories

Resources