[VBA] For文の使い分けについての疑問

このQ&Aのポイント
  • VBAを使用して複数列の処理をする場合、For each next文を2つ書く必要があるが、この考え方は合っているのか疑問。
  • For each next文は単列の処理でも問題なく使用でき、For next文は複数列の処理でも使用できるが、VBA的に正しいかどうかは疑問。
  • 質問に不備があれば指摘してほしい。
回答を見る
  • ベストアンサー

[VBA] For文の使い分けについての疑問

こちらの識者の方々にはいつもお世話になっています。 VBAの質問です。 環境は下記になります。 OS=windows7 pro 64bit Office=Excel2010(14.0.7128.5000) ・疑問点 For each nextもFor nextも、最下行まで処理をしたいときに使用することが多いのですが、 単列の場合はFor each next、複数列の場合はFor nextというような使い方をしています。 例:For each next Sub test()  Dim ws As Worksheet  Dim r As Range  Dim endRow As Long  Set ws = ThisWorkbook.Sheets(1)  endRow = ws.Cells(Rows.Count, 1).End(xlUp).Row  For Each r In ws.Range("A1:A" & endRow)   If r.Value Mod 2 = 0 Then r.Font.Bold = True  Next r End Sub 例:For next Sub test2()  Dim ws As Worksheet  Dim i As Long  Dim endRow As Long  Set ws = ThisWorkbook.Sheets(1)  endRow = ws.Cells(Rows.Count, 1).End(xlUp).Row  For i = 1 To endRow   If ws.Cells(i, 1).Value Mod 2 = 0 Then ws.Cells(i, 1).Font.Bold = True   If ws.Cells(i, 2).Value Mod 3 = 0 Then ws.Cells(i, 2).Font.Bold = True  Next i End Sub 単純に、複数列での処理をする場合にはFor each next文を2つ書かないといけないと思い(込み)、 上記のような運用にしていますが、そもそもこの考え方は合っていますでしょうか? 単列の処理であってももちろんFor next文で問題なく使用できますし、 複数列の処理の場合もFor each next文で処理することはできます(冗長ですが)が、 VBA的に正しいというか、合理的な考えであるのかどうかが疑問です。 みなさんはFor each nextとFor nextをどのように使い分けていますか? 質問に不備不足等ございましたらご指摘ください。 ご面倒お掛けしますがよろしくお願いします。

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

  • ベストアンサー
  • Prome_Lin
  • ベストアンサー率42% (201/470)
回答No.1

私は、「For Next」は、終わりの値が何らかの方法で確定できるときです。 すなわち、上記の質問者の例だと、私は両方とも、「For Next」を使います。 しかし、終わりの値が分かる場合でも、次のように、繰り返すときに数値ではないもので繰り返す場合があります。 For Each f In x.Files If InStr(f.Name, "ABC") > 0 Then ああしなさい、こうしなさい。 End If Next これは、「x」というフォルダに存在するすべてファイルを調べるときに使うものですが、このとき、ファイルの数は「x.Files.Count」によって、取得できます。 単に、繰り返すだけなら「For f = 1 to x.Files.Count」でいいのですが、調べたファイルのファイル名を取得したいような場合は、「For Next」では、どうすることも出来ません。 「For Next」の(例の場合なら「f」)変数は、「数値」だからです。 f.Nameとやっても、ファイル名は取得できません。 これは「For Each Next」でしか、できないのです。 数値でいい場合は、「For Next」の方が圧倒的に便利です。 質問者の例でも、その変数の数値を使って「Cells()」が使えるからです。 単純な回数を指定する場合は、「For Next」、そうでなく、変数が特殊な意味がある場合は「For Each Next」という感じです。

rihitomo
質問者

お礼

ありがとうございます。 参考になりました。

その他の回答 (1)

回答No.2

私は基本的に、配列の場合For Nextを使い、コレクションの場合For Each Nextを使います。 セルに対して何かを行う場合も、セルを配列とみなして処理するならFor Next、コレクションとして扱うならFor Each Nextを使います。

rihitomo
質問者

お礼

ありがとうございます。参考になりました。

