WebService系列:Office VBA调用Web Service
二月 13, 2009 in Oracle 融合中间件
Microsoft Office软件作为办公软件系统,已成为人们日常工作的必备工具,而其中的Excel更是各类人员的得力工具,
本文介绍基于Office VBA生成Web Service的客户端代理程序,使VBA程序能够调用Web Service。
基于的系统配置如下:
- Window XP
- Office 2003
- MS Office2003 WebServices Tools
- SOAP Toolkit3.0
- OC4J 10.1.3.3.0
一、使用MS Office2003 WebServices Tools
MS Office2003 WebServices Tools工具是为了简化在VBA中编写Web Services代理程序代码而设计的一个辅助工具,
它根据Web Services的wsdl描述文件生成对应的代理类以及用户自定义的类型结构类。
在 Office 应用程序中,单击“Visual Basic 编辑器”的“工具”菜单中的“Web 服务引用”即可启动 Microsoft Office 2003 Web Services Toolkit。
该工具提供了可用于下列用途的界面:
- 发现 Web 服务
- 选择所需的服务
- 创建为引用这些服务的 Visual Basic for Applications (VBA) 项目充当 Web 服务代理的类。
选择“Web服务URL(U)”,输入wsdl的URL地址,如
http://ORACLE:8888/aronehome/UserListInfoSoapHttpPort
点击搜索按钮,右边会显示出Web Services拥有的方法,点击“添加”按钮创建各种类。
根据wsdl的描述内容,它会创建几个类型的类文件:
| 类前缀 | 类类型 | 说明 |
| clsof_Factory_ | 对象工厂 | 如果有用户定义的类型结构则产生 |
| clsws_ | Web 服务代理 | Web Service的代理类,任何时候都产生 |
| struct_ | 用户定义的类型结构 | 非基本类型,用户自定义的类型则会产生,如PL/SQL中用户定义的Type或者Table都会产生 |
如上面的UserListInfo Web Services会产生如下的3个VBA类模块:
- clsof_Factory_UserListInfo
- clsws_UserListInfo
- struct_AronehomeDemoWs2User:对应的是PL/SQL中声明的user_type自定义类型
二、服务代理类模块描述
Web服务代理类模块主要完成以下工作:
- 实例化类(Class_Initialize),按照wsdl要求的类型创建一个SoapClient30对象实例
- 通过实例化的SoapClient30对象调用方法(wsm_getUserList(),wsm_updateUserInfo(ByVal ar_pUserList As Variant))
- 结束调用(Class_Terminate),释放资源
下面是clsws_UserListInfo服务的代理类模块的代码片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | Private sc_UserListInfo As SoapClient30 Private Const c_WSDL_URL As String = "http://oracle:8888/aronehome/UserListInfoSoapHttpPort?wsdl" Private Const c_SERVICE As String = "UserListInfo" Private Const c_PORT As String = "UserListInfoSoapHttpPort" Private Const c_SERVICE_NAMESPACE As String = "http://com/aronehome/demo/UserListInfo.wsdl" Private Sub Class_Initialize() Dim str_WSML As String str_WSML = "" str_WSML = str_WSML & "" str_WSML = str_WSML & "" str_WSML = str_WSML & "" str_WSML = str_WSML & "" str_WSML = str_WSML & "" str_WSML = str_WSML & "" str_WSML = str_WSML & "" Set sc_UserListInfo = New SoapClient30 sc_UserListInfo.MSSoapInit2 c_WSDL_URL, str_WSML, c_SERVICE, c_PORT, c_SERVICE_NAMESPACE 'Use the proxy server defined in Internet Explorer's LAN settings by 'setting ProxyServer to sc_UserListInfo.ConnectorProperty("ProxyServer") = "" 'Autodetect proxy settings if Internet Explorer is set to autodetect 'by setting EnableAutoProxy to True sc_UserListInfo.ConnectorProperty("EnableAutoProxy") = True Set sc_UserListInfo.ClientProperty("GCTMObjectFactory") = New clsof_Factory_UserListInfo End Sub Private Sub Class_Terminate() 'Error Trap On Error GoTo Class_TerminateTrap Set sc_UserListInfo = Nothing Exit Sub Class_TerminateTrap: UserListInfoErrorHandler ("Class_Terminate") End Sub Private Sub UserListInfoErrorHandler(str_Function As String) 'SOAP Error If sc_UserListInfo.FaultCode <> "" Then Err.Raise vbObjectError, str_Function, sc_UserListInfo.FaultString 'Non SOAP Error Else Err.Raise Err.Number, str_Function, Err.Description End If End Sub Public Function wsm_getUserList() As Variant 'Error Trap On Error GoTo wsm_getUserListTrap wsm_getUserList = sc_UserListInfo.getUserList() Exit Function wsm_getUserListTrap: UserListInfoErrorHandler "wsm_getUserList" End Function Public Sub wsm_updateUserInfo(ByVal ar_pUserList As Variant) 'Error Trap On Error GoTo wsm_updateUserInfoTrap sc_UserListInfo.updateUserInfo ar_pUserList Exit Sub wsm_updateUserInfoTrap: UserListInfoErrorHandler "wsm_updateUserInfo" End Sub |
这样VBA程序或者VBA宏就可以调用服务代理类中的方法来调用Web Service了
三、编写VBA宏代码调用代理类方法来调用Web Service
上面通过MS Office2003 WebServices Tools工具已经生成了调用Web Service的VBA代理类,下面编写VBA宏代码来调用它们
1,调用结果返回自定义复杂类型
上面的PL/SQL函数示例声明中看到,get_user_list函数返回一个基于自定义类型user_type的Table类型user_tbl,
对应的是通过MS Office2003 WebServices Tools工具可以生成的代理类clsws_UserListInfo中的wsm_getUserList()方法
下面是VBA宏代码调用的片段:
1 2 3 4 5 6 7 8 9 10 11 | Dim clsUserListInfo As clsws_UserListInfo Dim objCurUserListArray() As struct_AronehomeDemoWs2User Dim objCurUser As struct_AronehomeDemoWs2User Set clsUserListInfo = New clsws_UserListInfo objCurUserListArray = clsUserListInfo.wsm_getUserList For i = 0 To UBound(objCurUserListArray) Set objCurUser = objCurUserListArray(i) MsgBox objCurUser.username + "" + objCurUser.password Next |
2,提供复杂数据类型参数调用WebServices
上面的PL/SQL函数示例声明中看到,update_user_info函数返回一个基于自定义类型user_type的Table类型user_tbl,
对应的是通过MS Office2003 WebServices Tools工具可以生成的代理类clsws_UserListInfo中的wsm_getUserList()方法
下面是VBA宏代码调用的代码片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Dim lines As Integer Dim clsUpdateUserInfo As clsws_UserListInfo Dim objCurUserInfoArrary() As struct_AronehomeDemoWs2User Dim objCurUserInfo As struct_AronehomeDemoWs2User lines = 3 ReDim objCurUserInfoArrary(lines) As struct_AronehomeDemoWs2User For i = 1 To 3 Set objCurUserInfo = New struct_AronehomeDemoWs2User objCurUserInfo.userid = i objCurUserInfo.username = "a" + i objCurUserInfo.password = "b" + i Set objCurUserInfoArray(i) = objCurUserInfo Next Set clsUpdateUserInfo = New clsws_UserListInfo clsUpdateUserInfo.wsm_updateUserInfo objCurUserInfoArray |
注:上面传给Web Service的Table为objCurUserInfoArray,而PL/SQL在接收到这个Table时的count数要比实际的多一行,多出的一行全是空值,
是由于SOAP在进行序列化的过程中添加的,因此在PL/SQL代码中,需要将传入的Table变量的count数减去1,可能有的同学已经注意到PLSQL update_user_info方法中的“p_user_list.count -1”了。
三、执行VBA程序
如果上面的Web Service按照前期的课题中一样添加的安全性配置,那通过上面的代码在VBA程序中调用Web Services是执行不成功的,报出如下的错误:
ERROR OWS-04005: Missing <wsse:Security> in SOAP Header
和我们使用OC4J自带的测试页面进行测试时一样的错误,是由于没有提供安全验证信息到SOAP Header中。
而通过MS Office2003 WebServices Tools工具为我们产生的Web Services代理类中没有安全验证相关的内容,我们需要自己编写程序来产生SOAP Header的内容
下一篇文章将描述如何在VBA调用中添加认证信息以支持Web Service的认证
–
