
以下のSample1
とSample2
はどちらもC:\Temp
のサブディレクトも含めたファイル一覧を取得する関数です。
Sample1
は'Sample2'よりも実行時間が短いですが、コマンドプロンプトが表示されてしまいます。
質問①Sample1
でコマンドプロンプトを画面表示させない方法はありますか?
質問②Sample1
,Sample2
以外に素早くファイル一覧を取得できるような方法はありますか?
Sub Sample1() Dim WSH, wExec, sCmd As String, Result As String Set WSH = CreateObject("WScript.Shell") sCmd = "dir /B /S C:\Temp" Set wExec = WSH.Exec("%ComSpec% /c " & sCmd) Do While wExec.Status = 0 DoEvents Loop Result = wExec.StdOut.ReadAll MsgBox Result Set wExec = Nothing Set WSH = Nothing End Sub
Sub Sample2() Call FileSearch("C:\Temp") End Sub Sub FileSearch(Path As String) Dim FSO As Object, Folder As Variant, File As Variant Set FSO = CreateObject("Scripting.FileSystemObject") For Each Folder In FSO.GetFolder(Path).SubFolders Call FileSearch(Folder.Path) Next Folder For Each File In FSO.GetFolder(Path).Files Debug.Print File.Path Next File End Sub
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
下記のような質問は推奨されていません。
- 質問になっていない投稿
- スパムや攻撃的な表現を用いた投稿
適切な質問に修正を依頼しましょう。
回答5件
1
質問1は分かりません。
質問2は、Sample2は書き方を工夫すれば少し速くできますね。
VBA
1Option Explicit 2 3Sub Sample2() 4 Dim fso As New Scripting.FileSystemObject 5 FileSearch fso.GetFolder("C:\") 6End Sub 7 8Sub FileSearch(ByVal Folder As Scripting.Folder) 9 Dim File As Scripting.File, SubFolder As Scripting.Folder, f As String 10 On Error Resume Next 11 For Each SubFolder In Folder.SubFolders 12 FileSearch SubFolder 13 Next 14 For Each File In Folder.Files 15 f = File.Path 16 Next 17End Sub 18 19’参照設定で Microsoft Scripting Runtime にチェックを入れてください。 20 21’実行結果(C:\ をスキャン。出力はせず変数に格納するのみ。) 22’オリジナル 849秒 23’改良後 720秒 24 25’改良箇所 26’①参照設定をしてVariantの代わりにその型を使う 27’②引数をByValで渡す 28’③引数でFolderを渡す
VB.NET を使うともっと速くできます。
VB.NET
1Imports System.Collections.Concurrent 2Imports System.IO 3 4Module Module1 5 6 Private FileNameBag As New ConcurrentBag(Of String) 7 8 Sub Main() 9 Dim sw = Stopwatch.StartNew 10 Scan(New DirectoryInfo("C:\")) 11 Dim fileNames = FileNameBag.ToArray 12 Array.Sort(fileNames) 13 Dim scanTime = sw.Elapsed.TotalSeconds 14 sw.Restart() 15 For Each fileName In fileNames 16 Console.WriteLine(fileName) 17 Next 18 Dim outputTime = sw.Elapsed.TotalSeconds 19 Console.WriteLine("ファイル数=" & fileNames.Length & " スキャン時間=" & scanTime & " 出力時間=" & outputTime) 20 Console.ReadLine() 21 End Sub 22 23 Private Sub Scan(directory As DirectoryInfo) 24 Try 25 Parallel.ForEach(directory.GetDirectories, Sub(subDir) Scan(subDir)) 26 For Each file In directory.GetFiles 27 FileNameBag.Add(file.FullName) 28 Next 29 Catch 30 End Try 31 End Sub 32 33End Module 34 35’実行結果 36’ファイル数 358,553個 37’スキャン時間 5.98秒 38’出力時間 16.37秒
上記はサンプルですが、Windows アプリにして、コマンドラインパラメータ経由でスキャンするディレクトリ名を入力し、一時ファイルに結果を出力すればコマンドプロンプトを出さずにVBAから容易に利用できると思います。
投稿2017/07/16 17:49

退会済みユーザー
総合スコア0
0
Sample1 ですが、VBAではなくWindowsの機能を使っているので実行速度は速いですが、マクロとしては
「使わない方がいい」ですね(コードの可読性・セキュリティが低くなる)。
もし出力先を「Debug.Print」にするSample2でしたら、
(前提:ブックのVBEで「ツール」→「参照設定」→「Microsoft Scripting Runtime」にチェックを入れる)
ExcelVBA
1 2Sub Sample2() 3 Call FileSearch("C:\Temp") 4End Sub 5 6Sub FileSearch(Path As String) 7 Dim FSO As New FileSystemObject, Folders As Folders, Folder As Folder, Files As Files, File As File 8 'Set FSO = CreateObject("Scripting.FileSystemObject")→テキストでは 9 '「オブジェクト参照回数の増加により、マクロ実行速度低下の原因」となるとのこと。 10 Set Folders = FSO.GetFolder(Path).SubFolders 11 For Each Folder In Folders 12 ' Call FileSearch(Folder.Path)→自身のプロシージャを再帰呼び出ししているため、 13 '低下の原因となっている。 14 15 For Each File In Folder.Files 16 Debug.Print File.Path 17 Next File 18 19 Next Folder 20 21End Sub
こちらで実験しましたが、実行速度及び結果も問題無いと思います。
いかがでしょうか?
投稿2017/09/19 04:49
総合スコア111
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
0
VBAのDir関数を使って、フォルダー配下を再帰的に呼び出してフォルダー階層を取得するサブルーチン(WalkFolderList)を作ってみました。
Dir関数の使い方については、Dir関数でサブフォルダを取得するで調べるのが良いと思います。
作成した関数は、探索するフォルダーの最上位のフォルダーを"C:\Program Files\Windows NT"のように引数で指定するとその配下のフォルダーをカンマで繫いで表示する。WalkFolderList関数です。
[例]
WalkFolderList("C:\Program Files\Windows NT\で呼び出すとその配下のフォルダーをカンマで繫いで、次のような文字列で返却するものです。
"C:\Program Files\Windows NT,C:\Program Files\Windows NT\Accessories,...
コードは以下のようになります。Dir関数を用いて指定されたパス直下のファイル名やフォルダー名からフォルダー名を抜き出し、新しくそのフォルダー名からパスを作り出し自分自身(WalkFolderList)を呼び出すものです。
Public Function WalkFolderList(ByVal s As String) As String Dim i As Integer Dim v() As String Dim folderList As String Dim buf As String ' 指定されたパスがディレクトリでなかったら何もせずに空文字列を返却する。 If (GetAttr(s) And vbDirectory) = vbDirectory Then WalkFolderList = s Else WalkFolderList = "" Exit Function End If ' 該当フォルダー直下のフォルダーを動的配列の「v」に格納する。 buf = Dir(s, vbDirectory) i = 0 Do While buf <> "" If buf <> "." And buf <> ".." Then If (GetAttr(s & buf) And vbDirectory) = vbDirectory Then ReDim Preserve v(i) v(i) = s & buf i = i + 1 End If End If buf = Dir() Loop If i <> 0 Then '該当フォルダー直下のフォルダーの下にフォルダーがあるか自分自身の関数「WalkFolderList」を呼び出す For i = LBound(v) To UBound(v) WalkFolderList = WalkFolderList & "," & _ WalkFolderList(v(i) & "\") Next i End If End Function
投稿2017/09/18 12:56
総合スコア157
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
0
質問②に対する回答ですが、
FSOよりDirを使った方が、数倍早くなります。
後は、検索用に再帰の関数を作って、
サブディレクトリの中も処理していけば、
指定パス以下、全ファイルのパスが取得できるようになります。
※ある程度のプログラミング技術が必要です。
投稿2017/09/13 02:32
総合スコア1175
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
0
質問1:
Exec()
を使うと、コマンドプロンプトは隠せないようです。
代わりに、Run()
を使うように、と先行事例で書いてありました。
stackoverflow
質問2:
ueiさんの回答(細かくてバッチリですね!)を参照ください。
投稿2017/07/16 21:59
編集2017/07/16 22:18
退会済みユーザー
総合スコア0
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント


退会済みユーザー
2017/07/16 22:10

退会済みユーザー
2017/07/16 22:24

退会済みユーザー
2017/07/16 22:44

退会済みユーザー
2017/07/16 23:08

退会済みユーザー
2017/07/16 23:21
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
関連した質問
Q&A
解決済
条件に一致した行を別のシートにまとめたい
回答1
クリップ0
更新
2023/04/21
Q&A
解決済
ExcelVBA Access操作 リモートサーバーがないか使用できる状態ではありません
回答1
クリップ0
更新
2023/05/09
Q&A
受付中
Accessデータ連携のVBAによるファイル名変更
回答2
クリップ0
更新
2023/04/27
Q&A
解決済
マクロを含むxlsファイルの軽量化
回答2
クリップ0
更新
2023/04/11
Q&A
受付中
あるセルの文字列と一致するセルに色付け
回答3
クリップ1
更新
2023/04/22
Q&A
受付中
VBAで自動メール作成したいのとアクティブセルの行のある列の値を元に色々なセルの値を変数に代入したいです。
回答1
クリップ1
更新
2023/05/16
Q&A
解決済
既存Excelファイルの指定したセルを起点にAccess上のテーブルをエクスポートしたい
回答1
クリップ0
更新
2023/05/08
Q&A
解決済
QueryDefのparameters記述を省略したい
回答1
クリップ0
更新
2023/05/22
同じタグがついた質問を見る
VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
退会済みユーザー
2017/07/16 20:57