Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(指定なし : 指定なし)
For Nextの初歩的であろう質問です
投稿日時: 18/10/07 14:52:39
投稿者: hisayanxp

VBSで恐縮ですが、素朴な質問です。
 
Dim i
For i = 1 To 10
    i = i + 1
Next
MsgBox i
 
この結果は 11 になりました。
これは以下のように考えました。
 
i = i + 1 → 2  ・・・1回目
i = i + 1 → 3  ・・・2回目
i = i + 1 → 4  ・・・3回目
i = i + 1 → 5  ・・・4回目
i = i + 1 → 6  ・・・5回目
i = i + 1 → 7  ・・・6回目
i = i + 1 → 8  ・・・7回目
i = i + 1 → 9  ・・・8回目
i = i + 1 → 10  ・・・9回目
i = i + 1 → 11  ・・・10回目
 
ところが以下の場合、てっきり5回目の6が表示されると思ったら、7が表示されてしまいます。
 
Dim i
For i = 1 To 5
    i = i + 1
Next
MsgBox i
 
素朴な疑問でお恥ずかしいのですが、どなたか分かりやすくお教えいただけないでしょうか。
よろしくお願いします。

回答
投稿日時: 18/10/07 16:19:43
投稿者: WinArrow
投稿者のウェブサイトに移動

>以下のように考えました
提示した考え方のようには、動作しません。
 
通常は、ループ制御用のカウンタの値を
ループの中では変更しません。
(特異の例としては、あるかもしれませんが)
次のように
ループの中で、Debug.Printを入れて「i」の値を表示してみるとわかります。

Dim i As Long
For i = 1 To 10
    Debug.Print i
    i = i + 1
Next
Debug.Print i
 
 
 

回答
投稿日時: 18/10/07 16:31:13
投稿者: WinArrow
投稿者のウェブサイトに移動

変数「i」の値:For 命令で、VBにカウントアップを依頼しています。
それを、依頼者側で勝手に値を変更したら、まずいよね?
 
仮に
i = i -1
としたら、無限ループになってしまいますよ!

回答
投稿日時: 18/10/07 16:33:00
投稿者: チオチモリン

ループの中でループカウンタである変数の値を変化させていますから
一行ずつ見ていけば ↓ のようになります。
 
                     iの変化
For i = 1 To 10 0 → 1
    i = i + 1 1 → 2
Next 2 → 3
For i = 1 To 10
    i = i + 1 3 → 4
Next 4 → 5
For i = 1 To 10
    i = i + 1 5 → 6
Next 6 → 7
For i = 1 To 10
    i = i + 1 7 → 8
Next 8 → 9
For i = 1 To 10
    i = i + 1 9 → 10
Next 10 → 11 ◆
 
 
For i = 1 To 5 0 → 1
    i = i + 1 1 → 2
Next 2 → 3
For i = 1 To 5
    i = i + 1 3 → 4
Next 4 → 5
For i = 1 To 5
    i = i + 1 5 → 6
Next 6 → 7 ◆
 
ループの変数の注意事項としては、実数を使わないというのもあります。

回答
投稿日時: 18/10/07 16:39:09
投稿者: チオチモリン

ああ すいません。
スペースの扱いが某板と違うようです。
見苦しいですが、コードのあとの ○→○ というのが、コードの実行前と実行後の値です。
そのように読んでいただけるとありがたいです。
 

回答
投稿日時: 18/10/07 17:11:34
投稿者: WinArrow
投稿者のウェブサイトに移動

ループカウンターを自分でカウントアップする場合のコードの例
 
Dim i As Long
    i = 0
    Do Until i = 10
        i = i + 1
        Debug.Print i
    Loop
    Debug.Print i

回答
投稿日時: 18/10/07 17:58:53
投稿者: VBA-stepup

日本語で書くと
For i = 1 To 10
1 変数iの値が初期値 1から10になるまでの間 For〜Next文内の処理を繰返す。
 
  i = i + 1
 
Next
1 変数iの値にプラス1する(i = i + 1) Stepが省略されているので
2 変数iの値が10以下ならばFor〜Next文内の最初の行にジャンプする
  10より大きかったら繰返しを終了する。
 
こんな感じかな
 
以下のコードをステップ実行で処理の移行とiの値の変化を確認して下さい。

Sub test1()
    Dim i As Long
    Dim k As Long
    
    k = 1
    For i = 1 To 10
        MsgBox k & "回目の  iの値 = " & i
        i = i + 1
        k = k + 1
    Next
    MsgBox i
