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
Related
I'm trying to create a spreadsheet where the first sheet ("Catalog") contains some pre-filled and some empty values in a column. I want the values to be in a drop down list that are restricted to values found in the second sheet ("Products").
I would expect that if I set the the Excel validation formula for cells "A1:A1048576" in the "Catalog" sheet to be a list validation of "Products!A1:A100" that every cell would only allow values from "Products!A1:A100". However, I'm finding that my formula gets incremented for every row in the "Catalog" sheet (i.e. In row 2 the formula becomes "Products!A2:A101", in row 3 the formula becomes "Products!A3:A102").
If version matters I'm using EPPlus.Core v1.5.4 from NuGet.
I'm not sure if this is a bug or if I'm going about applying my formula wrong?
I've already tried directly applying the validation to every cell in the column one cell at a time. I found that not only does it moderately increase the size of the resulting Excel file but more importantly it also exponentially increases the time taken to generate the Excel file. Even applying the validation one cell at a time on the first 2000 rows more than doubles the generation time.
ExcelPackage package = new ExcelPackage();
int catalogProductCount = 10;
int productCount = 100;
var catalogWorksheet = package.Workbook.Worksheets.Add($"Catalog");
for (int i = 1; i <= catalogProductCount; i++)
{
catalogWorksheet.Cells[i, 1].Value = $"Product {i}";
}
var productsWorksheet = package.Workbook.Worksheets.Add($"Products");
for (int i = 1; i <= productCount; i++)
{
productsWorksheet.Cells[i, 1].Value = $"Product {i}";
}
var productValidation = catalogWorksheet.DataValidations.AddListValidation($"A1:A1048576");
productValidation.ErrorStyle = ExcelDataValidationWarningStyle.stop;
productValidation.ErrorTitle = "An invalid product was entered";
productValidation.Error = "Select a product from the list";
productValidation.ShowErrorMessage = true;
productValidation.Formula.ExcelFormula = $"Products!A1:A{productCount}";
I guess I'm not that adept at Excel formulas.
Changing this line:
productValidation.Formula.ExcelFormula = $"Products!A1:A{productCount}";
to this:
productValidation.Formula.ExcelFormula = $"Products!$A$1:$A${productCount}";
stopped the auto increment issue. Hopefully this answer will save someone else some sanity as I wasted half a day on this issue myself.
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]
I am trying an automation work on an excel sheet using c#. I want to delete blank rows present at the end of the excel sheet based on the no. of records in the first column only. Any other column may have different no. of rows than that in the first column.
For this purpose first I tried to evaluate the range of the first column and based on that I tried to delete rows after this in the excel sheet.
I used the following lines of code for this purpose :-
Range lastrow_new = sourceSheet2.get_Range("A6", Type.Missing);
if (excelApp.WorksheetFunction.CountA((int)(sourceSheet2.Rows[lastrow_new])) == 0)
{
for (int i = 1; i <= (int)(sourceSheet2.Rows[lastrow_new]); i++)
{
if (excelApp.WorksheetFunction.CountA(sourceSheet2.Rows[i]) == 0)
{
Range BlankRows = sourceSheet2.get_Range("A" + i + ":" + "FN" + lastrow_new);
BlankRows.Select();
BlankRows.EntireRow.Delete();
i = (int)(sourceSheet2.Rows[lastrow_new]) + 1;
}
}
}
But it is giving error of 'Type mismatch'.
Can anyone help ?
Thanks in advance.
I'm not sure i understand what you want... but if you want clear the consecutive rows after 'A6' column, you can try this code:
string value = sourceSheet2.Range["A1"].SpecialCells(XlCellType.xlCellTypeLastCell).Address;
value = value.Replace("$","");
sourceSheet2.Range["A6", value].ClearContents();
I was trying to insert a new row at the end of a worksheet using OLEDB. The worksheet has a format table in a Range (a1:xx), with format and formula stored. But OLEDB insert does not come with any format.
I have read the post How to copy format of one row to another row in Excel with c# talking about get the format, but doesn't work for me. Also, I don't think it will get the formula.
In the Excel UI, at the lower right corner of a formatted table, a double arrow would appear, and we can drag it to expand the format table range.
Anything we could do through C#?
Thanks.
Excel.Range last = xlWS.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
Excel.Range RngToCopyOri = xlWS.get_Range("A1", last).EntireRow;
Excel.Range RngToCopy = RngToCopyOri.Resize[RngToCopyOri.Rows.Count + 1, RngToCopyOri.Columns.Count]; //because insert will add only 1 row, so the range would be one row larger
Excel.Range RngToInsert = xlWS.get_Range("A1", Type.Missing).EntireRow;
RngToInsert.Insert(Excel.XlInsertShiftDirection.xlShiftDown, RngToCopy.Copy(Type.Missing));
I tried to copy Range(A1,lowerleft cell) to its original location, but nothing changed.
I tried Range.resize, autofill, autoformat. All of them has sort of problems. I finally gave up using OLEDB to insert data. Instead, i used
worksheet.UsedRange.Item[rowNo,getColumnIndex(worksheet,columnTitle)]=value
private int getColumnIndex(Excel.Worksheet sheetname, string header) {
int index=0;
Excel.Range activeRange=sheetname.UsedRange;
for (int i = 1; i <= activeRange.Columns.Count; i++) {
if (header == (string)(activeRange.Item[1,i] as Excel.Range).Value) {
index = i;
}
}
if(index==0)
throw some exception you like;
return index;
}
The getColumnIndex function aims to locate the column in SELECT [column] from...
In this way, the format table will automatically expand to the range you input the value.
How can I move to the next row in Excel using C#. I'm using Office PIA v 14. When I used Range.Next property, it takes me to the cell immediately right to the range. How can I move to the next row? ie. the cell immediately below.
Range.Next returns a Range object that represents the next cell.
I'm not really the greatest expert alive but according to the documentation you should use Offset instead. http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.range.offset
Here is some pseudo code
var excelApp = this.Application;
int skipRows = 1;
int skipCells = 0;
var nextRange = excelApp.ActiveCell.Offset[skipRows, skipCells].Select();
Try the following code:
Range oRng = ws.get_Range(Column + (row +1), Type.Missing);
where ws is the worksheet object.