[VBA, PowerShell] Accessのモジュール・クラスやクエリのSQLから特定文字列を抽出するためのテクニック
概要
この記事について
AccessのVBAツールを作成していると、
主にリファクタリングや機能追加のタイミングで、
モジュール、クラス、あるいはクエリのソース(SQL)から
特定の文字列をサーチして抽出したいことがあるかもしれない。
モジュール・クラスの場合はVBエディタ画面でctrl+Fを実行すれば可能だが、一覧でヒットした箇所を表示できないため、
全体を把握するのが大変だ。
また、クエリのSQLからサーチする機能は無いかと思う。
そのため、私は以下のようにして、
一度それぞれのデータをファイルとして取り出したあとに
PowerShellのコマンドでLinuxのGrepコマンド風に文字列を抽出している。
作成環境
- Windows10 Home
- MSOffice 2019
- PowerShell 5.1
テクニック
それぞれのデータをファイルとして取り出す
about
モジュールやクラスは、
VBAを用いてすべて一括でファイルとして取り出すことができる。
VBComponentオブジェクトのExportメソッドを使用すれば良い。
そちらのエクスポート機能を使用したほうが手早い。
また、
この関数で、
クエリのSQLも同時にsqlファイルとして取り出す。
コード
1'******************************************************************************************
2'*関数名 :exportCodesSQLs
3'*機能 :モジュール・クラスのコード及びクエリのSQLの出力
4'*引数 :
5'******************************************************************************************
6Sub exportCodesSQLs()
7
8 '定数
9 Const FUNC_NAME As String = "XXX"
10
11 '変数
12 Dim outputDir As String
13 Dim vbcmp As Object
14 Dim fileName As String
15 Dim ext As String
16 Dim qry As QueryDef
17 Dim qName As String
18
19
20
21 On Error GoTo ErrorHandler
22
23 outputDir = _
24 Access.CurrentProject.Path & _
25 "\" & _
26 "src_" & _
27 Left(Access.CurrentProject.Name, InStrRev(Access.CurrentProject.Name, ".") - 1)
28 If Dir(outputDir, vbDirectory) = "" Then MkDir outputDir
29
30 'モジュール・クラスの出力
31 For Each vbcmp In VBE.ActiveVBProject.VBComponents
32 With vbcmp
33 '拡張子
34 Select Case .Type
35 Case 1
36 ext = ".bas"
37 Case 2, 100
38 ext = ".cls"
39 Case 3
40 ext = ".frm"
41 End Select
42
43 fileName = .Name & ext
44 fileName = gainStrNameSafe(fileName) 'ファイル名に使用できない文字を置換
45 If fileName = "" Then GoTo ExitHandler
46
47 'output
48 .Export outputDir & "\" & fileName
49
50 End With
51 Next vbcmp
52
53 'SQLの出力
54 With CreateObject("Scripting.FileSystemObject")
55 For Each qry In CurrentDb.QueryDefs
56 Do
57 qName = gainStrNameSafe(qry.Name) 'ファイル名に使用できない文字を置換
58 If qName = "" Then GoTo ExitHandler
59
60 If qName Like "Msys*" Then Exit Do 'システム関連クエリは除外
61
62 With .CreateTextFile(outputDir & "\" & qName & ".sql")
63 .write qry.SQL
64 .Close
65 End With
66 Loop While False
67 Next qry
68 End With
69
70ExitHandler:
71
72 Exit Sub
73
74ErrorHandler:
75
76 MsgBox "エラーが発生したため、マクロを終了します。" & _
77 vbLf & _
78 "関数名:" & FUNC_NAME & _
79 vbLf & _
80 "エラー番号:" & err.Number & vbNewLine & _
81 err.description, vbCritical, "マクロ"
82
83 GoTo ExitHandler
84
85End Sub
86
87
88
89
90'******************************************************************************************
91'*関数名 :gainStrNameSafe
92'*機能 :ファイル名に使用できない文字をアンダースコアに置換する
93'*引数 :対象の文字列
94'*戻り値 :置換後文字列
95'******************************************************************************************
96Public Function gainStrNameSafe(ByVal s As String) As String
97
98 '定数
99 Const FUNC_NAME As String = "gainStrNameSafe"
100
101 '変数
102 Dim x As Variant
103
104 On Error GoTo ErrorHandler
105
106 gainStrNameSafe = ""
107
108 For Each x In Split("\,/,:,*,?,"",<,>,|", ",") 'ファイル名に使用できない文字の配列
109 s = Replace(s, x, "_")
110 Next x
111
112 gainStrNameSafe = s
113
114ExitHandler:
115
116 Exit Function
117
118ErrorHandler:
119
120 MsgBox "エラーが発生したため、マクロを終了します。" & _
121 vbLf & _
122 "関数名:" & FUNC_NAME & _
123 vbLf & _
124 "エラー番号:" & err.Number & vbNewLine & _
125 err.description, vbCritical, "マクロ"
126
127 GoTo ExitHandler
128
129End Function
exportCodesSQLsを実行すれば、
Accessファイルの置かれているディレクトリの「src_Accessファイル名」フォルダに
各種ソースファイルが格納される。
PowerShellのコマンドで文字列を抽出する
about
PowerShellを起動し、
エクスポートされたファイルのディレクトリに移動する。
LinuxのGrep風に
文字列をサーチして一覧表示するコマンドは、
以下のようにした。
1Get-ChildItem | ForEach-Object{ Write-Output ($_.Name + "`r`n------") ; (Get-Content $_ | Select-String "ここにサーチしたい文字列を記入する" ) | ForEach-Object{Write-Output ($_.lineNumber.Tostring() + ":" + $_) } ;Write-Output "------" }
最初にサーチ対象ファイル名が表示され、ヒットした行番号とその行の文字列が出力される。
これをファイルごとにループさせる。
例
例えば、全てのファイルから
「ID」という文字列をサーチして一覧で表示したい場合、
次のようにコマンドを実行する。
1Get-ChildItem | ForEach-Object{ Write-Output ($_.Name + "`r`n------") ; (Get-Content $_ | Select-String "ID" ) | ForEach-Object{Write-Output ($_.lineNumber.Tostring() + ":" + $_) } ;Write-Output "------" }
結果は例えばこのようになる。
関連記事
- [VBA] クラスを利用するメリットと方法について & 簡単なサンプル(2)
- [Access VBA] サブフォーム上のレコードを挿入、削除する簡単なサンプル
- [Access VBA] フォームのコントロールに対してWithEventsでイベントリスナークラスを作成する際に気をつけなければならないこと
- [Access VBA] デザインビューのテーブル定義を表形式でエクスポートするAccessツールを作成した
- [Access VBA] デザインビューのテーブル定義を表形式でエクスポートする関数を作成した