質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

3回答

3199閲覧

vba 再帰呼び出し 初期化

yakumo02

総合スコア103

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2020/08/06 06:07

以下のコードは、あるフォルダのサブフォルダを取得して、サブフォルダの中にあるファイルを全て取得します。
その後、取得したファイル名をエクセルに貼り付けます。
貼り付け時は.a=55 Cells(a, 1)として、aの値を更新して55行目から行を1行づつずらして56行、57行と、貼り付けたいと思っています。
しかし、サブフォルダを取得するときに再帰を使っているので、毎回aの値が55に初期化させてしまい、55行目にしか貼り付けることができません。
aの値を更新して貼り付けたいです。
ご教授お願いします。

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 file_path = "C:\Users******\Desktop****" book = Dir(file_path & "*テスト.xls*") a = 55 'エクセルファイル取得 For Each File In FSO.GetFolder(path).Files If File.Name = Dir(path & "*テスト.xls*") Then 'ここで貼り付け Workbooks(book).Worksheets("Sheet1").Cells(a, 1) = File.Name End If Next File End Sub

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ExcelVBA

1Option Explicit 2 3'Microsoft Scripting Runtimeを参照設定して使用すること 4Dim mFSO As FileSystemObject 5Dim mRng As Range 6 7Sub test() 8 Dim strFolder As String 9 Dim ix As Long 10 11 'フォルダー選択指定 12 If GetFolderPath(strFolder) = False Then Exit Sub 13 '書き出しセル初期値 14 Set mRng = Workbooks(Workbooks.Count).Worksheets(1).Range("A55") 15 'FSO取得 16 Set mFSO = New FileSystemObject 17 18 'ファイルフルパス一覧取得 19 GetFileList mFSO.GetFolder(strFolder), ix 20End Sub 21 22'フォルダの選択 23Private Function GetFolderPath(ByRef sPath As String) As Boolean 24 With Application.FileDialog(msoFileDialogFolderPicker) 25 .InitialFileName = ThisWorkbook.Path 26 .AllowMultiSelect = False 27 .Title = "フォルダの選択" 28 If .Show = True Then 29 sPath = .SelectedItems(1) 30 GetFolderPath = True 31 End If 32 End With 33End Function 34 35'ファイル一覧取得(サブフォルダ含む) 36Private Function GetFileList(ByVal objFolder As Folder, ByRef i As Long) As Boolean 37 Dim fo As Folder 38 Dim fi As File 39 40 For Each fo In objFolder.SubFolders 41 GetFileList fo, i 42 Next 43 44 For Each fi In objFolder.Files 45 If mFSO.GetExtensionName(fi) Like "xls?" Then 46 i = i + 1 47 With mRng(i, 1) 48 .Worksheet.Hyperlinks.Add Anchor:=.Cells, _ 49 Address:=fi.Path, _ 50 TextToDisplay:=fi.Name 51 End With 52 End If 53 Next 54End Function 55 56

僕なら
Private Function GetFileList(ByVal sPath As String, ByRef i As Long) As Boolean
のように、セルの相対位置の値を、
次の呼び出すプロシージャに受け渡していきますかね。

あと、単にファイル名を一覧にしても、どこのフォルダーにあるかわからないので、
ハイパーリンクを挿入して、見つけたファイルを直接開けるようにしてみました。

それから、FSOを何度も取得したり開放したりすることは無駄かなと、
モジュールレベルで使えるように変数を宣言してみました。
もちろんセルの位置もモジュールレベルで宣言してもいいかと思います。

あと、同じ値を得るために同じDir関数を使うのも無駄です。
書いてるのは一言だけど、VBAで書いてないので見えないけど、
誰かが書いたプログラムを呼び出していることになるので、
同じ値を使うときは、変数に値を1回保持して、それを使いまわすといいと思います。

あと、せっかくFSOを使っているので、どうせならFSOをフル活用してもいいかなと思いました。
Dir関数の方が処理は速いらしいですが、コードを書くのに
FSOの方が使い便利がいいので。

※簡単な動作確認はしてますが、
もれなくリストアップされるかは確認してませんので、
間違いがないか自己責任でお願いします。

※コードに不具合があったので修正しました。

投稿2020/08/06 09:05

編集2020/08/07 01:15
mattuwan

総合スコア2163

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yakumo02

2020/08/07 01:53 編集

ご丁寧にご回答ありがとございます。 こちらの書き方も勉強していこうと思いますが、radames1000さんとのコメントの方も見ていただけないでしょうか?
yakumo02

