• 締切済み

VBA Findの使い方

以下のコードは、最初の見つかったXYZに対しては、正しく処理されますが、 その後はうまくいきません。 なぜ、なのでしょうか? また、どうすれば見つかったすべてのXYZに対して処理ができるのでしょうか? (B列からxyzを検索し、その隣のセルに99を入力する) Sheets("Sheet1").Select Do While (True) Columns("B:B").Select Set mySelect = Selection.Find(What:="XYZ") If mySelect Is Nothing Then Exit Do mySelect.Offset(, 1).Value = 99 Loop End Sub

  • mk1234
  • お礼率94% (1832/1940)

みんなの回答

回答No.6

No.2 です。説明文について【訂正】です。 | | ご提示のコードでは、 | > Columns("B:B").Select | 繰り返し、B列を選択し直している → 常に【先頭】セルはB1になる。 | > Set mySelect = Selection.Find(What:="XYZ") | 引数Afterが省略されている為、 | 【先頭】セルを基準に[次を検索]する。 | つまり、B1を基準に次に見つかるセルを検索することを | 繰り返していることになり、その次、へ進むことが出来ていません。 誤) アクティブセル  ↓ 正) 先頭セル 失礼しました。 手作業で[次を検索]する場合の説明として以前書いたものを そのまま転用してしまって間違いに気付きませんでした。 VBAでは、  Selection.Find 引数Afterを省略した場合の基準セルは、  Selection(1) に位置する【先頭】セルです。 以上、訂正コメントでした。

  • kagakusuki
  • ベストアンサー率51% (2610/5101)
回答No.5

 回答No.4です。  失礼致しました。先程の回答のVBAマクロには一部バグがありましたので訂正致します。 Sub QNo9126961_VBA_Findの使い方() Const SearchValue = "XYZ" Const SearchRangeAddress = "B:B" Dim mySelect As Range, SearchRange As Range, FirstAddress As String With Application .ScreenUpdating = False .Calculation = xlManual End With With Sheets("Sheet1") Set SearchRange = .Range(SearchRangeAddress) Set mySelect = SearchRange.Find( _ What:=SearchValue, After:=SearchRange.Resize(1, 1) _ , LookIn:=xlValues, LookAt:=xlWhole _ , SearchOrder:=xlByColumns) If mySelect Is Nothing Then MsgBox SearchRangeAddress _ & "の範囲内には、検索値として設定されている" _ & vbCrLf & vbCrLf & SearchValue & vbCrLf & vbCrLf _ & "と同じ値を持つセルは見つかりませんでした。" _ & vbCrLf & vbCrLf & "マクロを終了致します。" _ , vbInformation, "該当セル無し" Else FirstAddress = mySelect.Address Do mySelect.Offset(, 1).Value = 99 Set mySelect = SearchRange.FindNext(mySelect) If mySelect.Address = FirstAddress Then Exit Do Loop End If End With With Application .Calculation = xlAutomatic .ScreenUpdating = True End With End Sub

  • kagakusuki
  • ベストアンサー率51% (2610/5101)
回答No.4

 複数のセルを検索する際にFindを使って行う場合には、最初の検索のみFindで行い、Do~Loopの中ではFindNextを使う様にします。 Sub QNo9126961_VBA_Findの使い方() Const SearchValue = "XYZ" Const SearchRangeAddress = "B:B" Dim mySelect As Range, SearchRange As Range, FirstAddress As String With Application .ScreenUpdating = False .Calculation = xlManual End With With Sheets("Sheet1") Set SearchRange = .Range(SearchRangeAddress) Set mySelect = SearchRange.Find( _ What:=SearchValue, After:=ActiveCell _ , LookIn:=xlValues, LookAt:=xlWhole _ , SearchOrder:=xlByColumns) If mySelect Is Nothing Then MsgBox SearchRangeAddress _ & "の範囲内には、検索値として設定されている" _ & vbCrLf & vbCrLf & SearchValue & vbCrLf & vbCrLf _ & "と同じ値を持つセルは見つかりませんでした。" _ & vbCrLf & vbCrLf & "マクロを終了致します。" _ , vbInformation, "該当セル無し" Else FirstAddress = mySelect.Address Do mySelect.Offset(, 1).Value = 99 Set mySelect = SearchRange.FindNext(mySelect) If mySelect.Address = FirstAddress Then Exit Do Loop End If End With With Application .Calculation = xlAutomatic .ScreenUpdating = True End With End Sub

  • f272
  • ベストアンサー率46% (7997/17097)
