★★★★★★Access2000VBA・Excel2000VBA独学~★★★もっともシンプルなQueryTableオブジェクト操作のVBAプログラム例(内部結合の場合=VLOOKUP関数的な処理)。「自ファイルデータを覗きに行く」ケース。ピボットのソースにするとパワーピボット的なことがバージョン2000でもできます。~
※まだ書きかけです。すみません。
※間違ってたらすみません。
※メモ書きなので、自分でも意味不明な箇所も多いです。ごめんなさい。
★ サンプルダウンロード
https://euc-access-excel-db.com/00000WPZIP/msqry_test01.zip
解凍してVBAを有効にし、VBEを開いたら、「Module1_最シンプル」モジュールに次項のコードがあります。
★ もっともシンプルな、かつ、コードを「分けない」事例
以下のコードで抽出した結果を、Offset関数を使って行列可変の範囲に指定したのち、ピボットのソースにするとパワーピボット的なことがバージョン2000でもできます。
(VBA操作がパワーピボットやパワークエリよりも断然にやりやすいので、「自動化」という意味では、QueryTableオブジェクトを使うことは、全バージョンでおススメできる方法です。2019でも使えます。もちろん、パワーピボットやパワークエリが有利な場面もありますのでそのときはそちらを使うほうがいいです。)
なお、以下のサンプルではINNER JOIN を使った「内部結合」をしていますが、もちろんSQL文を変えれば、外部結合をしたり、その他の句を使ったりもできます。
副問い合わせもできます。
※以下は自ファイルを覗きに行く例ですが、
s_FullName = ThisWorkbook.FullName
s_FDPath = ThisWorkbook.Path
の2行で他ファイルを指定すれば、他ファイルも扱えます。
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
' ' Sub MsqTest01() Dim s_FullName As String Dim s_FDPath As String Dim s_SQL01 As String Dim s_SQL02 As String Dim v_Sqlstr01 As Variant Dim o_Qtbl01 As QueryTable Dim s_Cnn01 As String Dim o_WSMe As Worksheet s_FullName = ThisWorkbook.FullName s_FDPath = ThisWorkbook.Path '↑自ファイルのデータを覗きに行くという設定にします。 Set o_WSMe = Application. _ ActiveWorkbook. _ Worksheets.Item("検索結果") '↑QueryTableオブジェクトを生成したいシートの名前を設定します。 s_SQL01 = "" s_SQL01 = s_SQL01 & "SELECT 列01, 列02, 列03, 列04" s_SQL01 = s_SQL01 & " FROM [データ$] INNER JOIN [検索値$]" s_SQL01 = s_SQL01 & " ON [データ$].列01 = [検索値$].比較値 " s_SQL02 = "" s_SQL02 = s_SQL02 & "ORDER BY 列01 , 列02" '↑SQL文の部分作成・準備。 ' 基本、書き換えるのは、ここと前段階のシート名だけでいいです。 v_Sqlstr01 = Array(s_SQL01, s_SQL02) '↑QueryTableオブジェクトのCommandプロパティがバリアント型なので ' 一応それに合わせてSQL文を作成・本番。 ' SQL文がメッチャ長くなるようなら、エラーを回避するために ' s_SQL03、s_SQL04、s_SQL05、と増やしていきます。 ' (句ごとに分けるとか。) ' エラーになるまでは増やさなくてもOKです。 s_Cnn01 = s_Cnn01 & "ODBC;" s_Cnn01 = s_Cnn01 & "DSN=Excel Files;" s_Cnn01 = s_Cnn01 & "DBQ=" & s_FullName & ";" s_Cnn01 = s_Cnn01 & "DefaultDir=" & s_FDPath & ";" s_Cnn01 = s_Cnn01 & "DriverId=1046;" '2010の場合? s_Cnn01 = s_Cnn01 & "MaxBufferSize=2048;" s_Cnn01 = s_Cnn01 & "PageTimeout=5;" '↑「ODBC」という接続方法で自ファイルに接続する設定。 ' 「MicrosoftQuery」も「ODBC」接続です。 ' 「ODBC」以外には「OLEDB」接続があります。 ' そのうち、「ACE」系の接続方式では「ADO」や「xlsx、xlsm拡張子のExcelファイル」「64bit・32bitのExcel」を使う時に良く使います。 ' そのうち、「JET」系の接続方式では「DAO」や「xls拡張子の古いExcelファイル」「32bitExcelのみ」を使う時に良く使います。ただ、ADOももちろん使えます。 ' 「ADO」や「DAO」でも、SQLを使うことができます。 If o_WSMe.QueryTables.Count = 1 Then o_WSMe.QueryTables.Item(1).Delete o_WSMe.UsedRange.ClearContents End If '↑もしすでにQueryTableオブジェクトがあったら、削除。 ' QueryTableオブジェクトだけ削除しただけだと値が残ってしまうので全部消す。 Set o_Qtbl01 = o_WSMe.QueryTables.Add( _ Connection:=s_Cnn01, _ Destination:=o_WSMe.Range("A1")) '↑空のQueryTableオブジェクトの作成。 o_Qtbl01.CommandText = v_Sqlstr01 '↑SQL文のセット。 o_Qtbl01.Refresh '↑SQL文の実行(更新)。 End Sub ' ' |
★ 少し高度な感じの、かつ、コードを「分ける」事例
MSQtest01() から、vrtMakeMsqOwnFileTest02()を「Call」で呼び出します。
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
' ' Sub MSQtest01() Dim strFullName As String '中身を覗きにいきたいファイルのフルパスを格納する変数。UNCパスも使えます。 Dim strFDPath As String 'そのファイルのフォルダパスのみを格納する変数。フルパスからファイル名を取り除いたものです。(最後の\は付いていてもいなくても大丈夫っぽいです。) Dim strSQL01 As String '部分的なSQL文を格納するための変数です。句ごとか、文字数ごとに複数作成します。 Dim strSQL02 As String '同上 Dim vrtSqlstr01 As Variant '部分的な複数のSQL文を最終的に1つに合体させるための変数です。SQLの実行の段階で、MicrosoftQuery(QueryTableオブジェクト)のCommandTextプロパティにこれを渡すのですが、それがVariant型であるため、ここでもVariant型を使います。 Dim strImpShtNm99 As String '覗きに行ったものを 吸い込みたいシートの名前を格納する変数。 '*************************************************************************** '各種設定(MicrosoftQuery=QueryTableオブジェクトに渡すデータの一部) '*************************************************************************** strFullName = "D:\1\リレーションテストやSQLで使えるテーブルの範囲のテスト.xlsm" '覗きに行きたいファイルを指定 strFDPath = "D:\1" 'そのフォルダパスのみを指定 strImpShtNm99 = "MsQRY吸込" '*************************************************************************** 'SQL文の作成(これもMicrosoftQuery=QueryTableオブジェクトに渡すデータの一部) '*************************************************************************** '副問い合わせありのSQLの例02(ちょっと長めの例) strSQL01 = "" strSQL01 = strSQL01 & "SELECT 連番" strSQL01 = strSQL01 & " ,顧客ID" strSQL01 = strSQL01 & " ,`Sheet3$`.氏名" strSQL01 = strSQL01 & " ,数量" strSQL01 = strSQL01 & " ,単価" strSQL01 = strSQL01 & " ,金額" strSQL02 = strSQL02 & " FROM" strSQL02 = strSQL02 & " (" strSQL02 = strSQL02 & " SELECT *" strSQL02 = strSQL02 & " ,数量*単価 AS 金額" strSQL02 = strSQL02 & " FROM `Sheet1$` INNER JOIN `Sheet3$`" strSQL02 = strSQL02 & " ON `Sheet1$`.顧客ID = `Sheet3$`.連番02 " strSQL02 = strSQL02 & " )" strSQL02 = strSQL02 & " WHERE 数量 >= 1 AND 金額 >= 300" strSQL02 = strSQL02 & " ORDER BY 金額 DESC;" '*************************************************************************** 'SQL文の実行 '*************************************************************************** 'SQLをVariant型の変数に格納(代入)します。 vrtSqlstr01 = Array(strSQL01, strSQL02) '「vrtMakeMsqOwnFileTest01()」関数に、すべての設定を投げつけて、実行させます。 Call vrtMakeMsqOwnFileTest02(strFullName, strFDPath, strImpShtNm99, vrtSqlstr01) End Sub '################################################################################################################################################################### '自ファイルの指定したシートに他ファイルのデータをMicrosoftQueryに読み込む関数 '(A1セルを起点に吸い込み) ' 'strSrcFullPath01 :読み込みたいファイルのフルパスを指定します。一応xlsmやxlsx。xlsの場合は"DriverId=1046;"を"DriverId=790;"に変えたほうがいいかもしれません。 'strSrcFdPath01 :読み込みたいファイルのフォルダパスを指定します。(ファイル名を除いたもの) 'strImpShtNm01 :吸い込みたい自ファイルのシートの名前を指定します。 'vrtSql01 :SQL文を指定します。 ' 句ごとか、一定の文字数(300文字ごとくらい)ごとの ' 配列として扱います。 ' SQLの実行の段階で、MicrosoftQuery(QueryTableオブジェクト)の ' CommandTextプロパティにこの変数に代入したSQL文を渡すのですが、 ' それが「Variant型」の「配列」であるため、 ' ここでもVariant型を使います。 ' '################################################################################################################################################################### Sub vrtMakeMsqOwnFileTest02(strSrcFullPath01 As String, _ strSrcFdPath01 As String, _ strImpShtNm01 As String, _ vrtSQL01 As Variant) Dim Qt_MeQtbl01 As QueryTable Dim strCnn01 As String Dim Ws_MeSht01 As Worksheet Dim objPrms01 As Parameters '*********************************************************************************************************************************** '覗きに行くデータへの接続をするときの、接続文字列の設定。 '接続文字列が横に長くて見にくくなってしまうので、見やすく扱いやすく(書き換えやすく)します。 'いじるのは「DBQ」「DefaultDir」「DriverId」の3つです。DriverIdは「790」でもOKかもしれません。 ' '※設定値の参考Webページ ':https://docs.microsoft.com/ja-jp/sql/odbc/microsoft/odbc-jet-sqlconfigdatasource-excel-driver?view=sql-server-2017 '*********************************************************************************************************************************** strCnn01 = strCnn01 & "ODBC;" strCnn01 = strCnn01 & "DSN=Excel Files;" strCnn01 = strCnn01 & "DBQ=" & strSrcFullPath01 & ";" ' strCnn01 = strCnn01 & "DBQ=D:\1\リレーションテストやSQLで使えるテーブルの範囲のテスト.xlsm;" strCnn01 = strCnn01 & "DefaultDir=" & strSrcFdPath01 & ";" ' strCnn01 = strCnn01 & "DefaultDir=" & ThisWorkbook.Path & ";" strCnn01 = strCnn01 & "DriverId=1046;" '2010の場合? ' strCnn01 = strCnn01 & "DriverId=790;" '97、2000~2003の場合? strCnn01 = strCnn01 & "MaxBufferSize=2048;" strCnn01 = strCnn01 & "PageTimeout=5;" '******************************************************************************* 'もし指定したシートにMicrosoftQueryの結果の表(=QueryTablesオブジェクト)が '無かったら、作って表示させる処理。 '******************************************************************************* '吸い込む自ファイルのシートをオブジェクト変数に代入します。 Set Ws_MeSht01 = Application.ActiveWorkbook.Worksheets(strImpShtNm01) 'メインの処理 If (Ws_MeSht01.QueryTables.Count <= 0) Then '指定したシートにMicrosoftQueryの結果の表が何も無かったら作って終わる。 Set Qt_MeQtbl01 = Ws_MeSht01.QueryTables.Add( _ Connection:=strCnn01, _ Destination:=Ws_MeSht01.Range("A1")) Qt_MeQtbl01.CommandText = vrtSQL01 'SQL文を設定 Qt_MeQtbl01.Refresh 'SQL文の実行と反映 Exit Sub '何もない状態から作ったので、プログラム自体をここで終わらせます。 Else 'もしすでに、指定したシートにMicrosoftQueryの結果の表が 'あったら何もしないで次へ。 End If '******************************************************************************* '既にMicrosoftQueryの表があったら、その SQL内容だけを書き換えて反映させる処理。 '******************************************************************************* 'もし、既存のMicrosoftQueryの表にパラメータが設定されていたらそれを削除。 'パラメータがセルに設定されていた場合、新しいクエリがそのセルにかぶると '動作がおかしくなることがあるため。 Set objPrms01 = Ws_MeSht01.QueryTables(1).Parameters If 1 <= objPrms01.Count Then objPrms01.Delete '実際のSQL文の書き換えと実行 Ws_MeSht01.QueryTables(1).CommandText = vrtSQL01 'SQL文を設定(書き換え) Ws_MeSht01.QueryTables(1).Refresh BackgroundQuery:=False 'SQLの実行と表示 End Sub ' ' |
- 投稿タグ
- 「ニセモノ」への道, 「本物」に近づくために, AccessVBA, Accessの独学, Access操作の基礎, Accesの独学, ADO/DAO, ExcelSQL, ExcelVBA, Excelの独学, Excel操作の基礎, Excel連携VBA, MicrosoftQuery, ODBC, SQL, パソコンでの自動化, マクロ, 独学, 自動化