With構文をマスターする!便利な使い方と注意点まとめ

今回の目標

「Withとは? 何が便利で、なぜ使うのか?」や「End Withがあるのに『End Withが必要です』とエラーになった! なんで!?」とイラ…疑問を持ったあなたへ。
この記事では、Withの使い方から、Withを入れ子にしたときの挙動、Withの実用例、『End Withが必要です』の対応方法まで、まとめて丁寧に解説します!

目標リスト

  • With について理解を深める
  • With を使用できるようなる
  • With を入れ子にしたときの挙動を知る
  • With のコンパイルエラーを対処できるようなる

説明

Withとは? 何が便利で、なぜ使うのか

With構文は、オブジェクトの記載を省略することが出来る珍しい機能を持ちます。
省略することにより、読みやすさとミス削減に効果があります。また、文字が減ることにより、可読性を上げられます。

With オブジェクト
    '処理
End With 

With ブロックの中では「.」と描くだけで、「オブジェクト.」の意味を持ちます。

With ThisWorkbook
    'MsgBox ThisWorkbook.Worksheets("Sheet1").Range("A1") と同じ
    MsgBox .Worksheets("Sheet1").Range("A1")  '←Worksheetsの前に「.」
End With

上記例では、オブジェクトを直接指定していますが、オブジェクト変数でも可能です。

Withで設定できるオブジェクトの例です。

オブジェクトのデータ型型名
ワークブックオブジェクトWorkbook
ワークシートオブジェクトWorksheet
レンジオブジェクトRange
図形オブジェクトShape
ファイルオブジェクトFile ※1
フォルダオブジェクトFolder ※1

Withの使用例

1.同じシート内でセルの値を変更する

Sheet1のB1の値をSheet1のA1の値に変更します。

Sub WithSample1()
    With ThisWorkbook.Worksheets("Sheet1")
        .Range("B1") = .Range("A1")
    End With
End Sub
【出力結果】
Sheet1のセルB1の値が、Sheet1のセルA1の値になる。

2.Withを使用して、図形を変更する

図形の色や図形内のフォントを変更します。

Sub WithSample2()
    With ActiveSheet.Shapes("Rectangle 1")
        '図形の色を黄緑色へ
        .Fill.ForeColor.RGB = RGB(180, 255, 180)
        '図形の枠線を黒へ
        .Line.ForeColor.RGB = RGB(0, 0, 0)
        '図形内の文字色を黒へ
        .TextFrame.Characters.Font.Color = RGB(0, 0, 0)
        '図形内の文字のフォントをメイリオへ
        .TextFrame.Characters.Font.Name = "メイリオ"
        '図形内の文字のフォントサイズを20へ
        .TextFrame.Characters.Font.Size = 20
    End With
End Sub
【実行結果】

図形「Rectangle 1」が次の通り、変更されます。

・背景色が黄緑色       ・図形の枠線が黒色
・図形内の文字が黒    ・フォントがメイリオ
・フォントサイズが20

WithSample2 の実行結果

3.Withを入れ子にして、セルの値に変更する

Withは入れ子にすることもできます。
入れ子とは、ある構文(ブロック)の中に、構文を入れることで、ネストとも呼ばれます。 今回は、Withブロックの中にWithブロックを設定(ネスト)します。
入れ子にした内側のWithには「.」をつけることで、外側のWithを継承することが出来ます。 逆に入れ子にしたWithにドットを付けていない場合(競合してしまった場合)、外側のWithは引き継がれずに無視されます(詳細は後述します)。

Sub WithSample3()
    With ThisWorkbook
        '下は「ThisWorkbook.Worksheets("Sheet1")」と同じ
        With .Worksheets("Sheet1")    '←「.」をつけている
            MsgBox .Name    '←Sheet1 と表示される
        End With            '←ここでSheet1のWith は終わる
        '以下、最初に定義した「With ThisWorkbook」になる
        MsgBox .Name        '←実行中のブック名 が表示される
    End With
End Sub
【出力結果】

下記、実行結果は新規作成した、名前のついていないExcelファイルです。

1回目のメッセージボックス:Sheet1
2回目のメッセージボックス:Book1

4.WithとFor構文、If構文を併用する

WithはFor構文、If構文等を入れ子にして使用することができます。
C3~C10まで繰り返し、C列が70以上ならD列に"優"、C列が30以上ならD列に"可"、それ以外ならD列に"不可"と入力させます。

Sub WithSample4()
    Dim i As Long
    'マクロを実行しているブックのSheet1
    With ThisWorkbook.Worksheets("Sheet1")
        For i = 3 To 10
            If 70 <= .Range("C" & i) Then
                .Range("D" & i) = "優"
            ElseIf 30 <= .Range("C" & i) Then
                .Range("D" & i) = "可"
            Else
                .Range("D" & i) = "不可"
            End If
        Next i
    End With
End Sub
【出力結果】

「Sheet1」のC3~C10セルに点数を入力すると、D列に評価が出力されます。

行数 C列(点数) D列(判定)
390
475
561
629不可
785
830
915不可
1070

5.一時的にオブジェクトを作成して、Withで使いまわす

CreateObjectでオブジェクトを作成し、Withで使い倒します。
下記サンプルはファイルのファイル名、ファイルサイズ、最終更新日時を取得してセルに入力しています。

Sub WithSample5()
    Dim path As String
    '筆者はヤマダではありません。
    path = "C:\Users\Yamada\Desktop\abc.txt"
    'ファイルオブジェクト
    With CreateObject("Scripting.FileSystemObject").GetFile(path)
        ActiveSheet.Range("A3") = .Name     'ファイル名
        ActiveSheet.Range("B3") = .Size     'ファイルサイズ
        ActiveSheet.Range("C3") = .DateLastModified  '最終更新日時
    End With
End Sub
【出力結果】

実行対象のファイルにより下記、出力結果が変わります。

行数 A列(ファイル名) B列(ファイルサイズ)C列(最終更新日時)
3abc.txt13642025/7/4 10:27:43

Withを使うべき場面と使うべき『でない』場面

Withを使うべき場面

1つのオブジェクトに対する操作を行う場面です。
下記の例は1つのシートオブジェクトに対し、操作を行っています。

Sub WithSampleMerit1()
    With ThisWorkbook.Worksheets("Sheet1")
        .Range("B1") = .Range("A1")
        .Range("B3") = .Range("A3")
        .Range("B7") = .Range("A7")
    End With
End Sub

動的に範囲を指定する時、RangeとCellsを組み合わせ、それぞれにシートオブジェクトを指定すると安全に処理が実行できます。 そのため、Withが有効に使用できます。

Sub WithSampleMerit2()
    With ThisWorkbook.Worksheets("Sheet1")
        'C1:C3 の値を D1:D3 に格納
        .Range(.Cells(1, 4), .Cells(3, 4)).Value = _
            .Range(.Cells(1, 3), .Cells(3, 3)).Value
    End With
End Sub

外側のWithでシートオブジェクトを指定し、内側のWithで罫線の設定をしています。

Sub WithSampleMerit3()
    With ThisWorkbook.Worksheets("Sheet1")
        .Range("B2") = 60
        .Range("B3") = 70
        .Range("B4") = 80
        .Range("B5") = 90
        '範囲:B2~B5の罫線を引く
        With .Range("B2:B5").Borders
            .LineStyle = xlContinuous
            .Color = vbBlack
        End With
    End With
End Sub

Withを使うべき『でない』場面

複数のオブジェクトに対する操作を行う場面です。
下記のように、異なるシートを行き来する場面が該当します。

Sub WithSampleBad1()
    With ThisWorkbook
        With .Worksheets("Sheet1")
            .Range("B1") = .Range("A1")
        End With
        With .Worksheets("Sheet2")
            .Range("B2") = .Range("A2")
        End With
        With .Worksheets("Sheet1")
            .Range("B3") = .Range("A3")
        End With
    End With
