- ベストアンサー
エクセル2003VBAで・・・
エクセル2003VBAでダイアログでファイルを複数選択して開くというのは知っているのですが、「フォルダ」を「複数」選択して「フォルダ名」をあるセルに反映させるようにしたいのですが、どのようにすればいいのでしょうか? 例えば、フォルダをダイアログ上で複数選択し、1つ目のフォルダ名をA1セルに反映。2つ目のフォルダ名をA2セルに反映。同様に後もフォルダを選択しただけ、繰り返し・・・。 よろしくお願いします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
>前回のソースでも上手くいったのですが、何が間違っていたのでしょうか? 百聞は一見にしかずということわざを知っていますか? こんばんわ maintec さん。 実際にどっちも動かせばわかります。 …そう言うのは簡単です。実際そうしたほうが賢いですし早いです。 まぁここで百行書くより実行すれば一瞬で違いがわかるのですがあえて書きましょう。 前回の間違っていた場所は mainfolder = Left(myfolder, InStrRev(myfolder, "\")) を下記に変更しました。と私はいいました。 mainfolder = myfolder & "\" 前者はファイルパスからファイルを除いたパスを取得するときに使います。後者は単にフォルダパスに\マークをつけるだけの処理です。 実際のパスだとどうなるでしょうか? C:\Documents and Settings\user\デスクトップ\testfolder がmainfolder変数に格納されていたとします。 すると前者は C:\Documents and Settings\user\デスクトップ\ となり後者は C:\Documents and Settings\user\デスクトップ\testfolder\ とこうなります。 今回の処理ではフォルダ名と連結しているのでひとつ階層が足りなくなってしまいます。 以上です。 今日は随分とmaintecさんと会話した気がします(ついにおやすみなさいから始まりおはよう・こんにちわ・こんばんわと挨拶が一ループしてしまいました。)。 私の暇人さに気づくべきか質問する前に考え調べる事を助言すべきか(まぁ恐らく前者に私は気づくべきでしょう。なぜならソースが完成した時点でこのQNo.4341643は解決済みなのですから)。
その他の回答 (4)
- argument
- ベストアンサー率63% (21/33)
こんにちわ maintec さん そろそろ頭もはっきりして来ました。張っていたデータの間違いに気づいたのがいい例ですね。まぁこれまたどうでもいい前文ですね。 では処理内容を説明します。 '変数の初期化 myfolder = "" 'まぁ標準的なフォルダ選択の手法(きっと検索したほうが早い) 'Application.FileDialogはまぁダイアログ関係表示させるための処理で 'msoFileDialogFolderPickerを渡すことでフォルダ選択にします 'Showは値が格納されたか否かで、ある場合SelectedItemsの第一要素に '選択したディレクトリパスが格納されていますのでそれを変数に入れます With Application.FileDialog(msoFileDialogFolderPicker) If .Show = True Then myfolder = .SelectedItems(1) End If End With 'もしセットした変数の中にフォルダパスが格納されていないならば処理を中断する If myfolder = "" Then Exit Sub '正直これは説明面倒なんで検索してほしいんですが For Each fl In CreateObject("Scripting.FileSystemObject").GetFolder(myfolder).subfolders: fn = fn & fl.Name & "\": Next この処理を初心者でもわかるように噛み砕くと 'FileSystemObjectという技術・オブジェクトを作成 'set fso = CreateObject("Scripting.FileSystemObject") 'さらにそのfsoのフォルダオブジェクトを作成 'set gf = fso.GetFolder(myfolder) 'そして指定フォルダに存在するsubfoldersつまり配下のフォルダを 'for処理でフォルダがある限り処理する 'その際に.nameで名前を取得しそれを\を付けながら全て結合する 'For Each fl In gf.subfolders 'fn = fn & fl.Name & "\" 'next 'ちなみにオブジェクト作成した場合通常破棄する必要があり(なくても大丈夫ですが・・) 'set fso = Nothing:set gf = Nothing 'そして私はこのオブジェクト破棄なども面倒くさいし 'この程度一行で十分だと感じたの長ったらしい式が一行できた訳です 'なぜオブジェクトの破棄がない?それはインスタンス化(オブジェクト作成)をしていないためです 'インスタンスって何ですか?クラス→インスタンス化して通常処理します。 'どうしても知りたいなら検索してください今回の件では 'この構造を完全に理解する必要性はまるでありません。 'さて上記処理で名前を全て取得はできました。 'ですが 名前\名前\名前\ といくと最後に邪魔な\が残るので削除します '邪魔な\を削除し、それをsplitで\区切りに配列化します folderlist = Split(Left(fn, Len(fn) - 1), "\") 'フォルダを配列化しましたが各名前しかありません。言ってる事がわかりますか? 'そうつまり通常は選択するとフルパスが格納されるのにディレクトリが足りません。 'そのため選択したフォルダパスから親ディレクトリが必要です。親パス+\を作成します mainfolder = myfolder & "\" 'さて後は配列のある限りA列にひたすら列挙していくだけの処理です For i = 0 To UBound(folderlist) Range("A" & i + 1).Value = mainfolder & folderlist(i) Next さて各処理が理解できましたか? 正直説明文を書くだけで思いもよなぬ時間がかかりました。 なぜ?それはもちろん貴方がこの処理の何がわからないか書いてないためですもしかしたら私の読解力が足りないのかも知れません(きっと後者でしょう)。 もしそもそも今回の処理全てがわからないのであればもちろん全ての説明は必要だったでしょう。ですがそれでは実装後きっとメンテナンスができないと思われるためなんとも言いがたいですね。 さてそんな事はどうでも良いですね。幾人の回答者がめげずに全てを回答してくれるか程度の問題なのですから。 少し、本当に些細なアドバイスするならば私の回答を待つよりぱっと見てみたことない構文は検索するともっと早く回答を得られることでしょう。 また検索してもわからないような事であれば質問内容がもっと絞れ回答者も増えることでしょう。 まぁあくまでアドバイスです。結局の所もちろん私はわかる範囲ならば答えるのですから(ですが私はもちろん誰であれ一人の知識では万能の答えを持っている訳ではない事を少しだけ考え質問すれば、最も最速かつ詳細で複数の回答をえられるかもしれません)。
- argument
- ベストアンサー率63% (21/33)
おっと寝ぼけてました。気づかなかったようですが間違いがありました。(デバッグ中の古いほうを張ってしまったようです。) mainfolder の処理部分は mainfolder = myfolder & "\" でした。 つまり正しいソースは Sub Sample() myfolder = "" With Application.FileDialog(msoFileDialogFolderPicker) If .Show = True Then myfolder = .SelectedItems(1) End If End With If myfolder = "" Then Exit Sub For Each fl In CreateObject("Scripting.FileSystemObject").GetFolder(myfolder).subfolders: fn = fn & fl.Name & "\": Next folderlist = Split(Left(fn, Len(fn) - 1), "\") mainfolder = myfolder & "\" For i = 0 To UBound(folderlist) Range("A" & i + 1).Value = mainfolder & folderlist(i) Next End Sub こちらを使ってください。 説明はこのあと投稿します。
お礼
回答ありがとうございます。 前回のソースでも上手くいったのですが、何が間違っていたのでしょうか? お手数をおかけして申し訳ありませんが、ご説明よろしくお願いします。
- argument
- ベストアンサー率63% (21/33)
おはようございます maintec さん 久々の休日にで寝すぎました。そんなことどうでも良いですね。 さてではフォルダの列挙でしたね?前回の文でもしフォルダの規則があるなら言って下さい。という匂いを含ませた回答でしたがないのでとりあえず指定フォルダに含まれる全フォルダをA列に列挙しましょう。 下記を回答として提示します。 Sub Sample() myfolder = "" With Application.FileDialog(msoFileDialogFolderPicker) If .Show = True Then myfolder = .SelectedItems(1) End If End With If myfolder = "" Then Exit Sub For Each fl In CreateObject("Scripting.FileSystemObject").GetFolder(myfolder).subfolders: fn = fn & fl.Name & "\": Next folderlist = Split(Left(fn, Len(fn) - 1), "\") mainfolder = Left(myfolder, InStrRev(myfolder, "\")) For i = 0 To UBound(folderlist) Range("A" & i + 1).Value = mainfolder & folderlist(i) Next End Sub さて実行してみましたか?指定したフォルダに含まれるすべてのフォルダをA列に表示できたと思います。 たとえば今回そのままA列に列挙しましたが列を変えたりここにif文とlikeと使い特定の命名規則のフォルダのみ取得したりできます。 処理違い・補足・追加処理等必要でしたらいってください。
お礼
argument様おはようございます。 久々の休日に度々、私の質問にお答え頂きありがとうございます。 早速、argument様に教えて頂いた構文でテストしたところ、私の望み通りにできました。 本当のデータは会社にあるので、月曜に会社でやってみようと思います。 argument様の本当にお暇な時で結構ですので、今回の構文の説明を頂ければ、後学の為に参考させて頂きたいと思います。 お時間があるとき・気が向いたときで構いませんので、よろしくお願いします。
- argument
- ベストアンサー率63% (21/33)
はじめまして maintec さん あぁ眠いです。もう五時過ぎますね。。いやどうでもいんですけど。 私の知る限り自作する以外方法はありません。 Application.FileDialogにしろAPIを使用するにしろ単一フォルダを選択するの普通です。 なぜかって?必要性が低いからです。 フォルダパスさえひとつ取得できれば別にその中のフォルダを取得することが出来るからです。dirでもできたような気もしますが私ならfsoを使います。さて眠いのでそろそろ寝ますがもしも貴方がどうしても絶対に一つずつ複数選択したいんですといわれなければ私は起きてから処理(指定フォルダを選択肢後、特定規則のフォルダをまたは全てのフォルダをAの列に格納するソース)を考えますがまぁその時は声を掛けてください。それではおやすみなさい。
お礼
朝早く(夜遅く?)に回答ありがとうございます。 私の勉強不足でargument様のおっしゃる回答方法がイメージできません。そういうレベルなのですが、もしよろしければ解決方法を教えて頂けないでしょうか?
お礼
ご返事が遅くなり申し訳ありません。 また、私の勉強不足から幾度と詳細な説明を頂き、大変感謝しております。 昨日、会社で実際のデータを使い、argument様に教えて頂いたソースを使わせて頂いたところ、問題なく上手く処理ができました。 ありがとうございました。