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
}
}
}
Related
I am relatively new to c#, I am creating an windows application which would read all the lines from a text file. The user will input the string which needs to be replaced in Column[0] and the text with which it needs to be replaced in Column1 of the DataGridView control.
I have created two string arrays column0 and column1.
However, I am getting an error while replacing the string in line (column0, column1)
The following is my code:
string[] column0 = new string[dgvMapping.Rows.Count];
string[] column1 = new string[dgvMapping.Rows.Count];
int j = 0;
foreach(DataGridViewRow row in dgvMapping.Rows)
{
if (!string.IsNullOrEmpty(Convert.ToString(row.Cells[0].Value)))
{
column0[j] = Convert.ToString(row.Cells[0].Value);
column1[j] = Convert.ToString(row.Cells[1].Value);
j++;
}
}
var _data = string.Empty;
String[] arrayofLine = File.ReadAllLines(ofd.FileName);
using (StreamWriter sw = new StreamWriter(ofd.FileName + ".output"))
{
for (int i = 0; i < arrayofLine.Length; i++)
{
string line = arrayofLine[i];
line = line.Replace(column0[i], column1[i]);
sw.WriteLine(line);
}
}
I am using OpenFileDialog to select the file.
The Error While Executing:
You are looping around a file of unknown number of lines, and assuming that the count of lines in the grid is exactly the same as that of the file. Your code will only work if both the file and the gridView have the same number of lines.
One of the solutions, is to loop over the array of lines (as you have already did), and search for the GridViewRow in which the current line contains a key in your DGV. If this is the case, then replace all the occurences of the key by the value (obtained from the gridView) in that line, otherwise do nothing.
Check out the code below :
// Convert the row collection to a list, so that we could query it easily with Linq
List<DataGridViewRow> mySearchList = dataGridView1.Rows.Cast<DataGridViewRow>().ToList();
const int KEY_INDEX = 0; // Search index in the grid
const int VALUE_INDEX = 1; // Value (replace) index in the grid
for (int i = 0; i < arrayofLines.Length; i++)
{
string line = arrayofLines[i];
// Get data grid view Row where this line contains the key string
DataGridViewRow matchedRow = mySearchList.FirstOrDefault(obj => line.Contains(obj.Cells[KEY_INDEX].Value.ToString()));
// If this row exists, replace the key with the value (obtained from the grid)
if (matchedRow != null)
{
string key = matchedRow.Cells[KEY_INDEX].Value.ToString();
string value = matchedRow.Cells[VALUE_INDEX].Value.ToString();
line = line.Replace(key, value);
sw.WriteLine(line);
}
else
{
// Otherwise, do nothing
}
}
Stuartd is correct… there are more lines in the file than there are elements to search. I am not sure what the search is doing in a sense that it seems somewhat limited. The code appears to search for each item depending on what line it is. The searched value in column 0 and the replace value in column 1 of row 0… will only replace those values for the FIRST line in the file. The DataGridViews second row values will search/replace only the SECOND line and so on. This seems odd.
Example the two string arrays (column0 and column1) have sizes set to the number of rows in dgvMapping. Let’s say there are 5 rows in the grid, then the array sizes will be 5 strings. When you start the loop to write the strings, the loop starts at 0 and stops at the number of lines in the file. The code uses this i variable as an index into the two arrays. If there are more lines in the file, than there are rows in the grid… then you will get the error.
Again, this seems odd to do the search and replace this way. Assuming you want to search for EACH term in all the rows in column 0 and replace the found searched string with the replace string in column 1, then you will need to loop through EACH row of the grid for EACH line in the file. This will replace ALL the search/replace terms in the grid with ALL the lines in the file. If this is what you what to accomplish below is one way to achieve this, however…there are possibly better ways to accomplish this.
The code below reads the file into one big string. Then the code loops through ALL the grid rows to search/replace the strings in the big string. Hope this helps.
string bigString = File.ReadAllText(ofd.FileName);
try {
using (StreamWriter sw = new StreamWriter(ofd.FileName + ".output")) {
for (int k = 0; k < dgvMapping.Rows.Count; k++) {
if (dgvMapping.Rows[k].Cells[0].Value != null && dgvMapping.Rows[k].Cells[1].Value != null) {
string searchTerm = dgvMapping.Rows[k].Cells[0].Value.ToString();
string replaceTerm = dgvMapping.Rows[k].Cells[1].Value.ToString();
if (searchTerm != "") {
bigString = bigString.Replace(searchTerm, replaceTerm);
} else {
// one of the terms is empty
}
} else {
// one of the terms is null}
}
}
sw.WriteLine(bigString);
}
}
catch (Exception ex) {
MessageBox.Show("Write Erro: " + ex.Message);
}
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 have a datatable containing a list of service calls placed each month. Column F4 contains the serial number of the machine, now all I wanted to do was find the number of service calls placed for each serial number and add the count to a new a column. I wrote the code below and all was working fine but then a problem arose when a hash sign '#' appeared in the data to reflect an unknown or yet assigned serial number. This caused the error "Cannot perform '=' operation on System.String and System.Int32." on the line "DataRow[] FoundRow = dt.Select("[F4] =" + chkStr);
The F4 column is a text/string and I even tried cloning the datatable and manually assigning the column to .DataType = typeof(String); I know its the # sign giving the issue as if I remove from the data for testing purposing all is fine. Can anyone shed some light on this. Many thanks.
// datatable dt contains all my monthly call data
dt.Columns.Add("Counter", typeof(System.Int32)); // add a count column to the datatable
for (int i = 0; i < dt.Rows.Count; i++) //loop through the datatable
{
string chkStr = dt.Rows[i]["F4"].ToString(); // get 1st serial num, then each other one in loop
DataRow[] FoundRows = dt.Select("[F4] =" + chkStr); // OK now select all the table rows containing this serial, place in FoundRows
Int32 count = FoundRows.Length; // get the length which is a count of the same serial num / service calls
dt.Rows[i]["Counter"] = count;
}
Don't worry about counting the value as in Int32. Who cares; you can still "use" the number when it is a string. Read it as a string, "#" will be valid and numbers will be valid. Here is a simple solution that will even tell you how many have not been assigned yet.
public class GroupCounter {
private Dictionary<string, int> serialNumbers;
public GroupCounter() {
this.serialNumbers = new Dictionary<string, int>();
}
public Dictionary<string, int> Count(DataTable table) {
foreach (DataRow row in table.Rows) {
int counter;
string serial = row.Field<string>("COLUMN");
if(!this.serialNumbers.TryGetValue(serial, out counter)){
this.serialNumbers.Add(serial, 1);
}
counter++;
}
return this.serialNumbers;
}
}
Since this returns a Dictionary you can use dictionary[key] (your serial number) to fetch to count for any serial number.
many thanks for your suggestions but found the answer was simply to add single quote marks ' around the chkStr as below and the code then handled the # hash characters fine. Appreciate your time.
DataRow[] FoundRows = dt.Select("[F4] ='" + chkStr + "'");
Ok so I just did a quick test to see if my code was set to read properly from the DataGrid, and it does, but once it finishes reading I get the error "Object reference not set to an Instance of an object" and I'm not sure what it's referring to. Is it because the loop continues after the rows has reached the end of the DataGrid?
public static void UploadFromExtrernalSource(PlantAreaCode_CreateView PACCreate)
{
// For each row in the DataGrid, and for each column, stores the information in a string.
for (int rows = 0; rows < PACCreate.dataGridView1.Rows.Count; rows++)
{
for (int col = 0; col < PACCreate.dataGridView1.Rows[rows].Cells.Count; col++)
{
string value = PACCreate.dataGridView1.Rows[rows].Cells[col].Value.ToString();
Console.WriteLine(value + ",");
}
}
}
EDIT: Also when I print to console, it prints each value on a new line. Why?
Problem1 : You are trying to convert the null value from one of the cells into String.
Solution1 : before converting cell value into String do a null check.
Problem 2: you are using Console.WriteLine() method to display each cell value.so that it prints each cell value in a new Row/Line.
Solution 2: you need to use Console.Write() method instead of Console.WriteLine() to print cell values, and once after printing all cell values from a given row you need to use Console.WriteLine() to print new line.
Suggestion: you don't need to declare the string variable value each time in a for loop, so you can move the string variable declaration out of the loop.
Try This:
public static void UploadFromExtrernalSource(PlantAreaCode_CreateView PACCreate)
{
// For each row in the DataGrid, and for each column, stores the information in a string.
String value = String.Empty;
for (int rows = 0; rows < PACCreate.dataGridView1.Rows.Count; rows++)
{
for (int col = 0; col < PACCreate.dataGridView1.Rows[rows].Cells.Count; col++)
{
if(PACCreate.dataGridView1.Rows[rows].Cells[col].Value!=null)
{
value=PACCreate.dataGridView1.Rows[rows].Cells[col].Value;
Console.Write(value + ",");
}
else
{ value=String.Empty; }
}
Console.WriteLine();//it prints a new line
}
}
hey i think you are trying to convert null value of a cell into string . try to check for the null before converting it to the string hope this will help !
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();
}
}