MFC 操作 word

来源:互联网 发布:linux守护进程编写 编辑:程序博客网 时间:2024/06/05 11:22

环境:win7+vs2010+office2010/2013

1、  创建MFC工程,非Unicode。

2、  添加Word的类库

添加所有的接口,可以作为一个文件夹,以后再使用只要加入该文件夹就可以了。

由于函数命名冲突,需要在生成的头文件中做相应处理,即:

//#import "C:\\Program Files\\Microsoft Office\\Office14\\MSWORD.OLB"no_namespace

#import"C:\\Program Files\\MicrosoftOffice\\Office14\\MSWORD.OLB" no_namespace\

       raw_interfaces_only\

       rename("FindText", "_FindText")\

       rename("Rectangle", "_Rectangle")\

       rename("ExitWindows", "_ExitWindows")

对于不同版本的office,其默认的类型库位置如下表所示:

Office 版本

路径

Office 2003

C:\Program Files\Microsoft Office\Office11

Office 2007

C:\Program Files\Microsoft Office\Office12

Office 2010

C:\Program Files\Microsoft Office\Office14

Office 2013

C:\Program Files\Microsoft Office\Office15

特别的,word2013在vc2010下必须手动指定类型库文件位置。

3、在stdafx中添加调用的头文件

#include"Word2010/CApplication.h"   // word程序对象

#include"Word2010/CDocuments.h"   // 文档集对象

#include"Word2010/CDocument0.h"   // 单个docx对象

#include"Word2010/CSelection.h"// 该对象代表窗口或窗格中的当前所选内容,使用率最高

#include"Word2010/CCell.h"// 表格单元格

#include"Word2010/CCells.h"     // 表格单元格集合

#include"Word2010/CRange.h"   // 该对象代表文档中的一个连续范围

#include"Word2010/CTable0.h"   // 单个表格

#include"Word2010/CTables0.h" // 表格集合

#include"Word2010/CFont0.h"    // 字体

#include"Word2010/CParagraphs.h"    // 段落集合

#include"Word2010/CParagraphFormat.h"  // 段落样式

#include"Word2010/CParagraph.h"     // 单个段落

#include"Word2010/CnlineShape.h"    // Inline图形对象集合

#include"Word2010/CnlineShapes.h"  // 单个Inline图像对象

#include"Word2010/CRow.h"      // 单个行

#include"Word2010/CRows.h"    // 行集合

#include"Word2010/CFields.h"

#include"Word2010/CPane0.h"    // 页眉等设置

#include"Word2010/CWindow0.h"//页眉等设置

#include"Word2010/CView0.h"//页眉等设置

#include"Word2010/CPageSetup.h"    // 页面设置

4、注销每个引入的头文件的import行

//#import "C:\\Program Files\\MicrosoftOffice\\Office14\\MSWORD.OLB" no_namespace

不过如果使用wdMove等参数的话,只需要在CApplication.h文件中改为:

//#import "C:\\Program Files\\MicrosoftOffice\\Office14\\MSWORD.OLB" no_namespace

#import"C:\\Program Files\\MicrosoftOffice\\Office14\\MSWORD.OLB" no_namespace\

       raw_interfaces_only\

       rename("FindText", "_FindText")\

       rename("Rectangle", "_Rectangle")\

       rename("ExitWindows", "_ExitWindows")

否则,如果没有上面一段,则报错提示为(即全部头文件都注销import的情况下):

但是上述的方法会带来一个问题,就是当word版本改变时会出现问题,解决办法就是上述报错的变量都用其数值代替就不会有问题了(写代码时可以加上用以查看wdMove等变量的值),如下面一些:

wdAlignParagraphLeft = 0

wdAlignParagraphCenter = 1

wdAlignParagraphRight = 2

wdAlignParagraphJustify = 3

wdParagraph = 4

wdMove = 0

wdStyleHeading1 = -2

wdStory = 6

页面纵向wdOrientPortrait=0

页面横向wdOrientLandscape=1

enum WdUnits

{

    wdCharacter =1, // 字母

    wdWord = 2, // 单词

    wdSentence = 3,// 句子

    wdParagraph =4, // 段落

    wdLine = 5, // 行

    wdStory = 6, //所选区域

    wdScreen = 7,// 当前屏幕

    wdSection = 8,// 部分

    wdColumn = 9,// 列

    wdRow = 10, // 行

