Check for already opened file

Hello,

is there a way to check whether an Excel-file is opened by a different user, e.g. on a file that is on a network drive?

I know, I can open an Excel file in Gembox.Spreadsheet even though it is already opened in Excel, but as soon as I try to save it, I get the expected “System.IO.IOException” because the file is used by a different process. I’d like to avoid this by pointing this out to the user already on opening the file.

I cannot find anything in the document properties or protection settings, that fits my need. Would you please help me?

Cheers,

Frank

Hi Frank,

The reason why GemBox.Spreadsheet is able to read the file, even though it’s opened in an Excel application, is because it’s reading it with something like this stream:

using (var stream = File.Open("input.xlsx", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    var workbook = ExcelFile.Load(stream, LoadOptions.XlsxDefault);
    // ...
}

So, what you need to do is open the file without the FileShare.Write or FileShare.ReadWrite flag.
For example, try this (the File.OpenRead uses FileShare.Read value):

try
{
    ExcelFile workbook;
    using (var stream = File.OpenRead("input.xlsx"))
        workbook = ExcelFile.Load(stream, LoadOptions.XlsxDefault);
    // TODO ...
}
catch (IOException e)
{
    Console.WriteLine(e.Message);
}

Does this solve your issue?

Regards,
Mario

Hi Mario,

actually this does not solve the issue (100%).
One could use something like this to check before opening the file for write access. But there is a small chance that someone opens the file after my program checks the file status and opens the excel file for writing. So the check does not work 100%.

I’m more looking for something like the Workbook.UserStatus Property from
Microsoft.Office.Interop.Excel. I want to check after I opened the file. Maybe even tell the user something about the one using the file.

I played around with the file access/share rights a little and I stumbled on a behaviour, I’m not able to explain. Maybe you can.

// --- 1.) This one works, when no other programm opened the given excel file  ------------------
// Otherwise it failes when saving - which is to be expected
var workbook = ExcelFile.Load(excelFileName, LoadOptions.XlsxDefault);
workbook.Save(excelFileName);
// ------------------------------------------------------------------------------------------------------
// --- 2.) This one is not working, even though no other program is accessing the file ------------
// Exception on workbook.Save -->  The process cannot access the file <excelFileName> because it is being used by another process.
// I think, this one should work. The file stream is opened with FileAccess.ReadWrite.
using (var stream = File.Open(excelFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
                var workbook = ExcelFile.Load(stream, LoadOptions.XlsxDefault);
                workbook.Save(excelFileName);
}
// --------------------------------------------------------------------------------------------------------

Why is the second solution with the stream raising an exception?

Cheers Frank

Hi Frank,

First, regarding the issue you have, it occurs because you’re using FileAccess.ReadWrite.
Try setting that to FileAccess.Read.

Now regarding the Workbook.UserStatus property, that is information from the Microsoft Excel application itself, that is not a part of the XLSX file.

Anyway, if you’re concerned about someone opening the file after you loaded it into ExcelFile then what you could do is keep that stream from File.OpenRead("input.xlsx") undisposed until you decide to save the ExcelFile object.

For example, something like this:

try
{
    var stream = File.OpenRead("input.xlsx");
    var workbook = ExcelFile.Load(stream, LoadOptions.XlsxDefault);

    // TODO ...

    stream.Dispose();
    workbook.Save("input.xlsx");
}
catch (IOException e)
{
    Console.WriteLine(e.Message);
}

Regards,
Mario