【Excel・Access VBA】ADO入門|DBへの接続とレコードセットの取得をわかりやすく解説

VBA
スポンサーリンク

今回の記事では、Excel VBAやAccess VBAの「ADO」を使用し、データベースへ接続してレコードセットを取得する一連の処理を初心者向けに解説していきます。

VBAで業務用のツールを開発したり、データ集計を自動化する場合に、ADOは必ず習得しておきたい技術です。

是非参考にしてください。
 
 

ADOとは

「ADO」の正式な名称は「ActiveX Data Objects」です。
このADOは様々なデータベースに接続してレコードを扱うための汎用的なインターフェイスです。

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の機能を呼び出す際に、参照設定からライブラリを指定する場合は以下の画像のようになります。

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上部の「ツール」→「参照設定」を選択し、

VBEでの参照設定画面表示手順

前述した「参照設定」画面を表示して、以下のライブラリにチェックを入れてください。

Microsoft ActiveX Data Objects 2.8 Library

VBAの参照設定画面

尚、他にもバージョン違いで複数のライブラリがありますが、2.7以前は古いADOの互換維持で用意されており、6.1など大きいバージョン番号のライブラリもありますが、中身は2.8とほぼ同じものの様です。

通常は「Microsoft ActiveX Data Objects 2.8 Library」にチェックをつけてください。

 
 

ADOでデータを取得する一連の流れ

VBAからADOを利用して、外部のデータベースに対してデータを取得する一連の処理の流れを説明します。

  1. ADOオブジェクトを生成
  2. 接続先データベースへの接続文字列を使用して外部DBに接続
  3. SQL分を生成し、文字列型の変数に代入
  4. ADOオブジェクトを使用してSQLを実行し、戻り値をレコードセットで受け取る
  5. データベースへの接続を閉じる
  6. 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
1行目ではADODBオブジェクトの変数を宣言しています。
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」の二種類があり、この記事でその違いを説明すると長くなるため割愛しますが、どちらのインターフェイスが実行環境の端末に入っているかによって、当項で説明する「接続文字列」の種類が変わります。

Officeがインストールされている段階で、SQL ServerやAccessなどの「ODBC」ドライバーも併せてインストールされると思いますが、Oracleやその他のデータベース製品と接続する場合は、その接続先ごとのインターフェイス(主にODBCドライバー)をインターネットからダウンロードしてインストールしてあげる必要があります。

データベースと接続する際に、接続先データベースのホスト名(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 の最後のレコードに移動します。
上記の「説明」は、Microsoftの解説文面のまま記載しています。

「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で接続したデータベースからレコードを取得してレコードセットを作成する方法は主に以下の方法があります。

  1. RecordsetオブジェクトのOpenメソッドで直接レコードセットに格納する。
  2. ConnectionオブジェクトのExecuteメソッドを実行してその戻り値をレコードセットオブジェクトに格納する。
  3. 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
	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文など値を返さない処理を実行した場合はレコードセットは戻しません。

中の人
中の人
このConnectionオブジェクトでは、「BeginTrans」などのトランザクション管理で必要なメソッドも持っており、この「ConnectionオブジェクトのExecuteメソッドでデータを取得する方法」が一番理解しやすいのではないかと思います。

 

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で接続したデータベースで登録されている「ストアドプロシージャ」にパラメーターを渡して実行する場合は、Commandオブジェクトを介さないと実行できません。
過去に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を使用してデータベースに接続したり、レコードセットを取得する基本的な実装方法を解説させていただきました。

本来は、レコードセットの取得だけではなく、データの更新処理なども紹介したかったのですが、記事が長くなってしまったため、また機会があれば別の記事で紹介させていただきます。

今回の記事が皆さまお仕事の参考になれば幸いです。

今回も長々と読んでいただきましてありがとうございました。
それでは皆さまご機嫌よう!

タイトルとURLをコピーしました