愚者の経験

「また今度」はほとんどこない

Access2010でのODBCDirectの代替案

Access2013はAccessProject(ADP)がサポートされないのでほぼODBCを使うことになると思います。
しかしAccess2007以降ODBCDirectは使えません。

以下の文は実行時エラー3847
「ODBCDirectはサポートされません。DAOの代わりにADOを使用するには、
コードを記述しなおしてください。」と怒られます。

        CreateWorkspace("test", "", "", dbUseODBC)

ではADOでしか外部データベースに接続できないのかというとそうでもありません。
ODBCDirectの代わりにどうやって動的(コード)で接続するかというと
TableDef、QueryDefにある「Connect」プロパティを操作することで実現可能になります。

SQLコマンドパススルー発行関数

Public Function ServerExecute(SQLString As String, Connect As String, _
                Optional ReturnsRecords As Boolean = False, _
                Optional RecordsetType As DAO.RecordsetTypeEnum = dbOpenForwardOnly, _
                Optional RecordsetOption As DAO.RecordsetOptionEnum = dbReadOnly + dbSQLPassThrough, _
                Optional StoredReturn As Boolean = False) As DAO.Recordset

    With CurrentDb.CreateQueryDef("")
        .Connect = Connect
        .SQL = SQLString
        .ReturnsRecords = ReturnsRecords
        .ODBCTimeout = 0

        If (ReturnsRecords = True) Then
            Set ServerExecute = .OpenRecordset(RecordsetType, RecordsetOption)
        Else
            If (StoredReturn = True) Then
                .ReturnsRecords = True
                .SQL = "declare @ret int" & vbCrLf & _
                    "execute @ret=" & .SQL & vbCrLf & _
                    "select @ret as Ret"
                Set ServerExecute = .OpenRecordset(RecordsetType, RecordsetOption)
            Else
                .Execute
            End If
        End If
    End With
End Function

こんなかんじにすればDatabaseオブジェクトをオープンせずに
外部データベースにコマンドを発行、結果の取得ができます。

DAO.Recordsetをフォームの「Recordset」プロパティにセットする場合はRecordsetTypeをdbOpenSnapshotに指定しないと、実行にエラー(ナンバー7965)となり
「”Recordset/レコードセット”プロパティに、そのオブジェクトは使えません」が出ます。

またテーブルのリンクを貼り直すには以下のような感じで。

Public Function TablesRelink(ByVal Connect As String) As Boolean
On Error Resume Next
        Dim tdf As TableDef
        Dim pConn As String

        ' テーブルオブジェクトをループ
        For Each tdf In CurrentDb.TableDefs
                With tdf
                        ' Connectプロパティがあるかどうかでリンクテーブルかを調べる
                        If (Nz(.Connect, "")  "") Then
                                pConn = .Connect

                                ' プログラムの接続文字列代入
                                .Connect = Connect
                                .RefreshLink

                                If (Err.Number <> 0) Then
                                        ' エラーの場合は接続文字列を元に戻す
                                        .Connect = pConn
                                        Err.Clear

                                        ' 元の接続文字列でリンク確認
                                        .RefreshLink
                                        If (Err.Number <> 0) Then
                                                TablesRelink = True
                                                Err.Clear
                                        End If
                                End If
                        End If
                End With
        Next
End Function

複数のODBCでリンクしている場合は難しいですね。
これは内部ではJET経由になるのでしょうね。

広告

Access2010でのODBCDirectの代替案」への5件のフィードバック

  1. snaf 1月 23, 2013 2:10 pm

    こんにちは。
    SQLコマンドパススルーで得られたレコードセットをフォームのデータシートに表示する方法知りませんか?
    SQL ServerはExec …の形です^^;;

    • rsskkr 1月 23, 2013 6:26 pm

      はじめましてsnafさん、rsskkrです。コメントいただきありがとうございます。
      ご質問に回答いたしたいのですが、「SQLコマンドパススルーで得られたレコードセット」とは
      どのような状態を指してらっしゃいますか?

      見当違いかもしれませんがExecの形でもこの投稿にあります「ServerExecute」の関数の
      第一引数にそのまま代入すれば実行出来ると思います。それをセットすれば表示できます。

      Set Me.Recordset=ServerExecute(“exec (‘select 1 as test’)”,”DSN=xxxx;~~~”,True,dbOpenSnapshot)

      上記の様にVBAをわざわざ使わなくてもセオリー通りAccessでパススルークエリを作成し、
      それをフォームのレコードソースに設定すれば表示は可能のはずです。

      考えが及ばず申し訳ありませんが、支障がない程度で構いませんので詳細を
      教えていただけるとまた別の回答も出来るかもしれません。

  2. hide. 3月 26, 2015 5:32 pm

    ファイルDSNだと、できないですよね?

    • rsskkr 3月 30, 2015 10:01 am

      hide.様
      はじめまして、コメントありがとうございます。
      ファイルDSNはファイルの中を読んで得られた文字列をConnectプロパティに入れればとりあえず動くのではないかと思います。

  3. hide. 3月 31, 2015 10:48 am

    rsskkr様
    ありがとうございます。ご指摘の方法で確認できました。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。