How to delete all rows from excel except header in c# - c#

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);

Related

C# - Excel: Deleting an entire row in excel, with a particular value at the first column of the row to be deleted

I am creating a web application using an excel file. If the excel file has m rows and n columns, and I have to delete the entire row if the value of cell in column A of the row is a string 'str'.
I tried various methods. The one I am stuck with right now deletes more than half of the existing elements. I'm working with the Microsoft.Office.Interop.Excel. I would like to know why that happens and a solution for the problem. Thanks in advance.
public void DeleteRow(int m, string str)
{
for (int rCnt = 2; rCnt <= m; rCnt++)
{
if((ws.Cells[rCnt, 1]).ToString().Contains(str))
{
((Range)ws.Rows[rCnt]).Delete(XlDirection.xlUp);
}
}
wb.Save();//save the workbook
wb.Close(false, "", false);//close the workbook
}
}
I even tried using:
((Range)ws.Rows[rCnt]).EntireRow.Delete(XlDirection.xlUp);
instead of:
((Range)ws.Rows[rCnt]).Delete(XlDirection.xlUp);
Go bottom up:
for (int rCnt = m; rCnt >= 2; rCnt--)
This will avoid deleting the wrong rows as rows shift after deletion.

ExcelWorksheet.UsedRange is counting wrong if file has empty rows on top

I have c# windows application that is reading files content. I wanted to extract values from used rows only.
I am using this code:
int rows = ExcelWorksheet.UsedRange.Rows.Count;
Everything works fine. Except when I have empty rows on top, the counting will be incorrect.
-File has no special characters, formula or such. Just plain text on it.
-The application can read excel xls and xlsx with no issue if the file has no empty rows on top.
Okay, now I've realized I'm doing it all wrong. Of course it will not read all of my UsedRange.Rows because in my for loop, I am starting the reading always on the first row. So I get the ((Microsoft.Office.Interop.Excel.Range)(ExcelWorksheet.UsedRange)).Row; as a starting point of reading
This code works:
int rows = ExcelWorksheet.UsedRange.Rows.Count;
int fRowIndex = ((Microsoft.Office.Interop.Excel.Range)(ExcelWorksheet.UsedRange)).Row;
int rowCycle = 1;
for (int rowcounter = fRowIndex; rowCycle <= rows; rowcounter++)
{
//code for reading
}
Instead of read Excel row-by-row, better to get it in C# as a Range, and then handle it as
Sheet.UsedRange.get_Value()
for whole UsedRange in Sheet. Whenever you'd like to get a part of UsedRange, do it as
Excel.Range cell1 = Sheet.Cells[r0, c0];
Excel.Range cell2 = Sheet.Cells[r1, c1];
Excel.Range rng = Sheet.Range[cell1, cell2];
var v = rng.get_Value();
You well know size of v in C# memory from the values of [r1-r0, c1-c0]

delete every row after specific string in excel through C#

I want to delete every row that comes after my specific keyword and including the keyword row as well. Can anybody please help me with C# code.
Example :- I have not attached a dummy excel file as I am posting it from mobile.
I have a word in excel :- "hello user" so I have to delete all the lines of data after this including it as well. And most important this data is not on the fixed line it can be on any line number....Suppose for now I have given it on 10th line so it may come on 12th line in next file.
Line no. Data
10. "hello user"
11. A
12. B
And so on
.
.
.
.
.
I think this code should work for you:
const string magicWord = "HelloUser";
Excel.Application app = new Excel.Application();
Excel.Workbook workbook = app.Workbooks.Open(#"myWorkbook.xlsx");
Excel.Worksheet worksheet = workbook.Sheets[1]; //Excel has no zero based index!!!
int magicWordRowIndex = Int32.MaxValue;
//Here we find your magic word. But we can't delete the rows here, so just save the index
for (int row = 1; row <= worksheet.Rows.Count; row++)
{
for (int column = 1; column <= worksheet.Columns.Count; column++)
{
if (worksheet.Rows[row][column] == magicWord)
{
magicWordRowIndex = row;
break;
}
}
}
//Now we run reversed, because else our magicWordRowIndex become invalid if we delete rows
for (int row = worksheet.Rows.Count; row >= magicWordRowIndex; row--)
{
((Excel.Range) worksheet.Rows[row, Missing.Value]).Delete(Excel.XlDeleteShiftDirection.xlShiftUp);
}
Actualy I'm not able to test it but should do the job, maybe you need minor changes and fit it to your needs.
First it finds your magicword which is hardcoded on the beginning. After finding this word we go delete all rows from bottom up to your existing word.
Notice that you need to reference: Microsoft.Office.Interop.Excel

Weird issue when removing columns from a datatable

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.

Read Excel Cell And Set Row Colour

I am using Com Interop and C#. I have to iterate through an Excel file looking for certain values in each of the rows (always in column 2). For some values I need to set the background colour of the row to red.
I am having trouble:
Reading the value in cell [i][2] for row i, and
Setting the background colour of this row.
Basically I am looking for something like this (which is the best I can find after much Googling):
// ws is the worksheet
for (int i = 1; i <= ws.Rows.Count; i++)
{
Range range = ws.Cells[i][2];
int count = Convert.ToInt32(range.Value2.ToString());
if (count >= 3)
{
Range chronic = ws.UsedRange.Rows[i];
chronic.EntireRow.Cells.Interior.Color = 0xFF0000;
}
}
Of course this doesn't work. I can't get past the first hurdle of just reading the cell. Any advice is appreciated.
Try this. The code assumes that the value in the column 2 cell is a number.
using Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;
Missing noValue = Missing.Value;
Excel.Range conditionalCell;
foreach (Excel.Range usedRange in ws.UsedRange.Rows)
{
conditionalCell = usedRange.Cells[noValue, 2] as Excel.Range;
if (Convert.ToInt32(conditionalCell.Value2) >= 3)
{
usedRange.Cells.Interior.Color = Excel.XlRgbColor.rgbRed;
}
}

Categories