• 締切済み

ForEach...文でRows(1)を指定エラー

For Each element In group ...Next ステート文で、group に Rows(1) を指定し、セルのValueプロパティを取得しようとするとエラー「型が一致しない」が出る。指定した範囲内の1行目のセルの値を確認しようと以下のマクロを作り、実行するとエラーが出る。その理由をどなたか教えてください。 Sub testA() Dim r0 As Range Dim r1 As Range Dim cr As Range Dim i As Integer Dim result as Boolean Set r0 = Worksheets("Sheet1”).Range("B4:D5") Set r1 = r0.Rows(1) For Each cr In r1 Debug.Print cr.Value ‘*** (0) エラー発生 Next cr ‘*** 以下はうまくいく。 For Each cr In r1 Debug.Print cr.row ‘*** (1) Debug.Print cr.Column ‘*** (2) Next cr result = TypeOf r1 Is Range  ‘*** (3) Debug.Print result ‘*** True ‘*** 確認したいことをFor Each … Next を使わないで, ‘*** セルを相対位置で指定すればうまくいく。 For i = 1 to r1.Columns.count Debug.Print r1.Cells(1, i).row Debug.Print r1.Cells(1, i).Column Debug.Print r1.Cells(1, i).Value ‘*** エラーなし Next i End Sub よく分からないのは(1)(2)(3) なのに なぜ Value プロパティ取得で(0)「型が一致しない(実行時エラー’13’)」になるところです。環境はExcel 2013, Windows 10です。 よろしくお願いします。

みんなの回答

回答No.2

こんにちは。 お望みの結果を得るには、 目的によって違うので、3例、 ' ///   Set r0 = Worksheets("Sheet1").Range("B4:D5")   Set r1 = r0.Rows(1)   For Each cr In r1.Cells ' ←★     Debug.Print cr.Row; "-"; cr.Column, cr.Value   Next cr ' /// または、 ' ///   Set r0 = Worksheets("Sheet1").Range("B4:D5")   Set r1 = r0.Rows(1).Cells ' ←★   For Each cr In r1     Debug.Print cr.Row; "-"; cr.Column, cr.Value   Next cr ' /// 場合によっては、 ' ///   Set r0 = Worksheets("Sheet1").Range("B4:D5")   Set r1 = Application.Intersect(r0, r0.Rows(1)) ' ←★   For Each cr In r1     Debug.Print cr.Row; "-"; cr.Column, cr.Value   Next cr ' /// などのように、 'Rows態'のRangeオブジェクトに含まれるすべての行   をループさせるのではなく、 'Rows態'のRangeオブジェクトに含まれるすべてのセル   をループさせます。 > Set r0 = Worksheets("Sheet1”).Range("B4:D5") > Set r1 = r0.Rows(1) > For Each cr In r1 > Debug.Print cr.Value‘*** (0) エラー発生 > Next cr r1 には セル範囲の行範囲を表す 'Rows態'のRangeオブジェクト が格納されています。 > For Each cr In r1 cr の意味は 'Rows態'のRangeオブジェクト を 1行ずつ(毎)ループした セル範囲の行を表す Rangeオブジェクト が渡されます。 > Debug.Print cr.Value‘*** (0) エラー発生 cr.Value 自体は正しいプロパティの使い方ですが、 戻り値がVariant型配列です。 Variant型配列をそのまま Debug.Print することは出来ませんから、 「型が一致しない(実行時エラー’13’)」を返します。 > For Each cr In r1 range.Rows プロパティは、 application.Rows プロパティ や worksheet.Rows プロパティ と、 同じように、 戻り値としては、Range型で、中身はrange.Rowsです。 以下、[VBAヘルプ(Excel 開発者用リファレンス)]より |Range.Rows プロパティ |指定されたセル範囲の行を表す Range オブジェクトを返します。 以上引用。 Range型オブジェクトには、Cells、Rows、Columns、 様々な形態のオブジェクトが格納されます。 ※本回答では、説明し易くする為の便宜的な用語として  「'Rows態'のRangeオブジェクト」という造語を使っています。 ひとつのオブジェクト型に複数の携帯のオブジェクトやコレクションが格納されることは、 よくあることですが、 Range クラスでは、.Type プロパティのようにオブジェクトを特定する為の情報は、 用意されていません。 r1 に格納されたのは、'Cells態'のRangeオブジェクト なのか?を調べる必要がある場合には、 ' ///   If r1.Count = r1.Cells.Count Then     For Each cr In r1       Debug.Print cr.Row; "-"; cr.Column, cr.Value     Next cr   Else     For Each cr In r1.Cells       Debug.Print cr.Row; "-"; cr.Column, cr.Value     Next cr   End If ' /// などのように.Count と .Cells.Count を比較するのが簡単です。 因みに、Rows とか Row という名のコレクション(オブジェクト)はありませんが、 'Rows態'のRangeオブジェクトをループやItemで扱っていると、 あたかもRowsコレクションを操作しているような挙動を得られるけれど、 実体はRange オブジェクトだからこそ、 .Valueを始めとしたプロパティやメソッドを、そのまま使えることが殆どです。 行や列単位など、臨機応変に塊りを扱えるクラスとして重宝するのがRangeなのですが、 ご質問のケースのように、その多機能さがアダとなり時に解り難くなることもあるということです。 シンプルなアドバイスとして、  Rows、Columns、に対して総当たりループをする場合、  行や列単位の処理なのか、単セル単位の処理なのか、まずは確認。  単セル単位ならば、.Cells プロパティのことを思い出して。 という纏めになります。 > Debug.Print cr.row‘*** (1) > Debug.Print cr.Column‘*** (2) range.Row プロパティ、range.Column プロパティは、 rangeオブジェクトの形態に係らず、 range.Cells(1) や range.Areas(1).Cells(1) の 行/列インデックスを返しますから、エラーにはなりません。 > result = TypeOf r1 Is Range  ‘*** (3) r1 はRange型で指定しています。、 range.Rows プロパティの戻り値もRange型ですからNothingにはなりません。 従って、result = True です。 この手の判別に TypeOf を使うのは初めて見ました。  result = TypeName(r1) = "Range" とか、個人的には、既定のオブジェクト型については、 TypeName関数を使うことが殆どですが、 私には、評価できる素養がありませんので、この点はスルーでお願いします。 以上です。

EulerKnowsNo
質問者

お礼

Realbeatin さん ありがとうございました。 例示いただいた3例のうち1例目と2例目は理解できましたので、利用させていただきます。3例目については調べてみます。 反省 (1)Range オブジェクト についての理解が全く浅はかであることがわかりました。 「>'Rows態'のRangeオブジェクト」「>'Cells態'のRangeオブジェクト」について、理解できるかわかりませんが、調べてみます。 (2)「For each… 」文についても、group が Range であれば Cell 単位でループすると思い込んでいました。 後悔 For Each cr In r1 Debug.Print cr.row ‘*** (1) Debug.Print cr.Column ‘*** (2) Next cr を実行すれば、1回しかループしないので行単位であることに気がついたかも? 実際は(2)の後に(0)を付けて実行したので無理でした。 Debug.Print cr.Value ‘*** (0) エラー発生 (3)「TypOf」について オブジェクトの型について知りたいとネットで検索すると例があったので使いました(対象がRange ではなかったかも)。「 TypeName 」関数をしりませんでした。調べてみます。 詳しい説明をいただき大変参考になりました。 いろいろ勉強になります。 本当にありがとうございました。

  • okormazd
  • ベストアンサー率50% (1224/2412)
回答No.1

Set r1 = r0.Rows(1) で、r1はr0の1行目の範囲をオブジェクトとするrowのコレクション(といってもこの場合は1つしかないが)になります。 For Each cr In r1 で、crはrowのオブジェクトを取り出すことになります。 Debug.Print cr.Value crはrowだからvalueプロパティはありません。ないものを表示させようとするから、エラーになるのです。 次のようにして確認してはいかがでしよう。 Set r1 = r0.Rows(1) For Each cr In r1 Debug.Print cr.row Next cr または、 Set r1 = r0.Rows For Each cr In r1 Debug.Print cr.row Next cr

EulerKnowsNo
質問者

お礼

Okormazd さん ありがとうございました。 「 For each item in group … Next」文について、誤解していました。 group が行タイプ(?)でも、その行内のセル単位でループすると思い込んでいました。 Rows, rowコレクション、For each … 文について調べてみます。 本当にありがとうございました。

関連するQ&A

  • [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をどのように使い分けていますか? 質問に不備不足等ございましたらご指摘ください。 ご面倒お掛けしますがよろしくお願いします。

  • 【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 もっと、無制限に、たくさんのセルを選択できるようにしたいのですが、何か手はないでしょうか? ご教授お願いします。

  • エクセル2003のVBAで列を指定

    エクセルで特定の列の2~10行目に対して、ある作業をする場合、列を指定する方法は以下のどれがいいでしょうか?あるいはもっといい方法があれば教えてください。 実際には列は約40列(固定)、行は1~2万行(変動)程度で、作業はもっと複雑です。 Sub test01() Dim col Dim i As Long, n As Long For Each col In Array(1, 3, 7, 8, 11) '列番号で指定 For i = 2 To 10 n = n + 1 Cells(i, col).Value = n Next i Next col End Sub Sub test02() Dim col Dim i As Long, n As Long For Each col In Array("A", "C", "G", "H", "K") '列の記号で指定 For i = 2 To 10 n = n + 1 Cells(i, col).Value = n Next i Next col End Sub Sub test03() Dim col Dim i As Long, n As Long For Each col In Range("A2,C2,G2,H2,K2") 'セルで指定 For i = 2 To 10 n = n + 1 col.Offset(i - 2).Value = n Next i Next col End Sub

  • Resizeでエラーが出る原因と処置

    シート構成 |[A] |[B] [1] |名前  |出席回数    [2] |いぬ | 5 [3] |ねこ | 4 [4] |うさぎ | 3 [5] |たぬき | 6 [6] | | [7] | | [8] | | [9] | | [10]|いぬ | 5 [11]|たぬき | 6 以下のコードでは、 50,60のコードはOKですが 70のコードはNG(アプリケーション定義またはオブジェクト定義のエラーです)です。 どう変更すれば、エラーが無くなりますか ? Option Explicit Sub test() Dim i As Long Dim r As Range Dim mb As Long 10 mb = Cells(Rows.Count, "B").End(xlUp).Row 20 i = 2 30 For Each r In Range("B2:B" & mb) 40 If r >= 5 Then 50 Cells(i + 8, "A") = Range(r.Address).Offset(0, -1) 60 Cells(i + 8, "B") = Range(r.Address) 70 Range(r.Address).Resize(, -1).Copy Destination:=Range("D1") 80 Stop 90 i = i + 1 100 End If 110 Next End Sub

  • 指定したセルに1がない時、For を抜けたいのですが・・・

    Office XP Personal 2002 Excel 2002 指定した範囲セルに1がない時、下記の1つの For だけ を抜けたいのですが・・・ どのように変更すればよろしいでしょうか? よろしくお願い致します。 Sub test() Dim i As Integer Dim n As Range For i = 1 To Worksheets.Count - 1  Worksheets(i).Activate  For Each n In .Range("E6", .Range("E6").End(xlDown))   If Not n.Cells.Value = 1 Then   End If   Next n    MsgBox "「1」 がありません。", 48   Exit For  'For Each n In .Range("E6", .Range("E6").End(xlDown))   '続く   '・    '・ End Sub

  • set文でエラーがでます

    以下のコードで  実行エラー''9'「インデックスが有効範囲にありません。」が出る原因と対処方法を教えてください。 Set ws = Worksheets(FileName2) FilewName2はローカルウインドウでは問題なく表示されています。 Sub 括弧及び括弧内文字削除() ' 'ダイアログでターゲットファイル(txt)を選択(読み込み) --------------- Dim FileName As Variant Dim FileName2 As String Dim FilePath As String Dim fso As New FileSystemObject FileName = Application.GetOpenFilename(FileFilter:="Txtファイル,*.txt) If FileName = False Then Exit Sub End If 'ターゲットファイルの拡張子無しのファイル名を取得 FileName2 = fso.GetBaseName(FileName) 'ターゲットファイルのパス取得 FilePath = Replace(FileName, Dir(FileName), "") Workbooks.Open FileName '括弧内文字列削除(括弧も含む)-------------------------------- Dim RegExp As Object Dim Cell As Range Dim tr As Long 'DATAを処理する行数 tr = Cells(Rows.Count, "A").End(xlUp).Row Set RegExp = CreateObject("VBScript.RegExp") RegExp.Global = True RegExp.Pattern = "[((].*[))]" ' Application.ScreenUpdating = False Dim buf Dim i As Long With Range("A1", Cells(Rows.Count, "A").End(xlUp)) buf = .Value For i = 1 To UBound(buf) buf(i, 1) = RegExp.Replace(buf(i, 1), "") Next .Value = buf End With ' Range(Cells(1, 1), Cells(tr, 1)).Select ' For Each Cell In Selection ' Cell = RegExp.Replace(Cell, "") ' Next '新規に修正ファイルをテキストファイルに書き出す ------------- Dim ws As Worksheet Set ws = Worksheets(FileName2) Dim datFile As String datFile = FilePath & FileName2 & "_mod.srt" Open datFile For Output As #1 For i = 1 To tr Print #1, ws.Cells(i, "A").Value Next Close #1 Application.ScreenUpdating = True MsgBox datFile & "に書き出しました" & vbCrLf & _ "処理が終了したのでEXCELを閉じて終了です。" '// Excelを終了する Application.Quit ActiveWorkbook.Close SaveChanges:=False ThisWorkbook.Close SaveChanges:=False End Sub

  • エクセル2019 VBAについて

    エクセル2019でVBAを使いコピーペーストの勉強中です、次の箇所(Dim i As integr)で、ユーザー定義型は定義されていませんと指摘されて止まってしまします、Sheet("データ")には3行のデータは入っています、VBA初心者のため、この後が、なかなか前に進めません、どうかよろしくおねがいします。 ********************************** Sub 練習() Dim s1 As Worksheet: Set s1 = Worksheets("請求書") Dim s2 As Worksheet: Set s2 = Worksheets("データ") Dim r1 As Integer: r1 = 18 Dim r2 As Integer: r2 = 2 { Dim i As integr } For i = 0 To 2 s1.Range(s1.Cells(r1 + i, 1), s1.Cells(r1 + i, 3)).Value = s2.Range(s2.Cells(r2 + i, 2), s2.Cells(r2 + i, 4)).Value s1.Cells(r1 + i, 4).Value = s1.sells(r1 + i, 2).Value * s1.Cells(r1 + i, 3).Value Next End Sub ***************************************

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

    こんにちは、マクロ初心者ではないつもりですが、基本ができていないのか、以下の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です。

  • エクセルVBA/シェープの文字列を取得

    エクセル2010です。 BOOK内の各シートにボタンやチェックボックス、ラベルやテキストボックスなどが配置されています。 これらの貼り付けられたものの一覧を作りたいのです。 Sub obj_Check() Dim st Dim sp Dim i As Long For Each st In Sheets For Each sp In st.Shapes i = i + 1 With Sheets("Sheet3") .Cells(i, "A").Value = sp.Name ' .Cells(i, "B").Value = sp.Caption ’これがエラー .Cells(i, "C").Value = st.Name End With Next sp Next st End Sub とやってみましたがsp.Captionがエラーになります。 .Cells(i, "B").Value = sp.Shapes.Range.Character.Text としても同じです。 どうやったら、シェープに書かれた文字列が取得できるのでしょうか?

  • エクセルVBAの条件指定が上手くいきません

    「7を超えたら、For Eachステートメントを抜けなさい」という条件を入れたいのですが、 7を超えても処理が継続し困っています。 勉強不足で申し訳ないですが、ご教授願います。 【やりたいこと】 まず、セルB1~D3までのセルの値(9つ)が、7を超えない条件で1を加算していきます。 加算したときの値はE~Gの列に貼り付けていきます。 7を超えた時点でFor Eachステートメントを抜けます。 また、B1~D3までのセルには計算式が入っており、A1に数字を入れると、 それぞれ異なる増え方をします。(計算式自体は$A$1+1.1、$A$1+2.1などシンプルなもの) Sub test() Dim i As Range Dim n As Long Dim x As Long n = 1 x = 1 For Each i In Range("B1:D3") Range("A1").Value = x If i < 7 Then Range("B1:D3").Copy Cells(n, 5).Select Selection.PasteSpecial Paste:=xlPasteValues n = n + 3 x = x + 1 ElseIf i > 7 Then Exit For End If Next End Sub お手数ですが、宜しくお願いいたします。

専門家に質問してみよう