Excel VBA質問箱 IV

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

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


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

【32701】条件付でVLOOKUP関数を適用する mai×2 05/12/21(水) 1:21 質問[未読]
【32702】Re:条件付でVLOOKUP関数を適用する Kein 05/12/21(水) 2:47 回答[未読]
【32703】Re:条件付でVLOOKUP関数を適用する Kein 05/12/21(水) 2:52 発言[未読]
【32704】Re:条件付でVLOOKUP関数を適用する Kein 05/12/21(水) 2:59 発言[未読]
【33265】おそくなってしまい、大変申し訳ございませ... mai×2 06/1/6(金) 12:47 お礼[未読]

【32701】条件付でVLOOKUP関数を適用する
質問  mai×2  - 05/12/21(水) 1:21 -

引用なし
パスワード
   初めまして。
最近ExcelVBAでのアプリケーション開発の仕事を始めた者です。
アルゴリズムというか、フローは思いつくのですが、
どういう関数やコードをどのように使うの、というところが追いついていません。
日々、ヘルプとネットで奮闘中です。

早速ですが、お知恵を拝借したいことがございます。
例えば学校や塾で成績の一覧表を作成する時なのですが...

Sheet1がデータ入力シート
sheet2がマスター定義シートです。

sheet2の構造は、
ID|学年|クラス|氏名 となっています。
そしてSheet1に成績データを取り込んで集計を行うのですが、
sheet1のA列に生徒のIDが入るので、
B列→学年
C列→クラス
D列→氏名
の各データを、sheet2のマスターからもってきます。
ここまでならVLOOKUP関数を使えばできるのですが、
成績データ側に、マスター上存在しないIDデータが含まれることがあります。
このようなときには、D列に「該当ナシ」と表示されるようにしたいのです。
(B,C列は空白)

VLOOKUP関数だけでは不可能だと思い、
「sheet1A列の入力データがsheet2A列に存在する個数」
を返すユーザ定義関数(仮にstrFindと名づけます)を作成し、
StrFind関数の結果が1以上になった場合はVlookup関数で引っ張ってきたデータを表示、
結果が0になった場合は「該当ナシ」(B,C列は空白)という表示をさせようと考えているのですが、
もし、もっと効率のよい方法がありましたらご教授いただければ幸いです。
よろしくお願いいたします。

(Ver.情報)
OS:WinXP Pro(SP2)
Excel:Excel2000

【32702】Re:条件付でVLOOKUP関数を適用する
回答  Kein  - 05/12/21(水) 2:47 -

引用なし
パスワード
   そーいう処理なら、VLOOKUP関数とかFunctinプロシージャを使わなくても、普通の
マクロ(Subプロシージャ)でやった方が軽いし簡単です。コードは↓こんな感じです。
    
Sub Get_MyData()
  Dim Sh1 As Worksheet, Sh2 As Worksheet
  Dim C As Range
  Dim Rnm As Long

  Set Sh1 = Worksheets("Sheet1")
  Set Sh2 = Worksheets("Sheet2")
  Sh1.Range("B:D, AA:AA").ClearContents
  With Sh1.Range("A2", Sh1.Range("A65536").End(xlUp)).Offset(, 26)
   .Formula = _
   "=IF(ISNA(MATCH($A2,Sheet2!$A:$A,0)),FALSE,MATCH($A2,Sheet2!$A:$A,0))"
   On Error Resume Next
   Intersect(.SpecialCells(3, 4).EntireRow, Sh1.Range("D:D")) _
   .Value = "該当なし !"
   On Error GoTo 0: On Error GoTo ELine
   For Each C In .SpecialCells(3, 1)
     Rnm = C.Value
     C.Offset(, -25).Resize(, 3).Value = _
     Sh2.Range(Sh2.Cells(Rnm, 2), Sh2.Cells(Rnm, 4)).Value
   Next
ELine:
   .ClearContents
  End With
  Set Sh1 = Nothing: Set Sh2 = Nothing
End Sub 

* Sheet1 の1行目は項目という前提にしていますが、もしデータが入力されて
いるのなら

With Sh1.Range("A1", Sh1.Range("A65536").End(xlUp)).Offset(, 26)
   .Formula = _
   "=IF(ISNA(MATCH($A1,Sheet2!$A:$A,0)),FALSE,MATCH($A1,Sheet2!$A:$A,0))"

というように修正して下さい。
なおご覧のとおり、このコードは数式をセルに埋めて判定する形になってますが、
MATCH関数はVLOOKUP関数に比べて軽いので、データ数が増えるほど差が出るはず
です。しかも VLOOKUPなら B〜D列の全てのセルに入力する必要があるため、
なおさら重くなる、と判断しています。ま、普通のマクロにするなら数式を使った
コードにしなくても出来るのですが、そのへんは微妙な問題で、数式による判定も
適切に行えば速度が期待できるため、あえてこのようなコードを組んでみた
というわけです。

【32703】Re:条件付でVLOOKUP関数を適用する
発言  Kein  - 05/12/21(水) 2:52 -

引用なし
パスワード
   あ、すいません。もし1行目が項目なら
>Sh1.Range("B:D, AA:AA").ClearContents
では項目も一緒に消してしまうことになるので

Sh1.Range("B2:D65536, AA:AA").ClearContents

に修正しておいて下さい。

【32704】Re:条件付でVLOOKUP関数を適用する
発言  Kein  - 05/12/21(水) 2:59 -

引用なし
パスワード
   んーと・・さらに数式を簡素化することも追加して

Sub Get_MyData()
  Dim Sh1 As Worksheet, Sh2 As Worksheet
  Dim C As Range
  Dim Rnm As Long

  Set Sh1 = Worksheets("Sheet1")
  Set Sh2 = Worksheets("Sheet2")
  Sh1.Range("B2:D65536, AA:AA").ClearContents
  With Sh1.Range("A2", Sh1.Range("A65536").End(xlUp)).Offset(, 26)
   .Formula = "=MATCH($A2,Sheet2!$A:$A,0)"
   On Error Resume Next
   Intersect(.SpecialCells(3, 16).EntireRow, Sh1.Range("D:D")) _
   .Value = "該当なし !"
   On Error GoTo 0: On Error GoTo ELine
   For Each C In .SpecialCells(3, 1)
     Rnm = C.Value
     C.Offset(, -25).Resize(, 3).Value = _
     Sh2.Range(Sh2.Cells(Rnm, 2), Sh2.Cells(Rnm, 4)).Value
   Next
ELine:
   .ClearContents
  End With
  Set Sh1 = Nothing: Set Sh2 = Nothing
End Sub 

何が変わったかと言いますと、#N/Aエラーはエラーとして表示させ、SpecialCells
メソッドの第二引数で、そのエラーのセルを検出するようにしたのです。これで先の
コードより少しすっきりしますね。

【33265】おそくなってしまい、大変申し訳ございま...
お礼  mai×2  - 06/1/6(金) 12:47 -

引用なし
パスワード
   keinさんへ

ご回答いただき、ありがとうございました。
しばらくパソコンから遠ざかっていたためご挨拶が遅れ、
大変失礼いたしました。

ご指導いただいたとおりMatch関数の方が、
データ件数が多いときには負荷が軽くていいですね。
それにユーザーにシートをいじらせる場合には、
なるべくシートに関数そのものを埋め込まない方が安全ですので、
ご教授頂いたとおり組み直しました。

ありがとうございました。

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