Excel宏更改外部数据查询连接-例如,从一个数据库指向另一个数据库

Excel宏更改外部数据查询连接-例如,从一个数据库指向另一个数据库,excel,excel-external-data,connection-string,vba,Excel,Excel External Data,Connection String,Vba,我正在寻找一个宏/vbs来更新所有外部数据查询连接,以指向不同的服务器或数据库。这是一种手动操作的痛苦,在2007年之前的Excel版本中,有时手动操作似乎是不可能的 有人有样品吗?我看到有不同类型的连接“OLEDB”和“ODBC”,所以我想我需要处理不同格式的连接字符串?连接字符串格式基本上是不相关的,因为Excel会将其传递给数据提供程序 手动更新一个查询表,然后执行以下操作: dim w as worksheet, q as querytable for each w in thiswo

我正在寻找一个宏/vbs来更新所有外部数据查询连接,以指向不同的服务器或数据库。这是一种手动操作的痛苦,在2007年之前的Excel版本中,有时手动操作似乎是不可能的


有人有样品吗?我看到有不同类型的连接“OLEDB”和“ODBC”,所以我想我需要处理不同格式的连接字符串?

连接字符串格式基本上是不相关的,因为Excel会将其传递给数据提供程序

手动更新一个查询表,然后执行以下操作:

dim w as worksheet, q as querytable

for each w in thisworkbook.worksheets
  for each q in w.querytables
    q.connection = SampleSheet.querytables("PreparedQueryTable").connection
  next
next

最后我写了以下内容,提示输入连接详细信息,创建一个连接字符串,然后更新所有外部数据查询以使用该连接字符串

'''' Prompts for connection details and updates all the external data connections in the workbook accordingly.
'''' Changes all connections to use ODBC connections instead of OLEDB connections.
'''' Could be modified to use OLEDB if there's a need for that.
Sub PromptAndUpdateAllConnections()
    Dim Server As String, Database As String, IntegratedSecurity As Boolean, UserId As String, Password As String, ApplicationName As String
    Dim ConnectionString As String
    Dim MsgTitle As String
    MsgTitle = "Connection Update"

    If vbOK = MsgBox("You will be asked for information to connect to the database, and this spreadsheet will be updated to connect using those details.", vbOKCancel, MsgTitle) Then
        Server = InputBox("Database server or alias and instance name, e.g. 'LONDB01' or 'LONDB01\INST2'", MsgTitle)
        If Server = "" Then GoTo Cancelled
        Database = InputBox("Database name", MsgTitle, "a default value")
        If Database = "" Then GoTo Cancelled
        IntegratedSecurity = (vbYes = MsgBox("Integrated Security? (i.e. has your windows account been given access to connect to the database)", vbYesNo, MsgTitle))
        If Not IntegratedSecurity Then
            UserId = InputBox("User Id", MsgTitle)
            If UserId = "" Then GoTo Cancelled
            Password = InputBox("Password", MsgTitle)
            If Password = "" Then GoTo Cancelled
        End If
        ApplicationName = "Excel Reporting"

        ConnectionString = GetConnectionString(Server, Database, IntegratedSecurity, UserId, Password, ApplicationName)
        UpdateAllQueryTableConnections ConnectionString
        MsgBox "Spreadsheet Updated", vbOKOnly, MsgTitle
    End If
    Exit Sub
Cancelled:
    MsgBox "Spreadsheet not updated", vbOKOnly, MsgTitle
End Sub

'''' Generates an ODBC connection string from the given details.
Function GetConnectionString(Server As String, Database As String, IntegratedSecurity As Boolean, _
    UserId As String, Password As String, ApplicationName As String)

    Dim result As String

    If IntegratedSecurity Then
        result = "ODBC;DRIVER=SQL Server;SERVER=" & Server & ";DATABASE=" & Database _
                & ";Trusted_Connection=Yes;APP=" & ApplicationName & ";"
    Else
        result = "ODBC;DRIVER=SQL Server;SERVER=" & Server & ";DATABASE=" & Database _
                & ";UID=" & UserId & ";PWD=" & Password & ";APP=" & ApplicationName & ";"
    End If

    RM_GetConnectionString = result
End Function