関連するQ&A

  • セルに対して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ができない理由を知りたいからです。 ご回答よろしくお願いします。

  • Excel VBA 連番印刷

    昨日以下の質問をさせていただいた者です。 http://okwave.jp/qa/q8349562.html こちらで教えていただいた以下のコードに、 J2のセルに連番を振るコードを付け足したいと思い、 同じくこちらのサイトの過去の履歴にあった以下コードを参考にとやってみているのですが、 Next で指定された変数の参照が無効です。と言われてしまいます… 印刷部数の指定はいらず、sheet印刷のJ2セルに1から始まる連番を振りたいのです。 どのように修正をしたらいいのかご教示願います。 Sub Sample4() Dim i As Long, endRow1 As Long, endRow2 As Long, myArea1 As Range, myArea2 As Range Dim wS1 As Worksheet, wS2 As Worksheet, wS3 As Worksheet Set wS1 = Worksheets("DB") Set wS2 = Worksheets("印刷") Set wS3 = Worksheets("Sheet3") endRow1 = wS1.Cells(Rows.Count, "A").End(xlUp).Row Range(wS1.Cells(1, "A"), wS1.Cells(endRow1, "A")).AdvancedFilter Action:=xlFilterInPlace, unique:=True wS1.Range("A:A").Copy wS3.Range("A1") wS1.ShowAllData For i = 2 To wS3.Cells(Rows.Count, "A").End(xlUp).Row endRow2 = wS2.Cells(Rows.Count, "B").End(xlUp).Row If endRow2 > 9 Then Range(wS2.Cells(10, "B"), wS2.Cells(endRow2, "H")).ClearContents Range(wS2.Cells(10, "J"), wS2.Cells(endRow2, "J")).ClearContents End If wS1.Range("A1").AutoFilter field:=1, Criteria1:=wS3.Cells(i, "A") wS2.Range("B6") = wS3.Cells(i, "A") Set myArea1 = Range(wS1.Cells(2, "B"), wS1.Cells(endRow1, "H")).SpecialCells(xlCellTypeVisible) Set myArea2 = Range(wS1.Cells(2, "I"), wS1.Cells(endRow1, "I")).SpecialCells(xlCellTypeVisible) myArea1.Copy wS2.Activate ActiveSheet.Range("B10").Select Selection.PasteSpecial Paste:=xlPasteValues myArea2.Copy wS2.Activate ActiveSheet.Range("J10").Select Selection.PasteSpecial Paste:=xlPasteValues endRow2 = wS2.Cells(Rows.Count, "B").End(xlUp).Row 'Range(wS2.Cells(1, "A"), wS2.Cells(endRow2, "J")).PrintOut Next i wS1.AutoFilterMode = False wS3.Cells.Clear End Sub 連番印刷のコード Sub NumberPrint() Dim idx As Integer Dim res  res = Application.InputBox("印刷部数を入力してください", Type:=1)  If res > 0 Then   For idx = 1 To res    Range("AW3").Value = idx    ActiveSheet.PrintOut   Next idx  End If End Sub

  • 【vba】複数のセルをfor文で選択したい

    vbaを独学で学んでおります。 質問内容は、 for文で条件に合ったセルを複数選択するにはどうすればいいのかというものです。 下のプログラムを作ってみたんですが、ループする回数がある一定の数を超えるとエラーが起こります。rangeオブジェクトにつかえる文字列の長さは、255文字までだとかなんとかだそうです。 Public Sub test() Dim str As String Dim i As Integer str = Cells(1, 1).Address For i = 2 To 50 str = str & "," & Cells(i, i).Address Next Range(str).Select End Sub さらに、次のプログラム使っても、256個ぐらいしかセルが選択できません。(これも何かの上限?) Public Sub test2() On Error GoTo エラー Dim r As Range Dim i As Integer Set r = Cells(1, 1) For i = 2 To 300 Set r = Union(r, Cells(i, i)) Next r.Select エラー: r.Select MsgBox ("256個しか選べませんでした") End Sub もっと、無制限に、たくさんのセルを選択できるようにしたいのですが、何か手はないでしょうか? ご教授お願いします。

  • VBAでのfor文について

    5行のデータがあるとして、先頭の文字がaで始まる行を削除して 上に詰めたいと考えています。 しかし、Range("i:i")のところに可変の数字iをうまく指定できて いないようで、うまく実行されません。 どこがまずいのでしょうか? Sub sample() Dim i As Integer For i = 1 To 5 activeworksheet.Cells(i, 2) = Mid(Cells(i, 1), 1, 1) If Cells(i, 2) = "a" Then ActiveSheet.Range("i:i").Delete shift:=xlshiftUp End If Next End Sub

  • VBAで複数のシート名を置換する処理

    Dim ws As Worksheet Dim i As Long For i = 1 To ThisWorkbook.Sheets.Count For Each ws In ThisWorkbook.Sheets If ws.name Like "*T*" Then ws.name = Replace(ws.name, "T", "S") End If Next Next End Sub この処理をするとnameメソッド失敗worksheetオブジェクト 処理できるようにするにはどうすればいいんでしょうか

  • VBA どこでもセル選択

    教えて頂いたVBAなのですがもう一つ Sub Macro1() Dim Ws01 As Worksheet Dim Counter As Long, i As Long, j As Long Dim INP As String Set wS = Worksheets("Sheet4") wS.Cells.ClearContents For i = 3 To ActiveSheet.UsedRange.Rows.Count INP = "" For j = Selection(1).Column To Selection(Selection.Count).Column If Cells(i, j) = 1 Then INP = INP & Cells(2, j) & "," End If Next j Counter = Counter + 1 If INP <> "" Then wS.Cells(Counter, "A") = Left(INP, Len(INP) - 1) End If Next i End Sub -------------------------------------------------------------- For i = 3 のところを3としないでどのセル(行)にも対応させたいのですが どうすればいいでしょうか?

  • エラー Nextに対するForがありませんについて

    VBAに慣れていないのですが、下記のマクロを組んでみました。 実行すると、コンパイルエラー Nextに対するForがありませんと出てしまいました。 原因が良く解らないので解る方いらっしゃいましたら教えてください。 それと、もっと良い書き方などありましたらアドバイスを下さい。 よろしくお願いします。 Sub レポート作成2each() Dim ReportMaxRow As Long '上方向に最終行を検索し行番号を格納 Dim AddWsName As String 'シート名格納 Dim Ws As Worksheet 'オブジェクト格納 Dim i As Long '繰り返しのカウントを格納 Dim flag As Boolean '真偽 ReportMaxRow = Worksheets("レポート元").Cells(Rows.Count, 1).End(xlUp).Row For i = 2 To ReportMaxRow If Cells(i, "N").Value <> "" Then If Cells(i, "O").Value <> "" Then AddWsName = Cells(i, "K").Value For Each Ws In Worksheets If Ws = AddWsName Then flag = True Next Ws   ←ここでエラーになります。 If flag = True Then Worksheets("レポート元").Cells(i, 1).EntireRow.Copy _ Destination:=Worksheets(AddWsName).Cells(Rows.Count, 1).End(xlUp).Offset(1, 0) Else Worksheets.Add ActiveWorksheet.Name = AddWsName Worksheets("レポート元").Cells(i, 1).EntireRow.Copy _ Destination:=Worksheets(AddWsName).Cells(Rows.Count, 1).End(xlUp).Offset(1, 0) End If MsgBox i + "行目の発注数の入力がませんでした。" & vbNewLine & "処理を中断します, _ vbOKOnly + vbExclamation, "お知らせ" End If Else MsgBox i + "行目の発注数の入力がませんでした。" & vbNewLine & "処理を中断します", _ vbOKOnly + vbExclamation, "お知らせ" End If Next i End Sub

  • For Each でシートのループ

    簡潔に質問する為に以下のマクロを見て頂きたいのですが、 この場合sheet1,sheet2,sheet3のそれぞれの(1,1)に2が発生せず 現在目でみているシートにのみ有効なのですが、全シートに有効に するには何が足りないのでしょうか Sub aaa() Dim ws As Worksheet For Each ws In Worksheets  Cells(1,1)=2 Next End Sub

  • エクセルVBAでFor each文

    下記のようなコードを書きたいのですが「オブジェクトが必要です」というエラーが 出力されてしまいできないようです。何か代替案はありますでしょうか。 --- dim ws as worksheet with thisworkbook for each ws in array(.worksheets(1),.worksheets(2),.worksheets(3)) with ws 'ここに処理を書く end with next ws end with --- ちなみにこのbookにある全てワークシートで処理を回したいわけではなく 特定のシートのみで処理をしたいです。 エクセル2003です。 よろしくお願いします。

  • VBA ループ文

    お手数ですが、回答お願いします。 VBAでループ文を勉強しております。 最初のfor 文で1000行、1000列に文字を入力、 次のdo 文でその文字を全部消したいのですが、うまくいきません。 またfor 文で1000行、1000列で文字を入力しているのですが、 時間がかかるのは仕方がないことなのでしょうか? お手数ですが、ご教授お願いします。 Sub 文字入力() Dim i As long Dim t As long For i = 1 To 1000 For t = 1 To 1000 Cells(i, t) = "wooo" Next t Next i End Sub ================================================================= Sub 文字入力消し() Dim i As long Dim t As long i = 1 Do t = 1 Do Cells(i, t) = "" t = t + 1 Loop Until Cells(i, t) = "" i = i + 1 Loop Until Cells(i, t) = "" End Sub

専門家に質問してみよう