End Sub
Sub test2()
    Dim i As Long
    Dim k As Long
    
    k = 1
    For i = 1 To 10
        MsgBox k & "回目の  iの値 = " & i
        i = i + 1
        If k = 3 Then Exit For
        k = k + 1
    Next
    MsgBox i
End Sub

回答
投稿日時: 18/10/08 11:01:16
投稿者: sy

引用:
For i = 1 To 10
    i = i + 1
Next

この記述では i=i+1 と Next でそれぞれ1が加算されます。
なので i=9 の時に i=i+1 で[10]になって Next で1加算されて[11]になるので、
その時点でループが終了するので[11]と言うメッセージが返ります。
ループ自体は10回実行されるのではなく、1,3,5,7,9の時の5回しか実行されません。
 
引用:
For i = 1 To 5
    i = i + 1
Next

此方の記述の場合は、1,3,5の時の3回ループが実行されますが、i=5 の時に i=i+1で[6]になり、
Nextで[1]加算されて[7]になり、その時点でループ終了になるので[7]と言うメッセージが返ります。

回答
投稿日時: 18/10/08 13:10:35
投稿者: sy

引用:
i = i + 1 → 2  ・・・1回目
i = i + 1 → 3  ・・・2回目
i = i + 1 → 4  ・・・3回目
i = i + 1 → 5  ・・・4回目
i = i + 1 → 6  ・・・5回目
i = i + 1 → 7  ・・・6回目
i = i + 1 → 8  ・・・7回目
i = i + 1 → 9  ・・・8回目
i = i + 1 → 10  ・・・9回目
i = i + 1 → 11  ・・・10回目

これは1回目の時に、なぜ2になると思ったんでしょうか?
ループカウンターが1から始まるから、i=i+1で2になると思ったんでしたら正解です。
 
でもそれなら、なぜ2回目以降はループカウンターの加算分は考慮されなかったんでしょうか?
i=i+1など無くても、iの値は増えていきますよね。
 
1回目と同じように考えたら、ループカウンターで1づつ加算されるのに、
更にi=i+1とすれば2づつ増えていくと、想像するのが普通と思いますが。
 
今回はループカウンターの加算分を無視して考えてたので、おかしな考えになってしまったんです。
 

回答
投稿日時: 18/10/08 17:42:49
投稿者: たらのり

こんにちは
 
(他の方の発言と被ると思いますが)
For Next では,ループ変数(ここでは i)の値は
自動的に(指定された分だけ)変化するので,
あえて値を変更する必要はありません。
 

Dim i
For i = 1 To 5
    MsgBox "ループ内 " & i
Next
MsgBox "ループ外 " & i

このコードでは,次々と以下のメッセージボックスが
表示されます。
 
ループ内 1
ループ内 2
ループ内 3
ループ内 4
ループ内 5
ループ外 6

投稿日時: 18/10/11 17:14:34
投稿者: hisayanxp

沢山の方に助けていただいて、For…Nextの構文がだいぶ分かったような気がしました。
皆様、ありがとうございました。
教わったことをもとにして色々実験をしていましたら、変な所でひっかかってしまいました。
こんな記述です。
 
Dim i
For i = 1 To 5
i = i + 1
MsgBox i
Next
MsgBox i
 
2,4,6,8と表示されると思いましたが、最後が8ではなく7になりました。
この原因が分かりません。
ちなみにこのように考えました。よろしくお願いします。
 
 
Dim i
For i = 1 To 5
i = i + 1   …i に 1を代入
MsgBox i    …2 になる
Next      … 3+1で
MsgBox i    … 4
 

 
Dim i
For i = 1 To 5
i = i + 1   …i に 5を代入
MsgBox i    …6 になる
Next      … 7+1で
MsgBox i    … 8
 
 
 
 

回答
投稿日時: 18/10/11 17:51:25
投稿者: たらのり

こんにちは
 

Sub ForNext()
    Dim i
    For i = 1 To 5
        i = i + 1
        MsgBox i
    Next
    MsgBox i
End Sub

Sub ForNext を If と GoTo で書き直すと、以下のような
イメージになると思います:
 
Sub IfGoTo()
10: Dim i
    
20: i = 1                           ' For の "i = 1"
30: If Not (i <= 5) Then GoTo 99    ' For の "To 5"

40: i = i + 1
50: MsgBox i
    
60: i = i + 1                       ' For の "Next"
70: GoTo 30                         ' For の "Next"

99: MsgBox i
End Sub

# VBS で行番号は無効かもしれませんが
 