2020/08/07 02:02

すみません、以上は解決しました。
yakumo02

2020/08/07 02:04

とてもご丁寧な対応ありがとうございました!
guest

0

こんな感じではどうでしょうか。

VBA

1Option Explicit 2' 3Private pstrMyPath As String 4Private plngLayer As Long 5Private plngRowCount As Long 6' 7Function Test_Sample_Miniature() 8 pstrMyPath = "C:\test" 9 plngRowCount = 54 10 plngLayer = 0 11 Call 自己参照(pstrMyPath, plngLayer) 12End Function 13' 14'*********************************************** 15' <自己参照> 16'*********************************************** 17Function 自己参照(ByVal MyPath As String, ByVal intLayer As Integer) 18 Dim fs As Object 19 Dim MyFolders As Object 20 Dim MyFiles As Object 21 Dim fsObj As Object 22 Dim MyObj As Object 23 intLayer = intLayer + 1 24 Set fs = CreateObject("Scripting.FileSystemObject") 25 Set fsObj = fs.GetFolder(MyPath) 26 For Each MyObj In fsObj.SubFolders 27 plngRowCount = plngRowCount + 1 28 Cells(plngRowCount, intLayer + 0) = MyObj.Name 29 Cells(plngRowCount, intLayer + 1) = MyObj.DateCreated 30 Cells(plngRowCount, intLayer + 2) = MyObj.DateLastAccessed 31 Cells(plngRowCount, intLayer + 3) = MyObj.DateLastModified 32 Call 自己参照(MyObj.Path, intLayer) 33 Next 34 For Each MyObj In fsObj.Files 35 plngRowCount = plngRowCount + 1 36 Cells(plngRowCount, intLayer + 0) = MyObj.Name 37 Cells(plngRowCount, intLayer + 1) = MyObj.DateCreated 38 Cells(plngRowCount, intLayer + 2) = MyObj.DateLastAccessed 39 Cells(plngRowCount, intLayer + 3) = MyObj.DateLastModified 40 Next 41 Set fs = Nothing 42End Function

(参考資料)
https://teratail.com/questions/281147

投稿2020/08/06 07:08

編集2020/08/06 07:42
tosi

総合スコア553

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yakumo02

2020/08/07 01:53

ご丁寧にご回答ありがとございます。 こちらの書き方も勉強していこうと思いますが、radames1000さんとのコメントの方も見ていただけないでしょうか?
yakumo02

2020/08/07 02:02

すみません、以上は解決しました。
yakumo02

2020/08/07 02:04

とてもご丁寧な対応ありがとうございました!
guest

0

ベストアンサー

前々回の質問でhatena19さんが紹介してくださった
サブフォルダを含めてファイル一覧を取得する(Dir関数の再帰呼び出し):Excel VBA|即効テクニック|Excel VBAを学ぶならmoug
を最後まできちんと読めばわかりますよ。


下記が参照URLに記載の内容の一部です。

VBA

1Sub Test() 2  cnt = 0 3  Call Sample3("C:\Work") 4End Sub

cntをここで初期化し、Sample3に進んでいます。
この例ではcnt=54とすれば次から1を足されていくのでご希望のものになると思います。

投稿2020/08/06 06:17

編集2020/08/06 23:58
radames1000

総合スコア1925

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yakumo02

2020/08/06 07:53 編集

失礼しました 誤記です
yakumo02

2020/08/06 08:44

すみません、やはりa=55をどこに記述すればいいのかが分かりません whileの中に記述しても当然毎回初期化されます
yakumo02

2020/08/07 01:48

編集ありがとうございます 以下のようにしたのですが、プロシージャが違うのか何も書き込まれません Sub sample() a = 55 Call FileSearch("C:\Users\xxxxxx\Documents\Document\xxxxx") End Sub Sub FileSearch(path As String) Dim FSO As Object, Folder As Variant, File As Variant, buf As String Set FSO = CreateObject("Scripting.FileSystemObject") buf = Dir(path & "*???.xls*") _ For Each Folder In FSO.GetFolder(path).SubFolders Call FileSearch(Folder.path) Next Folder Do While buf <> "" a = a + 1 ThisWorkbook.Worksheets("Sheet2").Cells(a, 1) = buf buf = Dir() Loop End Sub
yakumo02

2020/08/07 02:03

すみません、グローバル変数を宣言していませんでした
yakumo02

2020/08/07 02:04

とてもご丁寧な対応ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問