★★★ Access2000VBA・Excel2000VBA独学~(多分、全バージョン共通・・・だと思います。)DAO、ADO、SQL、Microsoft Query、QueryTableオブジェクト、といった、「真のExcelデータベース(?)」で、でき「ない」こと・逆に20年前もからでき「る」こと。~
(僕は1年前くらいからやっとこさExcelVBAをまじめにやりはじめたド素人です。Accessとのオートメーションは多少してきましたが、ExcelVBAではグラフも動かせません。Excel自体もMicrosoft Queryやピボットくらいしか使ったことが無く、関数なんて全然知りませんし、きれいな作表などしたこともありません。銀行に資金繰り表出すのに縦横罫線だけの普通の表を作ったことがあるくらいです。)
※まだ書きかけです。すみません。
※間違ってたらすみません。
※メモ書きなので、自分でも意味不明な箇所も多いです。ごめんなさい。
目次
★ はじめに
★ DAO・ADOそれぞれ単独、DAO・ADO+SQL、Microsoft Query+SQL、QueryTableオブジェクト+SQLで、
共通の、でき「ない」こと
▼できないこと(01) Excelファイルに対してだけは、「削除」ができない。
▼できないこと(02) DAO・ADO+SQLやQueryTableオブジェクト+SQLでのINSERT文の実行では、
Max関数でのINSERTができない。(その他の関数も使えないかもです。)
▼できないこと(03) ダミーデータの前もっての入力なしに、セルの緑三角マークエラーを回避すること。
▼できないこと(04) 文字列型の列に値を入力すると「接頭語」の「'」がついてしまい取れない。
▼できないこと(05) SQLやDAO・ADOでは、直接、セルに対して書式を変えたり、数式を入れたりすることができない。
★ (多分、全バージョン共通・・・だと思います。)DAO、ADO、SQL、Microsoft Query、QueryTableオブジェクト、
といった、「真のExcelデータベース(?)」で20年前からできること
(01)閉じたままの相手ファイルの内容を、自ファイルのシートに表示すること
(02)1シートを1テーブルにすること、セル範囲を1テーブルにすること
(03)閉じたままの相手ファイルの内容を、自ファイルのVBAから書き換える(削除以外。追加と編集)
(04)閉じたままのファイルのシートへの表自体の作成(テーブル定義してシステムテーブルを作成)
(05)表をセルアドレスじゃなくて列名で操作するので、ソースの表の列が入れ替わったり、新しくできたりしても再設定が要らない。
表全体が多少移動されても、ちゃんと列名で書き込み・読み込みができる。
(06)列をインデックス番号や名前などで操作する=表の中で横のループ処理ができる
(07)For Each 文を使う(例えば列の操作などに)
(08)SQLの結果に、さらに、SQLをかけ、さらにSQLをかける、などの多段的なSQL利用
(09)「生データの表×仮想表」など、複数の表同士のリレーションができる(VLOOKUP関数のような紐付けができる。
表の数は2つでも3つでも、4つでも。1本だけでなく複数本同時のリレーションも。)
(10)複数の表をリレーションしながら、かつ・フィルタをかけながら、かつ・同時に簡易クロス集計やグループ化集計もする。
(フィルタ+簡易ピボット/集計機能、を、より複雑な条件でもできるようにした感じ)
(11)表に限ってだけは、クラスモジュールでオブジェクト化する必要が少なくなる
(12)ExcelVBAと同じように、オブジェクト、プロパティ、メソッド、コレクション、が使える
(13)相手ファイルがファイルサーバに在ってもOK。(UNCパスOK!)
※Shift+TABキー、もしくは、Homeキー、Homeキー+TAB数回、を押すと、目次付近に戻れます。
★ はじめに
上記の「目次」を見ていただければお分かりになられますとおり、『 DAO・ADOそれぞれ単独、DAO・ADO+SQL、Microsoft Query+SQL、QueryTableオブジェクト+SQL 』では、結構なことができます。
特に・・・・、
(05)表をセルアドレスじゃなくて列名で操作するので、ソースの表の列が入れ替わったり、新しくできたりしても再設定が要らない。表全体が多少移動されても、ちゃんと列名で「相手ファイルが閉じたままでも」書き込み・読み込みができる。
(06)列をインデックス番号や名前などで操作する=表の中で横のループ処理ができる
(07)For Each 文を使う(例えば列の操作などに)
(09)「生データの表×仮想表」など、複数の表同士のリレーションができる(VLOOKUP関数のような紐付けができる。表の数は2つでも3つでも、4つでも。1本だけでなく複数本同時のリレーションも。)
(10)複数の表をリレーションしながら、かつ・フィルタをかけながら、まつ・同時に簡易クロス集計やグループ化集計もする。(フィルタ+簡易ピボット/集計機能、を、より複雑な条件でもできるようにした感じ)
(13)相手ファイルがファイルサーバに在ってもOK。(UNCパスOK!)
・・・・というのは、便利ですよね。
全部、相手先のExcelファイルが「閉じたまま」でもできるんですから・・・。
「列名」ベースでVBAプログラムが書けるので多少なりとも可読性も上がりますし・・・。
が、いろいろ試してたら「思いもよらぬこと」ができなかったりもしましたので、その対応策もふくめて、先にそちらの「できないこと」をご紹介してから、「できること」をご紹介したいと思います。(僕は1年前くらいからやっとこさExcelVBAをまじめにやりはじめたド素人です。Accessとのオートメーションは多少してきましたが、ExcelVBAではグラフも動かせません。Excel自体もMicrosoft Queryやピボットくらいしか使ったことが無く、関数なんて全然知りませんし、きれいな作表などしたこともありません。銀行に資金繰り表出すのに縦横罫線だけの普通の表を作ったことがあるくらいです。)
もちろん、繰り替えしになりますが、(ExcelVBAド素人の僕でも)けっこうなことができるんだなあ、ともわかりましたので、そちらのほうもちゃんと皆様にもご紹介したいと思います。
・・・しかし・・・
なぜこれをExcelVBAのレジェンドさん達がこれまで「20年間も」「放置し続け」「1っ冊もまともな本にしてこなかったのか」・・・、本当に、こころの底から疑問に思います。
僕が買ったことある本は、MySQLを使う人が、Microsoft Queryの使い方を書いた本を出したやつくらい・・・。それも相手がMySQLだったので、MySQLの説明も少なくなく、結局、Microsoft Queryの説明はそう大した説明は載っていませんでした。
ちなみにですが、ExcelVBAのレジェンドさん達の市販書籍では、『 Microsoft Queryの使い方やExcelでのDAOやADOのことを詳しく書いた書籍 』は、「1っ冊も」、見たことないです。
VBAやAPIも大事だけど、でも初心者向けにはそんな本なんかよりも、こっちを先に出さないといかんでしょ?と思ってしまうくらいです。
「Excelって表計算とグラフがメインのソフトなんじゃないの?だったらなぜ???」とマジでこころの底から疑問に思ってしまいます。
僕のようなExcelVBAド素人の僕でも・・・、(確かに「できないこと」もあり若干不便な点もありつつも、でも、それでも、)「けっこうなことができるんだなあ」と思わされましたし、利用場面在りそう・・・、と、実際、いろいろと使えそうです。
マジで、Microsoft Queryの画面で、Accessのクエリの画面とまったくと言っていいほど同じことできますし(というかこちらが ”元祖” なのかも?)、QueryTableオブジェクトもDAOもADOも全部、Accessと同じようにExcelVBAから操作できるので、『 ほんとうに小さなリレーショナルデータベースアプリケーション 』なら、Access要らなくない?と思うほどです。
少なくとも それらを使えば、「Accessの練習」が、「データ照会・集計の面も、システム構築の面も両方とも」「Accessの作法と同じような感じで」できちゃいます。Excelの作法じゃなくて。
僕みたいなExcelVBAの超ド素人でもこれだけわかるのだから、「自称プロ」の方でない限りは、もっと「便利に使える方法が」いろいろ分かって、しかも、「不都合を埋める」ための「対策」も色々と打てるはずなんですけど・・・
20年もあったんですから・・・。
Excel2000が出て以降でさえ。
なんでExcelVBAのレジェンドさんたちは20年以上も「放置」で「何もしてこなかった」んでしょうか?
VBAなんか広める前にこちらを先に広めたほうがよかったのに。
(もちろん、両方できるほうがいいので、両方やる、VBAはあとで、という意味で。無駄なコードが多少なりとも減って、VBAがもっと生き生きしますよね。)
それでもだめならVBAで、というほうが効率化できる気がしますけど・・・
そのほか、レジェンドさん達は、「オブジェクトの階層構造全図一覧、TypeName関数、Parentプロパティ、ローカルウィンドウ、イミディエイトウィンドウ」などを教えまくって、「初心者でもヘルプとオブジェクトブラウザを使えるようにサポートする・初心者でもヘルプの読み方を教える」ということからも逃げまくっています。
僕はレジェンドさん達のそういう本を一冊も見たことがありません。
(出してたらすみません。でも、少なすぎます。レジェンドさんじゃない先生が一人だけ、ちゃんとやっているのは見ていますが・・・。大変参考になります。)
そのため、教え方が20年前とほとんど変わっていません。
これも20年間放置です。
自力でエラーに対処できない初心者が後を絶ちません。
自力でエラーに対処できないから挫折します。
いつまでたっても、初級から中級に上がれません。
中級に上がるのが一気に難しくなっているままです。
なので「本質を教えない絆創膏ExcelVBA教育」・「”データ管理の基礎” やSQLなどを教えない絆創膏ExcelVBA教育」で儲けようとする人が減りません。
なぜそこを改善しようとしないのか、僕のようなExcelVBAのド素人・「習う側」にはぜんぜん理解できません。
もしそこをもっとやっていれば、今頃ExcrelVBAの初心者本は「どう、グラフやシェイプやSQLなどをVBA操作で動かして、どう見える化するか・分析や仮説と検証に生かすか・PDCAやFFA?にどう生かすか・どうビジネスに生かすか、とか、実用的なガントチャートの作り方、とか、ビジネスに役立つ実用的なシュミレーションプログラム、とか、POSレジなんて自分で作っちまいましょう、とか、どうVBAを統計に生かすか、とか、」、そういう本やサイトがもっともっと増えてて、それが「あたりまえ」になっているはずです。
特に、「Accessがダメすぎて使えない部分を、Excelで補うためのプログラムとオートメーション」という本だってもっともっとたくさん出てないといけないはずです。
Accessの得意とExcelの得意をオートメーションでつないで、お互いの「苦手を消し合う」という選択肢もきちんと用意ておく(でも敢えてそれにとらわれすぎもしない)というのが、一番自由になれて、コスパアップが見込めるんですから・・・。
Accessで数分で終わることを全部Excelで数日も・下手すると数週間もかけさせてやらせようとすること自体がバカすぎます。もちろんその逆も。
コストのことなんてまるで考えていません。
「Access+Accessランタイム+Excel オートメーション」や「Access+ブラウザ入力(ASPやPHP含め)+Excel オートメーション」といった本だって出てません。
なのにいまだに20年前とかわらない、ExcelVBA=初級も中級も「セルとシートを操作する」本ばっかり。
むしろグラフやシェイプを操作する本なんて減ってるんじゃないでしょうか?
逆に、「どうせ、セルとシートを操作することばっかりしか教えない・本質教えない」なら、「やることないなら」、だったら「なおさらMicrosoftQueryとかSQLとか教えないかんでしょう?未来につなげたいなら。」と思うんですけど。
理解できません。
Accessといっしょで、バージョン2000のころよりも書籍は退化している気がします。
「結局、”エンドユーザーコンピューティング” なんてかえってコスパが悪い。非効率。安い外注探してそっちに出した方がマシ。騙された。」ということの証明なのかもしれません。
★ DAO・ADOそれぞれ単独、DAO・ADO+SQL、Microsoft Query+SQL、QueryTableオブジェクト+SQLで、共通の、でき「ない」こと
▼できないこと(01) Excelファイルに対してだけは、「削除」ができない。
↓このWebページの「8.データ削除」のところです。
http://acompass.net/top0/?cmd=read&page=EXCEL%2FDB&word=ISAM
引用
『Jet OLE DB プロバイダを使用すると(つまりExcelでは)、Excel ブックのレコードの挿入および更新はできますが、DELETE の操作を行うことはできません。これはExcel固有の制限です。 DELETE 操作を実行すると、次のエラー メッセージが表示されます。』
あと、こちらも↓
『 http://blog.livedoor.jp/pitapo/archives/424211.html → なんかそういう仕様?らしいです。』
『 http://winofsql.jp/ado/exceltechasdb.htm → DELETE と DROP は一般的な SQL ですが、「削除」は Excel ではできません 』
『 https://docs.microsoft.com/ja-jp/sql/ado/guide/extensions/provider-support-for-adox-ado?view=sql-server-ver15』』の「Microsoft OLE DB Provider for ODBC」??
多分マイクロソフトさんのページにも、どっかに「Deleteはサポートしてない」と書いてあるのではないかと思います。
DAO、ADOでは、通常のそれぞれのレコード操作を使う場合でも、SQLを使う場合も、『 本来は「削除」ができる 』のですが、ただし、書き込む先が「Excelのファイル」だと、xls、xlsx、xlsm、すべての拡張子で、削除ができないもようです。(もしかしたらテキストファイルとかもそうかもしれません。未確認ですが。ExcelからAccessに対しては、SQL、あるいはDAOやADOのDeleteメソッドにて、レコードの削除ができます。MySQLなどに対してはどうかわかりません。未確認です・・・。)
「このisamでは、リンクテーブル内のデータを削除することはできません」というエラーになってしまいます。
これは、DAO・ADOそれぞれ単独の通常のUpdate操作でも、DAO・ADO+SQLの操作でも、同じエラーになってしまいます。相手が「Excelのシートやテキスト系のファイルなど」である限りは。(相手がAccessのmdbファイルやSQL Server などだとなりません。)
※(2019/11/08気づいた:「通常のUpdate操作」は、「通常のDelete操作」の書き間違いカモ!すみません!いつかちゃんと確認して書きなおします!)
「Microsoft Query」の画面からの「SQL実行」画面でも同じエラーで、VBAからQueryTableオブジェクトで操作したらODBCがらみのエラーになってしまいました。(何かうまい方法があるのかもしれませんが)
なので、そのような場合は、次のような方法を取ることが必要です。
(a)削除をしない。削除フラグを立ててそのレコードだけ抽出や集計から除外する。
削除フラグを立てて、SQL実行やQueryTableオブジェクト操作ではそのレコードだけ操作の対象から除外します。
削除ができないと不便なように感じますが、SQLが分かる人なら、さほど不便でもないのではないかと思います。
例えば2つの表をリレーションさせるにしても、お互いに、いったん、QueryTableオブジェクトにて、
削除フラグが立ったレコードを除外した結果を、各々、別々のシートに表示しておいて、
そのあと、その結果の表同士(=シート同時=システムテーブル同士)をリレーションさせればOKだと思います。
SQLの達人なら、副問い合わせなどを使って、1つのSQLでやっちゃえるんでしょうし・・・(僕はできませんけど)
もともと、ExcelでもAccessでも、クエリのクエリの、そのまたクエリ・・・、といったように、クエリのネストといいますか、『 多段的にクエリをかける 』ことができるので、削除ができない からといって、極端に不便になるわけでもないと思います。
逆に、「削除フラグのついたデータばかり見てたら、何かがわかる(不正とか)場合もある」ので、その意味でも、「削除が絶対」ではありません。(レコードが消えないことを永遠に隠しておいて、ユーザーに「削除=消滅」とわざと誤解させておくと、不正が見つかる場合があります。わざとそういう仕様にするケースもあるようです。)
もちろん、表と表のあいだの「整合性」を保つために、削除しない(できない)ことも多いです。
「データベース処理」の場合は、「あえて削除をしない」という仕様も、少なくないと思います。(特にマスタじゃなくて明細のテーブルのほう)
なので、削除できないことを、ことさら、気にする必要もないと思います。
(b)削除したいレコード(行)だけ、すべての列を「Null」に書き換える。
削除したいレコードだけ、主キーというか連番の値だけ残しておいて、あとは、すべての列を「Null」に書き換えます(上書きしてしまいます)。あるいは、初期値で埋めます。
初期値で埋めてしまえば、削除しなくても集計には含まれないようにできます。
すべての列を、たとえば件数も金額もNull(空白:不明な状態)、もしくはゼロなど、にしてしまえば、集計には何の影響もありません。
逆に、もしNullや空文字("")で埋めることで、シートのデータ抽出の動作が遅くなるようなら、たとえば、削除フラグの立ったレコード(行)には、・・・、
・数値型の列には「0」を、
・文字列型の列には「-----」を、
・日付の列には「1900/01/01(シリアル値の1)」を、
・時刻の列には「00:00:00(シリアル値の0)」・・・
などを上書きしておくのも良いかもしれません(その場合、不正やヒントの発見はできなくなってしまいますが)。
そうすれば、集計に含まれないようになると思います。
リストアップした際も、その行だけ 削除フラグやそれ以外の条件でフィルタで除外するか、もしくはVBA+フィルタでヒマな時に(そのExcelファイルを開いて、)自動的にALLで消してしまってもいいですし。
なお、SQLでのデータ書き換えの場合、True/Falseの列は、Nullを入れるとFalseになってしまうもようです。
そして、(a)(b)、いずれも、「一定の期間が経って、”やっぱ削除したい!” となったときに、VBAなどにて・・・、
・削除フラグの立ったものを、すべてのシートから一括消去
・初期値ばかりの行を、すべてのシートから一括消去、
・・・というような恰好で適宜、削除をすればOKかと思います。
※参考:Excelから、Access(mdbファイル)のレコードを削除する例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
' ' Sub DeleteTestFromMdbBySQL_01() Dim DBE As DAO.DBEngine Dim DB As DAO.Database Dim strSQL01 As String Dim rst As DAO.Recordset 'データベースオブジェクトの作成 Set DBE = New DAO.DBEngine 'データベースを開くための空の領域(空の部屋?)を作成 Set DB = DBE.OpenDatabase("D:\1\tes001.mdb") 'その部屋の中でデータベースを開く 'SQLでの削除操作の例 strSQL01 = "DELETE FROM t01 WHERE PK = 17;" 'レコードを削除するためのSQL命令=SQL文)の作成 DB.Execute strSQL01 'ExecuteメソッドでSQL命令の実行 'レコードセットオブジェクトでの削除操作の例 Set rst = DB.OpenRecordset("t01", dbOpenDynaset) 'レコードセットの作成(=テーブルを開く) rst.MoveLast 'MoveLastメソッドで最後のレコードに移動(移動した行を削除する例です。ほかにも色んな削除の方法があります。最後の行に移動したのも特に意味はなく、単なる「移動した行の削除」の例として、です。) rst.Delete 'Deleteメソッドでのレコードの削除 '操作が完了したあとの後片付け rst.Close Set rst = Nothing DB.Close Set DB = Nothing Set DBE = Nothing End Sub ' ' |
▼できないこと(02) DAO・ADO+SQLやQueryTableオブジェクト+SQLでのINSERT文の実行では、Max関数でのINSERTができない。(その他の関数も使えないかもです。)
後日調べたら、
『 SQLのほうのMAX関数(VBAというか、WorksheetFunction.MAXメソッドではなくて)』
を使って、レコード追加(=INSERT INTO)ができました。
例えば、現在レコードを追加しようとしている表の・・・、その連番列に「新たな最大値(つまり+1したもの)を入れながら」、同時にレコード追加もしたい場合・・・、
INSERT INTO テーブル名 (連番列名,列名02,列名03,)
VALUES(Max(連番列)+1,列名02への値,列名03への値);
・・・という書き方だとエラーになってしまいますが・・・、
INSERT INTO テーブル名A (連番列名,列名02,列名03,)
SELECT Max(連番列名)+1,列名02への値,列名03への値 FROM テーブル名B;
・・・という書き方だと「SQLのMAX関数」を使って、ちゃんとレコード追加できました。
テーブル名Aとテーブル名Bは同じテーブル名でも異なるテーブル名でもOKです。
同じテーブル名なら、現在レコード追加しようとしてるテーブルの連番の最大値が連番列に入りますし、異なるテーブル名なら、その異なるテーブルの最大値が書き込まれます。
INSERT INTO で書いた列の数と、SERECT で書いた列の数が同じで、それぞれの列にちゃんとそれぞれの値が正しく呼応していればOKです。
SELECTを使うので、最大値が必要ないときは、多分WHERE句で 他のテーブルから抽出した複数のレコードを、一括・一発で追加できるっぽいです・・・。(未確認です。)
ただ、その複数レコードの連番の最大値をすべて+1していきたい場合は、複数一括でやると全部同じ値になってしまうかもしれません。(こちらも未確認です。)
【▼ その他の方法】(以前書いた分)
SQL(JET SQL)では、連番列など、整数の列の最大値をMAX関数で求めることができます。
しかしこれは、SELECT文だけのようでして、INSERT文には使えないもようです。
その際、INSERT文でレコード追加したいときに連番の最大値を書き込むには、前述の方法のほかに、
なので、DAO、ADO、で書き換えしたいファイルに接続した際に、SQLを実行する前に、ついでに、事前に、最大値を WorksheetFunction.Max メソッド にて、調べておく必要があります。という方法もあります。(とりあえず。で。もっとほかにもあるかもしれません。)
WorksheetFunction.Max メソッド はDAO、ADO、の「レコードセット」と呼ばれるものに対しても使えます。
WorksheetFunction.Max(Rs("連番列の列名"))、みたいな感じで、連番列の最大値を取得することができます。(「Rs」が「レコードセット」の場合。「レコードセット=ある条件のもとに、データを絞り込んで抽出した ”仮想表” のようなもの」とイメージしてくだされば大丈夫だと思います。)
あとは、1をプラスした値を、INSERT文 のVALUE句などに含ませます。
すでにSQL文が事前作成されて出来上がってしまっている場合は、SQL文の中のVALUE句のなかで最大値(値そのもの)に該当する部分を、WorksheetFunction.Max メソッド で求めた最大値 +1の値に、ExcelVBAのReplace関数で置換します。
(置換するためには、SQL文を事前作成する際に、置換しやすいあらかじめ決めておいたダミーのVALUEの値(置換さえできれば数字じゃなくてもなんでもいい)に、しておく必要があります。)
※SQLは、QueryTableオブジェクトでも使うことができますが、その場合、
何らかのシートに表示させてからでないと最大値を求められないので、たとえば、
『 相手となるファイルが「閉じたまま」、かつ、こちらにも表示させないまま、
かつ、最大値を求めて全部やりたい・・・』、
という場合はQueryTableオブジェクトは使えません。
その場合、他のデータベースではOKでも、Excelだとダメ、
というケースもあるかもしれません。
(特殊じゃない書き方でも。Excelの仕様が原因で?とか。)
▼できないこと(03) ダミーデータの前もっての入力なしに、セルの緑三角マークエラーを回避すること。
Excelで、DAO・ADOそれぞれ単独、あるいはDAO・ADO+SQLなどでデータを書き込むと、セルの隅っこに「緑三角マークエラー」が表示されることがあります。(バージョン2007以降だったかな?忘れました。)
そのようなことが起こった場合、全列を埋めるダミーデータ(ダミーレコード)を、あらかじめ「1行だけ」入力しておくと防げるようです。
基本、例えばSQLでやるなら、全部の列に「Null」を入れておけばいいかと思いますが、それでSQLの動作速度が遅くなるようなら、(繰り返しになりますが)たとえば・・・
・数値型の列には「0」を、
・文字列型の列には「-----」を、
・日付の列には「1900/01/01(シリアル値の1)」を、
・時刻の列には「00:00:00(シリアル値の0)」・・・
・・・などを入力しておくとよいかと思います。
そして、前述のように削除フラグも立てておけば問題ないと思います。
そうすれば、集計に含まれないようになると思います。
リストアップした場合も、その行だけ削除フラグやそれ以外の条件でフィルタて消してもいいですし。
なお、SQLでのデータ書き換えの場合、True/Falseの列は、Nullを入れるとFalseになってしまうもようです。
DAO単独や、ADO単独ではまだテストしていません。
が、同じような方向性で行けるのではないかと思います。
▼できないこと(04) 文字列型の列に値を入力すると「接頭語」の「'」がついてしまい取れない。
適当なセルをコピーして、書式の貼り付けをすれば取れますが、SQL操作では直接それができません。
ただ、文字列型の列に「'」が付いたところで、
・VBAのRangeでも
・SQLでも
・DAO・ADOでも、
その「'」が読み込まれることはありません。
もちろん、変数にも代入されません。
数値に付いてるわけじゃないので、基本、何の問題もありませんので、慣れれば気にならないと思います。
また、文字列型の列に、「'」のついたセルと、ついてないセルが混ざっても「文字列型の列であれば」特に問題なさそうです。
また、(03)のようにダミーデータを入れておくと、その場合は、例えばSQLでレコード追加した際は「'」は、付かないっぽいです。(文字列型の列であっても。でも、間違ってたらすみません。)
▼できないこと(05) SQLやDAO・ADOでは、直接、セルに対して書式を変えたり、数式を入れたりすることができない。
SQLやDAO・ADOは、「データのみを操作する機能」ですので、セルの色やフォントの設定、ワークシートといった、「ExcelVBE側」のオブジェクトを、そのメソッドやプロパティで操作することはできません。(「”レコードセット”といったDAO・ADOのオブジェクト」と、「”セルやシート”といったExcelのオブジェクト」は、「異なるくくりでのオブジェクト」ですので。)
数式についても、「= ×× + ××× 」みたいな数式を「値として書き込む」ことはできますが、ただ、画面が開いてないと反映させることができません。しかも、ファイルを開くだけではダメなので少々面倒です。
また、SQLやADOを使ってレコード操作する際は、ファイルを閉じていることが多いですし、また、
★ (多分、全バージョン共通・・・だと思います。)DAO、ADO、SQL、Microsoft Query、QueryTableオブジェクト、といった、「真のExcelデータベース(?)」で20年前からできること
(01)閉じたままの相手ファイルの内容を、自ファイルのシートに表示すること
Microsoft Query(QueryTableオブジェクト)+SQL でループなしの一発表示(一発読み込み)
DAO単独(+ループ & Rangeセル操作、または、ループなしでRange.CopyFromRecordset一発貼り付け)
DAO+SQL(+ループ & Rangeセル操作、または、SELECT文 & ループなしでRange.CopyFromRecordset一発貼り付け)
ADO単独(+ループ & Rangeセル操作、または、、ループなしでRange.CopyFromRecordset一発貼り付け)
ADO+SQL(+ループ & Rangeセル操作、または、SELECT文 & ループなしでRange.CopyFromRecordset一発貼り付け)
(02)1シートを1テーブルにすること、セル範囲を1テーブルにすること
「レコードセット」として、シート全体だけではなく、『 セルアドレスでのセル範囲 』や 『 名前の定義で名前が付いた範囲 』を設定することができます。
ただし、セル範囲で設定した場合は、行(新規レコード)の追加をしたい場合、セル範囲をあらかじめ広げて、空白行を含めておく必要があります。
全行が値のあるレコードで埋まっていると、既存レコードと編集はできても、新規レコード追加が「いっぱいいっぱいなので追加できません、範囲は広げられません」的なエラーになります。
Microsoft Query(QueryTableオブジェクト)+SQL
DAO単独(例:Set Rs = db.OpenRecordset("明細表$A1:C20")とか。Set Rs = db.OpenRecordset("test範囲"))は読み込みはOKだけど、新規追加は空白行を作っても正常動作しませんでした。
DAO+SQL (例:Set Rs = db.OpenRecordset("SELECT * FROM [明細表$A1:C20]") とか、Set Rs = db.OpenRecordset("SELECT * FROM `明細表$A1:C20`")とか。Set Rs = db.OpenRecordset("SELECT * FROM test範囲")は読み込みはOKだけど、新規追加は空白行を作っても正常動作しませんでした。※ここでの「test範囲」は、名前の定義で付けた名前です。
ADO単独
ADO+SQL
(03)閉じたままの相手ファイルの内容を、自ファイルのVBAから書き換える(削除以外。追加と編集)
Microsoft Query(QueryTableオブジェクト)+SQL
DAO単独(+ループ & Rangeセル操作)
DAO+SQL(+ループ & Rangeセル操作、または、INSERT文やUPDATE文など)
ADO単独(+ループ & Rangeセル操作)
ADO+SQL(+ループ & Rangeセル操作、または、INSERT文やUPDATE文など)
(04)閉じたままのファイルのシートへの表自体の作成(テーブル定義してシステムテーブルを作成)
Microsoft Query(QueryTableオブジェクト)+SQL(未検証)
DAO+SQL(検証OK)xlsに。
ADOX+SQL(未検証)
(05)表をセルアドレスじゃなくて列名で操作するので、ソースの表の列が入れ替わったり、新しくできたりしても再設定が要らない。表全体が多少移動されても、ちゃんと列名で書き込み・読み込みができる。
Microsoft Query(QueryTableオブジェクト)+SQL
DAO+SQL
ADO+SQL
(06)列をインデックス番号や名前などで操作する=表の中で横のループ処理ができる
この場合は列が入れ替わったり新しく挿入されてしまったりするとちょっと困りますが、でも、そういうことが関係のない処理とか、そういったことに使えます。
現在の列名・列の順番の調査とか。
表全体が多少移動されても、ちゃんと列のインデックス番号で書き込み・読み込みができるのは前項と似た感じです。RangeプロパティやCellsプロパティを使うような感じと少し似ているかもしれません。
Microsoft Query(QueryTableオブジェクト)+SQL+Range
DAO単独+Range
DAO+SQL+Range
ADO単独+Range
ADO+SQL+Range
DAO+SQL
ADOX+SQL
(08)SQLの結果に、さらに、SQLをかけ、さらにSQLをかける、などの多段的なSQL利用
Microsoft Query(QueryTableオブジェクト)+SQL
(09)「生データの表×仮想表」など、複数の表同士のリレーションができる(VLOOKUP関数のような紐付けができる。表の数は2つでも3つでも、4つでも。1本だけでなく複数本同時のリレーションも。)
Microsoft Query(QueryTableオブジェクト)+SQL
DAO+SQL
ADO+SQL
(10)複数の表をリレーションしながら、かつ・フィルタをかけながら、まつ・同時に簡易クロス集計やグループ化集計もする。(フィルタ+簡易ピボット/集計機能、を、より複雑な条件でもできるようにした感じ)
Microsoft Query(QueryTableオブジェクト)+SQL
DAO+SQL
ADO+SQL
(11)表に限ってだけは、クラスモジュールでオブジェクト化する必要が少なくなる
(セル書式を頻繁に変えたい、とか、初期設定・再設定を何もせずにRangeで列名操作がしたい、などの場合は必要になるのかもしれませんが)
Microsoft Query(QueryTableオブジェクト)+SQL+Range
DAO単独
DAO+SQL
ADO単独
ADO+SQL
(12)ExcelVBAと同じように、オブジェクト、プロパティ、メソッド、コレクション、が使える
DAO単独
DAO+SQL
ADO単独
ADO+SQL
(13)相手ファイルがファイルサーバに在ってもOK。(UNCパスOK!)
Microsoft Query(QueryTableオブジェクト)+SQL+Range
DAO単独
DAO+SQL
ADO単独
ADO+SQL