変奏現実

パソコンやMMORPGのことなどを思いつくまま・・・記載されている会社名・製品名・システム名などは、各社の商標、または登録商標です。

この画面は、簡易表示です

ODBC

[MS-Access]ODBC接続先変更

接続先データベースのIPアドレスが変わってしまった場合、WindowsのODBCマネージャでIPアドレスを変更すると概ねOKだったが、MS-Accessで外部データベースをODBC接続でリンクした場合だけ、MS-Access内部でIPアドレスをコピっているらしく変更前のIPアドレスに繋ごうとする。

リンクテーブルマネジャを使用してもIPアドレスを書き換えれない様なので、リンクテーブルを2-3個作り直すハメになった。

しかし、VBAを使えばリンクテーブルが1000個あっても泣かずに済みそうだ。

Public Sub ODBC接続先更新(strConnect As String)
  For Each tableDef In CurrentDb.TableDefs
    If tableDef.Attributes = dbAttachedODBC Then   'リンクテーブルならば、
      tableDef.Connect = connectString       'ODBCの接続テキストを書換える
      tableDef.RefreshLink                         '書き換えた内容で動く様にする
    End If
  Next tdf
End Sub

短く読みやすい記事に載せるコードとしては最良だ。

しかし、今時のMS-Office365の中のAccess2007の中で保持しているODBC接続テキストが

ODBC;DATABASE=xxxxxx;DSN=xxxxxx;OPTION=0;PORT=xxxx;SERVER=192.168.1.xxx;CHARSET=xxxxx;

だったりするので、Connectプロパティを直に書換えるのはバージョンの依存度がかなり高そう。

※CHARSETを正しく指定しないと環境文字(㈱等)が?になったりするので地味に痛い。

実際にはこんな感じで使ってみた。

Public Sub ODBC接続先個別更新(SERVER_IP_ADR As String, UID As String,  PWD As String)
  For Each tableDef In CurrentDb.TableDefs
    If tableDef.Attributes = dbAttachedODBC Then   'リンクテーブルならば、dbAttachedODBC=536870912
        con = tbldef.Connect
        If con <> "" Then   '  一応、conが""の場合、をsplit(con,";") すると ubound() = -1になってしまうため除外する
            Dim a() As String
            a = Split(con, ";")
            Select Case a(0)
            Case "":    ' MDB
            Case "ODBC":    ' ODBC
                Dim fff As Boolean
                fff = False
                Dim b() As String
                Dim i As Integer
                Dim fUID As Boolean
                fUID = True
                Dim fPWD As Boolean
                fPWD = True
                For i = 1 To UBound(a)
                    If a(i) <> "" Then
                        b = Split(a(i), "=")
                        Select Case b(0)
                            Case "DATABASE":  '特に何もしない
                            Case "UID":
                                fUID = False
                                If b(1) <> UID Then
                                    Debug.Print "SERVER='" & b(1) & "' を 'SERVER=" & SERVER_IP_ADR & "'に更新します。"
                                    fUID = True
                                    b(1) = UID
                                    a(i) = Join(b, "=")
                                End If
                            Case "PWD":
                                fPWD = False
                                If b(1) <> PWD Then
                                    Debug.Print "SERVER='" & b(1) & "' を 'SERVER=" & SERVER_IP_ADR & "'に更新します。"
                                    fPWD = True
                                    b(1) = PWD
                                    a(i) = Join(b, "=")
                                End If
                            Case "DSN":     '特に何もしない
                            Case "OPTION":  '特に何もしない
                            Case "PORT":    '特に何もしない
                            Case "SERVER":
                                If b(1) <> SERVER_IP_ADR Then
                                    Debug.Print "SERVER='" & b(1) & "' を 'SERVER=" & SERVER_IP_ADR & "'に更新します。"
                                    fff = True
                                    b(1) = SERVER_IP_ADR
                                    a(i) = Join(b, "=")
                                End If
                            Case "CHARSET":  '特に何もしない
                            Case Else:       '特に何もしない
                        End Select
                    End If
                Next
                ' UIDが未設定の場合、追記する
                If fUID Then
                    ReDim Preserve a(UBound(a) + 1)
                    a(UBound(a)) = "UID=" & UID
                    fff = True
                End If
                ' PWDが未設定の場合、追記する
                If fPWD Then
                    ReDim Preserve a(UBound(a) + 1)
                    a(UBound(a)) = "PWD=" & PWD
                    fff = True
                End If
                ' 何か変更されていた場合は、接続テキストを再構成する
                If fff Then
                    con = Join(a, ";")
                    tbldef.Connect = con
                    tbldef.RefreshLink
                    Debug.Print "設定を更新しました。" & vbCrLf & "'" & con & "'"
                End If
            End Select
        End If
    End If
  Next tdf
End Sub

どうやらリンクテーブルには

  • TableDefAttributeEnum.dbAttachedODBC
    MS SQLServer など、ODBC を使うリンクテーブル
  • TableDefAttributeEnum.dbAttachedTable
    MS Access などの非ODBCのリンクテーブル

の2種類があるらしいけど、ググってもどんな動作環境なのかは判らなかったので、

  • Enumクラスを指定しないと遺憾な場合
  • Enumクラスがそもそも無い場合

がありそうで、この辺は実際に動かして調整するしか無さそうだ。

それとPORTなんかが違う場合もありそうだ。

※デフォは学習用、xxxxはデバッグ用、yyyyはテスト用、zzzzは実機とかね。

他のデータベースの場合は、コードページの設定やオプション等も違うだろうし、データベース・ディクショナリ名とか実行時ロール名とか独特な何かを指定しないとダメな場合もあるだろう。

そんな風にDATABASEが違うだけでテキストが全く異なる場合には最初のコードの方が良さそうだから、

MS-ACCESSのVBAのBASファイルには両方を置いておいた方が安心かな。




top