エクセルVBAで同じオブジェクトに対して複数の操作を行うとき、どのようにコードを書いていますか?
オブジェクト名を何度も繰り返し書いていませんか?
エクセルVBAでは、同じオブジェクトに対して処理を書くときは、Withステートメントを使えます。
Withステートメントは、指定オブジェクトに対する処理をまとめて書くことができるため、マクロのコードをスッキリすることさせる効果があります。
Withステートメントをつかうことで、マクロの可読性の向上につながります。プログラミングでは、可読性の向上(読みやすくなること)は、不具合の原因を見つけやすくなることや、機能のアップデートなどでの作業ミスを防止する効果があります。
また、特定のオブジェクトで複数のプロパティを設定するときなどの場面では、オブジェクトを繰り返し参照する必要がなくなることから、何度もオブジェクトを参照するケースと比較して処理が早くなるといったメリットもあります。
この記事では、エクセルVBAにおけるWithステートメントの基本的な使い方と使用時の注意事項について解説します。

WithステートメントはVBAのコードをスリム化できるものだよ。
VBAにおけるWithステートメントの概要とメリット
Withステートメントとは、同じオブジェクトに対して複数のプロパティやメソッドを指定するときに使う構文です。Withステートメントを使うと、オブジェクト名を一度だけ書いて、その後の操作をピリオド(.)でつなげることができます。Withステートメントの書き方は以下です。
With オブジェクト
.プロパティやメソッド
.プロパティやメソッド
End With
Withステートメントの最大メリットは、VBAのコードがスリムになり見やすくなることです。
オブジェクト名を繰り返し書く必要がなくなるので、全体のコードの量が減り、読みやすく、理解しやすくなります。また、オブジェクト名を書き間違える可能性が減ることもメリットと言えます。
さらにWithステートメントを使うと、オブジェクトの参照が高速になるというメリットもあります。これは、Withステートメント内ではオブジェクトの参照が一時的に蓄積されることで素早く取り出せるためです。
Withステートメントの使うイメージをあくまで個人的な感覚でお伝えするとすれば、主語や目的語をまとめるという表現になるかと思います。この言葉を念頭に置きながら記事を読み進めて頂いたあなたの理解につながればうれしいです。
●Withステートメントを使わない文章のイメージ
アーニャ・フォージャーの性別は 女のこ です。
アーニャ・フォージャーの学校は イーデン校 です。
アーニャ・フォージャーの能力は 他人の心をよむこと です。
ここでは「アーニャ・フォージャー」が主語となっていますが、3つの文章すべてにアーニャ・フォージャーが書かれていると冗長な表現となっています。
こちらの文章をWithステートメントをつかってスリムにしてみます。
●Withステートメントを使った文章のイメージ
アーニャ・フォージャーの
性別は 女のこ です。
学校は イーデン校 です。
能力は 他人の心をよむこと です。
「アーニャ・フォージャー」の部分をWithステートメントでまとめたことによって、それ以降の性別や学校、能力を説明する行では同じ言葉である「アーニャ・フォージャー」を省略することができます。
って、ただそれだけ?だと思われるかもしれませんが、ここで説明した例では「アーニャ・フォージャー」といった言葉が短いため、文字数もそれほど変わりませんが、これが「アーニャ・フォージャーの父親の同僚の赤メガネの男性」のように長いものであった場合「アーニャ・フォージャーの父親の同僚の赤メガネの男性」の文字列を繰り返し書かないだけでもプログラムのコードをすっきりさせることができます。

