2023/10/02
2023/11/28 一部修正(Recordset.Openの第1パラメータへのSQL文・テーブル名指定の違いについて)
2023/12/13一部補足(データの一括処理で、GetRowsメソッドの第2パラメータは使用不可?)

ADOでAccess・Excel・CSVへ接続・操作
- JET・ACEプロバイダ編 -




1.データベースへの接続方法

DAOでAccess・Excel・CSV等へ接続・操作」で説明しましたが、ExcelのVBAから「Microsoft Access」「Excelのワークシート」「CSV等のテキストファイル」のデータベースに接続・操作する方式には、主に「ODBC」「DAO」「ADO」の3種があります。
今回はADO方式の内、JET・ACEプロバイダーを使ったルート(図01では、黒線のルート)について説明します。
ADO方式のルート
図01

これ以外の接続・操作については、以下を参照下さい。
 ・DAOでAccess・Excel・CSVへ接続・操作
 ・ADOでAccess・Excel・CSVへ接続・操作(JET・ACEプロバイダ編)  ←今回
 ・ADOでAccess・Excel・CSVへ接続・操作(MSDASQLプロバイダ編)
 ・ODBCでAccess・Excel・CSVへ接続・操作

2.ADOのオブジェクトについて

ADOでのデータベースへの接続・操作には、ADOの「Connection」「Command」「Recordset」の各オブジェクトを図02のように組み合わせて行います。表内の指定内容の「テーブル」と「SQL文」は、Recordset.OpenメソッドやCommand.CommandTextプロパティ、Connection.Excecuteメソッドのパラメータとして指定する内容を指しています。
DAO方式のルート
図02

まず「各オブジェクト、及びそのメソッド・プロパティ」について説明をした後、図02で示した各ルートの実際のコードを紹介します。とりあえず接続するコードを知りたい場合は、先に「データベースに接続・操作するためのコード例」を確認下さい。

2ー1.ADOオブジェクトの種類

ADO直下には図02で示した以外にも、多くのオブジェクトが存在します。図03はそのオブジェクトが、バージョンにより使えるか否かと、実行時バインディング時にCreateObjectで生成可能か否かをまとめたものです。
オブジェクト内容事前バインディング実行時バインディング
Ver 2.8Ver 6.1CreateObject可
Commandデータソースに対して実行する特定コマンドの定義
Connectionデータソースへの接続
Error発生するアクセスエラーの詳細情報
Errors×
Fieldデータ列××
Fields××
ParameterCommandオブジェクトに関連付けられた引数
Parameters×
PropertyADOの動的特性×
Properties×
RecordRecordsetの行、又はファイルシステム内のディレクトリやファイル
Recordsetコマンド実行により返された結果
Streamデータの流れ
図03

これらのオブジェクトの内、データベースとの接続・操作にかかわる「Connection」「Recordset」「Command」オブジェクトについて、今回説明していきます。
なお後述する参照設定(図04)で「バージョン6.1」を選択した場合、図03の「Ver6.1」列で分かるように、Field(Fields)オブジェクトは存在しません。ですので「RecordsetのFieldsをADOのFieldsオブジェクトで受け取る(今回は、その手法については説明を省略しています)」場合は、バージョンを2.8とする必要があります。
但し実行時バインディング(CreateObject使用)の場合は、Fieldsオブジェクトは単なるObject(総称オブジェクト型)として宣言しますので、RecordsetのFieldsを「一般のObject」として受け取る事が可能です。

2ー2.ADOオブジェクト生成

ADOでデータベースとやり取りするには、まずADOオブジェクトを生成する必要があります。その生成方法には以下の2種類があります。
 ・「事前バインディング」・・・コードを実行する前に生成
 ・「実行時バインディング」・・コードを実行した時に初めて生成
事前バインディングの特徴は、コード作成時にインテリセンス(コード補完機能=使用可能なプロパティ等が表示され、選択することが可)が使えることと合わせ、効率が良い(≒実行速度が速い)ことです。
一方実行時バインディングは、PC環境の異なる複数ユーザーにマクロを配布する時でも安全です。

2ー2ー1.事前バインディング

事前バインディングでは、VBE(コードを書くウィンドウ)上部の「ツール」→「参照設定」から、図04のように「Microsoft ActiveX Data Objects X.X Library」にチェックをし有効にします。
ADOの参照設定
図04

X.Xの部分はバージョンを表していますが、最新Excelでは「2.8」①までと、少し飛んで「6.1」②が選択できるかと思います。
通常は「最新のもの」を選択するのが良いとされています。しかし複数のPCを対象に動かすようなシステムの場合に「最新バージョン」を選択して作ってしまうと、もしその「最新バージョン」がインストールされていないPCが存在する場合は、うまく動かない可能性が出てきます。ライブラリを選択する際には「どのPCにも入っているバージョン」を選ぶのが良いと思います。
なお、バージョンの2.8と6.1では、図03のようにADO直下のオブジェクトが異なります。最新の6.1にはField(Fields)オブジェクトがありません。但し、図53の210行目のような「カーソル行の対象列」を示すFieldsプロパティは大丈夫です。このFieldsはRecordsetオブジェクトのFieldsだからです。
プログラム的には、図04のようにADOのライブラリーを参照設定した上で、図05のように「オブジェクト変数をADOオブジェクトとして宣言」→「New句を使って生成」した後、オブジェクト変数を処理に使用します。
  1. '========== ⇩(1) 事前バインディングでの宣言と生成 ============
  2.  Dim cn As ADODB.Connection   '←Connectionオブジェクトの宣言
  3.  Dim rs As ADODB.Recordset    '←Recordsetオブジェクトの宣言
  4.  Dim cmd As ADODB.Command   '←Commandオブジェクトの宣言
  5.  Set cn = New ADODB.Connection   '←Connectionオブジェクトの生成
  6.  Set rs = New ADODB.Recordset    '←Recordsetオブジェクトの生成
  7.  Set cmd = New ADODB.Command   '←Commandオブジェクトの生成
  8.  
  9.  ( 生成したcn,rs,cmdオブジェクト変数を使い、接続やデータ取得・変更の処理・・・等)
図05

01~03行目では、各オブジェクト型毎に変数宣言をします。
05~07行目では、New句を使ってオブジェクトを生成します。
オブジェクト生成後は、そのオブジェクト変数(図05では、cn,rs,cmd )を使って処理を行います。

2ー2ー2.実行時バインディング

実行時バインディングの場合は、使用するオブジェクト毎にCreateObjectを使って生成します。
なおCreateObjectで生成できるADOオブジェクトは、図03で示したように一部分のみになります。
  1. '========== ⇩(2) 実行時バインディングでの宣言と生成 ============
  2.  Dim cn As Object   '←Connectionオブジェクトの宣言
  3.  Dim rs As Object    '←Recordsetオブジェクトの宣言
  4.  Dim cmd As Object   '←Commandオブジェクトの宣言
  5.  Set cn = CreateObject("ADODB.Connection")   '←Connectionオブジェクトの生成
  6.  Set rs = CreateObject("ADODB.Recordset")    '←Recordsetオブジェクトの生成
  7.  Set cmd = CreateObject("ADODB.Command")   '←Commandオブジェクトの生成
  8.  
  9.  ( 生成したcn,rs,cmdオブジェクト変数を使い、接続やデータ取得・変更の処理・・・等)
図06

21~23行目では、単なるObject型として変数宣言をします。
25~27行目では、CreateObject関数を使って各オブジェクトを生成します。オブジェクト生成後は、そのオブジェクト変数(図06では、cn,rs,cmd )を使って処理を行います。

3.Connectionオブジェクト

Connectionオブジェクトには複数のプロパティ・メソッドが存在します。
データベースに接続するためには、接続条件を指定したOpenメソッドの実行が必須ですが、Openの前にConnectionStringプロパティ、Providerプロパティなどに接続条件を事前設定させる手法も使えます。
またConnectionオブジェクトのExecuteメソッドを使えば、コマンドが実行できます。

3ー1.Openメソッド他(データベース接続関係)

データベースに接続するには、下記のようにConnectionオブジェクトのOpenメソッドを使います。
 Connection.Open (ConnectionString, UserID, Password, Option)