    wdWindow = 11,// 窗口

    wdCell = 12, //单元格

   wdCharacterFormatting = 13, // 字体格式

   wdParagraphFormatting = 14, // 段落格式

    wdTable = 15,// 表格

    wdItem = 16 // 项目

};

具体可以参考手册或者通过VBA代码查看。

5、到CXXXApp.cpp文件中找到InitInstance函数

添加代码:

       // 例如修改为公司或组织名

       SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

 

       if ( !AfxOleInit() )

       {

              AfxMessageBox(_T("无法初始化COM的动态链接库!"));

              return FALSE;

       }

这一步可以通过在创建MFC工程时,勾选“自动化”。

6、具体代码

添加按钮,在按钮中实现:

void CVCForWordDlg::OnBnClickedButton1()

{

       // TODO: 在此添加控件通知处理程序代码

       COleVariant   covZero((short)0),

              covTrue((short)TRUE),

              covFalse((short)FALSE),

              covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR),

              covDocxType((short)0);

      

       // 定义word变量

       CApplication wordApp; // wordApp

       CDocuments docxs; // docxs

       CDocument0 docx, docx_active; // docx

       if ( !wordApp.CreateDispatch(_T("Word.Application")) )// 实例化wordApp,必须有初始化

       {

              AfxMessageBox(_T("本机没有安装word产品!"));

              return;

       }

       else

       {

              wordApp.put_Visible(FALSE);  // 设置文档开始不可见

 

              CString wordVersion = wordApp.get_Version();  // 获得当前word的版本,比如word201014.0,201315.0

 

              // ****************** 添加一个document ******************

              // 得到docxs

              docxs = wordApp.get_Documents();     // 或者下面一段

              // =====================================

              //LPDISPATCH disp = wordApp.get_Documents();

              //if ( NULL == disp )

              //     return;// FALSE;

              //docxs.AttachDispatch(disp);

              //if ( NULL == docxs.m_lpDispatch )

              //     return;// FALSE;

              // =====================================

 

              // 添加一个docx

              docx = docxs.Add(covOptional, covOptional, covOptional, covOptional); // 未用模板时,或者下面段两种

              // =====================================

              // 2,未用模板

              //docx.AttachDispatch(docxs.Add(covOptional, covOptional, covOptional, covOptional));

              // 3,使用模板

              //CComVariant tpl(_T("")), Visble, DocxType(0), NewTemplate(false);

              //docx = docxs.Add(&tpl,&NewTemplate,&DocxType,&Visble);

              // =====================================

              if ( NULL == docx.m_lpDispatch )

                     return;

 

              // ****************** 设置页边距 ******************

              // 放在创建文档后,需要CPageSetup.h

              docx_active = wordApp.get_ActiveDocument();

              CPageSetup oPageSetup = docx_active.get_PageSetup();

              // 设置为页面方向和页边距

              if ( oPageSetup.get_Orientation() == 0 )      // 若为纵向则设置为横向,纵向wdOrientPortrait=0,横向wdOrientLandscape=1

              {

                     oPageSetup.put_Orientation(1);    // 横向

                     // 设置上下左右变距,单位缇,以下参数设置的页边距是适中

                     oPageSetup.put_TopMargin( (float) 72);     // 适中时72=2.54cm,默认时90=3.17cm10≈0.35cm

                     oPageSetup.put_BottomMargin( (float) 72);// 适中时72=2.54cm,默认时90=3.17cm10≈0.35cm

                     oPageSetup.put_LeftMargin( (float) 54);     // 适中时54=1.9cm,默认时72=2.54cm

                     oPageSetup.put_RightMargin( (float) 54);   // 适中时54=1.9cm,默认时72=2.54cm

              }

              //else       // 设置为纵向

              //{

              //     oPageSetup.put_Orientation(0);

              //     // 设置上下左右变距,单位缇,以下参数设置的页边距是适中

              //     oPageSetup.put_TopMargin( (float) 72);      //适中时72=2.54cm,默认或普通时72=2.54cm10≈0.35cm

              //     oPageSetup.put_BottomMargin( (float) 72); //适中时72=2.54cm,默认或普通时72=2.54cm10≈0.35cm

              //     oPageSetup.put_LeftMargin( (float) 54);      //适中时54=1.9cm,默认或普通时90=3.17cm

              //     oPageSetup.put_RightMargin( (float) 54);    //适中时54=1.9cm,默认或普通时90=3.17cm

              //}

 

              // 声明一个CSelection对象,并实例化

              CSelection wordSelection = wordApp.get_Selection();

 

              // ****************** 设置文档内容 ******************

              wordSelection.TypeText(_T("虚拟试验仿真报表"));

              wordSelection.HomeKey(COleVariant((short)5), COleVariant((short)1));// wdLine=5,返回当前行首,并选择当前行

              wordSelection.put_Style( COleVariant((short)-2) );//设置为标题1“样式,wdStyleHeading1=-2

              // 设置选择区域字体,一定要放在样式后,否则格式会被样式的覆盖

              CFont0 font = wordSelection.get_Font();

              font.put_Name(_T("微软雅黑"));

              font.put_Size(16);  // 必须选择该行才可以修改,即必须有HomeKey那行

              // 获得当前段落,并设置对齐方式

              CParagraph lastPara = GetCurParagraph(docx);

              lastPara.put_Alignment(1);    // wdAlignParagraphLeft=0, wdAlignParagraphCenter=1,wdAlignParagraphRight=2

              // 结束当前段落编辑,移动光标到段落后

              wordSelection.EndOf(COleVariant((short)4), COleVariant((short)0));     // wdParagraph=4,wdMove=0

 

              wordSelection.TypeParagraph(); // 新起一段

              COleVariant covTime(_T("yyyy-MM-dd:dddd"));     // 时间格式可调整

              wordSelection.InsertDateTime(covTime, covFalse, covOptional, covOptional, covOptional); // 插入当前时间

              wordSelection.EndOf(COleVariant((short)4), COleVariant((short)0));     // 结束当前段落编辑,wdParagraph=4wdMove=0

 

              // 生成表格

              MakeRTITable( docx, wordSelection );

 

              // 以下为为不同段落设置不同字体和对齐方式示例

              wordSelection.TypeParagraph(); // 新起一段

              wordSelection.TypeText(_T("end of the story!"));

              wordSelection.HomeKey(COleVariant((short)5), COleVariant((short)1));// wdLine=5,返回当前行首,并选择当前行

              /*CFont0 */font = wordSelection.get_Font();

              font.put_Size(20);  // 必须选择该行才可以修改,即必须有HomeKey那行

              /*CParagraph */lastPara = GetCurParagraph(docx);

              lastPara.put_Alignment(3);    // 右对齐

              wordSelection.EndOf(COleVariant((short)4), COleVariant((short)0));     // 结束当前段落编辑,wdParagraph=4wdMove=0

 

              wordSelection.TypeParagraph(); // 新起一段

              wordSelection.TypeText(_T("Thanks for reading!"));

              wordSelection.HomeKey(COleVariant((short)5), COleVariant((short)1));// wdLine=5,返回当前行首,并选择当前行

              /*CFont0 */font = wordSelection.get_Font();

              font.put_Size(10);  // 必须选择该行才可以修改,即必须有HomeKey那行

              font.put_Name(_T("Times New Roman"));

              /*CParagraph */lastPara = GetCurParagraph(docx);

              lastPara.put_Alignment(1);    // 居中对齐

              wordSelection.EndOf(COleVariant((short)4), COleVariant((short)0));     // 结束当前段落编辑,wdParagraph=4wdMove=0

 

              // 插入分页符,用于换页

              wordSelection.InsertBreak(covOptional);

             

              // 插入公式,操作域

              CFields fields = wordSelection.get_Fields();

              COleVariant ofont = _variant_t(_T("Times New Roman"));

              COleVariant text = _variant_t(_T("EQ \\a \\ar \\co2 \\vs3 \\hs3(Axy,Bxy,A,B)"));    // 注意要两个\\,一个转义后不对!!!

              fields.Add( wordSelection.get_Range(), covOptional, text, covFalse );

              wordSelection.HomeKey(COleVariant((short)5), COleVariant((short)1));// wdLine=5,返回当前行首,并选择当前行

              lastPara = GetCurParagraph(docx);

              lastPara.put_Alignment(0);    // 左对齐

              wordSelection.EndOf(COleVariant((short)4), COleVariant((short)0));     // 结束当前段落编辑,wdParagraph=4wdMove=0

 

              // 获取应用当前Debug路径

              char fileName[MAX_PATH];

              GetModuleFileName(NULL, fileName, MAX_PATH);

              char dir[260];

              char dirver[100];

              _splitpath(fileName, dirver, dir, NULL, NULL);

              CString strAppPath = dirver;

              strAppPath += dir;

              //CString strAppPath = _T("D:\\");

 

              // ****************** 插入图片示例 ******************

              // 需要CWindow0.h, CPane0.h, CView0.h

              wordSelection.TypeParagraph();   // 另起一段

              CString strPicture = strAppPath + _T("\\截图.jpg");

              CnlineShapes nLineShapes = wordSelection.get_InlineShapes();

              CnlineShape nLineshape = nLineShapes.AddPicture(strPicture, covFalse, covTrue, covOptional);

 

              // ****************** 设置页眉页脚 ******************

              CWindow0 oWind = docx.get_ActiveWindow();

              CPane0 oPane = oWind.get_ActivePane();   // 一定将CPane改为CPane0或其他

              CView0 oView = oPane.get_View();

              // =============== 设置页眉 ===============

              oView.put_SeekView(9);      // wdSeekCurrentPageHeader=9

              /*CFont0 */font = wordSelection.get_Font();      // 设置选择区域字体

              font.put_Name(_T("华文楷体"));

              font.put_Size(16);

              /*CParagraphFormat */lastPara = wordSelection.get_ParagraphFormat(); // 默认为居中

              lastPara.put_Alignment(1);    // wdAlignParagraphLeft=0, wdAlignParagraphCenter=1, wdAlignParagraphRight=2

              wordSelection.TypeText(_T("网络大学"));

 

              // =============== 设置页脚,包括页码 ===============

              oView.put_SeekView(10);    // wdSeekCurrentPageFooter=10

              /*CFont0 */font = wordSelection.get_Font();      // 设置选择区域字体,一定要放在样式后,否则格式会被样式的覆盖

              font.put_Name(_T("华文楷体"));

              font.put_Size(16);

              /*CParagraphFormat */lastPara = wordSelection.get_ParagraphFormat(); // 默认为居中

              lastPara.put_Alignment(1);    // wdAlignParagraphLeft=0, wdAlignParagraphCenter=1, wdAlignParagraphRight=2

              // 添加页码

              wordSelection.TypeText(_T("第页共页"));

              wordSelection.MoveLeft( COleVariant((short)1), COleVariant((short)4), &covZero );

              /*CFields */fields = wordSelection.get_Fields();

              fields.Add( wordSelection.get_Range(), COleVariant((short)33), COleVariant("PAGE  "), &covTrue );     // 增加页码域,当前页码

              wordSelection.MoveRight( COleVariant((short)1), COleVariant((short)3), &covZero);

              fields.Add( wordSelection.get_Range(), COleVariant((short)26), COleVariant("NUMPAGES  "), &covTrue );    // 增加页码域,总页数

              oView.put_SeekView(0);      // 关闭页眉页脚,wdSeekMainDocument=0,回到主控文档

 

              // Word程序可见,显示报表

              //wordApp.put_Visible(TRUE);

 

              // 保存成果

              CString strSavePath = strAppPath;

              strSavePath += _T("\\报表.docx");

              docx.SaveAs(COleVariant(strSavePath), covOptional, covOptional, covOptional, covOptional,

                     covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional,covOptional);

 

              // 退出word应用

              docx.Close(covFalse, covOptional, covOptional);

              wordApp.Quit(covOptional, covOptional, covOptional);

              wordApp.ReleaseDispatch();

 

              MessageBox(_T("生成成功!"));

       }    

}

