tags:

views:

793

answers:

1

I have an existing Windows C++ application that links to ATL. I need to open an existing Excel file and access some properties. One of the things I need to do is determine if the user is currently viewing the Excel file.

We can assume that the user has Excel installed, although not sure which version.

What is the C++ / COM code to attach to an existing Excel file? How do I determine if the file is currently open by an instance of Excel? Assume I know the filename. I googled around for 15 minutes but haven't found out how to do this without MFC.

+3  A: 

Nice challenge. And because a challenge cannot be refused I sat in front of Visual Studio and here is a possible solution.

#include <windows.h>
#include <iostream>

using namespace std;

#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE11\\MSO.DLL" \
    rename("RGB", "MSORGB") \
    rename("DocumentProperties", "MSDocumentProperties")

using namespace Office;

#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"

using namespace VBIDE;

#import "C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE" \
    rename("DialogBox", "ExcelDialogBox" ) \
    rename("RGB", "ExcelRGB") \
    rename("CopyFile", "ExcelCopyFile") \
    rename("ReplaceText", "ExcelReplaceText")

void DumpCOMError(_com_error& e) {
    wcout << L"Error:" << endl;
    wcout << L"  Code = " << hex << e.Error() << endl;
    wcout << L"  Code meaning = " << e.ErrorMessage() << endl;
    _bstr_t bstrSource(e.Source());
    _bstr_t bstrDescription(e.Description());
    wcout << L"  Source = " << bstrSource << endl;
    wcout << L"  Description = " << bstrDescription << endl;
}

HRESULT IsXlsFileOpen(LPWSTR FileName, BOOL& file_open) {
    Excel::_ApplicationPtr pApplication;
    HRESULT hr = E_FAIL;
    if (FAILED(hr = pApplication.CreateInstance(L"Excel.Application"))) {
        file_open = FALSE;
        return hr;
    }

    _variant_t  varOption(static_cast<long>(DISP_E_PARAMNOTFOUND), VT_ERROR);
    Excel::_WorkbookPtr pBook;

    try {
        pBook = pApplication->Workbooks->Open(
                        FileName, 
                        varOption,
                        varOption,
                        varOption,
                        varOption,
                        varOption,
                        varOption,
                        varOption,
                        varOption,
                        varOption,
                        varOption,
                        varOption,
                        varOption);

        file_open = pBook->ReadOnly == VARIANT_TRUE;
        pBook->Close(VARIANT_FALSE);

        hr = S_OK;
    } catch (_com_error& e) {
        file_open = FALSE;
        DumpCOMError(e);
        hr = e.Error();
    }

    pApplication->Quit();
    return hr;
}

int main(int argc, wchar_t* argv[])
{
    CoInitialize(NULL);
    {
        BOOL fileOpen;
        HRESULT hr = IsXlsFileOpen(L"f:\\temp\\treta.xls", fileOpen);
        if (SUCCEEDED(hr)) {
            cout << "File is " << (fileOpen ? "open" : "not open") << "." << endl;
        }
        cout << "IsXlsFileOpen returned: 0x" << hex << hr << endl;
    }
    CoUninitialize();

    return 0;
}


Some deserved credits are in order:

http://www.vbaexpress.com/kb/getarticle.php?kb_id=625

http://www.codeproject.com/KB/wtl/WTLExcel.aspx

http://www.codeguru.com/forum/printthread.php?s=26acdf89a1a6b79b7aa6a52e11b8d832&amp;threadid=61997

smink