[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メソッドを使用すれば良い。

ただ、RubberDuckなどの拡張アドインをいれている場合は、
そちらのエクスポート機能を使用したほうが手早い。

また、
この関数で、
クエリの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 "------"  }  

結果は例えばこのようになる。

Grep結果01

Grep結果02

関連記事

comments powered by Disqus

Translations: