【Window業務効率化】バッチファイルとGetObjFmAccdb で Access のクエリをSQL抽出し、VBAスニペットを生成しよう

バッチファイルとGetObjFmAccdb で Access のクエリをSQL抽出し、VBAスニペットを生成しよう

この記事では、特定のフォルダ内にある「*.accdb」形式のAccessプロジェクトファイルに含まれるクエリを抽出する方法を紹介します。

具体的には、

  • GetObjFmAccdb.bat 
  • GetObjFmAccdb.exe

というバッチファイルとユーティリティプログラムを使用して、クエリをSQLファイルとして抽出し、さらにここからVBAのスニペット(注1)を生成します。

これらのツールを用いて*.accdb ファイル中に含まれるクエリをテキスト形式のSQLファイルやVBAのスニペットとして保存しておくと、Accessファイル内のクエリをSubversion のクライアント TortoiseSVN による差分管理ができるようになります。

また将来的にあなたの Access ツールをアップサイジングし、SQL Server をバックエンドとしたユーザー向けのフロントエンドとしてリファクタリングする際 、このVBAのスニペットの再利用があなたの生産性を爆上げすることは確実です。

しらかば堂

こんにちわ。しらかば堂です。
この記事が少しでも皆さんのお役に立てれば幸いです。

(注1) スニペット(英語: snippet)は、「断片」という意味で、再利用可能なソースコード、またはテキストの小さな領域を表すプログラミング用語です。

ツール開発の背景

それではまずこのツールの利用方法のイメージを理解しやすいよう、以下の記事

に登場する

  • 作成T2040日付女性入院者数男性入院者数_xlsx.accdb

というプロジェクトファイルに対し次の記事

で紹介した方法でマクロをVBAに変換した次のプロジェクトファイルをサンプルとして使用してみましょう。

作成T2040日付女性入院者数男性入院者数_xlsx.accdb の クエリ、マクロの実装状況


このプロジェクトファイルの中では、もともとautoexec マクロに定義されていたマクロがVBAに変換され、 main マクロから呼び出されているModule1 モジュール内のMain()関数として既に展開されています。

作成T2040日付女性入院者数男性入院者数_xlsx.accdb の Module1 内を VBA で参照する部分


これでリファクタリングの際、アクションマクロとVBAの中をいったり来たりしなくて済むのでツール全体の動作は直観的に理解できるようになったわけですが、ここまでくると続いて次のような願望も湧き上がってきますね。

みなみ

ところで DoCmd.OpenQuery で実行しているクエリが実際に何をしてるかって、結局それぞれのクエリをマクロのデザインビューで見てみないとわかんないじゃないですか。

これってなんかいい方法ないんですか?

しらかば堂

そうですね。

そうやってクエリを初心者にも簡単なグラフィカルなデザインピューで視覚的に作れるのがAccessの長所でもあるわけなんですが

みなみさんのスキルレベルが爆上がりして Subversion ToutoiseSVNを使いこなせるようになると当然そうした要望も出てきますよね。

今回ご紹介するツールはその願望を解決するために開発したんですよ~。


利用方法

それではこのツールの利用方法を具体的に紹介していきましょう。

まず先ほどご紹介したバッチファイル、ユーティリティプログラムを

  • %USERPROFILE%\Tools\bat\GetObjFmAccdb.bat
  • %USERPROFILE%\Tools\exe\GetObjFmAccdb.exe

配下に配置し

またこの GetObjFmAccdb.bat のコピーを以下のようにターゲットファイル

  • 作成T2040日付女性入院者数男性入院者数_xlsx.accdb

と同じフォルダに格納します。

GetObjFmAccdb.bat 実行前のフォルダ状況
しらかば堂

GetObjFmAccdb.bat のコピーをターゲットとなるVBAコードを含む*.accdbと同じフォルダ配下に配置するのは、このバッチファイルのダブルクリックでファイル名を指定せずに *.sql*.bas ファイルを抽出できるようにするためです。

