
みなさん、こんにちは。
ITソリューション事業部の林です。
本記事では、ExcelVBAのテクニックを紹介・解説いたします。
今回紹介するものは、「Withステートメント」です。
同じオブジェクトを操作するプロシージャでWithステートメントを使うと、ソースコードの見た目をすっきりさせて、可読性を向上する効果があります。
また、全体的にソースコードの文字数を減らせるので、マクロの作成速度の向上も期待できますよ。
【目次】
それでは、始めましょう!
Withステートメントとは
Withは、特別な処理を行うステートメントというわけではなく、ソースコードの記述を省略するために使用するものです。
Withの書式は以下の通りです。
Withステートメントの書式
With オブジェクト
(指定オブジェクトの操作)
End With
Withのことを簡単に言うと、「処理対象オブジェクトをまとめて書く」ことができるステートメントです。
まとめて書かないソースコードとは、例えば以下のようなものです。
Sub ExcelVBA007_1()
Dim EmpNum, EmpName, EmpDept, EmpJoinDate
EmpNum = Worksheets("社員情報").Cells(2, 1).Value
EmpName = Worksheets("社員情報").Cells(2, 2).Value
EmpDept = Worksheets("社員情報").Cells(2, 3).Value
EmpJoinDate = Worksheets("社員情報").Cells(2, 4).Value
MsgBox "社員番号:" & EmpNum & vbCrLf & _
"氏名:" & EmpName & vbCrLf & _
"部署:" & EmpDept & vbCrLf & _
"入社日:" & EmpJoinDate, vbInformation
End Sub
同じシートの2行目にあるセルの値を取得していますが、見た印象ではWorksheets("社員情報")がたくさん並んでいて、冗長な見た目になっています。
このようなケースでは、Withを使用すれば冗長さを無くすことができます。
それでは、例を用いてWithの使い方を見ていきましょう。
Withの使用例
使用例①
以下のシートから値を取得し、メッセージを表示します。

Sub ExcelVBA007_2()
Dim EmpNum, EmpName, EmpDept, EmpJoinDate
With Worksheets("社員情報")
EmpNum = .Cells(2, 1).Value
EmpName = .Cells(2, 2).Value
EmpDept = .Cells(2, 3).Value
EmpJoinDate = .Cells(2, 4).Value
End With
MsgBox "社員番号:" & EmpNum & vbCrLf & _
"氏名:" & EmpName & vbCrLf & _
"部署:" & EmpDept & vbCrLf & _
"入社日:" & EmpJoinDate, vbInformation
End Sub
先ほどの冗長なソースコードに対して、Withを用いて修正しました。
社員情報シートの2行目から値を取得する挙動自体は変わっていませんが、Worksheets("社員情報")の記述がWithで1箇所になったので、ソースコードの見た目がすっきりしましたね。
Withステートメントの内側では、先頭にドットを付けたオブジェクトは、Withで省略したオブジェクトの子オブジェクトであることを表します。
Withにワークシートを指定しており、その子レベルにあたるセルオブジェクトを記述する際は、ドット(.)を先頭に付け、.Cells(2,1)のように書きます。
プロシージャを実行すると、以下のようにメッセージが表示されます。

使用例②
Sub ExcelVBA007_3()
With Worksheets("社員情報")
With .Cells(2, 2)
.Font.Bold = True 'フォントを太字に変更
.Interior.ColorIndex = 7 'セル背景色を変更
End With
With .Cells(2, 4)
.Font.Italic = True 'フォントを斜体に変更
.Font.ColorIndex = 7 'フォント色を変更
End With
End With
End Sub
Withの内側にWithを入れ子にし、Cellsオブジェクトの記述を省略しました。
入れ子(内側)のWithでは、セルのプロパティを変化させています。
このように、1つ目のWithと2つ目のWithに関連を持たせる方法もあります。
プロシージャを実行すると、セルの状態が変化します。

With使用時の注意点
注意点① オブジェクトを指定しなければならない
Withで省略指定できる対象は、オブジェクトです。
言い換えると、オブジェクト以外のものを指定するとエラーになるということです。
例えば、以下のように.Cellsの途中で区切ってしまうと、コンパイルエラーが発生します。
Sub ExcelVBA007_4()
Dim EmpNum, EmpName, EmpDept, EmpJoinDate
With Worksheets("社員情報").Cells(2
EmpNum = , 1).Value
EmpName = , 2).Value
EmpDept = , 3).Value
EmpJoinDate = , 4).Value
End With
End Sub
Withは、あくまでオブジェクト指定を省略するステートメントであるということは念頭に置いておきましょう。
注意点② 指定できるオブジェクトは1つだけ
1つのWithステートメントに複数のオブジェクトは指定できません。
注意点③ Withの内側では最も近いWithとの関連が優先される
これは、Withを入れ子にするときに特に意識すべきことなのですが、Withで省略したオブジェクトと、その内側のオブジェクトやプロパティは、近いものほど関連が優先されます。
例えば、Sheet1のA2セルの値を、Sheet2とSheet3のA2セルに値を移そうとして、以下のようにWithを使っても、求めた結果は得られません。
Sub ExcelVBA007_5()
With Worksheets("Sheet1").Cells(2, 1)
With Worksheets("Sheet2")
.Cells(2, 1).Value = .Value
End With
With Worksheets("Sheet3")
.Cells(2, 1).Value = .Value
End With
End With
End Sub
実行しても実行時エラーになります。
エラーの原因は、内側のWithで参照できないプロパティを参照しようとしたことです。
内側のWithにある.ValueはWorksheets("Sheet2")やWorksheets("Sheet3")を参照しにいき、最も外側のWorksheets("Sheet1").Cells(2, 1)を参照しません。
そして、WorksheetsオブジェクトはValueプロパティを持ちませんので、結果としてエラーになってしまうということです。
このようなケースでは変数に値を一時的に記憶するなどして、対応しましょう。
Sub ExcelVBA007_5()
Dim Val1
With Worksheets("Sheet1").Cells(2, 1)
Val1 = .Value
End With
With Worksheets("Sheet2")
.Cells(3, 1).Value = Val1
End With
With Worksheets("Sheet3")
.Cells(3, 1).Value = Val1
End With
End Sub
終わりに
Withステートメントを使う際は、オブジェクトとプロパティのつながりを意識することが大事です。
また、Withステートメントを知っているマクロ作成者は、Withを使った方が良いケースがあれば必ずと言っていいほど使用します。
Withを知らないと、他人のソースコードを読んだときに読解が困難になりますので、チームで作業する人は覚えておくことを推奨します。
それでは、また次回お会いしましょう!