ラピードアクト株式会社

技術記事:ExcelVBAで仕事を効率化しようVol.7

みなさん、こんにちは。
ITソリューション事業部の林です。

本記事では、ExcelVBAのテクニックを紹介・解説いたします。
今回紹介するものは、「Withステートメント」です。

同じオブジェクトを操作するプロシージャでWithステートメントを使うと、ソースコードの見た目をすっきりさせて、可読性を向上する効果があります。
また、全体的にソースコードの文字数を減らせるので、マクロの作成速度の向上も期待できますよ。

【目次】

  1. Withステートメントとは
  2. Withの使用例
  3. With使用時の注意点
  4. 終わりに

それでは、始めましょう!

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にある.ValueWorksheets("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を知らないと、他人のソースコードを読んだときに読解が困難になりますので、チームで作業する人は覚えておくことを推奨します。

それでは、また次回お会いしましょう!