[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『ADOでリンクテーブルの接続』(TAKA)
宜しくお願いします。EXCEL,2007 ACCESS,2010です。
社内のPC-AとPC-BがありましてPC-Aのデスクトップ上の共有フォルダにリンク.accdbのファイルがあります。クエリなど5個程のテーブルをリンクさせております。ちなみにPC-AのみACCESSがインストールされています。PC-AのEXCELから下記コードを実行すると作動しますがPC-Bから操作すると「パス'C\Users....accdbは正しくありません。パス名に間違いないことと、ファイルが置かれたサーバーに接続していることを確認してください。」とエラーが表示されます。
質問内容はACCESSのリンクテーブルを使用してフルパスで他のPCからデータの抽出は可能でしょうか?仕様は共有フォルダのEXCELからADOを利用してテーブルのレコード更新、変更、削除(同時に編集できないようにEXCEL VBAで制御はしています。)クエリなどの抽出はACCESSのリンクテーブルで行いたいと考えています。
申し訳ございませんが抽出方法を教えて下さい。
Dim db As Object, rs As Object, cmd As Object, SQL As String
SQL 〜 省略 〜
Set db = CreateObject("ADODB.Connection")
db.Provider = "Microsoft.Ace.OLEDB.12.0"
db.Open ThisWorkbook.Path & "\リンク.accdb"
Set rs = CreateObject("ADODB.Recordset")
Set cmd = CreateObject("ADODB.Command")
Set cmd.ActiveConnection = db
cmd.CommandText = SQL
Set rs = cmd.Execute
If rs.EOF Then MsgBox "抽出した結果、レコードが見つかりません。"
Else
Range("a3").CopyFromRecordset rs
End If
rs.Close: db.Close
Set rs = Nothing: Set db = Nothing
ThisWorkbook.Path & "\リンク.accdb"
ネットワーク越しにファイルを参照するには
パスは\\****\**\リンク.accdbとなります。
PC-BからPC-Aの共有フォルダを開きリンク.accdbのプロパティを見て
フルパスを確認しましょう。
PC-Aも、\\****\**\リンク.accdbで接続できますが、ネットワーク越しに接続
する形になるので速度が落ちます。
PC-AはThisWorkBook.Path
PC-Bは\\****\**\リンク.accdb
で利用するようにします。
ここで問題になるのが、パスのハードコーディングです。(直にパスを書いてしまう)
利用する環境が変わった。Excelファイルを修正し配布し直した時などの事
を考えるとうまい仕組みが必要ですね。
・iniファイルに接続パスを仕込みOpen毎にiniファイルからパスを得る
・隠しシートに接続パスを仕込む
接続パスを返す関数を作成
Public Function GetDbPath() As String
Dim sh As WorkSheet Set sh = WorkSheets("隠しシート名") GetDbPath = sh.Range("A1").Value 'A1にはフルパス End Function
使用例
db.Open GetDbPath
接続先を選択して登録できる仕組みを作成します。(GetOpenFileNameなどで)
選択されたaccessファイルのパスをiniファイルや隠しシートに登録します。
この時大事なのは、上でも書きましたがPC-Aは必ず自デスクトップ上の
フォルダを直接選択し登録することです。ネットワーク→共有フォルダと
辿ってしまうと折角自PC上にあるのに速度低下を招きます。
このような仕組みを作成しておけば、環境が変わったり配布する数が多くなって
きても直ぐ対応出来ます。
(DonDon)
>テーブルをリンクさせております このリンク元のaccdbファイルは、PC-Bから見れる場所にあるんですか?
これも共有しておかないと、操作は、できませんよ!!
確認してみてください。
私は、Excelブックは、最近は、一つで共有させえていますよ、 最初から、読み取り専用にしていますから・・・。Excelにコードを置くのですから、 これに通常は、書き込みはしませんから・・・。
ichinose
回答ありがとうございました。
DonDon様、作動するか検証したいと思います。すいません!少しお時間を下さい。
ichinose様、PC-AにのみACCESSが導入しており、共有フォルダにテーブルのみのaccdbファイルをいくつも作成してあります。そのテーブルaccdbから同じ共有フォルダにリンクaccdbにリンクさせております。
EXCELファイルも同じ共有フォルダに複数入っておりますが、他の人が使用しているとBOOKを開けないよう制御はしています。
元々accdbファイルは一つでその中でテーブルやクエリを作成していましたが、先日、accdbがフリーズしてしまい。対策としてテーブルごとにファイルを作成して更新用と集計、抽出用のリンクテーブルを作成したほうがよいかと思いました。
PC-Bから共有フォルダ(PC-A)のリンク.accdbから抽出できたらと考えています。
DonDon様の回答も踏まえて色々トライしてみようと思います。
>PC-Bから共有フォルダ(PC-A)のリンク.accdbから抽出できたらと リンクテーブル設定時にUNCパスで設定されていますか? そうでなかったら、UNCパスでリンクテーブルを再設定してみて下さい
ichinose
ネットワーク越しにファイルを参照するにはサーバー名を指定すればよかったのですね!勉強になりました。
UNCパスでリンクテーブルを再設定したらあっさり作動しました。
後は、Excelファイルを全てのPCに配布しようか悩んでおります。今後のメンテナンス等も含めて色々トライしてみようと思います。
リンクテーブルもThisWorkbook.Pathみたいに簡単にフルパスができればよいのですが・・・ネットで調べるとVBAでできるみたいなことは書いてあったのですが。自宅にUSBで持ち帰るとリンクを再設定するのが大変なので今度、勉強してみようと思います。
返事が遅くなり申し訳ございませんでした。ありがとうございました。仕事で月末処理が終わらなかったので・・・
(TAKA)
>リンクテーブルもThisWorkbook.Pathみたいに簡単にフルパスができればよいのですが・・・ネットで調べるとVBAでできるみたいなことは書いてあったのですが
私も以前、テーブルリンク設定コードを調べた事がありました。 私は、これを仕事では使ったことがありませんが・・・。
Adox.Catalog を使って、既存テーブル属性を調べるとリンクテーブルの作成は、 出来ると思いますよ!!
標準モジュール(Module1)にAdox I/O プロシジャー群
'============================================================================ Private cat As Object 'ADOX.Catalog Function open_cat(flnm As String) As Long On Error Resume Next Set cat = CreateObject("ADOX.Catalog") cat.ActiveConnection = "Provider=Microsoft.Ace.OLEDB.12.0;" & _ "Data Source=" & flnm open_cat = Err.Number On Error GoTo 0 End Function '================================================================= Function get_cn() As Object Set get_cn = cat.ActiveConnection End Function '================================================================= Function create_lnktbl(tblnm As String, l_tblnm As String, ldbnm As String, Optional pwd As String = "", Optional exstr As String = "") As Long 'リンクテーブルを作成する 'Input:tblnm----テーブル名 ' l_tblnm--リンク先テーブル名 ' ldbnm----リンク先dbのフルパス ' pwd------リンク先にパスワードが設定されている場合、そのパスワード(省略可) ' exstr----他のデータベース(Excelやtxtファイル、etc)をリンクするときの追加ストリング(省略可) 'Output:create_lnktbl----0--正常終了,その他:異常終了 On Error GoTo err_lnkcreate_tbl Dim tbl As Object 'ADOX.Table create_tbl = 0 Set tbl = CreateObject("ADOX.Table") tbl.Name = tblnm Set tbl.ParentCatalog = cat With tbl .Properties("Jet OLEDB:Create Link").Value = True .Properties("Jet OLEDB:Remote Table Name").Value = l_tblnm .Properties("Jet OLEDB:Link Datasource").Value = ldbnm If pwd <> "" Then .Properties("Jet OLEDB:Link Provider String") = ";pwd=" & pwd If exstr <> "" Then .Properties("Jet OLEDB:Link Provider String").Value = exstr End If End With cat.Tables.Append tbl Set tbl = Nothing
ret_lnkcreate_tbl: On Error GoTo 0 Exit Function err_lnkcreate_tbl: MsgBox Error(Err.Number) create_tbl = Err.Number Resume ret_lnkcreate_tbl End Function '================================================================= Sub close_cat() On Error Resume Next cat.ActiveConnection.Close Set cat = Nothing On Error GoTo 0 End Sub
別の標準モジュール(Module2)に
'========================================================================== Sub mk_lnktbl() Dim uncp As String With CreateObject("wscript.network") uncp = "\\" & .computername & "\" & Replace(ThisWorkbook.Path, ":", "") End With If open_cat(ThisWorkbook.Path & "\Linktest.accdb") = 0 Then Call create_lnktbl("newtbl1", "Testtbl", uncp & "\testacc.accdb") End If Call close_cat End Sub
mk_lnktblの実行で このVBAコードを含むExcelブックと同じフォルダ上にある
Linktest.accdb というデータベースファイル上に
同じフォルダ上にあるtestacc.accdb内のTesttblというテーブルを
newtbl1 というテーブル名でリンクテーブルを作成します。
UNCパス変換は、WMIかAPIを使えばできるかもしれませんが、 今回は、WSHでコンピュータ名を取得し、あとは、文字列の置き換えで作成しました。
又、create_lnktblは、パラメータの指定で、Excelシートやtxtなどもリンク可能にしてあります。
参考になれば、幸いです。
ichinose
とりあえず下記内容でリンクの変更をトライ中ですが、うまくいかず相談させて下さい。PC-Aのフォルダの中にaaa.accdb, bbb ccc のファイルとリンク.accdbがあり、例えばaaa.accdbファイルにT_aaaのテーブルが一対でテーブルを作成しています。
リンク.accdbの標準モジュールに下記コードで一括変更したいのですが、DATABASE=\\・・・の所で処理が止まってしまい教えて頂けないでしょうか?文字列の結合の部分だと思うのですが・・
Dim tdf As TableDef, dbs As Database
Dim tbl() As Variant, fil() As Variant, i As Byte
'Microsoft DAO 3.6 Object Library参照設定
tbl = Array("T_aaa", "T_bbb", "T_ccc") 'テーブル名
fil = Array("aaa", "bbb", "ccc") 'accdbファイル名
Set dbs = CurrentDb
For i = 0 To UBound(tbl)
Set tdf = dbs.TableDefs(tbl(i))
With tdf .Connect = ";DATABASE=\\サーバー名\(省略)\フォルダ名\" & fil(i) & ".accdb";TABLE=" & tbl(i) .RefreshLink End With
Set tdf = Nothing Next i
MsgBox "リンクテーブルの変更が完了しました。"
dbs.Close: Set dbs = Nothing
(TAKA)
今度は、DAOですか? 私はDAOは、普段使わないのですが・・・、
Sub test() Dim tdf As TableDef, dbs As Database Dim tbl() As Variant, fil() As Variant, i As Byte Dim uncp As String uncp = "\\" & CreateObject("wscript.network").computername With CreateObject("scripting.filesystemobject") uncp = uncp & "\" & Replace(.GetParentFolderName(CurrentDb.Name), ":", "") End With tbl = Array("T_aaa", "T_bbb", "T_ccc") 'テーブル名 fil = Array("aaa", "bbb", "ccc") 'accdbファイル名 Set dbs = CurrentDb For i = 0 To UBound(tbl) Set tdf = dbs.TableDefs(tbl(i)) With tdf .Connect = ";DATABASE=" & uncp & "\" & fil(i) & ".accdb;TABLE=" & tbl(i) .RefreshLink End With Next i
MsgBox "リンクテーブルの変更が完了しました。"
dbs.Close Set tdf = Nothing Set dbs = Nothing
End Sub
ichinose@GW中の旅行で食べ過ぎ・・・
教えて頂いたコードにてトライしました。最初の質問の時のエラー表示がされます。msgbox uncpで確認すると、\\サーバー名\C\・・・・と恐らくドライブ名も連結されている為かと思われます。
とりあえず自分が掲示したコードの連結部分を修正したら作動しましたので下記のように都度、環境に合わせて切り替えようと思います。テーブルが増えるとArrayの部分で追加して・・・VBAのようで手動なんですけど(笑)
ichinose様、色々とお世話をおかけしました。大変助かりました。
With tdf
.Connect = ";DATABASE=\\サーバー名\(省略)\フォルダ名\" & fil(i) & ".accdb;TABLE=" & tbl(i) '.Connect = ";DATABASE=\\サーバー名\(省略)\フォルダ名\" & fil(i) & ".accdb;TABLE=" & tbl(i) .RefreshLink End With
(TAKA)
>\\サーバー名\C\・・・・と恐らくドライブ名も連結されている為 あっ、そうですねえ、そういう場合もありますねえ!! やっぱり、共有一覧と照らし合わせないと駄目ですねえ!!
一覧は、WMIを探ってみたらありました。
http://www.wmifun.net/sample/win32_share.html
この一覧と照合する方法でしょうかねえ!!
ichinose
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.