レシピ
OS:Windows
使用言語:Excel/VBA(Excel 2003で検証していますが2000でも動くでしょう)

 今回は指定されたフォルダにあるソースコードから,関数(function)を抜き出して一覧にするExcel/VBAのプログラムです。functionと書かれている次の行も抜き出してコメントとして抽出します。仕事で「関数の一覧をExcelで出して」とよく言われるので作ってみました。「簡易ドキュメント生成マクロ」とでも命名しておきます。


リスト1●functionの付く関数名とそのコメントを抽出するプログラム(Excel/VBA)のソースコード
[画像のクリックで拡大表示]

図1●リスト1を使って,PHPのプログラム・ファイルから関数名を抽出したところ
[画像のクリックで拡大表示]

 プログラミングも場数を踏んでいくと,頻繁に使う機能を集めた自前のライブラリができあがってきます。ましてや昨今では開発言語のオブジェクト指向化も進んでいて,結構な数のクラスライブラリを使いまわしたりする時代になりました。自分で作ったものとはいえ,しばらく使っていないとどんな関数やクラスを組み込んでいたのか記憶が薄れていきます。「ソースの中のコメントを読めばいい」と考えがちですが,共同作業のプロジェクトなどを経験すると,他人が作ったライブラリをいちいちコメントを頼りにして解読していくというのが本当に面倒な作業だということを実感できます。ここはやはり“関数一覧表”(あるいはクラス一覧表)を作っておくのが仲間のためでもあり,最終的には質問攻めにあわないですむ自分のためにもなりそうです。




 リスト1[拡大表示]がサンプル・プログラムのコードです。私の環境をベースにしているのでPHPソースから関数を抜き出すという作りになっています(図1[拡大表示])。全体の流れを説明しましょう。起動するとまずInputBoxダイアログを表示して,検索するフォルダ名を聞いてきます。フォルダ名はドライブ名を含めて“C:\foo”のように指定してください。フォルダ名を入力すると,プログラムはそのフォルダ内で,ファイル名に「.php」を含むものをピックアップします。続いて,ピックアップしたファイルを一つずつ開いて,ファイルの中で“function”という文字列を含む行を抽出します。functionの行を抽出できたら,“function”(functionの後のスペースも取ってます)という文字を削り取り,セルに関数名として書き出します。さらに,関数名の次の行も読み込んで,“//”を削り取ってコメントとしてセルに書き出します。なおサンプルは/* ~*/型の複数行コメントには対応していません。フォルダからのファイル情報取得にはFilesコレクションを,各ファイル内容の取得にはFileSystemObjectを使用しています。

リスト1●functionの付く関数名とそのコメントを抽出するプログラム(Excel/VBA)のソースコード
Sub PickupFunction()
 DirName = InputBox("関数を抽出するフォルダ名")
 If DirName = "" Then
  MsgBox "フォルダ名未入力"
  Exit Sub
 End If
 ChDir DirName 'フォルダ移動

 Set FSO = CreateObject("Scripting.FileSystemObject")
 Set FOL = FSO.GetFolder(DirName)
 Set FIL = FOL.Files

 ThisWorkbook.Sheets("Sheet1").UsedRange.Delete

 ThisWorkbook.Sheets(1).Range("B2") = "ファイル名"
 ThisWorkbook.Sheets(1).Range("C2") = "関数名"
 ThisWorkbook.Sheets(1).Range("D2") = "コメント"

 i = 3

 For Each Fx In FIL
  sFILE = Fx.Name 'ファイル名

  If InStr(sFILE, ".php") Then
   ThisWorkbook.Sheets(1).Cells(i, 2) = sFILE

   'ファイル内関数検索開始
   Set DocLine = FSO.opentextfile(sFILE, 1, False)

   Do Until DocLine.atendofstream
    '1 行読み出し
    Tmp = DocLine.readline

     'function を含む行なら
     If InStr(Tmp, "function") Then
     sFunction = Tmp
     sFunction = Replace(sFunction, vbTab, "")     'タブ除去
     sFunction = Replace(sFunction, "function ", "")  'function 除去
     ThisWorkbook.Sheets(1).Cells(i, 3) = sFunction
     sComment = DocLine.readline
     'タブ除去
     sComment = Replace(sComment, vbTab, "")
     'コメント指定除去
     sComment = Replace(sComment, "//", "")
     'スペース除去
     sComment = LTrim(sComment)
     ThisWorkbook.Sheets(1).Cells(i, 4) = sComment
     i = i + 1                     'セル位置1 段下げ
    End If
   Loop
   i = i + 1                       'セル位置1 段下げ
  End If
 Next
 MsgBox "抽出完了しました"
End Sub

 このプログラムが期待通りに動作するためには,次のような書式で関数を書いておく必要があります。

function foo(){
//○○を××する関数
 ~
}

 通常,関数のコメントというと,functionの行の上に入れることが多いと思います。しかし,コメントというのはソースの随所に入ってくるので,このコメントはfunctionの説明だと確定しづらいです。本末転倒という意見は重々承知しておりますが,Excel/VBAでピックアップしやすいように,上記のような形でソースを書いておくようにしてください。そうすれば,Excel/VBAに限らず,テキスト処理系の言語で簡単に抽出プログラムが組めるというわけです。あるいはサンプルの手法とは若干離れてしまいますが,“//■関数の説明”のように抽出しやすい条件ルールをオリジナルで決めてしまうという手もあるでしょう。

PHP以外の言語でも使える

 リスト1は,PHPのコードとその関数であるfunctionを読むように作ってあります。ですが,ピックアップする拡張子を変更したり,functionだけでなくclassやSubも抽出するように改造すれば,もちろん他のプログラミング言語のソースコード解析にも利用できます。ただし,クラス名やメソッド名の前に“Private”や“Public”が付くこともあるので,このあたりの処理はちょっとひねりが必要です。

 サンプルでは単純に,“.php”や“function”という文字列を含むかどうかで判断していますが,本来ならファイル名や関数行であるかどうかのチェックに正規表現を使用すべきです。例えばC言語版の場合,サンプルの「.php」を「.c」に変えただけでは,「.com」や「.cpp」も「.c」を含んでいるために,解析の対象になってしまいます。正規表現への改造も,皆さんの宿題とさせていただきます。

 なお,Excel/VBAの仕様のため,読み込むソース・ファイルの文字コードがシフトJISである必要があります。そうでないと,コメント部分の日本語に文字化けが発生します。英数字については,例えばEUCのソースを使っても文字化けしません。残念ながらExcel単体で文字コードの変換を行うというのは困難なので,解決しようと思うのであれば,この部分はPerlやPHPなどの力を借りることになると思います。

 抽出のためにプログラム・ソースの書き方に制約があったりと,ちょっと面倒に思えるかもしれませんが,自分だけで使うぶんにはこれで十分でしょう。逆に,もっとパーソナライズしていっても楽しいかと思います。その気になればExcel/VBAだけでも,かなり高度なドキュメント生成プログラムが作れます。今回もサンプルを種として,皆さんの手で育て上げてくださいませ。