ちなみにこのExportVBAcodeFromAccdb.bat は下記の記事でご紹介したもので、今回ご紹介する GetObjFmAccdb.batExportVBAcodeFromAccdb.bat のVBAコード抽出機能を包含しているためここでは利用しません。


この状態で GetObjFmAccdb.bat をダブルクリックして起動するとコマンドライン上に以下のような実行履歴が残り

C:\Home\0385\accdb4>GetObjFmAccdb.bat

C:\Home\0385\accdb4>rem @echo off

C:\Home\0385\accdb4>setlocal

C:\Home\0385\accdb4>C:\Users\shirakabado\Tools\exe\GetObjFmAccdb.exe /h

GetObjFmAccdb.exe[評価版] : ver 1.230 (2023/10/07 06:15:48)

使用方法:

>GetObjFmAccdb /h              ... このヘルプを出力します

>GetObjFmAccdb /v sample.accdb ... sample.accdb ファイルからVBAコードを抽出し、モジュール名.basを出力します

>GetObjFmAccdb /s sample.accdb ... sample.accdb ファイル内のクエリをSQLとして抽出し、クエリ名.sqlを出力します

>GetObjFmAccdb /c sample.sql   ... sample.sql ファイルをVBA変換し、sample.basを出力します

C:\Home\0385\accdb4>taskkill /f /im msaccess.exe  1>nul 2>&1

C:\Home\0385\accdb4>for %f in (*.accdb) do (
"%~ff" /decompile /x exit
 C:\Users\shirakabado\Tools\exe\GetObjFmAccdb.exe /v "%~ff"
 C:\Users\shirakabado\Tools\exe\GetObjFmAccdb.exe /s "%~ff"
)

C:\Home\0385\accdb4>(
"C:\Home\0385\accdb4\作成_T2040_日付_女性入院者数_男性入院者数_xlsx.accdb" /decompile /x exit
 C:\Users\shirakabado\Tools\exe\GetObjFmAccdb.exe /v "C:\Home\0385\accdb4\作成_T2040_日付_女性入院者数_男性入院者数_xlsx.accdb"
 C:\Users\shirakabado\Tools\exe\GetObjFmAccdb.exe /s "C:\Home\0385\accdb4\作成_T2040_日付_女性入院者数_男性入院者数_xlsx.accdb"
)

C:\Home\0385\accdb4>for %f in (*.sql) do (
C:\Users\shirakabado\Tools\exe\GetObjFmAccdb.exe /c "%~ff"
 rem del  "%~ff"
)

C:\Home\0385\accdb4>(
C:\Users\shirakabado\Tools\exe\GetObjFmAccdb.exe /c "C:\Home\0385\accdb4\Q2000_作成_T2000_日付.sql"
 rem del  "C:\Home\0385\accdb4\Q2000_作成_T2000_日付.sql"
)

C:\Home\0385\accdb4>(
C:\Users\shirakabado\Tools\exe\GetObjFmAccdb.exe /c "C:\Home\0385\accdb4\Q2020_作成_T2020_日付_男性_入院者数.sql"
 rem del  "C:\Home\0385\accdb4\Q2020_作成_T2020_日付_男性_入院者数.sql"
)

C:\Home\0385\accdb4>(
C:\Users\shirakabado\Tools\exe\GetObjFmAccdb.exe /c "C:\Home\0385\accdb4\Q2030_作成_T2030_日付_女性_入院者数.sql"
 rem del  "C:\Home\0385\accdb4\Q2030_作成_T2030_日付_女性_入院者数.sql"
)

C:\Home\0385\accdb4>(
C:\Users\shirakabado\Tools\exe\GetObjFmAccdb.exe /c "C:\Home\0385\accdb4\Q2040_作成_T2040_日付_女性入院者数_男性入院者数.sql"
 rem del  "C:\Home\0385\accdb4\Q2040_作成_T2040_日付_女性入院者数_男性入院者数.sql"
)

C:\Home\0385\accdb4>pause
続行するには何かキーを押してください . . .

 

