代码之家  ›  专栏  ›  技术社区  ›  ChadNC

Excel OpenText方法

  •  0
  • ChadNC  · 技术社区  · 16 年前

    0x800A03EC。

    我一直在搜索,看看是否可以找到错误的具体原因,但不幸的是,代码似乎涵盖了大量可能的错误。我将复制并粘贴似乎给我带来问题的代码,希望有人能够向我提供一些关于如何解决问题的反馈。我使用的是在本文中遇到的一个名为AutoWrap的方法 kb21686 文章

    我将在此处添加该方法:

    HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, int cArgs...) {
        // Begin variable-argument list...
        va_list marker;
        va_start(marker, cArgs);
    
        if(!pDisp) {
            //MessageBox(NULL, "NULL IDispatch passed to AutoWrap()", "Error", 0x10010);
            MessageBox(NULL,_T("IDispatch error"),_T("LError"),MB_OK | MB_ICONEXCLAMATION);
            _exit(0);
        }
    
        // Variables used...
        DISPPARAMS dp = { NULL, NULL, 0, 0 };
        DISPID dispidNamed = DISPID_PROPERTYPUT;
        DISPID dispID;
        HRESULT hr;
        char buf[200];
        char szName[200];
    
    
        // Convert down to ANSI
        WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
    
        // Get DISPID for name passed...
        hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
        if(FAILED(hr)) {
            sprintf_s(buf, "IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx", szName, hr);
            MessageBox(NULL, CString(buf), _T("AutoWrap()"), MB_OK | MB_ICONEXCLAMATION);
            _exit(0);
            return hr;
        }
    
        // Allocate memory for arguments...
        VARIANT *pArgs = new VARIANT[cArgs+1];
        // Extract arguments...
        for(int i=0; i<cArgs; i++) {
            pArgs[i] = va_arg(marker, VARIANT);
        }
    
        // Build DISPPARAMS
        dp.cArgs = cArgs;
        dp.rgvarg = pArgs;
    
        // Handle special-case for property-puts!
        if(autoType & DISPATCH_PROPERTYPUT) {
            dp.cNamedArgs = 1;
            dp.rgdispidNamedArgs = &dispidNamed;
        }
    
        // Make the call!
        hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType, &dp, pvResult, NULL, NULL);
        if(FAILED(hr)) {
            sprintf_s(buf, "IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx", szName, dispID, hr);
            MessageBox(NULL, CString(buf), _T("AutoWrap()"), MB_OK | MB_ICONEXCLAMATION);
            _exit(0);
            return hr;
        }
        // End variable-argument section...
        va_end(marker);
    
        delete [] pArgs;
    
        return hr;
    }

    在我打电话之前,一切正常:

    AutoWrap(DISPATCH_PROPERTYGET, &result, pXlBooks, L"OpenText",18,param1,vtMissing,vtMissing,paramOpt,paramOpt,
                    vtMissing,vtMissing,vtMissing,paramTrue,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing
                    ,vtMissing,vtMissing);

           VARIANT param1,paramOpt,paramFalse,paramTrue;
            param1.vt = VT_BSTR;
            paramOpt.vt = VT_I2;
            paramOpt.iVal = 1;
            paramFalse.vt = VT_BOOL;
            paramFalse.boolVal = 0;
            paramTrue.vt = VT_BOOL;
            paramTrue.boolVal = 1;
            //param1.bstrVal = ::SysAllocString(L"C:\\Documents and Settings\\donaldc\\My Documents\\DepositSlip.xls");
            param1.bstrVal = ::SysAllocString(L"C:\\logs\\TestOut.txt");

    如果我取消注释注释注释掉的param1并调用Open并传递它,那么param1的版本一切都会运行得非常好。不幸的是,在OpenText方法上调用Invoke时,我得到了0x800A03EC错误代码。我在C语言中使用互操作进行自动化时发现的90%,而其他10%则在VB中做同样的事情,而C语言例子有帮助,它们不利于解释当使用C++时参数的传递。我觉得这都是参数的问题,但我很难弄清楚它们到底有什么问题。

    提前感谢您提供的任何帮助,如果我需要发布更多代码,请让我知道pelase。

    2 回复  |  直到 16 年前
        1
  •  2
  •   barrowc    16 年前

    从链接到的知识库文章:

    一个警告是如果你通过 多个参数,它们需要

    从…起 MSDN OpenText 是:

    expression.OpenText(Filename, Origin, StartRow, DataType, 
    TextQualifier, ConsecutiveDelimiter, Tab, Semicolon, Comma, 
    Space, Other, OtherChar, FieldInfo, TextVisualLayout, DecimalSeparator, 
    ThousandsSeparator, TrailingMinusNumbers, Local)
    

    所以如果 param1 Local 参数,并且您没有向 Filename 所需的参数

        2
  •  0
  •   Jan    12 年前

    我一整天都在努力,但最终还是完成了。

    代码0x800a03ec模棱两可,它的意思基本上是,(无意冒犯!),你这个笨蛋!你做了件很愚蠢的事,试着自己去发现。接近旧的“语法错误”,无需进一步说明。

    这种情况下的问题是必须将参数传递给DISPATCH_方法调用 反过来 . 显然,使用单个参数不会导致问题,许多调度调用都可以使用单个参数。

    所以,当我想打开一个只有文件名的工作簿时,一切都正常。

    AutoWrap(DISPATCH_METHOD, &Result, pExcelWorkbooks, "Open", 1, fn);
    

    但是,例如,以下代码不起作用:

    _variant_t fn("MyExcelBook.xlsx"), updatelinks(0), readonly(true);
    VARIANT Result;
    hr = Autowrap(DISPATCH_METHOD, &Result, pExcelWorkbooks, "Open", 3, fn, updatelinks, readonly);
    

    要在不重写所有调用的情况下对此进行修改,应按如下方式扩展AutoWrap函数:

    // Allocate memory for arguments..
    VARIANT * pArgs = new VARIANT[cArgs + 1];
    // Extract arguments..
    if (autoType & DISPATCH_METHOD)
    {   // reverse (variable) DISPATCH parameters after cArgs
        for (int i = 1; i <= cArgs; i++)
            pArgs[cArgs-i] = va_arg(marker, VARIANT);
    }
    else
    {
        for (int i = 0; i < cArgs; i++)
            pArgs[i] = va_arg(marker, VARIANT);
    }
    

    (仅显示相关部分,整个方法见前面的帖子)。

    所以现在我调用C++版本的工作簿。

    _variant_t fn("MyExcelBook.xlsx"), updatelinks(0), readonly(true), optional(DISP_E_PARAMNOTFOUND, VT_ERROR);
    VARIANT Result; readonly,
    hr = Autowrap(DISPATCH_METHOD, &Result, pExcelWorkbooks, "Open", 7, fn, updatelinks,
            optional, optional, optional, readonly);
    //  copy the dispatch pointer to the workbook pointer
    if (Result.vt == VT_DISPATCH)
    {
        pExcelWorkbook = Result.pdispVal;
        //  save the workbook pointer to close it later if needed
        if (pExcelWorkbook)
            IDworkBooks.push_back(pExcelWorkbook);
    }
    

    正如您所看到的,您不必像在某些VB代码和C#中那样填写您无论如何都不会使用的尾部选项。

    快乐编码, 简