みなさん、こんにちは。
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を知らないと、他人のソースコードを読んだときに読解が困難になりますので、チームで作業する人は覚えておくことを推奨します。
それでは、また次回お会いしましょう!