首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DSOFramer在另一个窗口关闭Excel。如果文件中未保存数据,则dsoframer无法使用“尝试访问无效地址”打开。

DSOFramer在另一个窗口关闭Excel。如果文件中未保存数据,则dsoframer无法使用“尝试访问无效地址”打开。
EN

Stack Overflow用户
提问于 2008-10-30 21:56:34
回答 3查看 5.5K关注 0票数 4

我使用Microsoft's DSOFramer控件,允许我在对话框中嵌入一个Excel文件,这样用户就可以选择他的工作表,然后选择他的单元格范围;它与对话框上的导入按钮一起使用。

问题是,当我调用DSOFramer's OPEN函数时,如果我在另一个窗口中打开了Excel,它就会关闭Excel文档(但会继续运行)。如果它试图关闭的文档有未保存的数据,我将在另一个窗口中得到一个关闭Excel文档的对话框。如果未保存在文件中的数据,dsoframer无法使用messagebox:Attempt to access invalid address打开。

我构建了源代码,并逐步完成了它在其CDsoDocObject::CreateFromFile函数中的调用,在类IMoniker的对象上调用BindToObjectHR0x8001010a The message filter indicated that the application is busy。在此情况下,它试图通过InstantiateDocObjectServer classid of CLSID Microsoft工作表.这在HRESULT of 0x80040154 Class not registered中失败。InstantiateDocObjectServer只是在classid上调用CoCreateInstance,首先使用CLSCTX_LOCAL_SERVER,然后(如果失败)使用CLSCTX_INPROC_SERVER

我知道DSOFramer是一个流行的示例项目,用于在各种对话框和表单中嵌入Office应用程序。我希望有其他人有这个问题,并可能有一些洞察力,我如何能解决这个问题。我真的不希望它关闭任何其他打开的Excel文档,如果它由于未保存的数据而无法关闭文档,我真的不希望它出错。

更新1:我尝试过更改传入Excel.ApplicationExcel.Application(我知道该类会解决),但没有成功。在CDsoDocObject中,它试图打开键HKEY_CLASSES_ROOT\CLSID\{00024500-0000-0000-C000-000000000046}\DocObject,但失败了。我已经在视觉上确认了该密钥不在我的注册表中;该密钥用于指南,但没有DocObject子项。然后生成一个错误消息框:The associated COM server does not support ActiveX document embedding。当我尝试使用Excel.Workbook programid时,我会得到类似的结果(当然,不同的键)。

Excel 2:我尝试启动第二个实例,希望我的自动化将绑定到它(最近调用的),而不是问题Excel实例,但它似乎没有这样做。结果一致。我的问题似乎归结为这样:我在类BindToObject IMoniker**,的对象上调用,并接收** 0x8001010A (RPC_E_SERVERCALL_RETRYLATER) The message filter indicated that the application is busy**.我试着玩传递给** BindToObject 的旗帜(通过),但是似乎没有什么不同。

更新3:它首先尝试使用IMoniker类绑定。如果失败,它将调用用于CoCreateInstance clsid 的作为 fallback 方法。这可能适用于其他MS Office对象,但当它是Excel时,类则用于工作表。我将示例修改为CoCreateInstance _Application**,,然后获取工作簿,然后为目标文件调用** Workbooks::Open ,该文件返回一个工作表对象。然后,我返回该指针,并与原始示例代码路径合并。都开始工作了。

EN

回答 3

Stack Overflow用户

发布于 2008-11-14 21:22:28

假设您正在使用DSOFRAMER项目,则需要在第348行左右的dsofdocobj.cpp函数中将此代码添加到CreateFromFile函数中:

代码语言:javascript
复制
CLSID clsidExcelWS;
hr = CLSIDFromProgID(OLESTR("Excel.Sheet"),clsidExcelWS);                   
if (FAILED(hr)) return hr;

if (clsid == clsidExcelWS)
{
    hr = InstantiateAndLoadExcel(pwszFile, &pole);
    if (FAILED(hr)) return hr;
}
else
{
    <the IMoniker::BindToObject call and it's failure handling from the "stock" sample goes here>
}

然后,在CDsoDocObject中定义以下新成员函数:

