VC操作WORD文档总结

时间:2022-07-20 04:15:25

一、写在开头

最近研究word文档的解析技术,我本身是VC的忠实用户,看到C#里面操作WORD这么舒服,同时也看到单位有一些需求,就想尝试一下,结果没想到里面的技术点真不少,同时网络上的共享资料很多,但是很多就是起了一个头没有完整的资料,因此在此记录一下,首先感谢怪兽哥哥(开源了了IOCP一整套开源库的家伙还有很多隐藏技能大家可以关注他)、骨头哥(不少好资料)、savageII哥(大牛)这些网友他们很有共享精神。废话不说了开始正题。

二、环境搭建

我用的VC2010,其实在VC6.0以上的版本设置都差不多,这里我用一下网友的资料我就不写了

1、  创建MFC工程,非Unicode。

2、  添加类型库,类向导->

VC操作WORD文档总结

在这个页面中选择要使用的WORD的类,这里用到了COM技术,本人能力有限就不介绍COM的原理了,添加完毕后,在需要用的到地方#include就可以了,这个地方有个注意点 需要注释到每个类的最前面的

#import "C:\\Program Files\\Microsoft Office\\Office12\\MSWORD.OLB" no_namespace这一句话因为有的安装目录可能不在这里,会提示错误。‘

三、类介绍

这里还是用网友的资料,Microsoft Office Word 2003 对象是按层次顺序排列的,层次结构顶端的两个主类是 Application 类和 Document 类。这两个类非常重要,因为在大部分时间里,您要么是在使用 Word 应用程序本身,要么是以某种方式处理 Word 文档。Word 对象模型严格遵循用户界面。Application 对象提供整个应用程序的包装,每个 Document 对象表示单个 Word 文档。这些对象各自都有很多方法和属性,您可以使用这些方法和属性操作对象或与对象交互。
   
Application
对象。Application 对象表示 Word 应用程序,是其他所有对象的父级。它的所有成员通常作为一个整体应用于 Word。可以使用该对象的属性和方法来控制 Word 环境。
   
Document
对象。Document 对象是 Word 编程的中枢。当您打开文档或创建新文档时,就创建了新的 Document 对象,该对象被添加到 Word 的 Documents 集合中。焦点所在的文档叫做活动文档,由 Application 对象的 ActiveDocument 属性表示。
Selection 对象。Selection 对象表示当前选择的区域,Selection 对象只存在一个。在 Word 用户界面中执行某项操作(例如,对文本进行加粗)时,应首先选择或突出显示文本,然后应用格式设置。Selection 对象始终存在于文档中。如果未选中任何对象,它表示插入点。此外,该对象还可以表示多个不连续的文本块。

View对象。该对象包含窗口或窗格的视图属性(如全部显示、域底纹、表格虚线等等)。

Pane对象。代表一个窗格。
    Range 对象。Range 对象表示文档中的一个连续的区域,由一个起始字符位置和一个结束字符位置定义。Range 对象的数量并不局限于一个。您可以在同一文档中定义多个 Range 对象。
    Bookmark
对象。Bookmark 对象与 Range 对象类似,它也表示文档中的一个连续区域,并具有一个起始位置和一个结束位置。书签用于在文档中标记一个位置,或者用作文档中的文本容器。Bookmark 对象可以小到只有一个插入点,也可以大到整篇文档。您还可以在文档中定义多个书签。
    Selection对象。这个对象就相当于光标,很多操作跟他相关,选中,移动等都需要这个对象,它在我们的编程中占有很重要的地位。

Shape 对象。代表一个图形层对象,例如自选图形、任意多边形、OLE 对象、ActiveX 控件、图片等。Shape 对象是
Shapes
集合的一个成员,该集合包含了一篇文档正文部分的所有图形,或文档页眉和页脚部分中的所有图形。

此外还有CParagraph、Font、Table、Cell、Shape等对象具体的作用可以查看MSDN。

四、具体使用

  1. Word文档的启动

在APP文件的InitInstance函数中需要添加如下代码,这个地方就是COM的初始化,如果存在就不需要添加了

if ( !AfxOleInit() )

{

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

return FALSE;

}

CApplication0
WordApp ;

CDocuments
Docs ;

CDocument0
Doc ;

// 首先建立一个word实例对象

if (!WordApp.CreateDispatch(TEXT("Word.Application"))
)

{

AfxMessageBox("创建WORD服务失败!");

return
false;  // 一定要返回,否则程序崩溃

}

// 显示此对象文件 ,您也可以不调用此句,不显示对象文件

WordApp.put_Visible(false);

// 创建文档

Docs = WordApp.get_Documents();

// 打开一个新文档,将e:\\BuildJobEdit.rtf文件的内容添加到新文档中

CComVariant
tpl(strFile), NewTemplate(false), DocType(0), Visble;

Doc = Docs.Add(&tpl,&NewTemplate,&DocType,&Visble);

各种处理代码在此

// 释放各种对象

Docs.ReleaseDispatch();

Doc.ReleaseDispatch();

CComVariant
SaveChanges(false),
OriginalFormat, RouteDocument;

WordApp.Quit(&SaveChanges,&OriginalFormat,&RouteDocument
);

WordApp.ReleaseDispatch();

  1. Selection对象的应用,

获得当前word文档的光标。上面我们已经打开一个word文档了,CSelection Sel = WordApp.get_Selection();
这行代码就是获得光标了。