1行ずつ目で追って i の中身を確認しながら、GoTo がある
場合はそのとおりにトレースしてみてください。

回答
投稿日時: 18/10/11 18:00:38
投稿者: たらのり

60: i = i + 1                       ' For の "Next"


 
60: i = i + 1                       ' For の (省略された) "Step 1"

かな

回答
投稿日時: 18/10/11 19:38:40
投稿者: sy

引用:
MsgBox i    …2 になる
Next      … 3+1で
MsgBox i    … 4
全く理解されてませんね。
 
何でNext は 3+1 と言う発想になったんですか?
 
i=i+1 で1だったものが 2 になるのは良いですけど、
MsgBoxに表示させただけで 2 が 3 になるんですか?
 
For i = 1 to 5 Step 1
Next
これが省略せずに書いた時の記述です。
Forの部分で、iの値が1〜5の時にNextまでの間の処理をします。
NextでStepで指定した分の数値が加算されます。(Step -1とかなら-1を加算)

 
For i = 1 to 5 Step 1
    i = i + 1
Next
この場合、
1回目のループ
Forの行で i=1 になる、
i=1 は 1 to 5 の範囲内なのでループが実行される。
i=i+1の行で 1+1 なので i=2 になる
Nextの行で Steo 1の分が加算されて i=3 になる

2回目のループ
Forの行で i=3 になっている(1回目のNextで3になった時の数値のまま)、
i=3 は 1 to 5 の範囲内なのでループが実行される。
i=i+1の行で 3+1 なので i=4 になる
Nextの行で Steo 1の分が加算されて i=5 になる

3回目のループ
Forの行で i=5 になっている(2回目のNextで5になった時の数値のまま)、
i=5 は 1 to 5 の範囲内なのでループが実行される。
i=i+1の行で 5+1 なので i=6 になる
Nextの行で Steo 1の分が加算されて i=7 になる

4回目のループ
Forの行で i=7 になっている(3回目のNextで7になった時の数値のまま)、
i=7 は 1 to 5 の範囲に入っていないのでループが実行されずにステートメントが終了する。

この実行されなかった4回目のループの時の7が格納されてるんです。
 
 
 

回答
投稿日時: 18/10/11 20:34:19
投稿者: simple

(皆さんからの発言と重なっているかもしれません。お許し願います。)
 
皆さんから適切な助言をいただいているのに、意外そして残念です。
 
・文章による説明はひとまず置いて
ご自分でステップ実行して、
・ローカルウインドウで一行毎に i の値がどうなるか、自分で確認してください。
そこを手抜きしているから、理解できないんですよ。やってないでしょ?
 
私、過去、何回かあなたにステップ実行をしてくださいと、
推奨しています(例えば、下記 (*)参照)。
 
VBSだからというのは理由になりません。
基本部分に理解が深まっていないのですから、
VBSだなんていうのはすっぱり止めて、
デバッグ機能が(相対的に)充実しているVBAをしっかり学習してください。
 
ステップ実行して、事実をきちんと確認すれば、絶対に理解できるはずです。
他人の助言をしっかり受け止めたうえで、頑張って下さい。
 
 
---- 以下は 質問者以外はスキップいただいて結構です。 ----
 
> 投稿日時: 17/05/20 17:02:38 投稿者: hisayanxp
> ところで
> 1. ステップ実行する  とはF8をたたいて1行ずつ確認すればよいのでしょうか?
> どうもいろいろ調べてもピンときません。
>
> よろしくお願いします。
 
> 投稿日時: 17/05/20 17:16:24 投稿者: simple
> 今までに何度もデバッグの話が出てきたと思います。
> VBAに関するテキストは手元に購入していないのですか?
> ステップ実行に関する質問が今頃になって出てくるなんて
> 今まで人の話をどう聞いていたんでしょう。
> (中略)
> 本が買えないというなら、
> http://www.asahi-net.or.jp/~ef2o-inue/vba_k/sub04_030.html
> http://www.asahi-net.or.jp/~ef2o-inue/vba_k/sub04_030_03.html
> などを読んでみたらどうですか?
 
> 投稿日時: 17/05/20 18:16:23 投稿者: hisayanxp
> simpleさん、わかりやすいページを教えていただいてありがとうございました。
> 買った本はご紹介していただいたhpほどわかりやすくありませんでした。

投稿日時: 18/10/12 08:00:49
投稿者: hisayanxp

お教えいただきましたのはすべて試してみましたが、理解でっきない部分が結構ありました。もう一度見直してチャレンジします。
お騒がせいたしました。