Withで囲った部分の主語をまとめるイメージだね。
それでは、次からはWithステートメントの書きかたを説明していきます。
VBAのWithステートメントの基本的な書き方
それでは、Withステートメントの基本的な書き方についてみていきましょう。
With object [ statements ] End With
Withステートメントをつかうためには、With オブジェクト(Object)からEnd Withまでの間に指定したオブジェクトに対するプロパティやメソッドを書きます。さきほど紹介した文章をVBAのコードのように書いてみます。
With アーニャ・フォージャー
性別は 女のこ です。
学校は イーデン校 です。
能力は 他人の心をよむこと です。
End With
Withステートメントは、繰り返しのオブジェクト参照をスリム化するために使います。
そのため、指定項目では オブジェクト(Object)の指定は必須となります。オブジェクト(Object)には、ブック(ファイル)、セル、ワークシート、グラフ、フォームなどのほかに、クラスなどの作成したオブジェクトの参照も可能です。
With ステートメントを使用することで、特定のオブジェクトやユーザー定義型に対してオブジェクト名の指定を繰り返し書く必要がなくなり、Withステートメントでまとめて実行できます。
具体的には、1 つのオブジェクトにあるそれぞれのプロパティを変更したいときなどに有効です。
指定項目 | 必須/省略可 | 説明 |
---|---|---|
object | 必須 | 参照したいオブジェクトやユーザー定義型の名前を指定します。 |
statements | 省略可 | object に対して実行する1つ以上のステートメントを指定します。 |

With object ~ End Withが間に書いたオブジェクトがまとめられるよ。
オンラインスクールで現役エンジニアのサポートがあるテックアカデミーがおすすめ。
スキマ時間に学べて仕事も保証。必ず副業、始められます。まずは無料でプログラミング体験
Withステートメントを使ったサンプルマクロ
Withステートメントの使ったサンプルマクロを紹介します。
ここでは、エクセルのシート1のA1セルからF6セルまでの編集をするマクロにおいて、ワークシートオブジェクトのシート1をWithステートメントで参照した場合と、Withステートメントなしで、繰り返しワークシートオブジェクトを参照するVBAコードで比較しています。(どちらも全く同じ処理をするマクロです)
Option Explicit
Sub withステートメント使用例1()
'Withステートメントでこのブック(ファイル)のワークシート1のオブジェクトを参照する
With ThisWorkbook.Worksheets(1)
'セルA1に"With"を入力する
.Range("A1").Value = "With"
'セルB2の背景色を3(赤色)にする
.Range("B2").Interior.ColorIndex = 3
'セルC3にC3セルのアドレスを入力する
.Range("C3").Value = .Range("C3").Address
'セルD4にセル(オブジェクト)数を入力する
.Range("D4") = .Range("D4").Count
'セルE5にE5セルの行数を入力する
.Range("E5").Value = .Range("E5").Row
'セルF6にF6セルの列数を入力する
.Range("F6").Value = .Range("F6").Column
End With
End Sub
ポイントは、Withステートメントをつかってシートオブジェクトのシート1を参照している点です。
これによって、シート内のセルをするときにシートオブジェクトを何度も書く必要がなくなりました。Withステートメントでオブジェクトを参照している行は、ピリオド(.)から書きはじめます。

