web-dev-qa-db-ja.com

Microsoft Excelマクロの埋め込み接続文字列を変更する

次のように、実行時にその接続のCommandTextを変更してExcelスプレッドシートからパラメーターを渡すマクロを含むExcelドキュメントがあります。

Sub RefreshData()
ActiveWorkbook.Connections("Job_Cost_Code_Transaction_Summary")
  .OLEDBConnection.CommandText = "Job_Cost_Code_Transaction_Summary_Percentage_Pending @monthEndDate='" & Worksheets("Cost to Complete").Range("MonthEndDate").Value & "', @job ='" & Worksheets("Cost to Complete").Range("Job").Value & "'"
ActiveWorkbook.Connections("Job_Cost_Code_Transaction_Summary").Refresh
End Sub

接続コマンドを変更するだけでなく、別のデータベースでも使用したいので、接続を変更するように更新したいと思います。

enter image description here

マクロがコマンドパラメータをスプレッドシートの値で置き換えるのと同じように、スプレッドシートの値のデータベースサーバー名とデータベース名も置き換えるようにします。

完全な実装は必要ありません。シートの値を使用して接続を変更するためのコードで十分であり、そこから機能させることができます。

私はこのようなことをしようとしました:

 ActiveWorkbook
 .Connections("Job_Cost_Code_Transaction_Summary")
 .OLEDBConnection.Connection = "new connection string"

しかし、それは機能しません。ありがとう。

14
lukemh

私の質問に対する答えは以下の通りです。

他のすべての答えはほとんど正しいものであり、現在の接続の変更に焦点を当てていますが、接続に接続文字列を設定する方法を知りたいだけです。

バグはこれに帰着しました。私のスクリーンショットを見ると、接続文字列が次のようになっていることがわかります。

_Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=ADCData_Doric;Data Source=doric-server5;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=LHOLDER-VM;Use Encryption for Data=False;Tag with column collation when possible=False
_

私はActiveWorkbook.Connections("Job_Cost_Code_Transaction_Summary").OLEDBConnection.Connection = "connection string"でその文字列を設定しようとしていました

接続に完全な文字列を割り当てようとしたときにエラーが発生しました。そのプロパティで現在の接続文字列をMsgBoxできましたが、エラーを取得せずに接続文字列を元に戻すことはできませんでした。

その後、接続文字列の_OLEDB;_を文字列の先頭に追加する必要があることがわかりました。

だからこれは今すぐ動作します!!!

_ActiveWorkbook.Connections("Job_Cost_Code_Transaction_Summary").OLEDBConnection.Connection = "OLEDB;Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=ADCData_Doric;Data Source=doric-server5;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=LHOLDER-VM;Use Encryption for Data=False;Tag with column collation when possible=False"
_

非常に微妙ですが、それはバグでした!

13
lukemh

あなたはあなたが望むものを達成するためにとても近いと思います。

ODBCConnectionに変更できました。 OLEDBConnectionを設定できなかったのでごめんなさい。ODBCConnectionの出現をOLEDBConnectionに変更できます。

この2つのサブを変更して追加し、CommandTextおよびConnection Stringで置き換える必要があるものをスローします。注.Refresh接続を更新するために、実際のデータ更新が必要になるまで必要ない場合があります。

分割するという同じ考えを使用して他のフィールドを変更し、後で参加することができます。

Private Sub ChangeConnectionString(sInitialCatalog As String, sDataSource As String)
    Dim sCon As String, oTmp As Variant, i As Long
    With ThisWorkbook.Connections("Job_Cost_Code_Transaction_Summary").ODBCConnection
        sCon = .Connection
        oTmp = Split(sCon, ";")
        For i = 0 To UBound(oTmp) - 1
            ' Look for Initial Catalog
            If InStr(1, oTmp(i), "Initial Catalog", vbTextCompare) = 1 Then
                oTmp(i) = "Initial Catalog=" & sInitialCatalog
            ' Look for Data Source
            ElseIf InStr(1, oTmp(i), "Data Source", vbTextCompare) = 1 Then
                oTmp(i) = "Data Source=" & sDataSource
            End If
        Next
        sCon = Join(oTmp, ";")
        .Connection = sCon
        .Refresh
    End With
End Sub

Private Sub ChangeCommanText(sCMD As String)
    With ThisWorkbook.Connections("Job_Cost_Code_Transaction_Summary").ODBCConnection
        .CommandText = sCMD
        .Refresh
    End With
End Sub
2
PatricK

入力として更新されるOLEDBConnectionとパラメーターを受け取り、新しい接続文字列を返す関数を使用できます。 Jzzの答えに似ていますが、変更するたびにVBAコード内の接続文字列を編集することなく、ある程度の柔軟性が得られます。最悪の場合、新しいパラメーターを関数に追加する必要があります。

Function NewConnectionString(conTarget As OLEDBConnection, strCatalog As String, strDataSource As String) As String

    NewConnectionString = conTarget.Connection
    NewConnectionString = ReplaceParameter("Initial Catalog", strCatalog)
    NewConnectionString = ReplaceParameter("Data Source", strDataSource)

End Function

Function ReplaceParameter(strConnection As String, strParamName As String, strParamValue As String) As String

    'Find the start and end points of the parameter
    Dim intParamStart As Integer
    Dim intParamEnd As Integer
    intParamStart = InStr(1, strConnection, strParamName & "=")
    intParamEnd = InStr(intParamStart + 1, strConnection, ";")


    'Replace the parameter value
    Dim strConStart As String
    Dim strConEnd As String
    strConStart = Left(strConnection, intParamStart + Len(strParamName & "=") - 1)
    strConEnd = Right(strConnection, Len(strConnection) - intParamEnd + 1)

    ReplaceParameter = strConStart & strParamValue & strConEnd

End Function

特定のアプリケーションに使用した既存のコードからこれを変更したため、部分的にテストされており、完全にニーズを満たす前に調整が必要になる場合があります。

(新しいカタログとデータソースがワークシートのセルに格納されていると仮定すると)何らかの種類の呼び出しコードも必要になることに注意してください。

Sub UpdateConnection(strConnection As String, rngNewCatalog As Range, rngNewSource As Range)

    Dim conTarget As OLEDBConnection
    Set conTarget = ThisWorkbook.Connections.OLEDBConnection(strConnection)

    conTarget.Connection = NewConnectionString(conTarget, rngNewCatalog.Value, rngNewSource.Value)
    conTarget.Refresh

End Sub
2
citizenkong

この古いトピックに少し貢献したいと思います。 Excelファイルに多くの接続があり、それらすべてのDB名とDBサーバーを変更する場合は、次のコードも使用できます。

  • すべての接続を反復処理し、接続文字列を抽出します
  • 各接続文字列は、文字列の配列に分割されます
  • 変更する正しい接続値を検索する配列を反復処理し、他の値は変更されません
  • 配列を文字列に再構成し、変更をコミットします

この方法では、replaceを使用して以前の値を知る必要がなく、残りの文字列はそのまま残ります。また、セル名を参照できるため、Excelファイルに名前を付けることができます

私はそれが役立つことを願っています

Sub RelinkConnections()

Dim currConnValues() As String

For Each currConnection In ThisWorkbook.Connections
    currConnValues = Split(currConnection.OLEDBConnection.Connection, ";")
    For i = 0 To UBound(currConnValues)
        If (InStr(currConnValues(i), "Initial Catalog") <> 0) Then
            currConnValues(i) = "Initial Catalog=" + Range("DBName").value
        ElseIf (InStr(currConnValues(i), "Data Source") <> 0) Then
            currConnValues(i) = "Data Source=" + Range("DBServer").value
        End If
    Next
    currConnection.OLEDBConnection.Connection = Join(currConnValues, ";")
    currConnection.Refresh
Next

End Sub
1
reverpie

これでうまくいくはずです:

Sub jzz()

Dim conn As Variant
Dim connectString As String

For Each conn In ActiveWorkbook.Connections
    connectString = conn.ODBCConnection.Connection
    connectString = Replace(connectString, "Catalog=ADCData_Doric", "Catalog=Whatever")
    connectString = Replace(connectString, "Data Source=doric-server5", "Data Source=Whatever")

    conn.ODBCConnection.Connection = connectString
Next conn


End Sub

ブック内のすべての接続をループし、接続文字列を変更します(2つの置換ステートメントで)。

したがって、例を変更するには:

ActiveWorkbook.Connections("Job_Cost_Code_Transaction_Summary").ODBCConnection.Connection = "new connection string"
1
Jzz

同じ接続名を保持する必要があると思いますか?それ以外の場合は、無視して新しい接続を作成するのが最も簡単です。

接続の名前を変更し、名前を使用して新しい接続を作成できます。

ActiveWorkbook.Connections("Job_Cost_Code_Transaction_Summary").Name = "temp"
'or, more drastic:
'ActiveWorkbook.Connections("Job_Cost_Code_Transaction_Summary").Delete

ActiveWorkbook.Connections.Add "Job_Cost_Code_Transaction_Summary", _
    "a description", "new connection string", "command text" '+ ,command type

その後、この接続をDeleteして、古い接続/名前を復元します。 (私は現在、これを自分でテストすることができないので、慎重に踏む

または、現在の接続を変更することもできますSourceConnectionFile

ActiveWorkbook.Connections("Job_Cost_Code_Transaction_Summary").OLEDBConnection.SourceConnectionFile = "..file location.."

これは通常、システムに保存された。odcファイル(Office Data Connection)を参照します。このファイルには接続の詳細が含まれています。このファイルは、ウィンドウのコントロールパネルから作成できます。

指定していませんが、.odcファイルが現在の接続で使用されている可能性があります。

繰り返しますが、これらの提案をテストすることはできません。そのため、現在の接続の詳細を失うリスクを回避するために、さらに調査していくつかの予防措置を講じる必要があります。

0
Andy G