そして結果的に以下のように赤枠で囲った *.bas*.sql ファイルが自動作成されます。

Module 毎に抽出されたVBAコード

ここでModule 毎に抽出されたVBAコードは例えば以下のようなものになります。

Module Module1
Option Compare Database

Function Main()
    
    Const C_SUCCESS As Integer = 0
    Const C_FAILURE As Integer = 1
    
    DoCmd.SetWarnings False
    
    If (LinkExternalDbTable("Tools\accdb\作成_T0000_東京都コロナ発症状況_マスタ.accdb", "T0000_東京都コロナ発症状況_マスタ") = 0) Then
    Else
        Beep
        MsgBox "Link に失敗しました", vbOKOnly, ""
        Main = C_FAILURE
        Exit Function
    End If
    
    DoCmd.SetWarnings False
    DoCmd.OpenQuery "Q2000_作成_T2000_日付", acViewNormal, acEdit
    DoCmd.OpenQuery "Q2020_作成_T2020_日付_男性_入院者数", acViewNormal, acEdit
    DoCmd.OpenQuery "Q2030_作成_T2030_日付_女性_入院者数", acViewNormal, acEdit
    DoCmd.OpenQuery "Q2040_作成_T2040_日付_女性入院者数_男性入院者数", acViewNormal, acEdit
    
    Call ExportTableToBook("T2040_日付_女性入院者数_男性入院者数", "Tools_Data_Temp\xlsx\T2040_日付_女性入院者数_男性入院者数.xlsx")
    
    DoCmd.Quit acSave
    
    Main = C_SUCCESS
    
End Function

クエリから抽出されたSQL

次にクエリから抽出されたSQLは以下のようなものになります。このSQLはAccess内の同名のクエリをデザインモード(SQLビュー)で参照した際のテキストと同じものです。

SELECT T0000_東京都コロナ発症状況_マスタ.公表_年月日 AS 日付 INTO T2000_日付
FROM T0000_東京都コロナ発症状況_マスタ
GROUP BY T0000_東京都コロナ発症状況_マスタ.公表_年月日;

SQLから生成されたVBAスニペット

そしてこのSQLから生成されたVBAスニペットコードは以下のようなものになります。

Dim strSQL As String

strSQL = "SELECT T0000_東京都コロナ発症状況_マスタ.公表_年月日 AS 日付 INTO T2000_日付  " & _
         "FROM T0000_東京都コロナ発症状況_マスタ " & _
         "GROUP BY T0000_東京都コロナ発症状況_マスタ.公表_年月日;"

DoCmd.RunSQL strSQL
みなみ

わぁ~これあると便利かも~

解決できること

これらのツールと Subversion クライアント TortoiseSVN を利用すると

  1. クエリを含む .accdb ファイルの クエリに修正をかける
  2. GetObjFmAccdb.bat を起動し、クエリのSQLテキスト、そのVBAスニペットを生成する
  3. TortoiseSVN で上記修正に対する差分を抽出する
  4. 上記の差分も含めた全てをTortoiseSVN を使ってリポジトリにコミットする

といった一連の作業によリ、VBAコードの差分管理に加えてクエリの差分管理もできるようになります。

そしてこのSubversion Redmine と連携していれば、さらに問題(チケット)管理と修正したクエリの紐づけができるようになり、個人、チームでのクエリ開発の変更の可視化、維持管理に計り知れないメリットを提供します。

例えばここでサンプルとして紹介している

  • 作成T2040日付女性入院者数男性入院者数_xlsx.accdb

内の Q200_作成_T2000_日付 クエリの選択項目に以下のように 患者_年代 というフィールドを追加後

VBAコード修正、VBAコード抽出後の Sample.accdb 格納フォルダ


この GetObjFmAccdb.bat を実行すると TortoiseSVNの機能により変更のあったファイルのアイコンが赤いに変わります。

しらかば堂

さらに、TortoiseSVN Q2000_作成T2000日付.sqlQ2000_作成T2000日付.bas の差分比較すると以下のようにピンポイントで修正前後のSQL、VBAスニペットが見えるようになります
凄くないですか?

