I need to iterate over a specific excel row. For now I've got a code to iterate over a column and I want it to be similar to that. It looks like this:
int columnLength = xlWorkSheet.UsedRange.Rows.Count;
string lastCell = Regex.Replace(CONST_FIRST_CELL, #"\d+", columnLength.ToString()); //will give me the last cell in the column
var excelColumn = xlWorkSheet.Range[CONST_FIRST_CELL, lastCell ];
if (excelColumn == null)
{
throw new Exception("bad col");
}
for (int i = 1; i < columnLength ; i++)
{
Excel.Range currentValue = excelColumn [i];
....DO SOME STUFF....
}
how can I iterate over a specific row? I'm not sure how to get the last column like I got the last row cell in the above implementation since then I just had to switch a number with the length but now I somehow need to get the correct last cell of a row (which means switching the letters somehow i.e C4 to AD4) in order to get the range of first cell row and last...
The best solution I guess involves a foreach loop somehow?
You were almost there, your loop just needs some tuning:
//Input all the Int values you want
int targetRow = 1;
int startCol = 1;
int maxCol = 10; //With this value the loop below will iterate until column 9 (inclusive)
for (int i = startCol; i < maxCol ; i++)
{
Excel.Range currentRange = (Excel.Range)xlWorkSheet.Cells[targetRow, i];
if (currentRange.Value2 != null)
{
string curVal = currentRange.Value2.ToString();
}
}
IMO this is the best way to iterate through cells (by considering rows and/or columns). You can do it differently (on the lines of what you were trying): iterating within the columns of a given range (you would need to define the range as Excel.Range Type and then rely on the in-built property Columns), although I think that this can be more confusing. Example: if you have as input range C1:H5, "C:C" is the first column, "D:D" the second column, etc. With my approach, the first column will always be "A:A", the second column "B:B", etc.
Example of iterating through columns in a given range (inputRange):
foreach(Excel.Range curCol in inputRange.Columns)
{
if (curCol.Value2 != null)
{
//As far as each column only has one row, each column can be associated with a cell
string curVal = curCol.Value2.ToString();
}
}
Related
I can't seem to access the actual values in my column; My values for each row end up all being the same and actual row count. I can't seem to figure this out. Any help would be appreciated. Here's my current method:
private string converter() {
string binaryString = string.Empty;
int cellValue = 0;
int colIndex = 3;
foreach(DataGridViewRow row in this.dataGridView1.Rows)
{
cellValue = (int) row.Cells[colIndex].Value;
binaryString = parseString(cellValue);
}
return binaryString;
}
You are replacing the value of "binaryString" in each loop duration.
I'm not sure what your goal is, but perhaps this what you meant:
binaryString += parseString(cellValue);
Notice the +=
Edit - Another Approach?
Perhaps you want each value in a column to be converted? Try this, then.
private List<String> converter()
{
List<String> binaryStrings = new List<String>();
int cellValue = 0;
int colIndex = 3;
foreach(DataGridViewRow row in this.dataGridView1.Rows)
{
cellValue = (int) row.Cells[colIndex].Value;
binaryStrings.Add(parseString(cellValue));
}
return binaryStrings;
}
This gives you a list of converted strings. One string per row.
If you are using a DataTable I do not think you can make an Expression to convert a base 10 number to a binary string representation. However it is possible to add the binary string to the cell whenever a DataRow changes. If a DataRow changes in the DataTable, then the code can do the conversion of the base 10 value to a binary string representation and add the string to the proper cell.
In order to achieve this, the code needs to register the RowChanged event BEFORE the DataTable is filled. In addition, since a value is changed in the RowChanged event, it is necessary to turn off this event when the code adds the binary string to the table. This will prevent an obvious infinite loop, which would keep calling itself every time the binary string is added to the row.
You will need to change the names to match your requirements. Below is the line needed to register the RowChanged event with the DataTable. Note you need to set this line BEFORE you fill the table with data.
gridTable.RowChanged += new DataRowChangeEventHandler(Row_Changed);
Then all we need is this Row_Changed method. NOTE, the event is unregistered from the DataTable to avoid an infinite loop.
private static void Row_Changed(object sender, DataRowChangeEventArgs e) {
gridTable.RowChanged -= new DataRowChangeEventHandler(Row_Changed);
DataRow dr = e.Row;
int base10 = (int)dr["Base10"];
string binary = Convert.ToString(base10, 2);
dr["Binary"] = binary;
gridTable.RowChanged += new DataRowChangeEventHandler(Row_Changed);
}
I am guessing there may be other ways to accomplish this, the goal here was to avoid having to loop through the grid to set the binary strings. Hope this helps.
i was looking for a solution to your problem...
here i what i came with..
works here.
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
if(column.Name == "wanted column name")
{
for(int iRow = 0; iRow < dataGridView1.RowCount; iRow++)
{
string data = (string)dataGridView1[column.Index, iRow].Value;
//Do something with data
}
}
}
I have a column which is my third column.
I am stuggling to place the values into an unknown array size when it the button is clicked.
int rowCount = dataGridView1.Rows.Count;
string[] Priority = new string[rowCount];
if (rowCount > 1) // only sort if bigger than one line
{
for (int i = 2; i < rowCount; i++)
{
dataGridView1.Rows[i].Cells[2].Value = priority[i]; //put data into row thats been added
}
}
I get a System.IndexOutOfRangeException when I try with more than one row, it is fine if I want to add one value to an array and Im not sure what is wrong with it? Thanks
Try this:
// Modify the value in the first cell of the second row.
this.dataGridView1.Rows[i].Cells[0].Value = "new value";
// The previous line is equivalent to the following line.
this.dataGridView1[i, 2].Value = "new value";
Not sure if this is your problem, but you instantiate as "Priority"
then you are using 'priority'
prehaps a property named elsewhere?
I agree with the off by one. the i = 2 is confusing
I'm new, but I thought arrays were always finite in size.
just my thoughts.
I try to read whole rows of a given column in listview
As I'm new in C# and use of listview I saw it does not work as List
Below is the code that I use (What I found as solution in some sites)
for (int i = 0; i < rapview.Items.Count; ++i)
{
int idx = 0;
foreach (ColumnHeader header in rapview.Columns)
{
if (header.Text == "Bak. €")
{
MyArray[0] = GeneralMethod.GetClientName(conn, rapview.Items[1].Text);
di = new ListViewItem(MyArray);
tmpView.Items.Add(di);
}
++idx;
}
}
I want to retrieve 1st column 7th column cells, but I see that rapview.Items[1].Text is empty and similar for 7th cell.
Either I miss something or given solution is not correct.
How to read the value of those cells. If possible with column number by bypassing the foreach loop?
This is a loop that copies every value in the 7th column to a list of strings.
If there is no 7th column in the row it adds an empty string.
int column = 6;
List<string> values = new List<string>();
foreach (ListViewItem lvi in rapview.Items)
if (lvi.SubItems.Count - 1 < column) values.Add("");
else values.Add(lvi.SubItems[column].Text);
Note that C# counts zero-based, so the 7th column is indexed as 6.
You could test the value in row 1 column 7 as:
Console.WriteLine("Cell 7 in row 1 contains:" + values[0]);
Note that every Item in a ListView can have its own number of SubItems. Therefore we must test it before we access it!
Also note that SubItem[0] has the same value/text as the Item!
So I have this spreadsheet, it has Fname, Lname, Pnumber, Email, Cid. Cid is the only really important one, the rest are optional technically.
So instead of just doing a loop to see when the cell values starts being null, I know you can use the
WorksheetFunction.CountA(some 30 different variable that I do not understand but are optional too);
to get the actual numbers of filled cells, and it is instant. I have no idea how to do this.
This is what I'm going to do viva looping, but I know the CountA() function can do it in one line.
int i = 1;
while (i <= 200)
{
cell = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[i, 5];
if (cell.Value2 > 0)
{i++;}
else
{break;}
}
int totalCol = i;
Ok, this is what I have now, thanks everyone.
var cell = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[1, 1];
cell.Formula = "=CountA(E1:E200)";
double totalCells = (cell.Value2) -1;
I'm not in the IDE right now, but this should do the trick:
Dim cl As Microsoft.Office.Interop.Excel.Range
cl.Formula = "=CountA(E1:E200)"
myVal = cl.Value
I have two datagridviews in one form. The first, datagridview1 has columns and data:
name IC EMAIL TELEPHONE
------------------------------------------------------
rOO 898989096677 AB#YAHOO.COM 018-9097878
datagridview2 has
name IC EMAIL TELEPHONE ID
-----------------------------------------------------------
rOO 898989096677 AB#YAHOO.COM 018-9097878 8787
I would like to ask help on how to compare two datagridviews, as you can see in the figure I would like to compare the four columns from one datagridview to another datagridview and see if any results match. For example, does the roo name match with the another datagridview, I want the value in the id (8787) to be sent to another datagridview.
there is a very simple solution to compare twoo datagridview and show their result in 3rd one.
for (int i = 0; i < dtView1.Rows.Count; i++)
{
for (int j = 1; j < dtView1.Columns.Count; j++)
{
if ((dtView1.Rows[i][j]) == (dtView2.Rows[i][j]))
{
// here you can add your own logic
}
else
{
// here you can add your own logic
}
}
|
Let's assume that you populate both datagrids with the same objects that contain these 4 properties from your example. You must check for the selected row from the first datagrid if in the second datagrid there is an matching object, based on your filters. Use Linq. If so, then copy the data from the selected item from the first datagrid into the matching element from the seconds. I am affraid that you will need to do all these steps manually, because there is no method that can compare two data grids and you just set some filters and the job is done. You will have some work to do, but it is not hard. Good luck.
Steve's answer does not work correctly and will not compile.
Here is my solution:
int x = 0;
int y = 0;
int i = -1;
int z = 0;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
i++;
if ((dataGridView1.Rows[i].Cells[i].Value) == (dataGridView2.Rows[z].Cells[i].Value))
{
x++;
}
else
{
y++;
}
if (z < dataGridView2.Rows.Count)
{
z++;
}
if(z == dataGridView2.Rows.Count)
{
z--; //subtract 1 from the total count because the datagrid is 0 index based.
}
MessageBox.Show("Matched: " + x.ToString() + "\r\n" + "Not Matched: " + y.ToString());
A foreach loop on the datagrid will cycle through each row, you can then select a cell or even cells to compare. This code is a bit lengthy and I'm sure it can be simplified, however it does the job.
Currently this will check every row from datagrid 2 for a match in datagrid 2, only on a single column.
Its import to remember the datagrid is 0 index based. The Count property of the datagrid gives a [1]index based count, so we need to subtract the last iteration on datagrid 2.