変数の名前について


VBAでは、変数の命名に関して次のようなルールがあります。(以下、Excel 2007のヘルプより抜粋)

変数名には、文字 (英数字、漢字、ひらがな、カタカナ) とアンダスコア (_) を使うことができます。スペースや記号は使えません。変数名の先頭の文字は、英字、漢字、ひらがな、カタカナのいずれかでなければなりません。同一適用範囲 (スコープ) 内で同じ変数名を複数使うことはできません。また、変数名の長さは、半角で 255 文字以内でなければなりません。

つまり

  1. 変数名には文字(日本語を含む)のほか、アンダーバー(_)だけを使えて、そのほかの記号やスペースは使えない
  2. 変数名の先頭が数字やアンダーバー(_)ではいけない
  3. 同じ適用範囲で同じ名前は使えない
  4. 変数名の長さは半角で255文字まで

ということですね。

4.は、意識する必要はないでしょう。そんな長い名前を使うことは希でしょうし、もしエラーになったとしたら短くすればいいだけの話ですから。

2.と3.は、VBEが教えてくれますので安心です。

指摘されたら別の名前に直しましょう。

1.のように、変数名には日本語(漢字・ひらがな・カタカナなど、いわゆる昔で言う2バイト文字)を使用することができます。

Dim 合計 As Long, 住所 As String

昔は「変数名やプロシージャ名に日本語(2バイト文字)を使うとエラーになったり、誤動作する」と言われていましたし、確かに、エラーや誤動作の原因になりました。Excel 95でも「マクロ記録のプロシージャ名に長音(ー)が含まれていると、操作が記録されない」という不具合がありました。しかし、最近の環境は違います。日本語を使用することで問題が生じたのは、日本語を表す2バイトのコードに、プログラム的に特別な意味を表すコードが含まれていたのが原因です。Excelを作ったアメリカの事情と、複雑な字をパソコンで扱いたいという日本の事情が、うまくマッチしていなかったんですね。しかし、最近のWindowsやExcelは、文字を「ユニコード」という文字コードで扱っています。ユニコードは、半角英数字の"A"や"1"など、すべての文字が2バイトで定義されています。なので、昔のように、日本語(2バイト文字)を扱うことで問題は生じなくなりました。なにしろ、すべての文字が2バイトなのですから。したがって、安心して変数名に日本語を使えます。

もっとも、私はめったに日本語の変数名を使いません。それは、誤動作するからではなく、日本語変換のIMEを切り替えるのが煩雑だからです。

Sub Sample24()
    Dim 名前 As String
    名前 = InputBox("名前を入力してください")
    If 名前 = "" Then Exit Sub
    If InStr(名前, " ") > 0 Then
        Range("A1") = Left(名前, InStr(名前, " ") - 1)
        Range("B1") = Right(名前, Len(名前) - InStr(名前, " "))
    End If
End Sub

というようなコードを入力するとき、ひんぱんにIMEのオン/オフを切り替えるのは、プログラミングの思考が妨げられるだけでなく、IMEの切り替えを忘れて誤入力をすることが多いです。私は。ですから、個人的には、そうした理由で、日本語を使った変数名は使っていません。

変数には意味のある名前を

変数の名前には、その変数が何を表しているか、その変数にどんな内容の値が格納されるかが分かるような名前をつけましょう。たとえば、次のコードをご覧ください。

Sub Sample25()
    Dim X As String, Y As String
    X = InputBox("名前を入力してください")
    Y = InputBox("住所を入力してください")
    ''      :
    ''  何かの処理
    ''      :
    Range("A1") = X
    Range("B1") = Y
End Sub

InputBoxを使って、ユーザーから名前と住所を受け取ります。それぞれを、変数Xと変数Yに入れて、後で変数に入れた値をセルに書き込んでいます。プログラム的には、何も間違っていません。しかし、

    Range("A1") = X
    Range("B1") = Y

の部分を見て、間違いなく「セルA1に名前」「セルB1に住所」が入力されると分かるでしょうか?変数Xに何が入っているか知るには、ずっと上の、InputBoxのあたりを確認しなければなりません。もしこれが、

    Range("A1") = Y
    Range("B1") = X

と書かれていても、それが間違っているようには見えません。では、これを次のような変数名にしたらどうでしょう。

Sub Sample26()
    Dim UserName As String, UserAddress As String
    UserName = InputBox("名前を入力してください")
    UserAddress = InputBox("住所を入力してください")
    ''      :
    ''  何かの処理
    ''      :
    Range("A1") = UserName
    Range("B1") = UserAddress
End Sub

「セルA1に名前」「セルB1に住所」を入力しているというのが、コードを見ただけで分かりやすくなりました。「セルA1に名前」「セルB1に住所」というルールさえ理解していれば、次のコードは間違って見えるはずです。

    Range("A1") = UserAddress
    Range("B1") = UserName

コードの可読性を高めるために必要な考え方のひとつは、間違っているコードは、間違って見えるように書くということです。そのために「変数名に意味を持たせる」というのは、とても有効な手段です。

変数名に意味を持たせる目的は「可読性を高めるため」です。可読性を高めるのが目的なのですから、ただ単に、意味のある変数名を使えばいいのではありません。間違えてはいけない"重要な変数"が、重要に見えることも大事です。

Sub Sample27()
    Dim LoopCounter As Long, TemporaryString As String, UserName As String
    For LoopCounter = 1 To 100
        If Cells(LoopCounter, 1) <> "" And InStr(Cells(LoopCounter, 1), " ") > 0 Then
            TemporaryString = Cells(LoopCounter, 1)
            UserName = Left(TemporaryString, InStr(TemporaryString, " ") - 1)
            Cells(LoopCounter, 2) = UserName
        End If
    Next LoopCounter
End Sub

変数LoopCounterは、確かにForループで使うカウンタ変数です。名前としては間違っていません。また、変数TemporaryStringは文字列を一時的に格納する変数ですから、これもネーミングは正しいです。しかし、どちらもここでは"重要でない"変数です。重要でない変数にまで意味のある名前を付けた結果、重要な変数が埋もれてしまい、コード全体の可読性は、逆に低下しています。重要な変数が"重要に見える"ようにするには、重要でない変数の名前を簡素化するのがポイントです。次のコードと見比べてください。

Sub Sample27()
    Dim i As Long, tmp As String, UserName As String
    For i = 1 To 100
        If Cells(i, 1) <> "" And InStr(Cells(i, 1), " ") > 0 Then
            tmp = Cells(i, 1)
            UserName = Left(tmp, InStr(tmp, " ") - 1)
            Cells(i, 2) = UserName
        End If
    Next i
End Sub

後で解説するように、For Nextで使うカウンタ変数は、アルファベット小文字の「i」「j」「k」を使うのが一般的です。Cells(i, 1)というコードは、決して可読性が悪いわけではありません。であるなら、何も「変数には意味のある名前を付ける」ことにこだわって、Cells(LoopCounter, 1)とする必要はありません。可読性を高めるという目的を見失わないようにしてください。

よく使われる変数名

重要な変数を目立たせるには、重要でない変数に簡素な名前を使うのがポイントです。ここでは、そうした"重要でない"変数に、一般的によく使われる変数名をご紹介します。なお、ここで紹介する変数名は、絶対的なものではなく、こういう名前を使うことが多い…というレベルです。また、私の個人的なクセや経験にもよります。

buf
中間処理などで一時的に格納するときなど。「緩衝器」を表す英単語Bufferの略
Dim buf As String
buf = Range("A1")
tmp
一時的に使用する変数など。「仮の」を表す英単語Temporaryの略
Dim tmp As Variant
tmp = Split(buf, ",")
if tmp(1) = "" Then Exit Sub
i , j , k
For Nextステートメントのカウンタ変数。iは「繰り返し」を意味する英単語Iterationの頭文字とする説もある。jとkは、単にiの次のアルファベットだから
Dim i As Long, j As Long
For i = 1 To 10
    For j = 2 To 5
        Cells(i, j) = "tanaka"
    Next j
Next i
cnt
何かの件数などを数えるときの変数。「計数機」「カウンター」を意味する英単語Counterの略
Dim i As Long, cnt As Long
For i = 1 To 100
    If Cells(i, 1) = "田中" Then
        cnt = cnt + 1
    End If
Next i
MsgBox "田中は、" & cnt & "件です"
msg
ユーザーに対して表示する文字列を格納する変数。「メッセージ」を意味する英単語Messageの略
Dim msg As String, buf As String
msg = "住所を入力してください。" & vbCrLf & _
      "東京都の方は区からでけっこうです。、" & vbCrLf & _
      "その他の方は道府県名を省略しないでください。"
buf = InputBox(msg)
If buf = "" Then Exit Sub
msg = "住所は" & vbCrLf & buf & "ですね。" & vbCrLf & _
      "この住所は、後で変更できます。"
MsgBox msg, vbInformation
flag
オン(yes)/オフ(no)などの判定を格納する変数。「旗」を意味する英単語Flagから
Dim flag As Boolean, i As Long
For i = 1 To Sheets.Count
    If Sheets(i).Name = "合計" Then
        flag = True
        Exit For
    End If
Next i
If flag = True Then
    MsgBox "[合計]シートは存在します"
End If
n
一時的な数値を格納する変数。「数」を意味する英単語Numberの頭文字
Dim n As Long, i As Long
n = Cells(Rows.Count, 1).End(xlUp).Row
If n > 1 Then
    For i = 2 To n
        Cells(i, 1).Font.ColorIndex = 3
    Next i
End If

ハンガリアン記法について

変数の名前に関するルールのひとつに「ハンガリアン記法」と呼ばれるものがあります。ハンガリアン記法の詳しい解説は割愛しますが、簡単に言うと「変数名の先頭に、その変数の型を表す文字を付ける」というルールです。たとえば、文字列型(String)であれば「str○○」、長整数型(Long)の変数であれば「lng××」などのように。こうしたハンガリアン記法に関しては賛否両論で、最近では否定派が多いように感じます。

私も、どちらかと言えば、ハンガリアン記法に関して否定派です。特に、Excel VBAにおいては不要だと感じます。

そもそも、ハンガリアン記法が推奨された理由のひとつは「誤りが誤って見えるように書く」ということです。たとえば、C#で、次のコードはエラーになります。

private void sample()
{
    string strBuf = "100";
    int intBuf = 0;
    strBuf = strBuf * 2;
    intBuf = strBuf;
    MessageBox.Show(intBuf);
}

文字列型の変数を計算したり、整数型の変数をMessageBoxで表示しようとしているからです。確かにC#では、文字列型の変数を計算したり、整数型の変数をMessageBoxの引数に指定することはできません。型が違うからです。

では、VBAではどうでしょう。

Sub Sample28()
    Dim strBuf As String, lngBuf As Long
    strBuf = 100
    strBuf = strBuf * 2
    lngBuf = strBuf
    MsgBox lngBuf
End Sub

文字列型変数(strBuf)に数値を代入したり、その文字列型変数(strBuf)を計算してもエラーになりません。また、本来MsgBoxの引数には文字列を指定しなければなりませんが、長整数型(lngBuf)を指定してもエラーになりません。VBAでは、データの型が自動的に変換(キャスト)されます。良くも悪くも、これがVBAの特徴なのです。であるなら、変数が文字列型か長整数型かを明記することは、あまり意味がないように感じます。何しろ「strBuf = strBuf * 2」は間違っていないのですから。また、VBAにはすべての型を格納できるバリアント型(Variant)という型があります。バリアント型には文字列でも、数値でも、オブジェクトでも格納できます。そのバリアント型変数が「varBuf = varBuf * 2」のように使われていたとき、これが誤っているかどうかは、コードを見ただけで判別できません。

変数名に、変数の型を示す文字を付けるより、その変数が何に使われるかを明確にすべきです。「strBuf = strBuf * 2」は正しいコードかもしれません。しかし「UserName = UserName * 2」は、どう考えても間違っていると思います。

いわゆる、システムハンガリアンではなく、アプリケーションハンガリアンの考え方なら、私も賛成です。システムハンガリアンとアプリケーションハンガリアンについては・・・各自ネットなどで検索してくださいな。