【问题标题】:How to select distinct values from one column in adodb recordset Excel VBA?如何从 adodb 记录集 Excel VBA 中的一列中选择不同的值?
【发布时间】:2014-05-07 15:31:54
【问题描述】:

我有一个ADODB.Recordset rs,我从 DB 获得。我现在必须重复使用这个记录集两次。

这是我的记录集的示例:

Mike     Client
John     Manager
Karen    Client
Joe      Sub
Brian    Manager

现在我需要得到所有的标题,所以我想得到:

Client
Manager
Sub

我知道有rs.Filter,但我不确定我是否可以从中选择不同的。

我也知道我可以克隆这个 Recordset:

Dim rs_clone As ADODB.Recordset
Set rs_clone = New ADODB.Recordset
rs_clone = rs.getrows()

是否可以只克隆不同的记录?或者有什么更好的方法?谢谢

【问题讨论】:

  • 这在 vba Dim rs_clone As ADODB.Recordset = New ADODB.Recordset 中合法吗?在 vb.net 中可以,但不确定是否可以在 VBA 的一行中分配变量和实例化@
  • 你说得对,我只是在这里打的,但是思路很清楚。
  • 对不起=) 再也不会这样做了=)
  • rs_clone = rs.getrows() 在我的 Excel 上似乎也不起作用

标签: sql vba excel recordset


【解决方案1】:

在数据库中触发一个 sql 字符串为您提供了很大的空间来选择您想要返回的内容

小例子(在生产代码中使用我更喜欢的后期绑定),我要求从表列 MyColumn 中获得一个不同的列表

Dim cn As Object
Dim rs As Object

Set cn = CreateObject("ADODB.Connection")
cn.Open strConn
cn.CommandTimeout = 0

Set rs = CreateObject("ADODB.Recordset")
Set rs.ActiveConnection = cn


'=====================
rs.Open "SELECT Distinct MyColumn AS C FROM myTable"

strConn 需要设置为正确的连接字符串。


编辑

无法在vba: get unique values from array这篇文章的帮助下在数据库中触发sql字符串,我有以下解决方案。

如果您更喜欢早期绑定,则需要参考以下内容:

  • Microsoft ActiveX 数据对象(我使用 6.1 库)
  • Microsoft 脚本运行时(这样我们就可以使用字典)

代码如下:

Option Explicit

Global Const strConn As String = _
    "PROVIDER=MySQLprovider;" & _
    "P*SSWORD=MyPword;" & _
    "USER ID=MyLogin;" & _
    "INITIAL CATALOG=MyDB;" & _
    "DATA SOURCE=MyServer;" & _
    "USE PROCEDURE FOR PREPARE=1;" & _
    "AUTO TRANSLATE=True;"


Sub getDistinctRecords()

Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.ConnectionTimeout = 0
cn.Open strConn

Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
rs.ActiveConnection = cn

'>>this mimics your record set with non-distinct members
rs.Open _
    "SELECT 'a' as MyCol UNION ALL " & _
    "SELECT 'a' as MyCol UNION ALL " & _
    "SELECT 'b' as MyCol UNION ALL " & _
    "SELECT 'b' as MyCol"

Dim Arr() As Variant
Arr = rs.GetRows() 

Dim d As Scripting.Dictionary
Set d = New Scripting.Dictionary

Dim i As Long
For i = LBound(Arr, 2) To UBound(Arr, 2)
    d(Arr(0, i)) = 1
Next i

Dim v As Variant
For Each v In d.Keys()

    '>>d.Keys() is a Variant array of the unique values in myArray.
    '>>v will iterate through each of them.

    '>>to print to the immediate window
    Debug.Print v
Next v

'=====================
     'tidy up connection
On Error Resume Next
    Set rs.ActiveConnection = Nothing
On Error GoTo 0

If Not (rs Is Nothing) Then
    If (rs.State And 1) = 1 Then rs.Close
    Set rs = Nothing
End If
If Not (cn Is Nothing) Then
    If (cn.State And 1) = 1 Then cn.Close
    Set cn = Nothing
End If

End Sub

【讨论】:

  • @KarlRookey 它有助于避免版本问题。
  • @ckuhn203 - 这是对所有对象变量的一般性声明,还是仅用于处理数据库对象?我一直尝试提前绑定,因为它更快,但我想我听到了你和为什么说你会降低性能以降低版本兼容性问题的可能性。对吗?
  • @KarlRookey 这是一个一般性声明。后期绑定减少了使用 vba 时臭名昭著的“缺少参考”。特别是在不同用户使用不同版本软件的情况下。 (比如说 Office 2003 和 Office 2010)。这里有几个链接,其中包含有关该主题的更多信息。 Early vs. Late,这个在Programmers ExchangeWhat is early & late binding?
  • @ckuhn203 最初很容易使用早期绑定,因此您拥有智能感知等。然后一旦对代码感到满意并且一切正常,我相信转换为后期绑定会很好
  • @Bryuk “就我而言,我必须在代码中执行”是什么意思?您是否无法使用 DISTINCT 运算符在数据库中触发 sql 字符串?
猜你喜欢
  • 2011-04-26
  • 2011-01-05
  • 2017-09-25
  • 1970-01-01
  • 1970-01-01
  • 2014-01-26
  • 1970-01-01
  • 1970-01-01
  • 2017-04-22
相关资源
最近更新 更多