tags:

views:

832

answers:

4

I have an winforms application that loads in excel files for analysis. Currently, in order to open the excel file the file must not be already open in excel otherwise a FileIOException is thrown when I try and load in the file.

What I would like to do is allow my application to read in the file even if it is open in excel rather than forcing the user to close down the worksheet first. Note that the application in question only needs to read the file, not write to it.

Is this possible?

+2  A: 

How are you trying to open the file?

If you are trying to open it for read/write then you'll get the exception. If you are trying to open it for read only then you should be OK.

var file = File.Open("file.xls", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

This will only work if Excel has opened the file with FileShare.Read set to allow other applications (i.e. your's) to have access to the file. If this isn't set then Excel will have opened the file with exclusive access. Note: I don't think this is the case as you can open an Excel file (in Excel) for read if someone else has it open for edit.

UPDATE - OK I didn't test this properly until after darin's comments. You need the FileShare.ReadWrite flag despite the help indicating that it's for subsequent file openers. Not even FileShare.Read is good enough, which I find even odder.

ChrisF
This is not correct. Using FileShare.Read means: "open this file for me only if any prior openers have opened it for Read." which is not the case because Excel opened it for writing.
Darin Dimitrov
@darin - I'm not using FileShare.
ChrisF
Good answer. Indeed, Excel files are not opened with exclusive access, so this method is quite possible.
Noldorin
File.Open uses it behind the scenes with FileShare.None which won't work.
Darin Dimitrov
This code doesn't work for me. I get an exception.
Darin Dimitrov
@darin - point taken - answer updated
ChrisF
+9  A: 

You could try passing FileShare.ReadWrite when opening the file:

using (var stream = new FileStream(
       @"d:\myfile.xls", 
       FileMode.Open, 
       FileAccess.Read, 
       FileShare.ReadWrite))
{

}
Darin Dimitrov
I think the FileShare flag is for the other case - when you want to allow other applications to have access to the file
ChrisF
This from the meta data: "Contains constants for controlling the kind of access other System.IO.FileStream objects can have to the same file"
ChrisF
In the case of future openers, a FileShare.Read means "future openers can open the file for reading". In the case of past openers, FileShare.Read means "open this file for me only if it has past openers that opened it for reading only". That's why FileShare.ReadWrite needs to be used here, because Excel opens the file for writing.
Darin Dimitrov
I didn't find that in the documentation I saw - you learn something new everyday.
ChrisF
A: 

Try making a copy of the already opened file, read it and discard it. In order to check if the file is already opened, try reading and handle the exception by doing the copy, read, discard.

tzup
A: 

SpreadsheetGear for .NET can read workbooks while Excel has them open. Here is the code we use to do it (note that we lock the entire file after opening to keep Excel or any other app from writing while we are in the middle of reading):

stream = new System.IO.FileStream(path,
    System.IO.FileMode.Open,
    System.IO.FileAccess.Read,
    System.IO.FileShare.ReadWrite,
    SG.CompoundDocumentIO.Storage.OpenBufferLength);
try
{
    stream.Lock(0, stream.Length);
}
catch
{
    // .NET 1.1 requires cast to IDisposable
    ((IDisposable)stream).Dispose();
    throw;
}

Disclaimer: I own SpreadsheetGear LLC

Joe Erickson