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

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

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

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

Q&A

解決済

3回答

4574閲覧

【VBA】フルパス指定せずにサブフォルダ内のファイルを親フォルダに移動したい

debiranian

総合スコア2

VBA

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

0グッド

0クリップ

投稿2021/10/07 05:50

編集2021/10/07 08:16

前提・実現したいこと

#VBAで複数のサブフォルダ内にあるファイルを上階層のサブフォルダに移動したい。
一番下のサブフォルダ〔item〕内の各ファイルを、サブフォルダ〔A○○○○〕に移動したい。
※イメージ:
〔全てのファイル保存先〕 ※親フォルダ
→〔attached〕 ※都度納品される子フォルダ1
→〔A○○○○〕 ※子フォルダ2。中に1~3個の子フォルダ3が入っている。
→〔attachitem1〕→Excel,〔attachitem2〕→Word,〔attachitem3〕→pdf
※子フォルダ3。中にファイル形式がバラバラなファイルが1つずつ入っている。

※補足:
・〔〕はフォルダを指します。『→』は「中にある」と読んでください。
・〔A○○○○〕および〔attachitem○○〕の○部分は常に変わります。
・〔A○○○○〕は大量にあり、その中にある〔attachitem○○〕は1~3個。

発生している問題・エラーメッセージ

実行時エラー5 プロシージャの呼び出し、または引数が不正です。

該当のソースコード

Sub MoveData() Dim fso As FileSystemObject Dim S_RST As String '移動元 Dim D_RST As String '移動先 Set fso = CreateObject("Scripting.FileSystemObject") S_RST = "\全ての受領データ保存先\attached\A*\attachitem**.*" D_RST = "\全ての受領データ保存先\" fso.MoveFile S_RST, D_RST Set fso = Nothing MsgBox "完了!" End Sub

試したこと

上記の通り、〔A○○○○〕と〔attachitem○○〕は都度名前が変わるため、フルパスで指定することができません。そこでフォルダパスにワイルドカードを使ってみましたが、上手くいきませんでした。
パスを指定せずに〔attached〕から先のサブフォルダ内にあるファイルを検索し、移動させることは可能でしょうか。

補足情報(FW/ツールのバージョンなど)

Windows10 Excel2016を使用しています。

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

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

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

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

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

debiranian

2021/10/07 06:15

ご指摘ありがとうございます。
guest

回答3

0

fso.MoveFileではワイルドカードは使用できないので、エラーです。
事前に、ファイル名を求めて指定します。

参考:

VBA

1dim dirA(100) as string, d as string 2dim dirAN as integer 3 4dirAN=0 5d = Dir("\全ての受領データ保存先\attached\A*", vbDirectory) 6Do While d <> "" 7 dirA(dirAN) = d 8 dirAN = dirAN + 1 9 f = Dir 10Loop

で、dirA(0)dirA(dirAN-1)に、ワイルドカードに該当するディレクトリ名およびファイル名が入ります。

