Deleting a sheet in Excel - c#

I tried almost everything that I could find here on StackOverflow but my code keeps throwing the following error:
Exception from HRESULT: 0x800A03EC
on the line with delete(). I was hoping you people could help me out.
Here's my current code
var xlApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook book =
xlApp.Workbooks.Open(File_name);
xlApp.DisplayAlerts = false;
Excel.Worksheet worksheet = (Excel.Worksheet)book.Worksheets[2];
worksheet.Delete();
book.Worksheets.Add();
xlApp.DisplayAlerts = true;
book.Save();
book.Close();
xlApp.Quit();
Marshal.ReleaseComObject(worksheet);
Marshal.ReleaseComObject(book);
Marshal.ReleaseComObject(xlApp);
And here's the other code i tried:
oXL.DisplayAlerts = false;
worksheet = (Excel.Worksheet)theWorkbook.Sheets[i];
((Excel.Worksheet)theWorkbook.Sheets[i]).Delete();
oXL.DisplayAlerts = true;
oWB.Save();
oWB.Close(false, missing, missing);
oSheet = null;
oWB = null;
oXL.Quit();
And some more variations
Microsoft.Office.Interop.Excel.Application oXL = new Microsoft.Office.Interop.Excel.Application();
Excel.Workbook oWB;
Excel.Worksheet oSheet;
Excel.Workbooks oMWB;
and i'm using this reference:
using Excel = Microsoft.Office.Interop.Excel;

Working with the Excel Interop libraries, I encountered this error many times. The main cause of this problem (a generic COM exception), most of the times, is that Excel tries to find something you've asked for, but Excel isn't able to find it. See this answer, it helped me a lot.
Reading these lines:
Excel.Worksheet worksheet = (Excel.Worksheet)book.Worksheets[2];
worksheet.Delete();
I think that you're trying to delete a worksheet that's not existing. Check your Excel document.

I just made the most stupid mistake ever..... the excel file was a shared file, that's why i couldn't delete it..
Sorry for making such a stupid mistake, and thanks to everybody who tried to help me!

HRESULT: 0x800A03EC is an unknown COM error. This usually happens when Excel throws some error because your input or parameters were wrong.
This example provide msdn: Programmatically Deleting Worksheets from Workbooks
((Excel.Worksheet)this.Application.ActiveWorkbook.Sheets[4]).Delete();
So try next:
Excel.Worksheet worksheet = (Excel.Worksheet)book.Sheets[2];
worksheet.Delete();
instead of:
Excel.Worksheet worksheet = (Excel.Worksheet)book.Worksheets[2];
worksheet.Delete();

Try this:
xlApp.DisplayAlerts = false;
Excel.Worksheet worksheet = (Excel.Worksheet)book.Worksheets[2];
worksheet.Delete();
xlApp.DisplayAlerts = true;
Also important to keep in mind, interop starts to count from 1, not from 0. so deleting item [0] or deleting the only sheet will throw you an exception. if you plan to remove the [2] worksheet, the third one will take its place. So make sure to remove from the last to the first.

this is code i have used to delete the excel sheet
Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null)
{
return;
}
xlApp.DisplayAlerts = false;
string filePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
+ "\\Sample.xlsx";
Excel.Workbook xlWorkBook = xlApp.Workbooks.Open(filePath, 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Excel.Sheets worksheets = xlWorkBook.Worksheets;
worksheets[4].Delete();
worksheets[3].Delete();
xlWorkBook.Save();
xlWorkBook.Close();
releaseObject(worksheets);
releaseObject(xlWorkBook);
releaseObject(xlApp);
and use this
static void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
obj = null;
throw ex;
}
finally
{
GC.Collect();
}
}

Related

C# excel interop cut and paste exception

