MFC/VC++调用word进行报表制作
我在工作当中需要对大量的数据或者各种测试数据进行统计分析,最终的统计分析结果总归要汇总为一份报告,不管是内部使用也好还是外部提供给客户也好,一份内容翔实、格式精美的报告自然必不可少。我对MFC/VC++也不是高手,只是业余爱好自己动动手做些东西。自然,低于VC操作word可谓完全没有经验,在网络上面也查找了很多资料,都是些只言片语,不能真正的领略通过VC使用word的方法。于是自己摸索了几个礼拜,可谓耗时甚长,劳心劳力啊。MS的东西,封装的也太严实了,对于函数部分只有些许的简单介绍,往往看的云里雾里。没有实践还是不行啊!体会自己的经历,虽然辛苦但也有收获。不想其他朋友再继续走我走过的路,浪费时间、精力,故成文以共享。
废话少说,进入正题吧。
第一步,当然我们需要首先导入word需要的库。通过ClassWizard->Add Class选择From a Type Library…定位需要的库文件导入。本例应该使用C:"Program Files"Microsoft Office"OFFICE11"MSWORD.OLB,在这里尽可选择所有的类导入,反正用的时候都有了,呵呵。完成这一步,我们得到两个文件msword.h和msword.cpp,那就加入你的工程吧。
说明:如果需要在VC++/MFC开发程序操作word/excel等office元素,那么需要对必要的类型库进行导入.下面是office系列的类型库参考,导入类型库时候请选择正确的类型库进行导入.
应用程序 |
类型库 |
Microsoft Access 97 |
Msacc8.olb |
Microsoft Jet Database 3.5 |
DAO350.dll |
Microsoft Binder 97 |
Msbdr8.olb |
Microsoft Excel 97 |
Excel8.olb |
Microsoft Graph 97 |
Graph8.olb |
Microsoft Office 97 |
Mso97.dll |
Microsoft Outlook 97 |
Msoutl97.olb |
Microsoft PowerPoint 97 |
Msppt8.olb |
Microsoft Word 97 |
Msword8.olb |
Microsoft Access 2000 |
Msacc9.olb |
Microsoft Jet Database 3.51 |
DAO360.dll |
Microsoft Binder 2000 |
Msbdr9.olb |
Microsoft Excel 2000 |
Excel9.olb |
Microsoft Graph 2000 |
Graph9.olb |
Microsoft Office 2000 |
Mso9.dll |
Microsoft Outlook 2000 |
Msoutl9.olb |
Microsoft PowerPoint 2000 |
Msppt9.olb |
Microsoft Word 2000 |
Msword9.olb |
Microsoft Access 2002 |
Msacc.olb |
Microsoft Excel 2002 |
Excel.exe |
Microsoft Graph 2002 |
Graph.exe |
Microsoft Office 2002 |
MSO.dll |
Microsoft Outlook 2002 |
MSOutl.olb |
Microsoft PowerPoint 2002 |
MSPpt.olb |
Microsoft Word 2002 |
MSWord.olb |
Microsoft Office Access 2003 |
Msacc.olb |
Microsoft Office Excel 2003 |
Excel.exe |
Microsoft Office Graph 2003 |
Graph.exe |
Microsoft Office 2003 |
MSO.dll |
Microsoft Office Outlook 2003 |
MSOutl.olb |
Microsoft Office PowerPoint 2003 |
MSPpt.olb |
Microsoft Office Word 2003 |
MSWord.olb |
注意:这些类型库的默认位置是:
Office 版本 |
路径 |
Office 97 |
C:"Program Files"Microsoft Office"Office |
Office 2000 |
C:"Program Files"Microsoft Office"Office |
Office XP |
C:"Program Files"Microsoft Office"Office10 |
Office 2003 |
C:"Program Files"Microsoft Office"Office11 |
Dao350.dll 和 Dao360.dll 的默认位置是 C:"Program Files"Common Files"Microsoft Shared"Dao。
第二步,进入具体使用实践阶段。激动人心的时刻到来了,呵呵。不过别忘记把你的H文件#Include进来。下面是我的一个例子,从我具体的工程当中抽取出来供各位参考。有些地方我会简要解释。还等什么,赶紧试验一下代码吧。修改一下就是你的报告了,开心吧。
BOOLCMDIDemoApp::OnMakeReport()
{
_ApplicationwordApp;
DocumentswordDocs;
_DocumentwordDoc;
SelectionwordSelection;
RangewordRange;
TableswordTables;
TablewordTable;
CellwordCell;
CellswordCells;
//Paragraphs wordParagraphs;
//Paragraph wordParagraph;
_FontwordFont;
ShadingwordShading;
//
intnRow=0;
//
COleVariantvTrue((short)TRUE),
vFalse((short)FALSE),
vOpt((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
CComVariantdefaultBehavior(1),AutoFitBehavior(0);
//创建word application实例
if (!wordApp.CreateDispatch(_T("Word.Application")))
{
AfxMessageBox("Word CreateDispatch Failed!");
returnFALSE;
}
wordApp.SetVisible(TRUE);//make visible
wordApp.Activate();//激活
wordDocs=wordApp.GetDocuments();//get documents object
//
CStringstrDocTemplate;
CStringstrPath;
charszFullPath[_MAX_PATH];
::GetModuleFileName(NULL,szFullPath,_MAX_PATH);
strDocTemplate.Format("%s",szFullPath);
intnPos=strDocTemplate.ReverseFind('""');
strDocTemplate=strDocTemplate.Left(nPos);
strPath=strDocTemplate;
TRACE1("%s"n",strDocTemplate);
// strDocTemplate+="""Template""Report.doc";
// wordDoc=wordDocs.Open(COleVariant(strDocTemplate),&vOpt,&vOpt,&vOpt,&vOpt,
// &vOpt,&vOpt,&vOpt,&vOpt,&vOpt,&vOpt,&vTrue,&vOpt,&vOpt,&vOpt,&vOpt);
CComVarianttpl(_T("")),Visble,DocType(0),NewTemplate(false);
wordDoc=wordDocs.Add(&tpl,&NewTemplate,&DocType,&Visble);
wordSelection=wordApp.GetSelection();
//wordTables.AttachDispatch(wordDoc.GetTables());
wordTables=wordDoc.GetTables();
//wordParagraphs = wordDoc.GetParagraphs();
//wordParagraph=wordParagraphs.GetLast();
//wordRange=wordParagraph.GetRange();
//wordSelection.EndKey(COleVariant((short)6),COleVariant((short)0));
//move insertion point to the end of the story
/*
wdUnits:
wdCharacter=1
wdWord=2
wdSentence=3
wdParagraph=4
wdSection=8
wdStory=6
wdCell=12
wdColumn=9
wdRow=10
wdTable=15
wdMovementType:
wdMove=0
wdExtend=1
*/
//move to end of story
wordSelection.EndOf(COleVariant((short)6),COleVariant((short)0));
//1.1 RxLev Full
wordSelection.TypeText("1. 统计报告");
wordSelection.HomeKey(&CComVariant(5),&CComVariant(1));
//Format the line with selection
wordFont = wordSelection.GetFont();
wordFont.SetBold(9999998);//wdToggle
wordSelection.EndOf(&CComVariant(5),&CComVariant(0));
wordSelection.TypeParagraph();
wordSelection.TypeText("(1.1). 分段统计");
wordSelection.TypeParagraph();
wordFont.SetBold(9999998);//wdToggle
wordRange=wordSelection.GetRange();
//add table
//nRow=m_nRange1+1;
wordTable=wordTables.Add(wordRange,5/*row*/,4/*column*/,&defaultBehavior,&AutoFitBehavior);
wordRange=wordTable.GetRange();
//wordRange.MoveEnd(COleVariant((short)15),COleVariant((short)1));
//wordRange.Select();
//move end of table
//wordSelection.EndOf(COleVariant((short)15),COleVariant((short)0));
//insert rows
//wordSelection.InsertRowsBelow(COleVariant((short)5));
//选择第一个单元,进而选择第一行进行格式化
wordCell=wordTable.Cell(1,1);
wordCell.Select();
//select the row with current selection
wordSelection.EndKey(&CComVariant(10),&CComVariant(1));
//Format the row with selection
//wordFont = wordSelection.GetFont();
wordFont.SetBold(9999998);//wdToggle
wordCells=wordSelection.GetCells();
wordShading = wordCells.GetShading();
wordShading.SetTexture(0);
wordShading.SetBackgroundPatternColor(14737632);//15987699 14737632 adColorBlue
wordShading.SetForegroundPatternColor(-16777216);//-16777216 wdColorAutomatic
//move to end of table
//wordSelection.EndOf(COleVariant((short)15),COleVariant((short)0));
//wordParagraph=wordParagraphs.GetLast();
//wordRange=wordParagraph.GetRange();
//wordRange.MoveEnd(COleVariant((short)4),COleVariant((short)1));
//wordRange.SetText("Test");
//wordSelection=wordApp.GetSelection();
//wordSelection.MoveEnd(COleVariant((short)6),COleVariant((short)1));
wordCell=wordTable.Cell(1,1);
wordCell.Select();
wordSelection.TypeText("统计项目");
wordSelection.MoveRight(&CComVariant(12),&CComVariant(1),&CComVariant(0));
wordSelection.TypeText("采样");
wordSelection.MoveRight(&CComVariant(12),&CComVariant(1),&CComVariant(0));
wordSelection.TypeText("百分比");
wordSelection.MoveRight(&CComVariant(12),&CComVariant(1),&CComVariant(0));
wordSelection.TypeText("累计百分比");
//
//
wordSelection.EndOf(COleVariant((short)6),COleVariant((short)0));
wordSelection.TypeParagraph();
wordSelection.TypeText("(1.2). 分段统计");
wordSelection.HomeKey(&CComVariant(5),&CComVariant(1));
//Format the line with selection
wordFont = wordSelection.GetFont();
wordFont.SetBold(9999998);//wdToggle
wordSelection.EndOf(&CComVariant(5),&CComVariant(0));
wordSelection.TypeParagraph();
wordFont.SetBold(9999998);//wdToggle
wordRange=wordSelection.GetRange();
//add table
//nRow=m_nRange1+1;
wordTable=wordTables.Add(wordRange,5/*row*/,4/*column*/,&defaultBehavior,&AutoFitBehavior);
wordRange=wordTable.GetRange();
//选择第一个单元,进而选择第一行进行格式化
wordCell=wordTable.Cell(1,1);
wordCell.Select();
//select the row with current selection
wordSelection.EndKey(&CComVariant(10),&CComVariant(1));
//Format the row with selection
wordFont = wordSelection.GetFont();
wordFont.SetBold(9999998);
wordCells=wordSelection.GetCells();
wordShading = wordCells.GetShading();
wordShading.SetTexture(0);
wordShading.SetBackgroundPatternColor(14737632);//15987699
wordShading.SetForegroundPatternColor(-16777216);
wordCell=wordTable.Cell(1,1);
wordCell.Select();
wordSelection.TypeText("Range");
wordSelection.MoveRight(&CComVariant(12),&CComVariant(1),&CComVariant(0));
wordSelection.TypeText("Samples");
wordSelection.MoveRight(&CComVariant(12),&CComVariant(1),&CComVariant(0));
wordSelection.TypeText("Percentage");
wordSelection.MoveRight(&CComVariant(12),&CComVariant(1),&CComVariant(0));
wordSelection.TypeText("Calculation");
//
//Save document as report
SYSTEMTIMEsysTime;
GetLocalTime(&sysTime);
CStringstrReport;
strReport.Format("%d年-%d月-%d日 %d-%d-%d 报告",sysTime.wYear,sysTime.wMonth,
sysTime.wDay,sysTime.wHour,sysTime.wMinute,sysTime.wSecond);
strReport=strPath+""""+strReport;
wordDoc.SaveAs(COleVariant(strReport),COleVariant((short)0),vOpt,vOpt,vOpt,vOpt,vOpt,vOpt
,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt,vOpt);
//Release com
wordFont.ReleaseDispatch();
wordCells.ReleaseDispatch();
wordShading.ReleaseDispatch();
wordTable.ReleaseDispatch();
wordTables.ReleaseDispatch();
wordRange.ReleaseDispatch();
wordSelection.ReleaseDispatch();
wordDoc.RecheckSmartTags();
wordDocs.ReleaseDispatch();
wordApp.ReleaseDispatch();
returnTRUE;
}
注释如下:
1. 使用之前比忘记先进行COM环境的初始化,最好放在BOOLCMDIDemoApp::InitInstance()里吧。
//Initialize COM context
if (FAILED(::CoInitialize(NULL)))
{
AfxMessageBox("Initialize COM context failed!");
returnFALSE;
}
2. 注意几个函数的用法:
a) wordSelection.EndOf(COleVariant((short)6),COleVariant((short)0));
b) wordSelection.EndKey(&CComVariant(10),&CComVariant(1));
c) wordSelection.HomeKey(&CComVariant(5),&CComVariant(1));
d) wordTable=wordTables.Add(wordRange,5/*row*/,4/*column*/,&defaultBehavior,&AutoFitBehavior);
这几个函数可以说是我收获最大的地方了,EndOf/EndKey/HomeKey实现了当前焦点的任意移动,比如到一个文档的末尾或者行尾、表格的操作位置等。举例来说:EndOf (VARIANT* Unit, VARIANT* Extend) 其第二个参数Extend决定了你是单纯的移动光标还是扩展移动选中内容。通过VBA参考,你可以知道wdMove=0 wdExtend=1,这样就可以决定是移动还是扩展选择内容了。
当然还有其他很多操作可以摸索,大可以先用word的宏录制,然后编写自己的VC代码,不过确实是个繁琐的过程,很多VBA常量需要查找具体的value替换。
通过预先的模版,你可以实现打开一个word模版,然后添加你自己的内容,灵活应用。然后保存为自己的报告。请参阅我的例子自己实现吧。Enjoy it by yourself...... J
由于时间关系,我还没有摸索通如何在word报告中插入图表(chart/bar/pie)以及如何插入图片jpg等,这样就可以做出图文并茂的报告了。如果你有经验,欢迎交流共享。
2007-12-6
更多技术文章请参看施昌权的个人网站: http://www.joyvc.cn