I want to remove every column after the 3rd column from a CSV file loaded into a datatable, but I'm getting odd results. Here's my code.
System.Data.DataTable csv_datatable = null;
using (System.IO.StreamReader re = new System.IO.StreamReader(model.file.InputStream))
{
csv_datatable = CsvParser.Parse(re as System.IO.TextReader);
for (int x = 3; x < csv_datatable.Columns.Count + 1; x++)
{
csv_datatable.Columns.RemoveAt(x);
}
}
My sample CSV file:
7 columns, and I want to keep the first three.
email,first,last,middle,nick,job,phone
roryok#fakedomain.com,rory,wally,ok,danger,developer,555-0123
This is the result I get.
email,first,last,nick,phone
roryok#fakedomain.com,rory,ok,danger,555-0123
As you can see, rather than removing the last columns as I would expect, the code actually removes the 4th and 6th columns.
As usual, figured this out as I was posting, but I'll post the solution anyway in case it helps someone.
As each column is removed, the index for each column changes. So when you remove column 3, 4 becomes the new 3. This code works:
for (int x = 0; x < csv_datatable.Columns.Count; x++)
{
csv_datatable.Columns.RemoveAt(3);
}
This will loop over the number of columns, and remove the third column over and over again until everything is gone.
Related
How do I delete all rows in an excel spreadsheet except the header in c#?
I am trying to do this using the Microsoft.Office.Interop.Excel; library
I now have this code
Range xlRange = ws.UsedRange;
int rows = xlRange.Rows.Count;
Console.WriteLine(rows);
for (int i = 2; i <= rows; i++)
{
((Range)ws.Rows[i]).Delete(XlDeleteShiftDirection.xlShiftUp);
}
But it's not deleting all the rows, I think because it's deleting the rows when it hits a certain number that row is no longer there, what have I done wrong?
I managed to do it, I have started from the bottom instead of the top, so now my loop is
for (int i = rows; i != 1; i--)
{
((Range)ws.Rows[i]).Delete(XlDeleteShiftDirection.xlShiftUp);
}
Solution
var range = (Range)ws.Range[ws.Cells[2, 1], ws.Cells[ws.UsedRange.Rows.Count, ws.UsedRange.Columns.Count]];
range.Delete(XlDeleteShiftDirection.xlShiftUp);
There had been a change in v4 of .Net that using get_Range stopped working
If you were working in Excel, you would keep hitting delete on the second row, and observe the rows below shifting up, replacing the cells that were previously occupied by the deleted row.
To replicate that behavior in automation:
for (int i = 2; i <= rows; i++)
{
((Range)ws.Rows[2]).Delete(XlDeleteShiftDirection.xlShiftUp);
}
Note that you can also construct a range up front, and delete that without a loop, which will be much faster:
var range = (Range)ws.get_Range(
ws.Cells[1,2],
ws.Cells[ws.UsedRange.Cols.Count,ws.UsedRange.Rows.Count]
);
range.Delete(XlDeleteShiftDirection.xlShiftUp);
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!
I have a DataTable with one column filled with list of words from a text file, I create a method to read a string if the string is founded the row must be deleted, but the problem is that the DataTable don't get the updates.
foreach(string line in file)
{
tagst.Rows.Add(line)
}
string s;
for (int k = 0; k < tagst.Rows.Count; k++)
{
s = tagst.Rows[k]["Tags"].ToString();
if(s.Equals("Jad"))
{
tagst.Rows[k].Delete();
}
}
after your loop, call tagst.AcceptChanges();
per the documentation:
When AcceptChanges is called, any DataRow object still in edit mode successfully ends its edits. The DataRowState also changes: all Added and Modified rows become Unchanged, and Deleted rows are removed.
As #LarsTech stated, you'll want to rework your loop like:
for (int i = tagst.Rows.Count - 1; i >= 0; i--)
{
// ....
}
One issue with your coding is that when you removing rows - you need to start from the last one backward for very simple reason. Once you remove row 3,10,20 out of 100 how many rows will remain? Why do you need to start from bottom? Because tagst will be automatically re-indexed and reordered as soon as delete completed.
But your tagst.Rows.Count is already set and not getting refreshed ever!
Basically once your counter(K) hit number where rows already been deleted you will see error at best, at worse your app will crush if you do not have error handling routines set. Since you did not post actual code for how you create your tgst I will show how it can be done in array. Declaration of variable ommited...
Try this:
for (int k=tagstArray.Count; k>0; k--)
{
s = tagstArray[k].ToString();
if(s.Contains("Jad"))
{
tagstArray[k].Remove(k);
}
}
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();
}
}