首先,我们要介绍下ADO。
ADO (ActiveX Data Objects,ActiveX数据对象)是微软提出的应用程序接口,用以实现访问关系或非关系数据库中的数据……更多概念信息可以自行搜索。
之所以要学习ADO,一个原因是ADO自身的一些属性和方法对于数据处理是极其有益的;更重要的原因是,在EXCEL VBA中,一般只有通过ADO,才可以使用强大的SQL查询语言访问外部数据源,进而查、改、增、删相关数据源中的数据。
延伸在具体编程操作上,就形成了四步走发展战略:
VBA中引用ADO类库一般有两种方式。
所谓前期绑定,是指在VBE中手工勾选引用Microsoft ADO相关类库。
在Excel中,按
Sub 后期绑定()
Dim cnn As Object
Set cnn = CreateObject("adodb.connection")
End Sub
两种方式的主要区别是,前期绑定后,在代码编辑过程中,VBE的“自动列出成员”功能,可以提供ADO的属性和方法,这便于代码快捷、准确的编写。但当他人的Excel工作簿并没有手工前期绑定ADO类库时,相关代码将无法运行。因此后期代码绑定ADO的通用性会更强些,它不需要手工绑定相关类库。
比较好的用法是,代码编写及调试时,使用前期绑定,代码编写完善后,再修改为后期绑定发布使用。
不论我们使用SQL语言对数据源作何操作,都得首先使用ADO创建并打开一个到数据源的链接;这就好比得先修路,才能使用汽车运输货物。
在VBA中,我们通常使用ADO的Connection.Open语句来显式建立一个到数据源的链接。
Connection.Open语法如下:
connection.Open ConnectionString, UserID, Password, Options
虽然不同的数据库或文件有不同的连接字符串,但常用的数据库或文件的连接字符串均是固定的。
举个例子,如果将代码所在的Excel(2019版)作为一个外部数据源建立链接,代码如下:
Sub Testcnn()
Dim cnn As Object ' 定义变量
Set cnn = CreateObject("adodb.connection") ' 后期绑定ADO
cnn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties='Excel 12.0;HDR=yes;IMEX=0';Data Source=" & ThisWorkbook.FullName
' 建立链接
cnn.Close ' 关闭链接
Set cnn = Nothing ' 释放内存
End Sub
简单说下上面代码连接字符串中各关键字(第4行代码)的意思。
VBA代码Application.Version可以获取计算机的Excel版本号,因此以下代码兼顾了03及各高级版本Excel的情况:
Sub Testcnn2()
Dim cnn As Object
Dim strPath As String
Dim str_cnn As String
Set cnn = CreateObject("adodb.connection")
strPath = ThisWorkbook.FullName '当前工作簿的完整路径
If Application.Version < 12 Then '判断Excel版本号,以使用不同的连接字符串
str_cnn = "Provider=Microsoft.jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=" & strPath
Else
str_cnn = "Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties=Excel 12.0;Data Source=" & strPath
End If
cnn.Open str_cnn
cnn.Close
Set cnn = Nothing
End Sub
最后,需要提醒大家的是,链接是一种昂贵的资源(官方语),因此在代码运行完毕后,请养成关闭链接(cnn.Close)并释放内存(Set cnn = Nothing)的好习惯。
聊完了如何绑定ADO以及建立与数据源的链接,最后说下如何使用ADO执行SQL语句。
我们可以使用ADO的Connection对象或Recordset、Commannd执行SQL语句;这里大家只需要先了解Connection对象的Execute方法就可以了。
这是一个最常用的VBA+ADO+SQL套路化查询代码。
Sub DoSql_Execute1()
Dim cnn As Object, rst As Object
Dim strPath As String, str_cnn As String, strSQL As String
Dim i As Long
Set cnn = CreateObject("adodb.connection")
'以上是第一步,后期绑定ADO
'
strPath = ThisWorkbook.FullName
If Application.Version < 12 Then
str_cnn = "Provider=Microsoft.jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=" & strPath
Else
str_cnn = "Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties=Excel 12.0;Data Source=" & strPath
End If
cnn.Open str_cnn
'以上是第二步,建立链接
'
strSQL = "SELECT 姓名,成绩 FROM [Sheet1$] WHERE 成绩>=80"
'Sql语句,查询Sheet1表成绩大于80……姓名和成绩的记录
Set rst = cnn.Execute(strSQL)
'Execute()执行SQL语句,始终得到一个新的记录集rst
'以上是第三步,编写并执行SQL
'
Worksheets("结果表").Select '选中存放结果的工作表
Cells.ClearContents '清空值
For i = 0 To rst.Fields.Count - 1
'利用fields属性获取所有字段名,fields包含了当前记录有关的所有字段,fields.count得到字段的数量
'由于Fields.Count下标为0,又从0开始遍历,因此总数-1
Cells(1, i + 1) = rst.Fields(i).Name
Next
Range("a2").CopyFromRecordset rst
'使用单元格对象的CopyFromRecordset方法将rst内容复制到A2单元格为左上角的单元格区域
'以上是第四步,将SQL查询结果和字段名写入表格指定区域
'
cnn.Close '关闭链接
Set cnn = Nothing '释放内存
End Sub
简洁版(不考虑复制表头列名称)
Sub DoSql_Execute2()
Dim cnn As Object, rst As Object
Dim strPath As String, str_cnn As String, strSQL As String
Dim i As Long
Set cnn = CreateObject("adodb.connection")
'以上是第一步,后期绑定ADO
'
strPath = ThisWorkbook.FullName
If Application.Version < 12 Then
str_cnn = "Provider=Microsoft.jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=" & strPath
Else
str_cnn = "Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties=Excel 12.0;Data Source=" & strPath
End If
cnn.Open str_cnn
'以上是第二步,建立链接
'
strSQL = "SELECT 姓名,成绩 FROM [Sheet1$] WHERE 成绩>=80"
'Sql语句,查询Sheet1表成绩大于80……姓名和成绩的记录
Worksheets("结果表").Select '选中存放结果的工作表
Cells.ClearContents '清空值
Range("a2").CopyFromRecordset cnn.Execute(strSQL)
'Execute语句先执行SQL语句
'使用单元格对象的CopyFromRecordset方法将SQL查询到的内容复制到A2单元格为左上角的单元格区域
'此法代码简洁,但未能获取标题栏信息
'以上是第三步,执行SQL语句并将数据读入表格指定区域
'
cnn.Close '关闭链接
Set cnn = Nothing '释放内存
End Sub
以上。通常,我们只需要修改SQL语言以及放置查询结果的工作表名称。