Withで参照している部分は、ピリオドをつけることを忘れないようにね。
Option Explicit
Sub withステートメント使用しない()
'セルA1に"With"を入力する
ThisWorkbook.Worksheets(1).Range("A1").Value = "With"
'セルB2の背景色を3(赤色)にする
ThisWorkbook.Worksheets(1).Range("B2").Interior.ColorIndex = 3
'セルC3にC3セルのアドレスを入力する
ThisWorkbook.Worksheets(1).Range("C3").Value = ThisWorkbook.Worksheets(1).Range("C3").Address
'セルD4にセル(オブジェクト)数を入力する
ThisWorkbook.Worksheets(1).Range("D4") = ThisWorkbook.Worksheets(1).Range("D4").Count
'セルE5にE5セルの行数を入力する
ThisWorkbook.Worksheets(1).Range("E5").Value = ThisWorkbook.Worksheets(1).Range("E5").Row
'セルF6にF6セルの列数を入力する
ThisWorkbook.Worksheets(1).Range("F6").Value = ThisWorkbook.Worksheets(1).Range("F6").Column
End Sub
Withステートメントをつかったサンプルコードと比較すると、オブジェクトを参照するためのコードの分だけ長くなっています。
このサンプルマクロの規模であっても、かなりの文字数を減らせることができていますので、プログラムの規模が大きくなればなるほど文字数の削減の効果は大きくなっていくと言えます。
Withでオブジェクトのプロパティやメソッドを連続して指定する
Withステートメントでは、プロパティやメソッドを連続して指定ができます。
さきほどのサンプルコードでは、Withステートメントでシート1を参照しました。これでシート1のプロパティやメソッドについてコードの冒頭にピリオドをつけることで扱えるようになりました。
今度は、WithステートメントでA1セルを参照してみます。
Option Explicit
Sub withステートメント使用例3()
'Withステートメントでこのブック(ファイル)のワークシートのA1セルのオブジェクトを参照する
With ThisWorkbook.Worksheets(1).Range("A1")
'ピリオドを書くだけでシート1のA1セルに対するメソッドやプロパティに対して指定ができる
.Value = "A1セル" 'Valueプロパティで文字列を入力する
.Interior.ColorIndex = 3 'Interiorプロパティ背景色を赤色にする
.Copy 'Copyメソッドで文字列をコピーする
.Offset(0, 1).PasteSpecial Paste:=xlPasteValues 'PasteSpecialメソッドとOffsetプロパティでA1セルの右隣のセルに貼り付ける
End With
Application.CutCopyMode = False'コピーモードを解除する
End Sub
A1セルをWithステートメントで参照して、メソッドやプロパティを以下のように指定しています。
- Valueプロパティ
A1セルに文字列”A1セル”を入力する指定をしています。 - Interiorプロパティ
A1セルの背景色を赤色にする指定をしています。 - Copyメソッド
A1セルをコピーする指定をしています。 - PasteSpecialメソッド
A1セルでコピーした値をB2セルに貼り付ける処理を指定しています。

Range(“A1”)セルのメソッドやプロパティを連続で指定して処理を実行できるね。


Withステートメントで参照したオブジェクトのメソッドやプロパティをまとめて処理できるね。
Withステートメントのネストや終了方法について
Withステートメントは、別のWithステートメントのなかに配置することで入れ子(ネスト)にできます。
これは、オブジェクトの中にさらにオブジェクトがある場合に便利です。例えば、以下のコードでは、Rangeオブジェクトの中のFontオブジェクトに対してプロパティを指定しています。
Option Explicit
Sub withステートメント使用例4()
'Withステートメントでこのブック(ファイル)のワークシート1オブジェクトを参照する
With ThisWorkbook.Worksheets(1)
'Withステートメントを入れ子にしてA1セルオブジェクトを参照する
With .Range("A1")
.Value = "Withステートメントの(入れ子)ネスト" 'A1セルに文字を入力する
'さらにWithステートメントを入れ子にしてFontオブジェクトを参照する
With .Range("A1").Font
.Bold = True'文字の太字にする
.Color = vbYellow'文字色を黄色にする
.Size = 12'文字の大きさを12にする
End With 'Fontオブジェクトの参照を終了
End With 'A1セルオブジェクトの参照を終了
End With 'ワークシート1オブジェクトの参照を終了
上記のように、Withステートメントを入れ子(ネスト)にする場合、外側のWithステートメントのなかに新たなWith~End Withを書きます。
サンプルコードでは、ワークシート1を参照するためのWithステートメントのなかに、A1セルを参照したWithステートメントがあり、さらにそのなかにFontオブジェクトを参照して処理を実行しています。
Withステートメントで指定したオブジェクトの参照を終了するタイミングは、End Withの実行までとなりますので、参照の順番とは逆にフォントオブジェクトの参照が終了、つぎにA1セルの参照が終了、さいごにシート1の参照が終了といったながれです。


