http://blog.sina.com.cn/s/blog_945492f401012nnn.html
由于学习C++操作word文档是临时需要,所以有些东西也只是知其然不知其所以然,有些代码也是抄了人家的,拿来应需。
C++操作word听说有两种方法,一种是COM、一种是ATL,这里用的是COM。有些函数不知道参数是什么意思时,可以找到函数原型帮助理解。Word的预定义枚举类型都是Wd开头,如WdSeekView::wdSeekMainDocument表示文字视图,WdSeekView::wdSeekCurrentPageHeader表示页眉视图,使用这些枚举类型,可以帮助参数的设置。
这里给出了两个昨天写的例子,能运行的。环境是VS2008和Office2003。第一个例子介绍了创建新文档、插入表格、输入文字、字体设置、设置表格边框、合并单元格、设置页眉页脚、插入图片、保存文件等功能的方法。第二个例子生成了一个完整的报告,包括页边距、段落对齐等。
具体步骤:
1.新建MFC工程,project - add class,选择file。找到Office安装目录下的MSWORD.OLB文件,如C:\\Program Files\\Microsoft Office\\OFFICE11\\MSWORD.OLB
2.加入需要的接口,下面例子中,C开头的类都是此处加入的接口
3.VS2008会为工程添加相应头文件,此时需要把头文件里的
#import "C:\\Program Files\\Microsoft Office\\OFFICE11\\MSWORD.OLB" no_namespace
改成
#import "C:\\Program Files\\Microsoft Office\\OFFICE11\\MSWORD.OLB" no_namespace raw_interfaces_only \
rename("FindText","_FindText") \
rename("Rectangle","_Rectangle") \
rename("ExitWindows","_ExitWindows")
注意,“\”字符后面不能加空格
3.#include // 为了方便操作 VARIANT 类型变量,使用 CComVariant 模板类
4.好了,可以编程了
//例子1
void CMyWordDlg::OnBnClickedButton1()
{
CoInitialize(NULL);//初始化COM,与最后一行CoUninitialize对应
//CPageSetup pagesetup=doc.get_PageSetup();//页面设置相关,没用到
CApplication app;
if(!app.CreateDispatch(_T("word.application"))) //启动WORD
{
AfxMessageBox(_T("居然你连OFFICE都没有安装吗?"));
return;
}
AfxMessageBox(_T("WORD 已经运行启动啦,你可以用Ctrl+Alt+Del查看"));
app.put_Visible(TRUE); //设置WORD可见。
CDocuments docs = app.get_Documents();
docs.Add(new CComVariant(_T("")),new CComVariant(FALSE),new CComVariant(0),new CComVariant());//创建新文档
AfxMessageBox(_T("下面,程序要向WORD发送字符啦"));
CSelection sel=app.get_Selection();//Selection表示输入点,即光标闪烁的那个地方
CFont0 font =sel.get_Font();
font.put_Name(_T("宋体"));//设置字体
font.put_Size(14);
font.put_Color(WdColor::wdColorGreen);
font.put_Bold(1);
sel.TypeText(_T("HELLO\r\n大家好呀"));//调用函数Selection::TypeText 向WORD发送字符
font.ReleaseDispatch();//【注】【意】所有东西用完之后一定要ReleaseDispatch,否则报错;不过最好像例子2中,在最后集中ReleaseDispatch
//插入表格
CDocument0 doc = app.get_ActiveDocument();//活动文档
CTables0 tables = doc.get_Tables();
tables.Add(sel.get_Range(), 7,11, new CComVariant(),new CComVariant());//插入表
CTable0 table=tables.Item(1);
CBorders borders=table.get_Borders();//设置表格边框
borders.put_InsideLineStyle(WdLineStyle::wdLineStyleSingle);
borders.put_OutsideLineStyle(WdLineStyle::wdLineStyleDouble);
//borders.put_OutsideLineWidth(WdLineWidth::wdLineWidth075pt);
borders.ReleaseDispatch();
sel.TypeText(_T("test1"));
sel.MoveRight(COleVariant((short)1),COleVariant(short(1)),COleVariant(short(0)));
sel.TypeText(_T("Test2"));
sel.MoveRight(COleVariant((short)1),COleVariant(short(1)),COleVariant(short(0)));
sel.TypeText(_T("Test3"));
sel.MoveRight(COleVariant((short)1),COleVariant(short(1)),COleVariant(short(0)));
sel.TypeText(_T("Test4"));
sel.MoveRight(COleVariant((short)1),COleVariant(short(1)),COleVariant(short(0)));
sel.TypeText(_T("Test5"));
sel.MoveRight(COleVariant((short)1),COleVariant(short(1)),COleVariant(short(0)));
sel.TypeText(_T("Test6"));
sel.MoveRight(COleVariant((short)1),COleVariant(short(1)),COleVariant(short(0)));
sel.TypeText(_T("Test7"));
sel.MoveRight(COleVariant((short)1),COleVariant(short(1)),COleVariant(short(0)));
sel.TypeText(_T("Test8"));
sel.MoveRight(COleVariant((short)1),COleVariant(short(1)),COleVariant(short(0)));
sel.TypeText(_T("Test9"));
sel.MoveRight(COleVariant((short)1),COleVariant(short(1)),COleVariant(short(0)));
sel.TypeText(_T("Test10"));
sel.MoveRight(COleVariant((short)1),COleVariant(short(1)),COleVariant(short(0)));
sel.TypeText(_T("Test11"));
int i=0,j=0;
for(i=2;i<7;i+=2)
{
CCell c1=table.Cell(i,1);
CCell c2=table.Cell(i+1,1);
c1.Merge(c2);//合并单元格
c1.ReleaseDispatch();
c2.ReleaseDispatch();
}
CCell c;
CString strName[3];
strName[0] = "yingkou";
strName[1] ="zyq654321";
strName[2] ="iwaswzq";
for(j=0,i=0;i<3;++i,j+=2)
{
c=table.Cell(j+2,1);
c.Select();
CCells cs=sel.get_Cells();
cs.put_VerticalAlignment(WdVerticalAlignment::wdAlignVerticalCenter);
sel.TypeText(strName[i]);
sel.MoveDown(COleVariant((short)5),COleVariant(short(1)),COleVariant(short(0)));
cs.ReleaseDispatch();
c.ReleaseDispatch();
}
c=table.Cell(7, 2);
c.Select();
CString strData[6];
strData[0]="111";
strData[1]="222";
strData[2]="333";
for(i=0,j=0;i<6;++i,++j)
{
if(i%2==0)
j=0;
sel.TypeText(strData[j]);
sel.MoveUp(COleVariant((short)5),COleVariant(short(1)),COleVariant(short(0)));
}
c.ReleaseDispatch();
c=table.Cell(7, 2);
c.Select();//选中最后一行
sel.MoveDown(COleVariant((short)5),COleVariant(short(1)),COleVariant(short(0)));//下移,输入点到页末
c.ReleaseDispatch();
CComVariant pageBreak = CComVariant(WdBreakType::wdPageBreak);
sel.InsertBreak(&pageBreak);//插入分页符
sel.TypeText(_T("this is the 2nd page!\r\n"));
//设置页眉页脚
CWindow0 win = doc.get_ActiveWindow();//窗口Window对象
CPane pane = win.get_ActivePane();//当前活动Pane窗格对象
CView0 view = pane.get_View();//View视图对象
view.put_Type(WdViewType::wdPrintView);//设置视图类型:打印、打印预览、阅读...
view.put_SeekView(WdSeekView::wdSeekCurrentPageHeader);//页眉视图
CHeaderFooter headerfooter = sel.get_HeaderFooter();
//headerfooter.put_LinkToPrevious(FALSE);//取消“与上一节相同”
sel.TypeText(_T("this is header"));
view.put_SeekView(WdSeekView::wdSeekCurrentPageFooter);//页脚视图
sel.TypeText(_T("this is footer\r\nand here is 2nd line"));
sel.TypeText(_T("第 "));
CRange range = sel.get_Range();
CFields fields = range.get_Fields();
CField field = fields.Add(range, COleVariant((short)WdFieldType::wdFieldPage),COleVariant(short(0)),COleVariant(short(0)));//页码
sel.TypeText(_T("页 共 "));
range = sel.get_Range();
fields = range.get_Fields();
field = fields.Add(range, COleVariant((short)WdFieldType::wdFieldNumPages),COleVariant(short(0)),COleVariant(short(0)));//页数
sel.TypeText(_T(" 页"));
//下面是设置页码格式
view.put_SeekView(WdSeekView::wdSeekMainDocument);//返回文字视图
//插入图片,先以嵌入型图像插入,再转成浮移图像,可以移动位置,也可不转
//据说不先按嵌入型插入的话,都会插在第一页
range = sel.get_Range();
COleVariant vRange;
vRange.vt=VT_DISPATCH;
vRange.pdispVal = range.m_lpDispatch;
vRange.pdispVal->AddRef();
CnlineShapes inlineshapes = doc.get_InlineShapes();
CnlineShape inlineshape = inlineshapes.AddPicture(_T("C:\\Documents and Settings\\Administrator\\桌面\\未命名.bmp"), COleVariant((long)0), COleVariant((long)1),&vRange);
inlineshape.put_ScaleWidth(50);
inlineshape.put_ScaleHeight(50);
//CShape shape = inlineshape.ConvertToShape();
//shape.put_Width(165);
//shape.put_Height(165);
//shape.put_Top(200);
//shape.put_Left(100);
//shape.ConvertToInlineShape();
//shape.ReleaseDispatch();
vRange.Detach();
sel.TypeText(_T("oh, i see the image"));
inlineshape.ReleaseDispatch();
inlineshapes.ReleaseDispatch();
//pagenumers.ReleaseDispatch();
field.ReleaseDispatch();
fields.ReleaseDispatch();
range.ReleaseDispatch();
headerfooter.ReleaseDispatch();
view.ReleaseDispatch();
pane.ReleaseDispatch();
win.ReleaseDispatch();
//保存文件
CString FileName(_T("C:\\Documents and Settings\\Administrator\\桌面\\doc.doc")); //文件名
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
COleVariant varZero((short)0);
COleVariant varTrue(short(1),VT_BOOL);
COleVariant varFalse(short(0),VT_BOOL);
doc.SaveAs(COleVariant(FileName), varZero, varFalse,
COleVariant(_T("")), varTrue, COleVariant(_T("")),
varFalse, varFalse, varFalse, varFalse, varFalse,
covOptional,covOptional,covOptional,covOptional,
covOptional);
AfxMessageBox(_T("WORD准备要退出啦"));
table.ReleaseDispatch();
tables.ReleaseDispatch();
doc.ReleaseDispatch();
sel.ReleaseDispatch();
docs.ReleaseDispatch();
//调用Quit退出WORD应用程序。当然不调用也可以,那样的话WORD还在运行着那
app.Quit(new CComVariant(FALSE),new CComVariant(),new CComVariant());
app.ReleaseDispatch(); //释放对象指针。切记,必须调用
AfxMessageBox(_T("Step1执行完成。接着请学习Setp2"));
CoUninitialize();//对应CoInitialize
}
//【分割线】【分割线】【分割线】【分割线】【分割线】【分割线】【分割线】【分割线】
//【分割线】【分割线】【分割线】【分割线】【分割线】【分割线】【分割线】【分割线】
//例子2
void CReportDlg::OnBnClickedOk()
{
CApplication app;
CDocuments docs;
CSelection sel;
CFont0 font;
CDocument0 doc;
CTables0 tables;
CTable0 table;
CBorders borders;
CColumns0 columns;
CColumn column;
CCell c;
CWindow0 win;
CPane pane;
CView0 view;
CHeaderFooter headerfooter;
CRange range;
CFields fields;
CField field;
CnlineShapes inlineshapes;
CnlineShape inlineshape;
CShading shading;//底纹
CPageSetup pagesetup;//页面设置
CParagraphs paragraphs;
CParagraph paragraph;
CoInitialize(NULL);//初始化COM
if(!app.CreateDispatch(_T("word.application"))) //启动WORD
{
AfxMessageBox(_T("木有找到OFFICE。。。%>_
---------------------------------------------------------------------------------------------------------------------------------------------
注意:
1. 里面对象的所有索引都是从1开始,比如tables.Item(0)会出错,tables.Item(1)会得到首个表格
---------------------------------------------------------------------------------------------------------------------------------------------
例子:取得文档中表格中的单元格内容
// COM相关变量
COleVariant vTrue((short)TRUE);
COleVariant vFalse((short)FALSE);
COleVariant vOpt((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
// Word相关变量
CApplication wordApp; // 在对象继承结构中是最顶层的对象,可以通过它的方法访问别的工作类型的对象(本例主要是word)
CDocuments docs; // 代表所有打开的文档对象
CDocument0 doc; // 单一文件
CSelection selection; // 选择区域
CRange rangeWord; // 文档区域
CTables0 tables; // 所有表格
CTable0 table; // 单一表格
CCell cell; // 单元格
// 启动Word程序
if (!wordApp.CreateDispatch(_T("word.application"))) // 启动Word
{
AfxMessageBox(_T("无法启动Word"));
return FALSE;
}
// 设置Word不可见
wordApp.put_Visible(FALSE);
// 打开指定Doc
docs = wordApp.get_Documents();
doc = docs.Open(COleVariant(strFileName), vFalse, vTrue, vFalse, vOpt, vOpt,
vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt);
if (!doc) // 打开失败
{
AfxMessageBox(_T("无法打开文件"));
return FALSE;
}
// 获得选择焦点
selection = wordApp.get_Selection();
// 获得表格
tables = doc.get_Tables();
table = tables.Item(1); // 索引从1开始
// 获得首个单元格
cell = table.Cell(1, 1); // 索引从1开始
cell.Select(); // 选择首个单元格
// 顺序获得表格里每个单元格的内容
CString str = selection.get_Text();
while (cell = cell.get_Next())
{
cell.Select();
str = selection.get_Text();
}
// 关闭文档
doc.Close(vOpt, vOpt, vOpt);
// 退出Word
wordApp.Quit(vOpt, vOpt, vOpt);