通过前面的章节,我们已经知道……

如果说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 返回搜狐,查看更多

责任编辑:

声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。