[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『マクロにてINDEX+MATCH関数を使うには』(ガッツ )
A B C D E 1 A級 B級 C級 D級 2 りんご 50 35 20 15 3 バナナ 30 20 15 4 みかん 45 30 20 5 メロン 90 65 50 45 ・ ・ ・ 上記のような表があります。 マクロにてINDEX+MATCH関数を使って別のシートに結果を表示したいのですが、 ご教授いただけたら幸いです。 別のシートにも種類の違いはありますが、同じような表があり、結果は一つのシートに 出すようにしたいのです。 EXCELで作りましたが、一つのシートの結果は出せたのですが、シートが複数あるのでだめでした。 結果は足したり引いたりはしないで、ただ表示させるだけです。 Ver.EXCEL2002です。
VBAでワークシート関数を使うときは、 WorksheetFunctionプロパティを使うと 使用することが出来ます。
使える関数には制限があるので、詳しくはVBAのヘルプを読んで見て下さい。
(INA)
Dim myrange As Range Dim hinmei As Range na = ActiveSheet.Name Set myrange = Worksheets(na).Range("b2:e53") Set hinmei = Worksheets(na).Range("a2:a5") n = Inputbox("状態は?") d = InputBox("品名は?") answer = Application.WorksheetFunction.Index(myrange, Match(n, myrange, 0), Match(d, hinmei, 0)) sheet("結果").select Range("a1") = d Range("a2") = answer
上記のように自分なりに作ってみましたが、やはりエラーとなってしまいます。
いろいろなところを見ましたが、どうしても解かりませんでした。
手直しするとこんな感じでしょうか。 Index関数の行、列の配置が逆でした。 Match関数にもWorkSheetFunctionオブジェクトが必要です。 列の特定の部分で変数MyrangeはNGですね。等級見出しtoukyuの変数も追加。 Dim myrange As Range Dim hinmei As Range Dim toukyu As Range Dim n As String, d As String Dim answer As Double na = ActiveSheet.Name Set myrange = Worksheets(na).Range("b2:e53") Set hinmei = Worksheets(na).Range("a2:a5") Set toukyu = Worksheets(na).Range("B1:E1") n = InputBox("状態は?") d = InputBox("品名は?") With WorksheetFunction answer = .Index(myrange, .Match(d, hinmei, 0), .Match(n, toukyu, 0)) End With Sheets("結果").Select Range("a1") = d Range("a2") = answer いかがでしょう。 (KAMIYA)
INPUTBOXで入力後エラーが出てしまいます。 worksheetfunctionクラスのMATCHプロパティを取得できません
となります。
個人的にはこの手のマクロでInputBoxを使用するのは感心しません。 単に数値入力ならあまり問題は発生しませんが、文字列の場合、 単語の入力ミス、全角半角の違い、半角全角スペースの有無など、 ちょっと見ただけではわからない入力ミスですぐ期待通りの動作を しなくなります。今回のエラーもMatch関数中で#N/A!(該当なし) が出ているものと思われますので、入力値とリストのミスマッチが原因 だと推測します。 こちらの検証では正確に入力した場合には動作しますので、前述の 「入力ミス」 「リスト側の全角半角の区別」 「スペースの有無」 をご確認ください。 また、ここまでやっていまさらこう書くのも気が引けなくはありませんが、 このようにInputボックスでは入力値のミスマッチの可能性が非常に 高くなるので、上記以外の方法もご検討されてもよいかと思います。 (シート上でリストボックスからのシート選択、項目選択によって値を検索など) (KAMIYA)
ご指導ありがとうございます。 確かにそうだと思います。 ついでにで申し訳ないのですが、マクロでリストボックスは可能でしょうか?
"結果"シートに配置したコントロールで制御する場合のサンプルです。 "結果"シートに「コントロールツールボックス」より リストボックスをみっつ、コマンドボタンをひとつ、適当な位置へ配置してください。 この際、コントロールの名前がListBox1、ListBox2、ListBox3、CommandButton1 であることを確認してください。 ThisWorkbookオブジェクトへ下記コード Private Sub Workbook_Open() Dim sh As Worksheet If Worksheets("結果").ListBox1.ListCount = 0 Then For Each sh In ThisWorkbook.Worksheets If sh.Name <> "結果" Then Worksheets("結果").ListBox1.AddItem sh.Name End If Next sh End If End Sub "結果"WorkSheetオブジェクトへ同じく下記コード Dim sh As Worksheet Dim MyRow As Long Dim MyCol As Long Private Sub CommandButton1_Click() Dim MyRange As Range, hinmei As Range, toukyu As Range Dim n As String, d As String Dim answer As Double If Me.ListBox2.ListIndex < 0 Or Me.ListBox3.ListIndex < 0 Then MsgBox "リスト未選択です。" Exit Sub End If na = Me.ListBox1.Value Set sh = Worksheets(na) Set MyRange = sh.Range(sh.Cells(2, 2), sh.Cells(MyRow, MyCol)) Set hinmei = sh.Range(sh.Cells(2, 1), sh.Cells(MyRow, 1)) Set toukyu = sh.Range(sh.Cells(1, 2), sh.Cells(1, MyCol)) d = Me.ListBox2.Value n = Me.ListBox3.Value With WorksheetFunction answer = .Index(MyRange, .Match(d, hinmei, 0), .Match(n, toukyu, 0)) End With Range("a1") = d Range("a2") = answer End Sub Private Sub ListBox1_Change() Dim i As Long Dim C As Range For i = ListBox2.ListCount - 1 To 0 Step -1 Me.ListBox2.RemoveItem (i) Next i For i = ListBox3.ListCount - 1 To 0 Step -1 Me.ListBox3.RemoveItem (i) Next i Set sh = Worksheets(ListBox1.Value) MyRow = sh.Range("A2").End(xlDown).Row For Each C In sh.Range("A2:A" & MyRow) Me.ListBox2.AddItem C.Value Next C
MyCol = sh.Range("B1").End(xlToRight).Column For Each C In sh.Range("B1").Resize(1, MyCol - 1) Me.ListBox3.AddItem C.Value Next C End Sub コード登録後、いったん保存して再度ブックを開くと有効になります。 (KAMIYA)
KAMIYA様、大変有難う御座いました。 思うようになりました。 まだまだ勉強不足の自分がかなしいです。 これからもっと勉強していきます。
Set MyRange = sh.Range(sh.Cells(2, 2), sh.Cells(MyRow, MyCol)) Set hinmei = sh.Range(sh.Cells(2, 1), sh.Cells(MyRow, 1)) Set toukyu = sh.Range(sh.Cells(1, 2), sh.Cells(1, MyCol)) の部分の数値を変えなければいけないと思うのですが、 このコードの意味を教えて頂けないでしょうか。 (yasu)
その3ステートメントは次の書式で共通している。 Set Object変数 = Object取得式 Object取得式で取得したオブジェクトへの参照をオブジェクト変数へ格納する。 変数shはモジュールレベルの変数でListBox1_Changeイベントプロシージャでその内容が 取得されている。取得されるのはListBox1の値のシート名を持つシートである。 (なお、Workbook_Openで宣言されているプロシージャレベルの変数shとは直接関係がないが、 双方で変数名が同じであるため、紛らわしい使い方と言える) 変数myRow、myColも同じくモジュールレベルの変数でListBox1_Changeイベントプロシージャで その内容が取得されている。 変数myRowは変数shで取得されているシートのセルA2からEnd(xlDown)で取得できるセルの 行番号が格納される。 変数myColは変数shで取得されているシートのセルB1からEnd(xlToRight)で取得できるセルの 列番号が格納される。 Cells(行番号, 列番号) でそれぞれ行番号、列番号を指定することでRangeオブジェクトを 取得する。 Range(Range1, Range2) でRange1とRange2を対角にもつ矩形範囲を取得する。 モジュールレベル変数はこのケースではとくに必須ではないため、 プロシージャごとに取得すべきものと判断する。 なお、回答中のKAMIYAは2004年時点での私の旧HNである。 であるからして、コードの解説は責任を取らねば(笑 上記説明で分からない場合は、新規に質問してみてもよいかと。 (みやほりん)
>表と行と列の位置が違うだけ ^^^^ とありますが、 >2行づつセルを結合してあります ともありますので、仕様的には「まったく違うレイアウト」です。 適当に数字をいじれば適用できる、という考えでマクロに取り組むなら、 甘いと言わざるを得ません。 もし書いておられるような表の位置関係なら、数箇所の書き換えでは 済みませんし、むしろ違った考え方で作る必要があるように思えます。 私自身は最近はまるごと作ることが時間的にも能力的にも 出来なくなってきていますので、新規質問がいいと思いますよ。 (その場合は、元データの状態を詳しくて維持していただくのがよいと思われます) (みやほりん)
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.