ネストすることでオブジェクトの中のオブジェクトを参照することができるね。
WithステートメントでApplicationオブジェクトのプロパティを設定する
Withステートメントは、Applicationオブジェクトを参照することもできます。
ApplicationオブジェクトとはExcelアプリケーションのことで、このオブジェクトは画面の更新、アラート通知、数式の計算方法の切り替えなど、マクロの動作を早くするための設定をもっているため、大規模なマクロを動作する直前や直後にまとめて設定すると良いでしょう。
Option Explicit
Sub 処理前設定()
With Application 'アプリケーションオブジェクトを参照(Excel)
.ScreenUpdating = False '画面更新オフ
.DisplayAlerts = False 'エラー通知オフ
.Calculation = xlManual '自動計算オフ
End With
End Sub
06行目
画面の更新を停止します。
Falseにすることで編集した画面が描画されなくなります。大量の値を入力する場合など大きな処理で遅くなりそうな場面では、事前に設定しておくとマクロでの処理が速くなります。
07行目
画面上に出す通知を停止します。
通知には既にファイルが開かれている場面で出るものや、編集後のファイルを終了するときの保存を促すものなどがありますが、マクロの処理が停止してしまうことを予防するために一時的に通知を出さないようにします。
08行目
シート上にある数式の計算を手動に変更します。
シート上に書きこまれた数式の計算を手動(マニュアル)に変更します。自動のままだと常に計算される処理が実行されて余分な処理につかうリソースを省くことで処理が速くなります。
Option Explicit
Sub 処理後設定()
With Application 'アプリケーションオブジェクトを参照(Excel)
.ScreenUpdating = True '画面更新オン
.DisplayAlerts = True 'エラー通知オン
.Calculation = xlAutomatic '自動計算オン
End With
End Sub
06行目
画面の更新を再開します。
Trueにすることで編集した画面が描画されるようになります。ワークシートへの入力を処理を実行したあとに画面上に反映されるようにします。
07行目
画面上に出す通知を再開します。
Trueにするとエラー通知などが表示されるようになります。Falseのままだと本来必要とする通知まで出さないようになってしまっているので停止と再開はセットで実行するように注意が必要です。
08行目
シート上にある数式の計算を自動に変更します。
手動のままだとシートの上の関数などが計算されなくなるので、使用者が意図した結果を得られなくなったなどのトラブルを回避する上で元に戻すようにします。

Callで呼び出せるように、メインとは別のプロシージャで作っておくと便利だね。
Withステートメントでクラスオブジェクトのプロパティを設定する
Withステートメントは参照するオブジェクトを指定できることは解説しました。オブジェクトはブックやシート、セルなどがありますが、他にもクラスオブジェクトの参照ができます。
次に紹介するサンプルコードは、氏名・身長・体重を入力することで、BMIを計算し、計算結果のBMIによる判定をセルに出力するサンプルマクロです。ここでは、Withステートメントを使ってクラス内で宣言した変数に値を代入する処理をおこなっています。

Withはオブジェクトを参照できるなら、クラスもあつかえるってことだね。
まずは、出力するシートは以下のとおり。

