How to read open excel file at C# - c#

I want to read already open excel file with C#. I am using this method but it can't read the excel file while the file is open in Microsoft excel.
FileStream stream = File.Open("myfile.xlsx", FileMode.Open, FileAccess.Read);
It gives IOException: The process cannot access the file 'myfile.xlsx' because it is being used by another process.
I hope you understands what I mean. I want to keep excel file open and while file is open at Microsoft excel i want to read it from C#. I am using C# net framework 4.0

You need to open it with FileShare.ReadWrite:
FileStream stream = File.Open("myfile.xlsx", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
See this answer.

I think you can still copy the file while excel has it open, so you could make a copy of the file and then open that. Just make sure you clean up after yourself when you are done with the copy.

You could use the Interop library to use the already opened instance of Excel.
oExcel == (Excel.Application) System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")

You can try the File.Open with a fourth parameter - fileShare.
FileStream stream = File.Open("myfile.xlsx", FileMode.Open, FileAccess.Read, FileShare.Read);
You may need to specify write access also.

To ensure that correct opening and closing of the file please look at using the c# using statements
using (FileStream stream = File.Open("myfile.xlsx", FileMode.Open, FileAccess.Read))
{
}

To open the same file more than once at the same time, it needs to be opened in shared mode.
Hope this may help others.

Related

Open an Excel file in C# as read-only whilst file is open in Excel

I'm writing a application which converts data from an excel file into an XML file for another application. You make some changes to the excel file, save them, load them in my C# forms application as readonly and then save the resultant xml. Only problem is, this is a very iterative process and at the moment my application throws an exception if the file is open in excel. So to get it to work, you have to shut down excel (or close file), run application, then reopen excel.
My code is this;
using (var stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
which causes a IO Exception.
Oh, just found the answer; Change the last argument to FileShare.ReadWrite

File can´t rewritten because other process uses the file

I´ve written some code to send files as attachments of .eml files with C#.
I create the files in an Windows temp folder and attach them to a .eml file.
The .eml files are simply opened and send through Process.Start(filename); with the standard mailing program in windows. If the users wishes to send the file again, the file will be rewritten from the database to make sure its the newest version. Now to my problem: Randomly a few times or after just the first time I rewrite the file the error appears
The process cannot access the file because it is being used by another process
I acutally did some research on the web and found this other question. So I made sure like mentioned there, that the FileStream is set correctly with all arguments.var fs = new FileStream(tempPathSave, FileMode.Open, FileAccess.Write, FileShare.ReadWrite) Has someone an idea what is the reason for my problem? My biggest problem is, that I can´t really duplicate it to say it is happening when I do this or that.
EDIT: I am using the FileStream in an using statement to make sure that it is disposed right.
It is hard to properly understand what the problem is without actually seeing the code but from my experience you are not properly disposing the filestream object so it keeps a handle to the file
var fs = new FileStream(tempPathSave, FileMode.Open, FileAccess.Write, FileShare.ReadWrite)
So when you are done using your filestream, call
fs.Dispose();
which will dispose your filestream properly.
Moreover, you can use syntatic sugar, using which will automatically dispose your object
using(var fs = new FileStream(tempPathSave, FileMode.Open, FileAccess.Write, FileShare.ReadWrite)){
// use fs here
// STUFF
} //at the end fs will be disposed
I´ve found a solution for my problem. I just changed the FileStream to MemoryStream because the MailMessage constructor can handle a stream, too. The only point there is, that you have to keep the MemoryStream open until the .eml file is saved. And more important you have to watch out about the memory usage und make sure the afterwards every MemoryStream will be disposed.

Opening and reading a file which is open in Excel

It is possible to use a FileShare value of FileShare.ReadWrite to open a file for reading, while it is already open in other programs (e.g. like Excel). e.g.:
using (FileStream fs = new FileStream(#"c:\abd\somefile.xlsx",
FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
// read file, etc.
}
Just wondering if this a good idea. e.g. in worst case, what will happen if the external program is writing to the file, and your code is trying to read it at the same time ?
I have noticed libraries like spreadsheet gear that can read files even when they are open in Excel - are they basically hoping that they will be able to read the whole file into memory before any part of it is changed ?

After saving xlsx file using NPOI, when I open xlsx file, it says file corrupt

xlWorksheet.GetRow(1).GetCell(2).SetCellValue("Hello");
using (FileStream file = new FileStream("Test.xlsx", FileMode.Create, FileAccess.Write))
{
XLWorkBook.Write(file);
file.Close();
}
I used this code to write excel file. After writing the excel, when I open excel file manually it is corrupted.
I am using NPOI binary 2.1.3.1
Please tell how to avoid excel getting corrupted.
Try adding file.Flush(); before file.Close();:
xlWorksheet.GetRow(1).GetCell(2).SetCellValue("Hello");
using (FileStream file = new FileStream("Test.xlsx", FileMode.Create, FileAccess.Write))
{
XLWorkBook.Write(file);
file.Flush();
file.Close();
}
I would not recommend using file.Close() in a repeat loop.
Plus, I would recommend opening the file, doing the looping, and then flushing and closing the file.
This method is much better time-wise because repeatedly opening and closing a file consumes a lot of time and requires a trip to the drive every time.

How do I open a file that is opened in another application

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?
You could try passing FileShare.ReadWrite when opening the file:
using (var stream = new FileStream(
#"d:\myfile.xls",
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
{
}
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.
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
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.

Categories