Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


9753 / 13644 ツリー ←次へ | 前へ→

【25611】データ検索について えくせーる 05/6/8(水) 9:52 質問[未読]
【25612】Re:データ検索について IROC 05/6/8(水) 10:06 回答[未読]
【25613】Re:データ検索について えくせーる 05/6/8(水) 10:13 発言[未読]
【25632】Re:データ検索について ちゃっぴ 05/6/8(水) 23:09 回答[未読]
【25634】Re:データ検索について ちゃっぴ 05/6/9(木) 0:08 発言[未読]
【25635】Re:データ検索について ちゃっぴ 05/6/9(木) 0:19 発言[未読]
【25630】Re:データ検索について MokoMoko 05/6/8(水) 19:57 回答[未読]
【25636】Re:データ検索について ichinose 05/6/9(木) 7:38 発言[未読]

【25611】データ検索について
質問  えくせーる  - 05/6/8(水) 9:52 -

引用なし
パスワード
   ForやLoop等を使用しないで、A列のあるデータを検索し、
なおかつその行番号を取得したいのですが、何か良い方法があったらおしえてください。

●理由
For文を使用しているのですが、VBAの実行速度が遅い。

例)
A列の「いちご」を検索して

4と7の行番号を取得したい。(合致するデータが複数ある場合にも対応)

行 |  A列
−−−−−−−−
1 | りんご
2 | みかん
3 | すいか
<4>| <いちご>
5 | メロン
6 | なし
<7>| <いちご>
8 | レモン
9 | ぶどう
10 | メロン

【25612】Re:データ検索について
回答  IROC  - 05/6/8(水) 10:06 -

引用なし
パスワード
   ループしたくない理由は何ですか?

フィルタして可視セルをループするのが簡単ですが。
もしくは、Findメソッド(FindNextを使うのでループは必要)

【25613】Re:データ検索について
発言  えくせーる  - 05/6/8(水) 10:13 -

引用なし
パスワード
   ▼IROC さん:
>ループしたくない理由は何ですか?
>
>フィルタして可視セルをループするのが簡単ですが。
>もしくは、Findメソッド(FindNextを使うのでループは必要)


回答ありがとうございます。

アウトプットのデータが複数ある以上、ループ使わないとダメですね^^;

Vlookup的というかSQL的というか、(わかりにくいかも?)
負担が少なく速い方法が知りたいです。

Findメソッドを調べてみたいと思います。

【25630】Re:データ検索について
回答  MokoMoko  - 05/6/8(水) 19:57 -

引用なし
パスワード
   ▼えくせーる さん:
今晩は。ForやLoop無しでは一寸分かりませんが、できる限り
シンプルにしてみましたが・・・

>ForやLoop等を使用しないで、A列のあるデータを検索し、
>なおかつその行番号を取得したいのですが、何か良い方法があったらおしえてください。
>
>●理由
>For文を使用しているのですが、VBAの実行速度が遅い。
>
>例)
>A列の「いちご」を検索して
>
>4と7の行番号を取得したい。(合致するデータが複数ある場合にも対応)

Sub FindRow()
 Dim i As Long
 Dim k As Long
 Dim L As Long
i = 1
k = Cells(65536, 1).End(xlUp).Row
  For L = i To k
   I f Cells(L, 1).Value = "いちご" Then
     MsgBox "「いちご」の行は" & L & "です"
   End If
  Next
End Sub

【25632】Re:データ検索について
回答  ちゃっぴ  - 05/6/8(水) 23:09 -

引用なし
パスワード
   >アウトプットのデータが複数ある以上、ループ使わないとダメですね^^;
>
>Vlookup的というかSQL的というか、(わかりにくいかも?)
>負担が少なく速い方法が知りたいです。

今回の場合は、LoopがBottleneckになっているのではなく、
Loop内でObject Accessを行っているからです。

配列に置き換えてやるだけで、大幅なSpeedUpが望めるでしょう。

ついでに検索とのことですが、DataがSortされていれば、
2分探索を使用すれば、ものすごく速くなりますね。

Worksheet Functionでは、Matchの第3引数に1(-1)を
指定してやると2分探索になります。

まあ、この程度のAlgorithm一度、自分で書いてみるほうが
勉強にはなるかと思いますが・・・

【25634】Re:データ検索について
発言  ちゃっぴ  - 05/6/9(木) 0:08 -

引用なし
パスワード
   Sample です。

Const END_ROW As Long = 1000&

' これを実行
Sub Main()
  Dim i As Long
  
  For i = 1 To 5
    Debug.Print F_CallTest("test" & i)
  Next
End Sub

' Test呼び出し
Function F_CallTest(strProcedure As String) As String
  Dim curTime As Currency
  Dim i    As Long
  
  curTime = Timer
  For i = 1 To END_ROW
    Application.Run strProcedure, Cells(i, 1)
  Next
  
  F_CallTest = strProcedure & vbTab & CCur(Timer) - curTime
End Function