このサンプルエクセルシートに名前・身長・体重を入力して、BMIと判定結果を出力します。
このマクロのコードは以下のとおりです。
Option Explicit
Public 氏名 As String
Public 身長 As Double
Public 身長M As Double
Public 体重 As Double
Public BMI As Double
氏名・身長・体重・BMIと、身長をメートル表示にした値を代入する変数をパブリック(Public)で宣言しています。
パブリック(Public)で宣言する理由は、標準モジュールからクラス内の変数に値を代入する処理ができるようにするためです。なお、ここではクラスモジュールのオブジェクト名は”身体情報“としています。
続いて、標準モジュールに書いたサンプルコードです。
Option Explicit
Sub 身体情報を入力する()
Dim 情報入力 As 身体情報
Set 情報入力 = New 身体情報
'Withステートメントでクラスオブジェクト(身体情報)を参照する
With 情報入力
'クラス変数に数値を代入する処理
.氏名 = Application.InputBox("氏名を入力してください", "情報入力", Type:=2)
.身長 = Application.InputBox("身長をcmで入力してください", "情報入力", Type:=1)
.身長M = Application.WorksheetFunction.RoundUp(.身長 / 100, 1)
.体重 = Application.InputBox("体重をkgで入力してください", "情報入力", Type:=1)
.BMI = .体重 / (.身長M * .身長M)
End With 'クラスオブジェクト(身体情報)の参照を終了する
'Withステートメントでシート名がSheet5を参照する
With ThisWorkbook.Worksheets("Sheet5")
'2行目から開始する
Dim Row As Long: Row = 2
'空白行でないなら、ひとつ下の行へ
Do Until .Cells(Row, 1) = ""
Row = Row + 1
Loop
'情報をセルに出力する
.Cells(Row, 1) = 情報入力.氏名
.Cells(Row, 2) = 情報入力.身長
.Cells(Row, 3) = 情報入力.体重
.Cells(Row, 4) = 情報入力.BMI
'BMIから判定結果を出力する
If .Cells(Row, 4) >= 5.5 And .Cells(Row, 4) <= 9.9 Then
.Cells(Row, 5) = "低い"
ElseIf .Cells(Row, 4) >= 10 And .Cells(Row, 4) <= 19.9 Then
.Cells(Row, 5) = "標準"
ElseIf .Cells(Row, 4) >= 20 And .Cells(Row, 4) <= 24.9 Then
.Cells(Row, 5) = "やや高い"
ElseIf .Cells(Row, 4) >= 25 Then
.Cells(Row, 5) = "高い"
End If
End With 'Withステートメントでシート名がSheet5の参照を終了する
End Sub
05行目と06行目
クラスオブジェクトを変数として宣言しています。変数名は情報入力となります。
09行目
Withステートメントを使って、クラスオブジェクトである身体情報クラスを参照しています。
11行目・13行目・15行目・17行目・19行目
Application.InputBoxを使ってユーザーから入力された値を受け取り、それぞれの変数に代入しています。
23行目
Withステートメントを使って、シート5を参照しています。
25行目
入力する行を代入するための変数Rowを宣言します。
28行目から30行目
シート5のA列が空白になるまで行数を足していき、A列の空白行になるまで変数Rowに行数を代入します。
33行目から36行目
シート5のA列にクラス情報入力の氏名を入力します。
シート5のB列にクラス情報入力の身長を入力します。
シート5のC列にクラス情報入力の体重を入力します。
シート5のD列にクラス情報入力のBMIを入力します。
39行目、42行目、45行目、48行目
IFステートメントによる条件分岐処理によって、シート5のD列(BMI)の数値で低い、標準、やや高い、高いの判定結果をE列に入力します。