同様に、dir("\全ての受領データ保存先\attached\"+dirA(i)+"\attachitem*",vbDirectory)で次々に求めていきます。
(ワイルドカードは途中の部分には使えません)

別案:
コマンドプロンプトで、dir /s /b \全ての受領データ保存先\attachedを実行すると指定ディレクトリ以下のすべてのファイルがリストアップされます。このリストでいいなら、
VBAから、"cmd /c dir /s /b \全ての受領データ保存先\attached"を実行して、その出力を取ればいいです。

VBA

1Set WSH = CreateObject("WScript.Shell") 2Set cmd = WSH.Exec("cmd /c dir /s /b \全ての受領データ保存先\attached") 3Do While cmd.Status = 0 4 DoEvents 5Loop 6Do Until cmd.StdOut.AtEndOfStream 7 fso.MoveFile cmd.StdOut.ReadLine, D_RST 8Loop

この場合、cmd.exeを実行するのでコマンドプロンプトのウィンドウが一瞬出ます。

投稿2021/10/07 12:47

otn

総合スコア85901

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

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

debiranian

2021/10/08 05:04

ご回答ありがとうございます。 1.VBAの方を試してみたところ、「f=Dir」に「変数が定義されていません。」とエラーが出たため、 「d=Dir()」に書き直してみました。これでお間違いないでしょうか。 2.dirA(i)の部分はdirA(1)という意味でしょうか。 3.DoLoopを"+dirA(i)+"\attachitem*", についても書いてみました。  dをまた使用するとMoveFileを使用する際にdからdに移動するという内容になってしまうと思い、 dをeに書換え、MoveFile e,d にしてみましたが、「5;プロシージャの呼び出し、引数が不正です。」  とエラーになってしまいました(e As String で宣言済み)。 大変申し訳ございませんが、続きも教えていただけないでしょうか。また、この考え方はotn様のアドバイスと異なりますか。よろしくお願いいたします。
debiranian

2021/10/08 05:10

上記の内容は下記のとおりです。 dirAN = 0 d = Dir("\GVSVITFS10\Redirects$\717056\Desktop\ファイル保存先\全ての受領データ保存先\attached\A*", vbDirectory) Do While d <> "" dirA(dirAN) = d dirAN = dirAN + 1 d = Dir() Loop e = Dir("\全ての受領データ保存先\attached" + dirA(1) + "\attachitem*", vbDirectory) Do While e <> "" dirA(dirAN) = e dirAN = dirAN + 1 e = Dir() Loop Set fso = CreateObject("Scripting.FileSystemObject") fso.MoveFile e, d Set fso = Nothing
otn

2021/10/08 10:55 編集

1.あ、すいません。投稿時に「ディレクトリだからfよりdがいいだろう」と書き直そうとして漏れてました。dの間違いです。 2. dirA(1) だけでなく、dirA(0)からdirA(dirAN-1)まで全部についてforで実行しないといけないのでは? ディレクトリは複数あるんですよね? 3.d はdo whileループで一時的に使うだけなので、繰り替えし使ってかまいません。 また、dirA() は、"\全ての受領データ保存先\attached" の下のディレクトリ名を入れる配列なので、 "\全ての受領データ保存先\attached" + dirA(i) の下のディレクトリ名を入れる配列は別途必要です。dirB()など。 fso.MoveFile e, d ?? 移動先は固定では? ただ、Dirを使う方法は、このようにワイルドカードが複数階層にある場合は、面倒なので、どちらかというと、シンプルな別案の方がおすすめです。
debiranian

2021/10/09 00:07

ありがとうございます。 VBAを始めてまだ日が浅く稚拙な質問をしてしまい申し訳ございません。 dirの方で場合分けをするのですね。勉強不足でした。再度試してみます! 別案の方では理解しやすく、簡単に操作できたので感動しました! ありがとうございました! VBA以外の選択肢があることを知ることができてよかったです! ありがとうございました!
guest

0

ベストアンサー

考え方のみですが。

「attached」ファオルダ配下に「A○○○○」フォルダがあって、 これが対象となるのでしたら、FileSystemObjectオブジェクトで「A○○○○」フォルダを検索する処理からになると思います。
で、以下を参考に知てみてください。

https://www.tipsfound.com/vba/18022

これができたら、次は「A○○○○」フォルダ内の各フォルダのファイルを移動する、という処理になると思います。

投稿2021/10/07 08:54

hex309

総合スコア761

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

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

debiranian

2021/10/07 11:59

ご返事ありがとうございます。 次にファイルを動かすにあたってMoveFileを使うものと考えられますが、ここでパス指定をしなければならないため行き詰まっております。 フルパス指定の代わりとなるような書き方はございますか。 よろしくお願いします。
hex309

2021/10/07 12:37 編集

移動するファイルに対してはワイルドカードが使用できますが、移動先のフォルダは使用できません。 ループではダメなのですか?
debiranian

2021/10/08 05:17

ありがとうございます。 ループを使用したのちにどのようにしてソースパスとディスティネーションパスを指定するのかがわかりません。おそらく、2階層に渡るためループを2度繰り返すものと思われますが、その次にどのようにして2階層目のループ内を書くかで行き詰っております。 申し訳ございません。もう少しよろしくお願いします。
debiranian

2021/10/08 05:27

Sub Movedata2() Dim fso As FileSystemObject Set fso = New FileSystemObject Dim pfl As Folder Set pfl = fso.GetFolder("\GVSVITFS10\Redirects$\717056\Desktop\ファイル保存先\全ての受領データ保存先") Dim fl As Folder Dim flfl As Folder Dim flflfl As String For Each fl In pfl.SubFolders For Each flfl In fl.SubFolders fso.MoveFile(flfl.Path & "*.xlsx" ,"\全ての受領データ保存先\")   fso.MoveFile(flfl.Path & "*.doc" ,"\全ての受領データ保存先\") fso.MoveFile(flfl.Path & "*.pdf" ,"\全ての受領データ保存先\") Next Next Set fso = Nothing サイトを参考にして書いてみましたが、やはりfso.MoveFileで引っかかってしまいました。 ディスティネーションは本当は〔A○○○○〕にしたいのですが・・・。
hex309

2021/10/08 05:43

見つかったファイルは親フォルダに入れるんですよね。 以下でいかがでしょう。 ファイルが見つからないとエラーになるので、On Errorステートメントで回避しています。 For Each fl In pfl.SubFolders For Each flfl In fl.SubFolders On Error Resume Next fso.MoveFile flfl.Path & "*.xlsx", fl & "\" fso.MoveFile flfl.Path & "*.doc", fl & "\" fso.MoveFile flfl.Path & "*.pdf", fl & "\" On Error GoTo 0 Next Next
debiranian

2021/10/08 07:10

ありがとうございます。 入れたいのは〔A○○○○〕のフォルダですが、 ディスティネーションの指定が親フォルダまでしかわからなかったので暫定的に指定しました。 いただいたコードをそのまま活用してみたのですが、何故かファイルが移動してくれないです・・・。 恐らくファイルを見つけられていないのだと考えます。しかしどこが悪いのかわかりません。 Set pfl = fso.GetFolder("\全ての受領データ保存先\") fl In pfl.SubFolders flfl In fl.SubFolders は「『pflは\全ての受領データ保存先\まで』ですが、その先のサブフォルダを便宜上fl、さらにその先のサブフォルダをflflと定義します。」という意味で合っていますでしょうか。
hex309

2021/10/08 07:16

フォルダの構造は次のように提示頂いています。 〔全てのファイル保存先〕 ※親フォルダ →〔attached〕 ※都度納品される子フォルダ1 →〔A○○○○〕 ※子フォルダ2。中に1~3個の子フォルダ3が入っている。 となると、変数pflには、 Set pfl = fso.GetFolder("\全ての受領データ保存先\attached\") としないと、「A○○○○」がflにならないですよね。
debiranian

2021/10/08 08:15

動きましたああああああ!!!! ありがとうございます!!! しかし、次はファイル名の変更などがあるので行き詰ったらまたお世話になるかもしれませんが、 よろしくお願いいたします!! ありがとうございました!!
hex309

2021/10/08 08:57

お役に立てて何よりです。 もし、これでOKということであれば、ご質問をク解決済みにしていただければ。
debiranian

2021/10/08 10:32

失礼いたしました。 初投稿そして舞い上がってしまって忘れておりました。 ありがとうございました!!
guest

0

対象フォルダの条件指定が大変であれば、都度選択するのでもよいのでは?

フォルダ選択ダイアログについては以下を参考にしてください。
https://excel-ubara.com/excelvba1/EXCELVBA376.html

投稿2021/10/07 06:22

hex309

総合スコア761

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

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

debiranian

2021/10/07 11:57 編集

ありがとうございます。 実はファイルが膨大な量になるため、手作業はできるだけ避けたいのです。 贅沢で申し訳ありませんが、ワンクリックでなんとかしたいと考えております。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問