回答No.3

すでに質問にたいする回答は出ているので,別のアドバイス。 Findなんて遅いから使うのはやめたほうがいいよ。 Sub FindXYZ2() Sheets("Sheet1").Select Set rng = Range(Cells(1, 2), Cells(Rows.Count, 2).End(xlUp)) ary = rng For ix = LBound(ary) To UBound(ary) If ary(ix, 1) Like "*XYZ*" Then rng.Cells(ix, 1).Offset(, 1) = 99 End If Next End Sub

回答No.2

こんにちは。 とりあえず、こんな感じでしょうか? ' ' /// Sub ReW9126961() Dim c As Range Dim n1stRow As Long   Worksheets("Sheet1").Select   With Range("b:b")     Set c = .Find( _       What:="XYZ", After:=.Cells(.Cells.Count), _       LookIn:=xlValues, LookAt:=xlWhole, _       SearchOrder:=xlByColumns, SearchDirection:=xlNext, _       MatchCase:=True, SearchFormat:=False)     If Not c Is Nothing Then       n1stRow = c.Row       Do         c.Offset(, 1).Value = 99         Set c = .FindNext(c)       Loop Until c.Row = n1stRow     End If   End With End Sub ' ' /// range.FindNext メソッドが、 前回の検索結果を基準にして[次を検索]する方法です。 [次を検索]では、同じセルを何度でも通りますから、 放っておくと無限ループになるので対策が必要です。 今回の設問では単列範囲なので、 .Row プロパティで行位置について、 最初に見つかったセル、と、今見つかったセル、とで 比較して同じ位置に至ったらループを抜けます。 因みに、range.Find メソッドの各種引数についてですが、 直前に実行した際のオプション設定(引数指定) を基本的に踏襲する仕様ですので、 VBAで書く時は、一連の処理の中で最初に range.Find メソッドを実行する記述では、 引数を省略せずに書かないと、痛い目に合うことが多々あります。 一連の処理の中で2回め以降は、最初に命令したオプション設定が 踏襲されるので省略可能になります。 また、 今回の設問では隣のセルを書き換える処理だけなので構いませんが、 見つかったセルそのものを書き換える処理をする時などは、 次に見つかる筈のセルが無い場合もありますので、 そういう場合は、       Do         c.Value = Rnd()         Set c = .FindNext(c)         If c Is Nothing Then Exit Do       Loop Until c.Row = n1stRow のように書くことになります。 > 以下のコードは、最初の見つかったXYZに対しては、正しく処理されますが、 > その後はうまくいきません。 > > なぜ、なのでしょうか? ご提示のコードでは、 > Columns("B:B").Select 繰り返し、B列を選択し直している → 常にアクティブセルはB1になる。 > Set mySelect = Selection.Find(What:="XYZ") 引数Afterが省略されている為、 アクティブセルを基準に[次を検索]する。 つまり、B1を基準に次に見つかるセルを検索することを 繰り返していることになり、その次、へ進むことが出来ていません。 以上です。

  • m_and_dmp
  • ベストアンサー率54% (974/1797)
回答No.1

Find 関数は一つ見つかれば次を見つけようとしないのでは? それに、Loopで戻ったとき、また同じ場所のxyz を見つけるのでいつになってもNothing にならないと思います。試してみましたが、マクロが何時になっても終了しませんでした。(ESCで中断させました。) つぎのようにすると、期待した動きをすると思います。 Sub FindXYZ() Sheets("Sheet1").Select I = 1 Do While (True) Range(Cells(I, 3), Cells(1000, 3)).Select Set mySelect = Selection.Find(What:="XYZ") If mySelect Is Nothing Then Exit Do mySelect.Offset(, 1).Value = 99 myRow = mySelect.Row I = myRow + 1 Loop End Sub

