Closing an open excel workbook in C# - c#

There is one issue that I have been having, and I am trying to fix it because if the program crashes (the excel file stays open in the background), or the user has the excel workbook already open the program will crash because it is unable to open an already opened workbook.
Was trying to counter this issue by using the method from this question : C#: How can I open and close an Excel workbook?
But much to my dismay no success.
With this setup I get an error at wb.Close(true) saying I cannot use an unassigned local variable. To me it kind of makes sense, but I don't see how that is the case. It's not like an if statement where if the condition isn't met it doesn't jump in the loop. The try block will always execute.
Excel.Workbook wb;
try
{
wb = exApp.Workbooks.Open(#file);
}
catch (Exception)
{
wb.Close(true);
}
I also tried this way :
Excel.Workbook wb = new Excel.Workbook();
try
{
wb = exApp.Workbooks.Open(#file);
}
catch (Exception)
{
wb.Close(true);
}
but this time, I get a error: 80040154 Class not registered on the line Excel.Workbook wb = new Excel.Workbook(); when running the program. again... don't know why.
Any help is greatly appreciated.

Try this:
Excel.Workbook wb = null;
try
{
wb = exApp.Workbooks.Open(#file);
}
catch (Exception)
{
if (wb != null) wb.Close(true);
}

You want finally instead of catch. A finally block will always execute, whether there is an exception or not. Even if there isn't an Exception thrown, you still want to close the workbook to clear up the resources.
Something like this should be what you need.
Excel.Workbook wb = new Excel.Workbook();
try {
wb = exApp.Workbooks.Open(#file);
//More code...
}
catch (Exception ex) {
// Do any error handling you need/want to here.
}
finally {
// If there's a way to determine if the workbook is open, try that first.
wb.Close(true);
}

Related

C# : Close Excel file without popup

So basically my app triggers an excel macro, from a file, that updates the file and then closes it.
When I open the file I set the "DisplayAlerts = false" variable in order to ignore all popups and it works as expected in my computer... however, a colleague of mine tried to use it and for every file, he gets the popup asking if he wants to save all changes...
Checked other questions about the popups in excel but all suggested solutions use "oBook.Saved = true;" or "oBook.Close(false);", but these did not work for me.
my code is as follows:
using Microsoft.Office.Interop.Excel;
public static bool Trigger_Macro_From_File(string path)
{
ApplicationClass oExcel = null;
Workbook oBook = null;
try
{
string filename = Path.GetFileName(path);
string macro_name = "!some_macro";
string macro = #"'" + filename + #"'" + macro_name;
// Create an instance of Microsoft Excel
oExcel = new ApplicationClass
{
DisplayAlerts = false,
Visible = false
};
oBook = oExcel.Workbooks.Open(path);
RunMacro(oExcel, new Object[] { macro });
oBook.Save();
oBook.Saved = true;
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
oBook?.Close(false);
System.Runtime.InteropServices.Marshal.ReleaseComObject(oBook);
oBook = null;
oExcel?.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel);
oExcel = null;
GC.Collect();
}
}
Does anyone know anything about this?
Thanks in advance.
You could double-check that no other "Microsoft Excel" process is running in the Task Manager.
Let's say at some point in your development process you started your program and open the workbook with something like
xlWorkbook = xlApp.Workbooks.Open(filePath);
Then you encountered an exception for some reason, and killed the program without closing the file properly (workbook.Close(..), app.Quit(..) and so on).
The Microsoft Excel process is still running in the background, and has a handle on the file you want to edit. So you cannot execute an instruction that saves the file under the same name. This is why the popup is appearing.
This scenario is taken from the point of view of the developer, but the same behavior could have happened on your coworker's computer if your app crashed without quitting properly, and gets re-started.
Also, be careful that finally statement might not always be executed, so double-check which scenario could cause your app to close without releasing the COM object.

C# - Excel - Office Interop - Exception HRESULT 0x80010100 (RPC_E_SYS_CALL_FAILED)

I have a Windows forms application that runs an excel macro using Office Interop.
I run the macro from the main GUI thread but the macro is pretty long to run and after several minutes it ends up in an exception RPC_E_SYS_CALL_FAILED.
Any ideas?
Exception is : System call failed. (Exception from HRESULT: 0x80010100 (RPC_E_SYS_CALL_FAILED))
My code :
// Excel Objects
Excel.Application xlApp = null;
Excel.Workbook xlWorkBookMacro = null;
Excel.Workbook xlWorkBookBilan = null;
try
{
// Open Excel
xlApp = new Microsoft.Office.Interop.Excel.Application();
// Open Workbooks
xlWorkBookMacro = xlApp.Workbooks.Open(Properties.Settings.Default.PathToMacroBilan);
xlWorkBookBilan = xlApp.Workbooks.Open(Path.Combine(Folder, Filename));
// Run Macro
xlApp.Run(MacroName, Filename, DateBilan.AddHours(HEURE_DEBUT_BILAN).ToString("dd/MM/yyyy HH:mm:ss"), int.Parse(ScheduleRec["no_batch"].ToString()), int.Parse(ScheduleRec["no_oper"].ToString()), int.Parse(ScheduleRec["type_activ"].ToString()), Path.Combine(RepertoireEnrSous, EnrSous), ScheduleRec["edition"].ToString(), ScheduleRec["imprimante"].ToString(), ScheduleRec["orientation"].ToString());
// Close Workbooks
xlWorkBookBilan.Close(true);
xlWorkBookMacro.Close(false);
// Close Excel
xlApp.Quit();
// Clean Excel Objects
ReleaseExcelObject(xlApp);
ReleaseExcelObject(xlWorkBookBilan);
ReleaseExcelObject(xlWorkBookMacro);
}
catch (Exception ex)
{
TraceLogger.WriteLog(String.Format("Exception : {0}", ex.Message));
}
I finally found a solution in adding a DoEvents in the main loop of my macro.

C# Excel - How to switch to existing Worksheet and edit it?

So I open an existing Excel Application with a few Worksheets and add one Worksheet and edit it. That works perfectly fine.
Now I try to switch to another Worksheet to edit this one. Code here:
Excel.Worksheet OptimaPruefliste = OptimaWorkbook.Worksheets.get_Item(1);
OptimaPruefliste.Activate();
try
{
OptimaPruefliste.Range["A1:ZZ9999"].Borders.LineStyle = true;
OptimaPruefliste.Range["A1:ZZ9999"].Interior.Color = XlRgbColor.rgbWhite;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
It doesn´t throw an exception and it does get "OptimaPruefliste" as active sheet but it just doesn´t change anything.
So these three lines did the job:
OptimaPruefliste = (Worksheet)OptimaExcelApp.Worksheets.get_Item(1);
OptimaPruefliste.Activate();
OptimaPruefliste = OptimaExcelApp.ActiveSheet as Excel.Worksheet;

System.Runtime.InteropServices error when exporting dataGridView to Excel workbook

I have an application that displays certain database data, and includes a function to save that data to an excel workbook on request using the Microsoft.Office.Interop.Excel assembly. One of my users reports the following error when trying to save to an excel workbook:
System.Runtime.InteropServices.COMException (0x8002000B): Invalid index. (Exception from HRESULT: 0x8002000B (DISP_E_BADINDEX))
at Microsoft.Office.Interop.Excel.Sheets.get__Default(Object Index)
at WorkCalendar.Form1.saveBtn_Click(Object sender, EventArgs e)
We've verified that he does have Excel 2013 installed and all of the necessary assemblies came through ok according to the full exception details, so I hope one of you can shed some light on what's going on here.
Here's the saveBtn_Click event method mentioned in the error above (edited for conciseness)
private void saveBtn_Click(object sender, EventArgs e)
{
// creating Excel Application
_Application app = new Microsoft.Office.Interop.Excel.Application();
_Workbook workbook;
_Worksheet worksheet;
string fetchString = fetch.ToString("HH.mm.ss");
try
{
// Check for existing workbook and add new page
}
catch
{
// If no workbook found, create a brand new one
workbook = app.Workbooks.Add(Type.Missing);
worksheet = null;
worksheet = workbook.Sheets["Sheet1"];
}
try
{
// do not show the excel sheet being created
app.Visible = false;
worksheet = workbook.ActiveSheet;
worksheet.Name = fetchString;
// Get dataGridView data, insert it into the excel worksheet and format it
}
catch { }
finally
{
// save the application
// Exit from the application
app.Quit();
}
}
As I said, the application works fine on my and other computers on which it's been tested. Any ideas?
EDIT: Altered code example slightly to show the method looking for an existing workbook, and creating one if no workbook found.

Microsoft.Office.Interop.Excel for Office 2007

I want to try the Windows form application that converts a office file (Excel, Word, Powerpoint) into a PDF file.
My client's PC will not install Visual Studio and Office version is 2007.
My application uses Microsoft.Office.Iterop.Excel.dll to covert to the PDF format.
This dll file cannot be found on my client's PC and an error has occurred as following.
System.AugumentException: Value does not fall within the expected range.
at Microsoft.Office.Interop.Excel._Workbook.ExportAsFixedFromat(.......)
How can I solve this problem?
My code is following
public bool ExportWorkbookToPdf(string workbookPath, string outputPath)
{
// If either required string is null or empty, stop and bail out
if (string.IsNullOrEmpty(workbookPath) || string.IsNullOrEmpty(outputPath))
{
return false;
}
// Create COM Objects
Microsoft.Office.Interop.Excel.Application excelApplication;
Microsoft.Office.Interop.Excel.Workbook excelWorkbook;
// Create new instance of Excel
excelApplication = new Microsoft.Office.Interop.Excel.Application();
// Make the process invisible to the user
excelApplication.ScreenUpdating = false;
// Make the process silent
excelApplication.DisplayAlerts = false;
// Open the workbook that you wish to export to PDF
excelWorkbook = excelApplication.Workbooks.Open(workbookPath);
MessageBox.Show(workbookPath);
// If the workbook failed to open, stop, clean up, and bail out
if (excelWorkbook == null)
{
excelApplication.Quit();
excelApplication = null;
excelWorkbook = null;
MessageBox.Show("in null");
return false;
}
var exportSuccessful = true;
try
{
// Call Excel's native export function (valid in Office 2007 and Office 2010, AFAIK)
excelWorkbook.ExportAsFixedFormat(Microsoft.Office.Interop.Excel.XlFixedFormatType.xlTypePDF, outputPath);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
// Mark the export as failed for the return value...
exportSuccessful = false;
// Do something with any exceptions here, if you wish...
// MessageBox.Show...
}
finally
{
// Close the workbook, quit the Excel, and clean up regardless of the results...
excelWorkbook.Close();
excelApplication.Quit();
excelApplication = null;
excelWorkbook = null;
}
// You can use the following method to automatically open the PDF after export if you wish
// Make sure that the file actually exists first...
if (System.IO.File.Exists(outputPath))
{
MessageBox.Show(outputPath);
System.Diagnostics.Process.Start(outputPath);
}
return exportSuccessful;
}
As already said in the comments, each client needs to install the 2007 Microsoft Office Add-in: Microsoft Save as PDF. It doesn't matter if you are on Windows 8.1 or have any PDF reader installed. You need that Add-in to write PDFs with Office 2007. (You don't need any Add-In with Office 2010 or 2013.)

Categories