アプリ版:「スタンプのみでお礼する」機能のリリースについて

たとえば、下記のVBAコードは在庫数を更新するコードなのですが、ループを回す際にどちらのシートからループさせれば効果的なのでしょうか?

ws1は、商品在庫全てのデータがあり行数は膨大で、
ws2は、その日の注文データが入っており行数は少ないです。

私の考えでは、行数の少ないシートの2行目から値をまず取得し、行数の多いシートでマッチしたものを見つけて在庫処理、そしてその後また行数の少ないシートの3行目の値を取得、行数の多いシートへ、というほうが効率的に思えるのですが。。。処理は正常に行えており問題はないもののふと疑問に思いました。

ちなみに今はやりのAIにこの疑問を問いかけたところ、行数の少ないほうからがよい、との回答を得たすぐあとに、やっぱり行数の多い方からがいいですよねえ、、、と念のために聞いたら、やはり行数の多い方からがよい、との回答で以降その繰り返しになりました。。。

以上につきましてご助言いただけましたら幸いです。
よろしくお願い申し上げます。

以下、サンプルコード

Set wb1 = Workbooks.Open("\\HogePC\hoge_data\在庫表.xlsm")
Set ws1 = wb1.Sheets("総合")
Set ws2 = wb1.Sheets("ABC商店")

' Find the last row in both worksheets
lastRow1 = ws1.Cells(ws1.Rows.count, "U").End(xlUp).Row
lastRow2 = ws2.Cells(ws2.Rows.count, "K").End(xlUp).Row

' Loop through each
For i = 2 To lastRow2
For j = 2 To lastRow1
If ws2.Cells(i, "K").Value = ws1.Cells(j, "U").Value Then
' Check if K and M columns are not empty
If ws2.Cells(i, "K").Value <> "" And ws2.Cells(i, "M").Value <> "" Then
ws1.Cells(j, "AM").Value = ws1.Cells(j, "AM").Value - ws2.Cells(i, "M").Value

' Check if the stock became negative
If ws1.Cells(j, "AM").Value < 0 Then
minStockProductNum = ws1.Cells(j, "U").Value
MsgBox "在庫がマイナスになっています!商品番号:" & minStockProductNum
End If
End If
End If
Next j
Next i

質問者からの補足コメント

  • みなさん、ご回答誠にありがとうございました!

    某AIの回答より的確で納得できほっとしました。
    なるほどそうですよね。結局は両方のシートの全データを読み込むのでどちらを先にしても後にしても同じですよね。

    昨夜、今回の内容をAIに訊ね、そして憔悴し、イライラして関西弁で答えて!と聞いたとき、一度だけ「どっちでもええねん」との短い回答があり、それだけが正しかったようです。。。w

    今回の質問、締め切らさせていただきます。
    ありがとうございました!

      補足日時:2023/03/13 12:57

A 回答 (3件)

同じですよ。



2重ループのデータ数をm,nとします。

mでループしてヒットするまでの検索回数平均=m/2

mでヒット後、nでループしてヒットするまでの検索回数平均=n/2

両方がヒットするのに要する検索回数平均=mn/4

n、mの順序を変えても、両方がヒットするのに要する検索回数平均=mn/4
    • good
    • 0

>ws1は、商品在庫全てのデータがあり行数は膨大で、


>ws2は、その日の注文データが入っており行数は少ないです。

ws1は在庫数の修正がある。
ws2はその日のデータがあり修正の必要はない?

と言う事なら最初にws2のデータをDictionaryオブジェクトに放り込み、その後ws1のループで確認・修正を行なうとか?
無論Dictionaryオブジェクトに放り込む際に重複する項目があるのなら、その個数を先に計算させておくってのは必要かも。
そうすればその日に使った項目数分だけに纏められるし。

ただws1の行数が膨大って曖昧な感じですとちょっとどうなるかな?
おおよそ5万行とか10万行とか目安があると便利だったかも。
    • good
    • 0

こんにちは



それぞれの行数をN、Mとするなら、ご提示のコードの記述方法であれば、どちらをループの外側にしても実行回数はN×M回になるので、ほぼ同じと言えるでしょう。

IDのようなものをキーにしていて、一致する可能性が1回以下というのであれば、ヒットしたらループを抜け出すようにすることで、実行回数を大幅に低減できます。(=効率がよくなる)
その場合は、一覧的なデータを内側にして、見つけたら中断する方が効率的であろうと考えられます。

また、VBAはインタプリタ型なので、検索処理をFINDメソッドやシート関数のMATCH等を用いる方がVBA逐次比較を行うよりも速いことが想像されます。(確認していないので、絶対ではありませんが・・)

あるいは、ご提示のように1行ずつ比較処理を行うにしても、毎回シートの値を読むのは効率的ではありません。(=シートへのアクセスに時間がかかるので)
在庫一覧のキーを変数に読み込んでおいて、メモリ内で比較する方法を用いる方が格段に速くなるはずです。
    • good
    • 0

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