【问题标题】:How to count the words of a ms word 97-2003 doc file with c++?如何用 c++ 计算 ms word 97-2003 doc 文件的字数?
【发布时间】:2015-02-27 04:57:50
【问题描述】:

我刚刚学了一点COM,我知道VBA编程是基于MS提供的COM组件。但我现在不知道如何用 c++ 编程 office,因为我不知道如何为我的 c++ 程序导入类型库或其他东西。这是我的代码来计算一个doc文件的单词,但是失败了,你能帮我纠正一下吗,谢谢。

#include <objbase.h>
#include <stdio.h>
#include <assert.h>
#include <atlbase.h>
#include <atlconv.h>
#pragma comment(lib, "ole32.lib")
//0002095C-0000-0000-C000-000000000046

IID IID_Words = { 0x0002095C, 0x0000, 0x0000, {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }
//#import "msword.olb" how???
IDispatch* GetWordsInterface(LPCWSTR wszFileName);

int main()
{
    IDispatch *pDisp = NULL;
    LPOLESTR pwszFuncName = L"Count";
    DISPID dispID;
    HRESULT hr;

    pDisp = GetWordsInterface(L"D:\\test.doc");
    assert( pDisp != NULL );

    hr = pDisp->GetIDsOfNames( IID_NULL, &pwszFuncName, 1, LOCALE_SYSTEM_DEFAULT, &dispID );
    assert( hr == S_OK );

    VARIANT result;
    hr = pDisp->Invoke(
            dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET,
            NULL, &result, NULL, NULL);
    assert( hr == S_OK );

    printf("the count of words is %ld \n", result.dblVal);

    return 0;
}

IDispatch* GetWordsInterface(LPCWSTR pwszFileName)
{
    HRESULT hr = S_FALSE;
    IBindCtx *pbc = NULL;
    IMoniker *pMk = NULL;
    LPWSTR strClsid = NULL;
    LPWSTR strDisplayName = NULL;
    IUnknown *pUnk = NULL;
    IDispatch *pWords = NULL;
    CLSID clsid;

    hr = CoInitialize(NULL);
    assert( hr == S_OK );

    hr = CreateBindCtx( 0, &pbc );
    assert( pbc != NULL &&  hr == S_OK );

    hr = CreateFileMoniker(pwszFileName, &pMk);
    assert( hr == S_OK && pMk != NULL );

    hr = pMk->GetClassID(&clsid);
    assert( hr == S_OK );
    StringFromCLSID(clsid, &strClsid);
    wprintf(L"CLSID : %s\n", strClsid);
    CoTaskMemFree(strClsid);

    hr = pMk->GetDisplayName(pbc, NULL, &strDisplayName);
    assert( hr == S_OK && strDisplayName != NULL );
    CW2A ascii(strDisplayName);
    printf("Display Name : %s\n", ascii);
    //wprintf(L"Display Name : %s\n", strDisplayName);
    CoTaskMemFree(strDisplayName);

    hr = pMk->BindToObject(pbc, NULL, IID_IUnknown, (void**)&pUnk);
    assert( hr == S_OK && pUnk != NULL );


    hr = pUnk->QueryInterface(IID_Words, (void**)&pWords); // FAILED HERE
    assert( hr == S_OK && pWords != NULL );

    pUnk->Release();
    pMk->Release();
    return pWords;
}

【问题讨论】:

    标签: c++ com ms-word word-count


    【解决方案1】:

    这是正确的版本,原版失败是因为 Document 对象不支持 Words 接口,但我设法通过 Document._Document(interface) Words(property) 获取 Words 接口指针。

    // excelmoniker.cpp : 
    //
    #include "stdafx.h"
    
    //0002095C-0000-0000-C000-000000000046
    IID IID_Words = { 0x0002095C, 0x0000, 0x0000, {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
    //_DocumentInterface
    IID IID_innerDocument = { 0x0002096B, 0x0000, 0x0000, {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
    IDispatch* GetWordsInterface(LPCWSTR wszFileName);
    IDispatch* SubGetWordsInterface(IDispatch *pDoc);
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        IDispatch *pWords = NULL;
        LPOLESTR pwszFuncName = L"Count";
        DISPID dispID;
        HRESULT hr;
        DISPPARAMS dispParams = { NULL, NULL, 0, 0 };
        VARIANT result;
    
        hr = CoInitialize(NULL);
        assert( hr == S_OK );
    
        pWords = GetWordsInterface(L"D:\\test.doc");
        assert( pWords != NULL );
    
        hr = pWords->GetIDsOfNames( IID_NULL, &pwszFuncName, 1, LOCALE_SYSTEM_DEFAULT, &dispID );
        assert( hr == S_OK );
    
        hr = pWords->Invoke(
            dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET,
            &dispParams, &result, NULL, NULL);
        assert( hr == S_OK );
    
        printf("the count of words is %ld \n", result.dblVal);
    
        assert( pWords->Release() == 0 );
    
        CoUninitialize();
        return 0;
    }
    
    IDispatch* GetWordsInterface(LPCWSTR pwszFileName)
    {
        HRESULT hr = S_FALSE;
        IBindCtx *pbc = NULL;
        IMoniker *pMk = NULL;
        LPWSTR strClsid = NULL;
        LPWSTR strDisplayName = NULL;
        IDispatch *pDoc = NULL;
        IDispatch *pWords = NULL;
        CLSID clsid;
    
    
        hr = CreateBindCtx( 0, &pbc );
        assert( pbc != NULL &&  hr == S_OK );
    
        //Test for the clsid for the doc
        hr = GetClassFile(pwszFileName, &clsid);
        assert( hr == S_OK );
        StringFromCLSID(clsid, &strClsid);
        wprintf(L"associated file CLSID : %s\n", strClsid);
        CoTaskMemFree(strClsid);
    
        hr = CreateFileMoniker(pwszFileName, &pMk);
        assert( hr == S_OK && pMk != NULL );
    
        hr = pMk->GetClassID(&clsid);
        assert( hr == S_OK );
        StringFromCLSID(clsid, &strClsid);
        wprintf(L"CLSID : %s\n", strClsid);
        CoTaskMemFree(strClsid);
    
        hr = pMk->GetDisplayName(pbc, NULL, &strDisplayName);
        assert( hr == S_OK && strDisplayName != NULL );
        CW2A ascii(strDisplayName);
        printf("Display Name : %s\n", ascii);
        //wprintf(L"Display Name : %s\n", strDisplayName);
        CoTaskMemFree(strDisplayName);
    
        //Get _Document Interface pointer
        hr = pMk->BindToObject(pbc, NULL, IID_innerDocument, (void**)&pDoc);
        assert( hr == S_OK && pDoc != NULL );
    
        //Get _Words interface pointer
        pWords = SubGetWordsInterface(pDoc);
    
        assert( pMk->Release() == 0 );
        assert( pDoc->Release() == 0 );
        assert( pbc->Release() == 0 );
    
        return pWords;
    }
    
    IDispatch* SubGetWordsInterface(IDispatch* pDoc)
    {
        LPOLESTR pwszFuncName = L"Words";
        DISPID dispID;
        HRESULT hr;
        DISPPARAMS dispParams = { NULL, NULL, 0, 0 };
        VARIANT result;
    
        memset(&result, 0, sizeof(VARIANT));
    
        hr = pDoc->GetIDsOfNames( IID_NULL, &pwszFuncName, 1, LOCALE_SYSTEM_DEFAULT, &dispID );
        assert( hr == S_OK );
    
        hr = pDoc->Invoke( dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dispParams, &result, NULL, NULL);
        assert( hr == S_OK && result.vt == VT_DISPATCH && result.ppdispVal != NULL );
    
        return (IDispatch*)result.ppdispVal;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-23
      • 1970-01-01
      相关资源
      最近更新 更多