mk1234
質問者

お礼

回答ありがとうございます。 Findは、常に最初から検索するようですね

関連するQ&A

  • vbaで指定文字を含まない列を削除するとき

    vbaで指定文字を含まない列を削除したいです。 指定文字を含む列を削除するプログラムはできましたが、これを指定文字を含まない列を削除に変更したいです。 途中まで作ったこのプログラムを生かして、どう変更すれば含まないにできますか? 教えて頂けると助かります。 Private Sub CommandButton1_Click() Sheets("シート1").Select Do While (True) Rows("5:5").Select Set myselect = Selection.Find(What:="あああ", LookAt:=xlPart) If myselect Is Nothing Then Exit Do Columns(myselect.Column).Select Selection.Delete Shift:=xlUp Loop End Sub

  • vba  

    VBAはじめたばかりで、躓きました。 下記を実行すると、”Nextに対するForがありません。”とでます。 なぜこうなるのか教えてください。  G2~列2000の間が空白になるまで、  下記の処理を続けるようにしたいと思っています。  Dim i As Integer For i = 7 To 2000 Do If Cells(2, i) = "" Then Range("G2").End(xlToRight).Select ActiveCell.CurrentRegion.Resize(6, 5).Select Selection.Cut Range("B2").End(xlDown).Select ActiveCell.Offset(1).Select ActiveSheet.Paste Exit Do End If Next i Loop  よろしくお願いします。

  • Excel2013>VBA>sendkeys動ず

    Excel2013のVBAを使って自動更新をしようと思っています。    A  B   C 1  あ  AA  0 2  い  AB  1 3  う  AC  0 4  え  AA  1 5  お  AA  0 上記のようにシート内にデータはあります。B列「AA」C列の「ゼロ」を更新してC列の値を「1」にしようとしたときに、ピボットテーブルを使ってみようと思いました。 ピボットテーブルにてB列の「AA」、C列の「ゼロ」を抽出表示しました。   A  B  C 1 あ  AA  0 5 お  AA  0 思っていたように1行目と5行目が抽出されました。 後はゼロを別の値(仮に「2」とします)に変更するときに、カーソルの移動がうまくいきませんでした。 Range("C1").End(xlDown).Select Do ActiveCell.Offset(0, 0) = "2" ActiveCell.Offset(-1, 0).Select If Len(ActiveCell.Offset(0, 0)) = 0 Then Exit Do End If Loop しかし、これではカーソルが「C4」に移動してしまいました。 ピボットテーブルでたたんでしまっても、カーソルは見えないセルに移動するようです。 そこで、下記のように変更しました。 Range("C1").End(xlDown).Select Do ActiveCell.Offset(0, 0) = "2" Application.SendKeys "{UP}" If Len(ActiveCell.Offset(0, 0)) = 0 Then Exit Do End If Loop これは、カーソルがまったく動かずに最初の地点にいたままでした。 そこで、次はTABで移動することにしました。 Range("C1").Select Selection.SpecialCells(xlCellTypeVisible).Select Do ActiveCell.Offset(0, 0) = "2" Application.SendKeys "{tab}" If Len(ActiveCell.Offset(0, 0)) = 0 Then Exit Do End If Loop これでもカーソルは動きませんでした。 どうにかしてsendkeysの動かし方、もしくは更新でもっとうまいやり方をご存知の方、是非教えてください。よろしくお願いいたします。

  • Excel VBA 配列処理後の動作について

    Dim v As Variant             1.配列を使用して処理    v = (範囲)    処理      Range("A200").End(xlUp).Select    2.セルをA列最終行に移動 Do  If Selection = Range("A2") Then    処理    Exit Do  Else    処理    Selection.End(xlUp).Select  End if Loop 上記のように記述すると、配列処理の後の動作がうまくいきません。 セルは最終行に移動しているのですが、Do Loop では Selection は常に セルA2 として 認識されてしまいます。 If文の Selection を Selection.Address とするとうまく動作することを偶然見つけたので、 そちらで処理していくことにしましたが、なぜSelection のみでは期待通りに動作しないのでしょう? どなたかご教示いただけないでしょうか。 よろしくお願いいたします。

  • ExcelのVBAです。

    先日お答えいただいたVBAなんですが、 Sub Macro1() Sheets("Sheet1").Select Range("A1").Select Range(Selection, Selection.End(xlDown)).Select Selection.Copy Sheets("Sheet3").Select Range("A1").Select ActiveSheet.Paste Selection.End(xlDown).Select Application.CutCopyMode = False Do Selection.Insert Shift:=xlDown Selection.End(xlUp).Select Loop Until ActiveCell.Address = "$A$1" End Sub というのを使用させて頂いてます。 これを、コピー先のものを上書きせずに、コピーされたものがあれば表示させるといった風に出来ないでしょうか? 例  A    A 1 a 1 2 b → 2あ 3 c 3 右から左に一行間隔で別シートに表示させたいのですが、  A  1 a 2 あ 3 b 4 5 b という結果にしたいのです。 拙い文章で申し訳ないのですが、教えて頂きたいです。

  • VBAのFINDのエラーを回避したいです。

    以下のようなものを作成しましたが、1シートでは、問題なく回るものの2シート目のmをFINDしているところでエラーが発生します。原因は、該当するmが存在しないためだと思うのですが、そのような場合にエラーを回避し、次のシートへ飛びエラーが発生したシート番号を最後に表示してほしいです。 そのようなことは可能でしょうか? 読みにくいプログラムかもしれませんが、よろしくお願いします。 Dim top, m, under, bottom, cnt, she Application.ScreenUpdating = False '画面固定 cnt = Sheets.Count 'シートの数 For she = 1 To cnt Sheets(she).Activate Columns("F:F").Select Selection.Find(What:="0", After:=ActiveCell, LookIn:=xlFormulas, LookAt _ :=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _ False, MatchByte:=False, SearchFormat:=False).Activate top = ActiveCell.Row - 1 Rows("1:" & Format(top)).Select Selection.Delete Shift:=xlUp Range("A1").Select m = Range("E1") + 10 If m >= 60 Then m = m - 60 Else m = m End If Columns("E:E").Select Selection.Find(What:=Format(m), After:=ActiveCell, LookIn:=xlFormulas, LookAt _ :=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _ False, MatchByte:=False, SearchFormat:=False).Activate under = ActiveCell.Row bottom = Cells(ActiveSheet.Rows.Count, 1).End(xlUp).Row - 1 Rows(Format(under) & ":" & Format(bottom)).Select Selection.Delete Shift:=xlUp Range("A1").Select Next she End Sub

  • エクセルVBAで Do While (1)って?

    下記のような例文がありますが、 Do While (1)の括弧1の意味がわかりません。 Stri = "" iCount = 3 '入力データ開始行 Do While (1) If Trim(Sheets("テスト").Range("A" & iCount)) = "" Then Exit Do End If Stri = Stri & Sheets("テスト").Range("G" & iCount) & "," iCount = iCount + 1 Loop 以下のような使い方ならわかるのですが・・・・。 Do While Counter < 20 Counter = Counter + 1 MsgBox Counter Loop

  • VBA 並び替え

    たびたびお世話になります 選択範囲の並べ替えを行いたく こちらで教わった方法で セル位置の取得を行い Set r = Columns("A").Find("b1", lookat:=xlWhole, After:=Range("A" & Rows.Count)) Set rr = Columns("A").Find("bm123-1", After:=r, Searchdirection:=2) その取得した位置を元に並べ替えを行いたい 範囲選択をしています Range(r, rr.Offset(, 14)).Select その後並び替えを実施したいのですが Selection.Sort Key1:=Range(r.Offset(, 14)) この様にしてみましたが 実行時エラー1004が返されてしまいます どのようにすれば 並び替えができるのでしょうか よろしくお願いします

  • VBA 並び替え

    たびたびお世話になります 選択範囲の並べ替えを行いたく こちらで教わった方法で セル位置の取得を行い Set r = Columns(\"A\").Find(\"b1\", lookat:=xlWhole, After:=Range(\"A\" & Rows.Count)) Set rr = Columns(\"A\").Find(\"bm123-1\", After:=r, Searchdirection:=2) その取得した位置を元に並べ替えを行いたい 範囲選択をしています Range(r, rr.Offset(, 14)).Select その後並び替えを実施したいのですが Selection.Sort Key1:=Range(r.Offset(, 14)) この様にしてみましたが 実行時エラー1004が返されてしまいます どのようにすれば 並び替えができるのでしょうか よろしくお願いします

  • エクセルVBAでFindを使った検索について

    エクセル2003でVBAを勉強し始めたものです。 findを用いた検索についてご教授をお願いしたく、ご質問させていただきます。 まず、 <シート1> A列:受付No. B列:氏名 C列:物件名 <シート2> A~F列:省略 G~O列:物件名 とあります。 シート1上にコマンドボタンがあり、クリックするとシート1への入力用フォームが開きます。 さらに、そのフォーム内のテキストボックスに物件名を入力するのですが、テキストボックス内でダブルクリックで、物件検索用のフォームが開きます。 物件検索用フォーム内のテキストボックス(Text物件名検索)に文字列を入力し、コマンドボタン(command物件名検索)をクリックすると、フォーム内下部のリストボックス(List物件検索結果)内に、シート2のG~O列を検索した結果が並ぶようになっています。 その候補の中から選択したものが、シート1の物件名の列に並ぶようにしたいのです。 そこで、エクセルファイルを開いたすぐ後は、検索結果が意図通りに表示するのですが、一度他のコード(マクロにてシート1の行削除等)を実行した後、再度物件検索を行うと、検索結果が“なし”(その場合は「見つかりませんでした」とメッセージボックスが開くようにしてあります)となってしまいます。 変数の扱いがわるいのでしょうか?・・・ どうぞご教授のほどよろしくお願いいたします。 以下、検索用フォームのテキストボックス入力後、コマンドボタン(command物件名検索)をクリックしたときの処理コードです。 --------------------------------------- Private Sub command物件名検索_click() Dim bname As String Dim fndrange As Range Dim firstcell As String bname = Text物件名検索.Text Set fndrange = Sheets("TBオーナー").Columns("g:o").Find(bname) If bname = "" Then MsgBox ("キーワードを入力してください") Exit Sub Else If fndrange Is Nothing Then MsgBox ("見つかりませんでした") Text物件名検索.Text = "" Text物件名検索.SetFocus Else If Not fndrange Is Nothing Then firstcell = fndrange.Address Do Set fndrange = Sheets("TBオーナー").Columns("g:o").FindNext(fndrange) List物件検索結果.AddItem fndrange.Value Loop While Not fndrange Is Nothing And fndrange.Address <> firstcell End If End If End If End Sub ----------------------------------------- また、関係あるかわかりませんが、他のコード(シート1から行を削除するマクロ)も掲載させていただきます。 以下、 -------------------------------------- Private Sub Command削除_Click() Dim t As Long Dim DelNo As String Dim delNos As Long Dim s As Range DelNo = InputBox("削除するデータNOを入力してください") delNos = Val(DelNo) Set s = Sheets("TBマスター").Columns("A").Find(delNos, lookat:=xlWhole) If DelNo = "" Then Exit Sub ElseIf s Is Nothing Then MsgBox ("データがありません") Exit Sub Else t = Sheets("TBマスター").Columns("A").Find(delNos, lookat:=xlWhole).Row Rows(t).Delete End If End Sub --------------------------------------------------------- 質問のが悪いかも知れませんが、必要なことがあれば随時追記させてください。 以上、よろしくお願いいたします。

専門家に質問してみよう