なぜiは変数の値が保持されるのに、wは保持されないのでしょうか?

このQ&Aのポイント
  • VBAのFor Eachステートメントを使用してワークシートのオブジェクトを反復処理する中で、オブジェクト変数wの値が保持されない理由について質問です。
  • ワークシートのオブジェクト変数wはFor Eachステートメントのスコープ内でしか有効ではなく、ステートメントを抜けると値が破棄されるため、後続のMsgBoxでエラーが発生します。
  • VBAのヘルプドキュメントにはこの動作について明確に記載されていないため、混乱することがありますが、オブジェクト変数の有効範囲はスコープ内に限定されるので注意が必要です。
回答を見る
  • ベストアンサー

なぜiは変数の値が保持されるのに、wは保持されない

なぜiは変数の値が保持されるのに、wは保持されないのでしょうか? Sub test() Dim w As Worksheet Dim i As Long i = 1 For Each w In Worksheets i = i + 1 Next MsgBox i MsgBox w.Name End Sub -------------------------------------- を行うと、 MsgBox i は表示されるのに、 MsgBox w.Name は、 「オブジェクト変数または With ブロック変数が設定されていません。」になります。 wはオブジェクト変数だから、 For Each ステートメントを抜けると値が破棄されてしまうのでしょうか? でもvbaのヘルプの 「For Each...Next ステートメントの使い方」 を見ても 「ステートメントを抜けるとオブジェクト変数なら値が破棄されます」 と記載されていません。

質問者が選んだベストアンサー

  • ベストアンサー
  • keithin
  • ベストアンサー率66% (5278/7940)
回答No.2

ご質問のFor Each Nextの前に、ひとつ参考として sub test dim i for i = 1 to 5 next i msgbox i end sub と実行してみます。結果は(5じゃなく)「6」が現れます。 For To Nextフロー制御のルールは、Next行でエレメントがToを「超えた」時点で次行に制御を流します。 そこで、ご質問のFor Each Nextのヘルプを再度確認すると 「引数 group の中にもう要素がなくなったとき、ループは終了し、Next ステートメントの次のステートメントに実行が移ります」 のように解説されています。 つまりFor Each Nextでループを終了した時点で、変数Wは「もう何も入っていない」状態になってループを抜けています。(ローカルウィンドウで変数の中身を確認しながら追跡してみると、Nothingになってループを抜けている様子を見ることができます) このため、ご質問の状況が発生します。 なお、ループの途中でExit Forによって(=Nextせずに)ループを抜けた場合などは、その時点のwの中身が保持されたままになります。

KOVI65483
質問者

お礼

本当だ。 サンプルコードを実行してみたら、6になりました。 For Each...Nextで、ステートメントを無事終了して抜けると、値が破棄されて、 Exit Forで途中離脱すると、値が保持されたままなのですか。 Sub test() Dim w As Worksheet For Each w In Worksheets Exit For Next MsgBox w.Name End Sub をやってみたら、エラーにならず、値が保持されてました。ありがとうございました。

その他の回答 (1)

  • YUI_AI
  • ベストアンサー率45% (303/661)
回答No.1

下記URL等を参考にされると良いと思います。 http://msdn.microsoft.com/ja-jp/library/vstudio/5ebk1751.aspx 「element のスコープはループの本体になります」等の記述から判ると思いますが、wの保持される期間はルール終了までとなります。

KOVI65483
質問者

お礼

「element のスコープはループの本体になります」 =「wの保持される期間はルール終了まで」と読み替えればいいのですか。 URLよく読んでみます。ありがとうございました。

