• ベストアンサー

エクセルVBAで無限ループ

教えてください。 以下の2つのエクセルマクロはまったく同じことをさせようとしているのですが、test02の方は.Offset(1).Activateが働かないのか、無限ループに陥ってしまいます。 単にActiveCell.という記述をWith~End Withでまとめただけなのになぜこうなるのでしょうか? Sub test01() ActiveSheet.Cells(1, 1).Activate Do While ActiveCell.Value <> "" If Not IsNumeric(ActiveCell.Value) Then ActiveCell.Offset(0, 1).Value = "文字" ElseIf ActiveCell.Value > 0 Then ActiveCell.Offset(0, 1).Value = "正数" ElseIf ActiveCell.Value < 0 Then ActiveCell.Offset(0, 1).Value = "負数" Else ActiveCell.Offset(0, 1).Value = "その他" End If ActiveCell.Offset(1).Activate i = i + 1 Application.StatusBar = i Loop End Sub Sub test02() ActiveSheet.Cells(1, 1).Activate With ActiveCell Do While .Value <> "" If Not IsNumeric(.Value) Then .Offset(0, 1).Value = "文字" ElseIf .Value > 0 Then .Offset(0, 1).Value = "正数" ElseIf ActiveCell.Value < 0 Then .Offset(0, 1).Value = "負数" Else .Offset(0, 1).Value = "その他" End If .Offset(1).Activate i = i + 1 Application.StatusBar = i Loop End With End Sub

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

  • ベストアンサー
  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.3

With ActiveCellの判断が、システムが行っていることと、質問者様が思っていることとで違いがあることが原因かと思われます。 (多分、With分実行時に決めている。) 以下の2例を実行してみると、ActiveCellがどのように判断されているかわかるのでは? Sub test2() For i = 1 To 5  MsgBox (ActiveCell.Address)  With ActiveCell   .Offset(1).Activate  End With Next i End Sub Sub test1() With ActiveCell  For i = 1 To 5   MsgBox (ActiveCell.Address)   .Offset(1).Activate  Next i End With End Sub

merlionXX
質問者

お礼

ありがとうございました。 こうやってみるとよくわかりました。 本当のActiveCellは変わっていくのにWith ActiveCellの対象は変わりませんでした。 Sub test3() With ActiveCell For i = 1 To 5 MsgBox (ActiveCell.Address & "/" & .Address) ActiveCell.Offset(1).Activate Next i End With End Sub

すると、全ての回答が全文表示されます。

その他の回答 (3)

  • Yosha
  • ベストアンサー率59% (172/287)
回答No.4

「Sub test02()」 の場合、「With ActiveCell」 の後に、 Do ループを入れていて、そのループの中で 「Offset(1)」 を使って、 次の行を Active にしようとしていますが、頭の 「With ActiveCell」 は最初の 「Cells(1, 1).Activate」 を受けていますので、ループ内で何度 「.Offset(1).Activate」 を実施しても、Cells(1, 1) にたいして Offset(1) を行いますので、結局は、Cells(2, 1) を Active にするだけでそれ以下の行を Active にすることはできません。 それゆえに Cells(2, 1) が空セルでない限りループから脱出できません。 これが無限ループの原因です。 Sub test02() を F8 を使ってステップインしながら、セルの Active 状態を見てください。 Cells(2, 1) が Active になったままになっているのが分かります。 どうしても、With を使うのであれば、With と Do の行を入れ替えれば、正常に動きます。 Sub test02()  Dim i As Integer  ActiveSheet.Cells(1, 1).Activate  Do While ActiveCell.Value <> ""   With ActiveCell    If Not IsNumeric(.Value) Then     .Offset(0, 1).Value = "文字"    ElseIf .Value > 0 Then     .Offset(0, 1).Value = "正数"    ElseIf ActiveCell.Value < 0 Then     .Offset(0, 1).Value = "負数"    Else     .Offset(0, 1).Value = "その他"    End If    .Offset(1).Activate    i = i + 1    Application.StatusBar = i   End With  Loop End Sub

merlionXX
質問者

お礼

あるがとうございます。 仰せの通りでございます。

すると、全ての回答が全文表示されます。
回答No.2

これは初めて知った。 Option Explicit '==========クラスモジュールClass1============= 'Option Explicit 'Public a As Integer '============================================ 'Once you have entered a With...End With, 'you cannot reassign object until you have passed the End With. 'ってそういう意味なんだ… Sub fuga() Dim x As Class1 Dim y As Class1 Set x = New Class1 Set y = New Class1 x.a = 5 y.a = 4 With x MsgBox (.a) '5 Set x = y MsgBox (.a) '5 MsgBox (x.a) '4 End With End Sub

merlionXX
質問者

お礼

ありがとうございます。 クラスモジュールってまったくわからないのでご教示のコードをはしらせることはできませんでしたが、 'Once you have entered a With...End With, 'you cannot reassign object until you have passed the End With. って、要はWith...End With間でオブジェクトを再定義できないってことなんでしょうね。 勉強になりました。

すると、全ての回答が全文表示されます。
  • nattocurry
  • ベストアンサー率31% (587/1853)
回答No.1

詳しいことは解りませんが、 With ActiveCell にすると、その時点でのActiveCellだけが With ~ End With の対象になるんでしょうね。 つまり、動的には対応していないということですね。 だから、最初のループで .Offset(1).Activate の処理をして、実際のActiveCellは変わっても、With の対象は変わらない、ということじゃないでしょうか。

merlionXX
質問者

お礼

ありがとうございます。 きっとそういうことなんでしょうね。 不思議です。

すると、全ての回答が全文表示されます。

専門家に質問してみよう