I’m working on a project and I’ve ran into an exception that I don’t know how to fix. I’ve searched everywhere and can’t find a solution that helps.
I’m trying to cut a range on a spreadsheet that has found a specific value in a cell in Column A and paste the entire row of that specific value into a new spreadsheet starting from A2 and until the value is no longer found in the original spreadsheet.
My code currently pastes one row in the new spreadsheet then gives me this exception “The information cannot be pasted because the Cut area and the paste area are not the same size and shape.” The exception is happening at this point in the code;
Excel.Range from = currentFind.EntireRow;
Excel.Range to = oSheet.get_Range("A2:A2500");
I think I need to use the active cell and active sheet properties.
Please help me!
public void btnLoad_Click(object sender, EventArgs e)
{
Excel.Application oXL;
Excel._Workbook oWB;
Excel._Worksheet oSheet;
if (dmCheck.IsChecked == true && fldCheck.IsChecked == true)
{
oXL = new Excel.Application();
oXL.Visible = true;
oWB = (Excel._Workbook)(oXL.Workbooks.Add());
oSheet = (Excel._Worksheet)oWB.ActiveSheet;
string dXLPath = #"N:/DAILY2.xlsx";
Excel.Workbook dWB = oXL.Workbooks.Open(dXLPath);
Excel.Worksheet dSheet = dWB.Worksheets.get_Item(1);
Excel.Range dRng = dSheet.get_Range("B1");
dRng.EntireColumn.Hidden = true;
Excel.Range currentFind = null;
Excel.Range firstFind = null;
Excel.Range taskHazpoi = dSheet.get_Range("A2", "A2500");
currentFind = taskHazpoi.Find("HAZPOI", Type.Missing, Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlPart, Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext, false, Type.Missing, Type.Missing);
while(currentFind != null)
{
if (firstFind == null)
{
firstFind = currentFind;
}
else if (currentFind.get_Address(Excel.XlReferenceStyle.xlA1) == firstFind.get_Address(Excel.XlReferenceStyle.xlA1))
{
break;
}
Excel.Range from = currentFind.EntireRow;
Excel.Range to = oSheet.get_Range("A2:A2500");
from.Cut(to);
currentFind = taskHazpoi.FindNext(currentFind);
}
else if (dmCheck.IsChecked == false && fldCheck.IsChecked == false)
{
MessageBox.Show("Please check the DM and Flood box", "Report Loader");
}
I recommend you use Epplus instead of the interop Excel (i used it).
Advantages:
No requires office package installed in system.
No instance of Excel in memory.
Methods more clear.
Example of use:
http://zeeshanumardotnet.blogspot.com.es/2011/06/creating-reports-in-excel-2007-using.html?m=1
You found it in Nuget.
Regards,
You try to copy an entire row into the cell area A2:A2500, that's what triggers the exception.
For the 'to' range, take oSheet.get_Range("A2").EntireRow or oSheet.get_Range("A:A").

xlApp.ActiveWorkbook returns null

I have a 2010 Excel ribbon add-in. When you press a button it simply writes some lines of data into the excel app. In order to write this data I need to get the active worksheet. And in order to get the active worksheet I need the activeWorkBook. I can get the xlApp fine with
xlApp = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
And it retrieves the xlApp fine But whenever I try to get the active workbook it returns null. No matter what. Unless I restart my computer. Then it works, but only the first time. Below is the whole block of code in context. I'm wondering how to fix the xlApp.ActiveWorkBook being null. So that I can get the active worksheet. And then write data to the active worksheet.
public void sendData()
{
Excel.Application xlApp = null;
Excel.Workbook xlWorkBook = null;
Excel.Workbooks xlWorkBooks = null;
Excel.Worksheet xlWorkSheet = null;
object misValue = System.Reflection.Missing.Value;
try
{
xlApp = new Excel.Application();
//xlWorkBooks = xlApp.Workbooks;
//xlWorkBook = xlWorkBooks.Add(Properties.Settings.Default.FileToSend);
//xlWorkSheet = xlWorkBook.Sheets[1];
xlApp = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
xlWorkBook = (Excel.Workbook)xlApp.ActiveWorkbook;
xlWorkSheet = (Excel.Worksheet)xlWorkBook.ActiveSheet;
}
catch (Exception ex)
{
// handle error...
}
finally
{
if (xlWorkSheet != null)
Marshal.ReleaseComObject(xlWorkSheet);
if (xlWorkBook != null)
Marshal.ReleaseComObject(xlWorkBook);
if (xlWorkBooks != null)
Marshal.ReleaseComObject(xlWorkBooks);
if (xlApp != null)
Marshal.ReleaseComObject(xlApp);
}
Thanks in advance!
You're probably getting hold of the wrong Excel instance with your call to GetActiveObject. Use the Application reference passed into your COM add-in's OnConnection (or however your ribbon code is bootstrapped).
If you're using the Excel-DNA framework to make your managed Excel add-in, then you get hold of the right Application object with a call to ExcelDnaUtil.Application.

Excel process still runs in background

I'm reading some data from a sheet of an excel file using interop library. I get the data just fine by using Microsoft.Office.Interop.Excel and then reading all data in the sheet.
Application ExcelApp = new Excel.Application();
Workbook excelWorkbook = ExcelApp2.Workbooks.Open(excelFileNamePath);
_Worksheet excelWorksheet = excelWorkbook.Sheets[excelSheetName];
Range excelRange = excelWorksheet.UsedRange;
//...for loops for reading data
ExcelApp.Quit();
But after my application terminates, I tried to edit my excel file and had some problems while opening. Apparently the excel process keeps on running in the background even though I called ExcelApp.Quit(). Is there a way to properly close the excel file that the application uses? I'm new to c# so i'm probably missing something here.
Edit: Solved! Apparently there's a rule for com objects that discourages using 2 dots.
Excel.Application ExcelApp2 = new Excel.Application();
Excel.Workbooks excelWorkbooks = ExcelApp2.Workbooks;
Excel.Workbook excelWorkbook = excelWorkbooks.Open(excelFileName);
Excel._Worksheet excelWorksheet = excelWorkbook.Sheets[excelSheetName];
//...
excelWorkbook.Close();
Marshal.ReleaseComObject(excelWorkbook);
Marshal.ReleaseComObject(excelWorksheet);
Marshal.ReleaseComObject(excelRange);
ExcelApp2.Quit();
There was another similar question - and answer (https://stackoverflow.com/a/17367570/3063884), in which the solution was to avoid using double-dot notation. Instead, define variables for each object used along the way, and individually use Marshal.ReleaseComObject on each one.
Copying straight from the linked solution:
var workbook = excel.Workbooks.Open(/*params*/)
---> instead use -->
var workbooks = excel.Workbooks;
var workbook = workbooks.Open(/*params*/)
Then, when done, release each COM object:
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excel);
Long time no answer but what worked for me was to call the GC.Collect(); from the caller,
i.e. instead of
main()
{
...
doexcelstuff();
...
}
void doexcelstuff()
{
Excel.Application ExApp2 = new Excel.Application();
Excel.Workbook excelWb = ExApp2 .Workbooks.Open(excelFName);
Excel._Worksheet excelWorksheet = excelWb.Sheets[excelSName];
//...
excelWb.Close();
ExApp2.Quit();
Marshal.ReleaseComObject(excelWb);
Marshal.ReleaseComObject(excelWorksheet);
Marshal.ReleaseComObject(ExApp2);
excelWb = null;
excelWorksheet= null;
ExApp2= null;
GC.Collect();
}
Using above Excel does not die
but a very small change, to where the GC is called from
main()
{
...
doexcelstuff();
GC.Collect(); // <<-- moved the GC to here (the caller)
...
}
void doexcelstuff()
{
Excel.Application ExApp2 = new Excel.Application();
Excel.Workbook excelWb = ExApp2 .Workbooks.Open(excelFName);
Excel._Worksheet excelWorksheet = excelWb.Sheets[excelSName];
//...
excelWb.Close();
ExApp2.Quit();
Marshal.ReleaseComObject(excelWb);
Marshal.ReleaseComObject(excelWorksheet);
Marshal.ReleaseComObject(ExApp2);
excelWb = null;
excelWorksheet= null;
ExApp2= null;
// removed the GC from here
}
My guess is the garbage collector needs to also quietly clean up internally created temp values (including refs/pointers) from the heap - some of which I guess in this case are pointing to COM objects.
(Just takes a smidgen of understanding of how machines work underneath the source code.)
You are not closing your workbook. Close it and then release it before quitting the Excel application:
excelWorkbook.close();
Marshal.ReleaseComObject(excelWorkbook);
ExcelApp.Quit();
For me this worked!
//Initializing
Application excelApp = new Application();
Workbook excelWorkbook = excelApp.Workbooks.Open(pathExcelFile, 0, true, 5, "", "",
true, XlPlatform.xlWindows, "\t", false, false, 0,
true, 1, 0);
Worksheet excelWorksheet = (Worksheet)excelWorkbook.Sheets[1];
//closing
excelWorksheet = null;
excelWorkbook.Close();
excelWorkbook = null;
excelApp.Quit();
excelApp = null;
Interop is notoriously buggy... I use the following method after saving my workbook, and no longer have issues with Excel remaining open when I exit my applications:
while (Marshal.ReleaseComObject(wb) > 0);
while (Marshal.ReleaseComObject(xl) > 0);
wb = null;
xl = null;
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
wb is my workbook object, and xl is my Excel.Application object.
For me this worked :
//opening
var excelFile = new Application();
Workbook workBook1 = excelFile.Workbooks.Open(goldenCopy_path);
Workbook workBook2 = excelFile.Workbooks.Open(new_path);
Worksheet goldWorkSheet, newWorkSheet;
goldWorkSheet = workBook1.Worksheets[1];
newWorkSheet = workBook2.Worksheets[1];
//closing
//it will release the workbook from visual studio
goldWorkSheet = null;
newWorkSheet = null;
workBook1.Close();
workBook2.Close();
workBook1 = null;
workBook2 = null;
excelFile.Quit();
excelFile = null;
This code worked on me.
Excel.Application excelApp = null;
Excel.Workbooks excelWorkbooks = null;
Excel.Workbook excelWorkbook = null;
Excel._Worksheet xlWorkSheet = null;
Excel.Range range = null;
excelApp = new Excel.Application();
excelWorkbooks = excelApp.Workbooks;
excelWorkbook = excelWorkbooks.Open(excelName);
xlWorkSheet = (Excel.Worksheet)excelWorkbook.ActiveSheet;
range = xlWorkSheet.Range["C3"] ;
range.Value = "Update Data";
Marshal.ReleaseComObject(range);
xlWorkSheet.SaveAs(path);
Marshal.ReleaseComObject(xlWorkSheet);
excelWorkbook.Close();
Marshal.ReleaseComObject(excelWorkbook);
excelWorkbooks.Close();
Marshal.ReleaseComObject(excelWorkbooks);
excelApp.Quit();
Marshal.ReleaseComObject(excelApp);

creating excel sheet and writind data into it

I am working on writing the data into Excel sheet in c#.
I have wriiten the following code.
string excel_filename = #"C:\Users\Downloads\bookmain.xlsx";
Excel.Application excel = new Excel.Application();
excel.Visible = true;
Excel.Workbook wb = excel.Workbooks.Open(excel_filename);
Excel.Worksheet sh = wb.Sheets.Add();
sh.Name = "TestSheet";
sh.Cells[1, "A"].Value2 = "SNO";
sh.Cells[1, "B"].Value2 = "Name";
sh.Cells[1, "C"].Value2 = "ID";
for (int i = 0; i < 2; i++)
{
sh.Cells[i+2, "A"].Value2 = "1";
sh.Cells[i+2, "B"].Value2 = "A";
sh.Cells[i+2, "C"].Value2 = "1122";
}
wb.Save();
excel.Quit();
Here I have given the path of excel file that already exists and it is empty.
How to change this code that, when i give the path it should automatically check, if it exists it have to create otherwise no need to create.
Even my code also need to check sheet name, it it exist i shall directly edit it or else I need to create a new sheet.
Can any one share their response.
Thank you.
for checking existence of file :
if(!File.Exists(excel_filename))
{
//if not exists then only create:-
}
and for checking worksheet you can do like :
foreach (Sheet sheet in workbook.Sheets)
{
if (sheet.Name.equals("Test"))
{
//do something
}
}
UPDATED :
this is how it works :
Create Excel object
Excel.Application excel = new Excel.Application();
make Excel visible
excel.visible = true
add a worksheet
Excel.Worksheet sh = wb.Sheets.Add();
save it as
wb .SaveAs( #"C:\Users\Downloads\bookmain.xlsx",
Excel.XlFileFormat.xlXMLSpreadsheet, missing, missing,
false, false, Excel.XlSaveAsAccessMode.xlNoChange,
missing, missing, missing, missing, missing);

.Net Excel Interop Deleting a worksheet

I'm trying to delete a worksheet from a excel document from a .Net c# 3.5 application with the interop Excel class (for excel 2003).
I try many things like :
Worksheet worksheet = (Worksheet)workbook.Worksheets[1];
worksheet.Delete();
It's doesn't work and doesn't throw any error ...
After more than one hour looking I found the answer:
xlApp.DisplayAlerts = false;
worksheet.Delete();
xlApp.DisplayAlerts = true;
When dealing with deleting Excel Worksheets, there are two important things to know:
Excel interop counts from 1 (and not from zero), therefore, removing the second item will cause the third item to take its place!. so, the proper way to remove worksheets is from the last to the first:
// Remove LAST worksheet
MyWorkBook.Worksheets[3].Delete();
// and only then remove the second (which is the last one)
MyWorkBook.Worksheets[2].Delete();
alternatively, you can delete the second item ([2]) on the list twice, which will give you the same result.
The following line will throw exception when you only got one worksheet left:
MyWorkBook.Worksheets[1].Delete();
It is also important to note that the workbook must contain at least one worksheet; this means you cannot delete all worksheets in a workbook.
Microsoft.Office.Interop.Excel.Worksheet worksheet = Microsoft.Office.Interop.Excel.Worksheet)xlWorkBook.Worksheets[1];
worksheet.Delete();
Try to find worksheet by name:
var app = new Microsoft.Office.Interop.Excel.Application();
var workbook = app.Workbooks.Add();
((Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets["Sheet3"]).Delete();
we can delete the work sheet like this
Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null)
{
return;
}
xlApp.DisplayAlerts = false;
string filePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
+ "\\Sample.xlsx";
Excel.Workbook xlWorkBook = xlApp.Workbooks.Open(filePath, 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Excel.Sheets worksheets = xlWorkBook.Worksheets;
worksheets[4].Delete();
worksheets[3].Delete();
xlWorkBook.Save();
xlWorkBook.Close();
releaseObject(worksheets);
releaseObject(xlWorkBook);
releaseObject(xlApp);
and use this
static void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
obj = null;
throw ex;
}
finally
{
GC.Collect();
}
}
We delete excel worksheets from a c# console application like this:
Microsoft.Office.Interop.Excel.Worksheet worksheet =
(Worksheet)workbook.Worksheets["Worksheet_Name" (or) "Countings"];
worksheet.Delete();

Categories