' Data作成
Sub SetData()
  Dim lngData()  As Long
  Dim i      As Long

  ReDim lngData(1 To END_ROW, 1 To 1)
  
  For i = 1 To END_ROW
    lngData(i, 1) = "hogehoge" & i
  Next
  
  Cells(1, 1).Resize(END_ROW).Value = lngData
End Sub

' For 〜 Next Loop 順次検索
Sub test1(rngTarget As Excel.Range)
  Dim strTarget  As String
  Dim i      As Long
  
  strTarget = rngTarget.Value
  
  For i = 1 To END_ROW
    If Cells(i, 1).Value = strTarget Then Exit For
  Next
End Sub

' For Each 〜 Next Loop 順次検索
Sub test2(rngTarget As Excel.Range)
  Dim objTarget  As Excel.Range
  Dim strTarget  As String
  Dim i      As Long
  
  strTarget = rngTarget.Value
  
  For Each objTarget In Cells(1, 1).Resize(END_ROW)
    If objTarget.Value = strTarget Then Exit For
  Next
End Sub

' 配列 順次検索
Sub test3(rngTarget As Excel.Range)
  Dim strTarget  As String
  Dim vntData   As Variant
  Dim vntbuf   As Variant
  Dim strBuf   As String
  Dim i      As Long
  
  vntData = Cells(1, 1).Resize(END_ROW).Value
  strTarget = rngTarget.Value
  
  For Each vntbuf In vntData
    If vntbuf = strTarget Then Exit For
  Next
End Sub

' Find Method 順次検索
Sub test4(rngTarget As Excel.Range)
  Dim strTarget  As String
  Dim rngResult  As Excel.Range
  
  strTarget = rngTarget.Value
  With Cells
    Set rngResult = .Item(1).Resize(END_ROW).Find( _
      What:=strTarget, After:=.Item(1), LookIn:=xlFormulas, _
      LookAt:=xlWhole, SearchOrder:=xlByRows, _
      SearchDirection:=xlNext, MatchCase:=True)
  End With
End Sub


' Match 2分探索
Sub test5(rngTarget As Excel.Range)
  Dim vntResult As Variant
  
  vntResult = Application.Match( _
    rngTarget, Cells(1, 1).Resize(END_ROW), 1)
End Sub

【25635】Re:データ検索について
発言  ちゃっぴ  - 05/6/9(木) 0:19 -

引用なし
パスワード
   あ、重複があるんですね。

でしたら、AutoFilter使ってやるほうが簡単でしょう。

ただ、何で行番号を取得する必要があるの?
という疑問は残りますが・・・

行番号を取得したとして、それだけでは処理が完結するとは
思えないので、その後何をするのでしょう。

それによっては、行番号を取得すること自体が意味ないです。

【25636】Re:データ検索について
発言  ichinose  - 05/6/9(木) 7:38 -

引用なし
パスワード
   ▼えくせーる さん:
おはようございます。
間違いがあったので、再送です。


>ForやLoop等を使用しないで、A列のあるデータを検索し、
>なおかつその行番号を取得したいのですが、何か良い方法があったらおしえてください。
>
>●理由
>For文を使用しているのですが、VBAの実行速度が遅い。
>
>例)
>A列の「いちご」を検索して
>
>4と7の行番号を取得したい。(合致するデータが複数ある場合にも対応)
>
>行 |  A列
>−−−−−−−−
>1 | りんご
>2 | みかん
>3 | すいか
><4>| <いちご>
>5 | メロン
>6 | なし
><7>| <いちご>
>8 | レモン
>9 | ぶどう
>10 | メロン

例のようにA1からデータが入っているとして、
コードは、「いちご」を検索し、その行番号をC列に表示します。
尚、B列は、作業列として使用しています。
'============================================================
Sub test()
  moji = "いちご"
  Set rng = Range("a1", Cells(Rows.Count, 1).End(xlUp))
  With rng
   .Offset(0, 1).Formula = "=if(rc[-1]=""" & moji _
              & """,row(),"""")"
   ' 数式は 「=if(rc[-1]="いちご",row(),"")」がはいる
   On Error Resume Next
   Set ans = .Resize(, 2).SpecialCells(xlCellTypeFormulas, xlNumbers)
   If Err.Number = 0 Then
     ans.Copy
     Range("c1").PasteSpecial xlPasteValues
     Application.CutCopyMode = False
     End If
   On Error GoTo 0
   .Offset(0, 1).Value = ""
   End With
End Sub

こんな方法だとループコードを書かなくてもOKですが、
上記のコードはアルファベットの大文字と小文字の区別はしませんから
これの区別も必要なら、コード中の数式を変更しなければなりません。

尚、Findメソッドも有効な方法だと思いますが、

文字列の検索の場合、
例えば、A列に「苺」というデータが入力されていた場合、
「いちご」で検索しても「苺」を検索してしまうので注意が必要です。
(これで都合の良い場合もありますし、逆もあると思います)
Findは、フリガナも検索してしまうから・・・。

9753 / 13644 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free