今回の記事では、Excel VBAやAccess VBAの「ADO」を使用し、データベースへ接続してレコードセットを取得する一連の処理を初心者向けに解説していきます。
VBAで業務用のツールを開発したり、データ集計を自動化する場合に、ADOは必ず習得しておきたい技術です。
是非参考にしてください。
ADOとは
「ADO」の正式な名称は「ActiveX Data Objects」です。
このADOは様々なデータベースに接続してレコードを扱うための汎用的なインターフェイスです。
ADOはVBAから自由に呼び出すことができて、ExcelやAccess、Wordといったアプリケーションから、OracleやSQL Serverなどの外部データベースとの連携を可能にします。
また、VBAだけではなく、VBScriptやJavaなど別のプログラミング言語から呼び出すことも可能です。
因みに、VB.NETやC#などの.NET Frameworkを使用した言語では、ADO.NETを使用します。
ADOを使用するための参照設定
VBAのコードからADOを使用するために「参照設定」の方法を紹介します。
まず、「ADO」はVBAの基本的な言語の機能には実装されておらず、VBAから呼び出しが可能な「外部ライブラリ」として存在しています。
その「外部ライブラリ」をVBAのコード上で使用するためには、そのライブラリをVBA内で紐付けてあげる必要があります。
その紐付けを「バインディング」と呼んだりしますが、VBAでは「事前バインディング」と「遅延バインディング」といった仕組みがあります。
この違いは以下です。
種類名 | 内容 |
---|---|
遅延バインディング | 動的バインディングなどとも呼ばれます。 VBAのコード内でオブジェクト名を指定してオブジェクトを生成することで使用可能になります。 具体的には、CreateObject関数の引数としてオブジェクト名を渡して実行し、Object型の変数に代入します。 指定したオブジェクト名をもとにその実行環境に入っている適切なライブラリを自動的に参照します。 |
事前バインディング | 静的バインディングなどとも呼ばれます。 VBE(Visual Basic Editor)の画面上部の「ツール」から参照設定画面を開くと、参照可能なライブラリの一覧が表示されます。 使用するライブラリにチェックを付けて登録しておくことで、遅延バインディングのようにCreateObjectをしなくても、対象のオブジェクトを呼び出せるようになります。 予め参照設定で有効化しておくことで、VBAで対象のオブジェクト名やオブジェクト変数名を記述した際に、対応したメソッド名やプロパティ名が候補として表示される「入力補完機能」が使える。 |
事前バインディングをした場合、チェックを付けたライブラリ名と同じ名称のライブラリが実行環境に存在しないとコンパイルエラーになります。
例えば、Access VBAからExcelの機能を呼び出す際に、参照設定からライブラリを指定する場合は以下の画像のようになります。
この参照設定画面では、「Microsoft Excel 16.0 Object Library」を指定しています。
このライブラリはExcel 2016以降で使用されるライブラリであり、それ以前のバージョンのExcelがインストールされている端末で、この参照設定を入れたAccessファイルを開いても、対象のライブラリが見つからないため、参照設定が外れてしまいます。
参照設定が外れれば、そのライブラリを参照してオブジェクトを生成している処理の全てでエラーが発生することになります。
逆に遅延バインディングでは、オブジェクト名にバージョン名まで含めなくても良いものも多く、その場合は実行環境のバージョンに合わせたライブラリを自動的に参照します。
例えば、Access VBAからExcelの機能を呼び出す場合に使用するライブラリを遅延バインディングで指定する場合のサンプルは以下です。
※Access VBAからExcelを起動して終了するだけの処理です。
Dim objExcel As Object
Set objExcel = CreateObject("Excel.Application")
'Excelを表示します。
objExcel.Visible = True
'新規ブックを作成します。
objExcel.Workbooks.Add
'オブジェクトを破棄します。
Set objExcel = Nothing
参照設定をせずに、上記のようにコード上で参照させる場合、例えばExcel 2019がインストールされた端末上で作ったAccessアプリケーションであっても、古いExcelがインストールされている環境で開いても参照が外れてエラーになることはありません。
その意味では遅延バインディングのメリットは大きいのですが、VBAのコードを書くにあたって入力補完機能が使えないと、何かと面倒でもあります。
また、今回紹介するADOについては、異なるOSやOfficeのバージョンによって、入っているライブラリに大きく相違があるものではないため、当記事では「事前バインディング」を前提としてコードを記述していきます。
よって、VBE上部の「ツール」→「参照設定」を選択し、
前述した「参照設定」画面を表示して、以下のライブラリにチェックを入れてください。
尚、他にもバージョン違いで複数のライブラリがありますが、2.7以前は古いADOの互換維持で用意されており、6.1など大きいバージョン番号のライブラリもありますが、中身は2.8とほぼ同じものの様です。
通常は「Microsoft ActiveX Data Objects 2.8 Library」にチェックをつけてください。
ADOでデータを取得する一連の流れ
VBAからADOを利用して、外部のデータベースに対してデータを取得する一連の処理の流れを説明します。
- ADOオブジェクトを生成
- 接続先データベースへの接続文字列を使用して外部DBに接続
- SQL分を生成し、文字列型の変数に代入
- ADOオブジェクトを使用してSQLを実行し、戻り値をレコードセットで受け取る
- データベースへの接続を閉じる
- ADOの各オブジェクトを破棄する
実際のコードでは、データベースへの接続とSQLを実行してデータを取得する処理が同時に実施する場合もあり、上記の流れとは異なる場合もありますが、基本は上記の流れです。
対象のデータベースに対して、データベース側のユーザーIDやパスワードなどで認証したうえで、接続をする必要があります。
接続しないと、その後のデータ取得やデータ更新処理はできません。
接続が成功したら、そのデータベースに対してSQLなどを渡して実行させます。
尚、必ずしもSQLを実行しないといけないものではありませんが、SQLを使用する前提で覚えていただいた方が、より高度な処理にも対応できます。
SELECT文を実行した場合は処理結果としてSELECT結果の表が戻されてきますし、UPDATE文などの更新処理を実行した場合は、処理件数などの値が戻されてきます。
表はレコードセットとして戻されてくるため、そのレコードセットを取得してループで回して各行ごとの値を取り出すなどの処理をします。
一通りの処理が済めば、データベースとの接続は切断し、ADOで使用した各オブジェクトは破棄します。
今回の記事では、上記の流れで処理を実装する前提でサンプルコードの紹介や、実装内容の解説をしていきます。
データベース接続処理
ADOでは、まずデータベースとの接続をする必要があります。
当項では、ADOのオブジェクト変数を作成して、データベースとの接続に関する処理を説明していきます。
具体的には、ADOで用意されている「Connectionオブジェクト」を使用します。
詳しくは以下のMicrosoftの公式リファレンスをご参照ください。
VBAでADOを使用してデータベースに接続する部分のみを抜粋したコードは以下になります。
※以下のコードで記載している「接続文字列」については後述します。
Dim objCon As ADODB.Connection
Dim ConString As String
'新規インスタンスを作成します。
Set objCon = New ADODB.Connection
'接続文字列を変数に代入します。
ConString = "接続文字列"
'ConnectionオブジェクトのOpenメソッドに接続文字列を渡して接続します。
objCon.Open ConStirng
'コネクションを切断します。
objCon.Close
4行目では新規インスタンスを生成して変数objConにオブジェクトへの参照を代入しています。
8行目でOpenメソッドに接続文字列が格納された変数を引数として渡してデータベースと接続しています。
10行目でコネクションと切断しています。
【余談】オブジェクト変数宣言時のNewについて
「オブジェクト変数の宣言時にNewを付ける場合と付けない場合で何が違うのか」について、当記事の趣旨から外れますが簡単に解説しておこうと思います。
例えば、変数の宣言と同時にNewを指定することで、前述したデータベース接続時のコードの4行目を以下のように省略することができます。
Dim objCon As New ADODB.Connection
Dim ConString As String
ConString = "接続文字列"
objCon.Open ConString
objCon.Close
変数宣言時にNewを指定しておくことで、そのオブジェクトを最初に参照するタイミングでインスタンスが生成される挙動になります。
少ないコードで処理が記述できたほうが本来は望ましいのですが、当記事ではADO初心者向けに解説していることもあり、敢えて省略をしない前者の構文を採用します。
省略しない書き方の方が、変数の宣言と、新しいインスタンスを作成してオブジェクトへの参照を変数に代入する処理が分離されており、理解がより深まりやすい考えています。
接続文字列とは
今回の記事で紹介しているようなVBAなどのアプリケーションが外部のデータベースと接続する場合には、接続先の各データベース製品ごとに「ドライバー」又は「プロバイダー」と呼ばれるデータベース接続用のインターフェイスを仲介する必要があります。
そのインターフェイスはデータベース製品ごとに提供されており、データベースへの接続が必要になる端末には予めインストールしておきます。
このインターフェイスは主に「ODBC」と「OLE DB」の二種類があり、この記事でその違いを説明すると長くなるため割愛しますが、どちらのインターフェイスが実行環境の端末に入っているかによって、当項で説明する「接続文字列」の種類が変わります。
データベースと接続する際に、接続先データベースのホスト名(IPアドレス)やデータベースへのログインユーザー名やパスワード、接続するデータベース名やスキーマ名を指定する文字列を「接続文字列」と呼びます。
接続先データベース製品の種類やバージョンによって、文字列として対応している書き方(書式)は異なっており、決められた書式で接続情報を指定する必要があります。
以下で主要なRDBMSへの接続文字列の書式を紹介しておきます。
尚、接続先の製品によって接続文字列は様々あり、それらを広く当記事に掲載するのは困難です。
よって、以下に掲載していないデータベースへ接続する場合は、インターネットで検索してください。
すぐに目的の情報は見つかると思います。
接続先 | 接続文字列 |
---|---|
Access 2007以降 | Access 2007 – 2010 Provider = Microsoft.ACE.OLEDB.12.0; Data Source = ファイルパス Access 2013 Provider = Microsoft.ACE.OLEDB.15.0; Data Source = ファイルパス Access 2016 – 2021 Provider = Microsoft.ACE.OLEDB.16.0; Data Source = ファイルパス |
Microsft SQL Server(ODBC) | SQL Server認証 DSNレス接続 Driver={SQL Server};Server=接続先サーバ;Database=データベース;Uid=ユーザID;Pwd=パスワード |
Microsft SQL Server(OLE DB) | SQL Server認証 DSNレス接続 Provider=SQLOLEDB;Data Source=接続先サーバ;Initial Catalog=データベース;User Id=ユーザID;Password=パスワード |
ORACLE(OLE DB) | Oracle Clientのインストールが必要 tnsnames.oraを使用する場合 Provider=OraOLEDB.Oracle;Data Source=ネットサービス名;User Id=ユーザID;Password=パスワード |
ORACLE(OLE DB) | Oracle Clientのインストールが必要 接続情報を直接記述する場合 Provider=OraOLEDB.Oracle;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=サーバ名)(PORT=ポート番号))(CONNECT_DATA=(SERVICE_NAME=サービス名)(SERVICE_NAME=XE)));User ID=ユーザID;Password=パスワード |
今回の記事では、SQL ServerにODBCを使用して接続する前提でコードを紹介していきます。
レコードセットの解説とRecordsetオブジェクトの扱い方
当項では、ADOのデータ操作に欠かせないレコードセットに関する基礎的な解説と、「Recordsetオブジェクト」の扱い方を解説していきます。
レコードセットとは
まずは、そもそも「レコードセット」とは何か?について説明していきます。
RDB(リレーショナルデータベース)では、一つ一つのデータを行単位で管理をします。
その行ごとのデータを「レコード」と呼びます。
そのレコードをRDBから取得して、1行、又は複数行をメモリー内に格納するための一時的な入れ物を「レコードセット」と呼びます。
その一時的な入れ物は、RDBと同じように、列名を指定できて列ごとにデータ型を持ち、仮想的なテーブルのようにレコードを格納できます。
「レコードセット」はメモリー内で保持するための入れ物であり、ExcelやAccessなどから呼び出した場合、そのExcelやAccessを終了すると、メモリー内に保持していたレコードセットも消滅します。
ADOでは「Recordset」オブジェクトのインスタンスを作成して、レコードセットを格納します。
そのRecordsetオブジェクトを明示的に破棄しても消滅します。
レコードセットとカーソルの移動
レコードセットにレコードを格納後、そのレコードの値を確認するには、現在プログラム上でレコードセット内のどの行を参照しているかを把握し、参照する行を明示的に移動させながら処理をしていきます。
その参照を「カーソル」と呼び、現在参照しているカーソルを「カレントレコード」と呼びます。
レコードセット内にレコードが1行しか格納されていない場合はカーソルを移動する必要がありませんが、レコードセット内に複数行格納されている場合はループ処理と組み合わせて、カレントレコードを明示的に移動させながら全行を走査して処理をします。
Recordsetオブジェクトのカーソルの移動において最低限理解しておかないといけない、Recordsetオブジェクトのプロパティやメソッドを以下で紹介しておきます。
名前 | 種類 | 説明 |
---|---|---|
BOF | プロパティ | カレント レコードの位置が Recordset オブジェクトの最初のレコードより前にあることを示します。 |
EOF | プロパティ | カレント レコードの位置が Recordset オブジェクトの最後のレコードより後にあることを示します。 |
MoveNext | メソッド | カレント レコードの位置を 1 レコード前方 (Recordset の終端方向) に移動します。 |
MoveFirst | メソッド | カレント レコードの位置を Recordset の最初のレコードに移動します。 |
MoveLast | メソッド | カレント レコードの位置を Recordset の最後のレコードに移動します。 |
「MoveNext」の説明では「1レコード前方に移動します」となっていますが、そのまま受け取ると逆の機能として理解してしまうため、単純に「次のレコードに移動する」と理解してください。
上記以外にもカーソルの移動に関連するプロパティやメソッドは幾つかありますが、最低限上記のプロパティとメソッドを知っておけば事足ります。
上記のプロパティやメソッドを視覚的に図にすると以下になります。
このイメージ図の解説をしていきます。
「カレントレコード」は、レコードセットオブジェクトが参照している現時点のレコードの位置です。
レコードセットではレコードを参照する際に、MoveFirstやMoveLastなどで位置を指定しない限り、カレントレコードは1行目から開始します。
MoveNextメソッドを実行することで、カレントレコードは次のレコードに移動します。
カレントレコードがレコードセットの最終行を超えると、「EOF」プロパティがTrueになります。
ループ処理のなかで、この「EOF」プロパティの値を使用してレコードセットの最終行まで到達したかどうかを判定します。
また、そもそもレコードが無い状態を判別する場合にも、このEOFを使用します。
言葉で説明してもイメージがし難いため、レコードセットをループで処理する実装例を、部分的に抜粋して紹介します。
'EOFがTrueならレコードが存在しない。
If objRs.EOF Then
MsgBox "レコードが存在しません。"
Exit Sub
End If
'EOFがTrue = カレントレコードが最終行に到達したらループ終了
Do Until objRs.EOF
'レコードセットの0番目の列の値をDebug.Printで出力
Debug.Print objRs(0).Value
'カレントレコードを次に移動
objRs.MoveNext
Loop
このコードの「objRs」がRecordsetオブジェクトです。
EOFプロパティやMoveNextメソッドは上記のように使用するのが定石です。
尚、「BOF」プロパティでは先頭より前を判別できますが、カレントレコードを前に戻すような処理を使わない限り使う機会はないため、「EOF」との対比としてそういったプロパティがあるという程度の理解で結構です。
また、上記以外のプロパティやメソッドは、以下のMicrosoftの公式リファレンスをご確認ください。
レコードセット取得方法の種類と解説
当項では、レコードセットを取得する際の実装方法を、その種類ごとにサンプルコードを元に解説していきます。
レコードセットの取得方法例
ADOで接続したデータベースからレコードを取得してレコードセットを作成する方法は主に以下の方法があります。
- RecordsetオブジェクトのOpenメソッドで直接レコードセットに格納する。
- ConnectionオブジェクトのExecuteメソッドを実行してその戻り値をレコードセットオブジェクトに格納する。
- CommandオブジェクトのExecuteメソッドを実行してその戻り値をレコードセットオブジェクトに格納する。
ADOの操作に不慣れな場合やこれから学ぼうとされている場合は、ADOでデータベースからレコードを取得する方法をインターネットで調べても、記事によって採用する実装方法が異なることで、混乱する要因になります。
よって、上記で紹介した三通りの実装方法を当記事ではまとめて紹介します。
ただ、この三通りを使い分けられる必要はあまりなく、どれか一つの手法だけを覚えておけば十分です。
また、この三通りの手法のなかで、一つだけ覚えておくのであれば、「Connectionオブジェクト」の「Executeメソッド」を使用してデータを取得する方法です。
RecordsetオブジェクトのOpenメソッド実装例
当項では、RecordsetオブジェクトのOpenメソッドを実行して、レコードを取得する一連の処理を解説します。
尚、RecordsetオブジェクトのOpenメソッドに対する、Microsoftのリファレンスページのリンクは以下です。
詳しくは以下のリンクをご確認ください。
実際にRecordsetオブジェクトのOpenメソッドを使用してレコードを取得する場合の実装例を紹介します。
'ADODBのRecordsetオブジェクトの変数を宣言します。
Dim objRs As ADODB.Recordset
Dim ConString As String
Dim strSQL As String
'接続文字列を変数に格納しています。
ConString = "Driver={SQL Server};Server=IPアドレスやホスト名;Uid=ユーザーID;Pwd=パスワード;Database=データベース名"
'Recordsetオブジェクトの新規インスタンスを作成します。
Set objRs = New ADODB.Recordset
'実行するSQL文を変数に格納します。
strSQL = "SELECT * FROM Customer"
'RecordsetオブジェクトのOpenメソッドに必要な引数を渡してデータを取得しています。
objRs.Open strSQL, ConString, adOpenKeyset, adLockOptimistic
'レコードセットの0番目の列の値をDebug.Printで出力します。
Debug.Print objRs(0).Value
'Recordsetオブジェクトを閉じます。
objRs.Close
'オブジェクト変数を破棄します。
Set objRs = Nothing
上記のコードでは、12行目で、データベースに接続しつつ、同時にSQLをデータベースに渡して、その処理結果を「objRs」が受け取ります。
また、上記の処理ではl前項で説明したConnectionオブジェクトを使用していません。
RecordsetのOpenメソッドの引数には、接続先データベースへの接続文字列を渡せばConnectionオブジェクトを作らなくても接続できます。
また、Coonectionオブジェクトを作ってOpenにしたうえで、そのオブジェクト変数を引数に渡しても接続できます。
その場合は以下の処理になります。
Dim objCon As ADODB.Connection
Dim objRs As ADODB.Recordset
Dim ConString As String
Dim strSQL As String
Set objCon = New ADODB.Connection
ConString = "Driver={SQL Server};Server=IPアドレスやホスト名;Uid=ユーザーID;Pwd=パスワード;Database=データベース名"
objCon.Open ConString
Set objRs = New ADODB.Recordset
strSQL = "SELECT * FROM Customer"
objRs.Open strSQL, objCon, adOpenKeyset, adLockOptimistic
Debug.Print objRs(0).Value
objRs.Close
Set objRs = Nothing
上記のコードでは、8行目でConnectionオブジェクトでデータベースとの接続を確保して、RecordsetオブジェクトのOpenメソッドの引数としてそのConnectionオブジェクトを渡しています。
上記のコードでも結構です。
また、RecordsetオブジェクトのOpenメソッドの引数も理解する必要があるため、以下で説明します。
Recordsetオブジェクト.Open [Source],[ActiveConnection],[CursorType],[LockType],[Options]
パラメータ | 説明 |
---|---|
Source | SQL文字列やテーブル名などを指定します。 |
ActiveConnection | データベースの接続文字列を指定します。 または、接続済みのCoonectionオブジェクトを渡すことも可能。 |
CursorType | レコードセットのカーソルに関するタイプを指定します。 既定値は「adOpenForwardOnly」。 |
LockType | レコードセットに対するロック制御に関するタイプを指定します。 既定値は「adLockReadOnly」。 |
Options | Sourceで指定した値の種類を設定します。 既定値は「adCmdUnknown」。 |
■CursorType
通常は既定値である「adOpenForwardOnly」で良い。
その場合、レコードセットのカーソルは先頭から後ろに移動することしかできず、RecordsetオブジェクトのMovePreviousメソッドで、レコードセットのカーソルを一つ前に戻そうとするとエラーになります。
その代わり、処理は高速です。
また、RecordsetオブジェクトのMoveFirstメソッドでレコードセットの先頭にカーソルを戻すことは可能です。
もしレコードセットのカーソルを自由に移動できるようにする場合はCursorTypeを「adOpenKeyset」など別の値で指定します。
■LockType
通常は既定値である「adLockReadOnly」で良い。
その場合、レコードセットの値を書き換えることはできず、書き換えようとするとエラーになります。
レコードセットの値を書き換える必要がある場合は別の値を指定します。
尚、今回の記事で紹介するコードでは、レコードセットを書き換えて実テーブルの値に更新を掛ける実装は想定していないため、「adLockReadOnly」で問題ありません。
ConnectionオブジェクトのExecuteメソッド実装例
当項では、ConnectionオブジェクトのExecuteメソッドを実行して、レコードを取得する一連の処理を解説します。
尚、ConnectionオブジェクトのExecuteメソッドに対する、Microsoftのリファレンスページのリンクは以下です。
詳しくは以下のリンクをご確認ください。
実際にConnectionオブジェクトのExecuteメソッドを使用してレコードを取得する場合の実装例を紹介します。
'ADODBのConnectionオブジェクトの変数を宣言します。
Dim objCon As ADODB.Connection
'ADODBのRecordsetオブジェクトの変数を宣言します。
Dim objRs As ADODB.Recordset
Dim ConString As String
Dim strSQL As String
'Connectionオブジェクトの新規インスタンスを作成します。
Set objCon = New ADODB.Connection
'接続文字列を変数に格納しています。
ConString = "Driver={SQL Server};Server=IPアドレスやホスト名;Uid=ユーザーID;Pwd=パスワード;Database=データベース名"
'ConnectionオブジェクトのOpenメソッドに接続文字列を渡して接続します。
objCon.Open ConString
'実行するSQL文を変数に格納します。
strSQL = "SELECT * FROM Customer"
'ConnectionオブジェクトのExecuteメソッドの引数にSQLを渡して実行し、その戻り値をRecordsetオブジェクトに代入します。
Set objRs = objCon.Execute(strSQL)
'レコードセットの0番目の列の値をDebug.Printで出力します。
Debug.Print objRs(0).Value
'各オブジェクトを閉じてから破棄します。
objRs.Close
objCon.Close
Set objRs = Nothing
Set objCon = Nothing
尚、当コードの前半は前項のデータベースとの接続処理で解説したものを大きく変わらないため省略し、11行目以降を説明します。
16行目:ConnectionオブジェクトのExecuteメソッドの引数にSQLの文字列を渡してSQLを実行しています。戻り値はRecordsetオブジェクト型で返るため、それをRecordsetオブジェクト型の変数に代入しています。
20行目以降:Recordsetオブジェクト変数及びConnectionオブジェクト変数をそれぞれ閉じて、破棄しています。
ConnectionオブジェクトのExecuteメソッドの引数も理解しておく必要があるため、以下で説明します。
Connectionオブジェクト.Execute [CommandText],[RecordsAffected],[Options]
パラメータ | 説明 |
---|---|
CommandText | SQL文字列やテーブル名などを指定します。 |
RecordsAffected | ここにLong型の変数を指定することで、SQLのUPDATEやDELETE文などの実行した場合の処理実施件数がその変数に代入されます。 レコードセットを返さない処理が対象で、SELECT文などレコードセットを返す処理の場合は、-1が代入されます。 省略可能。 |
Options | CommandTextで指定した値の種類を設定します。 省略可能。 |
■CommandText
通常はこの引数だけ指定していただければ結構です。
■CommandText
上記の説明にもあるように、この引数としてLong型の変数をセットしておくことで、更新系のコマンド(SQL)を実行した場合に、処理件数を変数に入れてくれます。
処理件数を取得する必要が無ければ、この引数は指定しなくても結構です。
■Options
プロバイダー側にCommandText引数を評価させる必要があれば指定しますが、通常は指定しなくても結構です。
引数を指定する場合は、CommandTypeEnum 値、又はExecuteOptionEnum 値のビットマスクを指定します。
SQLのSELECT文などの値を返す処理を実行した場合は、戻り値はRecordsetオブジェクトで返されます。
また、その場合に作成されるRecordsetオブジェクトは、CursorTypeが「adOpenForwardOnly」、LockTypeが「adLockReadOnly」になります。
SQLのUPDATE文など値を返さない処理を実行した場合はレコードセットは戻しません。

