"Access denied" when saving an ExcelPackage created from a FileInfo object

Aug 14, 2012 at 10:13 PM

I create an ExcelPackage by specifying a FileInfo object to a spreadsheet that exists in my user's temporary folder (C:\users\<username>\AppData\Local\Temp on Win7), make changes to the spreadsheet, and call ExcelPackage.Save().  The Save() call throws an InvalidOperationException, with an inner exception saying "Error overwriting file", with an inner UnauthorizedAccessException, "Access to path '...' is denied".

The same user and application created the file we're trying to edit with ExcelPackage, so the permission should not be an issue.

The same end result occurs if I create a Read/Write FileStream for the existing file and specify that in the ExcelPackage constructor.

The big picture of what I'm trying to do is to create a new spreadsheet based on a template (embedded as a resource), modify its contents, and save it.  The only way I've gotten this to work is to provide ExcelPackage's constructor with both a Stream to the embedded resource and a FileStream (OpenOrCreate, Read/Write) for the output file.  This is much less convenient because not only do I now have to worry about an open stream, an open file handle, and an ExcelPackage, all of which need to be disposed of properly, but I also cannot edit a template if it already exists.

Why doesn't specifying a FileInfo object work?

Aug 16, 2012 at 2:00 PM

I found the issue, and the issue was mine.

Let me explain what I was doing, because it may help someone else that is migrating code from using traditional COM Microsoft Excel objects to using EPPlus.
Before migrating to EPPlus, what I was doing was creating a copy of a spreadsheet, that is an embedded resource, in the user's temp folder.  The key (problem) was that I was also setting the file attribute ReadOnly.  I would then modify the contents of that spreadsheet in code (adding data to it) and "open" it in Excel (by using the old "worksheet.Application.Visible = true" method) to display the data to the user.

The reason I set the file to ReadOnly was so that when Excel opened, it would have the data (modifications), but the user wouldn't be able to save the file, requiring them to "SaveAs" (the user would be prompted to SaveAs when closing Excel) and pick a location for the file.
This allowed me to run the "report" and show it to the user without 1) requiring the user to take the extra step to save it if they were only interested in viewing it and discarding it and 2) without having to save the modifications to disk (in the user's temp folder) if it's not going to be kept.  It sounds like a lot of unnecessary steps, but it really did result in a much cleaner experience for the user, especially if they were only interested in viewing the data real quick, without having to spend time browsing to a location in which to save it.

So, of course, when I migrated the code to use EPPlus, I was still setting the ReadOnly file attribute, causing it to bomb when it tired to "overwrite" (delete) the file.

Coming from using the COM objects, I also wasn't cognizant of the fact that EPPlus *has to* work differently.  It doesn't keep an open file handle, and writing modifications as they're made (like how you may be used to if coming from using the COM objects), but it reads the entire file contents into memory, makes modifications in memory, and then writes it all back to disk (hence the delete when doing a Save).

If anyone has any comments or would like to discuss this further, be my guest, but for those who are actively working on EPPlus, please consider this a non-issue/resolved.

Thanks!