TortouseSVN で ワークスペースの Q2000_作成T2000日付.sql とリポジトリとの差分表示画面
TortouseSVN で ワークスペースの Q2000_作成T2000日付.bas とリポジトリとの差分表示画面

読んでほしい方

  • Access VBAを使った業務効率化に取り組まれている方
  • Subversion を使った開発リソースの差分管理を実施中、もしくは検討されている方
  • Access VBA、およびクエリの維持管理の継承性を考慮している方、または苦労されている方

GetObjFmAccdb.bat の紹介

保存場所

本記事ではこのバッチファイルを以下の記事も参考にしながら

  • %USERPROFILE%\Tools\bat\GetObjFmAccdb.bat

に保存し、そのコピーをVBAコードを抽出したい .accdb ファイルが格納されているフォルダに保存します。%USERPROFILE% については必要に応じて以下の記事も参照ください。

詳細

このバッチファイル GetObjFmAccdb.bat は以下の記事で紹介している

ExportVBAcodeFromAccdb.bat の機能に加え、Accessプロジェクト(.accdbファイル)内の定義済のクエリ定義を SQL フォーマットのテキストとしてエクスポートし、さらにそのVBAスニペットを生成するためのものです。

rem @echo off
setlocal

%USERPROFILE%\Tools\exe\GetObjFmAccdb.exe /h

taskkill /f /im msaccess.exe >nul 2>&1

for %%f in (*.accdb) do (
    "%%~ff" /decompile /x exit
    %USERPROFILE%\Tools\exe\GetObjFmAccdb.exe /v "%%~ff" 
    %USERPROFILE%\Tools\exe\GetObjFmAccdb.exe /s "%%~ff" 
)

for %%f in (*.sql) do (
    %USERPROFILE%\Tools\exe\GetObjFmAccdb.exe /c "%%~ff" 
rem del  "%%~ff" 
)

pause
endlocal

GetObjFmAccdb.batの簡単な説明

行番号 説明
1 このバッチファイルで echo コマンド を除いた以後の実行コマンドそのもの、あるいはその実行結果を以下のようにコマンドプロンプト上に表示しないように指定
2 一時的な環境変数を作成し、スクリプト内での変更を限定します。
4 GetObjFmAccdb の評価版/有償版識別のためのヘルプ情報を出力します
6 現在実行中の msaccess.exe という名前のプロセスを念のため強制終了します。エラーメッセージは表示せず、結果を無視します。
8 現在のフォルダ内のすべての .accdbファイルに対して12行までの処理を繰り返すためのループです。
9 %%~ff で指定された現在処理中の.accdb データベースに対しVBAコードをデコンパイル(注1)します。”~”は指定されたパラメータから “” を取る修飾子です(注2)
10 %%~ff で指定された現在処理中の.accdb データベースをパラメータとして
%USERPROFILE%\Tools\exe\GetObjFmAccdb.exe /v
つまりVBA抽出機能を呼び出します。
11 %%~ffで指定された現在処理中の.accdb データベースをパラメータとして
%USERPROFILE%\Tools\exe\GetObjFmAccdb.exe /s
つまりSQL抽出機能を呼び出します。
14 現在のフォルダ内のすべての .sql ファイルに対して17行までの処理を繰り返すためのループです。
15 %%~ffで指定された現在処理中の.sql ファイルをパラメータとして
%USERPROFILE%\Tools\exe\GetObjFmAccdb.exe /c
つまりSQLのVBAスニペット生成機能を呼び出します。
16 .bas ファイルの作成された .sql が冗長と考える利用者向けに必要に応じて .sql ファイルを削除する為のもので、削除したいときは rem を外し有効化します。
19 GetObjFmAccdb の評価版/有償版識別のためのヘルプ情報を確実に参照できるようここで一旦ポーズします。必要に応じて削除してください。
20 setlocalで作成した一時的な環境変数を破棄し、元の状態に戻します。
参考情報

