接続先データベースの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ファイルには両方を置いておいた方が安心かな。