Sql server 用VBA控制数据库表单Excel

Sql server 用VBA控制数据库表单Excel,sql-server,excel,vba,Sql Server,Excel,Vba,我正在尝试创建一个excel加载项,它具有一组从数据库中提取值的函数(我使用MS SQL Server)。因此,我的查询将只返回一个记录集。我在vba代码中使用了如下内容 但问题是,如果我在100个单元格中有我的自定义函数,宏每次都会连接到数据库并从数据库中检索数据 是否有一种方法可以建立一个连接并使用该连接编写任意多的查询?简单,运行所有100个函数/循环来访问数据库。完成一个,然后关闭连接。看看下面修改过的代码 Option Explicit Sub ConnectSqlServer()

我正在尝试创建一个excel加载项,它具有一组从数据库中提取值的函数(我使用MS SQL Server)。因此,我的查询将只返回一个记录集。我在vba代码中使用了如下内容

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


是否有一种方法可以建立一个连接并使用该连接编写任意多的查询?

简单,运行所有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个循环,并在数据库连接关闭之前运行它。
希望它有用。

简单,运行所有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个循环,并在数据库连接关闭之前运行它。
希望它有用。

在这种情况下,不要在循环中执行db操作。这很耗时,而且使用不当。相反,在循环中创建select、insert或其他语句,然后完成循环操作和计算,然后只打开一次连接,向db发送请求(创建的sql脚本),从db获得响应,然后关闭连接。就这些。数据库操作必须与日常操作和递归操作分开。(反模式)敬请注意。

在这种情况下,不要在循环中执行数据库操作。这很耗时,而且使用不当。相反,在循环中创建select、insert或其他语句,然后完成循环操作和计算,然后只打开一次连接,向db发送请求(创建的sql脚本),从db获得响应,然后关闭连接。就这些。db操作必须避免日常操作和递归操作。(反模式)致以最诚挚的问候。

免责声明:虽然这不是本文所述问题的直接解决方案,但我想添加此方法,作为所述问题的更快、更简单的解决方案

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

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

现在,由于您希望将所有数据都放在一个表中,因此必须想出一种聪明的方法将所有这些数据合并到一个表中。一种方法可以是:

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

=INDEX(SQLdata,MATCH(1,(SQLdata[Table]="Users")*(SQLdata[UserID]=25),0),4)
请注意,我将表命名为SQLdata,以便于查看和理解公式。此外,像这样,您可以轻松地扫描Excel文件以查找对此表的任何引用

另一种方法可以是以下方法,以使表格更加简洁:

请注意,这一次我将
字符串
数字
以及
字符串
日期
s混合在一起(这是非常糟糕的设计,对于这里的一些人来说甚至不可能想到)。此外,列标题现在不那么具有描述性。然而,这也起作用:

=INDEX(SQLrev,MATCH(1,(SQLrev[Table]="Users")*(SQLrev[Dimension1]=25),0),5)
注意,这次我调用了表SQLrev

这两种解决方案还允许您聚合表中的数据。因此,如果你想要(例如)2017年苹果的平均价格,那么你可以使用以下公式将今年的报价相加,然后除以3:

=SUM(IF("StockMarket"=SQLrev[Table];1;0)*IF("AAPL"=SQLrev[Dimension1];1;0)*SQLdata[Price])/3
这种方法最显著的优点是,您只需更新整个Excel文件中的一个表,这意味着只有一个来自服务器的SQL pull

最显著的缺点(除了编写可能变得非常复杂的SQL select)是您需要知道需要驻留在该表中的所有数据。如果未将数据拉入此表,则上述公式都无法检索这些值

虽然这种方法肯定有其缺点,但它比您想要的Excel插件更容易实现


以上所有公式都是数组公式,必须按Ctrl+
Shift
+
Enter
输入。有关数组公式的更多信息,请阅读以下内容:

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

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

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

现在,由于您希望将所有数据都放在一个表中,因此必须想出一种聪明的方法将所有这些数据合并到一个表中。一种方法可以是:

之后你可以得到所有的