フォルダーを選択してファイルリストを作成する

[VBA系メニューへ] [質問掲示板] [バックナンバー目次]
こんにちは、三流プログラマーKen3です。

今回は、
フォルダーを選択してファイルリストを作成する
おや?どこかで見たような、見なかったような、、、
です。

今回作成したファイル名の取得、フォルダー選択のテストプログラム
http://www.ken3.org/p/lzh/off001.lzh
に
office-001.xls, office-001.mdb(フォルダー選択のテストだけ)
保存してます。
ダウンロードして、動きをチェックして見てください。

/* * 1.今回のキッカケ */

仕様、やりたいことをハッキリとさせる プログラムを組む前には、どんなことやりたい? こんなこと? など、作りたい最終結果のイメージを思い浮かべます。 まぁ、ここからの仕様の理解度、プログラムへの落し方が 意外と評価をわけたり、腕の見せ所なんだけどね。 ※詳細設計書の書き方やらなきゃね。。。は、ひとまず置いといて、 納品ファイルの一覧表を作って ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ と言われたら、アナタならどうしますか? ひとつの方法は、エクスプローラーでファイルを表示させて、 それを入力するか、ハードコピーを撮って貼りつけるか。 ←参考画面 プロ?ぽい人は、コマンドプロンプトで、 CD \VBA-TEST (目的のフォルダー) dir *.* > list.txt (DIRはファイル名を表示するコマンド) で、list.txtを作ってエディターなどで編集して処理します。 Microsoft(R) Windows 98 (C)Copyright Microsoft Corp 1981-1998. C:\WINDOWS>d: D:\BackupDISK\Et-mps_2317>cd \vba-test D:\VBA-TEST>dir *.* > list.txt D:\VBA-TEST> ←参考画面 list.txt の 中身は、 ドライブ D: のボリュームラベルは HD07G ボリュームシリアル番号は 2156-1EFF ディレクトリは D:\VBA-TEST . <DIR> 02-11-24 14:29 . .. <DIR> 02-11-24 14:29 .. 042-5-2 <DIR> 01-04-17 10:25 042-5-2 042-3 <DIR> 01-04-13 5:38 042-3 042-4 <DIR> 01-04-14 10:38 042-4 042-5 <DIR> 01-04-17 6:36 042-5 042-2 <DIR> 01-04-10 5:17 042-2 VBA002 <DIR> 02-11-14 6:42 vba002 VBA006 <DIR> 02-11-20 5:46 vba006 VBA013 <DIR> 02-12-02 23:52 vba013 VBA007 <DIR> 02-11-24 14:30 vba007 VBA015 <DIR> 02-12-05 15:54 vba015 VBA018 <DIR> 02-12-08 16:07 vba018 VBA016 <DIR> 02-12-05 21:10 vba016 VBA019 <DIR> 02-12-09 15:25 vba019 A100 TXT 13 02-12-24 1:01 A100.TXT TEST02~1 XLS 28,160 02-12-12 21:06 Test020-Book.xls TEST02~2 XLS 40,448 02-12-12 21:50 Test022-Book.xls DB023 MDB 81,920 02-12-14 1:25 db023.mdb TEST02~3 XLS 27,648 02-12-26 11:57 Test025-Book.xls OUT TXT 220 02-12-19 2:42 out.txt TEST02~4 XLS 30,720 02-12-17 20:22 Test027-Book.xls  ・  ・  ・ TEST05~3 XLS 37,376 03-01-26 19:40 Test052-Book.xls TEST05~4 XLS 44,032 03-01-28 19:08 Test053-Book.xls LIST TXT 0 03-01-31 2:30 list.txt 52 個 1,718,398 バイトのファイルがあります. 15 6,293.68 メガバイトの空きがあります. --- となっているので、あとは好きに編集できます。 毎回、そんなことやってられないので(やっててもいいんだけど) フォルダーを選択したらファイル名のリストを作成する処理をやりたいと思います。

/* * 2.日本語で書くのは簡単だけど、、、 */

フォルダーを選択したらファイル名のリストを作成するツール作ってよ。 やりたいことは〜〜みたいな感じでさ、簡単でいいからさ。 なんて、言われたら? ※簡単でいいからさ、、の一言にだまされないように(笑) ~~~~~~~~~~~~~~~~~~~~~~~~~~ さて、どうしましょうかねぇ。 今回のポイントになるのが、 ・ファイル名リストの取得方法 ・フォルダーの選択方法 ですね。 何で作ろうかなぁ。はじめの道具選びで運命がほぼ決まるよね。 よし今回はExcelでセルにファイル名を入れてみます。

/* * 3.ファイルのリストを取るにはDir関数を使う */

