プロが教えるわが家の防犯対策術!

いつもお世話になっております。
下記のコードは何年か前にこのサイトで
頂いたコードですが、実行すると
うまく抽出できていないように思います。

わかる方おしえてくれませんでしょうか

画像添付しました。
よろしくお願いいたします。

Sub 商品検索()
Dim dicT As Object
Dim maxrow1 As Long
Dim maxrow2 As Long
Dim sh1 As Worksheet
Dim sh2 As Worksheet
Dim row1 As Long
Dim row2 As Long
Dim key As Variant
Dim t1 As Variant
Dim t2 As Variant
Dim i As Long
Dim sh3 As Worksheet
Set sh3 = Worksheets("Sheet5")
Dim sname() As Variant '
Dim sdate() As Variant '
Dim price() As Variant '
Dim ctr As Long '
Set dicT = CreateObject("Scripting.Dictionary") '
Set sh1 = Worksheets("Sheet1")
Set sh2 = Worksheets("Sheet5")

maxrow1 = sh1.Cells(Rows.Count, 1).End(xlUp).Row '
maxrow2 = sh2.Cells(Rows.Count, 1).End(xlUp).Row '
t1 = Timer
For row1 = 2 To maxrow1
key = sh1.Cells(row1, "A").Value
If key <> "" Then
dicT(key) = row1 '
End If
Next
ctr = 0

For row2 = 2 To maxrow2
key = sh2.Cells(row2, "A").Value
ReDim Preserve sname(ctr)
ReDim Preserve sdate(ctr)
ReDim Preserve price(ctr)
If dicT.exists(key) = True Then
row1 = dicT(key)
sname(ctr) = sh1.Cells(row1, "B").Value '
sdate(ctr) = sh1.Cells(row1, "C").Value '
price(ctr) = sh1.Cells(row1, "D").Value '
Else
sname(ctr) = ""
sdate(ctr) = ""
price(ctr) = ""
End If
ctr = ctr + 1
Next

For i = 0 To ctr - 1
sh3.Cells(i + 1, 5).Value = i
sh3.Cells(i + 1, 2).Value = sname(i)
sh3.Cells(i + 1, 3).Value = sdate(i)
sh3.Cells(i + 1, 4).Value = price(i)
Next
End Sub

「連想配列」の質問画像

A 回答 (2件)

こんばんは



なんだかわざわざ複雑になるように作成されている様なので、よくわかりませんけれど・・・

Sheet1のA列の値は重複することがないと保証されているのでしょうか?
(ご提示のコードは、その仮定のもとに作成されているようなので…)
であるなら、Dictionaryも配列も不要だと思われます。

以下は、その前提での回答です。
ご提示のコードの内容は、Sheet5のA列の各行について、
 ・A列の値を、Sheet1のA列から検索
 ・ヒットした行のデータをコピペ
 (ヒットしなければ空白に)
という、単純なループ処理だけで足りるものと思われます。


>うまく抽出できていないように思います。
原因は、ご提示のコードで、
配列に(一旦)記録する際の添え字(=ctr)が、行数(=row2)とはずれていますが、出力する際に、それをきちんと調整・反映していないので、Sheet5で行の位置がずれてしまっているだけだと思われます。

同じ行のデータを書き写すだけなので、わざわざ値を配列に記憶しなくても、直接記入してしまえば配列は不要になります。
また、元データの総数は事前にmaxrow2で分かっているので、ループの中で毎回ReDim Preserveを行うのも無駄と言えます。

Dictionaryは検索値に合致する行を求めるのに利用していますが、keyに当たる値はSheet1のA列に並んでいるので、直接そこからFindなどで探してしまえば、Dictionaryそのものも不要になります。

処理速度を上げるために、メモリ上で処理したいような場合は、最初に
 data = Worksheets("Sheet1").Range("A1:D" & maxrow1).Value
としてメモリに取り込んでしまい、後はメモリ上で全て処理してしまうという方法も考えられます。


まったく別の発想で処理しても良いのなら・・・
ご提示のコードの内容は、通常のシートでのVLOOKUP関数利用の処理と全く同じ内容ですので、
 ・Sheet5の範囲に関数をセット
 ・値をペーストで固定値に変換
というロジックにしてしまえば、同じ処理を10行程度の記述で済ますことも可能であろうと想像します。
(実質的な計算を、ほとんどエクセルに行ってもらう方法とも言えます)
    • good
    • 1
この回答へのお礼

ありがとうございます。
VLOOKUP風のDictionaryだとばっかり
思っていました。
ありがとうございます。

お礼日時:2021/02/18 08:23

何か最近の物のように思いますが、気になっているのは変数の宣言が多すぎてわかりにくいって初級者は感じます。


なのでその後使う際にややこしくなるのかなと。

確かに20年程前ですとありがちなコードでしたが、当時からベテラン回答者さんがわかりやすく纏めた書き方をされてました。
検索して見つけた際には書かれた日付も気にされた方が宜しいのかも。
    • good
    • 0
この回答へのお礼

ありがとうございます。
VLOOKUP風のDictionaryだとばっかり
思っていました。
ありがとうございます。

お礼日時:2021/02/18 08:23

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!