(注1) /decompile スイッチはAccess の起動スイッチの一つで、VBA抽出の前に既にコンパイル済のVBAコードを未コンパイル状態に戻します。

ここではこの /decompile スイッチを /x exit スイッチと一緒に利用し、以下の exit マクロを呼び出し Access を終了するところまでを一気に実行しています。

Sample.accdb 内exit マクロ

詳細については必要に応じて以下の記事も参照ください。


(注2) バッチファイルのパラメータの修飾子の使い方については必要に応じて以下の記事も参照ください。

GetObjFmAccdb.exe の紹介

保存場所

バッチファイルと同様に

  • %USERPROFILE%\Tools\exe\GetObjFmAccdb.exe

に保存します。

入手方法

この GetObjFmAccdb.exeファイル はしらかば堂が開発したユーティリティプログラムで以下の2種類のインストーラを準備しており、インストーラを使って上記のフォルダに GetObjFmAccdb.exe として保存可能です。

しらかば堂

まず無償の評価版でその動作、効果を体感して頂き、気に入って頂けた方は有償版の購入をご検討くださいね。

評価版 有償版
説明 インストーラ入手先
価格 無償 3,000円
利用可能期間 1カ月 無制限
機能 ヘルプ(注2)
.accdb からの .bas 抽出(注3)
.accdb からの .sql 抽出(注4)
.sql からの .bas 生成(注5)  

(注2) ヘルプ … この GetObjFmAccdb コマンドで利用可能なコマンドスイッチ、使い方を表示します。

(注3) .accdb からの .bas 抽出 … 例えば Sample.accdb の中に VBA コードを含むフォームモジュール、標準モジュール、クラスモジュールが定義されているとき、/v スイッチを使用してこれらのモジュールからVBAコードを モジュール名.bas として抽出します。

(注4) .accdb からの .sql 抽出例えば Sample.accdb の中にクエリ定義が存在する場合、/q スイッチを使用してこれらのクエリをSQLテキスト クエリ名.sql として抽出します。

(注5) .sql からの .bas 生成 /c スイッチを使って上記機能で抽出された クエリ名.sql を入力とした VBA スニペットコード クエリ名.bas を生成します。

起動スイッチ

Windows 10 のコマンドプロンプト配下でこの GetObjFmAccdb.exe のヘルプ機能を実行すると以下のようになります。

>GetObjFmAccdb /h

GetObjFmAccdb.exe : ver 1.230 (2023/10/07 06:15:48)

使用方法:

>GetObjFmAccdb /h              ... このヘルプを出力します

>GetObjFmAccdb /v sample.accdb ... sample.accdb ファイルからVBAコードを抽出し、モジュール名.basを出力します

>GetObjFmAccdb /s sample.accdb ... sample.accdb ファイル内のクエリをSQLとして抽出し、クエリ名.sqlを出力します

>GetObjFmAccdb /c sample.sql   ... sample.sql ファイルをVBA変換し、sample.basを出力します

>

まとめ

この記事では、特定のフォルダ内にある「*.accdb」形式のAccessプロジェクトファイルに含まれるクエリを抽出する方法を紹介しました。

具体的には、

  • GetObjFmAccdb.bat 
  • GetObjFmAccdb.exe

というバッチファイルとユーティリティプログラムを使用して、クエリをSQLファイルとして取り出し、さらにそのSQLファイルからVBAのスニペット(注1)を生成する手順を説明しました。

これらのツールを用いて*.accdb ファイル中に含まれるクエリをテキスト形式のSQLファイルやVBAのスニペットとして保存しておくことで、Accessファイル内のクエリをSubversion のクライアント TortoiseSVN による差分管理ができるようになります。

また将来的にあなたの Access ツールをアップサイジングし、SQL Server をバックエンドとしたユーザー向けのフロントエンドとしてリファクタリングする際 、このVBAのスニペットの再利用があなたの生産性を爆上げすることは確実です。

この記事が少しでも皆さんのお役に立てれば幸いです。