Sudarshan's Blog

My Thoughts, Findings & Experiences

Excel Application Object – Unexpected Behavior

August 28, 2011 09:35

In my last article ‘’, I have explained why we choose to use Excel Application object for excel automation and its disposing mechanism. But, while testing we observed following unexpected behavior:

If we start processing multiple Excel files through windows service (like 25 to 50):

  1. For few files, it threw exception related to COM Interop. The exception does not have any details and it only says ‘File can be accessed’ even though file exists at correct location.
  2. For few files, it starts processing excel file. But the file processing never ends and its associated Excel process was alive too. (You can see ‘Excel’ process in ‘Task Manager’)

There is no solution for above 2 issues (or at least we are not able to find any yet).

So, beware while using Excel Application object in your application!

P.S.: Because of unreliable behavior of Excel Application Objet, we are thinking of using some other third party solution for Excel automation.

Excel Application Object–Expects ‘Desktop’ folder under certain paths

August 16, 2011 06:25

In my last article ‘’, I have explained why we choose to use Excel Application object for excel automation and its disposing mechanism. But, while testing we were getting following exception:

Microsoft Excel cannot access the file '<file path>'. There are several possible reasons:

• The file name or path does not exist.
• The file is being used by another program.
• The workbook you are trying to save has the same name as a currently open workbook.:    at Microsoft.Office.Interop.Excel.Workbooks.Open(String Filename, Object UpdateLinks, Object ReadOnly, Object Format, Object Password, Object WriteResPassword, Object IgnoreReadOnlyRecommended, Object Origin, Object Delimiter, Object Editable, Object Notify, Object Converter, Object AddToMru, Object Local, Object CorruptLoad)

But, file exists at that location.

After spending hours, I am able to find solution for this weird issue.

Basically solution is to create ‘Desktop’ folder under following paths on your machine:

If your machine is 64-bit then
- C:\Windows\SysWOW64\config\systemprofile

If your machine is 32-bit then
- C:\Windows\System32\config\systemprofile

 

My machine is 64-bit and I was already having ‘Desktop’ folder under ‘C:\Windows\SysWOW64\config\systemprofile’, but still it was not working.
Just to try out I created ‘Desktop’ folder under ‘C:\Windows\System32\config\systemprofile’ (which was not exist) on my machine.

And Bingo! Problem is solved. Exception went away and it is updating excel file correctly.

Really strange but it worked!

Looks like it creates some temporary file under ‘Desktop’ folder. But not too sure. Also it has something to do with under which user credentials it runs the windows service and excel application object.

Note: Paths may vary on your machine depending on where ‘windows’ folder reside.

I got idea for this solution from following 2 articles:

http://social.msdn.microsoft.com/Forums/en-US/innovateonoffice/thread/b81a3c4e-62db-488b-af06-44421818ef91?prof=required

Another solution: (but this requires registry changes – which is not preferred to do it on production machine)
http://social.technet.microsoft.com/Forums/en-US/office2007deploymentcompatibility/thread/334c9f30-4e27-4904-9e71-abfc65975e23

Happy Programming!

Disposing Excel Application object correctly

August 15, 2011 07:46

On one of our recent project, we need to process lots of Excel files in windows service. Basic requirement was: we need to read excel file from specific folders, perform some operations, do additional calculations on data which we read from excel file and then write some additional data to existing excel file.

We started with using OLEDB as first and safe choice. But issue with OLEDB is, you cannot alter existing file structure. That means in our case we cannot add new columns to the existing excel file. So, we left OLEDB option.

Now, the only solution available is to use Excel Application object which is part of Office Interop assemblies. Using this you can modify existing Excel files.

But, issue with this is: even though you execute code ‘Quit()’ method on Excel Application object, .Net does not dispose that Excel Application object. It will remain there in memory until you close your application. In our application, we are handling excel processing through windows service, so if we process 10 files then 10 excel objects will be created and they will reside in the memory. One can see those objects in Task Manager. Those objects will remain there until we stop Windows Service which creates these objects.

This is scary because we can’t stop Windows Service. If we don’t stop Windows Service then Excel objects will pile in the memory and at some point application will throw insufficient memory exception.

Another thing that surprised us is Microsoft suggests not to use Office objects in Automation. Here is what they say “Developers can use Automation in Microsoft Office to build custom solutions that use the capabilities and the features that are built into the Office product. Although such programmatic development can be implemented on a client system with relative ease, a number of complications can occur if Automation takes place from server-side code such as Microsoft Active Server Pages (ASP), ASP.NET, DCOM, or a Windows NT service.” in article http://support.microsoft.com/kb/257757

But for us using Excel Application object is the only option, so finally we come with following solution to dispose Excel Application object:

 

   1: public bool UpdateExcelFile(string filePath)
   2: {
   3:     Workbook workbook = null;
   4:     Worksheet worksheet = null;
   5:     Range worksheetCells = null;
   6:     Range usedRange = null;
   7:     Range cells = null;
   8:     Range columns = null;
   9:  
  10:     var excelApplication = new Application { DisplayAlerts = false };
  11:     
  12:     try
  13:     {
  14:         if (!File.Exists(filePath))
  15:             throw new ApplicationException("File does not exists");
  16:  
  17:         workbook = Open(excelApplication, filePath);
  18:         if (workbook == null)
  19:             throw new ApplicationException("File cannot be opened");
  20:  
  21:         var sheetIndex = GetSheetIndex(workbook, "SOV INPUT");
  22:         worksheet = workbook.Sheets[sheetIndex];
  23:         worksheetCells = worksheet.Cells;
  24:         usedRange = worksheet.UsedRange;
  25:         cells = usedRange.Cells;
  26:         columns = cells.Columns;
  27:  
  28:         // Perform file operations like adding new columns, 
  29:         // set values for new columns
  30:         
  31:         return true;
  32:     }
  33:     catch (Exception ex)
  34:     {
  35:         Logger.ErrorFormat("Error occurred while updating excel file {0} {1} : {2}", filePath, ex.Message, ex.StackTrace);
  36:         return false;
  37:     }
  38:     finally
  39:     {
  40:         GC.Collect();
  41:         GC.WaitForPendingFinalizers();
  42:         if (workbook != null)
  43:         {
  44:             if (columns != null) Marshal.ReleaseComObject(columns);
  45:             if (cells != null) Marshal.ReleaseComObject(cells);
  46:             if (usedRange != null) Marshal.ReleaseComObject(usedRange);
  47:             if (worksheetCells != null) Marshal.ReleaseComObject(worksheetCells);
  48:             if (worksheet != null) Marshal.FinalReleaseComObject(worksheet);
  49:             workbook.Close();
  50:             Marshal.FinalReleaseComObject(workbook);
  51:         }
  52:  
  53:         excelApplication.Quit();
  54:         Marshal.FinalReleaseComObject(excelApplication);
  55:     }
  56: }

 

As shown in solution: (Check ‘finally’ section)

  • You need to explicitly release reference for COM objects that you have created like
    1. Workbook
    2. Worksheet
    3. Worksheet cells

Only then ‘Quit()’ method on Excel Application object will dispose Excel Application object immediately.

Now, we can use Excel Application object safely within Windows Service. Thank you to my team member Selva for doing research on this.

Happy Programming!