Excelブックで、Alt+F11を押してVBAの編集画面を出してと、
Sub test_ファイル名を取出す()

    'ファイル名を取出して、セルにセットするテストを行う

    'A列をクリアする
    Range("A1:A9999").Value = ""  '1行〜9999行に空文字を代入

    ' C:\ 内のファイル名を表示します。
    Dim strFolder   As String  'フォルダー名
    Dim strFileName As String  'ファイル名
    Dim nYLine      As Integer '行カウンタ

    strFolder = "c:"  '検索するフォルダーを設定します。
    strFileName = Dir(strFolder & "\*.*", vbNormal)  '最初のファイル名を取る

    'ファイルが見つからなくなるまでループしてデータをセットする
    nYLine = 1
    Do While strFileName <> ""   ' ループを開始します。
        Cells(nYLine, 1) = strFileName 'セルにファイル名をセットする
        nYLine = nYLine + 1      ' カウントアップする
        strFileName = Dir        ' 次のファイル名を返します。
    Loop

End Sub
なんか難しそうだけど、プログラムなんてのは、 制御文(ここでは、Do Whileのループ)で流れつくって、 標準関数(Dir関数でファイル名取得) で取得した値を、オブジェクト(Excelのセル) にセットしただけなんですね。 難しいと感じるポイントがあって、 アルゴリズムと呼ばれてるのが、 制御文などの流れを作っている部分。 標準関数の使い方。 オブジェクトの操作。 大きく言うと、このプログラムでは、3点かなぁ。 アルゴリズムはひらめき系?の部分が多く、 標準関数やオブジェクトの操作は知識、 情報の探し方(調査能力、ヘルプを見るうまさ) かなぁ。 それだけじゃないだろオイ ~~~~~~~~~~~~~~~~~~~~~~~~

/* * 4.フォルダーの選択 */

上記のDIRのテスト関数で、 strFolder = "c:" '検索するフォルダーを設定します。 を好きなのに変えてよ、、、 strFolder = "D:\vba-test" '検索するフォルダーを設定します。 とプログラム変更してから実行してね。 おいおい、プログラムを直しながら実行させる、 そんなツール聞いたことないよね。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ そうですかぁ、エディターぐらい使えるよね(笑) 本気で言ってんの?(怒) イヤ冗談です(まったく、まじめ君は困ったもんだ。。。) さてと、フォルダーを選択させるダイアログを探すか。 えっ、ExcelやAccessのVBAだと無いの? やっと噂のAPIを使うんですか? そんなことしたくないので、 Shellオブジェクトを使ってみます。 ~~~~~~~~~~~~~~~~~
Sub test_フォルダーの選択()

    Dim objShell  As Object 'Shell
    Dim objFolder As Object 'Shell32.Folder
    Const strTitle = "フォルダを選択してください。"

    'シェルのオブジェクトを作成する
    Set objShell = CreateObject("Shell.Application")

    'フォルダー参照に設定
    Const lngRef = &H1
    'ルートフォルダーをデスクトップに設定
    '5でMy Documents、6でFavoritesなど
    Const fldRoot = &H0
    
    Set objFolder = _
            objShell.BrowseForFolder(0, _
                strTitle, lngRef, fldRoot)
    Set objShell = Nothing
    
    'フォルダー名を取出す
    Dim strMSG
    If objFolder Is Nothing Then 'キャンセルチェック
        strMSG = "キャンセル押しやがって、えっキャンセル押されたらのテスト?"
    Else
        If objFolder.ParentFolder Is Nothing Then
            strMSG = "選択されたのは[ルート(デスクトップ)]です"
        Else
            strMSG = "選択されたのは[" & objFolder.Items.Item.Path & "]です"
        End If
    End If
    MsgBox strMSG

End Sub
なんとか、出来たみたいですね。 *デスクトップを選択された時、ログインユーザーの場所を求めてないけどね。 システムやツールを作成する時、 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 標準関数や標準のダイアログで実行できない機能を 外部のオブジェクトを参照して、その機能を借用する(笑)なんてこともあります。 *WindowsAPIを操作する高度な方法もあります。 これも長くなるので、補足発行かなぁ(おいおい、そんなんでいいの?)

/* * 5.単体でテストしたサブルーチンをつなげる */

フォルダーの選択 と 指定したフォルダー内のリストの出力処理 上記2つのテストが完了しました。 さてと、つなげますか。 メインの流れは、 フォルダーを選択させる。    ↓ キャンセルだったら、処理を抜ける    ↓ 選択されたフォルダーを表示関数に渡し、表示する えっ、そんなものなの? 別に複雑にしたくないので。 プログラム作成になれて無い時は、 日本語の動作を箇条書きで書くといいですよ。
Sub Main()

    'フォルダーを選択させる

    'キャンセルだったら処理を抜ける

    '選択されたフォルダーを表示関数に渡し表示する