表格插入函数MakeRTITable(CDocument0& oDoc, CSelection&selection):

void CVCForWordDlg::MakeRTITable(CDocument0& oDoc, CSelection& selection)

{

       int nRowSize = 10;

       nRowSize = nRowSize == 0 ? 2 : nRowSize;       // 表格至少两行

       // new paragraph

       selection.TypeParagraph();    //新起一段

 

       // Add table title

       selection.TypeParagraph();    //新起一段

       selection.TypeText(RTITableTitle);

       CParagraph lastPara = GetCurParagraph(oDoc);

       //lastPara.put_Alignment(wdAlignParagraphCenter);   //下面表格内容也受此控制

       //selection.EndOf(COleVariant((short)wdParagraph), COleVariant((short)wdMove));

       lastPara.put_Alignment(1);    //下面表格内容也受此控制

       selection.EndOf(COleVariant((short)4), COleVariant((short)0));

 

       // Add table

       CTables0 wordTables = oDoc.get_Tables();

       CRange wordRange = selection.get_Range();

       COleVariant covTrue((short)TRUE), covFalse((short)FALSE), covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);

       CTable0 wordTable = wordTables.Add(wordRange, nRowSize , RTITableColumnSize, covTrue, covFalse);// 添加表格

       wordRange = wordTable.get_Range();

 

       // Make header

       CCell cell;

       for ( int i=1; i<RTITableColumnSize+1; i++ )

       {

              cell = wordTable.Cell(1, i); // 表格第一行第i列单元格

              cell.Select();

              selection.TypeText(RTITableFieldArray[i-1]);

       }

       //selection.EndOf(COleVariant((short)wdStory), COleVariant((short)wdMove)); //结束表格编辑

       selection.EndOf(COleVariant((short)6), COleVariant((short)0));// 结束表格编辑

 

       for ( int i=1; i<RTITableColumnSize+1; i++ )

       {

              cell = wordTable.Cell(2, i); // 表格第一行第i列单元格

              cell.Select();

              selection.TypeText(_T("111.0"));

       }

       //selection.EndOf(COleVariant((short)wdStory), COleVariant((short)wdMove)); //结束表格编辑

       selection.EndOf(COleVariant((short)6), COleVariant((short)0));// 结束表格编辑

 

       // 合并单元格,需要注意的是,合并整行前不能有单元格的合并,否则无法获取表格的行信息

       CRows rows;

       rows = wordTable.get_Rows();     // 获取表格的行

       CRow row;

       row = rows.Item(3);      // 指向第三行

       wordRange = row.get_Range();

       CCells cells;

       cells = wordRange.get_Cells();     // 得到该行所有单元格

       cells.Merge(); // 合并第三行为一列

       cell = wordTable.Cell( 4, 1 );

       cell.Merge( wordTable.Cell( 5, 1 ) );     //合并第一列中的第四行与第五行

 

       // 光标的移动方式.通过Selection类对象的方法对光标进行上下,左右等移动,实现对光标的定位功能

       selection.MoveRight( COleVariant((short)1), COleVariant((short)1), COleVariant((short)0) );// 向右移动鼠标到下一个字符

       selection.MoveDown( COleVariant((short)5), covOptional, covOptional );// 向下移动鼠标到下一行

       COleVariant vUnit((short)RTITableColumnSize);      // 光标移动方式为行  

       COleVariant vCount((short)3);

       selection.Move( &vUnit, &vCount );    // 移动3

       cells.Merge(); // 合并第三行为一列

       COleVariant vEnd((short)5);

       selection.EndKey( &vEnd, &covOptional ); // 将光标移动到行尾

}

自定义函数GetCurParagraph(CDocument0& curDoc):

CParagraph CVCForWordDlg::GetCurParagraph(CDocument0& curDoc)

{

       CParagraphs paragraphs = curDoc.get_Paragraphs();

       CParagraph lastPara = paragraphs.get_Last();

       return lastPara;

}

7、生成文档结果

8、说明

(1)关于设置页边距时的参数说明

以缇为单位,一个与屏幕无关的单位,用来保证屏幕应用程序对屏幕元素的定位和比例在所有的显示系统上的一致性。一缇等价于1/20 个打印机的磅。一逻辑英寸大约有1440 缇,一逻辑厘米约567 缇(打印时的一英寸或一厘米所对应的屏幕上的长度)。

但实际word文档中显示和打印效果来看,56.7缇=2cm,10缇=0.35cm。

(2)加载CPane.h文件前,将CPane改为CPane0,否则会出现重定义,还有一个afxpane.h中有CPane类

(3)生成的word文档,如果页码显示和公式显示为代码形式,一个可以直接全选右键“切换域代码”,对于页码则选中页脚同样操作即可;另一个可以设置word文档的格式,在文件——选项——高级中去掉“显示域代码而非域值”前面的勾即可。

(4)设置页边距和页面方向的时候,还是在创建文档后设置,否则在后面设置时可以会有一些问题。

(5)通过域代码来写简单公式,域代码格式可以参考网页:

http://blog.sina.com.cn/s/blog_6967a9d30100mrbx.html

其他相关内容,百度或谷歌,网上挺多的。

(6)本文档代码例子下载链接:

http://pan.baidu.com/share/link?shareid=508404&uk=2936052968