通过VBA从Excel控制数据库

时间:2017-03-09 12:29:52

标签: sql-server excel-vba vba excel

我正在尝试创建一个excel插件,它具有一组函数来从数据库中提取值(我使用的是MS SQL Server)。所以我的查询只返回一个记录集。我在我的vba代码中使用了类似下面的东西。

Using Excel VBA to run SQL query

但问题是如果我在100个单元格中有自定义函数,则宏每次都会连接到数据库并从数据库中检索数据。

有没有办法可以建立一个连接并使用该连接来编写任意数量的查询?

3 个答案:

答案 0 :(得分:0)

简单,运行所有100个函数/循环来访问数据库。一个你完成然后关闭连接。看看下面的修改后的代码......

Option Explicit

Sub ConnectSqlServer()

    Dim conn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim sConnString As String

    ' Create the connection string.
    sConnString = "Provider=SQLOLEDB;Data Source=INSTANCE\SQLEXPRESS;" & _
                  "Initial Catalog=MyDatabaseName;" & _
                  "Integrated Security=SSPI;"

    ' Create the Connection and Recordset objects.
    Set conn = New ADODB.Connection
    Set rs = New ADODB.Recordset

    ' Open the connection and execute.
    conn.Open sConnString

    '>>>> run 100 loops
    Dim i As Integer

    For i = 1 To 100
        Set rs = conn.Execute("SELECT * FROM Table" + 1 + ";")

        ' Check we have data.
        If Not rs.EOF Then
            ' Transfer result.
            ' I assume that you've 100 Sheets
            Sheets(i).Range("A1").CopyFromRecordset rs
        ' Close the recordset
            rs.Close
        Else
            MsgBox "Error: No records returned.", vbCritical
        End If
    Next

    ' Clean up
    If CBool(conn.State And adStateOpen) Then conn.Close
    Set conn = Nothing
    Set rs = Nothing

End Sub

我已添加100个循环并在关闭数据库连接之前运行它。 希望它有用。

答案 1 :(得分:0)

在这种情况下,不要在循环中执行db操作。这是耗时且不适当的用途。相反,在循环中创建select,insert或whatsoever语句然后编译循环操作和计算然后只打开连接一次并将请求(创建的sql脚本)发送到db并从db获取响应然后关闭连接。就这样。 db操作必须从dailiy和递归操作中提炼出来。(反模式)最好的问候。

答案 2 :(得分:0)

免责声明:虽然这不是该帖子中描述的问题的直接解决方案,但我想将此方法添加为更快更简单的解决方案。

步骤1:创建一个(可能隐藏的)工作表,在该工作表中提取此Excel文件中所需的所有SQL数据。将数据拉入 one 表,其中包含所有必需的列/维,以便从此表中获取数据。

这就是我的意思。假设您在此Excel文件中需要SQL Server上的表Users中的一些数据以及服务器上StockMarket表中的一些信息。从表Users中,您需要UserID,名字,姓氏和职位。在表格StockMarket中,您需要Stockmarket ID和此特定股票的价格。由于这些价格是按日期计算的,因此您还需要价格的报价日期。

现在,由于您希望所有人都在一个表中,因此您必须考虑将所有这些数据合并到一个表中的智能方法。一种方法可能如下: enter image description here

之后,您可以使用以下查找函数从上表中获取所有数据:

=INDEX(SQLdata,MATCH(1,(SQLdata[Table]="Users")*(SQLdata[UserID]=25),0),4)

请注意,我将表SQLdata命名为在查看公式并理解它时更容易。此外,您可以轻松扫描Excel文件以获取对此表的任何引用。

另一种方法可能是使表更简洁: enter image description here

注意,这次我将StringsNumbers混合,StringsDate混合(设计非常糟糕,对于某些人来说甚至不可能考虑到)。此外,列标题现在不太具描述性。然而,这也有效:

=INDEX(SQLrev,MATCH(1,(SQLrev[Table]="Users")*(SQLrev[Dimension1]=25),0),5)

注意,我这次调用了表SQLrev。

两种解决方案都允许您聚合表中的数据。因此,如果您想要(例如)2017年Apple的平均价格,那么您可以使用以下公式来总结今年的报价并将它们除以3:

=SUM(IF("StockMarket"=SQLrev[Table];1;0)*IF("AAPL"=SQLrev[Dimension1];1;0)*SQLdata[Price])/3

这种方法最显着的优点是您只需更新整个Excel文件中的一个表,这意味着服务器只有一个 SQL拉。

最值得注意的缺点(除了可能变得非常复杂的SQL选择之外)是您需要知道需要驻留在此表中的所有数据。如果未将数据提取到此表中,则上述公式都不能检索这些值。

虽然这种方法肯定有其缺点,但这比你想要的Excel AddIn更容易实现。

以上所有公式都是数组公式,必须按Ctrl + Shift + Enter输入。有关数组公式的更多信息,请阅读以下内容:https://support.office.com/en-us/article/Guidelines-and-examples-of-array-formulas-7D94A64E-3FF3-4686-9372-ECFD5CAA57C7