★★★★★★Access2000VBA・Excel2000VBA独学~★★★★★★ 超重要!!!『 SQL の学習用 』 ★★★★★★~ ODBCでQueryTableオブジェクトを自動作成するサンプルコード)。多分、2000以降の全バージョンで使えると思います。~ついでに、セルの値で結果表示を自動で切り替える「パラメータクエリ」のVBAでの自動作成も。~
  
※まだ書きかけです。すみません。
※間違ってたらすみません。
※メモ書きなので、自分でも意味不明な箇所も多いです。ごめんなさい。
  
目次
 ★ はじめに
 ★ サンプルのダウンロード:サンプルのExcelファイルについて
 ★ サンプルのイミディエイトウィンドウでの「外部ファイルの全てのシート名の取得」について
 ★ ExcelでのSQL文の「方言」についての概要
 ★ SQLのことがまだよくわからない方が「SQLをのVBAコードをできるだけ素早く書く」ための方法
 ★ プログラムについてのその他の重要な説明
 ★ パラメータクエリのVBAでの自動作成方法
   ▼ 何もない状態からのパラメータクエリの作り方の大すじ
     ※パラメータ用のセルを作る場所について
   ▼ パラメータクエリができてからの操作について
 ★ パラメータクエリをVBAで自動作成するプログラム例
   ▼ 「すでに作成されたQueryTableオブジェクト」に対して、パラメータを作成する例3つ
    (1個、2個、3個のパラメータの場合の例)
   ◎ パラメータが1つだけの場合
   ◎ パラメータが2つの場合
   ◎ パラメータが3つの場合
   ▼ そもそも「QueryTableオブジェクト自体」が作ってない場合のパラメータクエリの自動作成のプログラム例
   ◎ 1つめ:パラメータ呼び出し元プロシージャ(2010でテストして動きました。)
   ◎ 2つめ:呼び出されるプロシージャ(とりあえずこのサンプルプログラムでは、こちら側でパラメータを作ります。こっちらも2010で動きました。)
※Shift+TABキー、もしくは、Homeキー、Homeキー+TAB数回、を押すと、目次付近に戻れます。
  
  

※補足
「ODBC」とは、「ODBC接続」のことで、Microsoft Query の操作で使われる「データのソースに対する」、「データの接続方式」です。Microsoft Query の操作をマクロ記録すると、ODBCでの接続のコードが自動生成されます。
「データの接続方式」には、「ODBC」形式以外に、「OLEDB」形式もあります。
ADOやDAOなどを使う時は、「OLEDB」形式のほうが多いのではないかと思います。
「ODBC」では、OSの機能の「ODBCデータソース」という機能を使うと、テキストファイルなどもSQLを使って読むことができます。(単純な「テキストインポート」の機能ではSQLを使いながら吸い込むことができません。)

※本記事はあくまでも、読み込む先のシートが1シートにつき1つの表で、かつ、リスト形式=データベース形式の表=動的な表となっていることが前提です。

============
以下、本文です。

★ はじめに

一応、SQLを学習できる小さなプログラムを作ってみました。

このプログラムは、「VBAが上達したい」「集計をもっと簡単にやりたい」という、「独立したばっかり」の、まだ「資金の少ない方」の目線、そういう方向けに一番に書きました。

でも、もちろん、チームや部署単位で効率化したい、プログラミングやSQL自体を学んで、「Excelと電卓の延長としてだけではなく、真のコンピュータ、真のデータ管理機能、として使いたい」という方向けでもあります。

そういう方々にも是非、読んで、実際に、SQLを試して持てほしいです。

PowerPivot(パワーピボット)、PowerQuery(パワークエリ)、リレーション機能、テーブル機能、といった、比較的新しい機能とかなり似たようなことができ、でも、自動化しやすくて扱いも簡単なケースも少なくないため、それらの新しい機能とともに、より、選択肢が増えると思います。

「ループがあれば大丈夫」「ループだけがあれば怖いものない」という「誤った考え方ばかりを強要されて教わってきてしまった方」にも是非!!!
  

逆に、コスパアップ目線・コスパアップ意識がもともと無い方や、「時間」を「もったいない」と思わない、くさるほど時間のある方、資金が有り余っている方は、基本、今すぐには読まなくても大丈夫です。
ただ、そういう方であっても、いつかは読んでいただき、「SQL」や「MicrosoftQuery」「QueryTableオブジェクト」の便利さを知っていただけたらな・・・、と思います。
  

なお、特に、プロのExcelVBA講師の方々は是非もっとSQLのことを広めてほしいなと思います。

子供たちの未来はあなたがたにかかっているのですから。

  
  

★ サンプルのダウンロード:サンプルのExcelファイルについて

バージョン2010で作り、動作は2000と2010で確認を行いました。
もちろん、「完全」ではなく「テキトーです。」
すべてのバージョンでチェックはしてないので、エラーが出たらご自分で治すか、分かる方に直してもらってください。
でも、SQLの学習やVBAの基本の学習などには、意外と便利に使えると思います。
※あくまでも、読み込む先のシートが1シートにつき1つの表で、かつ、リスト形式=データベース形式の表=動的な表となっていることが前提です。

以下の「サンプルのダウンロード」、のリンクからダウンロードできます。
ウィルスチェックはESETでやりました。

サンプルのダウンロード

解凍するとxlsとxlsmが1個ずつ入っています。
「xls拡張子」のほうは2000~2003用
「xlsm拡張子」のほうは2007以降用
です。

あと、「5.xls」も入っています。
「5.xls」はデータの読み書きテスト用のブックです。
「Sheet1」のシートモジュールに書いてあるプログラムで「D:\1」フォルダを作成してから、その中に置いてテストしてみてください。
もちろん、好きなフォルダに入れてもOKですので、その際は、プログラムの中の読み込み先のパス(「s_TrgFNm001jj = "D:\1\5.xls"」)の部分を書き換えてください。

「xls拡張子」と「xlsm拡張子」は、
両方とも、10枚のシートがあらかじめ作ってあり、各シートのオブジェクト名(=CodeNameプロパティで取得できる名前)を、「Sheet01」「Sheet02」「Sheet03」・・・・のように、前ゼロを付けたオブジェクト名に変えてありますのでそこだけ要注意です。(プロジェクトウィンドウ内でのシートの並び順の関係で前ゼロを付けました。)
特に、『 ご自分でプログラムを一部修正したり・機能追加等々をするとき・かつ・CodeNameプロパティを使いたいとき 』、「だけ」は、注意してください。

ただ、一般的な「Worksheets("シート名")という使い方自体は、通常通りにおこなえます。

また、以降でお示しするプログラムがすべてのシートモジュールと標準モジュールに、修正すべきところは修正して、セットしてあります。

ですので、すぐに・・・、

・「VBA+ODBC+QueryTableオブジェクト」での、
・「SQLを使った複雑な条件での絞込や集計・リレーション」も「同時にやりながら」の、
・「閉じた外部ファイルからのシートデータの吸い込み」、

