Excel (VBA)

Excel VBAに関するフォーラムです。
  • 掲示板への投稿には会員登録(無料)が必要です。会員登録がまだの方はこちら
  • 掲示板ご利用上のお願い」に反するご記入はご遠慮ください。
  • Q&A掲示板の使い方はこちらをご覧ください
トピックに返信
質問

 
(Windows 10全般 : 指定なし)
フォルダ内のファイル名の取得
投稿日時: 19/10/12 12:45:15
投稿者: chokobanana

treeやdirを使えない人がいるのでマクロでフォルダ内のファイル名を取得したいです。
 
(やりたいこと)
データフォルダ内に入っているフォルダ名、さらに入っているフォルダ内のファイル名の取得、
取得した日をセルに記録したい。
 
下記のコードを組んだExcelシートをデータ(フォルダ)に入れて実行しても結果がでません。
どのようにしたらよろしいのでしょうか。
 
 
 
 
Sub Sample1()
 
    Dim i As Long, buf As String
     
    Const Path As String = "Z:\User\データ"
     
    buf = Dir(Path & "*.*")
     
    Do While buf <> ""
        i = i + 1
        Cells(i, 1) = buf
        buf = Dir()
    Loop
    MsgBox "全部で" & i & "個ファイルがありました"
     
End Sub

回答
投稿日時: 19/10/12 13:23:32
投稿者: WinArrow
投稿者のウェブサイトに移動

修正する箇所
 
案1
> Const Path As String = "Z:\User\データ"

    Const Path As String = "Z:\User\データ\"
 
案2
 
>buf = Dir(Path & "*.*")

buf = Dir(Path & "\*.*")
 
どちらを採用するかは、お任せします。

投稿日時: 19/10/12 14:54:39
投稿者: chokobanana

どちらも試してみました。
結果は「全部で0個ファイルがありました」となりました。
 
別のフォルダでも同じです。
 
どこが原因でしょうか。

投稿日時: 19/10/12 15:37:53
投稿者: chokobanana

もしかして、自分の希望と前に投降した式が根本的に違うのでしょうか。
 
(希望)
フォルダ内のファイル名取得
 ・ファイルの種類は多種(Excel、Word、PDF、圧縮等)
 ・サブフォルダが有る
 ・treeの結果のようにどのフォルダにどのファイルが入っているのか分かりたい
 ・作業日付を結果に残したい
 ・繰り返し作業する。
 
 
 
 

回答
投稿日時: 19/10/12 16:04:38
投稿者: simple

つかぬことをお聞きしますが、Z:ドライブといいますとやや特別ですね。
それはエクスプローラーではファイルたちが表示されているんでしょうか?

回答
投稿日時: 19/10/12 16:10:20
投稿者: WinArrow
投稿者のウェブサイトに移動

掲示のコードの中で、
Path で記述している
フォルダは
>下記のコードを組んだExcelシートをデータ(フォルダ)に入れて実行しても結果がでません。
とが違うのか、同じなのかは、回答者には、見えません。
 
若し、
本ブックは入っているフォルダと
pathが違うのでしたら
 
>buf = Dir(Path & "*.*")

 
 buf = Dir(Thisworbook.Path & "\*.*")
に変更してみましょう。
 

投稿日時: 19/10/12 17:47:19
投稿者: chokobanana

Z:ドライブはクラウドです。
エクスプローラーに表示されてます。
 
Path で記述しているフォルダはデータファルダです。
マクロ付きのExcelはデータフォルダの中に入れてます。
 
buf = Dir(Thisworbook.Path & "\*.*") に変更しましたがダメでした。
 
マクロ詳しくないので全然違うことをしているのかもしれません。
 
https://qiita.com/jooji/items/e4fac514494fb9270320
のサイトのマクロを試してみたのですが上手くいきませんでした。

回答
投稿日時: 19/10/12 18:49:55
投稿者: simple