Withステートメントでクラスオブジェクトを参照して、それぞれの変数に値を代入することとシートへの出力ができました。
なぜ、膨大な事務作業でも定時で退社できるのか。
実務をプロから学べる「ユースフル」の動画は永年見放題。Q&A機能で分からないを放置しないから安心。
詳しくは以下のリンクをクリック
VBAにおけるWithステートメントを使うときの注意点
Withステートメントを入れ子にするときは、以下の点に注意してください。
Withステートメントは必ずEnd Withステートメントで終了しなければなりません。
入れ子にした場合は、内側から順にEnd Withステートメントを記述します。
入れ子にしたWithステートメント内で、ピリオドから始まったコードは、直前(そのステートメントが含まれる最も内側)のWithステートメントで指定したオブジェクトのプロパティやメソッドとみなされます。
入れ子にしたWithステートメント内で、外側のWithステートメントで指定したオブジェクトのプロパティやメソッドにアクセスする場合は、完全修飾オブジェクト参照(すべての親オブジェクト名を含む)を指定する必要があります。
Withステートメントを入れ子にすると、コードの可読性が悪くなる可能性があるため、Withステートメントを入れ子(ネスト)にする場合は、変数などでオブジェクトを参照する方法などと比較してコードの書きかたを検討することをおすすめします。
例えば、以下のサンプルコードでは、シート1のA1セルからE4セルまでのセル範囲をWithステートメントで参照しています。
Option Explicit
Sub withステートメント使用例6()
'Withステートメントでこのブック(ファイル)のワークシート1オブジェクトを参照する
With ThisWorkbook.Worksheets(1).Range("A1:E4")
.Value = 10 '範囲内のセルに10を入力する
.Font.Size = 11 '範囲内のセルのフォントサイズを11にする
.Font.Color = 0 '範囲内のセルのフォントカラーをクリアにする
.Font.Bold = False '範囲内のセルの太字を通常に戻す
End With 'ワークシート1オブジェクトの参照を終了
End Sub
このVBAコードを、オブジェクト変数をつかった参照に書きかえると以下となります。
Option Explicit
Sub 変数でセル範囲を参照したコード()
'オブジェクト変数にセル範囲("A1:E4")を代入する
Dim セル範囲 As Range: Set セル範囲 = ThisWorkbook.Worksheets(1).Range("A1:E4")
セル範囲.Value = 10 '範囲内のセルに10を入力する
セル範囲.Font.Size = 11 '範囲内のセルのフォントサイズを11にする
セル範囲.Font.Color = 0 '範囲内のセルのフォントカラーをクリアにする
セル範囲.Font.Bold = False '範囲内のセルを太字を戻す
End Sub
06行目
セル範囲を参照する変数としてセル範囲を宣言して、ワークシート1のA1セルからE4セル範囲を参照します。
08行目
セル範囲であるA1セルからE4セルに10を入力します。
09行目
セル範囲であるA1セルからE4セルのフォントサイズを11に変更します。
10行目
セル範囲であるA1セルからE4セルのフォントカラーをクリアします。
11行目
セル範囲であるA1セルからE4セルの太字を戻します。

どちらも同じ処理を実行するよ。
変数のとり扱い方については以下の記事で解説しています。変数の基本的な使い方について知りたい人は以下の記事もあわせてご覧ください。
Withステートメント内で変数や関数を使うときの注意点
Withステートメント内では、ピリオドから始まるステートメントは、Withで指定したオブジェクトのプロパティやメソッドとみなされます。しかし、変数や関数を使う場合は、ピリオドをつけないようにしてください。ピリオドをつけると、変数や関数がオブジェクトのメンバーとして解釈されてしまい、エラーになる可能性があります。
以下のサンプルコードでは、変数iや関数MsgBoxをWithステートメントの中で使っていますが、ピリオドをつけるとエラーが発生します。
Option Explicit
Sub withステートメント使用例7()
Dim i As Long
'Withステートメントでワークシート4のA1セルからE4セルまでの範囲を参照する
With ThisWorkbook.Worksheets(4).Range("A1:E4")
For i = 1 To .Count 'Withステートメントで参照した範囲内のセルの個数分(20)繰り返す
MsgBox .Cells(i).Value'メッセージボックスで各セルに入力された値を表示する
Next i
End With 'ワークシート4オブジェクトの参照を終了
End Sub
08行目
Withステートメントでワークシート4のA1セルからE4セル範囲を参照します。
10行目
ForNext文をつかって繰り返し回数を指定していますが、.Conut ではWithステートメントで参照しているセル範囲のセルの数という意味です。参照しているA1からE4までのセルの個数は20であることから、変数iが1から20の間は処理を繰り返します。
実行結果としては、A1セルからE4セルに入力された値を順番にメッセージボックスに表示します。

