VBScriptで効率良く開発をする個人的なノウハウやポイント

VBScript入門
スポンサーリンク

今回の記事では、日常的にVBScriptを利用して自社の作業の自動化や省力化を行っている私が、VBScriptを利用して開発する場合のちょっとしたノウハウや、開発を楽にするポイントを紹介していきます。
 
 

今さら「VBScript」ってどうなの?

VBScriptはプログラミング言語としては、現在メジャーな存在ではありません。
プログラミング系のコミュニティにおいて、VBScriptが話題にあがることはほぼありません。

最近のプログラミング言語では、マルチプラットフォームに対応しているものも多いのですが、VBScriptはWindowsOS上でしか動きません。

また、昔はASP(Active Server Pages)と呼ばれるIISの拡張機能を利用することで、動的なウェブページを生成する際のプログラミング言語としても利用できましたが、そのASPはIE(Internet Explorer)上でしか動作をしないこともあり、IEの終了とともにウェブアプリケーション用の言語としての活躍の場もなくなりました。

そんな落ち目のプログラミング言語である「VBScript」ですが、限られた用途や利用環境であれば、まだ十分活かすことができます。

それどころか、適切に用途や利用環境を選定して利用する場合、他のメジャーなプログラミング言語と比較しても十分優位性を持つぐらいのポテンシャルがあると考えています。

具体的には過去に、「プログラミング初心者向けにVBScriptをおススメする記事」を書いており、そのなかでVBScriptのメリットをまとめています。
良ければこちらもご一読ください。

 
 

「VBScript」で開発する場合のノウハウやポイント

当項では、当記事の本題である、VBScriptで開発する場合の個人的なノウハウや開発が楽になるポイントを紹介していきます。

と言っても、それほど大したものはないかも知れませんが。

 

VBScriptで実装する処理をパターン化しておこう

VBScriptでは、Windows環境下であればあらゆる処理を自動化することができますが、言語仕様的な得手不得手もあり、何でもかんでもVBScriptで処理を作るのも効率的とは言えません。

よって、自分の中で「この処理はVBScriptで作る」、「この処理はVBScriptを使わない」といった線引きをして、VBScriptで作る処理を自身の定型パターンに当てはめて利用するような使い方をおススメしたいです。

とは言え、上の説明だけではお伝えしたい内容の意味が上手く伝わらないかと思います。
私の場合はどの様なケースでVBScriptを利用しており、どのようにパターン化しているのかの実例を紹介していきます。

業務システムのDB参照や更新を伴う処理の自動化

企業の情報システム部門では、自社で使用している基幹システムなどの業務システムの運用も仕事の内ですが、そのシステムのオンライン処理ではやりきれない更新処理や、データのチェック処理などをバッチプログラムとして作成し、日次で定期実行させるような使い方はVBScriptに適しています。

個人的にもこの用途でVBScriptを使うことが多いです。

当ブログでは過去の記事でも、VBScriptを使用したデータ更新処理に関するサンプルコードを掲載しています。
良ければ以下のリンク先もご参照ください。
尚、当記事では接続先のRDBMSはSQL Serverを前提としていますが、接続文字列を適切に修正していただければ別のRDBMSでも同様の実装で利用できます。

