EB000004_VBAエキスパート(ExcelVBAベーシック)合格講座/第四回:変数と定数

VBAエキスパート(ExcelVBAベーシック)合格講座/第四回:変数と定数 ExcelVBA Basic
  1. このページの内容について
  2. 変数
    1. 変数とは
      1. サンプルコード(クリックでコピー)
      2. 処理時間の違いを体感しましょう
    2. 変数の型
    3. 変数の宣言
      1. 変数を宣言する理由
      2. 変数の宣言方法
      3. 宣言を省略しても同じ結果になります
      4. 変数を宣言しないと起きること
      5. 変数の宣言を強制する
        1. VBEのオプションを開く
        2. 編集タブから「変数の宣言を強制する」を選択
        3. 新しいモジュールを作成すると変数の宣言を強制する文言が自動追加されます
        4. 変数を宣言せずに使用すると起きるエラー
      6. 宣言の省略記法
        1. サンプルコード(クリックでコピー)
        2. 誤った省略の仕方
    4. 変数の初期値
      1. サンプルコード(クリックでコピー)
      2. 変数の状態はローカルウィンドウから確認しましょう
    5. 変数への代入
      1. 値の代入
      2. オブジェクトの代入
    6. 変数の適用範囲(スコープ)
      1. スコープとは
      2. ローカル変数(局所変数)
        1. ローカル変数とは
        2. サンプルコード(クリックでコピー)
        3. 変数の宣言を強制しているかによって結果が異なります
      3. モジュールレベル変数
        1. モジュールレベル変数とは
        2. サンプルコード(クリックでコピー)
        3. 別のプロシージャ間で変数を共有することができました
      4. パブリック変数(グローバル変数)
    7. 変数の有効期間(寿命)
      1. 宣言方法による変数の有効期間の違い
        1. サンプルコード(クリックでコピー)
        2. 実行結果
      2. 変数の初期化の重要性
        1. サンプルコード(クリックでコピー)
        2. 実行結果
  3. 定数
    1. 定数とは
    2. 定数の使い方
      1. サンプルコード(クリックでコピー)
      2. 実行結果
    3. 定数のスコープ
      1. サンプルコード(クリックでコピー)
      2. 実行結果
    4. 定数を使ったサンプル(応用編)
      1. サンプルコード(クリックでコピー)
      2. 定数を使用する理由
  4. VBAエキスパート試験対策記事

このページの内容について

このページは、VBAエキスパート(ExcelVBAベーシック)試験合格講座の第四回記事です。第公式テキスト第5章「変数と定数」の内容について解説します。1時間の講義でお話する程度の分量です。講座受講者の復習での利用を想定しています。

変数

変数とは

データを一時的に格納しておく記憶域のことです。Excelのセル1つのようなものです。通常、セルへデータを書き出すよりも変数にデータを格納する方が処理速度が速いです。特に何万行ものデータを扱うと体感速度が大きく異なります。

サンプルコード(クリックでコピー)

Private Sub LoopRange50000()

Dim target_rng As Range
Dim i As Long

Set target_rng = ThisWorkbook.Worksheets(1).Range("A1")
Debug.Print Now

For i = 1 To 50000 Step 1
target_rng.Value = i
Next i

Debug.Print Now

End Sub
Private Sub LoopVariableMillion()

Dim x As Long
Dim i As Long

Debug.Print Now

For i = 1 To 1000000 Step 1
x = i
Next i

Debug.Print Now

End Sub

処理時間の違いを体感しましょう

サンプル上段のコードを実行すると、マクロを実行中のブックの左から1番目のシートのセルA1に5万回データ入力をします。入力前と後の時間がイミディエイトウィンドウに表示さます。下段のコードを実行すると変数に100万回データの格納を実施します。

私のPC環境
 サンプル上 ・・・ 12秒
 サンプル下 ・・・ 1秒未満

という結果になります。
大した差に見えないかもしれませんが、マクロ実行中に12秒も待たされると不安になるものです。自身の環境でも試してみてください。PCの性能によってはさらに時間がかかると思いますので、繰り返す数値は調整しましょう。

変数の型

変数には型を設定することができ、下記のようなものがあります。Excelのセルの書式のようなものです。

表記型名格納できるデータ
Booleanブール型True/False
Byteバイト型整数(0~255)
Integer整数型整数(-32,768~32,767)
Long長整数型整数(-2,147,483,648~2,147,483,647)
Currency通貨型小数点第四位までの数(-92,233,720,385,477.5808~922,337,203,685,477.5807)
Single単精度浮動小数点数型負の値の場合は -3.4028235E+38 から -1.401298E-45 まで、
正の値の場合は 1.401298E-45 から 3.4028235E+38 まで
Double倍精度浮動小数点数型負の値の場合は-1.79769313486231570 E + 308 から -4.94065645841246544 E-324まで
正の値の場合は1.79769313486231570 E + 308まで
Date日付型日付:100年1月1日~9999年12月31日
時刻:0:00:00~23:59:59
String文字列型最大20億文字
Objectオブジェクト型オブジェクト
Variantバリアント型変数に格納できるすべてのデータ

昔はメモリ節約のため、大きな値を格納しないことが事前にわかっている場合は、それに見合った小さな型を使用することが推奨されていました。しかし、いまはPC性能が向上しておりメモリを節約しても人間が体感できるほど実行速度に影響がでないため「大は小を兼ねる」型を選択しましょう。整数型は「Long」・小数点数型は「Double」がよく使用されます。

変数の宣言

変数を宣言する理由

変数は宣言することができます。宣言をすることで型が一目でわかるため、コードの可読性が向上します。宣言を省略して変数を使用する場合、すべて「Variant」型とみなされます。

変数の宣言方法

「Dim 変数名 As 型」のように記述します。

宣言を省略しても同じ結果になります

Private Sub Test_Decleare()
Dim cnt As Long
cnt = cnt + 1
Debug.Print cnt
End Sub
Private Sub Test_UnDecleare()
cnt = cnt + 1
Debug.Print cnt
End Sub

上記2つのサンプルをそれぞれ実行しても結果は同じです。

変数を宣言しないと起きること

変数の宣言は省略することができますが、宣言をしない場合、どんな変数も有効となってしまい開発者の意図しないエラーが発生することがあります。下記サンプルの実行結果はイミディエイトウィンドウに200が出力されるはずですが、そうなりません。どうすれば200が表示されるでしょうか?修正点を一目で判断できるでしょうか。

Private Sub Test_0O0O()
Dim No_01 As Long
Dim No_02 As Long

No_01 = 100
No_02 = 100

Debug.Print No_01 + No_O2
End Sub

変数の宣言を強制する

変数の宣言はExcelの設定で「強制」することができます。

VBEのオプションを開く

VBEを起動(「Alt」+「F11」)し、リボンの「ツール」⇒「オプション」を開く。

編集タブから「変数の宣言を強制する」を選択

「編集」タブ⇒「変数の宣言を強制する(R)」にチェックを入れて「OK」を押下する

新しいモジュールを作成すると変数の宣言を強制する文言が自動追加されます

設定が完了すると、新しく作成するモジュールの冒頭に「Option Explicit」という文言が自動で追加されるようになります。この文言はこのモジュール内で変数の宣言を強制し、宣言されていない変数がある場合、プロシージャの実行前にコンパイルエラーを発生させるというものです。設定によって変数の宣言が強制されているわけではなく、設定によって変数の宣言を強制する文言が自動追加されるようになったということです。そのため、変数の宣言を強制する設定をしていても手動で文言を削除すれば変数を宣言なしで使用できます。

変数を宣言せずに使用すると起きるエラー

前述のサンプルコードを変数の宣言を強制した状態で実行すると以下のようになり「No_02」と入力されるべき箇所に「No_O2」と入力されていたことがわかります。

宣言の省略記法

マクロが複雑になるほど使用する変数も多くなります。そんな時、複数の宣言を「,(カンマ)」で区切って1行にまとめて書くとコードの行数を抑えることができます。

サンプルコード(クリックでコピー)
Private Sub Test_Decleares()
Dim i As Long, j As Long, k As Long
Dim x, y, z As Long
Stop
End Sub
誤った省略の仕方

上記サンプルを実行すると「Stop」で動作を停止します。そこでローカルウィンドウを開き変数の中身を確認してみましょう。「x」と「y」がLong型ではなく、Variant型になってしまっていることがわかります。

変数の初期値

変数には型に応じてそれぞれ初期値が設定されています。

サンプルコード(クリックでコピー)

Private Sub InitialValue()
Dim bool As Boolean
Dim by As Byte
Dim i As Integer
Dim lng As Long
Dim cur As Currency
Dim sin As Single
Dim dbl As Double
Dim day As Date
Dim str As String
Dim obj As Object
Dim val As Variant
Stop
End Sub

変数の状態はローカルウィンドウから確認しましょう

上記サンプルを実行すると「Stop」で動作を停止します。そこでローカルウィンドウを開き変数の中身を確認してみましょう。

変数への代入

値の代入

代入演算子「=」を使用します。

Private Sub Test_SubstituteValue()

Dim hello As String
Dim today As String

hello = "こんにちは"
today = "2024/11/24"

Call MsgBox(hello & today & "です。")

End Sub

オブジェクトの代入

「Set」と代入演算子「=」を使用します。

Private Sub Test_SubstituteObject()

Dim wb As Workbook
Dim ws As Worksheet

Set wb = ThisWorkbook
Set ws = wb.Worksheets(1)

Debug.Print ws.Name

End Sub

変数の適用範囲(スコープ)

スコープとは

変数は宣言方法や宣言する場所によって使用できる範囲が異なります。この変数を使用できる範囲のことを「変数のスコープ」や「変数の可視範囲」と呼びます。

ローカル変数(局所変数)

ローカル変数とは

ローカル変数とはプロシージャ内で宣言された変数のことです。プロシージャ内で宣言された変数はそのプロシージャ内でしか使用することができません。下記サンプルコードで確認してみ下さい。「Test_Scope」はプロシージャ内で「msg」という変数を宣言し、msgに文字列を代入しています。その後「Test_ScopeSub」を呼び出していますがTest_ScopeSub内でmsgを使おうとしています。

サンプルコード(クリックでコピー)
Private Sub Test_Scope()

Dim msg As String
msg = "これはローカル変数です"

Call Test_ScopeSub

End Sub

Private Sub Test_ScopeSub()

Call MsgBox(msg, vbInformation)

End Sub
変数の宣言を強制しているかによって結果が異なります

上記サンプルコードで「Test_Scope」を実行すると、変数の宣言を強制している場合は「Test_ScopeSub」が呼び出されるときに「変数が定義されていません。」というエラーが発生します。変数の宣言を強制していない場合は、このエラーを回避できますが、「Test_ScopeSub」のmsgは「Test_Scope」のmsgとは別物とみなされるため、空白のメッセージが表示されます。

モジュールレベル変数

モジュールレベル変数とは

変数の宣言はプロシージャの外でも実行することができます。プロシージャの外で宣言された変数は、モジュール内であればどのプロシージャからも使用することができます。下記サンプルでは前述のようなエラーは発生しません。

モジュールレベル変数の宣言はどのプロシージャよりも上に記述する必要があります。

サンプルコード(クリックでコピー)
Dim msg As String

Private Sub Test_ScopeModule()

msg = "これはモジュールレベル変数です"

Call Test_ScopeModuleSub

End Sub

Private Sub Test_ScopeModuleSub()

Call MsgBox(msg, vbInformation)

End Sub
別のプロシージャ間で変数を共有することができました

上記のサンプルコードで「Test_ScopeModule」を実行するとモジュールレベル変数である「msg」に文字列を代入し「Test_ScopeModuleSub」を呼び出します。呼び出し先ではmsgをメッセージ表示します。モジュール内で変数の共有ができているためエラーが発生せず、また意図した通りのメッセージが表示されます。

モジュールレベル変数を定義する場合「Dim」は「Private」と置き換えて宣言することができます。この場合でも変数のスコープは同じです。

パブリック変数(グローバル変数)

モジュールレベル変数の「Dim」や「Private」を「Public」に置き換えて宣言すると別のモジュールからも使用可能な変数となります。サンプルコードでは表現しきれませんので、自身で試してみてください。

変数の有効期間(寿命)

宣言方法による変数の有効期間の違い

プロシージャ内で宣言された変数は、プロシージャの動作が終了すると中身は消えてしまいます。そのため2回目、3回目を実行しても結果は同じです。しかしモジュールレベル変数とパブリック変数はプロシージャ終了後も値が残るため、マクロの内容によっては1回目と2回目で実行結果が変わってしまいます。

サンプルコード(クリックでコピー)
Dim cnt As Long

Private Sub Test_Life()

cnt = cnt + 1
Debug.Print cnt

End Sub
実行結果

上記サンプルを実行すると実行の都度、イミディエイトウィンドウに表示される数値が増えていくことが確認できます。このように、モジュールレベル変数とパブリック変数はプロシージャの動作終了後も値を保持します。

変数の初期化の重要性

上記のように実行の都度結果が変わってしまうマクロは管理上好ましくありません。ユーザーの意図しない結果となってしまうことがあります。意図して実行結果を変えたい場合を除き、原則は変数を初期化して、何度実行しても同じ結果になるマクロを作成しましょう。

サンプルコード(クリックでコピー)
Dim cnt As Long

Private Sub Test_Initialize()

cnt = 0
cnt = cnt + 1
Debug.Print cnt

End Sub
実行結果

上記サンプルを実行すると、何度実行しても結果同じイミディエイトウィンドウに「1」が出力されます。

上記のように、変数に最初に入れておく値を代入することを「変数を初期化する」と表現します。

定数

定数とは

変数は「データを一時的に格納しておく記憶域のこと」です。また、変数は代入演算子を使用してマクロの実行中に何度でも書き換えることができます。定数とは、変数と同じく「データを一時的に格納しておく記憶域のこと」ですが、書き換えることができません。

定数の使い方

変数を宣言するときに使用する「Dim」を「Const」に置き換え、型指定後に続けて代入演算子を記述し、定数に入れる値を指定します。
例)Const TAIYO as String = “Sun”
「TAIYO」という定数を宣言し「Sun」という値を指定しています。

サンプルコード(クリックでコピー)

Private Sub Test_Const()

Const TAIYO As String = "Sun"

Debug.Print TAIYO

TAIYO = "Cloud"

End Sub

実行結果

上記のサンプルは実行しようとしてもエラーが発生します。定数を書き換えようとしているためです。このように、書き換えができないようVBAが管理してくれるため、プログラムを通じて変更する予定のないデータは定数で管理すると事故が少なくなります。

定数のスコープ

変数と同様です。宣言する場所や宣言の方法によって使用できる範囲を変更することができます。

サンプルコード(クリックでコピー)

Private Const KUMO As String = "cloud"
Const TAIYO As String = "Sun"

Private Sub Test_ModuleConst()

Debug.Print TAIYO

End Sub
Private Sub Test_PrivateConst()

Debug.Print KUMO

End Sub

実行結果

上記のサンプルはどちらも定数の内容をイミディエイトウィンドウに出力します。「Private」は記述しても省略しても動きは同じです。

定数も変数同様にパブリック(グローバル)定数として宣言することができます。宣言の方法はプロシージャの外に「Public」を付けて定数を宣言するだけです。サンプルではモジュールをまたぐ表現が難しいので自分で試してみてください。

定数を使ったサンプル(応用編)

このサンプルは難易度が高いので読み飛ばしOKです。

サンプルコード(クリックでコピー)

Private Property Get wsh() As Object

  Static Obj As Object
  If Obj Is Nothing Then Set Obj = CreateObject("WScript.Shell")
  Set wsh = Obj

End Property
Private Sub Test_YesConst()

Const URL_TOP As String = "https://funcref.com/{@page}"
Const LESSER As String = "lesserscraping/"
Const VBA_EX As String = "vbaexpertlesson/"
Const FIND_KEY As String = "{@page}"

Dim url As String
url = Replace(URL_TOP, FIND_KEY, VBA_EX)
Call wsh.Run(url)

url = Replace(URL_TOP, FIND_KEY, LESSER)
Call wsh.Run(url)

End Sub
Private Sub Test_NoConst()

Dim url As String
url = Replace("https://funcref.com/{@page}", "{@page}", "vbaexpertlesson/")
Call wsh.Run(url)

url = Replace("https://funcref.com/{@page}", "{@page}", "lesserscraping/")
Call wsh.Run(url)

End Sub

定数を使用する理由

上記、サンプルコードを実行すると、マクロを実行する人(ユーザー)のPCに設定されているデフォルトのブラウザを使用して当サイトの「VBAエキスパート」「LesserScraping」ページをそれぞれ開きます。プロシージャは2つ記述していますが、それぞれ同じ結果になります。見比べるとわかるように、定数を使用しない場合、宣言部がない分コードは短くなっています。しかし、処理部分のコードはひとつひとつの単語が長く、読みづらいです。定数を使用することで処理部分をすっきりさせることができ、また、書き換えができないため誤って書き換えてしまうこともなくなります。

VBAエキスパート試験対策記事

当サイトでは、オデッセイコミュニケーションズ社が運営する試験であるVBAエキスパートExcel VBA ベーシックExcel VBA スタンダード)の出題範囲をベースに用語や各種関数の解説などを行っています。試験合格に向けて必須と言われる公式テキストに沿って解説をしています。受験をするか悩んでいる方、テキストとは別視点の解説を見てみたい方、受験はしないがExcelVBA(マクロ)に興味がある方へ向けた記事です。

Comment