Excel Interop - Cancel selection - c#

I'm copying and inserting rows in an Excel sheet, like so:
while (rowsToAdd > 0)
{
// copy the existing row
insertionCell.EntireRow.Copy(Type.Missing);
// location of the new row
Range newRow = insertionCell.EntireRow.get_Offset(1, 0).EntireRow;
// insert the new row
newRow.Insert(XlInsertShiftDirection.xlShiftDown, Type.Missing);
rowsToAdd--;
}
The problem I have is that sometimes, I'm left with a selection marquee around the row I originally copied.
Is there a way I can cancel the selection marquee (the way you'd normally do it with the Escape key?)

In VBA it's Application.CutCopyMode = False

Adding
myExcelApplication.CutCopyMode = XlCutCopyMode.xlCopy;
seems to do the trick, though the documentation does not explain it very well, and seems to be wrong, since bools are mentioned.

I know it's pretty old, but as I had some issue copying one row to another, and as I got the proper solution on my case, I'm now glad to share it, just in case it could fix your problem (thinking about copy rows instead of inserting one).
Here is the solution:
Microsoft.Office.Interop.Excel.Range xlSourceRow;
Microsoft.Office.Interop.Excel.Range xlNewRow;
xlSourceRow.Copy(xlNewRow);
Using this solution prevents from getting any selection in your MS-Excel file.

Related

C# ExcelPackage (EPPlus) DeleteRow does not change sheet dimension?

I am trying to build a data import tool that accepts an EXCEL file from the user and parses the data from the file to import data into my application.
I am running across a strange issue with DeleteRow that I cannot seem to find any information online, although it seems like someone would have come across this issue before. If this is a duplicate question, I apologize, however I could not find anything related to my issue after searching the web, except for this one which still isn't solving my problem.
So the issue:
I use the following code to attempt to "remove" any row that has blank data through ExcelPackage.
for (int rowNum = 1; rowNum <= ws.Dimension.End.Row; rowNum++)
{
var rowCells = from cell in ws.Cells
where (cell.Start.Row == rowNum)
select cell;
if (rowCells.Any(cell => cell.Value != null))
{
nonEmptyRowsInFile += 1;
continue;
}
else ws.DeleteRow(rowNum);
//Update: ws.DeleteRow(rowNum, 1, true) also does not affect dimension
}
Stepping through that code, I can see that the DeleteRow is indeed getting called for the proper row numbers, but the issue is when I go to set the "total rows in file" count on the returned result object:
parseResult.RowsFoundInFile = (ws.Dimension.End.Row);
ws.Dimension.End.Row will still return the original row count even after the calls to DeleteRow.
My question is...do I have to "save" the worksheet or call something in order for the worksheet to realize that those rows have been removed? What is the point of calling "DeleteRow" if the row still "exists"? Any insight on this would be greatly appreciated...
Thanks
I think I figured out the problem. This is yet again another closure issue in C#. The problem is that the reference to "ws" is still the same reference from before the DeleteRow call.
In order to get the "updated" dimension, you have to redeclare the worksheet, for example:
ws = excelPackage.Workbook.Worksheets.First();
Once you get a new reference to the worksheet, it will have the updated dimensions, including any removed/added rows/columns.
Hopefully this helps someone.

C# Excel - AutoFilter stopping at first blank cell

Good Afternoon,
I'm having some issues with running a filter on a spreadsheet to delete blank cells.
I'm using the below code which should filter the whole range of the spreadsheet but it stops at the first empty row and then the autofilter fails.
Range spreadsheetLast = spreadSheetWs.Cells.SpecialCells(Microsoft.Office.Interop.Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
Range spreadsheetRange = spreadSheetWs.get_Range("A1", "T" + spreadsheetLast.Row);
spreadsheetRange.AutoFilter(1, "=", XlAutoFilterOperator.xlAnd, Type.Missing, true);
Range xlFilteredRange = spreadsheetRange.Offset[1, 0].SpecialCells(XlCellType.xlCellTypeVisible, Type.Missing);
I'm then deleting the rows using
xlFilteredRange.EntireRow.Delete(XlDirection.xlUp);
This is deleting basically everything off the spreadsheet. I've tried playing around with the offset and had no luck.
I attempted to change the range to be manual while testing to "A1", "T9999" and this didnt work either.
Any help much appreciated,
Mark
Edit: Changed code back to original
You can avoid the AutoFilter and use .SpecialCells(xlCellTypeBlanks).EntireRow.Delete to find blank cells in a Range and delete them.
In VBA (and maybe C#?) you can just use the whole column (A:A) as the Range for this.
The following VBA works fine for me to delete all the rows which have a blank in the first column. I assume this will translate to C# easily and work via interop also.
Sub DeleteBlanksFromColumnA()
Range("A:A").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub

PERFORMANCE - looping over cells - suppress “number stored as text” warning in Excel VSTO with C#

I am populating a ListObject with data from a database, and am pre-formatting ListColumns which come from VarChar (& similar) as Text before inserting the data.
This works well, but some affected cells now are showing the 'Number Stored As Text' error.
The answer https://stackoverflow.com/a/21869098/1281429 suppresses the error correctly, but requires looping through all cells (as it is not possible to perform the action on a range).
Unfortunately for large ranges this is unacceptably slow.
(n.b. - if you do it manually in Excel it's lightning fast)
Here is a code snippet in C# (for a particular column):
var columnDataRange = listColumn.DataBodyRange
var cells = columnDataRange.Cells;
for (var i = 1; i < cells.Count; i++)
{
InteropExcel.Range cell = cells[i, 1];
if (cell.Count > 1) break;
if (cell.Errors != null)
{
var item = cell.Errors.Item[InteropExcel.XlErrorChecks.xlNumberAsText];
item.Ignore = true;
}
}
Does anyone know of a faster way of doing this?
(Or, more generally, a faster way of iterating through cells in a range?)
Hope someone can help - thanks.
Edit: this is a VSTO Application-Level add-in for Excel 2010/2013.
Just to be sure - you are going from a database to an Excel export? Are you creating a new, clean spreadsheet or overwriting existing data in an existing spreadsheet?
If you are overwriting data in an existing spreadsheet, I would first clear the columns and format the columns in Excel (programmatically of course). It is likely old data and new data going into the same space are causing type issues.
So something like:
thisExcel.xlWorksheet.Range[yourrange].Value = ""
thisExcel.xlWorksheet.Range[yourrange].NumberFormat = choseyourformat
http://msdn.microsoft.com/en-us/library/office/ff196401(v=office.15).aspx
You should be able to apply that to a larger area.

GemBox.Spreadsheet last used row

I am trying to get the index of the last used row in a spreadsheet. I've found that in excel it could be done like that:
int lastUsedRow = worksheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell,
Type.Missing).Row;
But this doesn't seem to work with GemBox. The idea is that I have a template excel file that I want to fill with more information and therefore need the last row, so that I can continue on the next one.
Hi you can just use ExcelFile.Rows.Count property.
Gets the number of currently allocated elements (dynamically changes when worksheet is modified)
Try the following:
int lastUsedRow = worksheet.Rows.Count - 1;
Also regarding the shahkalpesh suggestion, yes you can also achieve your task with that approach as well, here is how:
var usedRange = worksheet.GetUsedCellRange(true);
int lastUsedRow = usedRange.LastRowIndex;
Note: I haven't used Gembox. My answer is based on searching in the documentation.
GetUsedCellRange returns a CellRange, which has a property named LastRowIndex.
Does this work the same way as Excel?

Excel c# Issue - formula not being recalculated

I am working on a document-level excel project. This is the third version.
One of the worksheet contains a list object (data fed from a database). Then there are cells contains formulas like the following
this.Range["F15"].Formula = "=COUNTIFS(HotList_ListObject[Product],E15,HotList_ListObject[Got_Interest],\"<>\")"
previously, I created the table by just drag-and-drop. then simply created a formula in the worksheets. and the formulas were recalculated as data in the listobject (HotList_ListObject above).
this time, I created the table by the code. Because Hotlist_ListObject is not on the worksheet until the application runs, I supply the formulas after creating the listobject by code.
I looked through the internet and did a couple of testings.
When I press F9, SHIFT+F9 and CTRL+ALT+F9, it doesn't recalculate.
Only when I press CTRL+SHIFT+ALT+F9, it recalculates
the explantion I found for CTRL+SHIFT+ALT+F9 is
Rechecks dependent formulas, and then calculates all formulas in all open workbooks, regardless of whether they have changed since last time or not.
It seems that because the formula is supplied in the worksheet by code, it does not create links to dependent formulas or something so it won't recalculate. (something like this, I suppose)
My users are not going to press the button every time they modify/add/delete records in the list.
what can I do to resolve this? How to tell Excel that the formulas need to recalculate every-time any thing changes in the listobject.
Thanks for any advice in advance!
Kind regards
Mark
Does setting the Calculation to Manual:
xlApp.Calculation = XlCalculation.xlCalculationManual;
xlApp.ScreenUpdating = false;
xlApp.DisplayAlerts = false;
xlApp.UserControl = false;
xlApp.EnableEvents = false;
Then populating your Hotlist_ListObject (that is not on the worksheet until the application runs and) then set calculation to Automatic:
xlApp.Calculation = XlCalculation.xlCalculationAutomatic;
xlApp.ScreenUpdating = true;
xlApp.DisplayAlerts = true;
xlApp.UserControl = true;
xlApp.EnableEvents = true;
Resolve the problem? If not could you please post some bare bones code to illustrate the issue.
Did you check the options settings? This might be reset to manual by a macro (check with macro editor using Alt+F11 for xlCalculateManual and make sure the macro is not stopped before Application.Calculation = xlCalculationAutomatic is executed to set calaculations back to automatic. Turning calculations off is an often used method to speed macros up, but when a macro is exited half-way, this manual calculation setting will stay.
Here is the manual setting.

Categories

Resources