関連するQ&A

  • 変数の値を破棄する方法

    データ型で宣言した場合、 変数の値はどうやって破棄すればいいのでしょうか? 例えば、標準モジュールに Option Explicit Dim s As String Dim w As Worksheet Sub test() Set w = ActiveSheet s = "sss" MsgBox w.Name MsgBox s Set w = Nothing s = Nothing End Sub とした場合、 s = Nothingがエラーになります。 オブジェクト型で宣言したら、 Set ●= Nothing で破棄しますが、 データ型で宣言した場合の正しい破棄の仕方を教えてください。 今回の例は、モジュールレベルのdimステートメント で宣言しているため、プロシージャーが終わっても 値を保持しています。

  • 変数iもjも同じく値を保持できるからどちらを使って

    このサンプルコードは、 変数iもjも同じく値を保持できるから、test1を使ってもtest2を使っても一緒なのでしょうか? Option Explicit Dim i As Integer Sub test1() Static j As Integer j = j + 1 Debug.Print j End Sub Sub test2() i = i + 1 Debug.Print i End Sub ご回答よろしくお願いします。

  • プロシージャーの外で宣言した変数の値の破棄の仕

    プロシージャーの外で宣言した変数の値の破棄の仕方について教えてください。 ++++++++++++++++++ Dim i As Long Sub test() i = i + 10 MsgBox i End Sub ++++++++++++++++++ を実行すると、どんどん値が増えていきますが、 回避するには、 ++++++++++++++++++ Dim i As Long Sub test() i = i + 10 MsgBox i i = 0 End Sub ++++++++++++++++++ とするしかないのでしょうか? ++++++++++++++++++ Dim i As Long Sub test() i = i + 10 MsgBox i Set i = Nothing End Sub ++++++++++++++++++ としたら、エラーになりました。

  • iと言う変数の値が1から10の間にないならば

    「iと言う変数の値が1から10の間にないならば」、としたいのですが どのようなコードを書けばいいのでしょうか? Sub test1() Dim i As Integer i = 11 If 1 < i < 10 Then MsgBox i & "は1から10の間にはありません" End If End Sub だと、メッセージが表示されてしまいます。

  • 変数の値について

    変数の値について教えてください。 VB2010 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim A As Single A = 2.0 MsgBox(A) End Sub 上記のプロシジャを実行するとメッセージボックスに2と表示され 2.0と表示しません。 2.0と表示させるには、どのようにすればよいなでしょうか。

  • 変数を保持して呼び出す方法

    変数を保持する方法 2022/02/10 15:36 変数が受け継がれない 2022/02/10 15:24 sub A(),subB()と複数のプロシージャをModule1に配置。 Sub Aでターゲットファイル(T_File)を指定して Sub Bで同じT_Fileを呼び出そうとしたのですが Subの前に配列は宣言しているのでPrivateのハズなのに 変数が受け継がれません T_Fileが”””となります。 多分、Sub A()が終了した時点で一度マクロが終了して 新たにSub B()を呼び出すので上手く変数が受け継がれないのだと思います。 何処かのシートのセルに変数を保持して呼び出す方法が考えられますが そのほかに変数を保持する方法は有りませんか? (できればシートのセルに保持しない方法があれば教えて下さい。) 以下コード(コードが長いので必要と思われる所だけを記載しています。) ’------------------------------------ Option Explicit Dim dlg As FileDialog Dim T_File As String Sub A() Set dlg = Application.FileDialog(msoFileDialogFilePicker) If dlg.Show = False Then MsgBox "処理はキャンセルされました。" Exit Sub Else End If '指定テキストファイル読み込み T_File = dlg.SelectedItems(1) '(途中のコード省略) If rc = vbNo Then MsgBox "処理を中止します。", vbCritical Exit Sub Else MsgBox "処理が終了しました。", vbInformation End If End Sub Sub B() ’T_File = dlg.SelectedItems(1) Folder_Name = CreateObject("Scripting.FileSystemObject").GetParentFolderName(T_File) End Sub

  • セルに対してFor Each~In~Nextを使う

    セルに対してFor Each~In~Nextを使う事は出来ない? シートやブックに対してループする時は Sub aaa() Dim w As Worksheet For Each w In Worksheets MsgBox w.Name Next End Sub 等を使いますが、 A1に「あ」 A2に「い」 A3に「う」 が入っている場合、 Sub bbb() Dim i As Long For i = 1 To Range("a65536").End(xlUp).Row MsgBox Cells(i, 1) Next End Sub で、全ての値を取得できますが、 For~to~nextではなく セルに対してFor Each~In~Nextを使う方法があれば教えてください。 上記のように Dim w As Worksheetは宣言できますが Dim c As Workcellとはできませんでした。 なぜわざわざFor~to~nextでできる事をFor Each~In~Nextでやりたいかと言うと、 シートやブックはFor~to~nextでできるのに、セルはFor~to~nextができない理由を知りたいからです。 ご回答よろしくお願いします。

  • 変数が増えてしまうのはなぜだか教えてください。

    こんにちは、マクロ初心者ではないつもりですが、基本ができていないのか、以下のSubで、変数の値が増えてしまいます。i = 3のままだと思っていたのですが、シートが移動するにつれてiの値が増えてしまうのは何故でしょうか。教えてください。 Sub tes() Dim i As Integer Dim ws As Worksheet i = 3 Debug.Print i For Each ws In Worksheets ws.Select For i = 1 To i Debug.Print i Cells(i, i) = i Next Next End Sub 新規のブックに書きました。Sheetは1~3です。

  • サブフォームに変数を代入し、RecordSourceの値を取得したい

    サブフォームに変数を代入し、RecordSourceの値を取得したいのですがうまくいきません。 Sub test1() Dim サブフォーム As String Dim フォーム As String フォーム= "土台" サブフォーム = "フォーム1" MsgBox Form_フォーム1.RecordSource End Sub ******************************************************************* Sub test2() Dim サブフォーム As String Dim フォーム As String フォーム= "土台" サブフォーム = "フォーム1" MsgBox Form_フォーム1.RecordSource MsgBox Forms(フォーム).Controls(サブフォーム).RecordSource End Sub オブジェクトは、このプロパティまたはメソッドをサポートしていません。(Error 438) ******************************************************************* Sub test3() Dim サブフォーム As String Dim フォーム As String フォーム = "土台" サブフォーム = "フォーム1" MsgBox Forms(サブフォーム).RecordSource End Sub 実行時エラー'2450' マクロの式またはVisual Basic コート゛で参照されている 'フォーム名'フォームが見つかりません。 ******************************************************************* test1~3のうち test1のみはうまくいくのですが 変数を代入したいです。 ヘルフ゜のには Forms![受注]![受注サブフォーム].Formとなってますが これじゃ変数を代入できないですよね。 どうすればサブフォームに変数を代入しつつ、RecordSourceの値を取得できるのでしょうか? よろしくお願いします。

  • 変数が勝手に変わります

    Dim i As Integer:Dim i2 As Integer:Dim card(5) As Integer:Dim expectPoint0card(1) As Integer '0枚のカードを交換する場合のすべての選択肢の期待値 Dim expectPoint1card(5) As Integer Sub porkerGame() card(1) = 1: card(2) = 2: card(3) = 3: card(4) = 4: card(5) = 5 getExpectPoint1card expectPoint1card End Sub Sub getExpectPoint1card(expectPoint1card() As Integer) Dim tesu1 As Integer:Dim sum1 As Integer For i = 1 To 5 getTesuSum1 i, tesu1, sum1 expectPoint1card(i) = sum1 / tesu1 Next i End Sub Sub getTesuSum1(rowNumber As Integer, tesu1 As Integer, sum1 As Integer) Dim card2(5) As Integer:tesu1 = 0:sum1 = 0 MsgBox rowNumber copy card, card2, 5 MsgBox rowNumber For i = 4 To 55 MsgBox rowNumber card2(rowNumber) = i addTesuSum card2, tesu1, sum1 Next i End Sub Sub copy(row() As Integer, row2() As Integer, i2 As Integer) For i = 1 To i2 row2(i) = row(i) Next i End Sub 上記のプログラムで、ウィンドウに1,6,4,5,6と表示され、その次には、エラーが表示します。僕は、ウィンドウに表示される変数RowNumberの値がしばらくの間は1のままであるようにプログラムを書いたつもりなのですが、変数rowNumberの値が変わるのは、どうしてでしょうか?教えてください。お願いします。

専門家に質問してみよう