merrymonk has asked for the wisdom of the Perl Monks concerning the following question:

Every time I implement a new application that involves writing a spreadsheet I seem to ask the following question.
”Is there a way of telling if a spreadsheet of the same name I want to write to is already open (usually by Excel)?”
It has happened again!
I know that one possible way is to try and open and write a test file of the same name.
I guess this may work but it always seems unsatisfactory.
Excel itself can tell. Therefore, I wondered if any wise Monk knew how to use Perl to ‘look’ at what Excel uses to get the answer to the ‘is this spreadsheet open’ question.

Replies are listed 'Best First'.
Re: Is an Excel spreadsheet open?
by Corion (Patriarch) on Feb 10, 2010 at 15:10 UTC

    I'd ask Excel, through Win32::OLE. Most likely, iterating over Application.Workbooks or somesuch should yield all filenames of all open files.

      Thanks for that. I looked in the link and found enum for all objects and thought that may give what I wanted.
      Therefore I wrote some Perl (below) to test it.
      Unfortunately, the count was always zero no matter how many Excel files were open.
      Googling for Excel and Enum, I did find a site where someone was trying gain access to a file by requesting a handle to it.
      I thought that this may give what I wanted on the basis that it would only return a handle if the file was there but not opened.
      I can easily test if a file is there – if it is not it cannot be open.
      This is also in the Perl code below. Unfortunately this did not work either since it always returned a handle and if the file was not open, it opened Excel with a ‘blank’ screen.
      Can anyone give me a clue as to what to do next?
      use OLE; use Win32::OLE::Const "Microsoft Excel"; use strict "vars"; my ($Count, $file, $ML); $Count = Win32::OLE->EnumAllObjects(sub { my $Object = shift; my $Class = Win32::OLE->QueryObjectType($Object); printf "# Object=%s Class=%s\n", $Object, $Class; }); print "count <$Count>\n"; $file = "C:\\abcd.xlsx"; $ML = Win32::OLE->GetObject($file) or print "can't get a handle on '$file'"; print "$ML\n";

        Again, why don't you ask Excel about its open files?

        # From memory, as I don't have Excel at hand currently use Win32::OLE 'in'; my $excel = Win32::OLE->CreateObject('Excel.Application'); for my $wb (in($excel->{Workbooks})) { print $wb->{Filename},"\n"; };
Re: Is an Excel spreadsheet open?
by davies (Monsignor) on Feb 10, 2010 at 19:28 UTC
    "Excel itself can tell" - true, but which Excel? I typically run several instances of Excel, and you will have to inspect them all to answer your question. Gargling tells me that EnumAllObjects gives only those that are already bound to Win32::OLE. I can't see any way of persuading GetActiveObject to return any instance of Excel apart from the first one it encounters. So, until you can put that in a loop to find all instances of Excel, I fear you are stuck with your test file approach. I don't like it either and could write the code for a single instance of Excel, but multiple instances are so common that I don't think you can ignore them. And Sod's Law is immutable - the last instance you find will always be the one that has the file open. I also agree with you about the impenetrability of the Win32::OLE docs.

    Regards,

    John Davies