BCB使用Variant和Automation对象操作Word
最近,我需要在基于BCB开发的程序上增加导出Word报表功能,由于之前使用Variant和Automation对象操作过Excel,于是放弃了使用Office2k的TWordApplication控件的方式,直接使用Variant就开始了。期间,我在网上搜索资料,发现会的人还真是少,当然了,除了“OLE专业户”妖哥了,在此表示感谢。通过这几天的努力,我还真收获了不少,特别是如何将VBA语言转换为BCB语言。想起这几天网上搜资料的辛苦,于是我决定把心得写下来,希望能帮到自己和其他有需要的人。
--By OYYJ
一、 基础概念
Word对象代表一个Word 的元素,如文档(Documents)、段落(Paragraphs)、表格(Tables)书签或单个的字符。
集合是用来存储Word中的一组对象。每一个集合将有两个使它有用的关键资源:Count属性和Item方法。Count属性说明在集合中有多少对象。Item方法则用于取得对一个请求项的引用,或者通过数字或者通过名字(如果该对象有一个的话)。例如,一个集合对象中可包含文档中的所有书签对象。通过使用属性和方法,可以修改单个的对象,也可修改整个的对象集合。属性是对象的一个特性或者该对象操作的一个方面。例如文档属性包含名称、内容、保存状态,以及是否启用修订。要更改一个对象的属性,可以修改属性的值。方法是对象可以进行的动作。
Variant使得使用Automation非常简单,在得到和操作Automation对象时最有用的方法是:
CreateObject()
GetActiveObject()
OleFunction()
OleProcedure()
OlePropertyGet()
OlePropertySet()
OleFunction()、OleProcedure()、OlePropertyGet()、OlePropertySet()本质上是对Exec()方法的包装器。Exec()由BCB使用以便执行一个进程或函数或者以取出或设置一个属性值。要做到这个,它依赖于如下四个类来访问想要的Automation功能:
Function()
Procedure()
PropertyGet()
PropertySet()
两种不同的使用方法见如下代码:
创建一个新的应用程序,放置一个Button在窗体上,命名它为Button_LaunchWord,标题为Launch Word。加入如下代码到该Button的OnClick事件中。
void __fastcall TForm_Automation::Button_LaunchWordClick(TObject *Sender)
{
Variant word_app;
Variant word_docs;
Variant word_select;
word_app = Variant::CreateObject("word.application");
word_docs = word_app.OlePropertyGet("Documents");
word_docs.OleProcedure("Add");
word_app.OlePropertySet("Visible", (Variant)true);
}
使用Exec()建立相同的代码如下:
void __fastcall TForm_Automation::Button_WordExecClick(TObject *Sender)
{
Variant word_app;
Variant word_docs;
Function Documents("Documents");//--Define the Documents funciton
Function AddDocument("Add");//--Define the add documents function
PropertySet Visibility("Visible");//--Define the visibility property
word_app = Variant::CreateObject("word.application");
word_docs = word_app.Exec(Documents);
word_docs.Exec(AddDocument);
Visibility << true;
word_app.Exec(Visibility);
}
二、 VBA转BCB对比
1、 在Word中插入表格的VBA如下:
ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=15, NumColumns:=4, DefaultTableBehavior:=wdWord9TableBehavior,AutoFitBehavior:=wdAutoFitFixed
翻译成BCB如下:
word_select = word_app.OlePropertyGet("Selection");
word_app.OlePropertyGet("ActiveDocument").OlePropertyGet("Tables").
OleProcedure("Add", word_select.OlePropertyGet("Range"), nRowCount, nColCount, 1, 0);
其中VBA的Selection为BCB中Word应用的选中word_app.OlePropertyGet("Selection")。
2、 选中Word中的表1,使表格文字均居中显示的VBA如下:
Selection.Tables(1).Select
Selection.SelectCell
Selection.ParagraphFormat.Alignment = wdAlignParagraphCenter
Selection.Cells.VerticalAlignment = wdCellAlignVerticalCenter
翻译成BCB如下:
word_table = word_app.OlePropertyGet("ActiveDocument").OlePropertyGet("Tables").
OleFunction("Item", 1);//Tables(1)
word_table.OleFunction("Select");//Tables(1).Select
word_select.OleFunction("SelectCell");//Selection.SelectCell
word_select.OlePropertyGet("ParagraphFormat").
OlePropertySet("Alignment", wdAlignParagraphCenter);
//Selection.ParagraphFormat.Alignment = wdAlignParagraphCenter
//使用wdAlignParagraphCenter 需要#include "Word_2K_SRVR.h"
word_select.OlePropertyGet("Cells").
OlePropertySet("VerticalAlignment", wdCellAlignVerticalCenter);
//Selection.Cells.VerticalAlignment = wdCellAlignVerticalCenter
至此,你是否找到了一些规律了呢?更多的就需要自己去尝试了。
三、 例程
在如上创建的工程中,操作Word插入两个表格,一个为15X4的,一个为8X4的,均带
表头。
void __fastcall TForm_Automation::Button_LaunchWordClick(TObject *Sender)
{
Variant word_app;
Variant word_docs;
Variant word_activedoc;
Variant word_select;
Variant word_table;
Variant word_paras;
Variant word_para;
Variant start_cell;
Variant end_cell;
Variant my_cell;
int nRowCount;
int nColCount;
AnsiString filename;
try
{
try
{
word_app = Variant::CreateObject("Word.Application");
}
catch (...)
{
ShowMessage("运行Word出错,请确认安装了Office!");
word_app = Unassigned;
return;
}
if (!DirectoryExists(ExtractFilePath(Application->ExeName) + "\\WordFile"))//文件夹WordFile不存在
{ //创建文件夹WordFile
if (!CreateDir(ExtractFilePath(Application->ExeName) + "\\WordFile"))
throw Exception("无法创建文件夹WordFile");
else
{
SaveDialog_Word->InitialDir = (ExtractFilePath(Application->ExeName) + "WordFile").c_str();
SaveDialog_Word->FileName = (ExtractFilePath(Application->ExeName) + "WordFile\\BCTS-1报表.doc").c_str();
}
}
//文件夹WordFile存在
else
{
SaveDialog_Word->InitialDir = (ExtractFilePath(Application->ExeName) + "WordFile").c_str();
SaveDialog_Word->FileName = (ExtractFilePath(Application->ExeName) + "WordFile\\BCTS-1报表.doc").c_str();
}
if (SaveDialog_Word->Execute())
{
filename = SaveDialog_Word->FileName;
Form_Automation->Enabled = false;
}
else
{
Form_Automation->Enabled = true;
return;
}
try
{
word_app.OlePropertySet("Visible", (Variant)false);
//新建一个文档并保存
word_docs = word_app.OlePropertyGet("Documents");
word_docs.OleProcedure("Add");
word_activedoc = word_app.OlePropertyGet("ActiveDocument");
word_activedoc.OleFunction("SaveAs", filename.c_str());
//
word_select = word_app.OlePropertyGet("Selection");
//添加标题
word_select.OlePropertyGet("Font").OlePropertySet("Size", 20);
word_select.OlePropertyGet("Font").OlePropertySet("Name", "黑体");
word_select.OlePropertyGet("ParagraphFormat").
OlePropertySet("Alignment", wdAlignParagraphCenter);
word_select.OleProcedure("TypeText", "BCTS-1报表\n");
//添加段落
word_select.OlePropertyGet("Font").OlePropertySet("Size", 10);
word_select.OlePropertyGet("Font").OlePropertySet("Name", "宋体");
Procedure AddText("TypeText");
word_select.Exec(AddText << WideString("\n"));
//插入表格1--分、合闸时间测量
nRowCount = 15;
nColCount = 4;
word_activedoc.OlePropertyGet("Tables").OleProcedure("Add", word_select.OlePropertyGet("Range"), nRowCount, nColCount, 1, 0);
//使表格1中文字居中
word_table = word_activedoc.OlePropertyGet("Tables").OleFunction("Item", 1);//Tables(1)
word_table.OleFunction("Select");//Tables(1).Select
word_select.OleFunction("SelectCell");//Selection.SelectCell
word_select.OlePropertyGet("ParagraphFormat").
OlePropertySet("Alignment", wdAlignParagraphCenter);
//Selection.ParagraphFormat.Alignment = wdAlignParagraphCenter
word_select.OlePropertyGet("Cells").
OlePropertySet("VerticalAlignment", wdCellAlignVerticalCenter);
//Selection.Cells.VerticalAlignment = wdCellAlignVerticalCenter
//合并单元格 做表头
//(1, 1)-(1, 4)合并为(1, 1)
start_cell = word_table.OleFunction("Cell", (Variant)1, (Variant)1);
end_cell = word_table.OleFunction("Cell", (Variant)1, (Variant)4);
start_cell.OleProcedure("Merge", end_cell);
start_cell.OlePropertySet("Range", "一、分、合闸时间测量");
start_cell.OleFunction("Select");
word_select.OlePropertyGet("ParagraphFormat").OlePropertySet("Alignment", wdAlignParagraphLeft);
//(2, 1)-(2, 2)合并为(2, 1)
start_cell = word_table.OleFunction("Cell", (Variant)2, (Variant)1);
end_cell = word_table.OleFunction("Cell", (Variant)2, (Variant)2);
start_cell.OleProcedure("Merge", end_cell);
start_cell.OlePropertySet("Range", "合闸时间");
//注意前面已经合并的(2, 1)-(2, 2)变成了新的(2, 1)
start_cell = word_table.OleFunction("Cell", (Variant)2, (Variant)2);
end_cell = word_table.OleFunction("Cell", (Variant)2, (Variant)3);
start_cell.OleProcedure("Merge", end_cell);
start_cell.OlePropertySet("Range", "分闸时间");
//
my_cell = word_table.OleFunction("Cell", (Variant)3, (Variant)1);
my_cell.OlePropertySet("Range", "标准值(ms)");
my_cell = word_table.OleFunction("Cell", (Variant)3, (Variant)2);
my_cell.OlePropertySet("Range", "指示值(ms)");
my_cell = word_table.OleFunction("Cell", (Variant)3, (Variant)3);
my_cell.OlePropertySet("Range", "标准值(ms)");
my_cell = word_table.OleFunction("Cell", (Variant)3, (Variant)4);
my_cell.OlePropertySet("Range", "指示值(ms)");
/*//往表格中填入数据
for (int i = 0; i < 12; i++)
{
my_cell = word_table.OleFunction("Cell", (Variant)(4+i), (Variant)1);
my_cell.OlePropertySet("Range", StringGrid1->Cells[1][i+1].c_str());
my_cell = word_table.OleFunction("Cell", (Variant)(4+i), (Variant)3);
my_cell.OlePropertySet("Range", StringGrid1->Cells[4][i+1].c_str());
}
*/
//添加段落
word_paras = word_activedoc.OlePropertyGet("Paragraphs");
word_paras.OleFunction("Add");
word_paras.OleFunction("Add");
word_para = word_paras.OleFunction("Item", 74);
//插入表格2--弹跳时间测量
nRowCount = 8;
nColCount = 4;
word_activedoc.OlePropertyGet("Tables").OleProcedure("Add", word_para.OlePropertyGet("Range"), nRowCount, nColCount, 1, 0);
//操作表格
word_table = word_activedoc.OleFunction("Range").OlePropertyGet("Tables").OleFunction("Item", 2);
word_table.OleFunction("Select");
word_select.OleFunction("SelectCell");
word_select.OlePropertyGet("ParagraphFormat").OlePropertySet("Alignment", wdAlignParagraphCenter);
word_select.OlePropertyGet("Cells").OlePropertySet("VerticalAlignment", wdCellAlignVerticalCenter);
//合并单元格
//(1, 1)-(1, 4)
start_cell = word_table.OleFunction("Cell", (Variant)1, (Variant)1);
end_cell = word_table.OleFunction("Cell", (Variant)1, (Variant)4);
start_cell.OleProcedure("Merge", end_cell);
start_cell.OlePropertySet("Range", "二、弹跳时间测量");
start_cell.OleFunction("Select");
word_select.OlePropertyGet("ParagraphFormat").OlePropertySet("Alignment", wdAlignParagraphLeft);
//
my_cell = word_table.OleFunction("Cell", (Variant)2, (Variant)1);
my_cell.OlePropertySet("Range", "标准值(ms)");
my_cell = word_table.OleFunction("Cell", (Variant)2, (Variant)2);
my_cell.OlePropertySet("Range", "指示值(ms)");
my_cell = word_table.OleFunction("Cell", (Variant)2, (Variant)3);
my_cell.OlePropertySet("Range", "标准值(ms)");
my_cell = word_table.OleFunction("Cell", (Variant)2, (Variant)4);
my_cell.OlePropertySet("Range", "指示值(ms)");
/*
for (int i = 0; i < 6; i++)
{
my_cell = word_table.OleFunction("Cell", (Variant)(3+i), (Variant)1);
my_cell.OlePropertySet("Range", StringGrid1->Cells[3][i+1].c_str());
my_cell = word_table.OleFunction("Cell", (Variant)(3+i), (Variant)3);
my_cell.OlePropertySet("Range", StringGrid1->Cells[3][i+1+6].c_str());
}
*/
//将光标移到文档结尾
word_select.OleProcedure("EndKey", 6);
}
__finally
{
word_activedoc.OleProcedure("Save");
word_activedoc = Unassigned;
}
}
__finally
{
word_app.OleProcedure("Quit");
word_app = Unassigned;
}
ShowMessage("导出报表完毕!");
Form_Automation->Enabled = true;
}