汎用ツール利用のススメ
真崎 理人 MASAKI, Rihito
有限会社リヒトシステムズ
|
はじめに |
|---|
「明日からVBでの開発チームに入ってくれ」そう上司から言われたらどうしますか? 今までにVBでの開発経験があるのでしたら何の問題もありません.それまで開発チームで使っていた資料をダンボール箱に放り込めば準備完了となるでしょう.しかし,いままでにVBに触れたこともないとしたら…
プログラマを料理人に例えるのなら,昨日まで中華料理店のコックだったあなたが明日からはフランス料理店のキッチンに立つような感じです.新しい店の店長はあなたに“その腕”を期待しています.
恐れることはありません.あなたは“美味しい料理のためのアイデア”と“料理の基礎知識”をもっているはずです.あとはフランス料理特有の知識と調理技術を時間をかけて学べばよいのです.新しい店には,あなたが培ってきた料理のノウハウやレシピのメモを持っていけばよいのです.
しかし,もし,あなたが明日の開店時間にそのキッチンで料理人として働き,注文を受けた料理を作ることになるのであれば,使い慣れた中華鍋と大きな包丁を持っていくことを忘れてはなりません.新しい道具に慣れるまでは,これらの使い慣れた道具があなたを助けるからです.
ご存知の通り,フランス料理では一般に中華鍋や大きな包丁を使うことはあまりありません.なぜなら,フランス料理ではそのツールとしてフライパンやスリムなナイフを使うのが一般的ですし,中華鍋で焼いたステーキは商品にはなりません(鉄のフライパンでなければ,あの美味しそうな焼き色はつきませんからね).ですが,その付け合わせのニンジンのグラッセやソースならフライパンではなく中華鍋で作ることは大きな問題にはならないでしょう.あなたが(中華料理店で習得した中華料理の)調理技術をもってさえいれば,ほかのフランス料理の料理人と遜色のない良い仕事ができるはずです.慣れない手つきでフライパンを使ってもソースを焦がすばかりでは,ほかの料理人の助けになりませんし,かえって足を引っ張ることになってしまいます.
いきなり料理人の話になってしまいましたが,この中華鍋のような,どこのキッチン(開発環境)でも使えるツールは本当に便利なものです.よい機会ですから,ここであなたがいまの開発環境で使っているツールについて考えてみてください.
Q
あなたはこの(どこの開発環境でも使える)中華鍋のようなツールを持っていますか?
中華鍋という汎用ツールを持っていった料理人は,直面する日々の仕事を使い慣れたツールでこなすことができますから,新しい知識と技術をゆとりをもって吸収することができることでしょう.彼がフランス料理店のコックに昇進することはそれほど遠い将来のことではないかもしれません.
プログラマにとっても同じことがいえるのではないでしょうか(図1)? VBに限らず,今までと異なる開発環境になったからといって,いままでに培った技術やノウハウのすべてが無駄になることはありません.むしろ,正しいプログラミング技術をもつ者にとっては開発環境に依存する部分は以外に少ないものです.さらに,使い慣れたツールを新しい環境においても効果的に利用することができれば,新たな開発言語の言語仕様の習得に専念することができることでしょう.
プログラマたるもの「開発言語が変わったからといって何も恐れることなかれ」なのです.
もちろん,VBに慣れているプログラマにとっても汎用ツールは便利なものです.標準のVBに含まれるツールではお目にかかりにくい「高機能で軽快」をぜひ試してみてはいかがでしょうか?
図1:料理人とプログラマ
|
Q
VBによるアプリケーション開発だからといって,VBの製品パッケージに含まれるCD-ROMの中のツールだけしか使えないものとあきらめてはいませんか?
Q
本当に今のツールだけで満足していますか?
その答えのいくつかをご紹介することにしましょう.
|
VBプロジェクトを構成する ファイルとその内容 |
|---|
今回のツールはVB専用のツールではありませんから,VBの統合開発環境(IDE)内から起動するわけではなく,VBの関連ファイルを直接操作(読み込み,書き込み)します.「二度とVBが起動できなくなる」というような心配はありません.ですが万一のために,いまから説明するVBプロジェクトの関連ファイルのバックアップをとっておいてください(とくにファイルへの書き込みをする場合はなおさらです).「バックアップを忘れたために壊れたファイルをもとに戻す」などという作業はつまらないものです.
幸いなことに,VB2.0J時代から主要な関連ファイルはASCIIテキスト形式で保存されていますから,それらのファイルはVBを起動しなくても,ASCIIテキストをサポートしているアプリケーション(「メモ帳」など)であれば,その内容を見たり,変更したりすることはいとも簡単に行なえます.そうです,これらの関連ファイルのフォーマットさえ理解することができれば,あの鈍重なVBの統合開発環境(IDE)の呪縛から解き放たれることができるのです.
今回,着目する関連ファイルは「.vbp,.frm,.bas,.cls」の4種のファイルなのですが,それ以外にもVBでは数多くの関連ファイルを生成しています.
VBに付属する「Visual Basic Books Online」にその構成ファイルの記述がありますからご紹介しておきましょう(表1-1,表1-2).もちろん,いつもこんなに多くのファイルが必要となるわけではありません.作成するVBプロジェクトのタイプにより生成されるファイルが異なっているのです.
表1-1:VBプロジェクトを構成するファイル
★デザイン時に生成されるファイルおよびその他のファイル
| 拡張子 | 説明 |
| .bas | 標準モジュール |
| .cls | クラスモジュール |
| .ctl | ユーザーコントロールファイル |
| .ctx | ユーザーコントロールバイナリファイル |
| .dca | Activeデザイナキャッシュ |
| .dep | セットアップウィザードの依存ファイル |
| .dob | ActiveXドキュメントフォームファイル |
| .dox | ActiveXドキュメントバイナリフォームファイル |
| .dsr | Activeデザイナファイル |
| .dsx | Activeデザイナバイナリファイル |
| .frm | フォームモジュールファイル |
| .frx | バイナリフォームファイル |
| .log | 読み込みエラー時に生成されるログファイル |
| .oca | コントロールタイプライブラリキャッシュファイル |
| .pag | プロパティページファイル |
| .pgx | バイナリプロパティページファイル |
| .res | リソースファイル |
| .swt | Visual Basicセットアップウィザードテンプレートファイル |
| .tlb | リモートオートメーションタイプライブラリファイル |
| .vbg | Visual Basicグループプロジェクトファイル |
| .vbl | コントロールライセンスファイル |
| .vbp | Visual Basicプロジェクトファイル |
| .vbr | リモートオートメーション登録ファイル |
| .vbw | Visual Basicプロジェクトワークスペースファイル |
| .vbz | ウィザード起動ファイル |
表1-2:VBプロジェクトを構成するファイル
★実行時に生成されるファイル
| 拡張子 | 説明 |
| .dll | インプロセスActiveXコンポーネント |
| .exe | 実行可能ファイルまたはActiveXコンポーネント |
| .ocx | ActiveXコントロール |
| .vbb | ActiveXドキュメントブートストラップファイル |
| .vbd | ActiveXドキュメントファイル |
一般によく作成されるVBプロジェクトのタイプは「標準EXE」ですから,試しにサンプルプログラムでその構成ファイルを確認してみましょう.本来ならばフォームモジュールひとつと標準モジュールひとつで構成されるシンプルなサンプルプログラムなのですが,あとの説明のために,クラスモジュールと,ついでにカスタムコントロールである「MS-FlexGrid」も追加しておきました(図2〜5).
図2:サンプルプログラム
![]() |
図3:サンプルプログラムのプロジェクトウィンドウ
![]() |
図4:サンプルプログラムのプロジェクトプロパティ
![]() |
図5:Microsoft FlexGridコントロールを加える
![]() |
このVBプロジェクトでは7つの関連ファイルが生成されています(表2).バイナリ形式であるバイナリフォームファイル(.frx)以外はASCIIテキスト形式ですから「メモ帳」などのアプリケーションでその内容を眺めてみれば,そのフォーマットの意味は容易に理解できます.
表2:VBプロジェクトを構成するVB関連ファイル(サンプル)
| ファイル名 | 拡張子 | ファイル形式 | 内容 |
| NumLock02.vbp | vbp | ASCIIテキスト | プロジェクトの構成情報およびプロパティ |
| NumLock02.vbw | vbw | ASCIIテキスト | デザインモードでのワークスペース情報 |
| NumLock021.frm | frm | ASCIIテキスト | フォームやコントロールのプロパティおよびVBソースコード |
| NumLock021.frx | frx | バイナリ | フォームやコントロールの付加バイナリ情報 |
| NumLock022.bas | bas | ASCIIテキスト | 標準モジュールのプロパティとVBソースコード |
| Class1.cls | cls | ASCIIテキスト | クラスモジュールのプロパティとVBソースコード |
| Sample.frm | frm | ASCIIテキスト | (略:NumLock021.frmに同じ) |
各情報の保存先は以下のとおりです.
リスト1:VBプロジェクトファイル(.vbp)ファイルの内容
Type=Exe
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\System32\StdOle2.tlb#OLE Automation
Form=frmNumLock021.frm
Object={5E9E78A0-531B-91F6-C2863C385E30}#1.0#0;msflxgrd.ocx
Module=modNumLock022; NumLock022.bas
Class=SampleClass; Class1.cls
Form=Sample.frm
"Startup=""frmNumLock021"""
"HelpFile="""""
"Command32="""""
"Name=""NumLockSample02"""
"HelpContextID=""0"""
"Description=""NumLockの切り替えサンプル(その2)"""
"CompatibleMode=""0"""
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
"VersionCompanyName=""Rihito Systems Co.,Ltd"""
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=0
Unattended=0
ThreadPerObject=0
MaxNumberOfThreads=1
|
リスト2:フォームモジュールファイル(.frm)の内容
VERSION 5.00 … (1)
"Object = ""{5E9E78A0-531B-91F6-C2863C385E30}#1.0#0"";""msflxgrd.ocx""" … (2)
Begin VB.Form frmNumLock021 … (3)
" Caption = ""NumLock切り替えのサンプル""" … (4)
ClientHeight = 2895
ClientLeft = 60
ClientTop = 345
ClientWidth = 4305
" LinkTopic = ""Form1"""
ScaleHeight = 2895
ScaleWidth = 4305
StarUpPosition = 3 'Windowsの規定値 … (5)
Begin MSFlexGridLib.MSFlexGrid MSFlexGrid1 … (6)
Height = 1155
Left = 240
TabIndex = 4
Top = 1620
Width = 1815
_ExtentX = 3201
_ExtentY = 2037
_Version = 65541
" MouseIcon = ""NumLock021.frx"":0000" … (7)
End
Begin VB.CommandButton Command1
…
(省略)
…
End
End
"Attribute VB_Name = ""frmNumLock021""" … (8)
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False … (9)
Option Explicit
Private Sub Command1_Click() … (10)
" keybd_event VK_NUMLOCK,_"
" &H45,_"
" KEYEVENTF_EXTENDEDKEY Or &H0,_"
0
" keybd_event VK_NUMLOCK,_"
" &H45,_"
" KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP,_"
0
End Sub … (11)
|
リスト3:標準モジュールファイル(.bas)の内容Attribute VB_Name = "modNumLock022" … (1) Option Explicit … (2) Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte,_ ByVal bScan As Byte,_ ByVal dwFlags As Long,_ ByVal dwExtraInfo As Long) Public Const VK_NUMLOCK = &H90 Public Const KEYEVENTF_EXTENDEDKEY = &H1 Public Const KEYEVENTF_KEYUP = &H2 … (3) |
なお,ワークスペースファイル(.vbw)には統合開発環境の各ウィンドウの最終位置情報などが保存されているファイルですから,このファイルについての説明は割愛します.
おわかりですね.VBプログラムソースコードを作成する場合,必ずしもVB統合開発環境(IDE)を使う必要はないのです.VBのエディタに慣れていないプログラマも(慣れているプログラマも),使い慣れた高機能な「vi」やその他のエディタでVBプログラムソースコードを直接編集することは可能なのです.その他のプロパティや構成情報の変更も同様であることは言うまでもありません.
ただし,注意しなければいけないこともあります.これらの関連ファイルはVBの統合開発環境(IDE)から操作されることを前提としていますから,そのフォーマットを勝手に変更しては正常にVBの統合開発環境から利用できなくなる可能性があります.
関連ファイルの改変に慣れないうちは,「確実にバックアップをとる」,「改変はVBプログラムソースコード部分にとどめ,各プロパティ情報については参照のみにする」などの注意をしてください.
少し,前準備が長くなってしまいました.では,さっそくいくつかの汎用ツールの利用法を紹介することにしましょう.
ここで,各汎用ツールのリファレンスを書いてしまえば「この記事はおしまい!」なのですが,それではあまり面白くはありません.そこでVBでのカスタムアプリケーション開発の現場でしばしば発生するいくつかの「問題事例」を解決する方法のひとつとして各汎用ツールをご紹介していくことにしましょう(なお,各汎用ツールのリファレンスの抜粋についてはコラムとして別にまとめておきました).
|
再コンパイルの必要なプロジェクトはどれだ?(その1) 〜モジュールの依存関係を把握する〜 |
|---|
Q
納品したVBカスタムアプリケーションにバグがありVBプログラムソースコードの修正を行ないました.修正した標準モジュールはいくつかのVBプロジェクトで共用しているので,それらのVBプロジェクトについても再コンパイルする必要があるのですが,対象となるVBプロジェクトファイルを手軽に洗い出すことはできないでしょうか?
A
できます.これらの関連ファイルの依存関係はプロジェクトファイル(.vbp)に記述されていますから,修正した標準モジュールのファイル名が記述されているプロジェクトファイルを洗い出せばよいのです(リスト1参照).
当然ですが問題解決の具体的な方法は,いくつもあります.すべてのVBプロジェクトをVBの統合開発環境(IDE)から開いて該当ファイルの有無を確認する方法もありますし,プログラム設計書のページをめくって,依存ファイルの一覧をチェックしてもかまわないでしょう.ですが,今回は「テキストファイルの全文検索」により該当するVBプロジェクトファイルを洗い出してみましょう.
試行その1
grepユーティリティを使用する
キーワードからテキストファイルの全文検索をするにはgrepが便利です.また,その機能の便利さと手軽さからgrep機能を標準で搭載するテキストエディタも少なくありませんから,「コマンドプロンプト(Windows 95では「MS-DOSプロンプト」)」を使う必要もありません(ここでは,シェアウェアである「秀丸エディタ」で実行してみました).
使用手順は簡単です.VBプロジェクトファイルが保存されているフォルダを指定してキーワード
「修正した標準モジュールのファイル名」
とすれば,完了です.例では6つのVBプロジェクトファイルが見つかりました(図6).あとは,それらのVBプロジェクトファイルの再コンパイルをするだけです.
試行その2
VBでツールを作成する
もちろん,この機能をVBでプログラムを書いて実現することは可能です.「Dir関数」「Input #ステートメント」「InStr関数」を使ってVBプログラムを作ってみました(図7).
難しいプログラムではありませんから30分ほどで完成しました.しかし,このツールを作る必要が本当にあるでしょうか?
図7:VBサンプルプログラム1
― コンパイル対象プロジェクトの洗い出し
応用など
|
再コンパイルの必要なプロジェクトはどれだ?(その2) 〜実行ファイル(.exe)とその依存ファイルと実行ファイルのタイムスタンプを比較する〜 |
|---|
Q
実行ファイル(.exe)が最新でないものがあるようです.そのVBプロジェクトのソースファイルのタイムスタンプより古いVBプロジェクトの再コンパイルを手軽にすることはできないでしょうか?
A
できます.このようなケースにはmakeユーティリティを使いましょう.makeはその依存ファイルのタイムスタンプと実行ファイルのタイムスタンプを比較し,最新でないVBプロジェクトの再コンパイルを行なうことができます.
「再コンパイルの実行が漏れたら大変!」と,ひとつでもソースファイルの修正があると,すべてのVBプロジェクトを一括で再コンパイルしている場面に出会ったことがあります.確かに全VBプロジェクトを再コンパイルしておけば“再コンパイル漏れ”を防ぐことはできますが,無用な再コンパイルは“実行ファイルのバージョン管理を複雑にする”だけでなく“再コンパイル処理の実行自体がコンパイルするコンピュータの環境に依存する”VBの宿命から考えれば「無用なトラブルを生む原因」となりがちです.無条件に一括コンパイルすることは避けるべきです.
「ソースファイルが変更されたVBプロジェクトのみを再コンパイルする」機能は,まさにmakeの機能そのものといえます.makeの機能はとても単純です.makeはメイクファイルと呼ばれるファイルに記述されたソースファイルとオブジェクトファイルのタイムスタンプを比較して,オブジェクトファイルが存在しないかタイムスタンプがソースファイルのタイムスタンプより古ければ,指定したコマンドを実行してくれます.
つまり,このコマンドに該当プロジェクトの再コンパイルを指定することにより「ソースファイルが変更されたVBプロジェクトのみを再コンパイルする」機能を実現することができるわけです.
コマンドラインからのVB5プロジェクトの再コンパイルは,VB5のコマンドラインオプションから「/make」オプションを使い次のように記述します.
vb5.exe /make プロジェクトファイル名
VB5のコマンドラインオプションは他にもあります(図9).makeにはいくつかの版がありますが,ここではVisual C++ 5.0Jにも含まれる「nmake(Microsoft版 make)」を利用してみました.
図9:VB5.EXE /? を実行してVB5のコマンドラインオプションを確認する
試行その3
nmakeユーティリティを使用する
nmakeの実行に先立って,各VBプロジェクトごとにそのソースファイル(依存ファイル)をメイクファイルに記述しておきます(リスト4).
リスト4:メイクファイルを作成する
#MAKE サンプル
# Project1.exeの依存ファイルが実行ファイルより
#新しいときにはProject1をリコンパイルする.
Project1.exe: Form1.frm Form2.frm Module1.bas Module2.bas Class1.cls
vb5.exe /make Project1.vbp
|
ではnmakeを実行してみましょう.サンプルのVBプロジェクトのソースファイル(依存ファイル)はリスト5のようになっているものとします.いまForm1.frmに改変を加えnmakeを実行すると(図10),Form1.frmを使用しているVBプロジェクトファイルのみが再コンパイルされます(リスト6〜8).
リスト5:VBプロジェクトとそのソースファイル(依存ファイル)
Project1.exe
+ Form1.frm
+ Form2.frm
+ Module1.bas
+ Module2.bas
+ Class1.cls
Project2.exe
+ Form10.frm
+ Form11.frm
+ Module1.bas
+ Module10.bas
+ Class10.cls
Project3.exe
+ Form1.frm
+ Form20.frm
+ Module21.bas
|
図10:nmakeの実行
リスト6:nmake実行前のタイムスタンプ
98/04/07 06:16p 743 Form1.frm ← ソースファイルを修正した 98/03/30 05:35p 506 Form10.frm 98/03/30 05:35p 506 Form11.frm 98/03/30 05:34p 504 Form2.frm 98/03/30 05:36p 506 Form20.frm 98/03/30 05:35p 50 Module1.bas 98/03/30 05:35p 51 Module10.bas 98/03/30 05:34p 50 Module2.bas 98/03/30 05:36p 51 Module21.bas 98/03/30 05:34p 239 Class1.cls 98/03/30 05:35p 240 Class10.cls 98/03/30 06:16p 9,728 Project1.exe 98/03/30 05:37p 9,216 Project2.exe 98/03/30 07:22p 9,216 Project3.exe 98/04/07 06:16p 729 Project1.vbp 98/03/30 05:37p 743 Project2.vbp 98/03/30 05:37p 685 Project3.vbp 98/03/30 07:22p 210 Project1.mak 98/03/30 07:22p 214 Project2.mak 98/03/30 07:21p 189 Project3.mak 98/03/30 06:43p 69 Domake.bat |
リスト7:実行したバッチファイルの内容
nmake -f Project1.mak nmake -f Project2.mak nmake -f Project3.mak |
リスト8:nmakeの実行結果(ログ)
C:\>nmake -f Project1.mak
vb5.exe /make Project1.vbp
C:\>nmake -f Project2.mak
'Project2.exe' は更新する必要がありません.
C:\>nmake -f Project3.mak
vb5.exe /make Project3.vbp
|
結果は,リスト9のような結果となっていますから,目的どおり,再コンパイルの必要なVBプロジェクトの再コンパイルが完了していることがわかるでしょう.
リスト9:nmake実行後のタイムスタンプ
98/04/07 06:16p 743 Form1.frm ← ソースファイルを修正した 98/03/30 05:35p 506 Form10.frm 98/03/30 05:35p 506 Form11.frm 98/03/30 05:34p 504 Form2.frm 98/03/30 05:36p 506 Form20.frm 98/03/30 05:35p 50 Module1.bas 98/03/30 05:35p 51 Module10.bas 98/03/30 05:34p 50 Module2.bas 98/03/30 05:36p 51 Module21.bas 98/03/30 05:34p 239 Class1.cls 98/03/30 05:35p 240 Class10.cls 98/04/01 07:59p 9,728 Project1.exe ← 再コンパイルされている 98/03/30 05:37p 9,216 Project2.exe 98/04/01 07:59p 9,216 Project3.exe ← 再コンパイルされている 98/04/07 06:16p 729 Project1.vbp 98/03/30 05:37p 743 Project2.vbp 98/03/30 05:37p 685 Project3.vbp 98/03/30 07:22p 210 Project1.mak 98/03/30 07:22p 214 Project2.mak 98/03/30 07:21p 189 Project3.mak 98/03/30 06:43p 69 Domake.bat |
試行その4
VBでツールを作成する
先ほど試行その2のVBで作成したツールにこの機能を追加するには「Win32 APIであるGetFileTime」を利用することになります.このプログラムを作成することもそれほど難しいわけではありませんが,「手軽に軽快に」使えるはずのツールを使う以前に,一度限りとはいえWin32 APIまでもちだすとなると,その価値は少ないでしょう.先のサンプルにこの機能を追加することはまたの機会にすることにしましょう.
応用など
|
デグレードの原因はどこだ? 〜プログラムソースの変更個所を探す〜 |
|---|
Q
ソースプログラムを修正したところ,修正前にはなかったバグが発生しました.バックアップしておいた修正前のVBプログラムソースコードを使って,今回の修正作業での変更部分を手軽に見つけることはできないでしょうか?
A
できます.このようなケースにはdiffユーティリティを使いましょう.diffはファイルの比較を行ないます.比較するファイルがテキストファイルならば「行単位」での比較を行ない,異なる行を洗い出すことも手軽に行なえます.
「プログラムの修正前のバックアップはとってはいたものの…」このようなことはよくあることです.冗談のような話ですが,3000行以上のVBプログラムソースコードにもかかわらず,印刷したそのプログラムの新旧のソースリストを前に“定規とマーカー”を使ってコード内容をチェックしているプログラマを見かけたことがあります.せっかくのコンピュータです,ファイルの比較などの単純作業はコンピュータに任せるにかぎります.
試行その5
diffユーティリティを使用する
diffにも数多くのオプションがありますが,ここでは「-cオプション:文脈差分(context diff)を求める」を利用しておきましょう.あとは比較する2つのファイル名を指定するだけです.
diff -c1 [旧ファイル名][新ファイル名]
このコマンドを実行することにより,新旧ファイル内容が比較され2つのファイルの相違行の位置と内容が-c1オプションを指定しているためその前後1行とともに表示されます(図11).
図11:diffの実行結果
試行その6
WinDiffを使用する
make,diffとコマンドプロンプトからのCUIな操作が続きましたから,ここでちょっとVisual C++ 5.0Jに同梱されているWinDiffも紹介しておきましょう(図12).WinDiffはdiffのような多くの機能はありませんが,Windows標準インターフェイスで操作できることから筆者の周りでもよく使われています.
図12:WinDiffの実行画面
応用など
|
ソースコードからドキュメントを自動生成したい! 〜正規表現を利用した高度な検索と整形機能〜 |
|---|
Q
作成したVBプロジェクトで使用している「定数の一覧表」を客先に納品しなければいけません.VBプログラムソースコードから「定数一覧表」を手軽に作ることはできないでしょうか?
A
できます.このような「整形処理」などを伴う少し複雑なケースではawkユーティリティが便利です.正規表現を用いた短いスクリプトを記述することで,VBプログラムソースコードの中から必要な情報を整形して取り出すことができます.
awkは入力パターンに応じた処理をスクリプトに記述することにより,単純なテストデータ作りから高度なデータ処理まで実現できる高機能なファイル処理言語です.その機能の高さはプログラミング言語といっても過言ではないでしょう.awkを知れば知るほどその多才さにひかれ,ありとあらゆることまでawkで書いてしまう傾向があるのですが,本稿では理解を助けるためにも基本的な使い方にとどめておくことにします.心配はいりません.awkの文法はC言語に似ていますからC言語の基礎知識さえあれば,サンプルの“awkスクリプト”を理解することはそれほど難しくはないでしょう(リスト10).
awkにもいくつかの版があります. ここではgawkを利用してみました.
リスト10:awkスクリプトのサンプル ― 定数一覧の取得 ―
#!/usr/local/bin/gawk
#
# Const PickUp -> Stdio(CSV)
# Field 1: File Name
# Field 2: Column Number
# Field 3: Constname
# Feild 4: Expression
# Feild 5: Type
# Feild 6: All Row Value
#
BEGIN{
OFS = ","
fn = ""
}
{
if(fn != FILENAME){
lc = 0
fn = FILENAME
}
lc++
gsub(/'.*/,"")# コメント削除
if($1 == "Public" || $1 == "Private"){
sp = 2
} else {
sp = 1
}
if($sp == "Const"){
if($(sp+2)== "As"){
tp = sp + 5
type = $(sp+3)
} else {
tp = sp + 3
type = "no type"
}
expression = $tp
for(i = tp + 1;i <= NF;i++){
expression = expression " " $i
}
print FILENAME,lc,$(sp+1),expression,type,$0
}
}
|
試行その7
gawkユーティリティを使用する
awkと「正規表現」の知識があれば,テキストの処理はまさに“思うがまま”です.先にも書いた通りawkは非常に高機能ですから,ここではそのスクリプトと実行例を記述することにとどめることにします(awkの機能の説明をするとなれば,それだけで一冊の本になってしまいますからね).
VBプログラムソースコードは「フォームモジュールファイル(.frm)」「標準モジュールファイル(.bas)」「クラスモジュールファイル(.cls)」にありますから,その中から“Const”を検索すればよいわけです.もちろん,単純な全文検索では困りますから,ここでは“コメントアウトされている定数は除外”し“Public または Private で書き出されていること”を条件にして処理するスクリプトを書いて実行してみましょう(図13).
gawk -f [スクリプトファイル名][処理するVB関連ファイル名]
あとは,CSV形式で書き出した出力結果をExcelなどで読み込めば完了です(図14).
図13:awkスクリプトの実行(定数一覧の取得)

図14:定数一覧表の完成

試行その8
VBでツールを作成する(その2)
If条件式を多用すれば,VBでもツールが作成できそうです.しかし,“正規表現”を利用しようとなると少々やっかいなことになります.もともと“文字列操作処理”を苦手としているVBが“正規表現”をサポートしているはずもありません.幸いなことにサードパーティ製のカスタムコントロールの中に手ごろなコントロールがありました.VS-OCXの製品パッケージに同梱されている「AWKコントロール」(文化オリエント株式会社)がそれです.
「さっそくこのカスタムコントロールを使ってサンプルプログラムを作ろう!」と思ったのですが,この「AWKコントロール」を使って先のawkスクリプトを実行するのでは,VBでツールを作成する意味もありません.これも,またの機会にしておくことにしましょう.
応用など
リスト11:awkスクリプトのサンプル ― 関数一覧の取得 ―
#!/usr/local/bin/gawk
#
# Procedure PickUp -> Stdio(CSV)
# Field 1: File Name
# Field 2: Procedure Name
# Field 3: Procedure Type
#
$0 ~ / Sub / || $0 ~ / Function / {
for(i=1;i<=NF;i++){
if($i == "Sub" || $i == "Function"){
split($(i+1),arr,"(")
if($(i-1)== "Declare"){ #case 外部(API,DLL)
type = "Foreign " $i
} else {
type = $i
}
name = arr[1]
}
}
print FILENAME,name,type
}
|
|
VBでフルパステストを実現する 〜デバッグ用コードの埋め込み〜 |
|---|
Q
汎用機でのCOBOLプログラミング開発の検査工程で,すべてのロジックの実行を確認する「フルパステスト」をしていました,VBでも「フルパステスト」を実現することはできないでしょうか?
A
この機能を実現することは少々やっかいですが,試しに作ってみましょう.
「フルパステスト」とは,そのプログラムの全ロジックの動作確認をするテストです.“全ロジックを動作させる”といっても,多くのプログラムでは“If 〜 Else 〜”のように条件により実行するロジックが複雑に分岐していますから,そのすべてを動作させるとなるとなかなかやっかいなものです(筆者も苦しめられた経験があります).とはいえ,実行されることがありえない“死にロジック”の排除ができるなど,そのプログラム品質のUPに貢献する効果は少なくありませんから,このテストをVBの環境でも実現するためにツールを作成してみましょう(リスト12).
リスト12:awkスクリプトのサンプル ― フルパスチェック ―
#!/usr/local/bin/gawk
#
# Snapdump(logout Procedure)Add
#
BEGIN{
pc_cnt = 0
}
{
if($1 == "If" || $1 == "Else" || $1 == "ElseIf" || $1 == "Case"){
pc_cnt++
print
printf("App.LogEvent \"PathCheck%05d,\" & Format$(Now, \"yyyy/mm/dd hh:mm:ss\",vbLogEventTypeInformation\n",pc_cnt)
} else {
print
}
}
|
試行その9
awkとVBを使用する
ここでは次の方法で実現することにしましょう.
App.LogEvent "PathCheck(連番)," & Format$(Now, "yyyy/mm/dd hh:mm:ss"), vbLogEventTypeInformationイベントログ出力用のコードは“すべての条件分岐命令”の直後に挿入しなければなりません.ご存知の通りVBの条件分岐命令にはさまざまなものがありますが,ひとまずは「If」「Else」「Case」の直後に挿入するスクリプトを書き,実行してみましょう.
grep -v 'PathCheck' [処理するファイル名]これで,削除は完了です.
リスト13:awkスクリプト実行前のコード(抜粋)― フルパスチェック ―
Private Sub Command2_Click()
If Text1.Text = "YES" Then
Debug.Print "Yes"
Select Case Text2.Text
Case "0"
Debug.Print "0"
Case "1"
Debug.Print "1"
Case "2"
Debug.Print "2"
Case Else
Debug.Print "else"
End Select
Else
Debug.Print "No"
End If
End Sub
|
リスト14:awkスクリプト実行後のコード(抜粋)― フルパスチェック ―
Private Sub Command2_Click()
If Text1.Text = "YES" Then
App.LogEvent "PathCheck00001," & Format$(Now, "yyyy/mm/dd hh:mm:ss"), vbLogEventTypeInformation
Debug.Print "Yes"
Select Case Text2.Text
Case "0"
App.LogEvent "PathCheck00002," & Format$(Now, "yyyy/mm/dd hh:mm:ss"), vbLogEventTypeInformation
Debug.Print "0"
Case "1"
App.LogEvent "PathCheck00003," & Format$(Now, "yyyy/mm/dd hh:mm:ss"), vbLogEventTypeInformation
Debug.Print "1"
Case "2"
App.LogEvent "PathCheck00004," & Format$(Now, "yyyy/mm/dd hh:mm:ss"), vbLogEventTypeInformation
Debug.Print "2"
Case Else
App.LogEvent "PathCheck00005," & Format$(Now, "yyyy/mm/dd hh:mm:ss"), vbLogEventTypeInformation
Debug.Print "else"
End Select
Else
App.LogEvent "PathCheck00006," & Format$(Now, "yyyy/mm/dd hh:mm:ss"), vbLogEventTypeInformation
Debug.Print "No"
End If
End Sub
|
リスト15:イベントログへの出力結果 ― フルパスチェック ―
Information Application c:\vbevent.log: Thread ID: 209 ,Logged: PathCheck00001,1998/04/04 07:26:51 Information Application c:\vbevent.log: Thread ID: 209 ,Logged: PathCheck00003,1998/04/04 07:26:51 Information Application c:\vbevent.log: Thread ID: 209 ,Logged: PathCheck00001,1998/04/04 07:26:53 Information Application c:\vbevent.log: Thread ID: 209 ,Logged: PathCheck00004,1998/04/04 07:26:53 Information Application c:\vbevent.log: Thread ID: 209 ,Logged: PathCheck00001,1998/04/04 07:26:56 Information Application c:\vbevent.log: Thread ID: 209 ,Logged: PathCheck00005,1998/04/04 07:26:56 Information Application c:\vbevent.log: Thread ID: 209 ,Logged: PathCheck00001,1998/04/04 07:26:59 Information Application c:\vbevent.log: Thread ID: 209 ,Logged: PathCheck00005,1998/04/04 07:26:59 |
応用など
|
最後に |
|---|
今月の企画は「プラットフォームを超越する」ですが,もちろん,かの「write at once言語」のことではなく(それはそれで大変興味のある企画なのですが,そういう訳ではなさそうです),「異なる開発環境でアプリケーション開発をしてきた(他言語では開発経験がある)新人VBプログラマのための特集」ということらしいのです.
筆者の周りでもプログラマの「開発環境」は日常的に変わります.開発言語が変わることはもとよりプラットフォームとなる基本ソフト(以降OS)自体が変わることも珍しくはありません.
おそらく読者の中にも昨日までVB以外のアプリケーション開発言語でプログラムを書いていたのに,上司に呼ばれ「明日からVBアプリケーション開発プロジェクトに移ってくれ」と言われたプログラマも少なくないことでしょう.多くの場合「君のいままでの実績ならVBでも何の問題もない」などという誉め言葉(?)とともに「期待しているからね」という“おまけ”があとに続くのが常なのですが,それらの言葉には根拠がないことは言うまでもありません.悪いことに,それらの誉め言葉はあなたが参加する開発プロジェクトでは,なぜだか言葉どおりに受け取られ「はじめて触れるVBの習熟に十分な教育工数を与えられない」大きな理由になったりするものです.
まぁ文句を言ってもはじまりません.プログラマたるもの開発言語ごときの変更にひるんでいる暇はありません.悲しいかな,実力のあるあなたには「ほかのVBスペシャリストと同じ生産性がある」ものとして,すでに開発スケジュールが引かれているのですから.
本稿では「料理人のたとえ」を使いながら汎用ツールとしてUNIXで有名なツールの幾つかを紹介してきました.もちろん便利なツールはこれだけではなく,最近流行のPerl*をはじめいろいろとあります.料理人がさまざまな種類のフライパンから料理に合ったひとつを選んで調理をするように,プログラマも多くの“手になじんだ”ツールの中から目的に合ったツールを“適材適所”に使いわけられるようになりたいものです.普段から新しいツールを試して“手になじむ”ツールの数を増やしてゆけば,VBが“手になじむツールのひとつ”となるのも遠い未来の話ではありません.
また真に「プラットフォームを超越する」のならば,プログラミングの理論を学ぶこともとても大切なことです.もう「古典」の部類に入る本なのですが,筆者のお気に入りは次の4冊です.本誌5月号で推薦されている書籍にも良い本が沢山ありますので,これらの本を読まれることをお勧めします.