光标的移动。这就要看光标的移动函数了,CSelection的移动函数很多,主要有Move、MoveLeft、MoveRight等,具体的用法有很多大家可以自行查看MSDN帮助文档。

获得内容。我这里要提的有一个关键函数get_Text(),这个函数有一个作用,如果不是选中一段文字的情况下,它获得是光标旁边的那个字符的内容,也就是光标右边的那个字符。正因为有了这个功能我们就可以进行word文档的解析了。

do

{

CString strChar=Sel.get_Text();

}

while(Sel.Move(&_variant_t(1),&_variant_t(1))>0);

通过上面这段代码我们就可以一个字一个字的遍历word文档了strChar就代表光标右边的文字了。

很多人说你这种办法太笨了,这样的效率太慢了,别着急我这种做是有原因的,如果我们要针对word文档做其他操作的话,这种方式的优点就很明显了,我们如果想在当前光标点做插入和更改文字内容的操作就很方便了,我称这种方式为入微级的操作,如果只是想单单获得word的内容的话下面我还有其他的办法,请耐心的看下去。

添加内容,Selection还有InsertBefore和InsertAfter等操作,可以在当前光标点插入文字了。

选中文字,Selection的setRang函数可以帮助我们选中文字Sel.SetRange(iBeg,iEnd); 他的两个参数告诉我们的选中的起始点。选中文字后我们就可以对选中的文字设置字体颜色等操作了。

小技巧:

  • Sel.Move(&_variant_t(1),&_variant_t(1))是向前移动一个字符,如果在文档的结尾处会返回0
  • 选中一段文字后Sel.Move(&_variant_t(1),&_variant_t(1))会将光标定位到这段文字的末尾,而不是移动一个字符。
  • 用Selection的设置Font时必须选中一段文字才能设置,否则会提示异常。
  • StartOf和endof函数可以控制光标移动到某些内容的开头和结尾。
  • InsertBefore和InsertAfter添加文字后会选中添加的文字。
  • 这种方式针对复杂表格可能会导致死循环,我的方式是遇到表格直接不操作跳过去,等最后用表格类操作表格内容。
  1. 3.    
    页眉页脚的操作

尽管有HeaderFooter等类,如果是只是想获得内容,并且更新全部内容,而不进行入微级的操作的话可以使用这个类结合Sections会有很好的效果,这种方式很强大但是存在一定的问题,例如页眉页脚不一样的如何操作呢,我不是很喜欢,我要掌控所有,我需要的是入微级的操作。这种方式我贴一段VB宏的代码,给大家点启发

With ActiveDocument.Sections(1)

.Headers(wdHeaderFooterPrimary).Range.Text = "Header text"

.Footers(wdHeaderFooterPrimary).Range.Text = "Footer text"

End With

下面介绍我的方法直接上代码了

CWindow0  window=WordApp.get_ActiveWindow();

CPane0   pane=window.get_ActivePane();

CView0   view=pane.get_View();

//处理页眉

view.put_SeekView(9);//进入页眉视图

view.put_SeekView(10); //进入页脚视图

view.put_SeekView(0);//进入正文视图

进入到这三种视图后我们就可以利用Selection对象对我们的页眉页脚随心所欲的进行我们的操作了,具体操作看你自己的需求了。

小技巧:进入到页眉视图后想进入到下一个页眉视图怎么办呢,利用view.NextHeaderFooter();就可以进入到下一个页眉视图了,页脚也是一样的操作。如果想从页眉页脚视图中出来就可以view.put_SeekView(0);

  1. 4.    
    文本框的操作

主要类是shape和shapes,这个操作很简单直接贴代码了

//文本框处理

CShapes shapes=Doc.get_Shapes();//获得所有图形的集合

long shapCount=shapes.get_Count();//图形的数量

for (int lc = 1 ; lc < shapCount+1 ;
lc++ )//遍历图形

{

CShape
shape=shapes.Item(&_variant_t(lc));

CTextFrame
text=shape.get_TextFrame();//对象包含指定图形的文字

if (text.get_HasText())//对象是否包含文字

{

shape.Select(&_variant_t(true));

Sel.StartOf(&_variant_t(6),&_variant_t(0));

//光标的入微级操作

}

}

注意:如果文本框中再嵌套文本框这种方法可能不好用,如果大牛知道怎么操作,请联系我谢谢。

  1. 5.    
    表格的操作

主要是类是CTables、CTable、Cells、Cell,代码如下

CTables0
tables=Doc.get_Tables();//获得当前文档所有表格的集合

int iTableCount=tables.get_Count();

for (int t=1;t<iTableCount+1;t++)//遍历表格

{

CTable0 table=tables.Item(t);//获得表格

table.Select();//选中表格

CCells cels=Sel.get_Cells();//获得表格单元格的集合

int iCelCount=cels.get_Count();

CCell cel=cels.Item(1);//获得第一个单元格

cel=cel.get_Next();//获得下一个单元格

}

获得了单元格我们就可以进行入微级的光标操作了

     注意点:这里用的是get_Next()函数进行单元格的集合的遍历主要是因为用循环的方式时报错了,具体原因不祥,如果知道的大牛请联系我。

五、写在最后

花了2个小时把这篇文章写完了,第一次写,啰嗦的东西不少,还有很多东西没总结出来,遗漏了不少,因为工作限制,业务逻辑的代码就没发出来,请大家见谅,本身我的水平也有限,没有太多高深的东西,先写这么多吧,后续在继续补充,本身QQ:158513320,欢迎大家交流拍砖,跪求大牛指点谢谢。