クラウドではなく通常のローカルのディスクではどうですか?
問題を切り分けたほうがよいと思います。
 
cmd プロンプト画面で
Dir Z:\User\データ\*.*
を実行して、何が出力されますか?

回答
投稿日時: 19/10/12 19:12:16
投稿者: WinArrow
投稿者のウェブサイトに移動

>Z:ドライブはクラウドです。
 
これはあなたのPCのドライブです。
たとえ、うまくいったとしても、
他のPCでは異なりますから
固定値で定義することできません。
 
また、クラウドは、何を使っているのでしょう?

回答
投稿日時: 19/10/12 21:14:32
投稿者: WinArrow
投稿者のウェブサイトに移動

クラウドのファイルを開くテストしてみました。
 
クラウドは、OneDriveです。
OneDriveのフォルダにテスト用xlsmを保存してあります。
テストコード
Sub test()
Dim Myf, wbk As Workbook
    Myf = Dir(ThisWorkbook.Path & "\*.xls?")
    Set wbk = Workbooks.Open(ThisWorkbook.Path & "\" & Myf)
    Debug.Print wbk.Name
    wbk.Close False
End Sub
 

回答
投稿日時: 19/10/13 16:05:49
投稿者: simple

クラウドの話はそちらで解決してもらうことにして、

引用:
もしかして、自分の希望と前に投降した式が根本的に違うのでしょうか。
(希望)
フォルダ内のファイル名取得
 ・ファイルの種類は多種(Excel、Word、PDF、圧縮等)
 ・サブフォルダが有る
 ・treeの結果のようにどのフォルダにどのファイルが入っているのか分かりたい
 ・作業日付を結果に残したい
 ・繰り返し作業する。

あなたの投稿したコードで上記のことが実現できているとお考えなんでしょうか。
あなたが希望を持つことはご自由ですが、作成依頼はやめましょう。(掲示板の禁止事項になっています)
treeはフォルダ構造を表すものですが、
それと同様の形態でファイル情報を入れたものは、そう簡単に自作はできません。
 
http://www.asahi-net.or.jp/~ef2o-inue/vba_o/sub05_110_080.html
あたりをみて、そのまま使うのがよいと思います。

回答
投稿日時: 19/10/14 09:42:05
投稿者: MMYS

chokobanana さんの引用:
treeやdirを使えない人がいるのでマクロでフォルダ内のファイル名を取得したいです。
 
buf = Dir(Thisworbook.Path & "\*.*") に変更しましたがダメでした。
 

それ以前にあなたはDir関数を理解してますか。
よく分からんけど適当に作ったら、希望通りに動いた。なんてことあるの。
 
目的地の向かうのに適当にバスや電車に乗ったら目的地の東京駅八重洲口に着いた。
なんてあるわけない。
 
こちらは理解してますか。
http://officetanaka.net/excel/vba/function/Dir.htm
とくに次の記述が重要です。
> 続けて次のファイルを取得するときには、Dir関数に引数を与えずに実行します。
 
Dir関数、
https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/dir-function
Microsoft公式にも、もちろん書かれています。
> フォルダー内のすべてのファイルに対して反復処理を行うには、空の文字列を指定します。

投稿日時: 19/10/14 12:56:03
投稿者: chokobanana

提示した式はCドライブでも上手くいきませんでした。
教えて頂いた修正でもダメでした。
 
treeやdirはcmdで使用していました。
マクロではありません。
 
マクロは詳しくないのでネットで検索して例としてあったものを試しております。
どこがおかしいのか教えて頂きたく こちらに投降させてもらいました。
 
投降した式がどの程度希望をクリアしているかは結果が返ってこないので分かりませんが
満たしていない部分は調べてい補足しようと思っておりました。
 
やりたいこととかけ離れているようでしたら教えて下さい。
 
最終的に下記の内容の結果を望んでおります。
treeやdirとまったく同じ答えを望んでいるわけではありません。
 
作業日
 
●●フォルダ
  □ファイル
  △ファイル
  ◎◎フォルダ
       ××ファイル
    △〇ファイル
★★フォルダ
  △◆ファイル
  
 
    
 
   
 
 
 
 
 
 
 

回答
投稿日時: 19/10/14 16:59:43
投稿者: simple

おかしいですね。
質問の冒頭にあったコードは概ね正しいです。
すでに指摘があったように \ が抜けている点を除き、正常動作します。
私も、正しく動作することを実際に確認したうえでコメントしています。
 
まずは出発点として、これについて、意見一致をさせるのが先決でしょう。
 
即効テクニックでも、ほぼ同様のコードが提示されています。コード自体は正しいはずです。
https://www.moug.net/tech/exvba/0060088.html
こちらをよく研究してください。
 
なにかしら勘違いがあるんじゃないですか?
フォルダ名が少し違っているとか、くらいしか思いつきません。
こちらではきちんと動くのだから、
動かない理由は「そちらでよく調べて下さい」としか言えませんよ。
 
そうか、フォルダを指定させればいいのかも。
下記を実行してみてください。

Sub Sample1()
    Dim i As Long, buf As String
    Dim foldername As String
    
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show = True Then
            foldername = .SelectedItems(1)
        End If
    End With
    
    buf = Dir(foldername & "\*.*")
    Do While buf <> ""
        i = i + 1
        Cells(i, 1) = buf
        buf = Dir()
    Loop
    MsgBox "全部で" & i & "個ファイルがありました"
End Sub

続いて、クラウド上のもの(Z:にドライブ割当したもの)についても、
上記で実行(選択)してみてください。
 
----------------------
なお、
引用:
cmd プロンプト画面で
Dir Z:\User\データ\*.*
を実行して、何が出力されますか?
と言う質問に対する回答をいただいていません。
>教えて頂いた修正でもダメでした。
というのが回答ですか?
ダメでしたじゃなくて、何が出力されるか、文字列を書いてもらえませんか?

回答
投稿日時: 19/10/14 17:52:10
投稿者: Moko

Dir 関数
https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/dir-function?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev11.query%3FappId%3DDev11IDEF1%26l%3Dja-JP%26k%3Dk(vblr6.chm1008898)%3Bk(TargetFrameworkMoniker-Office.Version%3Dv16)%26rd%3Dtrue
 
Zドライブに「vbNormal」属性のファイルが無い、
ということじゃありませんか?
 
buf = Dir(Path & "\*.*", vbDirectory)
 
でどうなりますか?

回答
投稿日時: 19/10/14 18:16:25
投稿者: Moko

投稿日時: 19/10/14 12:56:03
のような結果を望むなら再帰処理が不可欠です。
 
サブフォルダを含めてファイル一覧を取得する(Dir関数の再帰呼び出し)
https://www.moug.net/tech/exvba/0060088.html
 
 

回答
投稿日時: 19/10/14 19:00:20
投稿者: simple

なるほど、直下にはフォルダしか無くて、そのフォルダの下のファイルをということですか。
それは明確にそう質問してくれないとわかりません。
Dir Z:\User\データ\*.* の結果を示してもらうと、もっと早くわかったはずです。
すでに指摘があったように、即効テクニックの記事が参考になるでしょう。(私も紹介しています)
 
また、
再掲しますが、以下が使えるはずです。ダウンロードして使うだけです。

引用:
http://www.asahi-net.or.jp/~ef2o-inue/vba_o/sub05_110_080.html
あたりをみて、そのまま使うのがよいと思います。

以上

回答
投稿日時: 19/10/14 21:30:38
投稿者: MMYS

simple さんの引用:
おかしいですね。
質問の冒頭にあったコードは概ね正しいです。
 
なるほど、直下にはフォルダしか無くて、そのフォルダの下のファイルをということですか。
それは明確にそう質問してくれないとわかりません。

質問者さんは動きません。としか書いてません。
ファイルだけなら正しいコードです。(サブフォルダは対象外)
質問者さんは自動でサブフォルダまでリストアップすると思っていたら?
 
このコードなら結果は〇〇となると思うけど
実際は△△になる。ステップ実行すると、□のところ、意図した動きをしない。
なせなんだろう。と詳しくかかないと適切なアドバイスは受けられないです。
 
そして、なぜそうなるかを自分で考えないと、時間ばかり過ぎ去ります。
 
 

回答
投稿日時: 19/10/14 23:26:37
投稿者: simple

引用:
https://qiita.com/jooji/items/e4fac514494fb9270320
のサイトのマクロを試してみたのですが上手くいきませんでした。
これだって、
配下のフォルダにあるファイルは検索しているはずですがね。
 
総体として、「うまくいきません」一辺倒なので、他人には伝わりませんね。

投稿日時: 19/10/15 13:02:09
投稿者: chokobanana

皆様 色々とありがとうございます。
 
少しづつ回答させて頂きます。
順番が違うかもしれませんが お許し下さい。
 
>クラウドのファイルを開くテストしてみました。
 
エラー52が出ます。
パスはshiftキーを押しながら右クリックし、パスのコピーを貼りつけました。
 
Sub test()
Dim Myf, wbk As Workbook
    Myf = Dir(ThisWorkbook.Path & "Z:\User\データ\Book1.xlsm")
    Set wbk = Workbooks.Open(ThisWorkbook.Path & "\" & Myf)
    Debug.Print wbk.Name
    wbk.Close False
End Sub
 
>おかしいですね。
>質問の冒頭にあったコードは概ね正しいです。
>すでに指摘があったように \ が抜けている点を除き、正常動作します。
>私も、正しく動作することを実際に確認したうえでコメントしています。
>まずは出発点として、これについて、意見一致をさせるのが先決でしょう。
 
新しいファイルで下記のマクロを設定し、実行しました。
クラウドではエラー52となります。
Cドライブでは正常に動きました。
 
Sub Sample1()
  
    Dim i As Long, buf As String
      
    Const Path As String = "Z:\User\データ"
      
    buf = Dir(Path & "*.*")
      
    Do While buf <> ""
        i = i + 1
        Cells(i, 1) = buf
        buf = Dir()
    Loop
    MsgBox "全部で" & i & "個ファイルがありました"
      
End Sub
 
>そうか、フォルダを指定させればいいのかも。
>下記を実行してみてください。
 
ご提示いただいた下記コードで試してみました。
クラウドではエラー52が出ます。
Cドライブは正常に動きました。
 
Sub Sample1()
    Dim i As Long, buf As String
    Dim foldername As String
     
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show = True Then
            foldername = .SelectedItems(1)
        End If
    End With
     
    buf = Dir(foldername & "\*.*")
    Do While buf <> ""
        i = i + 1
        Cells(i, 1) = buf
        buf = Dir()
    Loop
    MsgBox "全部で" & i & "個ファイルがありました"
End Sub
 
 
 
  
 
 
 

回答
投稿日時: 19/10/15 13:37:26
投稿者: WinArrow
投稿者のウェブサイトに移動

chokobanana さんの引用:
皆様 色々とありがとうございます。
 
少しづつ回答させて頂きます。
順番が違うかもしれませんが お許し下さい。
 
>クラウドのファイルを開くテストしてみました。
 
エラー52が出ます。
パスはshiftキーを押しながら右クリックし、パスのコピーを貼りつけました。
 
Sub test()
Dim Myf, wbk As Workbook
    Myf = Dir(ThisWorkbook.Path & "Z:\User\データ\Book1.xlsm")
    Set wbk = Workbooks.Open(ThisWorkbook.Path & "\" & Myf)
    Debug.Print wbk.Name
    wbk.Close False
End Sub

 
やはり、Dir関数について、理解されていないようですね・・
> Myf = Dir(ThisWorkbook.Path & "Z:\User\データ\Book1.xlsm")
こんなコードではエラーになるのは当たり前です。
 
Book1.xlsm
というファイルが
Z:\User\データ
というフォルダに存在するとう前提で
 
↓のように修正してみましょう
    Myf = Dir(ThisWorkbook.Path & "\Book1.xlsm")
 
 

投稿日時: 19/10/15 16:22:58
投稿者: chokobanana

>↓のように修正してみましょう
>Myf = Dir(ThisWorkbook.Path & "\Book1.xlsm")
 
下記で試してみました。
やはりエラー52が出ます。
きちんと修正できてないようでしたら教えて下さい。
 
Sub test()
Dim Myf, wbk As Workbook
    Myf = Dir(ThisWorkbook.Path & "\Book1.xlsm")
    Set wbk = Workbooks.Open(ThisWorkbook.Path & "\" & Myf)
    Debug.Print wbk.Name
    wbk.Close False
End Sub
 

回答
投稿日時: 19/10/15 17:22:49
投稿者: WinArrow
投稿者のウェブサイトに移動

Dir関数で
エラー52
は、アクセス権 有無に関係するようです。
 
普通の場合、ファイルがない場合は、""が返ることになりエラーにはならないと思います。
 

回答
投稿日時: 19/10/15 17:27:47
投稿者: hatch315
メールを送信

実行するExcelファイルがネットワーク上にあるとThisWorkbook.Pathは空に
なるみたいなので対策として
 
Option Explicit
 
      'カレントディレクトリ設定
      Declare Function SetCurrentDirectory Lib "kernel32" Alias "SetCurrentDirectoryA" (ByVal CurrentDir As String) As Long

Public Sub test()
 
Dim Myf As String
Dim wbk As Workbook
     
        
   'DLLファルダ設定(LAN対応)
    SetCurrentDirectory ThisWorkbook.Path
    ChDir ThisWorkbook.Path

        
     
     
    MsgBox ThisWorkbook.Path
     
    Myf = Dir(ThisWorkbook.Path & "\Book1.xlsm")
    Set wbk = Workbooks.Open(ThisWorkbook.Path & "\" & Myf)
    Debug.Print wbk.Name
    wbk.Close False
End Sub
 
赤字の部分の追加が必要みたいです。
 
 

回答
投稿日時: 19/10/15 17:35:56
投稿者: hatch315
メールを送信

スイマセン OneDrive上のファイルの読込はできないかも知れません。
 

引用:
実行するExcelファイルがネットワーク上にあるとThisWorkbook.Pathは空に
なるみたいなので対策として
  
Option Explicit
  
      'カレントディレクトリ設定
      Declare Function SetCurrentDirectory Lib "kernel32" Alias "SetCurrentDirectoryA" (ByVal CurrentDir As String) As Long
 
Public Sub test()
  
Dim Myf As String
Dim wbk As Workbook
      
         
   'DLLファルダ設定(LAN対応)
    SetCurrentDirectory ThisWorkbook.Path
    ChDir ThisWorkbook.Path
         
      
      
    MsgBox ThisWorkbook.Path
      
    Myf = Dir(ThisWorkbook.Path & "\Book1.xlsm")
    Set wbk = Workbooks.Open(ThisWorkbook.Path & "\" & Myf)
    Debug.Print wbk.Name
    wbk.Close False
End Sub
  
赤字の部分の追加が必要みたいです。
 

投稿日時: 19/10/19 14:34:36
投稿者: chokobanana

色々とありがとうございます。
クラウドは諦めました。
 
サーバー上で行いたいと思います。
サーバー上でフォルダの中のファイルは取得できました。
 
次はサブフォルダとサブフォルダの中のファイルを取得したく、教えて頂いた
下記のコード試してみました。
 
www.asahi-net.or.jp/~ef2o-inue/vba_o/sub05_110_080.html
 
 
2つとも同じシートに組んで実行すると下記の部分が青くなり
「ユーザー定義型は定義されていません」とでます。
どう対処したらよいのでしょうか?
 
Private Sub SEARCH_SUB_FOLDER(ByVal objPATH As Folder, _
                              ByRef GYO As Long, _
                              ByVal COL As Long)

回答
投稿日時: 19/10/19 15:35:11
投稿者: simple

必要な「参照設定」が漏れていることが
考えられます。

投稿日時: 19/10/19 15:45:18
投稿者: chokobanana

ごめんなさい、ダウンロードを失念してました。
 
ダウンロードでテストしましたら下記エラー
 
「このプロジェクトのコードは64ビットシステムで使用するために更新する必要が
あります。Declareステートメントの確認および更新をおこない、次にDeclareステートメント
にPtrSafe属性を設定してください」
 
ヘルプ見ても分かりません。
どうしたらよいのでしょうか?

回答
投稿日時: 19/10/19 17:56:54
投稿者: simple

OSではなく、Officeのバージョンが64bitなんですかね。
互換性の問題があるから、32bit版のOfficeを推奨します、
などという話は聞いたことがあります。
私はこのあたり全く詳しくないので、他の方のコメントをお待ち下さい。
 
# もちろん、私の手元では正常動作するんです。
# 私が作ったものではないので、制作者責任が私にあるわけでもないので、
# 頑張って下さい、としか申し上げられません。
# 別の方向を考えた方がよいかもしれません。
# すみませんね。

回答
投稿日時: 19/10/19 20:02:19
投稿者: simple

(32ビットOfficeと64ビットOfficeに関する)自分用の覚え書きです。
 
(1)
modFolderPicker1 標準モジュールの最初のほうに
Private Declare Function WNetGetConnection Lib "mpr.dll" _
    Alias "WNetGetConnectionA" _
    (ByVal lpszLocalName As String, _
     ByVal lpszRemoteName As String, _
     cbRemoteName As Long) As Long
という宣言があるはず。
 
その一行目の Declareのあとに PtrSafe を追加して、
Private Declare PtrSafe Function WNetGetConnection Lib "mpr.dll" _
   (以下同じ)
と変更してみてはどうか。
(こちらはネットワークがらみの機能のようで、端折る訳にはいかない模様)
 
(2)
module1 にある
Private Declare Sub GetSystemTime Lib "KERNEL32.dll" _
    (lpSystemTime As SYSTEMTIME)
についても、Declareのあとに PtrSafe を追加して
Private Declare PtrSafe Sub GetSystemTime Lib "KERNEL32.dll" _
    (lpSystemTime As SYSTEMTIME)
としてみてはどうか。
(尤も、実行時間など普通のTimerで十分だし、時間計測すら不要かもしれないから、
  削ってしまってもよいだろう。)
 
上記2つとも、手元で確認したわけではないので、多分OKだろうが、うまくいく保証はしかねます。
(まあ、表示されたメッセージ内容そのままだから、致命的なことにはならないはず。)
 
------------------------------
【参考にしたドキュメント】
・"64bit Excelが動かない"などで検索して下さい。
  64ビットOfficeの下位互換性問題がたくさん出てくる。
  APIを使った古いコードを使う場合に起きるトラブルの模様。
  速度向上よりも、互換性対応の観点から、32ビットOfficeの再インストールを推奨する
  記事が結構あります。
・対応策の原典は下記。
https://docs.microsoft.com/ja-jp/office/client-developer/shared/compatibility-between-the-32-bit-and-64-bit-versions-of-office
・このなかに示されている "Win32API_PtrSafe.txt"というファイルをダウンロードすると、
  Win32APIに関して、Declare宣言の様式が網羅的に書いてある模様。

トピックに返信