End Sub

With をブックに設定すれば、見やすくなりましたが横に広がってしまいました。

Sub WithSampleBad2_1()
    With ThisWorkbook
        .Worksheets("Sheet2").Range("B1") = .Worksheets("Sheet1").Range("A1")
        .Worksheets("Sheet2").Range("B2") = .Worksheets("Sheet2").Range("A2")
        .Worksheets("Sheet1").Range("B3") = .Worksheets("Sheet1").Range("A3")
    End With
End Sub

オブジェクトがまたがる場面では、Set を使用しましょう。

Sub WithSampleBad2_2()
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet
    Set ws1 = ThisWorkbook.Worksheets("Sheet1")
    Set ws2 = ThisWorkbook.Worksheets("Sheet2")
    ws2.Range("B1") = ws1.Range("A1")
    ws2.Range("B2") = ws2.Range("A2")
    ws1.Range("B3") = ws1.Range("A3")
End Sub

Withを入れ子にして競合した場合

入れ子にした内側のWithに「.」をつけずに、外側のWithを引き継がない場合、外側のWithは無視されます。

Sub WithSampleTest1()
    With ThisWorkbook.Worksheets("Sheet1")
        With ThisWorkbook.Worksheets("Sheet2")
            MsgBox .Name    '← With の「Sheet2」が有効
        End With        '← ここで、With の「Sheet2」が終了
        MsgBox .Name    '← With の「Sheet 1」 が有効
    End With
End Sub
【出力結果】
1回目のメッセージボックス:Sheet2
2回目のメッセージボックス:Sheet1

【コンパイルエラー:End With が必要です】のエラー解説

Withを使用すると「コンパイルエラー:End With が必要です。」とエラーが生じる場合があります。 エラー発生時、自動的に選択される文字から、原因が判断できます。

1.コンパイルエラー時、End Sub(End Function)が選択された場合

これはプロシージャ内の「End With」を記載が漏れているパターンです。
適切な箇所に「End With」を記載してください。

'【エラーサンプル】「End With」の記載漏れ
Sub WithSampleErr1()
    With ThisWorkbook   '←対応するEnd With がない
    
End Sub   '←この「End Sub」が選択される

2.コンパイルエラー時、End With が選択された場合

With内にある End With 以外のブロックが締められていません。
例えば、「If ‥ Then」とあるのに「End If」がない、「For ‥ To ‥」とあるのに「Next」がない等、ブロック構成が未完成の状態にこのエラーが発生します。

「End If」がないサンプルです

'【エラーサンプル】「End If」の記載漏れ
Sub WithSampleErr2_1()

    With ThisWorkbook
        If Range("A1") < 10 Then  '←対応するEnd Ifがない

    End With   '←この「End With」が選択される
End Sub

「Next」がないサンプルです

'【エラーサンプル】「Next」の記載漏れ
Sub WithSampleErr2_2()
    Dim i As Long
    
    With ThisWorkbook
        For i = 1 To 11 '←対応するNext がない
            
    End With   '←この「End With」が選択される
End Sub

このエラーは、With内に未完了のブロックがある場合に発生する時に発生します。With内の途中に原因があっても、End With が原因かのように表示されまるため、注意が必要です。

Sub WithSampleErr2_3()
    Dim i As Long
    
    With ThisWorkbook.Worksheets("Sheet1")
        If .Range("H5") < 10 Then
            .Range("H6") = "ABC"
        End If
        For i = 1 To 11  '←【原因】対応するNext がない
        If .Range("A3") < 10 Then
            .Range("B3") = "NO牧場"
        End If
    End With    '←この「End With」が選択される
End Sub

このエラーは、コメントアウトしていたプログラムを解除した時や、不要なプログラムを一斉に削除した時に発生することが多いです。

関連リンク

ページの先頭へ