(前年11月就说要写这篇技术日志了,一直拖到今天,直到自己觉得再不写会忘掉的时候。唉,现在自己果然是很懒啊,争取以后能一个星期写一篇,我是不是应该到CSDN去写呢?总是感觉在校内写技术日志不伦不类……)
---------------------------------------
首先,把我参考的两个地址放上来,博主写到很好,我这里只是把学到的东西做记录自己备查而已。
用Visual C++操纵MS Word:
http://www.cnblogs.com/scq2099yt/archive/2008/01/07/1028697.html
MFC/VC++调用word进行报表制作:
http://www.cnblogs.com/scq2099yt/archive/2008/01/07/1028717.html
其次,说说重点:
重点就是怎么把VBA_Sub MyReporter.bas里的VBA代码转换成WORD.OLE代码,上面的两篇文章写的很好,照着一步一步做就成了。
下面,一步一步开始吧:
1. 首先,要打开Word的宏记录功能。
备注:在Word中,使用VBA为脚本的宏,可以使文件具有一定逻辑处理功能。例如自动生成及处理数据等。
2. 然后创建一个新宏
3. 记录一个宏,在记录好以后,可以对宏进行简单的编辑,想调试看运行结果时,点击“运行”按钮。这一步很重要,在把这个VBA脚本翻译成C++可执行的代码前,这里的逻辑就是最后生成Word文档的逻辑,因此,要仔细调试,把其中没有必要的步骤去除,尽量精简生成文档的步骤。
4. 在最终获得一个这样的脚本后,就可以准备开始C++的编程了,这里,贴出我完成的脚本(为了不公开项目里的数据,这里我稍做改动,把数据相关的内容全部替换了)
Sub MyReporter()
Documents.Add DocumentType:=wdNewBlankDocument ' //生成一个空文档
Selection.TypeText Text:="某某报表" ' //输入第1行内容
Selection.TypeParagraph ' //换行
Selection.TypeText Text:="行1:" ' //输入第2行内容
Selection.TypeParagraph ' //换行
Selection.TypeText Text:="行2:" ' //输入第3行内容
Selection.TypeParagraph ' //换行
Selection.TypeText Text:="行3:" ' //输入第4行内容
Selection.TypeParagraph ' //换行
Selection.TypeText Text:="行4:" ' //输入第5行内容
Selection.TypeParagraph ' //换行
Selection.TypeText Text:="行5" ' //输入第6行内容
Selection.TypeParagraph ' //换行
' //添加一个6行4列的表格,使用默认样式
ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=6, NumColumns:= _
4, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
wdAutoFitFixed
' //添加表的内容并设置表的格式
' //输入表内第1行内容
Selection.TypeText Text:="列1" ' //输入第1列内容
Selection.MoveRight Unit:=wdCharacter, Count:=1 ' //向右移动鼠标到下一列
Selection.TypeText Text:="列2" ' //输入第2列内容
Selection.MoveRight Unit:=wdCharacter, Count:=1 ' //向右移动鼠标到下一列
Selection.TypeText Text:="列3" ' //输入第3列内容
Selection.MoveRight Unit:=wdCharacter, Count:=1 ' //向右移动鼠标到下一列
Selection.TypeText Text:="列4" ' //输入第4列内容
' //输入表内第2行内容
Selection.MoveDown Unit:=wdLine, Count:=1 ' //向下移动鼠标到下一行
Selection.MoveLeft Unit:=wdCharacter, Count:=3 ' //向左移动鼠标到第1列
Selection.TypeText Text:="列1" ' //输入第1列内容
Selection.MoveRight Unit:=wdCharacter, Count:=3 '// 向右移动鼠标到第4列
Selection.TypeText Text:="列4" ' //输入第4列内容
' //输入表内第3行内容
Selection.MoveDown Unit:=wdLine, Count:=1 ' //向下移动鼠标到下一行
Selection.MoveLeft Unit:=wdCharacter, Count:=3 ' //向左移动鼠标到第1列
Selection.TypeText Text:="列1" ' //输入第1列内容
Selection.MoveRight Unit:=wdCharacter, Count:=1 ' // 向右移动鼠标到第2列
Selection.TypeText Text:="列2" '//输入第2列内容
Selection.MoveRight Unit:=wdCharacter, Count:=1 ' // 向右移动鼠标到第3列
Selection.TypeText Text:="列3" '//输入第3列内容
Selection.MoveRight Unit:=wdCharacter, Count:=1 ' // 向右移动鼠标到第4列
Selection.TypeText Text:="列4" '//输入第4列内容
' //输入表内第4行内容
Selection.MoveDown Unit:=wdLine, Count:=1 ' //向下移动鼠标到下一行
Selection.MoveLeft Unit:=wdCharacter, Count:=3 ' //向左移动鼠标到第1列
Selection.TypeText Text:="列1" ' //输入第1列内容
Selection.MoveRight Unit:=wdCharacter, Count:=3 ' //向右移动鼠标到第4列
Selection.TypeText Text:="列4" ' //输入第4列内容
' //输入表内第5行内容
Selection.MoveDown Unit:=wdLine, Count:=1 ' //向下移动鼠标到下一行
Selection.MoveLeft Unit:=wdCharacter, Count:=3 ' //向左移动鼠标到第1列
Selection.TypeText Text:="列1" ' //输入第1列内容
Selection.MoveRight Unit:=wdCharacter, Count:=3 ' //向右移动鼠标到第4列
Selection.TypeText Text:="列4" ' //输入第4列内容
' //输入表内第6行内容
Selection.MoveDown Unit:=wdLine, Count:=1 ' //向下移动鼠标到下一行
Selection.MoveLeft Unit:=wdCharacter, Count:=3 ' //向左移动鼠标到第1列
Selection.TypeText Text:="列1" ' //输入第1列内容
Selection.MoveRight Unit:=wdCharacter, Count:=3 ' //向右移动鼠标到第4列
Selection.TypeText Text:="列4" ' //输入第4列内容
' //设置表的格式
Selection.MoveUp Unit:=wdLine, Count:=5 ' //向上移动鼠标到表的第1行(目前鼠标在第1行第4列最后一个字符后)
Selection.MoveLeft Unit:=wdCharacter, Count:=15 ' //向左移动鼠标到第1列的第1个字符前
Selection.MoveDown Unit:=wdLine, Count:=5, Extend:=wdExtend ' //向下选取5行,共选取6行(执行这句后,第1列全部选中)
Selection.MoveRight Unit:=wdCharacter, Count:=3, Extend:=wdExtend ' //向右选取3列,共选取4列(执行这句后,整个表被选中)
Selection.ParagraphFormat.Alignment = wdAlignParagraphCenter ' //设置对齐方式为“居中”
' //开始设置表以前内容的格式
Selection.MoveUp Unit:=wdLine, Count:=1 ' //向上移动鼠标到上一行
Selection.ParagraphFormat.Alignment = wdAlignParagraphCenter '//设置此行为“居中”格式
Selection.MoveUp Unit:=wdLine, Count:=5 '// 向上移动鼠标到第1行
Selection.ParagraphFormat.Alignment = wdAlignParagraphCenter '//设置标题行为“居中”格式
Selection.EndKey Unit:=wdLine ' //将鼠标定位到第1行末
Selection.HomeKey Unit:=wdLine, Extend:=wdExtend ' //将鼠标定位到第1行首,同时选取整行
Selection.Font.Bold = wdToggle ' //设置标题行为“粗体”
Selection.Font.Size = 15 ' //设置标题行字号为15(小三号)
Selection.MoveDown Unit:=wdLine, Count:=1 ' //向下移动鼠标到正文第1行
Selection.HomeKey Unit:=wdLine ' //将鼠标定位到正文第1行首,(第2行行首)
Selection.MoveDown Unit:=wdLine, Count:=11, Extend:=wdExtend ' //向下选取除标题行外的全部内容
Selection.Font.Size = 12 ' //设置字号为12(小四号)
Selection.WholeStory '// 选取全部内容
Selection.Font.Name = "宋体" '// 设置全部内容为“宋体”
' //保存文件为《某某报表.doc》到默认位置,WORD的默认路径是“我的文档”
ActiveDocument.SaveAs FileName:="某某报表.doc", FileFormat:= _
wdFormatDocument, LockComments:=False, Password:="", AddToRecentFiles:= _
True, WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:= _
False, SaveNativePictureFormat:=False, SaveFormsData:=False, _
SaveAsAOCELetter:=False
' 退出程序,关闭Word
Application.Quit
End Sub
5. 这就是最后一步了,就是把上面的VBA编程C++可执行的代码。当然,在生成这个工程的时候,一定要添加外部的库,这里,在MFC中操作WORD2003的库使用的是 MSWORD.OLB ,一般情况下,可以在OFFICE所在的文件夹下,通过搜索获得。对于如何添加这个外部链接库,这里不做记录了,会MFC的人,这个是基本功。那么在生成MFC工程后,把上面的VBA代码,一条一条翻译成C++的代码就行了,以下是翻译的结果:
(把以下代码放到一个事件中,比如对一个Button的单击响应事件中,就可以运行了)
//****待用的操作WORD的 常量
const int wdCharacter = 1;
const int wdLine = 5;
const int wdAlignParagraphCenter = 1;
const int wdExtend = 1;
const int wdToggle = 9999998;
const int wdFormatDocument = 0;
const int wdWord9TableBehavior = 1;
const int wdAutoFitFixed = 0;
const int wdNULL = 0;
const int wdNewBlankDocument = 0;
const int wdWindowStateMinimize = 2;
//****待用的操作WORD的 变量
_Application wordApp;
Documents wordDocs;
_Document wordDoc;
Selection wordSelection;
Range wordRange;
Tables wordTables;
Table wordTable;
Cell wordCell;
Cells wordCells;
_Font wordFont;
Shading wordShading;
Paragraphs wordParagraphs;
//****创建word application实例,失败的话返回false
if (!wordApp.CreateDispatch(_T("Word.Application")))
{
AfxMessageBox("Word CreateDispatch Failed!"); //显示错误信息
return FALSE; //返回false
}
wordDocs=wordApp.GetDocuments();//获得 documents 实例
//****添加新的空白文档(调用COM)
//(参考自:http://www.cnblogs.com/scq2099yt/archive/2008/01/07/1028717.html)
CComVariant tpl(_T("")),Visble,DocType(0),NewTemplate(false);
wordDoc=wordDocs.Add(&tpl,&NewTemplate,&DocType,&Visble);
wordSelection=wordApp.GetSelection(); //获得 wordSelection 实例
//****添加文字
wordSelection.TypeText("某某报表"); //输出1行
wordSelection.TypeParagraph(); //换行
wordSelection.TypeText("行1:"); //输出2行
wordSelection.TypeParagraph(); //换行
wordSelection.TypeText("行2:"); //输出3行
wordSelection.TypeParagraph(); //换行
wordSelection.TypeText("行3:"); //输出4行
wordSelection.TypeParagraph(); //换行
wordSelection.TypeText("行4:"); //输出5行
wordSelection.TypeParagraph(); //换行
wordSelection.TypeText("行5"); //输出6行
wordSelection.TypeParagraph(); //换行
//****插入表格
wordTables=wordDoc.GetTables(); //获得表格
wordRange = wordSelection.GetRange();
//添加一个6行4列的表格,使用默认样式
wordTables.Add(wordRange,
6, // 行数
4, // 列数
COleVariant((short)wdWord9TableBehavior),
COleVariant((short)wdAutoFitFixed));
/*** 注意 COleVariant((short)XXX) 这个方法可以把int型转换为 VARIANT* 类型 ***/
//添加表的内容并设置表的格式
//输入表内第1行内容
wordSelection.TypeText("列1"); //输入第1列内容
wordSelection.MoveRight(COleVariant((short)wdCharacter),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向右移动鼠标到下一列
wordSelection.TypeText("列2"); //输入第2列内容
wordSelection.MoveRight(COleVariant((short)wdCharacter),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向右移动鼠标到下一列
wordSelection.TypeText("列3"); //输入第3列内容
wordSelection.MoveRight(COleVariant((short)wdCharacter),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向右移动鼠标到下一列
wordSelection.TypeText("列4"); //输入第4列内容
//输入表内第2行内容
wordSelection.MoveDown(COleVariant((short)wdLine),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向下移动鼠标到下一行
wordSelection.MoveLeft(COleVariant((short)wdCharacter),
COleVariant((short)3),
COleVariant((short)wdNULL)); //向左移动鼠标到第1列
wordSelection.TypeText("列1"); //输入第1列内容
wordSelection.MoveRight(COleVariant((short)wdCharacter),
COleVariant((short)3),
COleVariant((short)wdNULL)); //向右移动鼠标到第4列
wordSelection.TypeText("列4"); //输入第4列内容
//输入表内第3行内容
wordSelection.MoveDown(COleVariant((short)wdLine),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向下移动鼠标到下一行
wordSelection.MoveLeft(COleVariant((short)wdCharacter),
COleVariant((short)3),
COleVariant((short)wdNULL)); //向左移动鼠标到第1列
wordSelection.TypeText("列1"); //输入第1列内容
wordSelection.MoveRight(COleVariant((short)wdCharacter),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向右移动鼠标到第2列
wordSelection.TypeText("列2"); //输入第2列内容
wordSelection.MoveRight(COleVariant((short)wdCharacter),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向右移动鼠标到第3列
wordSelection.TypeText("列3"); //输入第3列内容
wordSelection.MoveRight(COleVariant((short)wdCharacter),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向右移动鼠标到第4列
wordSelection.TypeText("列4"); //输入第4列内容
//输入表内第4行内容
wordSelection.MoveDown(COleVariant((short)wdLine),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向下移动鼠标到下一行
wordSelection.MoveLeft(COleVariant((short)wdCharacter),
COleVariant((short)3),
COleVariant((short)wdNULL)); //向左移动鼠标到第1列
wordSelection.TypeText("列1"); //输入第1列内容
wordSelection.MoveRight(COleVariant((short)wdCharacter),
COleVariant((short)3),
COleVariant((short)wdNULL)); //向右移动鼠标到第4列
wordSelection.TypeText("列4"); //输入第4列内容
//输入表内第5行内容
wordSelection.MoveDown(COleVariant((short)wdLine),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向下移动鼠标到下一行
wordSelection.MoveLeft(COleVariant((short)wdCharacter),
COleVariant((short)3),
COleVariant((short)wdNULL)); //向左移动鼠标到第1列
wordSelection.TypeText("列1"); //输入第1列内容
wordSelection.MoveRight(COleVariant((short)wdCharacter),
COleVariant((short)3),
COleVariant((short)wdNULL)); //向右移动鼠标到第4列
wordSelection.TypeText("列4"); //输入第4列内容
//输入表内第6行内容
wordSelection.MoveDown(COleVariant((short)wdLine),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向下移动鼠标到下一行
wordSelection.MoveLeft(COleVariant((short)wdCharacter),
COleVariant((short)3),
COleVariant((short)wdNULL)); //向左移动鼠标到第1列
wordSelection.TypeText("列1"); //输入第1列内容
wordSelection.MoveRight(COleVariant((short)wdCharacter),
COleVariant((short)3),
COleVariant((short)wdNULL)); //向右移动鼠标到第4列
wordSelection.TypeText("列4"); //输入第4列内容
//设置表的格式
wordSelection.MoveUp(COleVariant((short)wdLine),
COleVariant((short)5),
COleVariant((short)wdNULL)); //向上移动鼠标到表的第1行(目前鼠标在第一行第4列最后一个字符后)
wordSelection.MoveLeft(COleVariant((short)wdCharacter),
COleVariant((short)15),
COleVariant((short)wdNULL)); //向左移动鼠标到第1列的第1个字符前
wordSelection.MoveDown(COleVariant((short)wdLine),
COleVariant((short)5),
COleVariant((short)wdExtend)); //向下选取5行,共选取6行(执行这句后,第1列全部选中)
wordSelection.MoveRight(COleVariant((short)wdCharacter),
COleVariant((short)3),
COleVariant((short)wdExtend)); //向右选取3列,共选取4列(执行这句后,整个表被选中)
wordParagraphs = wordSelection.GetParagraphFormat(); //获得对齐方式实例
wordParagraphs.SetAlignment(wdAlignParagraphCenter); //设置表中的全部内容为“居中”
//开始设置表以前内容的格式
wordSelection.MoveUp(COleVariant((short)wdLine),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向上移动鼠标到上一行
wordParagraphs = wordSelection.GetParagraphFormat(); //获得对齐方式实例
wordParagraphs.SetAlignment(wdAlignParagraphCenter); //设置此行为“居中”格式
wordSelection.MoveUp(COleVariant((short)wdLine),
COleVariant((short)5),
COleVariant((short)wdNULL)); // 向上移动鼠标到第1行
wordParagraphs = wordSelection.GetParagraphFormat(); //获得对齐方式实例
wordParagraphs.SetAlignment(wdAlignParagraphCenter); //设置标题行为“居中”
wordSelection.EndKey(COleVariant((short)wdLine),
COleVariant((short)wdNULL)); //将鼠标定位到第1行末
wordSelection.HomeKey(COleVariant((short)wdLine),
COleVariant((short)wdExtend)); //将鼠标定位到第1行末
wordFont = wordSelection.GetFont(); //获得字体实例
wordFont.SetBold(wdToggle); //设置标题行为“粗体”
wordFont.SetSize(15.0); //设置标题行字号为15(小三号)
wordSelection.MoveDown(COleVariant((short)wdLine),
COleVariant((short)1),
COleVariant((short)wdNULL)); //向下移动鼠标到正文第1行
wordSelection.HomeKey(COleVariant((short)wdLine),
COleVariant((short)wdNULL)); //将鼠标定位到正文第1行首,(第2行行首)
wordSelection.MoveDown(COleVariant((short)wdLine),
COleVariant((short)11),
COleVariant((short)wdExtend)); //向下选取除标题行外的全部内容
wordFont = wordSelection.GetFont(); //获得字体实例
wordFont.SetSize(12.0); //设置标题行字号为12(小四号)
wordSelection.WholeStory(); // 选取全部内容
wordFont = wordSelection.GetFont(); //获得字体实例
wordFont.SetName("宋体"); //设置全部内容为“宋体”
//保存文件为《某某报表.doc》到默认位置,和此程序在一起
CString fileName = "//某某报表.doc";
CString fullFileName = GGetAppPath() + fileName;
wordDoc.SaveAs(COleVariant(fullFileName), //FileName
COleVariant((short)wdFormatDocument), //FileFormat
COleVariant((short)FALSE), //LockComments
COleVariant(""), //Password
COleVariant((short)FALSE), //AddToRecentFiles
COleVariant(""), //WritePassword
COleVariant((short)FALSE), //ReadOnlyRecommended
COleVariant((short)FALSE), //EmbedTrueTypeFonts
COleVariant((short)FALSE), //SaveNativePictureFormat
COleVariant((short)FALSE), //SaveFormsData
COleVariant((short)FALSE), //SaveAsAOCELetter
COleVariant((short)wdNULL), //Encoding
COleVariant((short)FALSE), //InsertLineBreaks
COleVariant((short)FALSE), //AllowSubstutitions,
COleVariant((short)wdNULL), //LineEnding
COleVariant((short)wdNULL) //AddBiDiMarks
);
//退出程序,关闭Word
wordApp.Quit(COleVariant((short)wdNULL),
COleVariant((short)wdNULL),
COleVariant((short)wdNULL));
return TRUE; // 生成成功,返回TRUE
6. 最后,编译,调试,运行,哈哈,最后,我生成了一个这样的表: