Setとは? オブジェクト変数の使い方とNothingの意味を解説
Workbook型やWorksheet型の変数の最後に半角ドットをつけると、メソッドやプロパティの候補一覧が表示されます。 メソッドとプロパティは(語弊はありますが)簡単に言うと、メソッドはオブジェクト変数でのみ使用できる専用の関数、プロパティはオブジェクト変数でのみ使用できる専用の変数と覚えてください。 ただし、Object型で宣言した後は候補一覧が表示されないため、注意が必要です。 Setを使用するのは、変数とオブジェクトを紐づける時のみで、メソッドやプロパティを使用する時はSetを付ける必要はありません。 文字通り、Set=設定する、ということですね。
Functionプロシージャでオブジェクトを返す場合Functionプロシージャでオブジェクトを返す場合、 Function名で返す時と、呼び出し元で受け取る際の2か所でSetを使用する 必要があります。
Function SampleSet1() Set SampleSet1 = ThisWorkbook.Worksheets(1) End Function Sub Main1() Dim ws As Worksheet Set ws = SampleSet1 End Sub 【例外】引数でオブジェクト変数に参照先を格納する場合Functionプロシージャの引数をオブジェクトを渡すことが出来ます。 なお、 オブジェクト(オブジェクト変数)を引数にする場合、"Set"を付ける必要がありません。
Function SampleSet2(wb as Workbook) '← ここは Set 不要 '何らかの処理 End Function Sub Main() ’マクロを実行しているブックオブジェクトを送る SampleSet2 ThisWorkbook End Sub オブジェクト変数の参照を解除する Set 変数 = NothingSet 変数 = Nothing を使うと、オブジェクト変数の初期化(メモリの解放)を行うことができます。ただし、VBAでは自動的に初期化がありますので、通常は不要となります。詳細は、後述します。
Setの使用例 ブックをオブジェクト変数に代入する Sub sample1_1() 'Workbook型の変数wbを作成する Dim wb As Workbook '変数wbに実行しているブックオブジェクトを参照させる Set wb = ThisWorkbook '実行しているブックを閉じる wb.Close '←ThisWorkbook.Close と同じ End Sub シートをオブジェクト変数に代入する Sub SetSample1_2() Dim ws As Worksheet Set ws = ThisWorkbook.Worksheets(1) '実行しているシート名を表示する MsgBox ws.Name '←MsgBox ThisWorkbook.Worksheets(1).Name と同じ End Sub Setを使うメリットは?-
見やすさ(可読性)が大きく向上する Set を使用するとプログラムが短くなり、読みやすくなります。 Setを使用しないパターンと使用するパターンを比較してみます。 まずは、Set を使用しないパターンです。
これまで述べてきた通り、オブジェクトの参照を変数に格納する場合、変数の前に"Set"を付ける必要があります。 この場合「実行時エラー 91」が発生します。
'実行時エラー 91になる(Sheet1のセルA1に"a"を格納したかった) Sub SetSample3_1() Dim ws As Worksheet '先頭に"Set" を忘れているため、エラーが発生する _ ※「Set ws = Worksheets("Sheet1")」が正しい ws = Worksheets("Sheet1") ws.Cells(1, 1) = "a" End Sub 【実行時エラー 438】存在しないプロパティやメソッドを参照存在しないプロパティやメソッドを参照すると「実行時エラー 438」が発生します。 Object型へ想定していたオブジェクトと異なるオブジェクトを代入したケースがあります。他に、プロパティ名やメソッド名をタイプミスしたケースがあります。
Object型へ想定していたオブジェクトと異なるオブジェクトを代入したケース '実行時エラー 438になる(ブックを閉じたかった) Sub SetSample3_2_1() Dim wb As Object '"Worksheets" は不要(ミス) Set wb = ThisWorkbook.Worksheets 'WorksheetsオブジェクトにCloseメソッドはない wb.Close ' ←ここでエラーが発生する End Sub プロパティ名やメソッド名をタイプミスしたケース '実行時エラー 438になる(シート名を変えたかった) Sub SetSample3_2_2() Dim ws As Object Set ws = Worksheets(1) 'ws.Name が正しい(Namee になっている) ws.Namee = "シート1" ' ←ここでエラーが発生する End SubObject型でなく、Worksheet型で変数を作成すると「コンパイルエラー:メソッドまたはデータメンバーが見つかりません。」とエラーメッセージが表示されます。 可能であれば、Object型を使用せず、Worksheet型等を指定 するようにしましょう。
【論理エラー】2つのオブジェクト変数が干渉し合っている2つのオブジェクト変数を作成し参照先が同じオブジェクト コンパイルエラーや実行時エラー等にならない論理エラー(プログラムは実行できるが想定と異なること)です。 2つの変数が同じオブジェクトを参照している場合、片方の変数を通じてオブジェクトを変更すると、もう片方の変数から参照したときに変更内容が反映されています。 あくまで、オブジェクト変数は1つのオブジェクトを参照しているだけで、実体は1つだからです。
Sub SetSample3_3_1() Dim wb1 As Workbook Dim wb2 As Workbook Set wb1 = ThisWorkbook Set wb2 = wb1 '↓wb1のSheet1のセルA1も"Hello"となる wb2.Worksheets("Sheet1").Range("A1") = "Hello!" End SubSetSample3_3_1 と SetSample3_3_2は同じ結果になります。
Sub SetSample3_3_2() Dim wb1 As Workbook Dim wb2 As Workbook Set wb1 = ThisWorkbook Set wb2 = wb1 '↓【wb2】のSheet1のセルA1も"Hello"となる wb1.Worksheets("Sheet1").Range("A1") = "Hello!" End Sub Set 変数 = Nothing は必要?普通にVBAを使用する分には、不要となります。 なぜなら、VBAには、参照カウント方式という、オブジェクト変数の参照が完全になくなると、自動的にメモリが解放される仕組みがあります。 ただし、大きいプロシージャや大量のデータ、大規模な配列を使用する場合、メモリを解放する必要があります。 また、循環参照など特殊なケースではメモリが残ってしまうこともあるため、Set = Nothingを使って明示的に解放することが推奨される場面があります。
'Nothingの使用例 Sub SetSample4_2() Dim ws As Worksheet Set ws = ThisWorkbook.Worksheets(1) MsgBox ws.Name '←MsgBox ThisWorkbook.Worksheets(1).Name と同じ 'オブジェクト変数を初期化(解放)する Set ws = Nothing End Sub確認テスト
- 次の条件を満たすプログラムを作成しなさい。
- マクロを実行しているブックの左から1番目のシートオブジェクトを取得する
- シートオブジェクトより、シート名を「hoge」と変更する
関連リンク
- 次ページ:VBAでエクセルファイルやCSVファイルを開く
- 前ページ:指定のブックのセルのデータを取得・格納する
- 【実行時エラー91】オブジェクト変数または With ブロック変数が設定されていません。
Copyright © 2018 ExcelVBA.Work All Rights Reserved.