End Sub
みたいに、コメントだけの関数を書いてみる、でいいと思います。 処理のまとめ方にもポイントがあって、 値の受け渡し方法や書き方がプログラムがうまい人とヘタな人の差になるのかなぁ。 ※そこをハヤク教えろよ、隠すなよ  まぁまぁ、今回は置いといて次回以降ね。。。  忘れんなよ(怒)
Sub Main()

    Dim strFolder  '選択されたフォルダーを格納

    'フォルダーを選択させる
    strFolder = getFOLDER()  'フォルダーの選択関数を呼ぶ

    'キャンセルだったら処理を抜ける
    If strFolder = "キャンセル" Then
       Exit Sub
    End If

    '選択されたフォルダーを表示関数に渡し表示する
    Call setFILELIST(strFolder)  'データのセット

End Sub
と、変数を使って、2つのユーザー関数を制御するMain関数としました。 'フォルダー選択ダイアログを表示して、リターン値で選択場所を返す 'キャンセルの時は文字列キャンセル、 'デスクトップの時は文字列を返す
Function getFOLDER() As String

    Dim objShell  As Object 'Shell
    Dim objFolder As Object 'Shell32.Folder
    Const strTitle = "フォルダを選択してください。"

    'シェルのオブジェクトを作成する
    Set objShell = CreateObject("Shell.Application")

    'フォルダー参照に設定
    Const lngRef = &H1
    'ルートフォルダーをデスクトップに設定
    '5でMy Documents、6でFavoritesなど
    Const fldRoot = &H0
    
    Set objFolder = _
            objShell.BrowseForFolder(0, _
                strTitle, lngRef, fldRoot)
    
    'フォルダー名を取出し、リターン値をセット
    If objFolder Is Nothing Then 'キャンセルチェック
        getFOLDER = "キャンセル"  'リターン値にキャンセルをセット
    Else
        If objFolder.ParentFolder Is Nothing Then
            getFOLDER = "デスクトップ"
        Else
            getFOLDER = objFolder.Items.Item.Path 'パスをセットする
        End If
    End If

    Set objFolder = Nothing
    Set objShell = Nothing

End Function
値を返すユーザー関数 Functionにして、 テストで、メッセージボックスの確認していた部分を、 getFOLDER = "キャンセル" 'リターン値にキャンセルをセット getFOLDER = "デスクトップ" getFOLDER = objFolder.Items.Item.Path 'パスをセットする に変えただけでした。 次の表示部は、 '引数(パラメータ)でフォルダー名をもらい、 'データをA列にセットする
Sub setFILELIST(strFolder As String)

    'A列をクリアする
    Range("A1:A9999").Value = ""  '1行〜9999行に空文字を代入

    Dim strFileName As String  'ファイル名
    Dim nYLine      As Integer '行カウンタ

    '最初のファイル名を取る
    strFileName = Dir(strFolder & "\*.*", vbNormal)
    
    'ファイルが見つからなくなるまでループしてデータをセットする
    nYLine = 1
    Do While strFileName <> ""   ' ループを開始します。
        Cells(nYLine, 1) = strFileName 'セルにファイル名をセットする
        nYLine = nYLine + 1      ' カウントアップする
        strFileName = Dir        ' 次のファイル名を返します。
    Loop

End Sub
と、フォルダーの場所をパラメータで受け取り、データをセットしました。 ツール、プログラム作りとかいってたけど、 標準関数のファイル名を返すDir関数 と Shellオブジェクトを使用したフォルダーの選択、 たんなる関数やオブジェクトの操作を組み合わせだけなんですね。 'フォルダーを選択させる strFolder = getFOLDER() 'フォルダーの選択関数を呼ぶ と1つ使えそうな?関数ができあがりましたね。

/* * 6.終わりの挨拶 */

今回作成したファイル名の取得、フォルダー選択のテストプログラム http://www.ken3.org/p/lzh/off001.lzh に office-001.xls, office-001.mdb(フォルダー選択のテストだけ) 保存してます。 ダウンロードして、動きをチェックして見てください。 ※コピーして、システムに組み込んで使ってみてください。  えっ、ハヤク、デスクトップの位置を知る方法を書けって? 拾い読みして、 1つでも何かの参考となれば幸いです。 Excel/Access大好き、三流プログラマーKen3でした。 ※今日はふざけすぎました、解除しないでね。

三流君のHP主な飛び先

VBA系のメルマガで書いた解説を項目ごとにまとめてます

[VBAでAccessを操作(一般)]
[VBAでAccessのレポートを操作]
[VBAでAccessのUserForm/サブフォームを操作]
[VBA Access から Excel 連携]

[VBA でExcel オブジェクト/プロパティ/メソッド/一般]
[VBA でExcel UserForm(ユーザーフォーム)を操作する]
[VBA ExcelからAccessを操作する]

[VBA Outlookの操作]
[VBA IEの操作]
[VBA テキストファイル(*.txt,*.html,*.csv)の操作]
[VBA標準関数関係とその他解説]

ASP系の解説を項目ごとにまとめてみました

[ASP Form等を使用したデータのやり取り]
[ASP その他処理サンプル]
[ASP テキストファイル処理]
[ASP VBScript関数関係の説明]
[ASP ADOでMdbファイルを使う]
[ASP ADOでExcelと接続してみた]