CommandオブジェクトのExecuteメソッド実装例
当項では、CommandオブジェクトのExecuteメソッドを実行して、レコードを取得する一連の処理を解説します。
尚、CommandオブジェクトのExecuteメソッドに対する、Microsoftのリファレンスページのリンクは以下です。
詳しくは以下のリンクをご確認ください。
実際にCommandオブジェクトのExecuteメソッドを使用してレコードを取得する場合の実装例を紹介します。
'ADODBのConnectionオブジェクトの変数を宣言します。
Dim objCon As ADODB.Connection
'ADODBのRecordsetオブジェクトの変数を宣言します。
Dim objRs As ADODB.Recordset
'ADODBのCommandオブジェクトの変数を宣言します。
Dim objCmd As ADODB.Command
Dim ConString As String
Dim strSQL As String
'Connectionオブジェクトの新規インスタンスを作成します。
Set objCon = New ADODB.Connection
'接続文字列を変数に格納しています。
ConString = "Driver={SQL Server};Server=IPアドレスやホスト名;Uid=ユーザーID;Pwd=パスワード;Database=データベース名"
'ConnectionオブジェクトのOpenメソッドに接続文字列を渡して接続します。
objCon.Open ConString
'Commandオブジェクトの新規インスタンスを作成します。
Set objCmd = New ADODB.Command
strSQL = "SELECT * FROM Customer"
'CommandオブジェクトのCommandTextプロパティにSQLをセットします。
objCmd.CommandText = strSQL
'CommandオブジェクトのActiveConnectionプロパティにOpen済みのConnectionオブジェクトをセットします。
objCmd.ActiveConnection = objCon
'CommandオブジェクトのExecuteメソッドを実行して、その戻り値をRecordsetオブジェクトに代入します。
Set objRs = objCmd.Execute
'レコードセットの0番目の列の値をDebug.Printで出力します。
Debug.Print objRs(0).Value
'各オブジェクトを閉じてから破棄します。
objRs.Close
objCon.Close
Set objRs = Nothing
Set objCmd = Nothing
Set objCon = Nothing
上記処理についても解説していきます。
尚、これまでの説明で重複する部分については省略します。
16行目:Commandオブジェクト変数に対して新規インスタンスを作成します。尚、6行目のCommandオブジェクト宣言時にNewを付与することで、この16行目の記述は省略可能です。
19行目と21行目:Commandオブジェクトの必要なプロパティをセットしています。Commandオブジェクトでは他にもプロパティが有りますが、最低限このプロパティをセットすればSQLの実行は可能です。
過去にADOからストアドプロシージャを実行する場合の処理を記事で解説しています。
これまでの説明を踏まえた一連の処理実装例
当記事では、ADOを使用したデータベースとの接続からレコードセットの取得に関する一連の実装方法を解説してきました。
これらを踏まえて、一連の処理の実装に関するサンプルコードを紹介していきます。
尚、レコードセットの取得処理については、前項でも紹介した「Connectionオブジェクト」の「Executeメソッド」を利用した実装にします。
Dim objCon As ADODB.Connection
Dim objRs As ADODB.Recordset
Dim ConString As String
Dim strSQL As String
'データベースと接続します。
Set objCon = New ADODB.Connection
ConString = "Driver={SQL Server};Server=IPアドレスやホスト名;Uid=ユーザーID;Pwd=パスワード;Database=データベース名"
objCon.Open ConString
'SQLを実行してレコードセットを取得します。
strSQL = "SELECT * FROM Customer"
Set objRs = objCon.Execute(strSQL)
'レコードセットにレコードが存在しなければ処理を終了します。
If objRs.EOF Then
Msgbox "データが存在しないため処理を終了します。"
Else
'レコードセットの件数分ループしてDebug.Printで出力します。
Do Until objRs.EOF
Debug.Print "1列名の値:" & objRs(0).Value & " 2列目の値:" & objRs(1).Value
'カレントレコードを次に進めます。
objRs.MoveNext
Loop
End If
'各オブジェクトを閉じてから破棄します。
objRs.Close
objCon.Close
Set objRs = Nothing
Set objCon = Nothing
当サンプルコードを補足します。
当コードのベースは、「Connectionオブジェクト」の「Executeメソッド」を説明した際に使用したサンプルコードです。
それに対して、実行したSQLでレコードセットが取れたか否か(条件に適合するレコードがデータベースに存在したか否か)を判定する処理を追加しています。
カレントレコードがEOFではない=レコードが取得できた場合は、カレントレコードがEOFになるまでループ処理を繰り返して、各レコードの値をDebug.Printで出力しています。
尚、その処理ではレコードセットオブジェクトに対して以下のように値を取得しています。
objRs(0).Value
レコードセットオブジェクトに対して、配列の添え字のように、番号で列を指定することが可能です。
列は番号で指定するだけではなく、名前でも指定が可能です。
objRs("列名").Value
例えば、「Address」という名称の列名のレコードの値を取得する場合は、以下です。
objRs("Address").Value
また、「Valueプロパティ」は省略して、以下のように書いても同じように値を取り出せます。
objRs("Address")
ただ、値を取り出す場合に、コードは省略せずに明示的にプロパティまで書いた方が見落としや間違いが減ると思うので、なるべく省略せずに書くことをおススメします。
また、ループ処理内で「objRs.MoveNext」でカーソルを移動させています。
これをしないと、無限ループになってしまうため、注意してください。
また、生成したADODBオブジェクトは必ずNothingで破棄してください。
基本的には、ExcelやAccessなどのVBAを実行しているアプリケーションが終了すれば、それらのオブジェクトは消滅しますが、処理によってはデータベース側にセッションやプロセスが残り続ける原因にもなり得るため、作法として必ず破棄するコードも書いてください。
【参考】ADO操作のクラス化
ADOを使用したデータベースへの接続、SQLを実行やトランザクション処理の一連の操作をクラス化したサンプルコードを過去に当ブログで紹介しております。
クラス化することで、コードの記述内容を共通化することができて非常に便利です。
ADOを使用したデータベースの操作に慣れてきたら、是非こちらもチャレンジしてみてください。
最後に
今回の記事では、ExcelやAccessのVBAでADOを使用してデータベースに接続したり、レコードセットを取得する基本的な実装方法を解説させていただきました。
本来は、レコードセットの取得だけではなく、データの更新処理なども紹介したかったのですが、記事が長くなってしまったため、また機会があれば別の記事で紹介させていただきます。
今回の記事が皆さまお仕事の参考になれば幸いです。
今回も長々と読んでいただきましてありがとうございました。
それでは皆さまご機嫌よう!