前面我已经总结了VBA最常见的一些应用;相对来说,下面这几种应用都比较少见一点,这里就是做一个索引,当需要的时候可以直接查询需要的资源。经过前面的了解,大家肯定也猜到了,这些应用基本上都是通过调用COM实现的。所以只要系统底层COM能完成的功能,基本在VBA中都可以去完成。此外,除了调用COM对象完成相应的功能,扩充VBA的能力最纯粹的手段就是直接调用API了。这个已经超出了VBA的范围,这里就是简单提及一下。对于COM对象创建的时候是“前期绑定”还是“后期绑定”的区别也就不再重复了。每个对象,我就是简单总结一下常见的用法。
一、网络应用
直接使用Workbook对象获取网络内容
在装有Frontpage Server Extension的服务器上,可以直接以Workbook的形式保存和打开Excel。除了分享这些Excel文档,直接使用Workbook也可以直接打开和使用网页上的内容。打开以后,基本上就当Sheet一样处理了。
'打开远程Excel
Set oBk = Workbooks.Open("http://www.MySite.com/book1.xlsx")
'另存为
oBk.SaveAs "http://www.MySite.com/Book2.xlsx"
Dim oRng As Range
'打开网页
Set oBk = Workbooks.Open("http://www.x-rates.com/d/USD/table.html")
'查找内容
Set oRng = oBk.Worksheets(1).Cells.Find("British Pound")
'显示内容
MsgBox oRng.Offset(0, 1).Value
使用Web Query获取网络数据
从Excel97加入了Web Query的支持后,几乎在每个新的版本中,这个方面的内容都得到了强化。我们可以使用这个特性获取网络上一张表的数据。主要使用的是Application.QueryTables。例子如下:
Dim oBk As Workbook
Dim oQT As QueryTable
'数字的格式设置
Dim sDecimal As String
Dim sThousand As String
Dim bUseSystem As Boolean
Set oBk = Workbooks.Add
With oBk.Worksheets(1)
Set oQT = .QueryTables.Add( _
Connection:="URL;http://www.x-rates.com/d/USD/table.html", _
Destination:=.Range("A1"))
End With
'设置QueryTable的相关属性
With oQT
.Name = "USD"
'选中特定的表
.WebSelectionType = xlSpecifiedTables
'导入Page上第14个表
.WebTables = "14"
'忽略Page上的格式
.WebFormatting = xlWebFormattingNone
'不会尝试去识别日期
.WebDisableDateRecognition = True
'每次打开文件的时候不会刷新数据
.RefreshOnFileOpen = False
'等待查询结束
.BackgroundQuery = True
'伴随Workbook一起保存数据
.SaveData = True
'根据表中数据调整列宽度
.AdjustColumnWidth = True
End With
With Application
'保存当前文档的分隔符格式
sDecimal = .DecimalSeparator
sThousand = .ThousandsSeparator
bUseSystem = .UseSystemSeparators
'设置分隔符
.DecimalSeparator = "."
.ThousandsSeparator = ","
.UseSystemSeparators = True
'忽略任何错误
On Error Resume Next
'执行查询,等待结束
oQT.Refresh BackgroundQuery:=False
'恢复文档的分隔符格式
.DecimalSeparator = sDecimal
.ThousandsSeparator = sThousand
.UseSystemSeparators = bUseSystem
End With
End Sub
这种方式十分依赖于页面中<table>节点的顺序,需要注意。
使用InternetExplorer对象操纵DOM模型
使用前面的方法都有一定的局限性,如果我们关注的不是整个表,而只是页面的某些部分,这个时候使用InternetExplorer对象是最方便的。这个对象的Document属性代表了整个的页面,可以使用这Document的属性和方法获取页面的各个部分(就是常说的DOM操作)。使用这个对象处理页面内容是最强大,最直接的一种方式。InternetExplorer对象的使用示例:
Dim oIE As InternetExplorer
Dim sPage As String
Dim iGBP As Long, iDec As Long
Dim iStart As Long, iEnd As Long
Dim dRate As Double
'创建隐藏的IE实例,可以通过设置Visible属性来显示IE
Set oIE = New InternetExplorer
'打开网页
oIE.Navigate "http://www.x-rates.com/d/USD/table.html"
'等待加载完毕,也可以使用下面的方式等待:
'While obIE.Busy = True
'DoEventsWend
Do Until oIE.readyState = 4
DoEvents
Loop
'DOM操作
sPage = oIE.Document.body.InnerText
'查找目标
iGBP = InStr(1, sPage, "British Pound")
iDec = InStr(iGBP, sPage, ".")
iStart = InStrRev(sPage, " ", iDec) + 1
iEnd = InStr(iDec, sPage, " ")
dRate = Val(Mid$(sPage, iStart, iEnd - iStart))
MsgBox "The USD/GBP exchange rate is " & dRate
End Sub
这种方式其实也是IE自动化的一种手段:http://www.excely.com/excel-vba/ie-automation.shtml
IE文档对象资料:http://club.excelhome.net/forum.php?mod=viewthread&tid=263887
网页分析资料:http://club.excelhome.net/thread-377077-1-1.html
邮箱登陆问题:http://club.excelhome.net/thread-357475-1-1.html
使用XmlHttp获取网页内容
XmlHttp是一套可以在Javascript、VbScript、Jscript等脚本语言中通过http协议传送或从接收XML及其他数据的一套API。XmlHttp最大的用处是可以更新网页的部分内容而不需要刷新整个页面。来自MSDN的解释:XmlHttp提供客户端同http服务器通讯的协议。客户端可以通过XmlHttp对象(MSXML2.XMLHTTP.3.0)向http服务器发送请求并使用微软XML文档对象模型Microsoft® XML Document Object Model (DOM)处理回应。现在的绝对多数浏览器都增加了对XmlHttp的支持,IE中使用ActiveXObject方式创建XmlHttp对象,其他浏览器如:Firefox、Opera等通过window.XMLHttpRequest来创建xmlhttp对象。 使用这种方式访问网页内容比较快一点,但是兼容性不如使用IE对象的方式。
VBA从网络下载文件是可以通过XmlHttp对象实现的,例子如下:
http.Open "GET", url, True
http.send
If http.ReadyState <> 4 Then
DoEvents
Else
Set oStream = CreateObject("ADODB.Stream")
oStream.Type = 1
oStream.Open
oStream.Write http.responsebody
sFile = Replace(Mid(url, InStrRev(url, "/") + 1), "?", "-")
oStream.SaveToFile "C:" & "\" & sFile, 2 '本地保存文件名
oStream.Close
End if
其它小例子:http://www.excelpx.com/thread-163323-1-1.html。
XmlHttp对象参考:http://blog.csdn.net/tfgdd/article/details/5062767。
VBA调用WebService
这个在VBA中也可以实现的,一般需要类库辅助,其实与XML操作还是有关系的,可以参看下面链接:
从Office调用Web Service:http://www.excely.com/excel-vba/ie-automation.shtml
如何调用Web Service:http://msdn.microsoft.com/en-us/magazine/cc163837.aspx
二、XML操作
在VBA中处理XML文档在前面的文件系统中其实已经介绍过最简单的打开和保存了。下面综合总结一下:
当做普通文本文档处理或者打开放到Workbook中处理
使用这种方式,辅助正则表达式,再加上一大把处理字符串的方法,是可以完成任务的,只不过XML的结构优势一点都没用上。
使用ADO处理XML文档
这里充分体现了ADO的强大,配合SQL几乎可以完成任何的任务。别忘了添加MS ADO Library引用。
生成XML的操作示例:
Const stSQL As String = "SELECT * FROM [Report]"
Dim stCon As String
stCon = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & ThisWorkbook.FullName & ";" & _
"Extended Properties=""Excel 8.0;HDR=Yes"";"
Dim rst As New ADODB.Recordset
Dim str As New ADODB.Stream
With rst
.CursorLocation = adUseClient
.Open stSQL, stCon, adOpenStatic, adLockReadOnly, adCmdText
.Save str, adPersistXML
.Close
With str
.SaveToFile "C:\Report.xml", adSaveCreateOverWrite
.Close
End With
End With
Set str = Nothing
Set rst = Nothing
End Sub
读取XML的操作示例:
Dim rst As ADODB.Recordset
Dim stCon As String, stFile As String
Dim i As Long, j As Long
Set rst = New ADODB.Recordset
stFile = "C:\Report.xml"
stCon = "Provider=MSPersist;"
With rst
.CursorLocation = adUseClient
.Open stFile, stCon, adOpenStatic, adLockReadOnly, adCmdFile
Set .ActiveConnection = Nothing
End With
With ActiveSheet
For j = 0 To i - 1
.Cells(1, j + 1).Value = rst.Fields(j).Name
Next j
.Range("A2").CopyFromRecordset rst
End With
rst.Close
Set rst = Nothing
End Sub
使用MSXML处理XML文档
这应该是处理XML文档的首选策略了,它提供了XML DOM的所有方法和属性,使用起来很顺手。使用这个对象需要添加“Microsoft XML,v6.0”引用。
Dim xmlDom As MSXML2.DOMDocument
Dim xmlPlaceMark As MSXML2.IXMLDOMNode
Dim xmlPolygon As MSXML2.IXMLDOMNode
Dim xmlCoord As MSXML2.IXMLDOMNode
Dim sName As String
Dim vaSpace As Variant, vaComma As Variant
Dim i As Long, j As Long
Set xmlDom = New MSXML2.DOMDocument
xmlDom.Load "C:\Downloads\overlay_1198.kml"
For i = 0 To xmlDom.childNodes(1).childNodes(0).childNodes.Length - 1
If xmlDom.childNodes(1).childNodes(0).childNodes.Item(i).nodeName = "Placemark" Then
Set xmlPlaceMark = xmlDom.childNodes(1).childNodes(0).childNodes.Item(i)
Set xmlPolygon = xmlPlaceMark.childNodes(2).childNodes(0)
Set xmlCoord = xmlPolygon.childNodes(0).childNodes(0).childNodes(0)
sName = xmlPlaceMark.childNodes(1).childNodes(5).nodeTypedValue
With Sheet4.Cells(Sheet2.Rows.Count, 1).End(xlUp).Offset(1, 0)
.Value = sName
vaSpace = Split(xmlCoord.childNodes(0).Text, " ")
For j = LBound(vaSpace) To UBound(vaSpace)
vaComma = Split(vaSpace(j), ",")
.Offset(0, 1).Value = vaComma(0)
.Offset(0, 2).Value = vaComma(1)
Next j
End With
End If
Next i
End Sub
XML DOM的方法和属性:http://msdn.microsoft.com/en-us/library/ms764730
三、WMI信息
WMI是内置在Windows 2000、 Windows XP和Windows Server 2003 系列操作系统中核心的管理支持技术。基于由 Distributed Management Task Force (DMTF) 所监督的业界标准,WMI是一种规范和基础结构,通过它可以访问、配置、管理和监视几乎所有的Windows资源。大多用户习惯于使用众多的图形化管理工具来管理Windows资源,在WMI之前这些工具都是通过Win32应用程序编程接口(Application ProgrammingInterfaces,API)来访问和管理Windows资源的。只要你熟悉系统编程你就知道API有多么重要。但是大多数脚本语言都不能直接调用Win32 API,WMI的出现使得系统管理员可以通过一种简便的方法即利用常见的脚本语言实现常用的系统管理任务。 利用WMI需要和脚本如WSH和VBScript结合起来,可以实现的功能大家可以看微软的MSDN文档。
(介绍比较全)VBA中使用WMI:http://club.excelhome.net/thread-733445-1-1.html。
WMI中的Class介绍:http://msdn.microsoft.com/en-us/library/aa394554(v=VS.85).aspx
四、API扩充
在VBA中使用API,理论上可以完成任何操作系统提供的功能。但是实际上,除非万不得已,一般使用VBA或者其他COM提供的功能就足够了,真的算是价格便宜量又足。当上述这些功能不符合我们的需求的时候(特别是需要使用VBA中那纤弱的UserForm的时候),那就使用API吧。使用API需要先声明,再使用;声明过程中还涉及到类型的转化。如果想了解更多的内容,可以参考相关的资料。下面是质量比较高的一些资料:
VBA与API:http://blog.imwebs.com/article.asp?id=469
VBA调用API:http://www.excelperfect.com/index.php/2009/07/15/usewindowsapi/
VBA中API的函数集锦:http://www.cnblogs.com/james.wong/articles/93942.html
窗体API:http://www.vbafan.com/2009/07/19/excel-userform-api-tricks/
CreateObject与GetObject的不同:前面我已经多次使用CreateObject去创建COM的实例了,这里简单介绍一下另外一个相关的函数。
如果存在对象的当前实例,或者您希望使用已加载的文件创建对象,请使用 GetObject 函数,只要把COM组件的路径传给这个函数即可。如果不存在当前实例,并且不希望使用已加载的文件启动对象,那么使用 CreateObject 函数。这里最常见的一个用法是把Excel文件的路径传给GetObject,这个时候方法就返回这个文件对应的Workbook对象,但是并不会显式打开文件。这个时候就可以在后台处理文件的内容,比如拷贝Sheet到当前打开的Excel文件中。
注意:如果对象本身已经注册为 ActiveX 单实例对象,则无论调用多少次 CreateObject,都只会创建对象的一个实例。不能使用 GetObject 获取对用 Visual Basic 创建的类的引用。
GetObject方法的详细说明:http://msdn.microsoft.com/zh-cn/library/e9waz863(v=vs.80).aspx