この記事では、フォルダ内のExcelからプロシージャ名を検索する方法についてご説明します。
【動画】フォルダ内のExcelからプロシージャ名を検索する実際の動き
本題に入る前に、まずは次の動画をご覧ください。
フォルダ内のExcelファイルを一つ一つ開き、CodeModuleプロパティからプロシージャ名を取得し、検索したプロシージャ名をとを突合させて一致しているかを特定します。
もし一致していたら、そのプロシージャ名をシートに出力しています。
マクロ作成の流れ
Excelファイルの例
今回は次のExcelファイルを用意しました。
黄色いセルA2(filePath)には、Excelファイルが格納されている置き場のフルパスを入力します。
黄色いセルA5(findStr)には、モジュール名を検索する文字列を入力します。
「完全一致」(opb_allmatch)のラジオボタンを選択してマクロを実行すると、黄色いセルA5(findStr)に入力されたプロシージャ名が取得されます。
「部分一致」(opb_partmatch)のラジオボタンを選択してマクロを実行すると、黄色いセルA5(findStr)に入力された文字列が含まれるプロシージャ名が取得されます。
【参考】Excelファイルの格納先A2とA5のセルに値を入力し、「完全一致」を選択して実行ボタンをクリックすると、プロシージャ名が取得されてシートの表に出力されます。
今回のサンプルでは、プロシージャ名だけではなくファイル名やプロシージャ名などの情報も表に出力されます。
A2とA5のセルに値を入力し、「部分一致」を選択して実行ボタンをクリックすると、A5のセルに入力された文字列が含まれるプロシージャ名が取得されてシートの表に出力されます。
今回のサンプルでは、プロシージャ名だけではなくファイル名やプロシージャ名などの情報も表に出力されます。
【注意】VBComponentsコレクションを扱うにはある設定を行わないとエラーになり動作しない
VBComponentsコレクションを扱うにはある設定を行わないとエラーになり動作しません。
設定を行わないままVBComponentsコレクションを呼び出そうとすると下のようにエラーが発生して正常に動作しません。
ではその必要な設定はというと、次の画面(トラストセンター画面)で行う「VBA プロジェクト オブジェクト モデルへのアクセスを信頼する」のチェックを付ける設定です。
このチェックを付けておかないとエラーが先ほどのエラーが発生してしまうので、必ずチェックをつけましょう。
なお、チェックを付けるとセキュリティ面が弱くなってしまうデメリットがあるので、もし本マクロを使わないときはチェックを外しておきましょう。
ただし、本マクロを使い終わった後のチェックの有無設定はExcelを使用している端末の環境の仕様を最優先し、その仕様に合わせて行って下さい。
あくまでExcelの設定はお使いの環境の仕様を絶対に守るようお使いくださいね。
トラストセンター画面の開き方及び「マクロの設定」の表示方法
トラストセンター画面の開き方及び「マクロの設定」の表示方法は次の通りです。
①「ファイル」をクリックする
「ファイル」をクリックします。
②「オプション」をクリックする
「オプション」をクリックします。
③「Excelのオプション」画面でトラストセンターをクリックしトラストセンターボタンをクリックする
「Excelのオプション」画面が表示されたら、「トラストセンター」をクリックします。
するとトラストセンターに関する画面が表示されるので、その中にある「トラストセンターの設定」ボタンをクリックします。
④トラストセンター画面の開き方及び「マクロの設定」が表示される
「トラストセンター」画面が表示され、「マクロの設定」をクリックすると、「マクロの設定」に関する画面が表示されます。
手順は以上になります。
コードの例
Option Explicit Private Sub btn_exec_Click() Dim cnt As Long 'カウンタ Dim rowCnt As Long '値を出力する行位置 Dim thisWb As Workbook '本マクロ用のワークブック用変数 Dim ws As Worksheet 'ワークシート用変数 Dim filePath As String 'VBAオブジェクトモジュールの名称を取得したいExcelファイルの格納先 Dim buf As String 'Excelのファイル名を受け取る用の一時格納用変数 Dim fileName As String 'ファイル名 Dim wb As Workbook 'ワークブック用変数 Dim vbComp As Object 'VBProjectのVBComponentsコレクション用変数 Dim aryCnt As Long '配列用カウンタ Dim mdlNM As String 'モジュール名 Dim obj As Object 'CodeModuleオブジェクトを格納するオブジェクト変数 Dim strMatchFlg As Boolean '文字列が条件に合致するか判定するためのフラグ Dim procName As String 'プロシージャ名用変数 Dim scopeStr As String 'スコープ用変数 Dim kindStr As String '種類用変数 'データを出力する行位置 Const bgnRowPos As Long = 8 'プロシージャの数をカウントする用のカウンタを初期化する rowCnt = bgnRowPos '本マクロのブックを取得する Set thisWb = ActiveWorkbook '本マクロのブックのシート名を取得する Set ws = thisWb.Worksheets("work") 'モジュールに関する各情報を出力するセルをクリアする ws.Range("A" & bgnRowPos & ":F40").ClearContents If Right(ws.Range("filePath").Value, 1) <> "\" Then '入力された「Excelファイルの置き場」のフルパスの末尾に「\」が付いていない場合 '「Excelファイルの置き場」のフルパスの末尾に「\」を付けて、フルパスを変数filePathに格納する filePath = ws.Range("filePath").Value & "\" Else '入力された「Excelファイルの置き場」のフルパスの末尾に「\」が付いている場合 '「Excelファイルの置き場」のフルパスを変数filePathに格納する filePath = ws.Range("filePath").Value End If 'VBAオブジェクトモジュールの名称を取得したいExcelファイルを取得する buf = Dir(filePath & "*.xlsm") 'Excelファイルの数だけ処理を繰り返すループ Do While buf <> "" 'B列のセルにファイル名を出力する fileName = buf 'Excelファイルを開き、そのExcelファイルの情報をwbに代入する Set wb = Workbooks.Open(filePath & buf) ' 配列を初期化 ReDim myArray(0) 'VBProjectのVBComponentsコレクション内の各VBComponentに対して以下を繰り返すFor文 For Each vbComp In wb.VBProject.VBComponents '動的配列の再宣言を行う(配列に格納されている値を残したまま) ReDim Preserve myArray(aryCnt) '取得したモジュール名を配列に格納する myArray(aryCnt) = vbComp.Name 'カウンタを1増やす aryCnt = aryCnt + 1 Next vbComp For aryCnt = 0 To UBound(myArray) 'C列のセルにモジュール名を出力する mdlNM = myArray(aryCnt) 'VBComponentsプロパティから取得したVBComponentオブジェクトのCodeModuleオブジェクトを取得する Set obj = wb.VBProject.VBComponents(myArray(aryCnt)).CodeModule With obj '対象モジュールの行数分ループするfor文 For cnt = 1 To .CountOfLines Select Case thisWb.Sheets("work").OptionButtons("opb_allmatch").Value Case 1 'opb_allmatchが選択されている場合 If ws.Range("findStr").Value = .ProcOfLine(cnt, 0) Then 'モジュール名を検索する文字列と、コード上にあるモジュール名が同じ場合 'strMatchFlgにTrueを設定する strMatchFlg = True End If Case Else 'opb_allmatchが選択されていない場合 If InStr(LCase(.ProcOfLine(cnt, 0)), LCase(ws.Range("findStr").Value)) > 0 Then 'コード上にあるモジュール名に、モジュール名を検索する文字列が含まれている場合 strMatchFlg = True End If End Select If strMatchFlg = True Then 'strMatchFlgがTrueの場合 'プロシージャ名を取得してprocNameに格納する procName = .ProcOfLine(cnt, 0) If obj.Lines(cnt, 1) <> "" Then '行が空白でない場合 'スコープの取得 Select Case True Case InStr(LCase(.Lines(cnt, 1)), "public ") > 0 'プロシージャ名が含まれているソースコードに「public 」が含まれている場合 '変数scopeStrに「public」を格納する scopeStr = "public" Case InStr(LCase(.Lines(cnt, 1)), "private ") > 0 'プロシージャ名が含まれているソースコードに「private 」が含まれている場合 '変数scopeStrに「private」を格納する scopeStr = "private" Case InStr(LCase(.Lines(cnt, 1)), "friend ") > 0 'プロシージャ名が含まれているソースコードに「Friend 」が含まれている場合 '変数scopeStrに「friend」を格納する scopeStr = "Friend" Case InStr(LCase(.Lines(cnt, 1)), "static ") > 0 'プロシージャ名が含まれているソースコードに「Static 」が含まれている場合 '変数scopeStrに「static」を格納する scopeStr = "static" End Select '種類の取得 Select Case True Case InStr(LCase(.Lines(cnt, 1)), "sub ") > 0 'プロシージャ名が含まれているソースコードに「sub 」が含まれている場合 '変数kindStrに「sub」を格納する kindStr = "sub" Case InStr(LCase(.Lines(cnt, 1)), "function ") > 0 'プロシージャ名が含まれているソースコードに「function 」が含まれている場合 '変数kindStrに「function」を格納する kindStr = "function" Case InStr(LCase(.Lines(cnt, 1)), "property let ") > 0 'プロシージャ名が含まれているソースコードに「property let 」が含まれている場合 '変数kindStrに「Property Let」を格納する kindStr = "Property Let" Case InStr(LCase(.Lines(cnt, 1)), "property set ") > 0 'プロシージャ名が含まれているソースコードに「property set 」が含まれている場合 '変数kindStrに「property set」を格納する kindStr = "Property Set" Case InStr(LCase(.Lines(cnt, 1)), "property get ") > 0 'プロシージャ名が含まれているソースコードに「property get 」が含まれている場合 '変数kindStrに「Property Get」を格納する kindStr = "Property Get" End Select If scopeStr <> "" Then 'scopeStrに値が存在する場合 'D列のセルに「スコープ」を出力する ws.Range("D" & rowCnt).Value = scopeStr 'scopeStrに空白を設定する scopeStr = "" End If If kindStr <> "" Then 'kindStrに値が存在する場合 'E列のセルに「種類」を出力する ws.Range("E" & rowCnt).Value = kindStr 'F列のセルにプロシージャ名を出力する ws.Range("F" & rowCnt).Value = procName 'A列のセルに「項番」を出力する ws.Range("A" & rowCnt).Value = rowCnt - bgnRowPos + 1 If fileName <> "" Then 'fileNMがブランクではない場合 'B列のセルにファイル名を出力する ws.Range("B" & rowCnt).Value = fileName 'fileNMをブランクにする fileName = "" End If If mdlNM <> "" Then 'mdlNMがブランクではない場合 'C列のセルにモジュール名を出力する ws.Range("C" & rowCnt).Value = mdlNM 'mdlNMをブランクにする mdlNM = "" End If 'procNameを空白に設定する kindStr = "" 'procNameを空白に設定する procName = "" 'rowCntの値を1つ増やす rowCnt = rowCnt + 1 End If End If End If strMatchFlg = False DoEvents Next cnt End With Next Set obj = Nothing '開いたExcelファイルを閉じる Workbooks(buf).Close SaveChanges:=False '次のファイルを取得する buf = Dir() '配列を初期化する Erase myArray 'カウンタを初期化する aryCnt = 0 Loop If rowCnt = bgnRowPos Then 'モジュールが1件もない場合(rowCntの初期値がbgnRowPosの値なので) MsgBox "検索したモジュールが見つかりませんでした" End If '後処理 Set obj = Nothing Set wb = Nothing End Sub
注目すべきコード①
最初に見て頂きたいのは54行目から57行目です。
'VBAオブジェクトモジュールの名称を取得したいExcelファイルを取得する buf = Dir(filePath & "*.xlsm") 'Excelファイルの数だけ処理を繰り返すループ Do While buf <> ""
コードの説明
以上のコードは、今回のサンプルのA2の黄色いセルに入力されたExcelファイルの置き場にあるExcelファイルを取得し、Excelファイルの数だけ処理を繰り返すコードです。
Dir関数の引数にExcelファイルの置き場をフルパスで指定して実行することでExcelファイルを取得することができます。
取得したら変数bufに格納されます。
ちなみに、Excelファイルの置き場の全てを取得するには、290行目のDir関数を繰り返し実行することで取得することができます。
'次のファイルを取得する buf = Dir()
全てのExcelファイルを取得し終わったら、次のDir関数の戻り値がブランクになるのでDo文のループが終了します。
全てExcelファイル名を取得した後にDir関数を実行した直後の状態変数bufがブランクなのでDoループから抜ける
注目すべきコード②
次に見て頂きたいのは63行目です。
'Excelファイルを開き、そのExcelファイルの情報をwbに代入する Set wb = Workbooks.Open(filePath & buf)
コードの説明
以上のコードは、Openメソッドの引数にExcelファイルをフルパスで指定して実行し、そのExcelファイルの情報をwbに代入している処理のコードです。
Openメソッドを実行することでExcelファイルが開かれ、マクロがそのExcelファイルのマクロのコードを参照することができます。
つまり、Excelファイルにどんなモジュールがあるのかや、そのモジュール内にどんなプロシージャがあるのかを特定することができるようになります。
注目すべきコード③
次に見て頂きたいのは66行目から80行目です。
' 配列を初期化 ReDim myArray(0) 'VBProjectのVBComponentsコレクション内の各VBComponentに対して以下を繰り返すFor文 For Each vbComp In wb.VBProject.VBComponents '動的配列の再宣言を行う(配列に格納されている値を残したまま) ReDim Preserve myArray(aryCnt) '取得したモジュール名を配列に格納する myArray(aryCnt) = vbcomp.Name 'カウンタを1増やす aryCnt = aryCnt + 1 Next vbComp
コードの説明
以上のコードは、モジュール名を取得してそのモジュール名を配列に格納する処理のコードです。
コードの詳細
66行目のコードでは、配列myArrayを要素数0で初期化しています。
69行目では、VBProjectのVBComponentsコレクション内の各VBComponentに対して処理を繰り返すFor文を用意し、vbcompにはモジュールが格納されます。
72行目では動的配列の再宣言を行い、75行目ではnameプロパティからモジュールの名称を取得して配列myArrayに格納します。
For文が完了すると、Excelのモジュール名が全て取得されます。
注目すべきコード④
次に見て頂きたいのは88行目です。
'VBComponentsプロパティから取得したVBComponentオブジェクトのCodeModuleオブジェクトを取得する Set obj = wb.VBProject.VBComponents(myArray(aryCnt)).CodeModule
コードの説明
以上のコードは、VBComponentsプロパティから取得したVBComponentオブジェクトのCodeModuleオブジェクトを取得する処理のコードです。
CodeModuleオブジェクトを取得して変数objに格納していますが、このオブジェクトによりVBAのソースコードを参照することができます。
ソースコード内にあるプロシージャを取得するのにこのオブジェクトが必要になります。
注目すべきコード⑤
次に見て頂きたいのは95行目から122行目です。
Select Case thisWb.Sheets("work").OptionButtons("opb_allmatch").Value Case 1 'opb_allmatchが選択されている場合 If ws.Range("findStr").Value = .ProcOfLine(cnt, 0) Then 'モジュール名を検索する文字列と、コード上にあるモジュール名が同じ場合 'strMatchFlgにTrueを設定する strMatchFlg = True End If Case Else 'opb_allmatchが選択されていない場合 If InStr(LCase(.ProcOfLine(cnt, 0)), LCase(ws.Range("findStr").Value)) > 0 Then 'コード上にあるモジュール名に、モジュール名を検索する文字列が含まれている場合 strMatchFlg = True End If End Select If strMatchFlg = True Then
コードの説明
以上のコードは、「完全一致」または「部分一致」が選ばれている場合、モジュール名を検索する文字列がプロシージャ名と一致しているか、またはプロシージャ名の中にモジュール名を検索する文字列が含まれているかを判定する処理のコードです。
以上の条件に当てはまる場合は、変数strMatchFlgにTrueを設定します。
コードの詳細
96行目のコードは、「完全一致」のラジオボタンの選択状態を判定するSelect Caseです。
97行目のコードは、「完全一致」のラジオボタンが選択されている場合(1)に、101行目のコードが実行されます。
101行目のIF文では、黄色いセルA5(findStr)に入力されたプロシージャ名と、コードにあるプロシージャ名が一致するか判定します。
もし一致していれば106行目でstrMatchFlgにTrueを設定します。
「部分一致」が選択されていれば110行目のCase Elseの条件に合致し、114行目のコードが実行されます。
114行目のIF文では、コードにあるプロシージャ名が、黄色いセルA5(findStr)に入力された検索文字列を含まれるか判定します。
もし含まれていれば、118行目でstrMatchFlgにTrueを設定します。
以上でコードに存在するプロシージャ名が、黄色いセルA5(findStr)に入力された検索文字列と合致するか、または含まれるのかを判定しましたが、いずれかの条件に合致している場合、124行目のIF文にあるstrMatchFlgがTrueなのかを判定する条件に合致します。
注目すべきコード⑥
次に見て頂きたいのは98行目です。
'プロシージャ名を取得してprocNameに格納する procName = .ProcOfLine(cnt, 0) If obj.Lines(cnt, 1) <> "" Then
コードの説明
以上のコードは、プロシージャ名の取得と、コードが空白ではないかを判定する処理のコードです。
プロシージャ名を取得したら、次にコードが空白かどうかを判定します。
コードが空白の場合は、プロシージャ名が存在しないため、IFの条件には該当しません。一方、コードが空白でない場合には、このIFの条件に該当します。
注目すべきコード⑦
次に見て頂きたいのは137行目から167行目です。
'スコープの取得 Select Case True Case InStr(LCase(.Lines(cnt, 1)), "public ") > 0 'プロシージャ名が含まれているソースコードに「public 」が含まれている場合 '変数scopeStrに「public」を格納する scopeStr = "public" Case InStr(LCase(.Lines(cnt, 1)), "private ") > 0 'プロシージャ名が含まれているソースコードに「private 」が含まれている場合 '変数scopeStrに「private」を格納する scopeStr = "private" Case InStr(LCase(.Lines(cnt, 1)), "friend ") > 0 'プロシージャ名が含まれているソースコードに「Friend 」が含まれている場合 '変数scopeStrに「friend」を格納する scopeStr = "Friend" Case InStr(LCase(.Lines(cnt, 1)), "static ") > 0 'プロシージャ名が含まれているソースコードに「Static 」が含まれている場合 '変数scopeStrに「static」を格納する scopeStr = "static" End Select
コードの説明
以上のコードは、スコープを取得するコードの処理です。
プロシージャに使われているスコープ(public、private、friend、static)がどれかなのかを判定します。
スコープがどれなのかは、行に対してInStr関数を使って判定します。
コードの詳細
139行目のコードでは、InStrの引数に「public 」を指定し、戻り値が0以上の場合はスコープがpublicなので、144行目で変数scopeStrに「public」を格納しています。
ただしpublicの文字列が「Public」のように大文字小文字が混ざっているかもしれないので、LCase関数を使って文字全てを小文字に変換してからInstr関数を実行しています。
なお、変数scopeStrの値は、シートの表のD列に出力するのに使います。
146行目のコードでは、InStrの引数に「private 」を指定し、戻り値が0以上の場合はスコープがprivateなので、151行目で変数scopeStrに「private」を格納しています。
153行目のコードでは、InStrの引数に「friend 」を指定し、戻り値が0以上の場合はスコープがfriendなので、158行目で変数scopeStrに「friend」を格納しています。
160行目のコードでは、InStrの引数に「static 」を指定し、戻り値が0以上の場合はスコープがstaticなので、165行目で変数scopeStrに「static」を格納しています。
注目すべきコード⑧
次に見て頂きたいのは171行目から208行目です。
'種類の取得 Select Case True Case InStr(LCase(.Lines(cnt, 1)), "sub ") > 0 'プロシージャ名が含まれているソースコードに「sub 」が含まれている場合 '変数kindStrに「sub」を格納する kindStr = "sub" Case InStr(LCase(.Lines(cnt, 1)), "function ") > 0 'プロシージャ名が含まれているソースコードに「function 」が含まれている場合 '変数kindStrに「function」を格納する kindStr = "function" Case InStr(LCase(.Lines(cnt, 1)), "property let ") > 0 'プロシージャ名が含まれているソースコードに「property let 」が含まれている場合 '変数kindStrに「Property Let」を格納する kindStr = "Property Let" Case InStr(LCase(.Lines(cnt, 1)), "property set ") > 0 'プロシージャ名が含まれているソースコードに「property set 」が含まれている場合 '変数kindStrに「property set」を格納する kindStr = "Property Set" Case InStr(LCase(.Lines(cnt, 1)), "property get ") > 0 'プロシージャ名が含まれているソースコードに「property get 」が含まれている場合 '変数kindStrに「Property Get」を格納する kindStr = "Property Get" End Select
コードの説明
以上のコードは、プロシージャまたはpropertyの種類を取得するコードの処理です。
プロシージャに使われているプロシージャまたはpropertyの種類(sub、function、property let、Property Set、Property Get)がどれかなのかを判定します。
スコープがどれなのかは、行に対してInStr関数を使って判定します。
コードの詳細
173行目のコードでは、InStrの引数に「sub 」を指定し、戻り値が0以上の場合はプロシージャの種類がsubなので、178行目で変数scopeStrに「sub」を格納しています。
ただしsubの文字列が「Sub」のように大文字小文字が混ざっているかもしれないので、LCase関数を使って文字全てを小文字に変換してからInstr関数を実行しています。
なお、変数kingStrの値は、シートの表のE列に出力するのに使います。
180行目のコードでは、InStrの引数に「function 」を指定し、戻り値が0以上の場合はプロシージャの種類がfunctionなので、185行目で変数scopeStrに「function」を格納しています。
187行目のコードでは、InStrの引数に「property let 」を指定し、戻り値が0以上の場合はpropertyの種類がproperty letなので、192行目で変数scopeStrに「property let」を格納しています。
194行目のコードでは、InStrの引数に「property set 」を指定し、戻り値が0以上の場合はpropertyの種類がproperty setなので、199行目で変数scopeStrに「property set」を格納しています。
201行目のコードでは、InStrの引数に「property get 」を指定し、戻り値が0以上の場合はpropertyの種類がproperty getなので、206行目で変数scopeStrに「property get」を格納しています。
注目すべきコード⑨
次に見て頂きたいのは210行目から220行目です。
If scopeStr <> "" Then 'scopeStrに値が存在する場合 'D列のセルに「スコープ」を出力する ws.Range("D" & rowCnt).Value = scopeStr 'scopeStrに空白を設定する scopeStr = "" End If
以上のコードは、scopeStrが空白でない場合に、「注目すべきコード⑦」で取得したスコープをD列のセルに出力するコードです。
スコープが取得されてscopeStrに値が格納されていれば、スコープをD列のセルに出力します。
コードの詳細
210行目のコードでは、scopeStrに値(スコープ)が格納されているか判定します。
もしscopeStrに値(スコープ)が格納されている場合は、215行目でD列のセルにscopeStrの値(スコープ)を出力します。
218行目のコードでは、scopeStrに空白を設定しています。
次に見つけたプロシージャにスコープが無い場合にscopeStrの値(スコープ)が入ったままだと、そのままスコープがD列のセルに出力されてしまうので空白を設定しておきます。
注目すべきコード⑩
次に見て頂きたいのは210行目から220行目です。
If kindStr <> "" Then 'kindStrに値が存在する場合 'E列のセルに「種類」を出力する ws.Range("E" & rowCnt).Value = kindStr 'F列のセルにプロシージャ名を出力する ws.Range("F" & rowCnt).Value = procName 'A列のセルに「項番」を出力する ws.Range("A" & rowCnt).Value = rowCnt - bgnRowPos + 1 If fileName <> "" Then 'fileNMがブランクではない場合 'B列のセルにファイル名を出力する ws.Range("B" & rowCnt).Value = fileName 'fileNMをブランクにする fileName = "" End If If mdlNM <> "" Then 'mdlNMがブランクではない場合 'C列のセルにモジュール名を出力する ws.Range("C" & rowCnt).Value = mdlNM 'mdlNMをブランクにする mdlNM = "" End If 'procNameを空白に設定する kindStr = "" 'procNameを空白に設定する procName = "" 'rowCntの値を1つ増やす rowCnt = rowCnt + 1 End If
コードの説明
以上のコードは、「注目すべきコード⑩」で取得したプロシージャの種類が空白でない場合に、以下の情報を各列に出力するコードです。
– 項番:A列
– ファイル名:B列
– モジュール名:C列
– プロシージャ種類:E列
– プロシージャ名:F列
今回のサンプルでは、プロシージャ名だけでなく、ファイル名やモジュール名なども出力するようにしています。
また、kindStrとprocNameを空白にし、rowCntとprocNumの値を1つ増やしています。
コードの詳細
222行目のコードでは、kindStrに値(プロシージャの種類)が格納されているか判定します。
もしkindStrに値(プロシージャの種類)が格納されている場合は、227行目でE列のセルにkindStrの値(プロシージャの種類)を出力します。
230行目のコードでは、F列のセルにプロシージャ名を出力します。
233行目のコードでは、A列のセルに項番を出力します。
235行目のコードではfileNameが空白でないかを判定し、fileNameが空白でない場合に240行目でB列のセルにファイル名を出力します。
ファイル名を出力し終わったので、243行目のコードではfileNameを空白を設定しておきます。
247行目のコードではmdlNMが空白でないかを判定し、mdlNMが空白でない場合に252行目でC列のセルにモジュール名を出力します。
モジュール名を出力し終わったので、255行目のコードではmdlNMを空白を設定しておきます。
260行目ではkindStrに空白を、263行目のコードではprocNameに空白を設定しています。
266行目のコードではrowCntに1を増やしています。
注目すべきコード⑪
次に見て頂きたいのは284行目から287行目です。
Set obj = Nothing '開いたExcelファイルを閉じる Workbooks(buf).Close SaveChanges:=False
コードの説明
以上のコードは、obj変数にNothingを代入してメモリを解放し、開いているExcelファイルを閉じる処理のコードです。
以上のコードまでで、1つのExcelファイル内のモジュール名とプロシージャ名が全て取得し終わったので、メモリを解放と開いているExcelファイルを閉じる処理を行います。
なお、Excelファイルはあくまでモジュール名とプロシージャ名を取得するためだけに開いたので、Excelファイルを閉じる場合は何も変更しないでおきたいです。
Excelファイルに何も変更しないで閉じる場合は、251行のコードのようにcloseメソッドの引数SaveChangesにFalseを指定して実行します。
これでExcelファイルは何も変更されずに閉じることができます。
動作確認
【テスト①】マクロ実行前:完全一致で検索する場合
今回は以下のファイルを用意しました。
Excelファイルの格納先をA2の黄色のセルに、A5の黄色のセルにモジュール名を検索する文字列を入力しています。
また、「完全一致」のラジオボタンを選択しています。
以上の内容で実行ボタンをクリックします。
【テスト①】マクロ実行後:完全一致で検索する場合
モジュール名や、他にもモジュール名やファイル名などがシートに表に出力されました。
なお、以下のプロシージャ名を取得しています。
【テスト②】マクロ実行前:部分一致で検索する場合
今回は以下のファイルを用意しました。
Excelファイルの格納先をA2の黄色のセルに、A5の黄色のセルにモジュール名を検索する文字列を入力しています。
また、「部分一致」のラジオボタンを選択しています。
以上の内容で実行ボタンをクリックします。
【テスト②】マクロ実行後:部分一致で検索する場合
モジュール名や、他にもモジュール名やファイル名などがシートに表に出力されました。
なお、以下のプロシージャ名を取得しています。
最後に
この記事では、フォルダ内のExcelからプロシージャ名を検索する方法についてご説明しました。
Excelにあるプロシージャ名を検索するには、VBEをわざわざ開かないと検索できません。
Excelファイルを開いてVBE上で検索するのが面倒だと感じている場合に、今回紹介したマクロを使えばお手軽にフォルダ内のExcelからプロシージャ名を検索して探し出すことができるので参考にしてみてくださいね。
プログラミングのスキルを習得するなら
プログラミングのスキルを習得したい、今のスキルをもっと高めたい、そう考えているなら「プログラミングスクール」がおすすめです。
プログラミングのスキルの基礎を身につけるなら「TechAcademy」で1週間の無料体験があるので、これで「プログラミングの基礎」を学ぶのにおすすめですよ。