・・・が試せます。

なお、「xls拡張子(2000~2003用)」、「xlsm拡張子(2007以降用)」、両者ともに、プログラム内容は「まったく同じ」です。
それぞれにとっての「独自」のコードは、一切、在りません。

そして、パワークエリ(Power Query)、
パワーピボット(Power Pivot)、
リレーションシップ機能、などの新しい・かつ・似たことができる機能たち、

「よりも」、

・「便利・手軽」で、かつ、
・「高速」で、かつ、
・「汎用的」傾向にあり、「今の知識をそのまま利用できる人も少なくなく」、かつ、
・「VBAとも相性良く簡単にリレーションなどを自動化でき、」、かつ、
・表が「テーブル機能」でテーブル化されていなくてもリレーション可能、かつ、
・何枚の表でも、5枚でも6枚でも、簡単にドラッグ一発、あるいは、十数文字の記述でリレーション可能、かつ、
・テキストファイルなども簡単に扱え、
・ぶっちゃけ集計やリストアップの自動化をしたいなら、新しい機能たちよりも便利、

・・・・ですので、そういった「パワークエリ」等々の新しい機能たちとの違いを理解し、お互いが活かせる場面を探すのにも是非、使ってほしいと思います。

  
  
★ サンプルのイミディエイトウィンドウでの「外部ファイルの全てのシート名の取得」について

※こちらも、あくまでも、読み込む先のシートが1シートにつき1つの表で、かつ、リスト形式=データベース形式の表=動的な表となっていることが前提です。
  
  
サンプルファイルでは、「外部ファイルの全てのシート名の取得(=調査)」ができます。

調べ方は、イミディエイトウィンドウにて

? sn("Excelファイルのフルパス")

と入力してEnterします。

例えば「D:\1\5.xlsx」というファイルの場合、

? sn("D:\1\5.xlsx")

と入力してEnterします。(この「sn」は、「SheetName」の略としました。)

すると、そのままイミディエイトウィンドウの次の行から、そのExcelファイルのすべてのシートの名前(名前定義?の名前も含む)を列挙してくれます。

同様に、(ダウンロードできるサンプルファイルにはまだsn2プロシージャを追加してないので)、sn2のプロシージャ内容を標準モジュールに追加したのちに、

? sn2("D:\1\5.xlsx")
(「2」が増えただけ)

とやると、テーブル名とともに、列名もイミディエイトウィンドウに一覧表示されます。

SQLを書くときなどに参考として使えます。

xlsm、xlsx、xls、が調査の対象となります。
  
  
ただ、列名まではわかりませんので、列名は、『 SELECT * FROM [シート名$] 』というSQL文でいったんテーブルを吸い込んで、その結果の表の列名を見て、そんな形で調べてみてください。

※2021/02/04 追記
 サンプルでもブック内の全てのシートの、「列名」もわかるようにしました。
 サンプル内に、「sn2」というプログラムを追加しました。
 「? sn2("調査対象のブックのフルパス")」というかたちでイミディエイトで
 調べてみて下さい。
 ついでに、INSERT や UPDATE でエラーになってたので、それもエラーに
 ならないようにしておきました。

※補足
Excelの場合は、シート名(=テーブル名)はバッククォートで囲んでもいいし角カッコで囲んでもどちらでもOKです。ただし、「$」は必ずつけます。ODBCデータソースなどを使って、テキストファイルをSQLを使って吸い込みたいような場合は、テーブル名に「$」は要りません。


ワークシート全体:Select * from [Sheet1$]
名前なしセル範囲:Select * from [Sheet1$A2:E10]
名前付きセル範囲:Select * from 範囲名
(   ↑「範囲名」というのは「名前の定義」機能で付けた名前のことです。)

  
  
★ ExcelでのSQL文の「方言」についての概要

SQL文」という命令文は、「Microsoft Query」の画面や、「VBA」の画面で書くことができます。

MicrosoftQueryの画面のSQL画面(=SQLダイアログ=SQLビュー)では、「SQL文」という命令文を書くときには、縦に、句ごとや列名ごと、演算子?ごと(論理演算子や集合演算子など)、等々で、改行しても動きます。

命令文だからと言って、横にぶわーっとつなげて書かなくてもいいのです。

例えば、「( 」だけ、とか「 )」だけ、とか、「カッコ1個だけで1行使ってもダイジョブ」です。ただし、空白行は入れてはいけません。

一方、Microsoft Queryの画面以外では、VBAプログラムで「SQL文」という命令文を書けます。
どちらかというとこちらで書くことのほうが多いかもしれませんが、こちらで書くときには、変数を使って、縦に書いて、「&」でつなげていくとわかりやすいと思います。

例えば以下のように。

変数 = ""
変数 = 変数 & "SELECT "
変数 = 変数 & "    列名01"
変数 = 変数 & "    ,列名02"
変数 = 変数 & "    ,列名03"
変数 = 変数 & "    ,列名04"
変数 = 変数 & " FROM"
変数 = 変数 & "    テーブル名A INNER JOIN テーブル名B"
変数 = 変数 & "    ON テーブル名A.列名 = テーブル名B.列名"
変数 = 変数 & " WHERE"
変数 = 変数 & "    テーブル名A.列名 = '条件値';"

(※ExcelでのSQLの場合では、多くの場合は、「テーブル名」は「シート名に$記号を付けたモノ」になります。またテーブル名は角カッコ・または・バッククォートで囲む必要があります。)

(※上記のSQL文はHTMLのせいで表示に全角スペースを使ってしまってますので、「コピペ利用」「しないで」下さい。SQLでは命令語句や列名などの区切りに全角スペースを使うとエラーになりますので。)

このとき、句と句、演算子と演算子、列名と列名、などの間には、「半角でなら」「スペースをどんだけ入れてもOK!」です。
「全角のスペースはエラーになるのは」普通 通りです。
MicrosoftQueryの画面の「SQLダイアログ(SQLビュー)」では、上記の、変数や & 、""、などを取っ払った感じで、縦に改行して命令できます。

Excelの場合は、シート名(=テーブル名)はバッククォートで囲んでもいいし角カッコで囲んでもどちらでもOKです。ただ、いずれかで囲まないと基本、エラーになります。
特にFROM句は絶対にそれらでの囲みが要りますが、他の句では要らない場合もあるようです。ご自分でも試してみてください。(このへん、ちょっとわかりません。僕のPCが、現在、2010と2019が共存なのでそれでおかしくなっているのかもしれません。)

なお、Excelシートの場合は、テーブル名には「$」が必ず必要です。
これも、つけないとエラーになります。
また、AccessからExcelシートをSQLで参照する時も、「$」は必要だったように思います。
ODBCデータソースなどを使って、テキストファイルをSQLを使って吸い込みたいような場合は、テーブル名に「$」は要りません。

あと、VBAの場合、「変数 = 変数 & "××××××××××××××"」みたいな形態で書くことが多いです。
一応、「半角スペース+_ (アンダーバー)」で改行して書くこともできますが、その書き方の場合に限っては文字数に(数百文字までという)限界があってどこかでエラーになるに決まってて面倒くさいですし、そもそも、文が完成するまでいちいちエラーになるのでさらに面倒くさいため、僕は「変数 = 変数 & "××××××××××××××"」を使います。
短い命令文を書くなら「半角スペース+_ (アンダーバー)」で改行してもいいんですが、もう変数を毎行で書くほうがいろいろ付けたしや修正もしやすいし、それでやっています。
でも、基本自由なので、お好きな方で。。。

SELECT句などのFROM句以外では、「テーブル名.列名」のように「テーブル名をつける」、ということが要らず、「列名」だけを書いてもOKな場合も多いです。特に1つのテーブルしか扱っていないときなどは要りませんので、そういうのは普通と同じです。
なお、「テーブル名.列名」のように書くときは、テーブル名にはもちろん「$」が必要です。バッククォートや角カッコは要らない場合もあるかもしれません。うろ覚えですみません。また、できる場合とできない場合があります。

それから、「Microsoft Queryの画面・限定」ですが、自動生成されたSQL文をどこかにテキストファイルにバックアップしておいて、別のMicrosoft Queryの画面を表示した時に、(テーブルがまったく同じなら)そのとっておいたSQL文をSQLビューにコピペすると、クエリデザインの画面が再現されます。つまり、ドラッグや条件値の入力をまたやり直さなくてもいいのです。
これは、Accessの「クエリ」でもまったく同じことができます。

Microsoft QueryでのSQL操作では、次回開いた時にSQLがリセットされて消えてしまうこともあるのですが、そのとき、逐一、いちいち、SQL文をテキストファイルにバックアップしておくと、それを書き戻しさえすれば、クエリデザイングリッドの元々の状態が、「再現が一瞬で終わる」ので、かなりラクちんです。

VBAでSQL命令を書くときは、シートのモジュールに(コメントアウトして)メモしておいてもいいと思います。変数丸ごと。

ExcelでのSQLの場合、その「テーブル名」には「Sheet1!A1:F10」みたいな範囲指定や、「名前定義の名前」なども使えたかと思います。(うろ覚えです。すみません。)→と思ったらWebにありました!→『 Excelファイルに接続(ADO)
以下、引用。
ワークシート全体:Select * from [Sheet1$]
名前なしセル範囲:Select * from [Sheet1$A2:E10]
名前付きセル範囲:Select * from 範囲名
(↑3つ目の「範囲名」というのが「名前の定義」機能で付けた名前のことです)

ワイルドカードは % や _ などで、一般的なようです。(Accessは特殊で * や ? を使います。)

ASでの別名は使えます。(列名、テーブル名、ともに)

ASを使った結果、シート上に結果表示がなされたときに、その列名にシングルコーテーションが付加されてしまう場合は、ASの列名か、その内容の数式等々かいずれかを角カッコで囲むと正常にシングルコーテーション無しで表示された気がします(うろおぼえですみません。)

副問い合わせ(サブクエリ)も使えます。

「Case文」は使えないので、「Switch関数」?で代用する必要があります。
(これは、AccessのMDBでのSQLと同じです。)

SQL内でもVBAのInteractionオブジェクトのメンバの関数の一部は、「SQL文の中で直接」使えるもようです。「Switch関数」「IIF関数」「Choose関数」などです。
が、もちろん、SQL文の外で普通のVBA関数や変数を使って、SQL文に「&」を使って、混ぜて、結合してSQL文を作成していくことも可能です。

それから、Excelの場合、すごく不思議なんですが、SQL文の最後につける「;(セミコロン)」はExcelの場合はなぜか不要です。もちろんつけてもいいです。
ただ、あえて付けたほうがいい場合とあえて付けないほうがいい場合(特に、1つのSQLで、VBA側だけでなくMicrosoftQueryの画面での操作も可能にしたい場合など)があります。2007以降のMicrosoftQuery(結果がListObjectに埋め込まれたQueryTableオブジェクトになるケース)だけかもしれませんが・・・。
関連記事はこちら→『 ★★★Access2000VBA・Excel2000VBA独学~「QueryTableオブジェクト」~~「VBAプログラム」からも、「MicrosoftQueryの画面」からも操作が可能となる、そのための「VBAからのSQLの書き方」や「前提条件」など(概要説明のみ)~

  
  

SQLのことがまだよくわからない方が「SQLをのVBAコードをできるだけ素早く書く」ための方法

MicrosoftQueryの画面の「SQLビュー」には、横にぶわーっとつながったSQL文が自動生成されます。(Accessの「クエリ」も同じです。)
ドラッグでリレーションしたり、条件入力をして完了すると、その作業がずべてSQL命令に自動変換されて、SQLビューに表示できるようになります。

SQLのことがまだよくわからないうちは、このSQLビューに自動生成されたSQL文を活用します。

というのも・・・、Microsoft Queryで自動生成されたSQLをそのままVBAプログラムにペッタンコして流用すると、「あまり意味がわからなくてもSQL命令文が実行できてしまう」からです。

もちろん、いずれは、というか、少しずつ、自力でSQL文がかけるようになることが必要ですが、でも、はじめのうちは(特に独学の場合は)先生もおらずやはり不安です。
そのような中では、慣れるまで、「Microsoft Query」がある意味「先生」になってくれますので、自動生成されたSQL文をどういう意味なのかを探りつつ、そのまえに、まずはプログラムとして動くようにしてしまいます。

やり方としては以降のような感じです。

まず、Microsoft Queryで自動生成されたSQL文を、句ごとや演算子ごと(論理演算子や集合演算子など)、列名ごとなどで改行します。

それは、TeraPadやメモ帳などのテキストエディタで「置換」メニューによって、1~3回の操作で完了させます。Wordでもできます。手作業で1行ずつ改行しなくても一瞬で改行が終わるのでラクちんです。(僕はいつもTeraPadを使っています。)

MicrosoftQueryのSQLビューのSQL文は、Accessのクエリの場合と同じで、あまり切れ目がないのでぱっと見、文字だらけでわけがわからないと思いますが、TeraPadなどのテキストエディタやWordなどで・・・、

・「, 」(=カンマと半角スペース)を
  「半角スペース+カンマ+半角スペース+改行コード」に置換、とか、

・「AND 」(=ANDと半角スペース)を
  「半角スペース+AND+半角スペース+改行コード」に置換とか、

そういった処理をすると、縦方向にすこし見やすくなるのです。
(あえて半角スペースを前につけて置換するのは、SQLとしてのエラーが出ないようにするためです。いつか意味がわかると思います。)

たとえば以下のような横につながったSQL文があったとします。
  
  
SELECT 列名01 ,列名02 ,列名03 ,列名04 ,列名05
FROM テーブル名A INNER JOIN テーブル名B ON テーブル名A.列名 = テーブル名B.列名
WHERE テーブル名A.列名 = '条件値';