ConnectionのOpenメソッドには、4つのパラメータ設定が可能です。全て省略可です(図07)。
Connection.Openメソッドのパラメータ
パラメータ内容
ConnectionString省略可接続情報(図08
UserID省略可接続時のユーザー名
Password省略可接続時のパスワード
Options省略可接続の同期/非同期(図22
図07

なお、第4パラメータのOptionsは、ExecuteメソッドのOptionsとは全く別なので混同に注意です。

3ー1ー1.第1パラメータ(ConnectionString:接続情報)

図07の第1パラメータ(ConnectionString)には、図08のような情報を「文字列」として組み込みます。各項目の区切りは「;(セミコロン)」です(最後の項目には、セミコロンは必須ではありません)。
図08では「JET・ACE列」と「ODBC列」の2通りを併記していますが、「JET・ACE 列」の情報を使うことで、今回、図01のように「JET・ACEプロバイダ」→「JET・ACEエンジン」→「各データベース」という流れで接続・操作ができます。
なお「JET・ACE列とODBC列の混在」はできません。
ADOのConnectionStringの接続情報
内容JET・ACEODBC
プロバイダーProvider=Microsoft.ACE.OLEDB.12.0Provider=MSDASQL
ドライバーDriver={ODBCのドライバー名}
DB名Data Source=DB名DBQ=DB名
読取/書込ReadOnly=True/False
DSN名DSN=DSN名
ユーザー名User ID=ユーザー名UID=ユーザー名
パスワードPassword=パスワードPWD=パスワード
URL名URL=URL名
拡張プロパティExtended Properties=情報
図08

第1パラメータとして必須なのは「プロバイダー」と「データベース(DB)名」です。またExcelのワークシートやCSVファイルをデータベースとして扱う場合は、加えて「拡張プロパティ(Extended Properties)」の指定が必要です。
3ー1ー1ー1.プロバイダー名
図08では、プロバイダーの指定(Jet・ACEの列)を「"Provider = Microsoft.ACE.OLEDB.12.0"」としましたが、右辺の「ACE」はACEプロバイダーを示し、「12.0」はバージョンを示します。プロバイダに対する「対応するデータベースファイル(拡張子)」は、図09のようになっているようです。
プロバイダAccessExcelText
.mdb
(Jet作成)
.mdb
(ACE作成)
.accdb
(ACE作成)
.xls
~2003
.xlsx .xlsm .xlsb
2007~
.csv.txt
Jet系Microsoft.Jet.OLEDB.4.0Access2000~2003×××
ACE系Microsoft.ACE.OLEDB.12.0Access2007~2010
Microsoft.ACE.OLEDB.15.0Access2013(〇)(〇)(〇)(〇)(〇)(〇)
Microsoft.ACE.OLEDB.16.0Access2016~
図09

図09のプロバイダ名の右列は、各プロバイダがどの時代のものかを表しています。例えば「Microsoft.ACE.OLEDB.12.0」は「Access2007~2010」と同時期のもので、バージョン番号も同じ(どちらもメジャーバージョンは 12)です。と言ってそれ以降のOfficeで使えない訳では無く下位互換なので、例えばOffice2016(メジャーバージョン = 16)では「12.0 も使える」事になります。
但しAccess2013の「15.0」は特殊なようで、Office2016以上には標準では入っていませんし、逆にOffice2013で下位の12.0を使うとエラーが発生するようです。
今回のコード例では「Microsoft.ACE.OLEDB.12.0」を使って説明をしていますが、これは現状最も広く使えそうなプロバイダーだと思ったからです。本来ならば(32ビット、64ビットの違いも含めて)Officeの各バージョン毎に「どのプロバイダが使えるか」を表形式にしたかったのですが、手持ちのExcel種類が少なすぎて完成させられませんでした。複数種のO/S・Officeで使う場合には、事前に確認をした方が良いかもしれません。
なおOfficeが64ビット版の場合、Jet系プロバイダー(32ビット版のみしか無い)は動きません。
またOffice2010(メジャーバージョン=14)と同時期の「Microsoft.ACE.OLEDB.14.0」というのも存在するとの情報もあるのですが、私の引退したPC(Win Xp + 32ビット版Excel2010)で調べたところ、残念ながら14.0ではエラーとなりました。よって図09では「Office2010は12.0」としました。
寄り道(プロバイダの存在確認)
ADOを実行するPC内で、どのプロバイダが使用可能かは、WindowsのPowerShellで下記コマンドを実行することで確認できます。
(New-Object data.oledb.oledbenumerator).getElements() | select SOURCES_NAME, SOURCES_DESCRIPTION
結果は、例えば図10のようになり、今回の説明でも出てきたプロバイダが表示(赤矢印)されています。
使用可能なプロバイダをPowerShellで確認
図10

なおPowerShellには何種類かがありますが、ビット版で考えると「PowerShell」と「PowerShell(x86)」の2種類です。最近のWindows(64ビット)で考えると、単なる「PowerShell」が64ビット版で、「PowerShell(x86)」が32ビット版です。
使用可能なプロバイダを調べるには、以下のようにします。
 ・Windowsが64ビット版 + Officeが64ビット版 → 「PowerShell」で上記コマンドを実行
 ・Windowsが64ビット版 + Officeが32ビット版 → 「PowerShell(x86)」で上記コマンドを実行
 ・Windowsが32ビット版 + Officeが32ビット版 → 「PowerShell」で上記コマンドを実行
Windowsが32ビット版の場合、そのPowerShellは32ビット版となります。また、Officeは32ビット版に限りられます。
つまり「Officeのビット版と同じビット版のPowerShellを使用」すると、使用可能なプロバイダが分かるようです。
図10は「Windowsが64ビット版 + Officeが64ビット版」の時のもので、PowerShellも64ビット版ですが、逆に、32ビット版のPowerShell(x86)でコマンドを実行してみたのが以下になります。
ビットが合っていないPowerShellでプロバイダを確認
図11

32ビット版には「Jet.4.0」が入っていますが、Officeが64ビット版なので使えないですし、32ビット版Officeがインストールされていないため32ビット系の「ACE系」プロバイダがない という事のようです。
次の回で説明する「MSDASQL」は両方に存在します。どのビット版Officeがインストールされても大丈夫な状態です。

3ー1ー1ー2.データベース名
データベース名は、対象とするデータベースの種類により図12のように変わります。
データベース名
Accessファイル名(*.accdb, *.mdb)
Excelファイル名(*.xlsx 等)
CSV等CSVファイルがあるフォルダー名
図12

AccessやExcelのように、ファイル内に複数のテーブルを持てるタイプでは「ファイル名=データベース名」となりますが、CSVファイルのようにファイル=テーブルのようなものは「フォルダー名=データベース名」となります。
寄り道(テーブル名)
各データベースに於ける「テーブル」について図13に示します。
テーブル操作するテーブルSQLのテーブルとして
Accessテーブル名TestTable"TestTable""Select * from TestTable"
Excelワークシート名Sheet1"Sheet1$""Select * from [Sheet1$]"
CSV等CSVファイル名its-041.csv"its-041.csv""Select * from [its-041.csv]"
図13

Accessに於けるテーブルは、通常のデータベースとしてのテーブルと同じ扱いになります。
Excelでは、ワークシートがテーブル扱いとなります。例えばSheet1にデータがあるとすれば、Recordset.Openの第1パラメータにテーブル名を指定するような場合は、「"Sheet1$"」のように「シート名+$マーク」とします。またSQL文の中で使用する場合は、更に角カッコで囲み「Select * from [Sheet1$] 」のようにします。
CSVでは、CSVファイルそのものがテーブル扱いとなります。ファイル名がits-041.csvとすれば、テーブル名指定の場合はファイル名をそのまま使用して「"its-041.csv"」とし、SQL文の中で使う場合は角カッコで囲み「Select * from [its-041.csv] 」とします。

3ー1ー1ー3.ユーザー名、パスワード
データベースに「ユーザー名」や「パスワード」が設定されている場合は、ConnectionStringに指定します。
なお、Excelの「ブックの保護」で設定したパスワードは対象外です(「Password=ブック保護のパスワード」を指定しても、データは取得できません)。
このユーザー名・パスワードをExcelのVBA側で作成したAccessファイルに設定しようと試みました。やり方としては、ADOXのUsersコレクションから、NameプロパティとChangePasswordメソッドを使うようですが、残念ながらExcel VBAからは操作できませんでした。
実際のAccessで作成されたデータベース(*.accdb, *.mdb)の場合は当然設定が可能だと思います。
またこの内容は、Openメソッドの第2・第3パラメータと同じと思われます。
3ー1ー1ー4.拡張プロパティ(Extended properties)
ExcelのシートやCSVをデータベースにする際には、「Extended properties=」に続けてデータベースの種類(=ISAM形式(Indexed Sequential Access Method))を指定します。
データベース指定文字列
Excel2007~"Extended properties=Excel 12.0"
Excel97~2003"Extended properties=Excel 8.0"
CSVやテキストファイル"Extended properties=Text"
図14

そのPCで使用可能なISAM形式はレジストリで確認できるようで、例えば私のPCでは図15のようになります。
使用可能なISAM形式をレジストリで確認
図15

なおルール通りではありませんが、例えば「its-042.xlsm」に接続したい場合、ISAMを「Excel 8.0(Excel97~2003対応)」と指定しても問題無く接続出来ますし、「Excel 12.0 Xml(本来は拡張子xlsxに対応)」を指定してもOKです。下位互換と言えば良いのか、Excel間での壁は低いようです。
しかしデータベースの種類だけでは無く、使用するデータベースに関する「もっと細かい設定」が必要になる場合があります。例えば「データベースの先頭行がタイトルか否か」等です。その場合の構文としては「HDR=Yes」等と指定するのですが、これを図14の情報と併せて「"Extended properties=Excel 12.0;HDR=Yes;"」という文字列を組み立て、それをConnectionStringにすると、残念ながらエラーが出てしまいます。
ConnectionStringに例えば「“Provider = Microsoft.ACE.OLEDB.12.0; Data Source=C:¥Data¥its-042.xlsm; Extended Properties= Excel 12.0; HDR=No; " 」という文字列を指定すると、VBAはその文字列を「;(セミコロン)」で区切りながら解釈し、値を図16のように各プロパティに格納していきます。しかし、Properties("Extended Properties")プロパティには「理解できない文字列」として値が格納されてしまうためにエラーとなるのです。
ConnectionStringに設定した後の動き(エラー発生)
図16

一番最後の「HDR=No」がなぜ先にProperties("Extended Properties")プロパティに入ってしまうのかは、良く分かりませんでした。「Excel 12.0」と「HDR=No」の順番などを色々変えて試してみたのですが、どうやっても「HDR=No; Excel 12.0」という順番で入ってしまいます。
これを正しく設定するには、複数の「Extended Properties 値を1つの文字列」にする必要があります。具体的には図17のように「" Provider = Microsoft.ACE.OLEDB.12.0; Data Source=C:¥Data¥its-042.xlsm; Extended Properties= ""Excel 12.0; HDR=No""; "」と両端を二重のダブルクォーテーションで囲みます。
ConnectionStringに設定した後の動き(正常動作)
図17

こうすることで、ダブルクォーテーションで囲まれた複数の「Extended Properties 値」を、まとめてProperties("Extended Properties")プロパティに格納することが出来ます。
なお最後のセミコロンは必須ではありませんが、「Extended Properties= ""Excel 12.0; HDR=No;"""」の様に、ダブルクォーテーションの内側の最後にセミコロンを付けると、「初期化文字列の形式が違う」とエラーが発生しますので注意が必要です。
なお、Openメソッドの第1パラメータ(ConnectionString)に設定する事は、ConnectionオブジェクトのConnectionStringプロパティに設定することと同じですが、それ以外に「Connectionの各プロパティに直接指定」する方法もあります。
例えば、以下のように分割して指定することでもOKです。
 「Connection.Provider = " Microsoft.ACE.OLEDB.12.0 "」
 「Connection.Properties("Data Source") = "C:¥Data¥its-042.xlsm"」
 「Connection.Properties("Extended Properties") = "Excel 12.0; HDR=No"」
このように、直接「Connection.Properties("Extended Properties")」に拡張プロパティ値を指定すると、上記で示した「両端を二重のダブルクォーテーションで囲む」ことは不要になるので便利です。
ISAM形式を含めた拡張プロパティの設定項目を整理すると以下のようになります。
項目内容
ISAM形式
(先頭部)
"Excel 12.0":Excel2007~
"Excel 8.0":Excel97~2003
"Text":CSVやテキストファイル
HDRYES(既定)=先頭行がタイトル
NO=先頭行からデータ
IMEX0=書込(データ型混在時はエラー)
1=読取専用(データ型混在時、文字列型で読込み)
2=読取/書込(データ型混在時はエラー)
FMTテキストファイルの区切り種類(カンマ区切り固定)
Delimited、又はCSVDelimited
MAXSCANROWSデータ型判定の行数:8行で固定
図18

「HDR」は、データの先頭行が「タイトル行(Yes)」か「データ(No)」かの指定です。
なお、この先頭行をどう判断するかは、HDR項目だけでは決まりません。実は、次のIMEX項目の値にも影響を受けてしまいます。HDRとIMEXの組み合わせでの「先頭行の判断」は次の図19のようになります。
先頭行の判断
HDR
省略YesNo
I
M
E
X
省略タイトルタイトルデータ
0タイトルタイトルタイトル
1タイトルタイトルデータ
2タイトルタイトルデータ
図19

先頭行をタイトル行としたい場合は「IMEX = Yes、またはIMEXを省略」すればOKです。しかし先頭行をデータ行としたい場合、「IMEX=0」を付けてしまうと、思った通りにはならないので注意が必要です。
「IMEX」は開くモードの指定です。他サイトでは、以下のように説明しています。
 IMEX=0:書き込み(データ型が混在している時にはエラー発生)
 IMEX=1:読み取り専用(データ型混在時は文字列型で読み込む)
 IMEX=2:読み取り/書き込み(データ型が混在している時にはエラー発生)
しかし、実際の動作は少し異なり「よりみち」のようになるようです。
「FMT」は、CSV等のテキストファイルのデータ区切りに何の記号を使うかの指定です。設定値としては、カンマ区切り(CSVDelimited、Delimited)、タブ区切り(TabDelimited)の設定値があるようですが、試してみたところ「カンマ区切り以外のデータには対応できない」という結果となりました。
あるサイトでは「JETでは設定可能、ACEでは不可能」との説明もあるのですが、少なくともExcelのVBAからの指定は無視されるようです。
「MAXSCANROWS」は、データ型を判断するための行数指定です。既定値は「8(データ先頭から8行目の範囲で、異なるデータ型の有無を調べる)」で、1~16の設定が可能 との事ですが、ExcelのVBAからは何を指定しても「8行固定」でした。
なお図20のように、レジストリでMAXSCANROWS値を設定する方法はあるようです。しかし、VBAの範囲からは外れますので今回は「MAXSCANROWSは設定不可」という事にしておきます。
レジストリでのMAXSCANROWSの設定
図20

寄り道(IMEX値の検証)
上記IMEXの動作検証のため、「Excelシートデータベース」「CSVファイル」上でデータ型の混在/非混在状態を作り、条件を振って試してみました。併せてプロバイダも、ACE.12.0とJET.4.0を比較しました(図21)。
なお表の左端の「Excel」「CSV」は対象とするデータベースを、「Table」「SQL」はRecordset.Openに指定する第1パラメータをテーブルにするかSQL文にするかを、「Read」「Write」は、処理が参照(Select)か変更(Insert等)かを表しています。またテーブルを指定する際は、Recordset.Openのパラメータとして第5パラメータのOptionsに512(adCmdTableDirect)を、CursorType=0、LockType=2を指定して実行させました。
IMEX
ACE.12.0JET.4.0
012省略012省略
ExcelTableRead〇/△〇/〇〇/△〇/△ 〇/△〇/〇〇/△〇/△
Write〇/〇×/×××〇/〇 〇/〇×/×〇/〇
SQLRead〇/×〇/〇〇/×〇/× 〇/〇/〇〇/〇/
Write〇/〇×/×××〇/〇 〇/〇×/×〇/〇
CSVTableRead〇/△〇/△〇/△〇/△ 〇/△〇/△〇/△〇/△
Write〇/〇〇/〇〇/〇〇/〇 〇/〇〇/〇〇/〇〇/〇
SQLRead〇/×〇/×〇/×〇/× 〇/〇/〇/〇/
Write〇/〇〇/〇〇/〇〇/〇 〇/〇〇/〇〇/〇〇/〇
データ型:混在無し/混在有り
〇印:正常処理(データ型が異なる場合も、文字列として出力)
×印:実行不可、またはデータ型が異なる行でエラーが出る
△印:異なるデータ型は空白となる
赤字:プロバイダ種により異なる結果

図21

まずIMEXの機能ですが、この結果を見る限りでは、他サイトが説明している状態にはなっていません。辛うじて、IMEX=1は読取専用なので「Excelでは書き込みが不可」なことくらいでしょうか。
またプロバイダ違いで結果が異なる部分(赤字)で特記すべきは「JETでは正常に書き出し処理できていたIMEX=2が、ACEでは処理出来ない」事です。昔作ったプログラムをJetからACEに置き換えた場合、IMEX=2で処理している部分ではエラーとなってしまうので注意が必要です。
またデータ型が混在する場合、IMEX=1では「空白では無く、文字列として出力」してくれますが、この機能は「異なるデータ型が、8行目以内に存在」する場合に限られます。もし9行目以降に異なるデータ型が初めて出現した場合には、空白として出力されます。
そのための機能として「MaxScanRows」があるはずなので、色々と設定してみたのですが、今回条件ではACE・JETともに「データ型混在の判断行数は8行で不変」でした。

3ー1ー2.第2、第3パラメータ(UserID:ユーザー名、Password:パスワード)

Connection.Openの第2、第3パラメータは「UserID」と「Password」です。データベース接続にユーザー名とパスワードが必要な場合は設定をします。なおこの項目は、ConnectionStringのユーザー名・パスワードと同じもののようです。

3ー1ー3.第4パラメータ(Options:同期/非同期)

Connection.Openの第4パラメータ(Options)には、以下の値を指定します。
定数内容
adAsyncConnect16接続を非同期で開く
adConnectUnspecified-1接続を同期で開く(既定)
図22

同期で開く場合は、Openの処理をしている間は他の処理が出来ませんが、非同期の場合はOpen処理をしている間も次の処理に移る事が可能になります。但しStateプロパティ等で「Open処理が完了したか」を確認してからレコードセット取得処理やExecute処理に入る必要があります。
Open処理に多くの時間が必要で、且つ併行して行う作業が存在するようなシステム以外では、既定の「同期で開く」で良いと思われます。
なお同期・非同期の情報保持は、OpenしたConnectionオブジェクトのどのプロパティが担当しているかは分かりませんでした。ですのでOpen前に「同期・非同期をプロパティ設定」する手法は不明です。

3ー1ー4.データベース接続までのコード例

接続情報を指定してデータベースに接続する手順を、最も簡単な例でいくつか紹介します。
まず、Connection.Openメソッドの第1パラメータ(ConnectionString)に、プロバイダ名とデータベース名を指定する書き方を図23に示します。なおADOオブジェクトは実行時バインディング(以下同様)としています。
  1. '========== ⇩(3) Openメソッド実行時に全て指定 ============
  2.  Dim cn As Object   '←実行時バインディングのConnectionオブジェクト
  3.  Dim s As String   '←ConnectionStringの内容
  4.  Set cn = CreateObject("ADODB.Connection")   '←Connectionオブジェクトを生成
  5.  s = ThisWorkbook.Path & "¥" & "its-041.accdb"       '←データソース情報
  6.  s = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & s   '←プロバイダとデータソースを文字列化
  7.  cn.Open s   '←プロバイダとデータソースをOpenメソッドの第1パラメータに指定
  8.    (処理)
図23

44行目「Set cn = CreateObject("ADODB.Connection")」で、Connectionオブジェクトを生成します。
46~47行目で、第1パラメータ(ConnectionString)の文字列を作成しています。プロバイダー(Provider=)として「Microsoft.ACE.OLEDB.12.0」を、データベース(Data Source=)として「ThisWorkbook.Path & "¥" & "its-041.accdb"」を指定します。
パラメータの文字列が完成したら、49行目「cn.Open s」で、Openメソッドの第1パラメータに接続情報を渡して、データベースに接続します。
図23のように「接続情報文字列をOpenメソッドの第一パラメータ(ConnectionString)に渡す」のでは無く、「ConnectionオブジェクトのConnectionStringプロパティ」に事前に渡した後、Openメソッドを実行する事も可能です。コードとしては図24のようになります。
  1. '========== ⇩(4) ConnectionStringプロパティに値を指定 ============
  2.  Dim cn As Object   '←実行時バインディングのConnectionオブジェクト
  3.  Dim s As String   '←ConnectionStringプロパティの内容
  4.  Set cn = CreateObject("ADODB.Connection")   '←Connectionオブジェクトを生成
  5.  s = ThisWorkbook.Path & "¥" & "its-041.accdb"       '←データソース情報
  6.  s = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & s   '←プロバイダとデータソースを文字列化
  7.  cn.ConnectionString = s   '←ConnectionStringプロパティに接続情報を渡す
  8.  cn.Open   '←パラメータ無しでOpenメソッドを実行
  9.    (処理)
図24

図24の69行目では「Provider情報」と「Data Source情報」をConnectionStringプロパティに設定しています。この設定により、Provider情報は「Providerプロパティ」に、Data Source情報はPropertiesコレクション内の「Data Sourceプロパティ」に格納された後、71行目「cn.Open」でデータベースに接続します。
なおConnectionStringプロパティへの設定を重複すると、各プロパティは一旦空になった後、最新の情報に置き換えられてしまいます。但しProviderプロパティだけはProvider情報を書き換えない限りは残ってくれるようです。
図23ではOpenメソッドの第1パラメータに接続情報を渡し、図24ではConnectionStringプロパティに接続情報を渡しましたが、Connectionオブジェクト配下には、ConnectionStringプロパティの他にも以下のようなプロパティがあります(図25)。
(接続情報に関するプロパティのみを書き出しています。)
プロパティ内容
ConnectionString接続情報文字列
Provider接続するプロバイダ名
(既定:MSDASQL)
Properties
コレクション
Passwordパスワード
User IDユーザー名
Data Sourceデータベース名
Extended Properties拡張プロパティ
図25

この各プロパティに直接的に値を格納する手法が図26です。
  1. '========== ⇩(5) 各プロパティに値を直接指定 ============
  2.  Dim cn As Object   '←実行時バインディングのConnectionオブジェクト
  3.  Set cn = CreateObject("ADODB.Connection")   '←Connectionオブジェクトを生成
  4.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"   '←プロバイダを設定
  5.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←データソースを設定
  6.  cn.Open   '←パラメータ無しでOpenメソッドを実行
  7.    (処理)
図26

85行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」では、ConnectionオブジェクトのProviderプロパティに、ACEプロバイダを設定しています。
86行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"」では、ConnectionオブジェクトのPropertiesコレクション内のData Sourceプロパティに、Accessのファイル名を設定しています。
また、ExcelやCSVをデータベースとして使用する場合は「拡張プロパティ情報」を、ConnectionオブジェクトのPropertiesコレクション内のExtendes Propertiesプロパティに指定します。
各プロパティ値にデータを設定したら、88行目「cn.Open」でデータベース接続します。

3ー2.Executeメソッド(コマンドの実行)

ConnectionオブジェクトのExecuteメソッドの構文は以下のようになります。戻り値は「Recordsetオブジェクト」です
 Recordsetオブジェクト = Connection.Execute( CommandText, RecordsAffected, Options )
戻り値(レコードセット)をデータ処理する場合は、Setステートメントで受け取りますが、そのレコードセットは「読み取り専用」です。そのため、データの取得のみで、追加や変更・削除処理は出来ません。
なお第1パラメータに「InsertやUpdate・DeleteのSQL文を指定」した場合は、戻り値を操作している訳では無いので、追加・変更・削除処理は可能です(Excelは削除不可、CSVは変更・削除不可 である事は変わりません)。
このようなInsert文等を指定した時は、変更を目的としたレコードセットを受け取る必要が無いので、以下のように戻り値を受け取らず、そのまま実行します。
 Connection.Execute( CommandText, RecordsAffected, Options )
なおレコードセットを受け取る必要が無くても、ExecuteメソッドはRecordsetオブジェクトを戻してきます。もし、その戻されたRecordsetオブジェクトがデータか否かを調べる必要がある場合には「戻されたRecordsetオブジェクトのStateプロパティ」を確認します。
値が1(adStateOpen)であればデータとしてのレコードセットであり、ゼロ(adStateClosed)であればデータでは無い事が分かるようです。なお「Recordset.Close メソッド」を実行すると、State値はゼロになります。
Executeメソッドに指定できるパラメータは、以下の内容になります。
パラメータ内容
CommandText必須テーブル名、SQL文 等
RecordsAffected省略可Long型の変数に、変更レコード数を戻す
Options省略可CommandTextの種類(図30)
図27

第1パラメータ(CommandText)は必須で、テーブル名、またはSQL文 等を文字列で指定します。
第2パラメータ(RecordsAffected)には、Long型の変数を指定します。第1パラメータにデータ変更を伴うSQL文(Insert・Update・Delete)を指定しExecuteメソッドを実行すると、変更対象となったレコード数がこの変数に戻されます。コードで示すと、図28のようになります。
  1. '========== ⇩(6) Connection.Executeで変更対象行数を取得 ============
  2. Sub Record_Count()
  3.  Dim cn As Object    '←Connectionオブジェクト
  4.  Dim SQL As String    '←SQL文
  5.  Dim cnt As Long    '←変更対象のレコード数
  6.  Set cn = CreateObject("ADODB.Connection")    '←Connectionオブジェクトの生成
  7.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"    '←プロバイダをACEに設定
  8.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name   '←データベースをこのExcelに設定
  9.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"    '←拡張プロパティにExcelを設定
  10.  cn.Open    '←データベースに接続
  11.   SQL = "update [db$] set St='XYZ' where DT=#2000/11/20#"    '←SQL文にUpdate文を設定
  12.   cn.Execute SQL, cnt    '←SQL文を実行し、変更対象レコード数をcnt変数で取得
  13.   MsgBox "変更対象のレコード数:" & cnt & "行"    '←変更対象レコード数を表示
  14.  cn.Close    '←データベースを閉じる
  15.  Set cn = Nothing
  16. End Sub
図28

115行目「cn.Execute SQL, cnt」で、Executeメソッドの第2パラメータに指定した「Long型の変数cnt」に、変更対象となったレコード数が戻されますので、それを116行目「MsgBox "変更対象のレコード数:" & cnt & "行"」でメッセージ表示をさせています。
出力された様子は図29のようになります。
変更対象行数の表示
図29

SQL文は113行目の「update [db$] set St='XYZ' where DT=#2000/11/20#」ですので、DT列が2000/11/20のものを抽出し、St列の値をXYZに変更しています。図29のワークシートで、Dt列が「2000/11/20」なのは6~8行の「3レコード」なので、メッセージ表示も3行となります。
但し、変更する以前からSt列がXYZだった場合でも、値が変更された事は事実なので3行と表示されます。つまり、値が変わったことを表すのでは無い事には注意が必要です。言ってみれば「Select count(*) from [db$] where DT=#2000/11/20#」を実行した時に得られる値になります。
第3パラメータ(Options)は、第1パラメータ(CommandText)に指定したものの種類を指定します。
Options(第1パラメータの種類)
定数内容
adCmdUnspecified
or adOptionUnspecified
-1種類を指定せず
adCmdText1SQL文
adCmdTable2テーブル
adCmdStoredProc4ストアドプロシージャ
adCmdUnknown8不明(既定)
adAsyncExecute0x10(16)非同期実行
adAsyncFetch0x20(32)残り行を非同期で取得
adAsyncFetchNonBlocking0x40(64)取得中にブロックせず
adExecuteNoRecords0x80(128)行を返さないコマンド
adCmdFile256Recordsetファイル
adCmdTableDirect512全列が返るテーブル
(ExcelシートDB、CSVファイル)
adExecuteStream0x400(1024)コマンド実行結果をストリームとして返すもの
adExecuteRecord0x800(2048)単一行を返すもの
図30

既定値はadCmdUnknown(値=8)です。SQL文を指定した場合は既定(第3パラメータを省略)でも正しく判定してくれます。しかしテーブル名を指定する場合には注意が必要で「Excelのシート名やCSVのファイル名をテーブル名として指定した場合、adCmdTableDirect(値=512)を指定しないとエラーが発生」します。
またAccessでテーブル名を指定する際は、Optionsパラメータを省略する他、様々な値でもOKです。詳しくは「よりみち」を参照ください。

4.Recordsetオブジェクト

4ー1.Openメソッド(レコードセット取得)

データベース接続後は、データベースから値をレコードセットとして受け取り処理をしたり、データを変更(Insert、Update、Delete処理)したりします。
レコードセットの取得やデータ変更のSQL文を実行する方法1つとして、下記のようにRecordsetオブジェクトのOpenメソッドを使う方法があります。
 Recordset.Open (Source, ActiveConnection, CursorType, LockType, Options)
このOpenメソッドを実行すると、レコードセットを取得した場合はRecordsetオブジェクトにデータが入ります。
レコードセットのOpenメソッドには、下記の5つのパラメータが設定可能です。
Recordset.Openメソッドのパラメータ
パラメータ内容
Source省略可①テーブル名
②SQL文
③Commandオブジェクト
ActiveConnection省略可④Connectionオブジェクト
⑤ConnectionString文
(SourceにCommandオブジェクトを指定した場合は省略する事)
CursorType省略可カーソルの種類(図32)
LockType省略可ロックの種類(図33)
Options省略可Source(第1パラメータ)の種類(図30)
図31

4ー1ー1.各パラメータの値

第1パラメータのSourceは、テーブル名やSQL文を指定します。また事前にCommandオブジェクトのCommandTextプロパティにテーブルやSQL文をセットしておき、そのCommandオブジェクトを第1パラメータに持ってくることも可能です。
なお、Commandオブジェクトを指定する場合は、CommandTextプロパティに「テーブル名」や「SQL文」を格納するのと同時に、ActiveConnectionプロパティに接続中のConnectionオブジェクトを指定することが必要です。そして、下で説明する第2パラメータは必ず省略させます。
もし、第1パラメータにSQL文の例えば「Select * from テーブル名」を指定すると、第1パラメータにテーブル名を指定したのと同じレコードセットが得られることになります。しかし、テーブル名指定の時に可能だったデータの挿入・変更・削除処理は、Select文で全レコードを取り出したレコードセットでは実行できません。
再確認したら、Select文指定時でもデータの挿入・変更・削除処理が可能と分かりました(テーブル名指定時と同じ)。当時のExcelの状態がおかしかったのかもしれません。誤情報を流してしまい、申し訳ありませんでした。2023/11/28
第2パラメータのActiveConnectionは、接続しているConnectionオブジェクト変数を指定します。その他の方法として、Connectionオブジェクトの接続情報を文字列で指定することも可能です。
なお、各プロパティに値を直接指定している場合はConnectionStringのみでは充分では無く、Provider情報やデータベース名は盛り込んでおく必要があります。
また、第1パラメータにCommandオブジェクトを指定した場合は、第2パラメータは必ず省略します。
第3パラメータのCursorTypeには、以下の定数を指定します。
CursorType(カーソルの種類)
定数内容
adOpenForwardOnly0前方スクロールタイプカーソルを開く(既定)
adOpenKeyset1キーセットカーソルを開く
adOpenDynamic2動的カーソルを開く
adOpenStatic3静的カーソルを開く
adOpenUnspecified-1カーソルを指定せず
図32

第4パラメータのLockTypeには、以下の定数を指定します。
LockType(ロックの種類)
定数内容
adLockReadOnly1読み取り専用レコードを示す(既定)
adLockPessimistic2編集直後にレコードをロックする
adLockOptimistic3Updateメソッドを呼び出すときにのみレコードをロック
adLockBatchOptimistic4バッチ更新
adLockUnspecified-1ロックの種類を指定せず
図33

この第3(CursorType)と第4(LockType)パラメータの設定には注意が必要です。「各パラメータの組み合わせ」で詳しく説明しますが、第1パラメータにテーブル名を指定する際に「第3と第4パラメータを省略すると、思った処理ができない」可能性があります。逆に第1パラメータにSQL文を指定すれば、大きな不具合は無さそうです。
第5パラメータのOptionsは、第1パラメータ(Source)に指定したものの種類を、図30の定数で指定します。内容はConnectionオブジェクトのExecuteメソッドの第3パラメータ、CommandオブジェクトのExecuteメソッドの第3パラメータと同じです。
第1パラメータがSQL文の場合は省略でもOKですし、テーブルの場合でもAccessデータベースであれば省略でも問題ありません(詳細は「よりみち」を参照下さい)。しかし、テーブル名としてExcelのシート名やCSVのファイル名を指定する場合は、adCmdTableDirect(値=512)を指定しないとエラーが発生します。

4ー1ー2.各パラメータの組み合わせ

このRecordset.Open のパラメータの内、第1パラメータは「テーブル名」又は「SQL文」のどちらか(Commandオブジェクトでも関節的にはテーブル名かSQL文のどちらか)ですし、第5パラメータは、その第1パラメータに指定したものが何かを指定しますので一意で決まると言っても良いと思います。
また第2パラメータは接続したConnectionですし、その接続情報を文字列で指定したとしても、内容的には同じです。
多くの選択が可能なのは第3パラメータ(CursorType)と第4パラメータ(LockType)で、その組み合わせが実行内容にどのように影響しているかを確かめてみたのが以下になります。
4ー1ー2ー1.Accessの場合(Openメソッドにはテーブル名を指定)
データベース対象をAccessに、第1パラメータ(Source)にテーブル名を指定した状態で、CurorType(第3パラメータ)とLockType(第4パラメータ)の色々な組み合わせ状態を作ります。その各組み合わせで、データ取得(Select)・データ挿入(Insert)・データ変更(Update)・データ削除(Delete)のどの操作が可能かをまとめたのが図34です。
AccessDB + テーブル名
LockType定数CursorType定数
0
(Forward)
1
(Keyset)
2
(Dynamic)
3
(Static)
-1
(Unspecified)
adLockReadOnly1S・・・S・・・S・・・S・・・S・・・
adLockPessimistic2SIUDSIUDSIUDSIUDSIUD
adLockOptimistic3SIUDSIUDSIUDSIUDSIUD
adLockBatchOptimistic4S(IUD)S(IUD)S(IUD)S(IUD)S(IUD)
adLockUnspecified-1S・・・S・・・S・・・S・・・S・・・
S=Select処理、I=Insert処理、U=Update処理、D=Delete処理
「・」は処理不可
図34

まずLockTypeがadLockReadOnly(値=1:読取専用)の場合は、Select処理のみとなる事は容易に想像がつきます。またadLockUnspecified(値=-1:指定無し)は、既定のadLockReadOnlyと同じ状態になる事も頷けます。
LockType値が2(adLockPessimistic)と3(adLockOptimistic)の場合は、全ての処理が可能です。
一方でadLockBatchOptimistic(値=4:バッチ更新)の場合は、IUDをカッコ付きとしていますが、注意点が2つあります。
1つ目は、ExcelのVBA上では「バッチ処理として記憶できる容量が1レコード」である事です。例えばUpdateで2行分の処理を行おうとすると、2行目の処理を行う時点で「変更を保留している行の数が、設定された条件を超えました」とのエラーが発生します。それなら上限を増やせば良いのですが、残念ながらExcelのVBA側から変更する方法は見つかりませんでした。
2つ目は「レコードを変更した後にUpdateメソッドを実行しても、データベース本体には変更内容が保存されない」事です。バッチ処理という言葉の通り「UpdateBatch」メソッドを実行しない限り、変更内容はデータベースに保存されません。
この内容をプロパティ面から検証したのが図35です。Accessデータベースにテーブル名でレコードセットを取得(Open)した後の、Recordsetのプロパティです。CursorType値とLockType値を振ってプロパティを取得し、(Access,Excel,CSVでの違いも含め)違いが有ったプロパティのみを示しています。
なお図35のプロパティ結果一覧は、Accessにテーブルを指定した時と、SQL文を指定した時とで、全く同じ結果となりました。
Access時のRecordset.Openのプロパティ
図35

この内容を図34と見比べてみると「Updatability が値7(=1(更新)+ 2(削除)+ 4(挿入)」だと、Insert・Update・Delete処理が出来るように見えます。また「iRowsetUpdateがTrue」の時とも思えます。
しかし、SQL文を実行させた時(図36)の結果を併せてみると、傾向はありそうなものの決定的では無いことが分かります。
また「LockType」が値4の場合、値4は「バッチ処理」を表すはずなので、Updateメソッドではデータベースが更新されない(=図34)はずです。しかしSQL文の時(図36)には即更新されます。
結論から言うと「プロパティ値を見ただけでは、動作内容は特定できない」ようです。但し、テーブルを第1パラメータに指定した際には、プロパティ値によりある程度予測ができるような気がします。
なお、CursorTypeが1(adOpenKeyset)または3(adOpenStatic)の時に、Bookmark値が異常に大きな値(この時のAccessテーブルのレコード数は4行)になっているのが気になりましたが、今回の操作では特に異常は発生しません。元々ブックマーク機能は「Bookmark値を一旦保存しておき、後からBookmarkプロパティに設定することでジャンプする機能」と説明されていますが、ExcelのVBAから試してみましたがBookmark設定時にエラーが出てしまい、うまくいきませんでした。
4ー1ー2ー2.Accessの場合(OpenメソッドにはSQL文を指定)
次に、データベース対象をAccessに、第1パラメータ(Source)にSQL文を指定した時の状態が図36です。
なお、Inset,Update,Delete文を実行する手法としては図02のように、Connection.Execute、Command.Execute、Recordset.Openの3種類があります。ここは「Recordsetオブジェクト」の説明なので、図02のNo.9である「Recordset.Open」を使う方法で実行可不可のチェックとプロパティ値の確認を行っています。
AccessDB + SQL文
LockType定数CursorType定数
0
(Forward)
1
(Keyset)
2
(Dynamic)
3
(Static)
-1
(Unspecified)
adLockReadOnly1SIUDSI・・SIUDSIUDSIUD
adLockPessimistic2SIUDSIUDSIUDSIUDSIUD
adLockOptimistic3SIUDSIUDSIUDSIUDSIUD
adLockBatchOptimistic4SIUDSIUDSIUDSIUDSIUD
adLockUnspecified-1SIUDSI・・SIUDSIUDSIUD
S=Select文、I=Insert文、U=Update文、D=Delete文
図36

第1パラメータにテーブル名を指定した図34とは、全く異なる結果となります。
LockType=1(ReadOnly) × CursorType=1(Keyset)の組み合わせの時にのみ、UpdateとDeleteが実行できない状態です。それにしても、ReadOnlyなのにInsert文が実行できてしまうのも不思議です。
またLockType=4(バッチ処理)の場合、図34ではUpdateBatchメソッドを実行しない限り、データベースに変更内容が反映されませんでしたが、図36ではUpdateメソッドでそのまま反映されます。
この検証としてレコードセットのプロパティ値を調べてみたのですが、テーブル指定の図35と全く一緒でした。
結論として、SQL文を使う場合は「実行可不可をあまり気にせずに、ロックの種類を検討できる」と言えるのかもしれません。
4ー1ー2ー3.ExcelシートDBの場合(Openメソッドにはテーブル名を指定)
Excelのシートをデータベースにし、第1パラメータ(Source)にテーブル名を指定した時の状態が図37です。
なお、ExcelシートDBをテーブルとして操作する場合、第5パラメータ(第1パラメータの種類を指定)を省略するとエラーが発生します。色々試してみた結果、第5パラメータに「adCmdTableDirect(値=512)」を指定する事で「テーブルとしてレコードセットを取得」できます。図37図38では、その設定条件になっていますのでご注意下さい。
ExcelシートDB + テーブル名
LockType定数CursorType定数
0
(Forward)
1
(Keyset)
2
(Dynamic)
3
(Static)
-1
(Unspecified)
adLockReadOnly1S・・・・・S・・・・・S・・
adLockPessimistic2SI・・I・SI・・I・SI・
adLockOptimistic3SI・・I・SI・・I・SI・
adLockBatchOptimistic4S(I)・・(I)・S(I)・・(I)・S(I)・
adLockUnspecified-1S・・・・・S・・・・・S・・
S=Select処理、I=Insert処理、U=Update処理
図37

図37でも分かるように、CursorTypeが1(adOpenKeyset)または3(adOpenStatic)の時は、データ参照(Select相当)すら出来ません。と言ってデータが取得できない訳ではなく、カーソルを移動(MoveNextメソッド)しようとした時に「ブックマークが正しくない」とのエラーが発生するのです。
ですのでSelect相当だけでは無く、カーソルを移動しながら対象レコードを探す「Update相当」でもエラーが発生します(Insert相当はMoveNextを使わないため、エラー出ず)。
また、LockType=4(adLockBatchOptimistic)はバッチ処理のため、Accessの図34と同様に「UpdateBatch」メソッドを実行しないとデータベースは変更されません。
上記のブックマークエラーをプロパティ面から調べたのが図38です。項目はAccessの図35等と同じにしてあります。
Excel+Table時のRecordset.Openのプロパティ
図38

図37では、CursorType値がKeyset(値=1)とStatic(値=3)の場合はデータ参照が出来ませんが、プロパティ値で「1・3」と「0・2」とで差が見えるのは「Bookmark」「PageCount」「RecordCount」「iRowsetLocate」「Bookmarkable」です。 エラー内容(ブックマークが正しくない)から「Bookmark」「Bookmarkable」辺りが影響しているように思われますが、良くは分かりませんでした。
4ー1ー2ー4.ExcelシートDBの場合(OpenメソッドにはSQL文を指定)
Excelのシートをデータベースにし、第1パラメータ(Source)にSQL文を指定した時の状態が図39です。
ExcelシートDB + SQL文
LockType定数CursorType定数
0
(Forward)
1
(Keyset)
2
(Dynamic)
3
(Static)
-1
(Unspecified)
adLockReadOnly1SIUSI・SIUSIUSIU
adLockPessimistic2SIUSIUSIUSIUSIU
adLockOptimistic3SIUSIUSIUSIUSIU
adLockBatchOptimistic4SIUSIUSIUSIUSIU
adLockUnspecified-1SIUSI・SIUSIUSIU
S=Select処理、I=Insert処理、U=Update処理
図39

テーブル指定の図37と比較し、SQL文を使うと、ほぼ全ての組み合わせで処理が出来ることが分かります。但し「CursorType=1 × LockType=1」の時にUpdate処理が出来ません( × LockType=-1 も同様)。
これをプロパティ値で確認してみたのが図40になります。
Excel+SQL時のRecordset.Openのプロパティ
図40

図38と異なっているのは、一番上の「AbsolutePosition」と「Bookmark」のみです。しかもCursorTypeが0と2の場合は全く同じプロパティ値です。それなのに実行可否の結果(図37図39)は全く異なります。Excelについては、プロパティ値から動作を予測することは難しそうです。
4ー1ー2ー5.CSVの場合(Openメソッドにはテーブル名を指定)
CSVファイルを使い、第1パラメータ(Source)にテーブル名(=CSVファイル名)を指定した時の状態が図41です。
なおExcelシートDBの時と同様に、CSVでも第5パラメータ(第1パラメータの種類を指定)を省略するとエラーが発生します。図41図42では、第5パラメータに「adCmdTableDirect(値=512)」を指定し、Recordset.Openを実行しています。
CSV + テーブル名
LockType定数CursorType定数
0
(Forward)
1
(Keyset)
2
(Dynamic)
3
(Static)
-1
(Unspecified)
adLockReadOnly1S・・・S・・・S・
adLockPessimistic2SI・ISI・ISI
adLockOptimistic3SI・ISI・ISI
adLockBatchOptimistic4S(I)・(I)S(I)・(I)S(I)
adLockUnspecified-1S・・・S・・・S・
S=Select処理、I=Insert処理
図41

Excel+テーブル(図37)の時と似たような結果となり、CursorTypeが1と3の場合はSelect操作すら出来ません。またLockType=4の場合は、カッコ付きとしてあるようにUpdateBatchを使わないと変更値がデータベースに反映されません。
とりあえず、プロパティ値を紹介します(図42)が、Excel時(図38)と同様に良く分かりません。
CSV+Table時のRecordset.Openのプロパティ
図42

4ー1ー2ー6.CSVの場合(OpenメソッドにはSQL文を指定)
CSVファイルに対して、第1パラメータにSQL文を指定した時の実行可否を表したのが図43です。
CSV + SQL文
LockType定数CursorType定数
0
(Forward)
1
(Keyset)
2
(Dynamic)
3
(Static)
-1
(Unspecified)
adLockReadOnly1SISISISISI
adLockPessimistic2SISISISISI
adLockOptimistic3SISISISISI
adLockBatchOptimistic4SISISISISI
adLockUnspecified-1SISISISISI
S=Select処理、I=Insert処理
図43

CSVファイルに対しては、元々Select操作とInsert操作しか出来ませんが、全てのCursorTypeとLockTypeの組み合わせで両操作が出来ます。ちょうどExcel+SQLの操作(図39)からUpdateを取り除いた感じとなります。
この時のプロパティ値を図44に示しますが、テーブル指定の図42と異なっているのは、Excel時と同様の「AbsolutePosition」と「Bookmark」のみでした。
CSV+SQL時のRecordset.Openのプロパティ
図44

5.Commandオブジェクト

Commandオブジェクトには、複数のプロパティやメソッドが存在しますが、ここでは実行コマンドの格納やコマンドの実行に必要な「ActiveConnection」プロパティ、「CommandText」プロパティ、「Execute」メソッドの3種を説明します。

5ー1.ActiveConnectionプロパティ(データベースとの結び付け)

まず生成したCommandオブジェクトが、どの「データベース接続」に属しているかを指定するのがActiveConnectionプロパティです。構文としては、下記のように「接続中のConnectionオブジェクト」を指定します。
 Command.ActiveConnection = 接続中のConnectionオブジェクト
なおConnectionオブジェクトの代わりに、Provider名・Data Source名を含めた接続文字列(Excel等の場合は、Extended Properties も必要)をActiveConnectionに指定してもOKです。Microsoftのサイトでは、「接続が閉じている時に文字列指定」との説明がありますが、試してみると接続中でもOKでした。

5ー2.CommandTextプロパティ(実行コマンドの格納)

コマンドをCommandオブジェクトで実行する場合にも、またCommandオブジェクトに格納後Recordset.Openでレコードセットを取得する場合にも、「実行コマンドはCommandTextプロパティに代入」します。構文は以下の通りです。
 Command.CommandText = 実行コマンド(String型)
実行コマンドは、今回ではデータベースの「テーブル名」や「SQL文」です。

5ー3.Executeメソッド(コマンドの実行)

Commandオブジェクトでコマンドを実行するには、Executeメソッドを使用します。構文は以下となります。
 Command.Execute ( RecordsAffected, Parameters, Options )
なおExecuteメソッドを実行する前に、「ActiveConnectionプロパティで接続データベースへ紐付け」をし、「CommandTextプロパティに実行するテーブル名やSQL文を代入」しておく必要があります。
3つのパラメータは以下の内容になります。全て省略可です。
パラメータ内容
RecordsAffected省略可Long型の変数に、変更レコード数を戻す
Parameters省略可パラメータクエリ(SQL文)に渡す
パラメータ値の配列
Options省略可CommandTextの種類
(図30)
図45

第1パラメータのRecordsAffectedは、Long型変数を引数として与えておくことで、Insert・Update・Delete処理で影響を与えたレコード数を戻してくれるものです。使い方は図28と同じです。なおSelect文でも使用は出来ますが、選択したレコード数を戻してくれる訳ではありません。
第2パラメータのParametersは、CommandTextにパラメータクエリ(≒変数をSQL文に組み込んだようなもの)を指定した際、そのパラメータ値を配列として指定するものです(今回は、説明を省略します)。
第3パラメータ(Options)は、第1パラメータに指定したものの種類を図30のように指定します。内容はConnectionオブジェクトのExecuteメソッドの第3パラメータ、RecordsetオブジェクトのOpenメソッドの第5パラメータと同じです。
寄り道(テーブル名指定のExcelとCSVはCommand.Execute不可)
Command.Executeの第1パラメータに「テーブル名」を指定した場合、Options(Command.Executeでは第3パラメータ)の設定には少し注意が必要です。Connection.Execute、Recordset.Openの時も合わせて、まとめたのが以下になります。
テーブルを指定した時にデータ取得可能なOptionsパラメータ
Connection.ExecuteCommand.ExecuteRecordset.Open
Access省略 他省略 他省略 他
ExceladCmdTableDirect(512)×adCmdTableDirect(512)
CSVadCmdTableDirect(512)×adCmdTableDirect(512)
図46

ExcelやCSVのデータをテーブル名指定でレコードセットを取得する場合、Connection.ExecuteとRecordset.OpenではOptionsパラメータとして「adCmdTableDirect(512)」指定する必要があります(それ以外ではエラー発生)。しかしCommand.Executeでは、512を指定しても「引数が違う」とのエラーが発生します。ダメな理由は良く分かりませんでした。
そのため「テーブル名を指定してCommand.Executeで実行する場合は、Accessのみ」となります。
一方、図46では「省略 他」と表記したAccessでは、Optionsパラメータを省略する他にも色々な値でテーブル名での取得が可能です。以下はOptionsパラメータ値別にテーブル名での実行が可能か否かをまとめたものです。
テーブルを指定した時にデータ取得可能なOptionsパラメータ(Access)
定数内容Connection
.Execute
Command
.Execute
Recordset
.Open
adCmdUnspecified
or adOptionUnspecified
-1種類を指定せず
adCmdText1SQL文×××
adCmdTable2テーブル
adCmdStoredProc4ストアドプロシージャ×××
adCmdUnknown8不明(既定)
adAsyncExecute0x10(16)非同期実行
adAsyncFetch0x20(32)残り行を非同期で取得
adAsyncFetchNonBlocking0x40(64)取得中にブロックせず
adExecuteNoRecords0x80(128)行を返さないコマンド×××
adCmdFile256Recordsetファイル×××
adCmdTableDirect512全列が返るテーブル
(ExcelシートDB、CSVファイル)
×
adExecuteStream0x400(1024)コマンド実行結果をストリームとして返すもの×××
adExecuteRecord0x800(2048)単一行を返すもの×××
図47

面白いことに、Command.Executeの時に、OptionsパラメータにadCmdTableDirect(値=512)を指定するとエラーが出てしまいます。つまり「テーブルを指定する際は、Optionsは512」というルールはCommand.Executeでは成立しないのです。
それ以外のOptions値ではConnection、Recordsetと同じ結果となりましたが、ここで説明した以外の機能でも「Commandオブジェクトだけは特殊」という事があるかもしれませんので、注意が必要と思います。

5ー4.Commandオブジェクトの使用例

5ー4ー1.実行コマンドの格納

Commandオブジェクトを使用する場面は2種類あります。
1つ目は、実行するコマンド(テーブル名、またはSQL文)をCommand.CommandTextプロパティに格納した後「Recordset.Openの第1パラメータにCommandオブジェクトを指定」することでレコードセットを取得したり、変更のSQL文を実行したりする場面です。
  1. '========== ⇩(7) Commandオブジェクトに実行コマンドを格納 ============
  2.  Dim cn As Object   '←実行時バインディングのConnectionオブジェクト
  3.  Dim rs As Object   '←実行時バインディングのRecordsetオブジェクト
  4.  Dim cmd As Object   '←実行時バインディングのCommandオブジェクト
  5.  Set cn = CreateObject("ADODB.Connection")   '←Connectionオブジェクトの生成
  6.  Set rs = CreateObject("ADODB.Recordset")   '←Recordsetオブジェクトの生成
  7.  Set cmd = CreateObject("ADODB.Command")   '←Commandオブジェクトの生成
  8.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"   '←プロバイダ設定
  9.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←DB設定
  10.  cn.Open   '←データベースに接続
  11.  cmd.ActiveConnection = cn   '←接続条件をCommandオブジェクトに設定
  12.  cmd.CommandText = "Select * from TestTable"   '←実行コマンドをCommandオブジェクトに設定
  13.  rs.Open cmd   '←コマンドを格納したCommandを使って実行
  14.    (処理)
図48

144行目「cmd.ActiveConnection = cn」で、データベース接続条件を取り込みます。
145行目「cmd.CommandText = "Select * from TestTable"」で実行コマンドをCommandTextに格納します。
147行目「rs.Open cmd」で、そのSQL文をRecordsetオブジェクトから実行します。
一般的なRecordset.Openの使い方は「rs.Open SQL文 , Cn」のように、第1パラメータにSQL文やテーブル名を指定し、第2パラメータには接続情報のあるConnectionオブジェクトを指定しますが、Commandオブジェクトを使った147行目では、第2パラメータを省略します。
これは、第1パラメータに指定したCommandオブジェクトは、CommandTextプロパティにSQL文やテーブルが指定(145行目)し、ActiveConnectionプロパティに接続情報を指定(144行目)したからですが、第2パラメータを更に重複設定するとエラーが出ます。つまり「省略しないとエラー」との説明の方が正しいかもしれません
と言って、ActiveConnectionプロパティへの指定を省略し「rs.Open cmd, cn」とするとエラーが出ます。「CommandオブジェクトのCommandTextとActiveConnectionはセットで指定」する必要があります。
なお、図48はSelect文でしたが、CommandTextプロパティにテーブル名を指定しても同じです。またデータ変更用のSQL文を指定した場合は、147行目の実行でデータが変更されます。

5ー4ー2.コマンドの実行

2つ目は、実行コマンド(=テーブル名、SQL文)を指定した後、CommandオブジェクトのExecuteメソッドで実行をする場面です。その際、SQL文がSelect文であったりテーブル名であれば、ExecuteメソッドがRecordsetオブジェクトを戻してきますので、レコードセットとして取得します。またデータ変更のSQL文(Insert・Update・Delete文)であれば、データ変更を実行します。
  1. '========== ⇩(8) Commandオブジェクトで実行 ============
  2.  Dim cn As Object   '←実行時バインディングのConnectionオブジェクト
  3.  Dim rs As Object   '←実行時バインディングのRecordsetオブジェクト
  4.  Dim cmd As Object   '←実行時バインディングのCommandオブジェクト
  5.  Set cn = CreateObject("ADODB.Connection")   '←Connectionオブジェクトの生成
  6.  Set cmd = CreateObject("ADODB.Command")   '←Commandオブジェクトの生成
  7.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"   '←プロバイダ設定
  8.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←DB設定
  9.  cn.Open   '←データベースに接続
  10.  cmd.ActiveConnection = cn   '←接続条件をCommandオブジェクトに設定
  11.  cmd.CommandText = "Select * from TestTable"   '←実行コマンドをCommandオブジェクトに設定
  12.  Set rs = cmd.Execute   '←実行コマンドを実行
  13.    (処理)
図49

173行目「cmd.ActiveConnection = cn」で、データベース接続条件を取り込みます。
174行目「cmd.CommandText = "Select * from TestTable"」で実行コマンドをCommandTextに格納します。
175行目「Set rs = cmd.Execute」の右辺で、そのコマンドをCommandオブジェクトで実行し、戻り値であるRecordsetオブジェクトを変数rsで受け取り、処理をします。
なおデータ変更を伴うSQL文の場合は、変数で受ける必要は無いので、175行目は右辺のみでOKです。

6.データベースに接続する為のコード例

図02でも紹介した通り、データベースに接続・操作する方法はいくつかあります。図50はその再掲ですが、下半分(薄黄色のエリア)に、各手法での可能な操作(Select、Insert、Update、Delete)をまとめました。
一般的には「ExcelはDeleteが出来ない」「CSVはUpdateとDeleteが不可」などと言われていますが、接続・操作の方法でも変わってくることが分かると思います。なお実行時に指定するパラメータによっては、更に不可の操作もあるのでご注意下さい。
DAOの実行方法とコマンド可不可
図50

12種類と多そうに見えますが、基本的には以下の4種類で、実行するもの(テーブル、SQL文)が変わるだけです。しかも3と4は、Commandオブジェクトを経由するか否かの違いですので、3種と言っても良いくらいです。
 1.「Connection.Open(DB接続)」→「Connection.Execute(実行)」→(「処理」)
 2.「Connection.Open(DB接続)」→「Command.Execute(実行)」→(「処理」)
 3.「Connection.Open(DB接続)」→「Commandへコマンド格納」→「Recordset.Open(実行)」→(「処理」)
 4.「Connection.Open(DB接続)」→「Recordset.Open(実行)」→(「処理」)
ここでは図50に示す12種類の実際のコードを紹介していきます。
なおコードは、主に「Excel」について説明していきますが、見え消しにしてある「Accessのコード」「CSVのコード」と切り替えれば動作確認が出来るようにしています。(図50のNo.2はAccessしか動かないので、Accessで説明します。)
今回のコード例では、データベースとして「Access」「Excel」「CSV(カンマ区切りテキスト)を扱います。そのデータは、以下のような形の「4列×4行」としました。St、Nu、Dt、BLが列名になります。Excel、CSVも先頭行は列名行としています。
St(String型)Nu(Double型)Dt(Date型)BL(Boolean型)
"abc"1232023/1/2True
"def"1232023/2/2False
"abc"4562023/3/2False
"def"4562023/4/2True
図51

なお扱っているデータベースですが、Excelは本サンプルファイル(its-042.xlsm)のワークシート「DB」、CSVは添付のits-041.csvです。またAccessはサンプルファイルとしても添付していますが、その作成方法については「DAOでAccess・Excel・CSV等へ接続・操作」を参照下さい。

6ー1.テーブルを操作

データベースに接続し、「テーブル」を操作するコードとして4種類を以下で紹介します。
なお、主にExcelのシートデータベースについて説明していきます(図54のみAccess)が、以下のようにコードを切り替えることで、Access・CSVをデータベースの場合にすることが出来ます。丸番号は、図53図54図55図56で同じにしてあります。
Data SourceExtended Propertiesテーブル名実行
Access① Accessファイル名⑥ テーブル名そのまま⑨ Optionsパラメータは省略
Excel② Excelファイル名④ Excel 12.0 ・・・⑦ シート名+$印⑩ Optionsパラメータに512
CSV③ CSVファイルのフォルダー名⑤ Text ・・・⑧ CSVファイル名
図52

6ー1ー1.Connectionでテーブル名を実行し、レコードセット取得後に処理

図50のNo.1のコードは、以下のようになります。
  1. '========== ⇩(9) Connectionでテーブル名を実行しレコードセットを取得 ============
  2. Sub Pattern01()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim rs As Object   '←Recordsetオブジェクト
  5.  Dim SQL As String   '←テーブル名、又はSQL文
  6.  Dim i As Integer   '←レコードの行位置
  7.  Set cn = CreateObject("ADODB.Connection")
  8.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  9. ' cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←①Access
  10.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name   '←②Excel
  11. ' cn.Properties("Data Source") = ThisWorkbook.Path   '←③CSV
  12.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"   '←④Excel
  13. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"   '←⑤CSV
  14.  cn.Open
  15. '  SQL = "TestTable"   '←⑥Access
  16.   SQL = "db$"   '←⑦Excel
  17. '  SQL = "its-041.csv"   '←⑧CSV
  18. '  Set rs = cn.Execute(SQL)   '←⑨Access
  19.   Set rs = cn.Execute(SQL, , 512)   '←⑩Excel、CSV
  20.   With Sheet1.Range("B2")
  21.    .CurrentRegion.ClearContents
  22.    Do While Not rs.EOF
  23.     .Offset(i, 0) = rs.Fields(0).Value
  24.     .Offset(i, 1) = rs.Fields(1).Value
  25.     .Offset(i, 2) = rs.Fields(2).Value
  26.     .Offset(i, 3) = rs.Fields(3).Value
  27.     rs.MoveNext
  28.     i = i + 1
  29.    Loop
  30.   End With
  31.   rs.Close
  32.  cn.Close
  33.  Set rs = Nothing
  34.  Set cn = Nothing
  35. End Sub
図53

187行目「Set cn = CreateObject("ADODB.Connection")」で、Connectionオブジェクトを生成します。
189行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
192行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name」で、Excelのシートデータベースを指定します。
195行目「cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"」で、拡張プロパティの指定をします。
198行目「cn.Open」で、データベースに接続します。
201行目「SQL = "db$"」で、テーブル名として「Excelのシート名+$印」を変数SQLに代入します。
205行目「Set rs = cn.Execute(SQL, , 512)」の右辺では、ConnectionオブジェクトのExecuteメソッドでテーブル名を実行します。この時に第3パラメータには「Excel、CSVをテーブルとして読み込むためのadCmdTableDirect(値=512)」を設定します。第3パラメータへの値512の設定は、Excel+テーブル、CSV+テーブルの場合は必須ですが、Access+テーブルの場合に設定しても問題はありません。
この実行によりテーブルの全データ(レコードセット)が取得できますので、左辺の変数rsに代入します。なお、この段階では、レコードセットのカーソル(操作できる行位置)は、先頭行にあります。
207~217行目では、取得したレコードセットの全データをワークシート上に書き出しています。
207行目「With Sheet1.Range("B2")」では、シートへのデータ書き出しの基準点を決めています。
208行目「.CurrentRegion.ClearContents」は、その基準点を含むエリアに書かれていたデータをクリアします。
209行目「Do While Not rs.EOF」では、レコードセットの終端が来るまで210~215行目を回します。
210行目「.Offset(i, 0) = rs.Fields(0).Value」は、レコードセットの1列目のデータをシートの1列目に書き込みます。
211~213行目も同様に、2列目・3列目・4列目と書き込みます。
214行目「rs.MoveNext」では、カーソルを次の行に移動します。
215行目「i = i + 1」では、シート上の書き込み位置を1つ下に移動させています。
209行目で「rs.EOF = True」が成立すれば、データ処理が全て完了しDo~Loopを抜け出しますので、219行目「rs.Close」でレコードセットを閉じます。
220行目「cn.Close」では、データベースとの接続を終了させます。

6ー1ー2.Commandでテーブル名を実行し、レコードセット取得後に処理

図50のNo.2のコードは、以下のようになります。
  1. '========== ⇩(10) Commandでテーブル名を実行しレコードセット取得 ============
  2. Sub Pattern02()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim rs As Object   '←Recordsetオブジェクト
  5.  Dim cmd As Object   '←Commandオブジェクト
  6.  Dim SQL As String   '←テーブル名、又はSQL文
  7.  Dim i As Integer   '←レコードの行位置
  8.  Set cn = CreateObject("ADODB.Connection")
  9.  Set cmd = CreateObject("ADODB.Command")
  10.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  11.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←①Access
  12. ' cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name   '←②Excel
  13. ' cn.Properties("Data Source") = ThisWorkbook.Path   '←③CSV
  14. ' cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"   '←④Excel
  15. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"   '←⑤CSV
  16.  cn.Open
  17.   SQL = "TestTable"   '←⑥Access
  18. '  SQL = "db$"       '←⑦Excel
  19. '  SQL = "its-041.csv"  '←⑧CSV
  20.   cmd.ActiveConnection = cn
  21.   cmd.CommandText = SQL
  22.   Set rs = cmd.Execute    '←⑨Access
  23. '  Set rs = cmd.Execute(, , 512)   '←⑩Excel、CSV
  24.   With Sheet1.Range("B2")
  25.    .CurrentRegion.ClearContents
  26.    Do While Not rs.EOF
  27.     .Offset(i, 0) = rs.Fields(0).Value
  28.     .Offset(i, 1) = rs.Fields(1).Value
  29.     .Offset(i, 2) = rs.Fields(2).Value
  30.     .Offset(i, 3) = rs.Fields(3).Value
  31.     rs.MoveNext
  32.     i = i + 1
  33.    Loop
  34.   End With
  35.   rs.Close
  36.  cn.Close
  37.  Set rs = Nothing
  38.  Set cmd = Nothing
  39.  Set cn = Nothing
  40. End Sub
図54

238行目「Set cn = CreateObject("ADODB.Connection")」で、Connectionオブジェクトを生成し、239行目「Set cn = CreateObject("ADODB.Command")」で、Commandオブジェクトを生成します。
241行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
243行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"」で、Accessデータベースを指定します。
250行目「cn.Open」で、データベースに接続します。
252行目「SQL = "TestTable"」で、Accessのテーブル名を変数SQLに代入します。
256行目「cmd.ActiveConnection = cn」は、接続中のConnectionオブジェクトをCommandオブジェクトのActiveConnectionに指定し、ConnectionとCommandを結び付けています。
257行目「cmd.CommandText = SQL」では、CommandオブジェクトのCommandTextにテーブル名を指定しています。
259行目「Set rs = cmd.Execute」の右辺では、CommandオブジェクトのExecuteメソッドを実行し、Accessのテーブルを開いてレコードセットにし、左辺の変数rsに代入しています。
レコードセットを取得した後は図53と全く同じです。262~272行目では、取得したレコードセットをDo~Loopで回しながら全データをシート上に書き出しています。
この「Commandでテーブル名を実行しレコードセット取得」するパターンは、「Commandオブジェクト」でも説明しましたが、動く事が確認できたのはAccessのみです。ですので図54の中に一応記載しておいたExcel・CSVのコードに切り替えてもエラーが出ますので注意下さい。

6ー1ー3.Commandにテーブル名を格納後Recordset実行し、レコードセット取得後に処理

図50のNo.3のコードは、以下のようになります。
  1. '========== ⇩(11) Commandにテーブル名を格納後Recordset実行しレコードセット取得 ============
  2. Sub Pattern03()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim rs As Object   '←Recordsetオブジェクト
  5.  Dim cmd As Object   '←Commandオブジェクト
  6.  Dim SQL As String   '←テーブル名、又はSQL文
  7.  Dim i As Integer   '←レコードの行位置
  8.  Set cn = CreateObject("ADODB.Connection")
  9.  Set rs = CreateObject("ADODB.Recordset")
  10.  Set cmd = CreateObject("ADODB.Command")
  11.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  12. ' cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←①Access
  13.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name   '←②Excel
  14. ' cn.Properties("Data Source") = ThisWorkbook.Path   '←③CSV
  15.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"   '←④Excel
  16. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"   '←⑤CSV
  17.  cn.Open
  18.   cmd.ActiveConnection = cn
  19. '  SQL = "TestTable"   '←⑥Access
  20.   SQL = "db$"   '←⑦Excel
  21. '  SQL = "its-041.csv"   '←⑧CSV
  22.   cmd.CommandText = SQL
  23. '  rs.Open cmd, , 0, 2   '←⑨Access
  24.   rs.Open cmd, , 0, 2, 512   '←⑩Excel、CSV
  25.    GoTo Sel   'Sel,Ins,Upd,Del ←Excel,CSVでは、Update処理・Delete処理はエラーが出ます。
  26. Sel:
  27.    With Sheet1.Range("B2")
  28.     .CurrentRegion.ClearContents
  29.     Do While Not rs.EOF
  30.      .Offset(i, 0) = rs.Fields(0).Value
  31.      .Offset(i, 1) = rs.Fields(1).Value
  32.      .Offset(i, 2) = rs.Fields(2).Value
  33.      .Offset(i, 3) = rs.Fields(3).Value
  34.      rs.MoveNext
  35.      i = i + 1
  36.     Loop
  37.    End With
  38. GoTo En
  39. Ins:
  40.    rs.AddNew
  41.     rs.Fields(0) = "PQR"
  42.     rs.Fields(1) = 897
  43.     rs.Fields(2) = #11/20/2000#
  44.     rs.Fields(3) = True
  45.    rs.Update
  46. GoTo En
  47. Upd:
  48.    Do While Not rs.EOF
  49.     If CDate(rs.Fields(2).Value) = #11/20/2000# Then
  50.      rs.Fields(0) = "XYZ"
  51.      rs.Update
  52.     End If
  53.     rs.MoveNext
  54.    Loop
  55. GoTo En
  56. Del:
  57.    Do While Not rs.EOF
  58.     If CDate(rs.Fields(2).Value) = #11/20/2000# Then
  59.      rs.Delete
  60.     End If
  61.     rs.MoveNext
  62.    Loop
  63. En:
  64.   rs.Close
  65.  cn.Close
  66.  Set rs = Nothing
  67.  Set cmd = Nothing
  68.  Set cn = Nothing
  69. End Sub
図55

298行目「Set cn = CreateObject("ADODB.Connection")」でConnectionオブジェクトを生成、299行目「Set rs = CreateObject("ADODB.Recordset")」でRecordsetオブジェクトを生成、300行目「Set cn = CreateObject("ADODB.Command")」で、Commandオブジェクトを生成します。
302行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
305行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name」で、データベースであるExcelのファイル名を指定します。
308行目「cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"」で拡張プロパティを指定します。
311行目「cn.Open」で、データベースに接続します。
313行目「cmd.ActiveConnection = cn」は、接続中のConnectionオブジェクトをCommandオブジェクトのActiveConnectionに指定し、ConnectionとCommandを結び付けています。
316行目「SQL = "db$"」で、テーブル名(=Excelのシート名+$印)を変数SQLに代入します。
319行目「cmd.CommandText = SQL」では、CommandオブジェクトのCommandTextにテーブル名を指定しています。
322行目「rs.Open cmd, , 0, 2, 512」では、RecordsetオブジェクトのOpenメソッドを使ってレコードセットを取得しています。
第1パラメータには、313~319行目で準備をしたCommandオブジェクトを指定しています。
第2パラメータは通常はConnectionオブジェクトを指定するのですが、第1パラメータにCommandオブジェクトを指定した場合、重複してConnectionオブジェクトを指定してしまうとエラー(エラー内容:「Commandオブジェクトをソースに持つRecordsetオブジェクトのActiveConnectionプロパティを変更できません」)が発生しますので、省略とします。
第3~4パラメータは「0, 2」としていますが、これを省略(既定は CursorType=0、LockType=1)してしまうと「Select操作のみが可」となってしまいます。ですので、ここではCursorType=0、LockType=2(図37を参照下さい)としています。この組み合わせであれば、Accessの場合でも図34のように全操作が出来ますし、CSVでも図41のようにSelectとInsert操作が出来ます。
第5パラメータは、テーブル名指定なので「adCmdTableDirect(値=512)」を指定しています。なお、ここでは第1パラメータはテーブル名では無くCommandオブジェクトを指定していますが、CommandオブジェクトのCommandTextプロパティに対してテーブル名指定をしていますので、間接的にテーブル名指定という事になります。
なお、この512値の指定は、Excel・CSVでは必須ですが、Accessで指定しても問題はありません。
322行目によりレコードセットが得られたので、324~368行目でデータ処理をします。図55では4種の処理を324行目「GoTo Sel」で分岐させています。Selの部分を「Sel,Ins,Upd,Del」の4種で置き換える事で、Select操作・Insert操作・Update操作・Delete操作にジャンプさせています。
まずSelect処理は327~337行目です。内容は図53図54と全く同じで、Do~Loopを使いレコードセットの終端になるまで繰り返し、4列のデータをワークシートに書き込んでいます。
Insert処理は342~347行目です。まず342行目「rs.AddNew」で新たなレコードを作成します。カーソルは、この新たに作ったレコードの位置になります。
343行目「rs.Fields(0) = "PQR"」では、1列目に"PQR"という文字列をセットしています。344~346行目も同様に2~4列目にデータをセットしています。
各列へのセットが完了したら347行目「rs.Update」でデータベースを更新します。
Update処理は352~358行目です。Do~Loopで回しながら357行目「rs.MoveNext」で行を移動させ、全行を走査します。353行目「If CDate(rs.Fields(2).Value) = #11/20/2000# Then」で、3列目のデータが2000年11月20日のものを探し出し、見つかったら354行目「rs.Fields(0) = "XYZ"」で1列目のデータをXYZに書き換えます。
書き換えが終わったら、357行目の「rs.MoveNext」でカーソルが移動してしまう前に、355行目「rs.Update」でデータベースを更新します。
Delete処理は363~368行目です。Do~Loopで回しながら367行目「rs.MoveNext」で行を移動させ、全行を走査します。364行目「If CDate(rs.Fields(2).Value) = #11/20/2000# Then」で、3列目のデータが2000年11月20日のものを探し出し、見つかったら365行目「rs.Delete」でその行を削除します。なおDeleteの場合は、Updateメソッドを実行しないでも良いようです。
レコードセットの処理が完了したら、371行目「rs.Close」でレコードセットを閉じます。その後372行目「cn.Close」で、データベースとの接続を切ります。
なお、Excelは図37のように「CursorType=0 × LockType=2」の条件でもUpdateとDelete処理が出来ず、またCSVも図41のようにUpdateとDelete処理が出来ませんのでご注意下さい。

6ー1ー4.Recordsetでテーブル名を実行し、レコードセット取得後に処理

図50のNo.4のコードは、以下のようになります。
  1. '========== ⇩(12) Recordsetでテーブル名を実行しレコードセット取得 ============
  2. Sub Pattern04_Excel()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim rs As Object   '←Recordsetオブジェクト
  5.  Dim SQL As String   '←テーブル名、又はSQL文
  6.  Dim i As Integer   '←レコードの行位置
  7.  Set cn = CreateObject("ADODB.Connection")
  8.  Set rs = CreateObject("ADODB.Recordset")
  9.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  10. ' cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←①Access
  11.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name    '←②Excel
  12. ' cn.Properties("Data Source") = ThisWorkbook.Path    '←③CSV
  13.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"    '←④Excel
  14. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"    '←⑤CSV
  15.  cn.Open
  16. '  SQL = "TestTable"   '←⑥Access
  17.   SQL = "db$"     '←⑦Excel
  18. '  SQL = "its-041.csv"   '←⑧CSV
  19. '  rs.Open SQL, cn, 0, 2    '←⑨Access
  20.   rs.Open SQL, cn, 0, 2, 512    '←⑩Excel、CSV
  21.    GoTo Sel    'Sel,Ins,Upd,Del   ←Excel × Tableでは、Update処理・Delete処理はエラーが出ます。
  22. Sel:
  23.    With Sheet1.Range("B2")
  24.     .CurrentRegion.ClearContents
  25.     Do While Not rs.EOF
  26.      .Offset(i, 0) = rs.Fields(0).Value
  27.      .Offset(i, 1) = rs.Fields(1).Value
  28.      .Offset(i, 2) = rs.Fields(2).Value
  29.      .Offset(i, 3) = rs.Fields(3).Value
  30.      rs.MoveNext
  31.      i = i + 1
  32.     Loop
  33.    End With
  34. GoTo En
  35. Ins:
  36.    rs.AddNew
  37.     rs.Fields(0) = "PQR"
  38.     rs.Fields(1) = 897
  39.     rs.Fields(2) = #11/20/2000#
  40.     rs.Fields(3) = True
  41.    rs.Update
  42. GoTo En
  43. Upd:
  44.    Do While Not rs.EOF
  45.     If CDate(rs.Fields(2).Value) = #11/20/2000# Then
  46.      rs.Fields(0) = "XYZ"
  47.      rs.Update
  48.     End If
  49.     rs.MoveNext
  50.    Loop
  51. GoTo En
  52. Del:
  53.    Do While Not rs.EOF
  54.     If CDate(rs.Fields(2).Value) = #11/20/2000# Then
  55.      rs.Delete
  56.     End If
  57.     rs.MoveNext
  58.    Loop
  59. En:
  60.   rs.Close
  61.  cn.Close
  62.  Set rs = Nothing
  63.  Set cn = Nothing
  64. End Sub
図56

387行目「Set cn = CreateObject("ADODB.Connection")」で、Connectionオブジェクトを生成します。
388行目「Set rs = CreateObject("ADODB.Recordset")」で、Recordsetオブジェクトを生成します。
390行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
393行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name」で、データベースであるExcelのファイル名を指定します。
396行目「cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"」でExcelの拡張プロパティを指定します。
399行目「cn.Open」で、データベースに接続します。
402行目「SQL = "db$"」で、テーブル名(=Excelのシート名+$印)を変数SQLに代入します。
406行目「rs.Open SQL, cn, 0, 2, 512」では、RecordsetオブジェクトのOpenメソッドを使ってレコードセットを取得しています。
第1パラメータには、402行目で設定したテーブル名を指定します。
第2パラメータには、Connectionオブジェクトである変数cnを指定します。
第3~4パラメータは「0, 2」としていますが、これを省略(CursorType=0、LockType=1)すると「Select操作のみ」となってしまいます。ですので、ここではCursorType=0、LockType=2(図37を参照下さい)としています。この組み合わせであれば、ExcelではSelectとInsert処理が可能となります。またAccessの場合でも図34のように全操作が出来ますし、CSVでも図41のようにSelectとInsert操作が出来ます。
第5パラメータは、テーブル名指定なので「adCmdTableDirect(値=512)」を指定しています。
406行目によりレコードセットが得られたので、412~453行目でデータ処理をします。図56では4種の処理を408行目「GoTo Sel」で分岐させています。Selの部分を「Sel,Ins,Upd,Del」の4種で置き換える事で、Select操作・Insert操作・Update操作・Delete操作にジャンプさせています。
まずSelect処理は412~422行目です。Do~Loopを使いレコードセットの終端になるまで繰り返し、4列のデータをワークシートに書き込んでいます。
Insert処理は427~432行目です。427行目「rs.AddNew」で新たなレコードを作成し、428行目「rs.Fields(0) = "PQR"」で1列目に"PQR"という文字列をセットしています。429~431行目も同様に2~4列目にデータをセットしています。
各列にセットが完了したら432行目「rs.Update」でデータベースを更新します。
Update処理は437~443行目です。Do~Loopで回しながら442行目「rs.MoveNext」で行を移動させ、全行を走査します。438行目「If CDate(rs.Fields(2).Value) = #11/20/2000# Then」で、3列目のデータが2000年11月20日のものを探し出し、見つかったら439行目「rs.Fields(0) = "XYZ"」で1列目のデータをXYZに書き換えます。
書き換えが終わったら、442行目の「rs.MoveNext」でカーソルが移動してしまう前に、440行目「rs.Update」でデータベースを更新します。
Delete処理は448~453行目です。Do~Loopで回しながら452行目「rs.MoveNext」で行を移動させ、全行を走査します。449行目「If CDate(rs.Fields(2).Value) = #11/20/2000# Then」で、3列目のデータが2000年11月20日のものを探し出し、見つかったら450行目「rs.Delete」でその行を削除します。なおDeleteの場合は、Updateメソッドを実行しないでも良いようです。
レコードセットの処理が完了したら、456行目「rs.Close」でレコードセットを閉じます。その後457行目「cn.Close」で、データベースとの接続を切ります。
なお、Excelは図37のように「CursorType=0 × LockType=2」の条件ではUpdateとDelete処理が出来ず、またCSVも図41のようにUpdateとDelete処理が出来ませんのでご注意下さい。

6ー2.SQL(Select)文で操作

データベースに接続し、「SelectのSQL文」を操作するコードを以下で紹介します。
なお、Excelのシートデータベースについて説明しますが、以下のようにコードを切り替えることで、Access・CSVをデータベースの場合にすることが出来ます。丸番号は、図58図59図60図61で同じにしてあります。
Data SourceExtended PropertiesSQL文内のテーブル実行
Access① Accessファイル名⑥ テーブル名そのままOptionsパラメータは省略
Excel② Excelファイル名④ Excel 12.0 ・・・⑦ [シート名+$印]
CSV③ CSVファイルのフォルダー名⑤ Text ・・・⑧ [CSVファイル名]
図57

6ー2ー1.ConnectionでSQL文を実行しレコードセット取得

図50のNo.5のコードは、以下のようになります。
  1. '========== ⇩(13) ConnectionでSQL文を実行しレコードセット取得 ============
  2. Sub Pattern05()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim rs As Object   '←Recordsetオブジェクト
  5.  Dim SQL As String   '←テーブル名、又はSQL文
  6.  Dim i As Integer   '←レコードの行位置
  7.  Set cn = CreateObject("ADODB.Connection")
  8.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  9. ' cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←①Access
  10.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name    '←②Excel
  11. ' cn.Properties("Data Source") = ThisWorkbook.Path    '←③CSV
  12.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"    '←④Excel
  13. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"    '←⑤CSV
  14.  cn.Open
  15. '  SQL = "TestTable"   '←⑥Access
  16.   SQL = "[db$]"     '←⑦Excel
  17. '  SQL = "[its-041.csv]"   '←⑧CSV
  18.   SQL = "Select * from " & SQL
  19.   Set rs = cn.Execute(SQL)
  20.    With Sheet1.Range("B2")
  21.     .CurrentRegion.ClearContents
  22.     Do While Not rs.EOF
  23.      .Offset(i, 0) = rs.Fields(0).Value
  24.      .Offset(i, 1) = rs.Fields(1).Value
  25.      .Offset(i, 2) = rs.Fields(2).Value
  26.      .Offset(i, 3) = rs.Fields(3).Value
  27.      rs.MoveNext
  28.      i = i + 1
  29.     Loop
  30.    End With
  31.   rs.Close
  32.  cn.Close
  33.  Set rs = Nothing
  34.  Set cn = Nothing
  35. End Sub
図58

477行目「Set cn = CreateObject("ADODB.Connection")」で、Connectionオブジェクトを生成します。
479行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
482行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name」で、データベースであるExcelのファイル名を指定します。
485行目「cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"」でExcelの拡張プロパティを指定します。
488行目「cn.Open」で、データベースに接続します。
491行目「SQL = "[db$]"」で、テーブル名を一旦変数SQLに代入しますが、ここではSQL文内のテーブル名とするため、「Excelのシート名+$印 を角カッコで囲む」ようにします。なおCSVファイルの場合も同様に角カッコでCSVファイル名を囲む必要があります(Accessについては、テーブル名はそのまま)。
494行目「SQL = "Select * from " & SQL」で、実行するSQL文を組み立てます。
496行目「Set rs = cn.Execute(SQL)」では、右辺でConnectionオブジェクトのExecuteメソッドにSQL文を指定して実行させます。今回のSQL文は「Select ・・・」ですのでデータとしてレコードセットが戻されます。そのレコードセットを左辺の変数rsで受け取ることで、変数rsはRecordsetオブジェクトになります。この時点ではRecordsetは開かれた状態です。
そのレコードセットの処理が498~508行目になり、Do~Loopを使いレコードセットの終端になるまで繰り返し、4列のデータをワークシートに書き込んでいます。
処理が終了したら、510行目「rs.Close」でレコードセットを閉じます。Recordset.Openメソッドは実行していませんが、496行目を実行することにより変数rs(Recordsetオブジェクト)は開いていますので、処理終了後に閉じる必要があります。最後に511行目「cn.Close」で接続を閉じます。

6ー2ー2.CommandでSQL文を実行しレコードセット取得

図50のNo.6のコードは、以下のようになります。
  1. '========== ⇩(14) CommandでSQL文を実行しレコードセット取得 ============
  2. Sub Pattern06()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim rs As Object   '←Recordsetオブジェクト
  5.  Dim cmd As Object   '←Commandオブジェクト
  6.  Dim SQL As String   '←テーブル名、又はSQL文
  7.  Dim i As Integer   '←レコードの行位置
  8.  Set cn = CreateObject("ADODB.Connection")
  9.  Set cmd = CreateObject("ADODB.Command")
  10.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  11. ' cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←①Access
  12.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name    '←②Excel
  13. ' cn.Properties("Data Source") = ThisWorkbook.Path    '←③CSV
  14.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"    '←④Excel
  15. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"    '←⑤CSV
  16.  cn.Open
  17. '  SQL = "TestTable"   '←⑥Access
  18.   SQL = "[db$]"     '←⑦Excel
  19. '  SQL = "[its-041.csv]"   '←⑧CSV
  20.   SQL = "Select * from " & SQL
  21.   cmd.ActiveConnection = cn
  22.   cmd.CommandText = SQL
  23.   Set rs = cmd.Execute
  24.    With Sheet1.Range("B2")
  25.     .CurrentRegion.ClearContents
  26.     Do While Not rs.EOF
  27.      .Offset(i, 0) = rs.Fields(0).Value
  28.      .Offset(i, 1) = rs.Fields(1).Value
  29.      .Offset(i, 2) = rs.Fields(2).Value
  30.      .Offset(i, 3) = rs.Fields(3).Value
  31.      rs.MoveNext
  32.      i = i + 1
  33.     Loop
  34.    End With
  35.   rs.Close
  36.  cn.Close
  37.  Set rs = Nothing
  38.  Set cmd = Nothing
  39.  Set cn = Nothing
  40. End Sub
図59

528行目「Set cn = CreateObject("ADODB.Connection")」でConnectionオブジェクトを生成し、529行目「Set cmd = CreateObject("ADODB.Command")」でCommandオブジェクトを生成します。
531行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
534行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name」で、データベースであるExcelのファイル名を指定します。
537行目「cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"」でExcelの拡張プロパティを指定します。
540行目「cn.Open」で、データベースに接続します。
543行目「SQL = "[db$]"」で、テーブル名を一旦変数SQLに代入しますが、ここではSQL文内のテーブル名とするため、「Excelのシート名+$印 を角カッコで囲む」ようにします。なおCSVファイルの場合も同様に角カッコでCSVファイル名を囲む必要があります。
546行目「SQL = "Select * from " & SQL」で、実行するSQL文を組み立てます。
548行目「cmd.ActiveConnection = cn」は、接続中のConnectionオブジェクトをCommandオブジェクトのActiveConnectionに指定し、ConnectionとCommandを結び付けています。
549行目「cmd.CommandText = SQL」では、CommandオブジェクトのCommandTextにSQL文を指定しています。
551行目「Set rs = cmd.Execute」の右辺では、CommandオブジェクトのExecuteメソッドを実行し「ActiveConnectionプロパティに設定したデータベースに対し、CommandTextプロパティに設定したSQL文を実行」しています。そしてその戻り値であるレコードセットを左辺の変数rsに代入しています。
データのレコードセットが得られましたので、553~563行目で処理をしています。Do~Loopを使いレコードセットの終端になるまで繰り返し、4列のデータをワークシートに書き込みます。
処理が終了したら、565行目「rs.Close」でレコードセットを閉じます。Recordset.Openメソッドは実行していませんが、551行目を実行することにより変数rs(Recordsetオブジェクト)は開いていますので、処理終了後に閉じる必要があります。最後に566行目「cn.Close」で接続を閉じます。

6ー2ー3.CommandにSQL文を格納後Recordsetで取得

図50のNo.7のコードは、以下のようになります。
  1. '========== ⇩(15) ConnectionでSQL文を実行しレコードセット取得 ============
  2. Sub Pattern07()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim rs As Object   '←Recordsetオブジェクト
  5.  Dim cmd As Object   '←Commandオブジェクト
  6.  Dim SQL As String   '←テーブル名、又はSQL文
  7.  Dim i As Integer   '←レコードの行位置
  8.  Set cn = CreateObject("ADODB.Connection")
  9.  Set rs = CreateObject("ADODB.Recordset")
  10.  Set cmd = CreateObject("ADODB.Command")
  11.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  12. ' cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←①Access
  13.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name    '←②Excel
  14. ' cn.Properties("Data Source") = ThisWorkbook.Path    '←③CSV
  15.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"    '←④Excel
  16. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"    '←⑤CSV
  17.  cn.Open
  18. '  SQL = "TestTable"   '←⑥Access
  19.   SQL = "[db$]"     '←⑦Excel
  20. '  SQL = "[its-041.csv]"   '←⑧CSV
  21.   SQL = "Select * from " & SQL
  22.   cmd.ActiveConnection = cn
  23.   cmd.CommandText = SQL
  24.   rs.Open cmd
  25.    With Sheet1.Range("B2")
  26.     .CurrentRegion.ClearContents
  27.     Do While Not rs.EOF
  28.      .Offset(i, 0) = rs.Fields(0).Value
  29.      .Offset(i, 1) = rs.Fields(1).Value
  30.      .Offset(i, 2) = rs.Fields(2).Value
  31.      .Offset(i, 3) = rs.Fields(3).Value
  32.      rs.MoveNext
  33.      i = i + 1
  34.     Loop
  35.    End With
  36.   rs.Close
  37.  cn.Close
  38.  Set rs = Nothing
  39.  Set cmd = Nothing
  40.  Set cn = Nothing
  41. End Sub
図60

588行目「Set cn = CreateObject("ADODB.Connection")」でConnectionオブジェクトを生成し、589行目「Set rs = CreateObject("ADODB.Recordset")」でRecordsetオブジェクトを生成。また590行目「Set cmd = CreateObject("ADODB.Command")」でCommandオブジェクトを生成します。
592行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
595行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name」で、データベースであるExcelのファイル名を指定します。
598行目「cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"」でExcelの拡張プロパティを指定します。
601行目「cn.Open」で、データベースに接続します。
604行目「SQL = "[db$]"」で、テーブル名を一旦変数SQLに代入しますが、ここではSQL文内のテーブル名とするため、「Excelのシート名+$印 を角カッコで囲む」ようにします。なおCSVファイルの場合も同様に角カッコでCSVファイル名を囲む必要があります。
607行目「SQL = "Select * from " & SQL」で、実行するSQL文を組み立てます。
609行目「cmd.ActiveConnection = cn」は、接続中のConnectionオブジェクトをCommandオブジェクトのActiveConnectionに指定し、ConnectionとCommandを結び付けています。
610行目「cmd.CommandText = SQL」では、CommandオブジェクトのCommandTextにSQL文を指定しています。
612行目「rs.Open cmd」では、RecordsetオブジェクトのOpenメソッドを実行しています。第1パラメータに609~610行目で情報を格納したCommandオブジェクトを指定しています。
データのレコードセットが得られましたので、614~624行目で処理をしています。Do~Loopを使いレコードセットの終端になるまで繰り返し、4列のデータをワークシートに書き込みます。
処理が終了したら、626行目「rs.Close」でレコードセットを閉じ、627行目「cn.Close」で接続を閉じます。

6ー2ー4.Recordsetに直接SQL文を指定しレコードセット取得

図50のNo.8のコードは、以下のようになります。
  1. '========== ⇩(16) Recordsetに直接SQL文を指定しレコードセット取得 ============
  2. Sub Pattern08()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim rs As Object   '←Recordsetオブジェクト
  5.  Dim SQL As String   '←テーブル名、又はSQL文
  6.  Dim i As Integer   '←レコードの行位置
  7.  Set cn = CreateObject("ADODB.Connection")
  8.  Set rs = CreateObject("ADODB.Recordset")
  9.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  10. ' cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←①Access
  11.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name    '←②Excel
  12. ' cn.Properties("Data Source") = ThisWorkbook.Path    '←③CSV
  13.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"    '←④Excel
  14. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"    '←⑤CSV
  15.  cn.Open
  16. '  SQL = "TestTable"   '←⑥Access
  17.   SQL = "[db$]"     '←⑦Excel
  18. '  SQL = "[its-041.csv]"   '←⑧CSV
  19.   SQL = "Select * from " & SQL
  20.   rs.Open SQL, cn
  21.    With Sheet1.Range("B2")
  22.     .CurrentRegion.ClearContents
  23.     Do While Not rs.EOF
  24.      .Offset(i, 0) = rs.Fields(0).Value
  25.      .Offset(i, 1) = rs.Fields(1).Value
  26.      .Offset(i, 2) = rs.Fields(2).Value
  27.      .Offset(i, 3) = rs.Fields(3).Value
  28.      rs.MoveNext
  29.      i = i + 1
  30.     Loop
  31.    End With
  32.   rs.Close
  33.  cn.Close
  34.  Set rs = Nothing
  35.  Set cn = Nothing
  36. End Sub
図61

647行目「Set cn = CreateObject("ADODB.Connection")」でConnectionオブジェクトを生成し、648行目「Set rs = CreateObject("ADODB.Recordset")」でRecordsetオブジェクトを生成します。
650行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
653行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name」で、データベースであるExcelのファイル名を指定します。
656行目「cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"」でExcelの拡張プロパティを指定します。
659行目「cn.Open」で、データベースに接続します。
662行目「SQL = "[db$]"」で、テーブル名を一旦変数SQLに代入しますが、ここではSQL文内のテーブル名とするため、「Excelのシート名+$印 を角カッコで囲む」ようにします。なおCSVファイルの場合も同様に角カッコでCSVファイル名を囲む必要があります。
665行目「SQL = "Select * from " & SQL」で、実行するSQL文を組み立てます。
667行目「rs.Open SQL, cn」では、RecordsetオブジェクトのOpenメソッドを実行しています。第1パラメータには665行目で作成したSQL文を、第2パラメータには接続しているConnectionオブジェクト(変数cn)を指定します。
データのレコードセットが得られましたので、669~679行目で処理をしています。Do~Loopを使いレコードセットの終端になるまで繰り返し、4列のデータをワークシートに書き込みます。
処理が終了したら、681行目「rs.Close」でレコードセットを閉じ、682行目「cn.Close」で接続を閉じます。

6ー3.SQL(Insert等)文で操作

データベースに接続し、「Insertなどのデータを変更させるSQL文」を操作するコードを以下で紹介します。
なお、Excelのシートデータベースについて説明しますが、以下のようにコードを切り替えることで、Access・CSVをデータベースの場合にすることが出来ます。また、SQL文をInsert・Update・Deleteで切り替える事で異なる処理が可能です。
なお丸番号は、図63図64図65図66で同じにしてあります。
Data SourceExtended PropertiesSQL文内のテーブルSQL文
Access① Accessファイル名⑥ テーブル名そのまま⑪ Insert文
⑫ Update文
⑬ Delete文
Excel② Excelファイル名④ Excel 12.0 ・・・⑦ [シート名+$印]⑪ Insert文
⑫ Update文
CSV③ CSVファイルのフォルダー名⑤ Text ・・・⑧ [CSVファイル名]⑪ Insert文
図62

6ー3ー1.ConnectionでSQL文を実行しデータ変更

図50のNo.9のコードは、以下のようになります。
  1. '========== ⇩(17) ConnectionでSQL文を実行しデータ変更 ============
  2. Sub Pattern09()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim SQL As String   '←テーブル名、又はSQL文
  5.  Set cn = CreateObject("ADODB.Connection")
  6.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  7. ' cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←①Access
  8.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name    '←②Excel
  9. ' cn.Properties("Data Source") = ThisWorkbook.Path    '←③CSV
  10.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"    '←④Excel
  11. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"    '←⑤CSV
  12.  cn.Open
  13. '  SQL = "TestTable"   '←⑥Access
  14.   SQL = "[db$]"     '←⑦Excel
  15. '  SQL = "[its-041.csv]"   '←⑧CSV
  16.   SQL = "Insert into " & SQL & " (st,nu,dt,bl) values ('pqr',897,#11/20/2000#,true)"    '←⑪Insert文
  17. '  SQL = "update " & SQL & " set St='XYZ' where DT=#2000/11/20#"    '←⑫Update文
  18. '  SQL = "Delete from " & SQL & " where dt=#11/20/2000#"   '←⑬Delete文
  19.   cn.Execute SQL
  20.  cn.Close
  21.  Set cn = Nothing
  22. End Sub
図63

695行目「Set cn = CreateObject("ADODB.Connection")」でConnectionオブジェクトを生成します。
697行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
700行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name」で、データベースであるExcelのファイル名を指定します。
703行目「cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"」でExcelの拡張プロパティを指定します。
706行目「cn.Open」で、データベースに接続します。
709行目「SQL = "[db$]"」で、テーブル名を一旦変数SQLに代入します。
712行目「SQL = "Insert into " & SQL & " (st,nu,dt,bl) values ('pqr',897,#11/20/2000#,true)"」で、Insert文を組み立てています。
716行目「cn.Execute SQL」では、ConnectionオブジェクトのExecuteメソッドで、第1パラメータに指定した「データ変更用のSQL文」を実行します。
実行終了したら、718行目「cn.Close」で接続を閉じます。

6ー3ー2.CommandでSQL文を実行しデータ変更

図50のNo.10のコードは、以下のようになります。
  1. '========== ⇩(18) CommandでSQL文を実行しデータ変更 ============
  2. Sub Pattern10()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim cmd As Object   '←Commandオブジェクト
  5.  Dim SQL As String   '←テーブル名、又はSQL文
  6.  Set cn = CreateObject("ADODB.Connection")
  7.  Set cmd = CreateObject("ADODB.Command")
  8.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  9. ' cn.Properties("Data Source") = ThisWorkbook.Path & "\" & "its-041.accdb"   '←①Access
  10.  cn.Properties("Data Source") = ThisWorkbook.Path & "\" & ThisWorkbook.Name    '←②Excel
  11. ' cn.Properties("Data Source") = ThisWorkbook.Path    '←③CSV
  12.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"    '←④Excel
  13. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"    '←⑤CSV
  14.  cn.Open
  15. '  SQL = "TestTable"   '←⑥Access
  16.   SQL = "[db$]"     '←⑦Excel
  17. '  SQL = "[its-041.csv]"   '←⑧CSV
  18.   SQL = "Insert into " & SQL & " (st,nu,dt,bl) values ('pqr',897,#11/20/2000#,true)"    '←⑪Insert文
  19. '  SQL = "update " & SQL & " set St='XYZ' where DT=#2000/11/20#"    '←⑫Update文
  20. '  SQL = "Delete from " & SQL & " where dt=#11/20/2000#"   '←⑬Delete文
  21.   cmd.ActiveConnection = cn
  22.   cmd.CommandText = SQL
  23.   cmd.Execute
  24.  cn.Close
  25.  Set cmd = Nothing
  26.  Set cn = Nothing
  27. End Sub
図64

736行目「Set cn = CreateObject("ADODB.Connection")」でConnectionオブジェクトを生成し、737行目「Set cmd = CreateObject("ADODB.Command")」でCommandオブジェクトを生成します。
739行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
742行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name」で、データベースであるExcelのファイル名を指定します。
745行目「cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"」でExcelの拡張プロパティを指定します。
748行目「cn.Open」で、データベースに接続します。
751「SQL = "[db$]"」で、テーブル名を一旦変数SQLに代入します。
754行目「SQL = "Insert into " & SQL & " (st,nu,dt,bl) values ('pqr',897,#11/20/2000#,true)"」で、Insert文を組み立てています。
758行目「cmd.ActiveConnection = cn」は、接続中のConnectionオブジェクトをCommandオブジェクトのActiveConnectionに指定し、ConnectionとCommandを結び付けています。
759行目「cmd.CommandText = SQL」では、CommandオブジェクトのCommandTextにSQL文を指定しています。
761行目「cmd.Execute」で、CommandオブジェクトのExecuteメソッドを実行し「ActiveConnectionプロパティに設定したデータベースに対し、CommandTextプロパティに設定したSQL文を実行」しています。
実行終了したら、763行目「cn.Close」で接続を閉じます。

6ー3ー3.CommandにSQL文を格納後Recordsetで実行しデータ変更

図50のNo.11のコードは、以下のようになります。
  1. '========== ⇩(19) CommandにSQL文を格納後Recordsetで実行しデータ変更 ============
  2. Sub Pattern11()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim rs As Object   '←Recordsetオブジェクト
  5.  Dim cmd As Object   '←Commandオブジェクト
  6.  Dim SQL As String   '←テーブル名、又はSQL文
  7.  Set cn = CreateObject("ADODB.Connection")
  8.  Set rs = CreateObject("ADODB.Recordset")
  9.  Set cmd = CreateObject("ADODB.Command")
  10.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  11. ' cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←①Access
  12.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name    '←②Excel
  13. ' cn.Properties("Data Source") = ThisWorkbook.Path    '←③CSV
  14.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"    '←④Excel
  15. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"    '←⑤CSV
  16.  cn.Open
  17. '  SQL = "TestTable"   '←⑥Access
  18.   SQL = "[db$]"     '←⑦Excel
  19. '  SQL = "[its-041.csv]"   '←⑧CSV
  20.   SQL = "Insert into " & SQL & " (st,nu,dt,bl) values ('pqr',897,#11/20/2000#,true)"    '←⑪Insert文
  21. '  SQL = "update " & SQL & " set St='XYZ' where DT=#2000/11/20#"    '←⑫Update文
  22. '  SQL = "Delete from " & SQL & " where dt=#11/20/2000#"   '←⑬Delete文
  23.   cmd.ActiveConnection = cn
  24.   cmd.CommandText = SQL
  25.   rs.Open cmd
  26.  cn.Close
  27.  Set rs = Nothing
  28.  Set cmd = Nothing
  29.  Set cn = Nothing
  30. End Sub
図65

777行目「Set cn = CreateObject("ADODB.Connection")」でConnectionオブジェクトを生成し、778行目「Set rs = CreateObject("ADODB.Recordset")」でRecordsetオブジェクトを生成。779行目「Set cmd = CreateObject("ADODB.Command")」でCommandオブジェクトを生成します。
781行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
784行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name」で、データベースであるExcelのファイル名を指定します。
787行目「cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"」でExcelの拡張プロパティを指定します。
790行目「cn.Open」で、データベースに接続します。
793行目「SQL = "[db$]"」で、テーブル名を一旦変数SQLに代入します。
796行目「SQL = "Insert into " & SQL & " (st,nu,dt,bl) values ('pqr',897,#11/20/2000#,true)"」で、Insert文を組み立てています。
800行目「cmd.ActiveConnection = cn」は、接続中のConnectionオブジェクトをCommandオブジェクトのActiveConnectionに指定し、ConnectionとCommandを結び付けています。
801行目「cmd.CommandText = SQL」では、CommandオブジェクトのCommandTextにSQL文を指定しています。
803行目「rs.Open cmd」では、RecordsetオブジェクトのOpenメソッドの第1パラメータにCommandオブジェクトを指定して実行しています。この時、第2パラメータは省略します。
この803行目は「ActiveConnectionプロパティに設定したデータベースに対し、CommandTextプロパティに設定したSQL文を実行」している事になります。
実行が完了したら、805行目「cn.Close」でデータベース接続を閉じます。
なお、データ変更用のSQL文(Insert、Update、Delete)をRecordset.Openで実行した時は「Recordset.Closeは実行しない」ことに注意ください。このデータ変更SQLを実行した直後には、RecordsetオブジェクトのStateプロパティがゼロ(=レコードセットは閉じられている)となり、更に「Recordset.Close を実行してしまうと、エラーが発生」します。

6ー3ー4.SQL文を直接ecordsetで実行しデータ変更

図50のNo.12のコードは、以下のようになります。
  1. '========== ⇩(20) SQL文を直接ecordsetで実行しデータ変更 ============
  2. Sub Pattern12()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim rs As Object   '←Recordsetオブジェクト
  5.  Dim SQL As String   '←テーブル名、又はSQL文
  6.  Set cn = CreateObject("ADODB.Connection")
  7.  Set rs = CreateObject("ADODB.Recordset")
  8.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  9. ' cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←①Access
  10.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name    '←②Excel
  11. ' cn.Properties("Data Source") = ThisWorkbook.Path    '←③CSV
  12.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"    '←④Excel
  13. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"    '←⑤CSV
  14.  cn.Open
  15. '  SQL = "TestTable"   '←⑥Access
  16.   SQL = "[db$]"     '←⑦Excel
  17. '  SQL = "[its-041.csv]"   '←⑧CSV
  18.   SQL = "Insert into " & SQL & " (st,nu,dt,bl) values ('pqr',897,#11/20/2000#,true)"    '←⑪Insert文
  19. '  SQL = "update " & SQL & " set St='XYZ' where DT=#2000/11/20#"    '←⑫Update文
  20. '  SQL = "Delete from " & SQL & " where dt=#11/20/2000#"   '←⑬Delete文
  21.   rs.Open SQL, cn
  22.  cn.Close
  23.  Set rs = Nothing
  24.  Set cn = Nothing
  25. End Sub
図66

826行目「Set cn = CreateObject("ADODB.Connection")」でConnectionオブジェクトを生成し、827行目「Set rs = CreateObject("ADODB.Recordset")」でRecordsetオブジェクトを生成します。
829行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
832行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name」で、データベースであるExcelのファイル名を指定します。
835行目「cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"」でExcelの拡張プロパティを指定します。
838行目「cn.Open」で、データベースに接続します。
841行目「SQL = "[db$]"」で、テーブル名を一旦変数SQLに代入します。
844行目「SQL = "Insert into " & SQL & " (st,nu,dt,bl) values ('pqr',897,#11/20/2000#,true)"」で、Insert文を組み立てています。
848行目「rs.Open SQL, cn」で、RecordsetオブジェクトのOpenメソッドの第1パラメータにSQL文を指定し、第2パラメータに接続中のConnectionオブジェクト(変数cn)を指定することで、データベースに対してデータ変更処理を行います。
実行が完了したら、850行目「cn.Close」でデータベース接続を閉じます。
なお、データ変更用のSQL文(Insert、Update、Delete)をRecordset.Openで実行した時は「Recordset.Closeは実行しない」ことに注意ください。このデータ変更SQLを実行した直後には、RecordsetオブジェクトのStateプロパティがゼロ(=レコードセットは閉じられている)となり、更に「Recordset.Close を実行してしまうと、エラーが発生」します。

7.データの一括処理

上記で紹介した「レコードセットを取得し、ワークシートにデータを書き出す」コードは、レコードセットをDo~Loopで「1レコード単位」で取り出して処理する手法でした。それとは異なる方法で「全データを一括で取り出す」事も可能です。
一括で取り出すには、RecordsetオブジェクトのGetRowsメソッドを使用します。構文としては以下になります。
 配列 = Recordset.GetRows( Rows, Start, Fields)
戻り値は「インデックスがゼロ始まりの二次元配列」です。指定できるパラメータは以下の3つで、全て省略可です。
パラメータ内容
Rows省略可取り出す行数
既定=現カーソル位置 or Start指定位置から最終行まで
Start省略可取り出し開始のブックマーク
既定=現カーソル位置
Fields省略可取り出し列番号、又は列名
既定=全列
図67

第1パラメータのRowsは、GetRowsで取り出す行数を指定します。Recordset.Open直後のカーソル位置は先頭行にありますので、「省略すれば全行」が取り出せることになります。
なお取り出し行を「1」行に指定し、取り出した2次元配列をTranspose関数等で行列逆転させると「1次元配列」のデータとなりますので注意が必要です。
第2パラメータのStartは、ブックマーク文字列、又は図68の値を指定します。省略(=adBookmarkCurrent(値=0))すると、現在のカーソル位置となります。
定数内容
adBookmarkCurrent0現レコードから開始
adBookmarkFirst1最初のレコードから開始
adBookmarkLast2最後のレコードから開始
図68

Microsoftや他サイトでも図68のような説明が載っているのですが、しかし試してみると既定のゼロ以外ではエラー(エラー内容:Recordsetはブックマークをサポートしていない)が発生してしまいます。Recordset.Openメソッドを使い、第3パラメータ(CursorType)を調整してみたのですが同じエラーが出るようです。
また、レコードセットへのブックマーク方法までは今回調べ切れず、ブックマーク文字列については今回省略しますが、上記のようなエラー内容から考えると、第2パラメータは「ACE・Jetプロバイダーでは使えない」のかもしれません。
第3パラメータのFieldsは、列番号(先頭列=ゼロ)または列名(文字列)で指定します。省略すると、全列を出力します。
なお、複数列に限って出力したい場合は「Array(2,3)」のように配列の形で指定することで可能です。この例の場合は3列目+4列目を出力せよ という意味になります。
GetRowsメソッドを使って出力したデータは「行列が逆転した配列」になります。もちろんTransposeメソッドで行列を回転させる事は可能ですが、要素内に「Nullが入っているとエラー」が発生するので注意が必要です。また1行しか取得できなかった場合にTransposeで回転させると、二次元配列が一次元配列に変わってしまうので工夫が必要です。
図53のコード(1行ずつ出力処理)をGetRowsで一括処理するのが、以下のコードになります。
  1. '========== ⇩(21) GetRowsでまとめてデータ取得 ============
  2. Sub Pattern13()
  3.  Dim cn As Object   '←Connectionオブジェクト
  4.  Dim rs As Object   '←Recordsetオブジェクト
  5.  Dim SQL As String   '←テーブル名、又はSQL文
  6.  Dim GR As Variant   '←データ配列
  7.  Set cn = CreateObject("ADODB.Connection")
  8.  cn.Provider = "Microsoft.ACE.OLEDB.12.0"
  9. ' cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & "its-041.accdb"   '←①Access
  10.  cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name   '←②Excel
  11. ' cn.Properties("Data Source") = ThisWorkbook.Path   '←③CSV
  12.  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"   '←④Excel
  13. ' cn.Properties("Extended Properties") = "Text;HDR=Yes;IMEX=0;"   '←⑤CSV
  14.  cn.Open
  15. '  SQL = "TestTable"   '←⑥Access
  16.   SQL = "db$"   '←⑦Excel
  17. '  SQL = "its-041.csv"   '←⑧CSV
  18. '  Set rs = cn.Execute(SQL)   '←⑨Access
  19.   Set rs = cn.Execute(SQL, , 512)   '←⑩Excel、CSV
  20.    With Sheet1.Range("B2")
  21.     .CurrentRegion.ClearContents
  22.     GR = rs.GetRows
  23.     GR = WorksheetFunction.Transpose(GR)
  24.     .Resize(UBound(GR, 1), UBound(GR, 2)) = GR
  25.    End With
  26.   rs.Close
  27.  cn.Close
  28.  Set rs = Nothing
  29.  Set cn = Nothing
  30. End Sub
図69

867行目「Set cn = CreateObject("ADODB.Connection")」で、Connectionオブジェクトを生成します。
869行目「cn.Provider = "Microsoft.ACE.OLEDB.12.0"」で、ACEプロバイダを設定します。
872行目「cn.Properties("Data Source") = ThisWorkbook.Path & "¥" & ThisWorkbook.Name」で、Excelのシートデータベースを指定します。
875行目「cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=0;"」で、拡張プロパティの指定をします。
878行目「cn.Open」で、データベースに接続します。
881行目「SQL = "db$"」で、テーブル名として「Excelのシート名+$印」を変数SQLに代入します。
885行目「Set rs = cn.Execute(SQL, , 512)」の右辺では、ConnectionオブジェクトのExecuteメソッドでテーブル名を実行します。この時に第3パラメータには「Excel、CSVをテーブルとして読み込むためのadCmdTableDirect(値=512)」を設定します。
第3パラメータへの値512の設定は、Excel+テーブル、CSV+テーブルの場合は必須ですが、Access+テーブルの場合に設定しても問題はありません。
この実行によりテーブルの全データ(レコードセット)が取得できますので、左辺の変数rsに代入します。なお、この段階では、レコードセットのカーソル(操作できる行位置)は、先頭行にあります。
887~892行目では、取得したレコードセットの全データをワークシート上に書き出しています。
887行目「With Sheet1.Range("B2")」では、シートへのデータ書き出しの基準点を決めています。
888行目「.CurrentRegion.ClearContents」は、その基準点を含むエリアに書かれていたデータをクリアします。
889行目「GR = rs.GetRows」では、(カーソルは先頭にあるので)レコードセットの全データを取得し、変数GRに代入しています。この段階での配列GRは、行列逆転した状態で、且つ配列インデックスはゼロ始まりです。
890行目「GR = WorksheetFunction.Transpose(GR)」では、Transpose関数で行列を逆にし、いわゆる正しい行列方向にデータ変換しています。また配列インデックスも1始まりに変換されます(取得したデータ行が1行分の場合は、Transposeにより二次元配列→一次元配列 になります)。
891行目「.Resize(UBound(GR, 1), UBound(GR, 2)) = GR」では、貼り付けサイズを配列と同じサイズにしてから、配列データを貼り付けています。(1行しか取得できなかった場合は、ここでエラー(UBound(GR, 2)が無い)が出ます)
894行目「rs.Close」でレコードセットを閉じ、895行目「cn.Close」で接続を閉じます。
なお他のパターンでも、同様にGetRowsを使い一括処理を行うことが可能です。

アプリ実例・関連する項目

ExcelシートDBとSQLを使った会議室予約システム
ExcelシートDBとSQLを使った倉庫管理システム
共有資料の登録と閲覧ができるサーバーシステム
複数の備品を同時予約可能な貸出台帳
Accessデータベースを使用した売上台帳
設備の稼働状態を入力し、グラフで確認
ExcelからAccessデータベースを作成・操作

サンプルファイル

ADOでAccess・Excel・CSVへ接続・操作(JET・ACEプロバイダ編)(its-042.xlsm)
Accessデータファイル(its-041.accdb)
CSVデータファイル(its-041.csv)
セキュリティ向上を目的として「インターネット経由でダウンロードしたOfficeファイル(Excel等)のマクロは、既定でブロック」されるようにOfficeアプリケーションの既定動作が変更になりました。(2022年4月より切替開始)
解除の方法については「ダウンロードファイルのブロック解除方法」を参照下さい。