'''' Sets all external data connection strings to the given value (regardless of whether they're
'''' currently ODBC or OLEDB connections. Appears to change type successfully.
Sub UpdateAllQueryTableConnections(ConnectionString As String)
    Dim w As Worksheet, qt As QueryTable
    Dim cn As WorkbookConnection
    Dim odbcCn As ODBCConnection, oledbCn As OLEDBConnection
    For Each cn In ThisWorkbook.Connections
        If cn.Type = xlConnectionTypeODBC Then
            Set odbcCn = cn.ODBCConnection
            odbcCn.SavePassword = True
            odbcCn.Connection = ConnectionString
        ElseIf cn.Type = xlConnectionTypeOLEDB Then
            Set oledbCn = cn.OLEDBConnection
            oledbCn.SavePassword = True
            oledbCn.Connection = ConnectionString
        End If
    Next
End Sub

即使我们可以刷新特定的连接,它也会刷新链接到它的所有枢轴

对于这段代码,我从Excel中的表创建了切片器:

此代码适用于DB中的切片器:

Sub UpdateConnection()
    Dim ServerName As String
    Dim ConnectionString As String
    Dim DatabaseNameCount As Integer

    DatabaseNameCount = ActiveWorkbook.SlicerCaches("Slicer_Name").VisibleSlicerItems.Count

    If DatabaseNameCount = 1 Then
        ServerName = ActiveWorkbook.SlicerCaches("Slicer_Name").VisibleSlicerItems.Item(1).Name
        ConnectionString = GetConnectionString(ServerName)
        UpdateAllQueryTableConnections ConnectionString
    Else
        MsgBox "Please Select One Value", vbOKOnly, "Slicer Info"
    End If
End Sub
此代码适用于从同一工作簿中的Excel表创建的切片器:

Sub UpdateConnection()
        Dim ServerName As String
        Dim ServerNameRaw As String
        Dim CubeName As String
        Dim CubeNameRaw As String
        Dim ConnectionString As String

        ServerNameRaw = ActiveWorkbook.SlicerCaches("Slicer_ServerName").VisibleSlicerItemsList(1)
        ServerName = Replace(Split(ServerNameRaw, "[")(3), "]", "")

        CubeNameRaw = ActiveWorkbook.SlicerCaches("Slicer_CubeName").VisibleSlicerItemsList(1)
        CubeName = Replace(Split(CubeNameRaw, "[")(3), "]", "")

        If CubeName = "All" Or ServerName = "All" Then
            MsgBox "Please Select One Cube and Server Name", vbOKOnly, "Slicer Info"
        Else
            ConnectionString = GetConnectionString(ServerName, CubeName)
            UpdateAllQueryTableConnections ConnectionString, CubeName
        End If
    End Sub
为所需初始目录创建连接和更新连接的通用代码:

Function GetConnectionString(ServerName As String, CubeName As String)
        Dim result As String
        result = "OLEDB;Provider=MSOLAP.5;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=" & CubeName & ";Data Source=" & ServerName & ";MDX Compatibility=1;Safety Options=2;MDX Missing Member Mode=Error;Update Isolation Level=2"
        '"OLEDB;Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=" & CubeName & ";Data Source=" & ServerName & ";Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Use Encryption for Data=False;Tag with column collation when possible=False"
        GetConnectionString = result
    End Function

    Sub UpdateAllQueryTableConnections(ConnectionString As String, CubeName As String)
        Dim cn As WorkbookConnection
        Dim oledbCn As OLEDBConnection
        Dim Count As Integer, i As Integer
        Dim DBName As String
        DBName = "Initial Catalog=" + CubeName

        Count = 0
        For Each cn In ThisWorkbook.Connections
            If cn.Name = "ThisWorkbookDataModel" Then
                Exit For
            End If

            oTmp = Split(cn.OLEDBConnection.Connection, ";")
            For i = 0 To UBound(oTmp) - 1
                If InStr(1, oTmp(i), DBName, vbTextCompare) = 1 Then
                    Set oledbCn = cn.OLEDBConnection
                    oledbCn.SavePassword = True
                    oledbCn.Connection = ConnectionString
                    Count = Count + 1
                End If
            Next
        Next

        If Count = 0 Then
             MsgBox "Nothing to update", vbOKOnly, "Update Connection"
        ElseIf Count > 0 Then
            MsgBox "Connection Updated Successfully", vbOKOnly, "Update Connection"
        End If
    End Sub

w、 QueryTables.Count对我来说总是0,即使我有外部数据连接!?如果循环并使用工作簿,我可以看到连接。WorkbookConnections