代码语言:javascript
复制
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::InstantiateAndLoadExcel (protected)
//
//  Create an instance of Excel and load the target file into its worksheet
//
STDMETHODIMP CDsoDocObject::InstantiateAndLoadExcel(LPWSTR pwszFile, IOleObject **ppole)
{
    IUnknown *punkApp=NULL;
    Excel::_Application *app=NULL;
    Excel::Workbooks *wbList=NULL;
    Excel::_Workbook *wb;

    CLSID   clsidExcel;
    HRESULT hr = CLSIDFromProgID(OLESTR("Excel.Application"), &clsidExcel);
    if (FAILED(hr)) 
        return hr;

    hr = CoCreateInstance(clsidExcel, NULL, CLSCTX_LOCAL_SERVER,  IID_IUnknown, (void**)&punkApp);
    if (SUCCEEDED(hr)) 
    {
        hr = punkApp->QueryInterface(__uuidof(Excel::_Application),(LPVOID *)&app);
        if (SUCCEEDED(hr))
        {
            hr = app->get_Workbooks(&wbList);

            VARIANT vNoParam;
            VariantInit(&vNoParam);
            V_VT(&vNoParam) = VT_ERROR;
            V_ERROR(&vNoParam) = DISP_E_PARAMNOTFOUND;

            VARIANT vReadOnly;
            VariantInit(&vReadOnly);
            V_VT(&vReadOnly) = VT_BOOL;
            V_BOOL(&vReadOnly) = VARIANT_TRUE;

            BSTR bstrFilename = SysAllocString(pwszFile);

            hr = wbList->Open(bstrFilename, vNoParam,vNoParam,vNoParam,vNoParam,vReadOnly,vNoParam,vNoParam,vNoParam,vNoParam,vNoParam,vNoParam,vNoParam,0,&wb);
            if (SUCCEEDED(hr))
                hr = wb->QueryInterface(IID_IOleObject, (void**)ppole);

            VariantClear(&vReadOnly);
            VariantClear(&vNoParam);
            SysFreeString(bstrFilename);
        }
    }

    if (wb != NULL) wb->Release();
    if (wbList != NULL) wbList->Release();
    if (app != NULL) app->Release();
    if (punkApp != NULL) punkApp->Release();

    return hr;
}
票数 0
EN

Stack Overflow用户

发布于 2008-11-17 17:28:07

@Jinjin

  1. 您可以使用#
  2. 指令导入Excel文件。这将生成(并自动包含包含_Application结构(以及所需的其他结构)的Excel _Application文件)。理想情况下,您应该找到一个与您希望支持的最早Excel版本相匹配的OLB文件。本地系统上的一个可能在c:\Program \Microsoft\ Office 12中(假定您已经安装了Office 2007 )。它可能被命名为Excel.olb,或者XL5EN32.OLB (很明显,如果您还没有安装Excel的美国英语版本的话,of就不同了。)

因此,将.olb文件复制到您的项目源目录,然后在源文件的顶部为#import "XL5EN32.olb“添加一行。

  • 是的,打开旧版本。确保这种情况的最佳方法是找到一个OLB文件(在上面的第1项中提到),该文件来自Excel的安装,这是您希望支持的最早版本。我使用Office 2000中的Excel9.olb。我对Excel版本的测试一直到Office 2007的最新版本都很好。

  • 是的,在进行这些更改之后,您应该正常使用dsoframer。

  • 恐怕由于雇主的限制,我不能这么做。但是,如果您使用“股”dsoframer项目,进行本文第1部分中描述的更改,以及我在前面的文章中描述的更改,那么您几乎完全重新创建了我所拥有的。
票数 0
EN

Stack Overflow用户

发布于 2008-11-18 17:43:05

@Jinjin:您是否将导入语句(#import "XL5EN32.olb")放在使用Excel::_Application的cpp文件中?如果不是那样做..。不能只是把它添加到项目中。如果您已经这样做了,请尝试将此语句添加到cpp文件中,在cpp文件中使用这些映射#import "Debug\XL5EN32.tlh“。tlh文件是通过运行#import生成的头文件;您应该在Debug目录中找到它(假设您正在执行Debug构建)。

将_Application重命名为Application (和其他应用程序)并不是正确的方法。_Application结构是具有映射的结构。这就是为什么您没有找到应用程序->get_Workbooks。

您正在查找的是什么文件,您正在查找的是应用程序,而不是_Application?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/251909

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档