(※ExcelでのSQLの場合では、多くの場合は、「テーブル名」は「シート名に$記号を付けたモノ」になります。またテーブル名は角カッコ・または・バッククォートで囲む必要があります。)
  
  
これは短い例なので、文字列が右端までいっていませんが、通常は「切れ目のない文字の海」が何行も延々と続く・・・というイメージになります。

で、まず最初に、それをTeraPadやメモ帳などの「置換」機能を使って、一発変換を(条件を変えつつ)、2、3回繰り返し、以下のような状態にします。
  
  
SELECT 列名01
,列名02
,列名03
,列名04
,列名05
FROM テーブル名A INNER JOIN テーブル名B
ON テーブル名A.列名 = テーブル名B.列名
WHERE テーブル名A.列名 = '条件値';

(※ExcelでのSQLの場合では、多くの場合は、「テーブル名」は「シート名に$記号を付けたモノ」になります。またテーブル名は角カッコ・または・バッククォートで囲む必要があります。)
  
  
で、これをもう少し整形して以下のような感じにします。
  
  
SELECT
     列名01
     ,列名02
     ,列名03
     ,列名04
     ,列名05
FROM
    テーブル名A INNER JOIN テーブル名B
    ON テーブル名A.列名 = テーブル名B.列名
WHERE
    テーブル名A.列名 = '条件値';

(※ExcelでのSQLの場合では、多くの場合は、「テーブル名」は「シート名に$記号を付けたモノ」になります。またテーブル名は角カッコ・または・バッククォートで囲む必要があります。)
  
  
で、最終的には、これに変数部分をくっつけて・・・
  
  
変数 = 変数 & "SELECT "
変数 = 変数 & "    列名01"
変数 = 変数 & "    ,列名02"
変数 = 変数 & "    ,列名03"
変数 = 変数 & "    ,列名04"
変数 = 変数 & " FROM"
変数 = 変数 & "    テーブル名A INNER JOIN テーブル名B"
変数 = 変数 & "    ON テーブル名A.列名 = テーブル名B.列名"
変数 = 変数 & " WHERE"
変数 = 変数 & "    テーブル名A.列名 = '条件値';"

(※ExcelでのSQLの場合では、多くの場合は、「テーブル名」は「シート名に$記号を付けたモノ」になります。またテーブル名は角カッコ・または・バッククォートで囲む必要があります。)
  
  
・・・という感じになるように、
「"」と「" 」のあいだに、1行ずつコピぺしていけばOKです。(スペースも。)
自動的に「変数 = 変数 & " 」や 終わりの「"」をくっつけるプログラムを作れば一瞬で終わります。

(※上記のSQL文はHTMLのせいで表示に全角スペースを使ってしまってますので、「コピペ利用」「しないで」下さい。SQLでは命令語句や列名などの区切りに全角スペースを使うとエラーになりますので。)
  

このとき、
「SELECT」で列を特定し、
「WHERE」で行を特定しています。
「FROM」は「データを取り出す表」の、その「範囲」です。

もう少し普通の言い方をすると、

「FROM」に書かれた表の範囲から、
「SELECT」で列を特定し、
「WHERE」で行を特定して「仮想表」を生成します。

複数行 × 複数列、なら、「表範囲」が特定されるイメージで、
1行 × 1列、なら「1つのセル」が特定されるイメージ・・・、
という感じです。

基本、「FROM」のところでは、「1つの表」だけではなく、
「複数の表」を範囲として指定することもできます。