この記事のなかで書いているコードの大まかな構成は、私のなかでもパターン化しています。
先ずは以下で記事内のコードを転載します。

  Option Explicit
  Call Main()
    Sub Main()
    
      Dim objCon
      Dim query
      Dim srvName, dbName, loginName, loginPass
      
        'データベース接続情報を定義します。'
        srvName = "DBサーバ名"
        dbName = "DB名"
        loginName = "DBユーザ名"
        loginPass = "DBパスワード"
        
      'SQLServerへ接続します。********************************************
      On Error Resume Next
        Set objCon = CreateObject("ADODB.Connection")
        objCon.Open "Driver={SQL Server}; server=" & srvName & "; database=" & dbName & "; uid=" & loginName & "; pwd=" & loginPass & ";"
      'エラー処理'
      If Err.Number <> 0 Then
        Msgbox("エラーが発生しました。" & " エラーナンバー:" & Err.Number & " エラー詳細:" & Err.Description)
        Set objCon = Nothing
        Exit Sub
      End If
      
      Err.Clear
      On Error Goto 0
      
      'SQL文を生成し実行します。******************************************
        query = ""
        query = query & "UPDATE テーブル名 "
        query = query & "SET カラム1 = 値1 "
        query = query & "  ,カラム2 = 値2 "
        query = query & "  ,カラム3 = 値3 "
        query = query & "WHERE "
        query = query & "   カラム1 = xx"
        
      On Error Resume Next
        'トランザクションを開始します。
        objCon.BeginTrans
        'SQLを実行します。
        objCon.Execute(query)
        
      'エラー処理'
      If Err.Number <> 0 Then
        Msgbox("エラーが発生しました。" & " エラーナンバー:" & Err.Number & " エラー詳細:" & Err.Description)
        'トランザクションをロールバックします。
        objCon.RollbackTrans
        objCon.Close
        Set objRS = Nothing
        Set objCon = Nothing
        Exit Sub
      End If
      
      Err.Clear
      On Error Goto 0
        '更新をコミットします。
        objCon.CommitTrans
      '終了処理をします。。********************************************
        'オブジェクトを破棄します。
        objCon.Close
        Set objCon = Nothing
    
    End Sub

まず最初に変数を宣言したあとに、データベースに接続しています。
接続したら、SQL文を生成した後、そのSQLを実行しています。
記事のサンプルコードではすぐにUPDATE文を生成していますが、業務で実装する場合は、他にも色々な処理をしながらSQLを生成していたりします。

また、更新処理で失敗した場合に中途半端にデータが更新されることがないように、必ずトランザクション管理を実装しています。

また、以下の記事では、最初にSELECT文を実行し、取得した結果をレコードセットに格納して、そのレコードセットの行数分ループさせて、CSV形式のファイルに出力しています。

この記事ではCSVを生成するためにレコードセットでループさせていますが、このループ処理のなかで更にUPDATE文やINSERT文などの更新系SQLを実行すること可能です。
例えば、レコードセットで取得した行を一件ずつチェックして、分岐処理をしながらUPDATEやINSERTをするといった実装もよくやります。

システム間の連携処理の自動化

企業では様々な業務システムが稼働し、昨今では企業の業務ごとにスクラッチでシステム開発会社に作ってもらったシステムを利用するより、特定の業務向けのパッケージ製品やSaaSなどのシステムをピンポイントで利用して活用するケースが大半です。

そういった出来合いのシステムでは、それぞれでデータベースを持ち、必要になるデータをそのシステム内でしか保管できないため、各システム間のデータを共有したり連携をするために、人が手作業で二重や三重にデータをメンテナンスしているケースも珍しくありません。

そういった非効率な運用を見直して、各システム間のデータ連携で必要になる作業をVBScriptに置き換えて自動化するといった対応もよくやります。

例えば当ブログでは過去に以下のような記事を掲載しています。

この記事では、サイボウズ社のグループウェア製品である「ガルーン」で用意されているSOAP APIをVBScriptから実行し、ユーザーカウントの新規登録作業を自動化させています。

記事で紹介したサンプルコードは長文であり、一見するとわかり難いのですが、これもパターン化されています。

ガルーンでは用意されているAPIのURLに対してパラメーターを渡して実行させます。
ガルーンでは2種類のAPIが用意されており、「SOAP API」は電文用のデータフォーマットとして「XML」を使用します。
また、「REST API」ではデータフォーマットとして「JSON」を使用しています。

記事ではSOAP APIを使用しているため、XMLを文字列で生成しているのですが、このXML文の生成をして各APIを呼び出すまでの一連の処理は同じパターンで実装されています。

生成するXMLのうち、ヘッダー部分は共通のFunctionプロシージャで作成し、Body部分は呼び出すAPIごとにFunctionプロシージャを用意して作成し、最後にそれらのFunctionプロシージャで作成したXMLを一つに結合した文字列をWebメソッドでPOSTしています。

当ブログ内では、上記の記事以外にも、ガルーンのAPIを利用したサンプルコードを幾つか掲載していますが、すべて同じ実装パターンです。

一つの実装パターンを用意しておけば、後はそのなかの処理を少し書き換えるだけで、新しい処理も実装できて効率的です。

これらの活用例や実装方法のパターン化の重要性については、何もVBScriptに限ったものではないのですが、VBScriptを活用する際にも意識しておいていただくと良いかと思います。

