
配列(要素1万個)の中を探す時間を短縮するために、1回探し見つかったらその要素を削除し、次に探す際はちょっと短時間で済むようにしたいと思ってます。そのために配列をコレクションに変更しようと思ってます。可能でしょうか?
詳細
商品名が1万個、セルに入力されてます。各商品に該当するファイルを開き、処理後閉じ、次の商品に移ります。開くファイル名は配列に入ってます(要素数1万個)。ファイル名の一部に商品名があるので、これを検索し順次ファイルを開きます。
Dim Files(10000) As String
Dim i as Long, j as Long
’Filesにファイル名を代入する処理が途中にあります
.
For i=2 to Cells(Rows.Count, 1).End(xlUp).Row
Name="*" & Cells(i, 4) & ".txt"
For j=1 to Ubound(Files)
If Name Like Files(j) then
'ファイル開き処理
End if
Next
Next
雰囲気だけで書いてるので、実際と違います。書き間違いで動作しない可能性が高いです。
配列に収めたファイル名があって、セルの商品名に該当するファイル名を配列から探し、開き、処理、閉じるのです。しかしながら所要時間が1個1秒未満程度ですが、結構な時間になります。
質問
配列をコレクションに変更し、1個処理が終わる度にコレクションの要素から削除していけば、探す時間は短縮されると思ったのですが、どうでしょうか?速くなるでしょうか?
No.7ベストアンサー
- 回答日時:
こんにちは。
一応、二分木検索方を知らないわけではありませんが、Excel VBA?で、そのアルゴリズムを使ったことはありませんね。あえてやればできるというだけで、それに代わるものを考えてしまいます。
スピードを比較したわけではありませんから、どちらがどうとは言えませんが、1次元配列で1万個程度なら、ワークシート関数のMatch関数を使うのが速いような気がしますね。Match関数の中身はどうなっているかは知りませんが、二分木(Binary Tree)とは同じ働きをします。それから、Quickソートは、再帰があるから、思ったほどに速くはないはずです。ワークシートのコマンドを利用したほうが速そうです。
>配列をコレクションに変更し、1個処理が終わる度にコレクションの要素から削除していけば、
コレクションというのは、入れ物が大きいオブジェクトですから、数が増えれば、その分重くなるはずです。オブジェクト群を直接操作するなら可能ですが、そうでないと使う意味はあまりありません。
なお、
sName="*" & Cells(i, 4) & ".txt" 'Name -> sName :プロパティ名を直接変数にしてはいけません。
>If Name Like Files(j) then
Filter(VBA関数, 戻り値が、見つかららない場合は、-1 になる)
Application.Match (ワークシート関数:Application.からダイレクトなのは、エラー値を排除するため。IsError や Vartype : Long で戻り値の有効性を調べる)
No.6
- 回答日時:
× 配列に入れたファイル名をセルに入れて・・・・
〇 ファイル名を格納した配列をソートし・・・・
処理の準備1・・・Excelのセルを参照し配列準備
(1)商品名も配列に。
(2)ファイル名の一部にある商品名を配列に。
(3)ファイル名も配列に。
処理の準備2・・・配列に読み込んだデータをソート
処理の準備3・・・その他の準備
本処理
GoodsCounts = UBound(strGoodsNames())
FileCounts = UBound(strFileNames())
For I=1 TO GoodsCounts
'
' I番目の商品名の処理
'
strGoodsName=strGoodsNames(I)
'
' 商品名に対応するファイル名を検索
'
’-----------------------
' バイナリーサーチ
' -----------------------
' P=検索開始位置
' S=二分木探索変数XXX
' L=二分木探索変数XXX
' M=二分木探索変数XXX
'
・・・・・
・・・・・
’-----------------------
' ファイル処理
' -----------------------
・・・・・
・・・・・
Next I
つまり、EXCEL のセルを参照し配列に読み込むのは準備工程で一回だけです。その後のソートや検索もメモリ上に行います。双方共にソートしておけば、バイナリーサーチの検索ポイントを操作することが可能です。多分、一回の検索に要する時間は1万分の1秒以下だと思いますよ。なお、ファイル処理を上記For-Next文で行うのか、それとも全てを検索後に一括して行うか?これは、後者がお勧めです。まずは、ファイル処理を一括して行うに十分なデータをセルに書き出すか、シーケンシャルファイルとして吐き出すかして成功・不成功を確認。そういうプログラムの単純化がお勧めです。
No.5
- 回答日時:
keyを指定したCollectionオブジェクトを作れば、
「For j=1 to Ubound(Files)
If Name Like Files(j) then
の判定がなくなるでしょう。当然、Loopやクイックソートやバイナリーサーチも不要でしょう。Likeの意味がよく分かりませんが、Itemに重複があるということでしょうか。
また、
「For i=2 to Cells(Rows.Count, 1).End(xlUp).Row」
については、セル範囲をVariant型の変数に一括代入すれば、以降はメモリでの処理になり、シートとのI/Oが減ることでこちらは速くなると期待されます。(数十万件の処理で劇的に速くなったこともあります)
Collectionにすると、処理速度は若干遅くなるはずで、Variant型の変数との比較はやってみないと分からないと思います。
>配列をコレクションに変更し、1個処理が終わる度にコレクションの要素から削除していけば、探す時間は短縮されると思ったのですが
よく試すことがありますが、処理が先頭から順番に行われる場合、逆に末尾から行われる場合。末尾から行われる場合は削除して意味がある? 逆に先頭からの場合は削除にコストがかからないか考える必要があるでしょう。実際のデータを見ないと何とも言えませんね。感覚的にはコレクションならほとんど差がないのではと思います。
実は、質問にある「コレクション」の意味が、「Collectionオブジェクト」なのか「Dictionaryコレクション」なのか判断付きませんでした。個人的には「Dictionaryコレクション」を使っています。当然、ソート不要で削除も可能です(処理効果は分かりませんが)。実際、行ってみるのが一番です。ご参考に。
ありがとうございます。
Likeを使う理由はファイル名がまちまちで、商品名を含むのは確実ですが他の部分が一定してないからです。likeならワイルドカードを使えるからです。重複はありません。
コレクションは過去使ったことが無いので、おそらくオブジェクトだと思います。
まずは商品名の配列への代入を試してみます。そういえば一括で変数代入出来たような記憶があります。
No.4
- 回答日時:
D列に商品一覧を準備
F列にファイル名一覧を(マクロで?その必要があるのかは?)準備
sub macro1()
dim i as long
dim myFile as string
range("F:F").sort key1:=range("F1"), order1:=xlascending, header:=xlno
for i = 2 to range("A65536").end(xlup).row
myfile = application.vlookup("*" & cells(i, "D") & ".txt", range("F:F"),1)
’ファイル開き処理
next i
end sub
まぁ騙されたと思って試してみて下さい。
現実にはブックをイチイチ開く、閉じるの方が遥かにボトルネックになりそうですが。
#あぁ、あと実際の具体的なデータの中身とかナイショなので、カンジだけでこのマクロも書いてるので悪しからず。
ありがとうございます。
ファイル名をソートしてVlookupするのが肝ですね。エクセル関数をVBA上で使用出来るのは初めて知りました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 前回ご教授いただいたコードに覚えたてのループ処理で品名りんごAから順に20回for nextでループ 7 2023/01/13 22:01
- Visual Basic(VBA) vbaのエラー対応(実行時エラー7:メモリが不足しています) 4 2023/04/24 00:20
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
- Visual Basic(VBA) 貼り付けた値が消えていく 以下はソースファイルの2番目のシートのB6から最終行を取得 ターゲットファ 2 2023/07/27 12:23
- Visual Basic(VBA) vbaの構文の修正相談(xmlファイルを順に開いてコピペ作業) 1 2023/04/22 01:18
- Visual Basic(VBA) エクセルVBA(実行時エラー438)の対処法を教えてもらえないでしょうか 3 2023/04/22 13:43
- Visual Basic(VBA) 複数のcsvファイルをExcelに一括変換したい 2 2023/03/03 12:44
- Excel(エクセル) Excel VBAどこが間違ってますか? 4 2023/07/17 10:04
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C#でbyte配列から画像を表示さ...
-
VBA 変数名に変数を使用したい。
-
VBAでMODE関数をつくる
-
Dir関数で読み取り順を操作でき...
-
VB.NETの配列の限界を教えてく...
-
VBA Dowhile 判断条件に動的配...
-
プログラミング関係で質問です。
-
セル範囲から一次元配列の生成
-
7億ある配列を含んだ計算をした...
-
複数の配列変数を1つの配列変数...
-
コンボボックスのインデックス...
-
Excelのメモリ(配列)の上限は2G...
-
【緊急】インクルードファイル...
-
COBOLの基本的な事なので...
-
VBで配列に格納されているデー...
-
VBA: Select Caseを短くしたい
-
ASPのReDim Preserveについて
-
EXCELを使って、アクセスログを...
-
配列のペースト出力結果の書式...
-
C言語によるプログラミング
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBA 変数名に変数を使用したい。
-
vba フィルター 複数条件 3つ以...
-
C#でbyte配列から画像を表示さ...
-
Dir関数で読み取り順を操作でき...
-
エクセルでXY座標に並べられた...
-
配列のペースト出力結果の書式...
-
定数配列の書き方
-
大量の変数を定義するにはどう...
-
構造体配列の特定のメンバーをF...
-
Redim とEraseの違いは?
-
複数のtextboxの処理を一括で行...
-
VB.NETの配列にExcelから読み込...
-
COBOLの基本的な事なので...
-
Excel2010のinputboxで複数デー...
-
VBAでMODE関数をつくる
-
レコードセットの中身を配列に...
-
ReDim PreserveよりもReDimが遅い
-
EXCELを使って、アクセスログを...
-
配列の中の最大値とそのインデ...
-
VB6のメモリ解放に関して
おすすめ情報