その際、「VLOOKUP関数での表と表の紐つけ」のような「リレーション(リレーションシップ」という作業も行えます。(バージョン2016などで使える「リレーションシップ機能」と同じ機能です。商用利用としてはExcel以外の製品において30年前からある機能で、Excelにはバージョン2000の前、97でも使えてました。もっと前から使えていたかもしれません。)

なお、「FROM」のところでは、2つの表だけでなく、5つでも6つでも、複数の表を簡単にリレーション(=横結合)することができます。

以上は、SQLの意味がさほどわからなくても、できます。

単純に・・・・、
「変数 = 変数 & "××××××××××" 」の、「 " 」と「 " 」のあいだ(=つまり、「××××××××××」のところ)に、1行ずつコピペしてしまえばいいのです。
(このとき、SQL文を何も触らないように気を付けます。
 句と列名やテーブル名の間のスペースがなくなるとエラーになってしまうので。)

なお、SQL文内でWHERE条件などの中で「文字列」の意味を表す場合は、「"」ではなくて「'」を使います。
(=ダブルクォーテーションではなくて、シングルクォーテーションを使います。)
なので、「"」(ダブルのほう)を複数個、連ねて記述する必要はありません。

あと、ExcelのSQLの場合は、「ワイルドカード(置き換え文字)」は「*」ではなく「%」になります。(=アスタリスクではなくパーセント記号です。)
これはAccessの場合と異なりますが、「%」のほうが一般的で、Accessのほうが特殊です。

そういった意味で、MicrosoftQuery は、SQLの勉強のお供になります。

※ちなみにですが、MicrosoftQueryのSQLビューでも、半角スペースはどんだけ使ってもOKです。
なので、以下のようにテキストファイルで書いておいて、それをSQLビューにコピペしても、SQLは実行できます。(もちろん、スペースは全部半角です。先頭に必ず半角スーペースを入れておけばエラーになることもありません。

SELECT
     列名01
    ,列名02
FROM
    テーブル名A INNER JOIN テーブル名B
    ON テーブル名A.列名 = テーブル名B.列名
WHERE
    テーブル名A.列名 = '条件値';

(※ExcelでのSQLの場合では、多くの場合は、「テーブル名」は「シート名に$記号を付けたモノ」になります。またテーブル名は角カッコ・または・バッククォートで囲む必要があります。)

これはAccessのクエリのSQLビューでも同じです。
(※上記のSQL文はHTMLのせいで表示に全角スペースを使ってしまってますので、「コピペ利用」「しないで」下さい。SQLでは命令語句や列名などの区切りに全角スペースを使うとエラーになりますので。)
  

ちなみにですが、上記のSQLの、
「 テーブル名A INNER JOIN テーブル名B
  ON テーブル名A.列名 = テーブル名B.列名 」
という部分の意味は、
・テーブル名Aとテーブル名Bを、
・テーブル名Aの側の「列名」の列と、
・テーブル名Bの側の「列名」の列とで、
・INNER JOIN(=「内部結合」)する、
という意味です。

「内部結合」とは、
「AとB、両方の ” 列 ” に存在する値を含む ” 行 ” だけ、を、お互いに横に結合する」・・・、
というイメージです。

ちょうど、Vlookup関数で行うような2つの表の紐付けと同じようなことですが、ただ、VLookup関数のように、「紐付けした列の右側しか参照できない」などの制限はありません。
紐付けした列の右でも左でも、参照、あるいは表示させることができます。

  
  
★ プログラムについてのその他の重要な説明

サンプルなので動かなかったらごめんなさい。

すでにシート上にQueryTableオブジェクトがある場合は、
(a)QueryTableオブジェクトのSQL内容だけを更新する方法と、
(b)あってもなくてもいったんそのQueryTableオブジェクトを削除してから新設する方法
の2つが考えられると思いますが、とりあえず後者を選びました。

理由は、大きくは2つあります。

1つ目は、QueryTableオブジェクトを作成した自ファイルをも「覗きに行きたい」・・・、つまり、「自ファイル1つで完結したい」、、、、、、「自ファイル1つで」多段的にSQL文で条件絞り込みや条件付き集計をしたい・・・・というときがあります。
それは、「かなり複雑な条件」のときに解決策のひとつとして、とても助けになります。
(複雑なループのプログラムを書かなくて済む!!!!!!!!!!!からです。)

で、その場合、自ファイルの格納場所が変わってしまうと、「ソースのファイルが見つかりせん。」といった旨のエラーになることがあります。
それをできるだけ回避したいので、いったん削除して新設するほうを選んでしまいました。
QueryTableオブジェクトの内容更新だけでも可能かもしれませんが、何か面倒くさいことがあるといけないので、とりあえず、いったん削除して新設するほうを、「とりあえず」選んでしまいました。(もし必要なら、そういうSQLの内容変更と更新をするだけのプログラムの方が、多分考えることが少なくて簡単な気がしますので、ご自分でも作ることにチャレンジしてみてください。)

2つ目は、QueryTableオブジェクトを生成すると、名前の定義にもそれに紐ついた定義設定が勝手に追加されるのですが、そちらもある程度、QueryTableオブジェクトの内容によって連動して名前が書き換わったほうがいいかなと思い、とりあえずそうしました。
もちろん、名前の定義自体を単独で操作できるなら(a)の方法でもOKだと思いますが、下手にいじるとQueryTableオブジェクトが壊れそうな雰囲気だったので、知識不足でとりあえずやめました。
名前の定義の名前が、セル範囲はそのままに名前だけリネームできればもしかしたらいいのかもしれませんが・・・。ちょっと調査不足でよくわかりません。

※とりあえず、QueryTableオブジェクトを消してないのに、同名の名前定義を消すと、そのQueryTableオブジェクトは機能しなくなります。名前定義の名前を変えても同じ現象が起こるかもしれません。未確認ですのでご自分でも試してみてください。

また、どのソースにも対応する汎用的なQueryTableオブジェクトを作るときは、(名前の定義の名前なんてどうでもいいので)そういうことを考えることは不要かもしれませんが、このサンプルでは、とりあえず、考えてしまいました。

あと、QueryTableオブジェクトが作成されている時、そのSQL内容だけを変えて、「更新」することも可能です。ただ、その場合、QueryTableオブジェクトの名前と名前定義の名前も、その内容にみあったものに変えないと、「1つのファイル=自ファイルの中で」、多段的に・ネスト/入れ子的にSQLをかけていくときに戸惑うことがあるので、それも一応見越して、このサンプルでは、とりあえず、(b)の「QueryTableオブジェクトを削除してから新設する方法」をとってしまいました。
  
  

・・・というわけで、、人によっては色々と作り変えなどが必要かとは思います。

また、完全に作りこんでいるわけではないので、どんなバグが潜んでいるかはわかりません。
エラーが出たらご自分でご解決ください。
あるいは、分かる方に解決してもらってください。

自ファイルを覗きにいって、自ファイルのデータに対してQueryTableを作った場合、
で、かつ、
『 生成した「QueryTableオブジェクト」の結果表にて「Microsoft Queryの画面」を使いたい 』
という場合は、1つめのQueryTableの場合は大丈夫です。
それができます。
右クリックメニューの「クエリの編集」より、「Microsoft Queryの画面」を使ってSQL文の内容を再編集できます。
しかし、2つめのQueryTableオブジェクト以降は、生成されたQueryTableから『 右クリック操作にて「Microsoft Queryの画面」を使おうとした場合 』、「認識できません」的なエラーとなり、起動できませんでした。(もしかしたら、これも、僕のPCは2010と2019を混在させてるのが原因でエラーになるのかもしれません。ご自分のPCでも試してみてください。)

これは基本的には、2010でも、2000でも同じっぽいです。(でも、ほぼ未検証)

(※OSがWin2000やWin98で、Excelが2000の組み合わせだと、これは起こりません。いくらでも多段階に自ファイルを覗けます。XPだとSP3になると多分ダメです。SP2までは良かった気がします。ただ、いずれも自ファイルをMicrosoftQueryで覗くときは動作が遅いですが・・・。VBAだけなら高速です。)

なので、XP+Excel2000以降で、QueryTableオブジェクトにおいて、自ファイルを読みに行ったり、多段階なものを作りたいときは・・・・、

・VBA+ODBCや、
・VBA+OLEDB

・・・・などでQueryTableオブジェクトを作るしか方法がなさそうです。(いずれもSQLを使えます。)

でも、そのとき、まだ不慣れな方の場合、SQLを生成するのに、MicrosoftQueryは役立つと思います。
1段階だけなら自ファイルでもエラー無くMicrosoftQueryの画面が使えるようですので。
(バージョン違いのExcelを複数インストールしてあると、それも使えないかもしれませんが・・・)

SQLがExcelで使えると、「複雑な条件での集計やリストアップ」に限っては、(ループしなくていいので)「無駄なワークシート関数や無駄なVBAプログラム」がかなり減ると思いますので、是非、この機会に、SQLやQueryTableオブジェクトの操作に興味をもってみてください。

では以下、サンプルプログラムです。
  
  
(01) 各シートモジュールにコピペするコード

「test01」というプロシージャにて、SQLを使って外部のデータ(シート)を読み込めます。
SQLを使うので、もちろん、『 複数のシートをリレーションさせて集計やグループ化等々をしたもの 』を吸い込めます。
吸い込んだ際には、自動的に、名前の定義に、QueryTableオブジェクトと同じ名前の名前定義(Nameオブジェクト)が新設されます。

「QTDell01」というプロシージャでは、その読み込んだデータ(QueryTableオブジェクト)を削除します。2010でのテストでは、もともと「QueryTableオブジェクト」を削除すると連動して名前定義も消えますが、2000などでは残ってしまうのでそれを強制的に削除するようにしています。
なお、QueryTableオブジェクトを手動で削除する場合は、事前に表を右クリックして、「データ範囲プロパティ」にて「名前」を調べます。その後、列丸ごととか、行丸ごとを削除します。そして同じ名前の名前の定義も削除します。
でないと、名前の定義での名前が増えすぎて、自ファイルをネスト的・入れ子的にSQLをかけるときに難しくなってしまいますのでご注意ください。

  

【おおざっぱな使い方】

▼ 00:上記コードを、すべてのシートのシートモジュールにコピペします。
(ダウンロードしたサンプルファイルは、10枚のシートがあらかじめ作ってあり、この処理がしてあります。※ただ、Sheet1のオブジェクト名を「Sheet01」のように、前ゼロを付けたオブジェクト名にに変えてありますのでそこだけ要注意です。)

01:結果表示したいシートのシートモジュールを開きます。
例えばSheet1のモジュールを開きます。
※サンプルだと「Sheet01(Sheet1)」というモジュールです。

▼ 02:外部ファイルを覗きにいきたいときは、test01() のプログラムにて、「★設定部」のところで、「'他ファイルデータの吸込み用設定」のところの4行分を書き換えます。
自ファイルのシートを覗きにいきたいときは、前述の部分・4行分をコメントアウトし、「'自ファイルデータの吸込み用設定」の4行のほうをコメントアウトをはずします。

どのように書き換えたらいいかは、コメントや今書かれている内容などを見ればすぐにわかると思います。

▼ 03:「s_ChkQTobjNm01jj = "QTSht01_Imp_"」の行で、吸い込み結果の表(QueryTableオブジェクト)につけたい名前を設定します。「Sht01」の部分を、今開いているシートモジュールにひもついたシートがわかるような名前、あるいは、「Imp」以降をSQL内容が自分である程度思い起こせそうな短い内容で、それを名前に変えるといいと思います。

▼ 04:イミディエイトウィンドウにて、覗きに行きたいファイルのシート名や列名を調べます。
(やりかたは『 ★ サンプルのイミディエイトウィンドウでの「外部ファイルの全てのシート名の取得」について 』にて前述してあります。)
シート名だけ調べたいときは、
? sn("調べたいファイルの絶対パス")、
列名も調べたいときは
? sn2("調べたいファイルの絶対パス")、 ※「sn」に「2」を付けただけです
で調べられます。

※なお、数十万件もあるExcelファイルを覗きにいく(調べに行く)ときは、結果が出るまで十数秒か数十秒、あるいは数分、かかります。

▼ 05:最後に、「s_SqlStr01jj = "SELECT * FROM `Sheet1$`"」の行を書きかえます。
一番簡単なのは、「Sheet1$」の部分(バッククォート残す)を、前項の04:で調べたテーブル名(=シート名)にしてみます。

▼ 06:普通にF5キーなどでVBA(test01)を実行します。

SQL内容は色々と試し、コメントアウトなどでモジュール内にメモして残しておきます。
  
  
'★設定部

'他ファイルデータの吸込み用設定
s_TrgFNm001jj = "D:\1\5.xls" '外部の、吸い込みたい先のファイル
s_TrgFoldPath001jj = "D:\1" 'そのファイルが在るフォルダ
Set o_ImpSht001jj = Worksheets("Sheet1") '今のファイルの中の、QTオブジェクトを生成したいシート(オブジェクト)
s_ImpCelAddr001jj = "$A$1" 'そのシートのQTオブジェクトを生成したいセル位置

' '自ファイルデータの吸込み用設定
' s_TrgFNm001jj = ThisWorkbook.FullName '外部の、吸い込みたい先のファイル
' s_TrgFoldPath001jj = ThisWorkbook.Path 'そのファイルが在るフォルダ
' Set o_ImpSht001jj = Worksheets("Sheet1") '今のファイルの中の、QTオブジェクトを生成したいシート(オブジェクト)
' s_ImpCelAddr001jj = "$A$1"

  
  
(02)標準モジュールにコピペするコード
コピペだけします。
「部品」としてのプログラムなので特に何もしません。

  
  
  
★ パラメータクエリのVBAでの自動作成方法

パラメータクエリを作成したい場合は、SQL文の条件に半角の「?」を使います。
「(列名 Like ?)」とか「(列名 = ?)」「(列名 Between ? And ?)」とか、そんな形で使います。
(この「(列名 Like ?)」とか「(列名 = ?)」というのを「節」と呼ぶようです。ヘルプに書いてありました。)

複数のパラメータを使いたいときは、その数だけ「?」を使います。
パラメータの順番は先に書いたものから順番に、1、2、3、・・・・となります。

もう少し具体的に書くと、「?」を書いた順番に・・・、

ActiveSheet.QueryTables(1).Parameters(1)
ActiveSheet.QueryTables(1).Parameters(2)
ActiveSheet.QueryTables(1).Parameters(3)
  ・
  ・
  ・
・・・・と続いて作られていく・・・・という意味です。
「Between」などでは「?」を2つ使いますが、その中でも1つ目、2つ目、というかたちになります。

作ったパラメータは、実際のQueryTableオブジェクトでは、
QueryTableオブジェクトの右クリック→「パラメーター」でGUI画面で確認することができます。

なお、パラメータクエリは、格納場所を変えると壊れるかもしれません。
その際は、またSQLを使って
  
  

================================

▼ 何もない状態からのパラメータクエリの作り方の大すじ

例えば、以下のようなSQLを作ったとします。

  strSql01 = ""
  strSql01 = strSql01 & "SELECT * "
  strSql01 = strSql01 & " FROM Sheet1$ Sheet1$"
  strSql01 = strSql01 & " WHERE ( 顧客ID=? ) AND ( 単価>=? );"

この場合(演算子等々にかかわらず、とにかく)、「?」が2つあるので、「パラメータを2つ作りたい」、という意味になります。

で、以降が、その際の、パラメータの作り方と、パラメータの値の入力方法の設定です。
以降のプログラムの例だと、以下のような設定となります。

・「顧客ID」のパラメータを「param1」で作り、
 「J1」セルを入力箇所に設定+自動更新可能にする。

・「単価」のパラメータを「param2」で作り、
 「J2」セルを入力箇所に設定+自動更新可能にする。
  

なお、以下のなかで、「Qt_MeQtbl01」はすでに作成された空のQueryTableオブジェクトです。

また、パラメータを作成する前に、必ず、「?」を含むSQL文を、QueryTableオブジェクトにセットしておきます。
「s_SQLStr01 = "SELECT * FROM [Sheet1$] WHERE (列名 = ?)」
「qt.Sql = s_SQLStr01 」
みたいな形で。  

'1つめのパラメータの作成

Dim param1 As Parameter
Set param1 = Qt_MeQtbl01.Parameters.Add("prm1", xlParamTypeNumeric) '「数値型」のパラメータの作成
param1.SetParam xlRange, ActiveSheet.Range("J1") 'パラメータの入力箇所を「J1」セルとする。
'※Parameters.Addメソッドの第一引数の「 "prm1" 」は、作ったパラメータを特定するための名前です。
' この例なら「prm顧客ID」とか「顧客IDprm」とかにしてもとしてもOKです。
' また、「xlParamTypeNumeric」などのように、型の指定を正しくしないと
' エラーになります。
' 「?」の列のデータ型と必ず一致するように、ここは常に変えていかなくてはなりません。
  
'2つめのパラメータの作成

Dim param2 As Parameter
Set param2 = Qt_MeQtbl01.Parameters.Add("prm2", xlParamTypeNumeric)
param2.SetParam xlRange, ActiveSheet.Range("J2")
'※"prm2"も同様で、今回の例なら「prm単価」「単価prm」などとしてもOKです。

Qt_MeQtbl01.CommandText = vrtSql01 'SQL文を設定
Qt_MeQtbl01.Refresh 'SQL文の実行と反映

'セルパラメータの自動更新設定
'セルのパラメータの値を変更したと同時にクエリが自動更新されるようにする
'1回、QueryTableオブジェクトが作成されてRefreshされてからじゃないと
'エラーになる。

param1.RefreshOnChange = True
param2.RefreshOnChange = True
'ヘルプの事例は、すでに作成されたQueryTableオブジェクトに
'対してこの処理をしているか、Refesh前にやっている。
'本当にRefesh前にこの設定を入れても問題ないかは未確認。
'もしかしたら、エラーになるかもしれない。

=============
  
※パラメータ用のセルを作る場所について

本記事の例では、パラメータ用のセルをQueryTableオブジェクトを生成するシートと同じシートに作ってしまっていますが、できれば、パラメータのセルは、他のシートのセルにしたほうが無難かと思います。
でないと、QueryTableオブジェクトができたときに、パラメータ用のセルがQueryTableオブジェクトの範囲に上書きされたしまう可能性があるためです。また、生成されたQueryTableオブジェクトの結果に、さらにQueryTableオブジェクトをかけたい時に、パラメータ用のセルが原因で動作不良を起こすとも限りません。
未確認なので、ご自身でも一度試してみていただきたいのですが、そんな感じで、一応、本番ではパラメータ用のセルは別のシートに作ったほうがいいと思います。(パラメータセル専用のシートを設けるなどして。)
もちろん、「テスト段階」では同じシートに作ってもいいと思います。

  
  

▼ パラメータクエリができてからの操作について
  

'パラメータの個数の調査

? Worksheets("MsQRY吸込").QueryTables(1).Parameters.count
1
  

'パラメータの削除
'(パラメータの削除だけなので、QueryTableオブジェクトは残ります。

Worksheets("シート名").QueryTables(1).Parameters.delete

  
'パラメータのセルアドレスのチェック

? Worksheets("シート名").QueryTables(1).Parameters(1).SourceRange.Address
$F$3
$F$2
$F$2
  

'既に作成されたQueryTableオブジェクトの、
'パラメータのセルアドレス「だけ」の変更?・・・と思いきや、エラーでできませんでした。
' ↓ ※このプログラムは動きません。
Worksheets("シート名").QueryTables(1).Parameters(1).SourceRange.Address = "$F$3"

'それをやるには、ヘルプによると、以下のように.SetParamwメソッドだけを普通に使えばいいようです。
Worksheets("シート名").QueryTables(1).Parameters(1).SetParam xlRange, Range("J5")

'これはたとえば「G2」セルが1つ目のパラメータの入力セルだった場合に、それを「J5」セルに変更します。
'このとき、セルに値を中途半端に入れたり、型の違う値を入れたりするとエラーになることがありますが、OK、OK、してしまえば大丈夫です。そのあと正しい値をセルに入力してください。
'条件通りに、表が変化します。

なので、以降にあげた、「★ パラメータクエリをVBAで自動作成するプログラム例」でも、既存のQueryTableオブジェクトのパラメータのセル位置を変えたい場合は、「SQLを変えないでおいても」そのまま、このコードが使えます。

  
  

=============

'以下、色々とテスト。イミディエイトウィンドウにて。

? qt.Parameters(1).SourceRange.Address
$F$2

qt.Parameters(1).SourceRange.Address = "$F$3"

? Worksheets("MsQRY吸込").QueryTables(1).name
ExternalData_1
1
1
SELECT Sheet1$.連番, Sheet1$.顧客ID, Sheet1$.数量, Sheet1$.単価
FROM Sheet1$ Sheet1$
WHERE (Sheet1$.顧客ID=?)

? Worksheets("MsQRY吸込").QueryTables.item(1).PostText

================

  
  

★ パラメータクエリをVBAで自動作成するプログラム例

このプログラムの内容を、冒頭のダウンロードサンプルに追加してもよいと思います。
独立したプログラムにして、いったん作成されたクエリに対して、SQLの更新とともにおこなうようにすればいいと思います。
既存のプログラムの「プロシージャ内」に組み込むとすごく面倒くさいことになる気がしますので・・・。

是非、ご自分でもチャレンジしてみてください。
  

※本記事のここでのサンプルでは、「セルの値」をパラメータの値にする方法(xlRange)をとっています。(「XlParameterType 列挙」の「xlRange」。)

が、VBAのインプットボックス(Inputbox関数)の戻り値(指定しないと数字も文字列型)を使うやりかたなどもあるようです。
本記事のサンプルができあがってから、少し調べてみたら、以下のURLのような記事が見つかりました。
https://www.moug.net/tech/exvba/0060038.html
このWebページのサンプルでは、「type:=xlConstant(xlConstant=1= 引数 Value により指定された値を使用します。)」を使って、単純に、Inputbox関数の戻り値を使っています。
Inputbox関数は何も指定しないと数字や日付であっても文字列型として返ってきてしまうので、もしそれを使って、「型が違う」とQueryTableオブジェクトに怒られたら、このサイトのサンプルのようにInputboxで戻り値の型を指定したほうがいいかもしれません。
SQLのパラメータの入力値は、そのデータ型が「?」の列と同じデータ型でないと、「データ型がおかしいよ!」とエラーになりますので・・。
逆に、もし怒られなかったら問題ありません。(無い気もしますが・・・)

といいますか、↑このサイトのやり方よりも、「xlPrompt」を使うほうが手軽かもです。
QueryTableオブジェクトを右クリックして「更新」したときに、パラメータ値を入力するダイアログが出てくれるので・・・。「?」で作った数だけ、ダイアログが出てくれます。
またそのダイアログでは、入力した値をいちいちデータ型チェックや変換をする必要もありません。(入力値のデータ型を自動認識してくれます。)
あと、このサイトのやりかたでは、右クリックで「更新」したときに何も出ないかも・・・。よくわかりませんけど・・・。(出ても、どっかにボタン作成が要る?かもなのでめんどくさそうです。)

(しかし、このサイトは・・・、ここまでやっているなら、もっとSQLを広めればいいのに、と思ってしまいます。しかも、もっと、ちゃんとParameterオブジェクトの解説をすればいいのに・・・。なぜこの大御所サイトはしないのだろう???意味がわかりません。
VBAの「ループ処理だけが目的」「VBAが使えるぞすごいだろう?」「SQLなんていらないよ」という感じで、「計算や集計はどうでもいい」、プログラム作り・管理の「コスパ」なんて「どうでもいいだろ?」と言っているように見えてしまいます。
こういうのが「コスパが悪化する無駄なVBA・ワークシート関数を増やす原因」なんだと思います。過去によくお世話になっていただけに、いまだにこうなんだとガッカリします。
「AccessVBAなんてどうでもいい」とはもちろん言いませんが、でもExcelVBAをここまでやられているなら、「ExcelでのSQL」や「Microsoft Query」の操作も同時にもっとやればいいのに・・・と思ってしまいます。どうせAccessでSQLやることになるんですから・・・。
大御所サイトだからこそ、もっと、「複雑な条件での」「表計算・集計・リストアップ」、また、「表計算ソフトそのもの」「ビジネス応用そのもの」の「本質を」、やってほしいです。VBAでループ処理ができることだけが偉いわけではまったくもって、ありませんので・・・。)

そのほか、Parameterオブジェクトでは、前述しましたように、
Parameter.SetParam メソッドの「XlParameterType 列挙」にて、
「xlPrompt=0=値の入力を促すダイアログ ボックスを表示します。引数 Value はダイアログ ボックスに表示する文字列を指定します。 」
も使えます。

ヘルプを読めば全部書いてあります。
  

【参考】XlParameterDataType 列挙 の値

「SQLの中の、抽出条件に「?」を付けた列のデータ型」と必ず合致するように、以下のデータ型のどれかに毎回必ず変更します。

名前-----値-----説明
xlParamTypeBigInt------5-----多倍長整数型
xlParamTypeBinary------2-----バイナリ型
xlParamTypeBit------7-----ビット型
xlParamTypeChar-----1-----文字列型
xlParamTypeDate-----9-----日付型
xlParamTypeDecimal-----3-----小数点型
xlParamTypeDouble-----8-----二重型
xlParamTypeFloat-----6-----浮動小数点型
xlParamTypeInteger-----4-----整数型
xlParamTypeLongVarBinary------4-----長バイナリ型
xlParamTypeLongVarChar------1-----長文字型
xlParamTypeNumeric-----2-----数値型
xlParamTypeReal-----7-----リアル型
xlParamTypeSmallInt-----5-----小整数型
xlParamTypeTime-----10-----時刻型
xlParamTypeTimestamp-----11-----タイムスタンプ型
xlParamTypeTinyInt------6-----極小整数型
xlParamTypeUnknown-----0-----不明な種類
xlParamTypeVarBinary------3-----可変長バイナリ型
xlParamTypeVarChar-----12-----可変長文字列型
xlParamTypeWChar------8-----Unicode文字列型

  
  
▼ 「すでに作成されたQueryTableオブジェクト」に対して、パラメータを作成する例3つ(1個、2個、3個のパラメータの場合の例)

冒頭のサンプルファイル(xlsm、xls)に追加するなら、このプログラムが一番簡単かと思います。
各シートのモジュールにコピペして使ってみてください。

パラメータが無い既存のQueryTableオブジェクトの場合は、「?」を使ってSQL自体も変更します。
すでにパラメータが作ってあるQueryTableオブジェクトの場合は、SQLは変更せず、セル位置などだけを変更することもできます。(少し作り変えが必要ですが。)

なお、セルの値を使ったパラメータクエリは、VBAで自同生成したときに、そのセルの値が空白だと、SQL内容が正常でも「1004 エラー」になるようです。

なので、以降のプログラムでは「1」をダミーデータとしてセルに自動セットする形にしてあります。「1」なら、Excelの場合に限っては、日付、時刻、数値、文字、色々なデータ型に対応できるかな・・・と思いまして・・・。

ただこれは「とりあえずエラーにならないようにというだけのこと」なので、QueryTableオブジェクトができあがったら、本来のパラメータの値を入力しなおしてください。

もちろん、どのセルをパラメータ値の入力箇所にするか、最初からわかってはいるわけですので、本来のデータ型の値をあらかじめ、そのセルに入力しておけば なおいいです。
ただし、全角半角の入力ミスが無いように注意が必要です。

正しいデータ型の値が入っていれば、列名+レコード表示されますし
「1」のダミーデータなら、列名だけが表示されます。
  

◎ パラメータが1つだけの場合

以下のサンプルは「1つだけのパラメータを作る・セル位置を変える」などに使えますが、「2つ以上」には対応していません。
なので、2つ以上のパラメータを作成したい場合は、これ以降のサンプルもご参考にしてください。

注意
QueryTableオブジェクトを作ったときのSQLと、このプログラムのSQLのファイルやテーブル名が異なることがないようにします。

あと、以下のところの修正は、必ず、SQLの「?」のデータ型に合わせてAddメソッドの「xlParamTypeChar」の部分を書き換えます。データ型は、Parameters.Addメソッドのヘルプの、「XlParameterDataType 列挙」のリンクに書いてあります。

s_PrmNm1 = "具Prm"
Set Param1 = qt.Parameters.Add(s_PrmNm1, xlParamTypeChar) '変える
Set o_ParamRange1 = Worksheets("sheet1").Range("G2")    '変える。
Param1.SetParam xlRange, o_ParamRange1
Param1.RefreshOnChange = True

o_ParamRange1.Interior.Color = vbYellow
o_ParamRange1.Offset(0, 1).Value = "具Prm" '状況によって変える。(特にBetween)
o_ParamRange1.Value = "%"          '好きなダミーデータを入れる
                      '(目的のデータ型に合ったものを)

パラメータが2つ、3つ、と増えたら、増やしたものについては、
・ s_PrmNm1 、
・ Param1 、
・ o_ParamRange1 、
の、番号も変えます。
(あらかじめ、テキストエディタに上記の8行をコピペ―しておき、テキストエディタの置換機能で置換し、コピペし戻せばOKかと思います。)

  
  
◎ パラメータが2つの場合

  

◎ パラメータが3つの場合

  

  
  
============

▼ そもそも「QueryTableオブジェクト自体」が作ってない場合のパラメータクエリの自動作成のプログラム例

このプログラムでは、2つのプロシージャを使っています。
これは2つめのプロシージャでパラメータを作っています。(ここでは2個を。)

冒頭のサンプルファイル(xlsm、xls)に2つめのプロシージャだけを組み込むときは、そのままでは使えませんので、2つめのプロシージャの、
「'★★★★★★★★★ パラメータが2つある場合の例 ★★★★★★★★★」
の部分周辺を見て、作り変える必要があります。

基本、『 ▼ 「すでに作成されたQueryTableオブジェクト」に対して、「1つだけ」のパラメータを作成する例 』を組み込んで1個バージョン、2個バージョン、3個おバージョンを作りこめば、こちらのプログラムは要らないのかな・・・、とも思います。
でも、一応、「ご参考」まで。

◎ 1つめ:パラメータ呼び出し元プロシージャ(2010でテストして動きました。)

  

◎ 2つめ:呼び出されるプロシージャ(とりあえずこのサンプルプログラムでは、こちら側でパラメータを作ります。こっちらも2010で動きました。)