28

我正在从 MSDN 复制一个 VBA 代码片段,它向我展示了如何将 SQL 查询中的结果抓取到 excel 表(Excel 2007)中:

Sub GetDataFromADO()

    'Declare variables'
        Set objMyConn = New ADODB.Connection
        Set objMyCmd = New ADODB.Command
        Set objMyRecordset = New ADODB.Recordset

    'Open Connection'
        objMyConn.ConnectionString = "Provider=SQLOLEDB;Data Source=localhost;User ID=abc;Password=abc;"
        objMyConn.Open

    'Set and Excecute SQL Command'
        Set objMyCmd.ActiveConnection = objMyConn
        objMyCmd.CommandText = "select * from myTable"
        objMyCmd.CommandType = adCmdText
        objMyCmd.Execute

    'Open Recordset'
        Set objMyRecordset.ActiveConnection = objMyConn
        objMyRecordset.Open objMyCmd

    'Copy Data to Excel'
        ActiveSheet.Range("A1").CopyFromRecordset (objMyRecordset)

End Sub

我已经在下面添加了 Microsoft ActiveX Data Objects 2.1 Library 作为参考。而且这个数据库是可以访问的。

现在,当我运行这个子程序时,它有一个错误:

运行时错误 3704:关闭对象时不允许操作。

关于声明:

ActiveSheet.Range("A1").CopyFromRecordset (objMyRecordset)

知道为什么吗?

谢谢。

4

6 回答 6

26

我已将初始目录添加到您的连接字符串中。我还放弃了 ADODB.Command 语法,转而简单地创建自己的 SQL 语句并打开该变量上的记录集。

希望这可以帮助。

Sub GetDataFromADO()
    'Declare variables'
        Set objMyConn = New ADODB.Connection
        Set objMyRecordset = New ADODB.Recordset
        Dim strSQL As String

    'Open Connection'
        objMyConn.ConnectionString = "Provider=SQLOLEDB;Data Source=localhost;Initial Catalog=MyDatabase;User ID=abc;Password=abc;"
        objMyConn.Open

    'Set and Excecute SQL Command'
        strSQL = "select * from myTable"

    'Open Recordset'
        Set objMyRecordset.ActiveConnection = objMyConn
        objMyRecordset.Open strSQL            

    'Copy Data to Excel'
        ActiveSheet.Range("A1").CopyFromRecordset (objMyRecordset)

End Sub
于 2009-07-13T21:35:40.953 回答
17

建议更改:

  • 不要调用 Command 对象的 Execute 方法;
  • 将 Recordset 对象的 Source 属性设置为您的 Command 对象;
  • 不带参数调用 Recordset 对象的 Open 方法;
  • CopyFromRecordset在对;的调用中删除 Recordset 对象周围的括号。
  • 实际上声明你的变量:)

修改后的代码:

Sub GetDataFromADO()

    'Declare variables'
        Dim objMyConn As ADODB.Connection
        Dim objMyCmd As ADODB.Command
        Dim objMyRecordset As ADODB.Recordset

        Set objMyConn = New ADODB.Connection
        Set objMyCmd = New ADODB.Command
        Set objMyRecordset = New ADODB.Recordset

    'Open Connection'
        objMyConn.ConnectionString = "Provider=SQLOLEDB;Data Source=localhost;User ID=abc;Password=abc;"    
        objMyConn.Open

    'Set and Excecute SQL Command'
        Set objMyCmd.ActiveConnection = objMyConn
        objMyCmd.CommandText = "select * from mytable"
        objMyCmd.CommandType = adCmdText

    'Open Recordset'
        Set objMyRecordset.Source = objMyCmd
        objMyRecordset.Open

    'Copy Data to Excel'
        ActiveSheet.Range("A1").CopyFromRecordset objMyRecordset

End Sub
于 2009-07-13T21:57:07.853 回答
1

这是一个正确的连接字符串吗?
SQL Server 实例位于何处?

您将需要验证您是否能够使用上面指定的连接字符串连接到 SQL Server。

编辑:查看记录集的 State 属性,看看它是否打开?
此外,在打开记录集之前将 CursorLocation 属性更改为 adUseClient。

于 2009-07-13T16:54:14.923 回答
1

我坐在一台没有任何相关软件的电脑前,但从记忆中看,该代码看起来是错误的。您正在执行命令但丢弃RecordSet返回objMyCommand.Execute的命令。

我会做:

Set objMyRecordset = objMyCommand.Execute

...然后丢失“打开记录集”部分。

于 2009-07-13T21:25:35.110 回答
0

添加set nocount on到存储过程的开头(如果您在 SQL Server 上)。我刚刚在自己的工作中解决了这个问题,它是由中间结果引起的,例如"1203 Rows Affected",被加载到Recordset我试图使用的文件中。

于 2010-08-09T23:03:16.120 回答
0

@firedrawndagger:列出字段名称/列标题遍历记录集字段集合并插入名称:

Dim myRS as ADODB.Recordset
Dim fld as Field
Dim strFieldName as String 

For Each fld in myRS.Fields
    Activesheet.Selection = fld.Name
    [Some code that moves to next column]
Next
于 2017-01-11T07:38:33.237 回答