VBScriptでは向かない処理

参考までに、VBScriptでは向かない処理も紹介しておきます。
個人的にはこのような用途や実装が求められる場合、VBScriptではなく別の言語やツールを利用します。

  • JSONの生成や読み込みが必要になる処理
  • 高度な文字コードの制御が必要になる処理
  • データの暗号化が求められる処理
  • 大量のデータを扱うなど速度が求められる処理

上記のような用途や処理はVBScript自体に機能がなく実装できなかったり手間が掛かる、又は十分なパフォーマンスが得られないことが考えられます。

VBScriptに向いた処理、向かない処理はVBScriptを用いた実装経験を積まないと判別が付かないかと思いますが、上記の例も参考にしていただくと良いかと思います。

 

メイン処理もSubプロシージャ化しよう

VBScriptでは、プロシージャを作ることは必須ではなく、例えば以下のようにプロシージャを作成することなく直接コードを書き始めることができます。

  Option Explicit

  Dim test1

      test1 = "Hello VBScript!"

      msgbox test1

もちろんこれでも問題無く動作はしますし、ちょっとした処理の自動化であればこのような書き方でも良いのですが、私がVBScriptである程度手の込んだ処理を書く際には以下のようにします。

  • メイン処理用のSubプロシージャを作成する。
  • プロシージャの外ではメインプロシージャを呼ぶ処理のみを書く。

例えば以下のような書き方です。

  Option Explicit

  'メイン処理を呼び出します。
  Call Main()

      Sub Main()

          Dim test1

              test1 = "Hello VBScript!"

              msgbox test1

      End Sub

また、さらに別のSubプロシージャやFunctionプロシージャも作成する場合は以下の様に書きます。

  Option Explicit

  'メイン処理を呼び出します。
  Call Main()

      Sub Main()

          msgbox fnc_test()

      End Sub

      Function fnc_test()

          Dim test1

              test1 = "Hello VBScript!"

              fnc_test = test1

      End Function

このように書くことによって、以下のメリットがあります。

  • メイン処理の開始と終了が明確になる。
  • メイン処理を途中で抜ける場合にExit Subが使えるようになる。
  • 変数の適用範囲を限定できる。

VBScriptはスクリプト系言語ではありますが、他の言語と同じように、プログラムの開始と終了は処理単位ではっきりと作成しないと何となく気持ちが悪いです。

また、この書き方の大きなメリットは、メイン処理を抜ける際にExit Subが使えるようになるところです。
プロシージャを作らずに処理を強制的に中断する(終了)場合は、WScript.Quitを使いますが、これはVBScriptで実行しているプロセス自体を終了させる処理であり、少し意味合いが異なります。

また、他のVB系言語と同じ文法で処理が実装できた方が、より可読性も高いと言えます。

後、VBScriptでは、プロシージャの外で宣言した変数はグローバル変数となり、どのプロシージャからも参照可能になります。

しかし、SubプロシージャやFunctionプロシージャなどを複数作成して処理を分割して実装しているケースの場合、グローバル変数を多用することで、意図しない参照や書き換えによる不具合の原因になる可能性があります。

その為、変数はプロシージャのなかで宣言し、その適用範囲を限定することが重要です。

これらの理由により、メイン処理用のSubプロシージャを作って、そこにメイン処理を書く方法をおススメします。

 

タスクスケジューラとセットで利用しよう

VBScriptでは、テキストファイルにコードを書き、そのテキストファイルの拡張子を「.vbs」とリネームして保存することで、VBScriptの実行ファイルになります。
そのファイルをダブルクリックすることで、通常は.vbs拡張子とwscript.exeが紐づいており、wscript.exeのプロセスが起動して、VBScriptで記述したコードを実行します。

このように、vbsファイルを毎回ダブルクリックで実行するような使い方もできますが、私の場合VBScriptで作成したvbsファイルの大半は、Windows Serverの「タスクスケジューラ」に登録し、決められた時間に定時実行させるようにスケジューリングして利用しています。

上項でも紹介したような、データベースを参照して更新したり、データベースのデータを決められた条件で抽出してCSVファイルなどに吐き出すような処理を自動的に定時実行させようにしておくことで、その作業自体を自動化、無人化するといった活用が可能です。

VBScriptではタスクスケジューラと相性が良いため、定時実行を前提として活用する方法もおススメです。

当ブログでは、過去にタスクスケジューラの使い方に関する記事も公開しております。
良けれはこちらのリンク先もご一読ください。

 

変数の宣言は強制しておこう

VB系の言語では、コードの先頭に「Option Explicit」を付けることで、変数の宣言を強制することができます。
逆に言えば、「Option Explicit」を指定しないままコードを書くと、VBScriptとして用意されているステートメントやプロパティ名に存在しない文字列はすべて変数として自動的に扱われます。

例えば以下のように、変数を宣言することなくコードを書くことができます。

  
  Call Main()

      Sub Main()

              'test1は暗黙的に変数として扱われる
              test1 = "Hello VBScript!"

              msgbox test1

      End Sub

尚、当ブログではVBScript入門記事のなかで、「変数宣言の強制」について解説しています。

VBScriptでは、言語の名前のとおりスクリプト言語であり、手軽に処理を記述できるのがメリットでもあるため、必ずしも変数の宣言を強制化しないといけないものではないのですが、VBScriptの場合、他の一般的なプログラミング言語のように、デバッグができるIDE(統合開発環境)が存在しません。
厳密に言えば、以下の記事で紹介した通り、存在はするのですが、Microsoft公式のIDEは存在しません。

そのため、他の一般的なIDEを使ってコードを書く場合は、入力したコードの後に続く入力候補のメソッドやプロパティをリスト化して表示してくれる入力補完機能があり、一からすべてのコードを手打ちしなくてもコーディングできる仕組みが用意されていますが、VBScriptではIDEがないため、テキストエディタにすべて手打ちします。

よって、当然タイプミスなどが発生するケースも多く、また、実在しないメソッドやプロパティを書いてしまう構文上のミスも発生します。

変数の宣言を強制しない場合、その様なタイプミスはすべて変数として扱われてしまうため、タイプミスをした部分がエラーにはならず、タイプミスに気付けないケースも多々あります。

よって、書いたコードが意図した動作にならず、その原因の調査に時間を不必要に浪費してしまったり、また、タイプミスでエラーになるべき箇所がエラーにならず処理が通ってしまうことで、想定外の処理が実行されてしまい、致命的な不具合を起こす原因にもなり得ます。

また、そもそも変数を宣言せずにコードを書いた場合、そのコード内のどれが変数なのかを識別し難くなり、可読性が大きく下がります。

前述したとおり、VBScriptでは行ごとに実行してステップインでデバッグすることができないため、コードを眺めながら机上で実行時の動作を読み解くことが多い言語です。
適切な位置で適切な変数を宣言しておくことは、コードの可読性を確保するためにも非常に重要です。

変数の宣言を強制するメリット

  • タイプミスを検出してエラーを出してくれる。
  • 変数を必ず宣言して使用することになりコードが見やすくなる。

よって、VBScriptでは、必ずコードの先頭に「Option Explicit」を書いて、変数を宣言を強制するようにしてください。

 

デバッグ用にログ出力プロシージャを常に組み込んでおこう

VBScriptにおいて、IDEを利用した行単位でステップインしながら実行結果を確認するようなデバッグができないのは不便ですが、実際にはある程度VBScriptを書いているとそのうち慣れます。

以前に以下の記事でも紹介していますが、VBScriptのデバッグ方法として広く利用されているのは、MsgBoxを利用した方法です。
特定の変数の値をMsgBoxに渡し内容を確認するといった確認方法であれば、手軽に行えます。

ただ、例えば変数に格納した長文のSQL文字列が適切に生成されているかを確認したいとなった場合、MsgBoxでは表示できる文字数に限界もあり(1024バイトまで)、また表示した文字列をコピーして再利用することもできないため、別の方法でデバッグすることが必要になります。
そこでおススメしたいのは、予めログ出力用のプロシージャを作成しておき、処理実行時の値を確認したい場合は、そのログ出力用プロシージャを利用して確認する方法です。

当ブログでは過去に以下の記事でも紹介しています。

