【当前博文转自,貌似作者也是转的。。】
VC操作word实例详解 [转]我们操纵Word需要通过类型库中的MFC类。而这些类,应该都是基于一个叫COleDispatchDriver的类。至少我所了解到的都是这样。 COleDispatchDriver没有基类。COleDispatchDriver类实现OLE自动化中的客户方。OLE调度接口为访问一个对象的方法和属性提供了途径。COleDispatchDriver的成员函数连接,分离,创建和释放一个IDispatch类型的调度连接。其它的成员函数使用变量参数列表来简化调用IDispatch::Invoke。 学习如何自动化控制 Word、Excel 和 Powerpoint 的对象模型的最佳方法是使用这些 Office 应用程序中的宏录制器: 从工具菜单上的宏选项中选择录制新宏,然后执行您感兴趣的任务。 从工具菜单上的宏选项中选择停止录制。完成录制后,从工具菜单上的宏选项中选择宏,选择您录制的宏,然后单击编辑。您将看到生成的 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 //新增加了一个头文件,为使用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"#includevoid CStep3Dlg::OnOK() { // 这次,我们要控制在WORD中输入一些字符了 /_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"#includevoid 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中了")); _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);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:#include "msword9.h" #includevoid 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 { //这里只考虑了输入为纯汉字的情况,你自己修改为可以支持中英文混合的情况 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取得CLSIDif(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();} |