none
C++ Excel COM Automation - Workbook.SaveAs - Member not found RRS feed

  • Question

  • We recently noticed problems in our MFC legacy application, wherever we try to call Workbook.SaveAs, this call fails on machines which are a using an older version of Office than our development machines. I think I have narrowed down the problem to changes in the Excel type library, somewhere between 16.0.4549.1000 and 16.0.9029.2106 a new optional parameter was added to the SaveAs method.

    However, I am stumped as to why the change impacts us this time where it has never in the past 10+ years with similar changes to the type library. We use the following directives for import:

    // MSO
    #import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52"  \
    		no_dual_interfaces \
    		rename("RGB", "OfficeRGB") \
    		rename("SearchPath", "OfficeSearchPath")
    
    // VBA
    #import "libid:0002E157-0000-0000-C000-000000000046" \
    		no_dual_interfaces
    
    // Excel
    #import "libid:00020813-0000-0000-C000-000000000046" \
    		no_dual_interfaces \
    		rename("RGB", "ExcelRGB") \
    		rename("DialogBox", "ExcelDialogBox") \
    		rename("CopyFile", "ExcelCopyFile") \
    		rename("ReplaceText", "ExcelReplaceText")

    To my understanding, using "no_dual_interfaces" ensures that all calls of the generated wrapper methods are made through IDispatch, therefore using late binding, which should exactly solve the problem of modified methods in the type library. Or am I mistaken in that assumption?

    Example code illustrating the problem:

    // create Excel instance
    Excel::_ApplicationPtr excelApp;
    excelApp.CreateInstance(_T("Excel.Application"));
    
    // add a new workbook
    Excel::WorkbooksPtr workbooks = excelApp->GetWorkbooks();
    Excel::_WorkbookPtr workbook = workbooks->Add();
    workbook->Activate();
    
    // insert data
    // ...
    
    // save the workbook to the temp directory
    TCHAR lpTempPath[MAX_PATH];
    GetTempPath(MAX_PATH, lpTempPath);
    COleVariant filename(CString(lpTempPath) + _T("ExcelAutomation"));
    workbook->SaveAs(filename, vtMissing, vtMissing, vtMissing, VARIANT_FALSE, VARIANT_FALSE, Excel::xlNoChange, vtMissing, VARIANT_FALSE);

    Our SaveAs call only supplies parameters that have been supported for ages, all the newer parameters remain on their default value of vtMissing. Are we missing anything in expecting this call to work in the described scenario regardless of the exact Office version in use at the place of execution?

    with regards,

    Tobias


    • Edited by twolf_chsoft Thursday, November 15, 2018 3:43 PM Formatting
    Thursday, November 15, 2018 3:41 PM