OLE,全称Object Linking and Embedding,即对象链接和嵌入技术,是Windows系统中允许应用程序共享数据和程序功能的一种标准的便利方法。
在PowerBuilder中,在窗口画板上,可以放置OLE控件,把Windows系统内注册的OLE对象嵌入到界面中,该控件是被嵌入的对象的容器,用户能激活该OLE对象,调出产生它的原始服务程序,可视化编辑修改。
也能用编程的方法,在内存中创建对象,连接到服务程序,调用相应功能,设置对象的各种属性。这种方法不可视地操作对象,发送命令,并不需要在窗口中放置一个OLE控制,叫做“OLE自动化”。在这种情况下,还可以设置服务程序的可视属性为“True”,让服务程序显示在用户面前。
在PowerBuilder中,OLEObject对象类型是专门用于“OLE自动化”的。OLEObject是个动态对象类型,这意味着编译器会接受这个对象的任何属性、方法和参数列表,PowerBuilder不知道你调用的属性和方法是否有效,而是把它留给服务程序自己去判断,如果确实没有,就会在运行的时候报错。
使用OLEObject对象变量编程,少不了如下四步:
1. 声明变量,创建对象
OLEObject myoleobject
myoleobject = CREATE OLEObject
2. 连接到某个具体的OLE对象
myoleobject.ConnectToObject … 或者
myoleobject.ConnectToNewObject …
3. 利用OLE的属性和方法操作该对象
myoleobject.property = … /* 属性 */
myoleobject.function(…) /* 方法 */
4. 断开和OLE对象的连接,销毁对象,释放内存。
myoleobject.Quit()
myoleobject.DisconnectObject()
Destroy myoleobject
这种用编程的方法操作OLE对象,应用非常普遍。本文结合三个典型的应用实例,诠释具体的编程步骤。
一, 操作Word文档对象
要创建一份文件名为 contact.doc 的Word文档格式的信函,其中有四个书签:
a) name1 - 寄信人名字
b) name2 – 收信人称呼
c) address1 – 寄信人地址
d) body – 信的正文
该信函要有如下内容:
Multimedia Promotions, Inc.
1234 Technology Drive
Westboro, Massachusetts
May 16, 2005
[bookmark name1]
[bookmark address1]
Dear [bookmark name2]
[bookmark body]
Sincerely,
Frank Wang
程序代码如下所示:
OLEObject o1
integer result
string ls_name, ls_addr, ls_body
contact_ltr = CREATE oleObject /* 创建对象,分配内存 */
result = o1.ConnectToNewObject("Word.Application") /* 连到服务器 */
IF result <> 0 THEN /* 检测错误 */
DESTROY contact_ltr
MessageBox("OLE 错误", "不能连到Word. 出错代码: " + Sring(result))
RETURN
END IF
o1.Documents.open("c:\contact.doc") /* 打开预定义书签的文档 */
ls_name = … /* 人名存入变量 */
o1.Selection.goto("name1") /* 定位到书签name1 */
o1.Selection.typetext(ls_name) /* 插入人名 */
o1.Selection.goto("name2") /* 定位到书签name2 */
o1.Selection.typetext(ls_name) /* 插入人名 */
ls_addr = … /* 地址 */
o1.Selection.goto("address1") /* 定位到书签address1 */
o1.Selection.typetext(ls_addr) /* 插入地址 */
ls_body = … /* 正文 */
o1.Selection.goto("body") /* 定位到书签body */
o1.Selection.typetext(ls_body) /* 插入正文 */
o1.Application.printout() /* 打印 */
o1.Documents.close /* 关闭文档 */
o1.Quit()
o1.DisconnectObject()
DESTROY
二, 操作Excel文档对象
要生成某会员管理系统的会员资料卡,卡片中有多项内容规整地组合在一起,使用PB的DataWindow技术不能制作如此复杂的业务报表,因此利用Excel画出模板,然后在PB程序中往模板的各个位置填入相应内容。程序代码如下:
…
oleobject xlApp, xlSheet
xlApp = CREATE OLEObject
xlSheet = CREATE OLEObject
string ls_current_dir, ls_report_filename
ls_current_dir = GetCurrentDirectory()
ls_report_filename = ls_current_dir + "\report\会员资料卡.xls"
If xlApp.ConnectToObject(ls_report_filename) <> 0 Then
Messagebox("OLE 错误","不能连接到相应的 Excel表格")
Return t
End If
xlSheet = xlApp.application.workbooks(1).worksheets(1)
string ls_mem_id, ls_mem_name, ls_id_card_no, ls_sex, ls_join_date
string ls_join_unit_name, ls_employ_status
ls_mem_id = … /* 会员号 */
ls_mem_name = … /* 会员名 */
ls_id_card_no = … /* 身份证号码 */
ls_sex = … /* 性别 */
ls_join_date = … /* 入会日期 */
ls_join_unit_name = … /* 入会单位 */
ls_employ_status = … /* 就业状况 */
xlSheet.Range("B3").Value = ls_mem_name
xlSheet.Range("E3").Value = ls_sex
xlSheet.Range("H3").Value = "'" + ls_id_card_no
xlSheet.Range("B4").Value = "'" + ls_mem_id
xlSheet.Range("E4").Value = ls_join_date
xlSheet.Range("H4").Value = ls_join_unit_name
xlSheet.Range("H6").Value = ls_employ_status
……
xlSheet.Range("F30").Value = "打印日期:2005年05月16日')
xlApp.application.workbooks(1).saved = true /* 退出时不会提示保存 */
xlSheet.PrintOut /* 打印 */
xlApp.application.quit() /* 退出 */
xlApp.DisconnectObject() /* 断开连接 */
destroy xlApp /* 释放对象 */
destroy xlSheet /* 释放对象 */
三, 操作BusinessObjects文档对象 /
利用PB程序传递参数,自动刷新、打印BusinessObjects文档。
…
OLEObject boApp,boDoc 2
boApp = CREATE OLEObject
boDoc = CREATE OLEObject /* 打开的当前活动BO文档对象 */
integer li_result
li_result = boApp.ConnectToNewObject("BusinessObjects.Application.6")
string lstr_err
Choose Case li_result
case -1
lstr_err = '无效的调用'
case -2
lstr_err = '系统中没有安装 BusinessObjects.Application.6 这个类'
……
end choose
if li_result <> 0 then )
MessageBox("OLE 错误","不能连接到相应的 BO 对象 ~r~n" + lstr_err)
Destroy boApp
Destroy boDoc
return
end if
boApp.Interactive = False /* 刷新报表时,不显示参数对话框 */
string ls_filename /* 报表文件名称 */
string ls_fullname /* 报表文件带路径的全名 */
string ls_savedfile /* 报表文件带路径的全名 */
integer li_print_copies /* 打印份数 */
for i = 1 to dw1.RowCount() /* 选中的行 */
ls_filename = dw1.GetItemString(i,"bo_report_name")
ls_fullname = bo_dir + '\' + ls_filename + '.rep'
ls_savedfile = bo_dir + '\today\' + ls_filename + '.rep'
li_print_copies = dw1.GetItemNumber(i,"bo_print_pages")
if FileExists(ls_fullname) then
boDoc = boApp.Documents.Open(ls_fullname) /* 打开文档 */
wf_set_para_value(boDoc) /* 设置刷新报表时输入的参数值 */
boDoc.Refresh() /* 刷新 */
if DirectoryExists(bo_dir + '\today\') then
boDoc.SaveAs(ls_savedfile)
else
MessageBox('错误!','保存目录不存在')
exit
end if
for j = 1 to li_print_copies /* 打印 */
boDoc.PrintOut()
next
boDoc.Close(1) >
else
MessageBox('警告!','文件 ' + ls_fullname + ' 不存在')
end if
next
boApp.Application.Quit()
boApp.DisconnectObject()
Destroy boDoc
Destroy boApp
上面讲述的三个实例,是PowerBuilder开发工具使用OLE技术非常典型的应用。其中例一用于自动生成Word文档,例二用于构造复杂的业务报表,例三用于调用刷新BO报表,都是笔者在实际工作中积累的可运行代码,可以直接借鉴使用。本文拘于篇幅限制,在不影响领会基本意图的情况下做了删节。
PB的早期版本就开始支持OLE,但据笔者的使用经验,8.0以前的版本不是很完善。譬如,往Excel表格中填写中文时,用PB6和PB7都会出现乱码,用8.0以后的版本才解决问题。
本文例一和例三程序中,都使用了ConnectToNewObject()方法,该方法要求提供一个字符串格式的类型参数,例一中给的类型是"Word.Application",例三中给的类型是"BusinessObjects.Application.6",怎样知道这些类型呢?这些类型可以参考注册表中HKEY_CLASSES_ROOT分支下的名称,结合相应对象的SDK文档来确定。
为了方便地使用OLE编程技术,平时要注意收集各种对象的SDK文档。对于Microsoft Office而言,查看SDK文档很方便,从任意一个应用程序中的菜单“编辑”->“宏”->“Visual Basic编辑器”调出VBA的编辑界面,在帮助里就可以找到Microsoft Office的文档对象模型,以及Word、Excel等各种文档的属性和操作方法,使用起来非常方便。对于其它对象,便需要专门提供的SDK文档了。
在PowerBuilder程序中应用OLE编程技术,通过调用其它服务程序完成对应操作,编辑和输出各种文档,大大扩展了PB应用程序的功能,值得我们多多留意并加以使用。
![](http://images.enet.com.cn/end.gif)