Withステートメント内で変数や関数を使うときは、ピリオドをつけないように。
繰り返し文については、以下の記事でくわしく解説しています。For文以外の繰り返しの書きかたについても紹介していますので、あわせて参考にしてください。
Withで参照しているオブジェクトの位置や状態は変更しない
Withステートメントで参照しているオブジェクトの位置や状態が変わってしまうコードは書かないようにしましょう。なぜなら、あとからコード読むときに読み取れなくなってしまうからです。
では、位置や状態が変わってしまうケースを以下に紹介します。
サンプルのエクセルのシート1のA1 セルにA2セルにはそれぞれ文字が入力されています。

上記のエクセルのA1セルをWithステートメントで参照したサンプルコード
Option Explicit
Sub withステートメント参照している位置や状態がかわるコード()
'Withステートメントでこのブック(ファイル)のワークシート1のA1セルを参照する
With ThisWorkbook.Worksheets("sheet1").Range("A1")
Debug.Print .Value 'A1セルの内容をイミディエイトウィンドウに出力する[1]
'シート1の1行目に行を挿入する
ThisWorkbook.Worksheets("sheet1").Rows(1).Insert
Debug.Print .Value 'A1セルの内容をイミディエイトウィンドウに出力する[2]
'シート1の1列目に列を挿入する
ThisWorkbook.Worksheets("sheet1").Columns(1).Insert
Debug.Print .Value 'A1セルの内容をイミディエイトウィンドウに出力する[3]
'シート1のA1セルの入力された文字を削除する
ThisWorkbook.Worksheets("sheet1").Range("A1").ClearContents
Debug.Print .Value 'A1セルの内容をイミディエイトウィンドウに出力する[4]
End With 'ワークシート1オブジェクトの参照を終了
End Sub
06行目
Withステートメントでワークシート1のA1セルを参照します。
08行目
Debug.Print .Valueの”.Value”はA1セルに入力されている値を返します。ここではデバッグプリントを利用しているため結果をイミディエイトウィンドウに表示します。
11行目
Insert メソッドで行(Row)を挿入します。この処理が実行されるとA1セルがA2セルになります。
13行目
Debug.Print .Valueの”.Value”は参照当初のA1セルに入力されている「これはA1セルです。」を返します。11行目で行を挿入したことで参照しているセルがズレてしまっていますので、この時点のシート上のA1セルは空白となりますが結果としては参照した時点のものです。
16行目
Insert メソッドで行(Column)を挿入します。この処理が実行されると最初A1セルであったものがB2セルになります。(11行目でA2セルとなっていることから、行も挿入されています。)
18行目
Debug.Print .Valueの”.Value”は参照当初のA1セルに入力されている「これはA1セルです。」を返します。11行目と16行目で行と列を挿入したことで参照しているセルがズレてしまっていますので、この時点のシート上のA1セルは空白となりますが結果としては参照した時点のものです。
21行目
ClearContentsメソッドでA1セルに入力されている値の削除をします。11行目や16行目で行や列がズレているため、最初から空白ですが、Withステートメントで参照しているセルの値が消されるのかを検証するために実行しています。
23行目
Debug.Print .Valueの”.Value”は参照当初のA1セルに入力されている「これはA1セルです。」を返します。11行目と16行目、21行目で行、列の挿入と値の削除を処理したことで、この時点のシート上のA1セルは空白となりますが結果としては参照した時点のものです。
これはA1セルです。
これはA1セルです。
これはA1セルです。
Withステートメントで参照しているオブジェクトはA1セルですが、13行目の出力時は行が挿入されて元はA1セルであったセルはA2セルになっています。さらに18行目の出力時は列も挿入されているためB2セルに変わったとしても、結果は変わらず「これはA1セルです。」を表示します。
この結果から、Withステートメントの参照は、参照を開始した時点でのA1セルを参照していると言えます。その証拠に、このプロシージャをもう一度実行した場合は、新たなA1セルを参照しており、1度目のマクロの実行で行や列が追加されておりA1セルには何も入力されていないため、イミディエイトウィンドウに空白が返ってきます。
Withで参照しているオブジェクトの位置や状態を変更することはなるべく控える
理由としては、コードからどこを参照しているのかを読みとることが難しくなるためです。
プログラムのコードは自分以外の人がコードを読むことや、コードを作成した時期から相当な日数が経過したあとであっても、不具合が見つかったときや、機能の拡張で過去に書いたコードを改めて理解する必要が出てくることが一般的です。そのため、可読性が悪くなることは改めてコードを理解するときのハードルが高くなるからです。
Withステートメントを使う効果がそもそも可読性を上げる、つまり読みやすくすることであるとすれば、Withステートメントで参照している位置や状態が変わってしまうことは、本来の目的とは裏腹な結果になってしまいます。
これらを考えた場合、Withステートメントで参照しているオブジェクトをWithのなかで参照先を移動、状態を変更することはできるだけ避けたほうが良いでしょう。
Withステートメントを使いすぎるとコードが読みにくくなる可能性
Withステートメントを使うと、コード量がスリムになり、同じオブジェクトを記述する必要もなくなるためコードの入力も楽になります。しかし、Withステートメントを使いすぎることで、かえってコードが読みにくくなる場合があります。
特に、以下のような場合は注意が必要です 。
- Withステートメントを入れ子(ネスト)にする場合
- Withステートメント内で複数の異なるオブジェクトを操作する場合
- Withステートメント内でオブジェクトの位置や状態を変更するようなコードを書く場合
これらの場合は、Withステートメントを多用せずに、それぞれのオブジェクト名を明示的に書き込んだ方が読み取りやすくなります。またWithステートメント以外の参照方法として、指定のオブジェクトを変数に代入する書きかたを選択した方が可読性や安全性は良くなります。
VBAのWithステートメントに関する記事まとめ
本記事では、エクセルVBAにおけるWithステートメントで特徴と使い方について解説しました。Withステートメントをうまく使うことでVBAのコードを書くボリュームを減らすことができ、可読性が良くなる効果が期待できます。
また、WithステートメントはWithステートメント中にさらにWithステートメントを書きこむことで入れ子(ネスト)にできますが、多用することで逆効果として可読性が下がってしまう点には注意が必要です。
それでは、本記事のさいごにWithステートメントについてまとめていきます。
Withステートメントの利用方法と注意点
Withステートメントは、VBAでオブジェクトのプロパティやメソッドを連続して指定するときに便利な書きかたであり、使い方次第でコードの記述量を大きく減らすことができます。しかし、Withステートメントを扱うときには、いくつかの注意事項を意識しておく必要があります。
以下にWithステートメントの利用方法と注意点をまとめます。
- Withステートメントを使うと、オブジェクト名を省略してプロパティやメソッドにアクセスできる。
- Withステートメントは必ずEnd Withステートメントで終了する。
- Withステートメントは入れ子にできるが、乱用すると可読性が悪くなる可能性がある。
- Withステートメント内では、Withで指定したオブジェクトは変更できない。
- Withステートメント内では、Withで指定したオブジェクトの位置や状態を変更するようなコードは書かない。

どのオブジェクトを参照しているかが分かりにくくなってしまうのなら使用は控えようね。
以上、エクセルVBAでWithステートメントの利用方法と注意点の解説をしました。プログラミングでは、大規模で複雑な処理であってもシンプルで読みやすいコードで実装できることが、スキルアップにつながります。
今回紹介したWithステートメントも、使い方次第ではコード量を減らす効果はありますので、効率よくコードが書けるようになります。ただし、適切な使用方法での運用でなければ、コードを書く文字量は減らせても、プログラム全体の可読性が低下し、何をしているのかわかりにくいコードとなってしまうことに注意が必要です。
Withステートメントを適切に使うことが、マクロ開発者としてのスキルが向上するものだと覚えておくと良いでしょう。
今回はここまで。
![]() |
![]() |
コダマのもりブログはにほんブログ村に登録しています。
ブログの記事が役に立ったと感じて頂けたら、フォローお願いいたします。
コメント