VBScriptで作成する処理において、ログ出力をする予定があるか否かに関わらず、取り敢えず新しくVBSファイルを作成したら、必要な時にいつでも呼べるように以下のスクリプトも組み込んでおくと便利かと思います。
尚、以下のSubプロシージャでは、VBSファイル自身のカレントディレクトリ内に「logs」フォルダが存在していることが前提となっているため、このプロシージャを使用する場合は予めlogsフォルダを作成しておくか、必要によって使いやすいようにこのプロシージャを修正して利用してください。

  Sub SysWriter(str)

  	Dim objWshShell
  	Dim fso, fi
  	Dim LogFileName
  	Dim wkNow

  	'ファイル名に設定する日付をyyyymmdd形式で取得します。
  	wkNow = Year(Now())
  	wkNow = wkNow & Right("0" & Month(Now()) , 2)
  	wkNow = wkNow & Right("0" & Day(Now()) , 2)

  	'カレントディレクトリを取得して、カレントディレクトリのlogsフォルダ内にlogファイルを作成します。
  	Set objWshShell = WScript.CreateObject("WScript.Shell")
  	Set fso = CreateObject("Scripting.FileSystemObject")

  	LogFileName = objWshShell.CurrentDirectory & "\logs\" & wkNow & ".log"

  	'ファイルを開く
  	'もしも存在しない場合には作成する
  	Set fi = fso.OpenTextFile(LogFileName, 8, true)

  	fi.WriteLine (Date() & " " & Time() & ": " & str) 'ログを書き込む
  	Set fi = Nothing
  	Set objWshShell = Nothing

  End Sub

 

メール送信処理を組み込んで処理結果やエラー時に通知をしよう

こちらはVBScriptに限った話ではないのですが、私がVBScriptで何らかの処理を実装する場合で、且つ前述した「タスクスケジューラ」を組み合わせて処理の実行自体を自動化、無人化するような場合、大抵は併せてメール送信処理も組み込みます。

決まった時間に自動実行された処理が正常に完了したか否かを通知したり、または何らかのエラーが発生した場合のみ通知するなど、メールを飛ばす際の条件は実装した処理によって異なりますが、処理の正常終了や異常終了を通知する方法として、もっとも適切なのは今の昔もEメールです。

メールで通知をしてくれないと、VBScriptで実行した際に出力させているログを目視で確認することが必要になるなど運用が面倒になります。

尚、当ブログでは、以前にVBScriptからPowerShellのメール送信用コマンドレットを実行するサンプルコードを紹介する記事を掲載しています。
この処理であれば、STARTTLSにも対応しており比較的セキュリティの厳しいメールサーバーに対してもメールを送ることができます。

是非ご活用ください。

 

アルファベットの大文字と小文字は適切に書き分けよう

VBScriptでは、アルファベットの大文字と小文字を区別しません。
よって、例えば当記事のサンプルコードで使用している「MsgBox」を MSGBOX と書こうが、 msgbox と書こうがどちらも同じように動作します。
変数を宣言する際の「Dim」は、dim でも良いですし、dIM と書いても構いません。
また、変数名も TEST と宣言し、コード内で test を参照しても同じ変数として扱われます。

例えば同じVB系の言語でもIDEが使用できるVBAの場合は、各ステートメント名やメソッド名やプロパティ名などをすべて大文字、又は小文字でコードを書いても、ステートメントなどの予約語は自動的に所定の位置が大文字や小文字に置き換えられます。

また、コード内で書く変数も、変数名を宣言した際の大文字や小文字の指定内容に自動的に修正してくれます。
しかし、VBScriptではIDEがないため、自動的にアルファベットの大文字や小文字を修正してくれる機能はおそらくありません。
※もしかしたらテキストエディタの拡張機能としてそのような機能を提供しているものもあるかもしれませんが。

よって、VBScriptでは、言語仕様としてコード内の大文字と小文字は区別されずどちらも同じ文字として扱われ、且つ、IDEがないことでその大文字と小文字を正してくれる機能もないため、例えば 同じVBSファイル内で、msgbox と MSGBOX と MsgBox が混在することが可能です。
ただし、その様なでたらめなコードの書き方では、可読性は大きく下がり、後からそのコードを解析するのに時間が掛かってしまったり、不具合を見落としてしまう原因になります。

よって、VBScriptでコードを書く人が、自分自身で適切にルールを設けて、コード内の大文字と小文字を使い分けることが必要になります。

もちろん使い分けること自体を放棄して、すべて小文字でコードを書いても支障はないのですが、それでは可読性が低いため、あまりおススメできません。

個人的には以下のように大文字と小文字を使い分けています。

  • VBAの既定の使い分けを真似る
  • ステートメントなどの予約語の書き出しは大文字

VBScriptとVBAは言語仕様的にも非常に類似しており、変数宣言時の型指定が可能な点を除けば、両言語間はほぼコピペでも動作します。
普段からVBAでコードを書く機会が多いのであれば、VBAのIDEが自動的に変換してくれる大文字の使い分けと併せておくと、コードの可読性は大きく上がると思います。

また、上記のVBAでもそのようになっていますが、ステートメントなどの予約語を使用する場合に、書き出しの1文字目は必ず大文字を使用すると、結果的にVBAと類似した大文字の使用ルールが適用されることになるためそれでも結構です。
今回の記事で書いている各サンプルコードもこのルールを適用して書いています。

繰り返しになりますが、VBScriptではコードを書く人が大文字と小文字の使い分けにルールを設ける必要があり、それを適切に適用することでコードの可読性は大きく改善されるため、是非意識しておいてほしいポイントです。

 

エラー処理は細かく実装していこう

VBScriptで不便だと感じるのは、言語仕様的にエラー処理が貧弱なところです。
具体的には、エラー処理をまったく実装せず、例外エラーが発生したら処理が中断するのを受け入れるか、「On Error Resume Next」でエラーを無視して処理を続行させて、その後「Err.Number」を取得してIF文でエラー時の処理を実行させるかのどちらかしかありません。

本格的なバッチ処理などでVBScriptで作る場合は、当然前者はあり得ないので後者で実装します。

VBScriptにおける具体的なエラー処理のやり方については、過去に当ブログの記事で解説しているため、以下のリンク先をご確認ください。

業務システムで使用するバッチ処理では信頼性が求められるため、エラーが発生する可能性のある箇所を細かく分割し、そのエラー発生箇所によって個別に処理を分岐したいケースは多々あります。
VBScriptではお伝えしたとおり、発生したエラーを無視し、その後「Err.Number」でエラー番号を取得してエラーを検出してエラー時の処理を実装することしかできません。

その為、コード内のエラーが発生しそうな箇所を、「On Error Resume Next」と「On Error Goto 0」で細かく囲み、その範囲内でエラーが発生した場合の処理を個々に実装していくことになります。

例えば以下のような実装方法になります。

  Option Explicit

  Call Main()

      Sub Main()

          Dim ProcessName

              '以下の行以降で発生したエラーは無視されて実行します。
              On Error Resume Next

                  ProcessName = "何らかの処理1"
                  '何らかの処理1
                  '・・・
                  '・・・

              If Err.Number <> 0 Then
                  MsgBox ProcessName & "でエラーが発生しました。" & vbCrlf & "エラーナンバー:" & Err.Number & " エラー詳細:" & Err.Description)
                  '何らかの処理1に対するエラー処理
                  '・・・
                  '・・・
                  Exit Sub
              End If
              Err.Clear
              On Error Goto 0
              'エラー無視範囲ここまで。

              '以下の行以降で発生したエラーは無視されて実行します。
              On Error Resume Next

                  ProcessName = "何らかの処理2"
                  '何らかの処理2
                  '・・・
                  '・・・

              If Err.Number <> 0 Then
                  MsgBox ProcessName & "でエラーが発生しました。" & vbCrlf & "エラーナンバー:" & Err.Number & " エラー詳細:" & Err.Description)
                  '何らかの処理2に対するエラー処理
                  '・・・
                  '・・・
                  Exit Sub
              End If
              Err.Clear
              On Error Goto 0
              'エラー無視範囲ここまで。
      End Sub

決して洗礼されたコードとは呼べないのですが、VBScriptの言語仕様上仕方がない部分なので、取り敢えずVBScriptでは細かくエラー処理を実装することを意識してください。

 

適切なインデントや改行を意識してコードを書こう

インデントとは文章の先頭にタブを挿入したり、空白を複数挿入して字下げを行うことを言います。

コード内のブロックごとや処理ごとに適切なインデントを設定することで、コードの可読性は大きく向上します。

例えばMicrosoftが開発しているIDE(統合開発環境)のVisual Stusioでは、コード内に書かれた構文を解析しインデントをVisual Studio側で自動的に設定してくれます。
VBScriptでは専用のIDEがないために、何らかのテキストエディタでコードを書くのですが、インデントを自身で設定することになります。

また、インデント以外に「改行」もコードの可読性を向上させるためには重要な要素です。

インデントや適切な改行を意識せずにコードを書いても実装したコードの動作には影響がないのですが、コード全体の可読性が下がるため、普段から適切にインデントや改行位置を意識してコードを書く癖をつけておくべきです。

簡単な例として、以下でインデントや改行を適切に設定していないコードと、適切に設定したコードを比較してみます。

  'インデントや改行を使わずに書いたコード
  Option Explicit
  Dim test1
  test1 = "Hello VBScript!"
  msgbox test1
  'インデントや改行を適切に指定したコード
  Option Explicit

  Dim test1

      test1 = "Hello VBScript!"

      msgbox test1

ちょっとした短いコードだけを見ても、可読性に差がでます。

次項では、私がVBScriptでコードを書く際にインデントや改行をを付ける基準を紹介していきます。

処理のブロックごとにインデントを付けて構造化する。

プログラミングにおいて、インデントを適切に指定することで、コード全体を視覚的に構造化して、ブロック単位のプログラムの流れを分かりやすく表現できます。

構造化して分けるべきブロックとしては以下があります。

  • IfやSelect Caseなどの条件分岐範囲内の処理
  • ForやDoなど繰り返し範囲内の処理
  • エラー処理のハンドル対象範囲の処理
  • SubプロシージャやFunctionプロシージャで分割された処理

言葉で説明するだけではイメージし辛いかと思うので、実際のコードで説明してみます。

まずは、条件分岐処理と繰り返し処理をブロックごとにインデントを付けてみます。

  objRs.MoveFirst

  'ブロック1 ここから
  Do Until objRs.EOF
  	dataCount = dataCount + 1

  	'ブロック2 ここから
  	For Each field In objRs.Fields
  		data = field.Value

  		'ブロック3 ここから
  		If IsNull(data) Then
  			file.Write ","
  		Else
  			file.Write """" & data & """"

  			'ブロック5 ここから
  			If Not (field Is objRs.Fields.Item(objRs.Fields.Count - 1)) Then
  				file.Write ","
  			End If
  			'ブロック5 ここまで
  			
  		End If
  		'ブロック4 ここまで
  		
  	Next
  	'ブロック2 ここまで
  	
  	file.WriteLine
  	objRs.MoveNext
  Loop
  'ブロック1 ここまで

このコードはデータベースから取得したレコードセットを元に、CSV形式のデータを作成する処理の一部です。
冒頭では Do Until のブロックがあり、そのなかでインデントを一つ下げています。
その下には For Each のブロックがあり、そのなかでもインデントを更に一つ下げています。
また、更にそのなかに If で条件分岐をしており、そこでもインデントを下げています。

あと、ブロックの開始と終了位置には空白行を作るようにしてあります。

このようにブロック単位でインデントを作り階層化することで、その処理ブロックの範囲がインデントの階層から判別できるようになり、視覚的にコードの構造を把握しやすくなります。

次に、エラー処理のハンドル対象範囲やSubプロシージャ単位でインデントを付けてみます。
※エラー処理を説明した際に記載したコードと同じです。

  Option Explicit

  Call Main()

      Sub Main()

          Dim ProcessName

              '以下の行以降で発生したエラーは無視されて実行します。
              On Error Resume Next
                  ProcessName = "何らかの処理1"
                  '何らかの処理1
                  '・・・
                  '・・・

              If Err.Number <> 0 Then
                  MsgBox ProcessName & "でエラーが発生しました。" & vbCrlf & "エラーナンバー:" & Err.Number & " エラー詳細:" & Err.Description)
                  '何らかの処理1に対するエラー処理
                  '・・・
                  '・・・
                  Exit Sub
              End If
              Err.Clear
              On Error Goto 0
              'エラー無視範囲ここまで。

              '以下の行以降で発生したエラーは無視されて実行します。
              On Error Resume Next
                  ProcessName = "何らかの処理2"
                  '何らかの処理2
                  '・・・
                  '・・・

              If Err.Number <> 0 Then
                  MsgBox ProcessName & "でエラーが発生しました。" & vbCrlf & "エラーナンバー:" & Err.Number & " エラー詳細:" & Err.Description)
                  '何らかの処理2に対するエラー処理
                  '・・・
                  '・・・
                  Exit Sub
              End If
              Err.Clear
              On Error Goto 0
              'エラー無視範囲ここまで。
      End Sub

