• VC操纵Word


    我们操纵Word需要通过类型库中的MFC类。而这些类,应该都是基于一个叫COleDispatchDriver的类。至少我所了解到的都是这样。

    COleDispatchDriver没有基类。COleDispatchDriver类实现OLE自动化中的客户方。OLE调度接口为访问一个对 象的方法和属性提供了途径。COleDispatchDriver的成员函数连接,分离,创建和释放一个IDispatch类型的调度连接。其它的成员函 数使用变量参数列表来简化调用IDispatch::Invoke。

    学习如何自动化控制 Word、Excel 和 Powerpoint 的对象模型的最佳方法是使用这些 Office 应用程序中的宏录制器:

    1. 工具 菜单上的 选项中选择录制新宏 ,然后执行您感兴趣的任务。
    2. 工具 菜单上的 选项中选择停止录制 。
    3. 完成录制后,从工具 菜单上的 选项中选择 ,选择您录制的宏,然后单击编辑 。

    您将看到生成的 VBA 代码,该代码可完成您所录制的任务。记住,录制的宏在大多数情况下并 是最佳代码,但它可以提供快捷可用的示例。

    Application :代表 Microsoft Word 应用程序。Application 对象包含可返回最高级对象的属性和方法。例如,ActiveDocument 属性可返回当前活动的Document 对象。

    Documents :由 Word 当前打开的所有 Document(文档) 对象所组成的集合。

    Document :代表一篇文档。Document 对象是 Documents 集合中的一个元素。Documents 集合包含 Word 当前打开的所有 Document 对象。

    Selection: 该对象代表窗口或窗格中的当前所选内容。所选内容代表文档中被选定(或突出显示的)的区域,若文档中没有所选内容,则代表插入点。每个文档窗格只能有一个活动的 Selection 对象,并且整个应用程序中只能有一个活动的 Selection 对象。

    例子1 :

    #include "msword9.h" //为了使代码集中,方便阅读,所以把头文件放到了这里
    void CStep1Dlg::OnOK() 
    {
    _Application app; //定义一个WORD的应用对象
    if(!app.CreateDispatch(_T("Word.Application"))) //启动WORD
    {
       AfxMessageBox(_T("居然你连OFFICE都没有安装吗?"));
       return;
    }
    AfxMessageBox(_T("WORD 已经运行启动啦,你可以用Ctrl+Alt+Del查看"));
    app.SetVisible(TRUE); //设置WORD可见。
            //当然,如果你想要悄悄地调用WORD的功能,则注释掉这条语句
    AfxMessageBox(_T("现在你已经看到WORD的程序界面了吧"));
    AfxMessageBox(_T("WORD准备要退出啦"));
    VARIANT SaveChanges,OriginalFormat,RouteDocument; //定义调用QUIT时使用的参数
    SaveChanges.vt=VT_BOOL;     //设置退出WORD时候的保存参数
    SaveChanges.boolVal=VARIANT_FALSE; //为不保存任何文档,模板及设置
    ::VariantInit(&OriginalFormat);   //清空变量
    RouteDocument.vt=VT_EMPTY;    //清空变量的另一种方法
    //调用Quit退出WORD应用程序。当然不调用也可以,那样的话WORD还在运行着那
    app.Quit(&SaveChanges,&OriginalFormat,&RouteDocument);
    app.ReleaseDispatch();   //释放对象指针。切记,必须调用
    AfxMessageBox(_T("Step1执行完成。接着请学习Setp2"));
    }

    例子2:

    #include "msword9.h"
    #include <AtlBase.h> //新增加了一个头文件,为使用CComVariant替代VARIANT做准备
    
    void CStep2Dlg::OnOK() 
    {
    //以下3行代码,同Step1。就不解释啦
    _Application app;
    //为了简单,没有判断返回值。如果没有成功,记得检查你有没有AfxOleInit()呀?
    app.CreateDispatch(_T("Word.Application"));
    app.SetVisible(TRUE);      
    AfxMessageBox(_T("WORD已经启动,现在要退出啦"));
    AfxMessageBox(_T("怎么和Step1没有什么区别呀?"));
    AfxMessageBox(_T("嘿嘿,是没什么区别,但是使用方式简单了很多呀。看看源程序吧"));
    //准备调用_Application::Quit函数了,需要定义3个参数。
    //但是,这次我们使用CComVariant,这是一个模板类。
    //在定义的时候直接调用带参数的构造函数,比VARIANT使用简单多了吧
    CComVariant SaveChanges(false),OriginalFormat,RouteDocument;
    //使用 CComVariant 的不带参数的构造函数,默认就是使用VT_EMPTY,设置为空类型
    //另外,除了CComVariant,你还可以使用COleVariant和_variant_t,但我个人最喜欢前者
    app.Quit(&SaveChanges,&OriginalFormat,&RouteDocument);
    app.ReleaseDispatch();
    AfxMessageBox(_T("下面该学习Setp3了"));
    }

    例子3:

    #include "msword9.h"
    #include <AtlBase.h>
    
    void CStep3Dlg::OnOK() 
    {
    ////////////// 这次,我们要控制在WORD中输入一些字符了 /////////////////////
    /************* WORD 录制的宏,新建一个空文档,然后输入一些文字 ************
        Documents.Add Template:= _
            "C:/Documents and Settings/Administrator/Application Data/Microsoft/Templates/Normal.dot" _
            , NewTemplate:=False, DocumentType:=0
        Selection.TypeText Text:="HELLO"
        Selection.TypeParagraph
        Selection.TypeText Text:="大家好"
    ***************************************************************************/
    _Application app;
    app.CreateDispatch(_T("Word.Application"));
    app.SetVisible(TRUE);
    AfxMessageBox(_T("看好了,就要新建一个空白文档了"));
    //通过WORD宏可以知道,由于要使用Documents,于是我们定义一个并从app中取得
    Documents docs=app.GetDocuments();
    //准备调用Documents::Add函数了,需要定义4个参数。
    //从WORD宏可以看出来3个参数的类型为:
    //Template字符,NewTemplate布尔,DocumentType数值
    //但Add函数还需要一个参数是Visible,傻子也能看出来这个值表示是否显示出新文档
    //并且可以给默认值(VT_EMPTY)
    CComVariant Template(_T("")); //为了简单,没有使用WORD的文档模板
    CComVariant NewTemplate(false),DocumentType(0),Visible;
    docs.Add(&Template,&NewTemplate,&DocumentType,&Visible);
    AfxMessageBox(_T("下面,程序要向WORD发送字符啦"));
    //通过WORD宏可以知道,由于要使用Selection,于是我们定义一个并从app中取得
    //Selection表示输入点,即光标闪烁的那个地方
    Selection sel=app.GetSelection();
    //调用函数Selection::TypeText 向WORD发送字符
    sel.TypeText(_T("HELLO/r/n大家好呀"));
    AfxMessageBox(_T("看见了吗?我要退出啦"));
    sel.ReleaseDispatch();   //Selection 不用了,一定要释放
    docs.ReleaseDispatch();   //Documents 也不用了
    CComVariant SaveChanges(false),OriginalFormat,RouteDocument;
    app.Quit(&SaveChanges,&OriginalFormat,&RouteDocument);
    app.ReleaseDispatch();
    AfxMessageBox(_T("下面该学习Setp4了"));
    }

     

    例子4:

    #include "msword9.h"
    #include <AtlBase.h>
    
    void CStep4Dlg::OnOK() 
    {
    _Application app;
    app.CreateDispatch(_T("Word.Application"));
    app.SetVisible(TRUE);
    Documents docs=app.GetDocuments();
    CComVariant Template(_T(""));
    CComVariant NewTemplate(false),DocumentType(0),Visible;
    docs.Add(&Template,&NewTemplate,&DocumentType,&Visible);
    Selection sel=app.GetSelection();
    COleVariant varstrRange("");
    COleVariant varConfirmConversions(short(0),VT_BOOL);
    COleVariant varLink(short(0),VT_BOOL);
    COleVariant varAttachment(short(0),VT_BOOL);
    sel.InsertFile("C://My Project//WordOperator//doc//fjjb.doc",varstrRange,varConfirmConversions,varLink,varAttachment);
    sel.MoveUp(COleVariant((short)5),COleVariant((short)2),COleVariant((short)0));
    sel.TypeText("123456789 ");
    sel.MoveRight(COleVariant((short)12),COleVariant((short)1),COleVariant((short)0));
    sel.TypeText(_T("HELLO"));
    sel.MoveRight(COleVariant((short)1),COleVariant((short)1),COleVariant((short)0));
    sel.TypeText("123456789");
    AfxMessageBox(_T("好了,我要保存到c://hello.doc中了"));
    /**************** 这是在WORD中录制的新建文档直到另存的宏 *************
        Documents.Add Template:= _
            "C:/Documents and Settings/Administrator/Application Data/Microsoft/Templates/Normal.dot" _
            , NewTemplate:=False, DocumentType:=0
        Selection.TypeText Text:="Hello"
        Selection.TypeParagraph
        Selection.TypeText Text:="大家好"
        ChangeFileOpenDirectory "C:/"
        ActiveDocument.SaveAs FileName:="Hello.doc", FileFormat:=wdFormatDocument _
            , LockComments:=False, Password:="", AddToRecentFiles:=True, _
            WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
             SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _
            False
    *********************************************************************/
    
    /**************** 程序思路 ******************************************
    另存为的函数是ActiveDocument.SaveAs,显然表示的是对当前活跃的文档进行保存,
    在我们的类中没有ActiveDocument,其实它对应的是_Document,而这个可以由
    _Application 的GetActiveDocument()得到。你一定会提问:“你怎么知道的?”
    呵呵,怎么说那,我怎么知道的那?答案是:猜。其实如果使用的多了,分析、猜
    查找都是办法。如果想得到确切的方法,其实可以在VBA的书或微软的网站中搜索
    *********************************************************************/
    
    _Document doc=app.GetActiveDocument();   //得到ActiveDocument
    CComVariant FileName(_T("c://doc.wps")); //文件名
    CComVariant FileFormat(101);      //重点,看下面的说明
    CComVariant LockComments(false),Password(_T(""));
    CComVariant AddToRecentFiles(true),WritePassword(_T(""));
    CComVariant ReadOnlyRecommended(false),EmbedTrueTypeFonts(false);
    CComVariant SaveNativePictureFormat(false),SaveFormsData(false);
    CComVariant SaveAsAOCELetter(false);
    /*************** FileFormat 文件格式说明 ****************************
    参数FileFormat,在WORD的宏中,使用的是 wdFormatDocument,这是什么那?
    其实这是WORD宏中所使用的常量,由匈牙利命名可以知道wd其实是DWORD的意思
    知道了是一个正数,那么它到底是多少那?其实有一个办法可以知道,那就是在
    WORD宏程序中,加一条语句:MsgBox wdFormatDocument 这样你再运行宏程序,
    就能看到这个常量是多少了。呵呵,这个常量是0,我够聪明吧^_^
    *********************************************************************/
    doc.SaveAs(&FileName,&FileFormat,&LockComments,&Password,
       &AddToRecentFiles,&WritePassword,&ReadOnlyRecommended,
       &EmbedTrueTypeFonts,&SaveNativePictureFormat,&SaveFormsData,
       &SaveAsAOCELetter);
    
    sel.ReleaseDispatch();
    doc.ReleaseDispatch();
    docs.ReleaseDispatch();
    
    CComVariant SaveChanges(false),OriginalFormat,RouteDocument;
    app.Quit(&SaveChanges,&OriginalFormat,&RouteDocument);
    app.ReleaseDispatch();
    AfxMessageBox(_T("请检查c://hello.doc是否正常产生了。下面该学习Setp5了"));
    }

     

    例子5:

    /***************** WORD 中录制的宏,按笔画排序(全部选择,菜单表格/排序) ********
        MsgBox wdSortFieldStroke    '5      使用了常量,所以使用MsgBox得到具体的数值
        MsgBox wdSortOrderAscending '0
        MsgBox wdSortFieldSyllable '3
    MsgBox wdSeparateByTabs     '1
        MsgBox wdSimplifiedChinese '2052
        
        Selection.WholeStory   '全选
        Selection.Sort ExcludeHeader:=False, FieldNumber:="段落数", SortFieldType:= _
            wdSortFieldStroke, SortOrder:=wdSortOrderAscending, FieldNumber2:="", _
            SortFieldType2:=wdSortFieldSyllable, SortOrder2:=wdSortOrderAscending, _
            FieldNumber3:="", SortFieldType3:=wdSortFieldSyllable, SortOrder3:= _
            wdSortOrderAscending, Separator:=wdSortSeparateByTabs, SortColumn:=False, _
             CaseSensitive:=False, LanguageID:=wdSimplifiedChinese
        Selection.Copy     '把排序后的结果,复制到剪贴板
    *********************************************************************************/
    
    #include "msword9.h"
    #include <AtlBase.h>
    
    void CStep5Dlg::OnOK() 
    {
    CString str;
    GetDlgItemText(IDC_EDIT1,str);
    str.TrimLeft(); str.TrimRight();
    if(str.IsEmpty()) return;
    
    ::CoInitialize(NULL);
    _Application app;
    app.CreateDispatch(_T("Word.Application"));
    //app.SetVisible(FALSE); //这次不调用显示,因为我们要偷偷摸摸的转换:)
    Documents docs=app.GetDocuments();
    CComVariant Template(""),NewTemplate(false),DocumentType(0),Visible;
    docs.Add(&Template,&NewTemplate,&DocumentType,&Visible);
    Selection sel=app.GetSelection();
    
    for(int i=0;i<str.GetLength()/2;i++)
    { //这里只考虑了输入为纯汉字的情况,你自己修改为可以支持中英文混合的情况
       sel.TypeText(str.Mid(i*2,2)+"/r/n"); //2个字符表示一个汉字,用回车换行分隔
    }
    sel.WholeStory();   //全部选择
    
    CComVariant ExcludeHeader(false);
    CComVariant FieldNumber(_T("段落数")),SortFieldType(5),SortOrder(0);
    CComVariant FieldNumber2(_T("")),SortFieldType2(3),SortOrder2(0);
    CComVariant FieldNumber3(_T("")),SortFieldtype3(3),SortOrder3(0);
    CComVariant SortColumn(false),Separator(1),LanguageID(2052);
    CComVariant CaseSensitive(false),BidiSort,IgnoreThe;
    CComVariant IgnoreKashida,IgnoreDiacritics,IgnoreHe;
    //排序
    sel.Sort(&ExcludeHeader,&FieldNumber,&SortFieldType,&SortOrder,
       &FieldNumber2,&SortFieldType2,&SortOrder2,&FieldNumber3,
       &SortFieldtype3,&SortOrder3,&SortColumn,&Separator,
       &CaseSensitive,&BidiSort,&IgnoreThe,&IgnoreKashida,
       &IgnoreDiacritics,&IgnoreHe,&LanguageID);
    
    //其实,这里可以直接调用sel.GetText()取得文本。
    //但现在选择复制到剪贴板的方式。
    
    sel.Copy();   //复制到剪贴板
    
    if(OpenClipboard())
    { //从剪贴板取出排序后的文字
       HGLOBAL hMem=::GetClipboardData(CF_TEXT);
       LPCTSTR lp=(LPCTSTR)::GlobalLock(hMem);
       str=lp;
       ::GlobalUnlock(hMem);
    
       CloseClipboard();
    
       str.Replace("/r/n","");   //删除回车换行
       SetDlgItemText(IDC_EDIT2,str);
    }
    sel.ReleaseDispatch();
    docs.ReleaseDispatch();
    
    CComVariant SaveChanges(false),OriginalFormat,RouteDocument;
    app.Quit(&SaveChanges,&OriginalFormat,&RouteDocument);
    app.ReleaseDispatch();
    
    ::CoUninitialize();
    }

    例子6:

    #include "msword9.h"
    void CStep6Dlg::OnOK() 
    {
    CLSID clsid;
    HRESULT hr;
    hr=::CLSIDFromProgID(L"Word.Application",&clsid); //通过ProgID取得CLSID
    if(FAILED(hr))
    {
       AfxMessageBox(_T("不会吧,竟然没有安装OFFICE"));
       return;
    }
    IUnknown *pUnknown=NULL;
    IDispatch *pDispatch=NULL;
    _Application app=NULL;
    Selection sel=NULL;
    hr=::GetActiveObject(clsid,NULL,&pUnknown); //查找是否有WORD程序在运行
    if(FAILED(hr))
    {
       AfxMessageBox(_T("没有正在运行中的WORD应用程序"));
       return;
    }
    try
    {
       hr=pUnknown->QueryInterface(IID_IDispatch,(LPVOID *)&app);
       if(FAILED(hr)) throw(_T("没有取得IDispatchPtr"));
       pUnknown->Release(); pUnknown=NULL;
       sel=app.GetSelection();
       if(!sel) throw(_T("没有正在编辑的文档"));
       sel.WholeStory();     //全部选择
       CString str=sel.GetText();   //取得文本
       SetDlgItemText(IDC_EDIT1,str); //显示到编辑窗中
    }
    catch(LPCTSTR lpErr)
    {
       AfxMessageBox(lpErr);
    }
    if(pUnknown) pUnknown->Release();
    if(sel) sel.ReleaseDispatch();
    if(app) sel.ReleaseDispatch();
    }

    7、图片查找的demo(无选中功能)

    vc操纵word问题:查找到图片后如何得到该图片的长宽信息
    一个Word文档中已经有一张BMP图片。VC打开该文档,并Find查找到该图片。

    COleVariant   covTrue((short)TRUE),covFalse((short)FALSE),covOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR); 
    
    _Application   app;    //定义一个WORD的应用对象 
    app.CreateDispatch(_T("Word.Application")))    //启动WORD 
    app.SetVisible(true);                           //设置用户可见 
    Documents   docs=app.GetDocuments(); 
    docs.Open(                                         //打开文档 
                    COleVariant((LPCSTR)m_csPath,VT_BSTR), 
    covFalse,     //       确定转换       
    covTrue,     //       只读打开       
    covFalse,     //       添加到最近使用文件列表       
    covOptional,     //       PasswordDocument.       
    covOptional,     //       PasswordTemplate.       
    covFalse,     //       Revert.       
    covOptional,     //       WritePasswordDocument.       
    covOptional,     //       WritePasswordTemplate.       
    COleVariant(long(1)),       //       Format.       如果是Word97,这便是最好一个参数       
    covOptional,     //       编码             下面是Word       2000/2002专用的参数       
    covTrue)     //       可见       
                        
    Selection   sel=app.GetSelection(); 
    Find   find=sel.GetFind(); 
    find.ClearFormatting(); 
    find.Execute(                                       //开始查找图片 
    COleVariant(_T("^g"),VT_BSTR), 
    covFalse, 
    covFalse, 
    covFalse, 
    covFalse, 
    covFalse, 
    covTrue, 
    COleVariant(long(1)), 
    covFalse, 
    COleVariant("",VT_BSTR), 
    covFalse, 
    covFalse, 
    covFalse, 
    covFalse, 
    covFalse);

     8、文字查找(有选中功能)

        COleVariant   covTrue((short)TRUE),covFalse((short)FALSE),covOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR); 
        Find t_find=sel.GetFind();
        t_find.ClearFormatting();
        t_find.Execute(COleVariant(_T(""),VT_BSTR),
            covFalse,
            covFalse,
            covFalse,
            covFalse,
            covFalse,
            covTrue,
            COleVariant(long(1)),
            covFalse,
            COleVariant("",VT_BSTR),
            covFalse,
            covFalse,
            covFalse,
            covFalse,
            covFalse);

    9、带选中功能的

    void DoSelctionPicture()
    {   
    sel.MoveRight(COleVariant(
    short(1)),COleVariant(short(1)),COleVariant(short(0)));//撤销当前的选中状态。 sel.MoveLeft(COleVariant(short(1)),COleVariant(short(1)),COleVariant(short(0)));//撤销当前的选中状态。 COleVariant covTrue((short)TRUE),covFalse((short)FALSE),covOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR); Find t_find=sel.GetFind(); t_find.ClearFormatting(); t_find.Execute(COleVariant(_T("^g"),VT_BSTR), covFalse, covFalse, covFalse, covFalse, covFalse, covTrue, COleVariant(long(1)), covFalse, COleVariant("",VT_BSTR),//要替换的字符串。空 covFalse, covFalse, covFalse, covFalse, covFalse); sel.MoveRight(COleVariant(short(1)),COleVariant(short(1)),COleVariant(short(1)));//选中。bug:多选中了一个右边的字符。 }

    10、扩展

    //sel.MoveRight(COleVariant((short)1),COleVariant((short)1),COleVariant((short)1));//左移,以字为单位。
    //m_Sel.MoveDown(COleVariant((short)4),COleVariant((short)1),COleVariant((short)0));//下移,以行为单位。
    //m_Sel.MoveLeft(COleVariant((short)2),COleVariant((short)1),COleVariant((short)0));//左移,以词组为单位。
    //m_Sel.MoveLeft(COleVariant((short)1),COleVariant((short)1),COleVariant((short)0));//左移,以字为单位。
    //m_Sel.MoveStart(COleVariant((short)2),COleVariant((short)1));
    //m_Sel.MoveDown(COleVariant((short)4),COleVariant((short)1),COleVariant((short)1));//选中下移,以行为单位。
    //m_Sel.MoveLeft(COleVariant((short)2),COleVariant((short)1),COleVariant((short)1));//选中左移,以词组为单位。
    //m_Sel.MoveLeft(COleVariant((short)1),COleVariant((short)1),COleVariant((short)1));//选中左移,以字为单位。
    //m_Sel.TypeBackspace();//删除选中内容。

    11、插入图片【此部分来源:http://blog.csdn.net/halin1983/article/details/4533112

    VC++6.0向Word文件的指定位置上插入一张图片,需要用到nlineShapes类型的AddPicture方法。

    在MSDN中,该方法的声明如下:

    **************************************************************************

    在文档中添加一幅图片。返回一个 Shape 对象,该对象代表图片,并将其添加至 InlineShapes 集合。

    expression.AddPicture(FileName, LinkToFile, SaveWithDocument, Range)
    expression      必需。该表达式返回一个 InlineShapes 对象。

    FileName     String 类型,必需。图片的路径和文件名。

    LinkToFile     Variant 类型,可选。如果为 True,则将图片链接到创建该对象的文件;如果为 False,则将图片作为该文件的独立副本。默认值是 False。

    SaveWithDocument     Variant 类型,可选。如果为 True,则将链接的图片与文档一起保存。默认值是 False。

    Range     Variant 类型,可选。图片置于文本中的位置。如果该区域未折叠,那么图片将覆盖此区域,否则插入图片。如果忽略此参数,则自动放置图片

    **************************************************************************

    根据该说明的定义,第四个参数Range是用来设置图片位于文本中的位置的。因此,我们可以利用该参数向某一指定位置插入图片。具体方法如下:

     

    Selection sel=m_app.GetSelection();//获取文档的selection
    InlineShapes inlineshapes = sel.GetInlineShapes();
    inlineshapes.AddPicture("D:\abc.bmp",COleVariant((short)FALSE),COleVariant((short)TRUE),&_variant_t(sel.GetRange()));//添加图片,并制定其位置为当前光标位置
    inlineshapes.ReleaseDispatch();
    sel.ReleaseDispatch();
    
    
    //注意上面第四个参数的转换方法,用到了_variant_t变量,使用此种方法可以将LPDISPATCH转换成VARIANT*类型

     

    如此就可将图片直接插入到光标当前所在位置

    Document对象的保存功能:

    LPCWSTR pathstr=L"D:\abc.doc";
    VARIANT path;
    path.vt=VT_BSTR;
    path.bstrVal=SysAllocString(pathstr);
    VARIANT overw;
    overw.vt=VT_BOOL;
    overw.boolVal=VARIANT_TRUE;
    VARIANT name;
    name.vt=VT_BSTR;
    name.bstrVal=NULL;
    m_FramerControl.Save( path,overw,path,path);
    

      

  • 相关阅读:
    mysql创建用户,并赋予权限:只能查某个数据库中的某张表(只读)
    Fastjson toJSONString用单引号进行转换
    MyBatis传入参数为list、数组、map写法
    进制GB和GiB的区别
    leaflet 根据一个经纬度及距离角度,算出另外一个经纬度
    ubuntu下安装YApi
    Oracle 存储过程测试
    Oracle两种临时表的创建与使用详解
    一月到十二月的英文
    spring framework各个版本下载网址
  • 原文地址:https://www.cnblogs.com/songtzu/p/3374596.html
Copyright © 2020-2023  润新知