通过前面的章节,我们已经知道……
如果说Connection对象是数据库的链接,那么Recordset对象则是数据的链接。我们使用Connection对象创建对数据库的链接,然后使用SQL语句向数据库提交查询,此时ADO将查询结果储存在Recordset对象中,我们则可以使用Recordset对象的各种方法、属性等对查询结果进行加工处理,比如复制、更新、遍历、筛选、排序等……
上一章我们分享了如何将Recordset对象的数据复制到Excel表格。
Excel VBA+ADO+SQL入门教程024:初识Recordset对象
一个新的问题是,如何对记录集的数据进行循环遍历?
毕竟循环遍历是VBA语言里最基础也是最重要的概念之一。江湖名录,多少复杂烧脑的函数数组公式敌不过VBA一次简单的循环遍历?
通常有两种方法实现对记录集的遍历,一种是游标法,一种是数组法。
数组应是我们所熟悉的,我们今就先来分享它。
举个栗子。
下图是某班级一次考试的成绩表,需要查询第6到第15名之间的学生信息,要求将查询结果按成绩高低降序排列。
如果只是使用SQL语句,代码如下。
Sub GetRSwithSQL()
Dim cnn As Object
Dim rst As Object
Dim strSQL1 As String, strSQL2 As String, strSQL As String
Set cnn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
cnn.Open "Provider =Microsoft.ACE.OLEDB.12.0;" _
& "Extended Properties =excel 12.0;" _
& "Data Source =" & ThisWorkbook.FullName
strSQL1 = "(select top 15 姓名,成绩 from [成绩表$] order by 成绩 desc) "
'提取前15名学生名单
strSQL2 = "(select top 10 姓名,成绩 from " & strSQL1 & " order by 成绩) "
'提取6到15名学生名单
strSQL = "select 姓名,成绩 from " & strSQL2 & "order by 成绩 desc"
'对结果降序排列
rst.Open strSQL, cnn, 1, 3
Cells.ClearContents
[a1:b1] = Array("姓名", "成绩")
Range("a2").CopyFromRecordset rst
'将记录集结果复制到单元格区域
rst.Close
cnn.Close
Set rst = Nothing
Set cnn = Nothing
End Sub
strSQL1对数据源的成绩按降序排列,提取前15名的数据。
strSQL2对strSQL1的查询的成绩按升序排列,再提取前面10名的数据,也就是第6到第15名之间的学生信息。
最后的strSQL语句对strSQL2的查询成绩再按降序排列,即可得到我们所需要的结果。
这里的山路十八弯 这里的水路九连环……有点绕……
干嘛不直接查询前15名的数据,然后从第6名取数,取到第15名呢?
最好也增加一列名次字段吧?比如下图酱紫?
实现代码如下
:
Sub GetRSwithArray()
Dim cnn As Object
Dim rst As Object
Dim strSQL As String
Dim aData As Variant, aResult As Variant
Dim i As Long, j As Long
Set cnn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
cnn.Open "Provider =Microsoft.ACE.OLEDB.12.0;" _
& "Extended Properties =excel 12.0;" _
& "Data Source =" & ThisWorkbook.FullName
strSQL = "select top 15 姓名,成绩 from [成绩表$] order by 成绩 desc "
'提取前15名学生名单
rst.Open strSQL, cnn, 1, 3
aData = rst.GetRows
'记录集转二维数组
ReDim aResult(0 To UBound(aData, 2), 0 To 2)
'声明一个新数组,将记录集数组转换过去
For i = 5 To UBound(aData, 2)
For j = 0 To 1
aResult(i - 5, j) = aData(j, i)
aResult(i - 5, 2) = i + 1
Cells.ClearContents
[a1:c1] = Array("姓名", "成绩", "名次")
Range("a2").Resize(UBound(aResult), 3) = aResult
rst.Close
cnn.Close
Set rst = Nothing
Set cnn = Nothing
End Sub
代码先使用SQL语句查询前15名的学生名单,然后使用Recordset对象的Getrows方法,将记录集转换为二维数组,最后遍历数组,取第6到第15名之间的学生信息。
Getrows方法语法格式如下:
array = recordset.GetRows( [Rows], [Start], [Fields] )
其中array代表返回值,是一个二维数组。
参数Rows是可选的,表示要检索的记录数,默认值为-1,表示取得Recordset对象所有的记录。
比如,只需要检索前10条数据,代码如下:
aData = rst.GetRows(10)
参数Start是可选的,表示GetRows操作开始处的记录书签,可以是下图所示的值之一。
参数Fields是可选的,表示单个字段名/编号,或者字段名/编号数组,ADO仅返回指定字段中的数据。
比如,只需要检索姓名字段的数据,代码如下:
aData = rst.GetRows(-1, 0, "姓名")
aData = rst.GetRows(-1, 0,
0
)
这儿需要着重说明的是,
GetRows方法将Recordset中的记录复制到一个二维数组中,该数组第一个下标是标识字段,第二个下标是标识记录编号,下标均为0。
因此,如果需要将该数组中的值正确赋值到单元格区域,需要进行一次转置……
说到转置,很多朋友可能会想到系统自带的转置函数:Transpose。但通常并不建议大家使用该函数,原因如下:
1,该函数处理的数据量有限制,最多65536行或256列。
2,该函数运算效率并不高。
3,该函数对记录集的数据类型有限制,不允许包含null值,否则会导致程序错误。
所以通常还是建议大家使用声明一个新数组循环转换的方法,如上述代码所示。
本来还想举个例子……Getrows这种方法更常用于将记录集的查询结果导入窗体控件中,比如ListBox/ComboBox之类,然而篇幅所限,还是江湖路远 后会有期吧。
示例文件下载:
https://pan.baidu.com/s/1JamvwIR90L57H0dlIx4wIg#list/path=%2F
返回搜狐,查看更多
责任编辑:
声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。