冒頭で Subプロシージャの Main() を呼び出してインデントを一つ下げています。
その配下にSubプロシージャを定義し、そのSubプロシージャ内でも、変数の宣言部分と変数の宣言以降のコードをインデントで区別しています。

On Error Resume Next でエラー処理のハンドル開始を指定し、一つインデントを下げて処理を記述することで、この On Error Resume Next の対象範囲を人が判別しやすようにしてあります。

このように、書いたコードに適切なインデントを適用することで、コードの可読性は大きく向上します。

どのような時にインデントで字下げをするかは、関わるプロジェクトのコーディング規約があればそれに準じます。
コーディング規約が無かったり、一人でコードを書く機会が多ければ、自身で何らかのルールを設けておくことが必要です。

尚、このインデントや改行については、VBScriptに限らず他のプログラミング言語であっても同様に重要です。

 

演算子(オペレータ)はスペースで区切って書こう

VBScriptの演算子は他のプログラミング言語と比べると種類が少ないのですが、この演算子もコードを書くにあたり非常に重要な要素です。

VBScriptでは以下の種類の演算子があります。

算術演算子:数値を足したり引くといった四則計算などで使う演算子
比較演算子:値を左辺と右辺で比較して大小や等しいか否かを判定するための演算子
論理演算子:And(論理積)やOr(論理和)などの判定で使用するための演算子
連結演算子:文字列を連結するための演算子

VBScriptでは演算子を使用する場合、演算子の前後にスペースを入れても入れなくてもどちらでも書けます。

言葉ではイメージがし辛いと思います為、以下のサンプルコードを確認してください。

  '演算子の前後にスペース入れない
  Dim a
  a=1+1
  If a>1 Then
  Msgbox a
  End If
  '演算子の前後にスペース含める
  Dim a
  a = 1 + 1
  If a > 1 Then
  Msgbox a
  End If

各演算子の前後にスペースを含めることで、コードの可読性は向上します。

些細な内容ではありますが、常にスペースを入れて読みやすく書くように心掛けてください。

 

エディタは「Visual Studio Code(VSCode)」を使おう

前述したように、VBScriptでは専用の純正のIDEが存在しません。
よって、何らかの高機能なテキストエディタを利用してコードを書くことになります。

もちろんメモ帳でもコードは書けますが、構文を解析して色分けしてくれる「シンタックスハイライト」ぐらいは使えないと効率良くコードを書くことは難しいです。

そこで個人的におススメしたいテキストエディタはMicrosoftが無償で提供している「Visual Studio Code(VSCode)」です。
ちょっとした設定で簡単にVBScrit用のシンタックスハイライトが設定でき、VBScript以外の言語のコーディングでも活用できます。

当ブログでは、以前にVSCodeでVBScriptを書く際に設定しておくべき項目を紹介した記事も掲載しています。

コーディングを効率良く行うには、使い勝手のよいテキストエディタの存在は不可欠です。
もちろん「VSCode」じゃなきゃダメなわけではなく、お気に入りのテキストエディタがあれば、それを使用していただいてもまったく問題はありません。
ただし、もしそういったこだわりがないのであれば「VSCode」を選択しておくのが無難です。

まだ使用したことがなければ是非試してみてください。

 
 

最後に

今回の記事では、VBScriptで開発する場合の個人的なノウハウやポイントを紹介させていただきました。

これらの内容は、本当に個人的なVBScript固有のノウハウ的な内容もあれば、VBScriptに限らず、一般的なプログラミングにおける書き方の作法のようなものもあります。

比較的初心者向けの記事として書いているため、プログラミング上級者の方ではあまり参考にはならないかも知れません。

それでも、今回の記事が誰かの助けや参考になるようであれば幸いです。

今回も長々と読んでいただきましてありがとうございます。
それでは皆さまごきげんよう

タイトルとURLをコピーしました