一行のコードで終わらせる ②-2 一行を分解してみる

昨日は、指定フォルダ内にある全ファイルのパスを取得する「一行のコード」(※自作ではありません)を紹介した。
infoment.hatenablog.com
自作ではない悲しさで、不明の部分が多々あった。

そこで今回は、これを可能な限り分解して、理解してみようと思う。
f:id:Infoment:20190103100809p:plain

改めて、昨日の「一行」を見てみよう。

Function_FileList = Filter(Split(CreateObject("wscript.shell").exec("cmd /c Dir """ & FolderLocation & """ /b /a-d").stdout.readall, vbCrLf), ".") 

人によって手法は様々と思うが、私の場合、複雑なコードを組むときの手順は次のとおりだ。

  1. 最も基本的な部分を作成する。
  2. 必要に応じて、段階的に条件分岐や繰り返しを付加する。

従って今回は上記の逆手順で、数式の分解を試みる。

Filter関数

今回初めて知った関数。ある配列を、特定の文字列を持つ要素だけでフィルタリングする。従って、戻り値も配列となる。
www.tipsfound.com

配列

Split(CreateObject("wscript.shell").exec("cmd /c Dir """ & FolderLocation & """ /b /a-d").stdout.readall, vbCrLf)

フィルタ文字

"."

「.」を含むということは、つまり何某かの拡張子を含むファイルパスということになる。なるほど。
ここまでを整理すると、このようになる。

Function Function_FileList(FolderLocation As String)
    Dim seq As Variant
        seq = Split(CreateObject("wscript.shell").exec("cmd /c Dir """ & FolderLocation & """ /b /a-d").StdOut.ReadAll, vbCrLf)
    Dim FilterCharacter As String
        FilterCharacter = "."
        
    Function_FileList = Filter(seq, FilterCharacter)
End Function

Split関数

Split関数は、文字列を指定文字で区切り、配列を返す関数だ。
www.tipsfound.com

文字列

CreateObject("wscript.shell").exec("cmd /c Dir """ & FolderLocation & """ /b /a-d").stdout.readall

区切り文字

vbCrLf

vbCrLfは、改行を表すコード。こちらの解説が、とても参考になる。
thom.hateblo.jp

つまり今回は、一行に一つファイルパスを含む複数行の文字列を分割(Split)して、配列を作成していることになる。
ここまでを整理すると、このようになる。

Function Function_FileList(FolderLocation As String)

    Dim temp As String
        temp = CreateObject("wscript.shell").exec("cmd /c Dir """ & FolderLocation & """ /b /a-d").StdOut.ReadAll
    Dim seq As Variant
        seq = Split(temp, vbCrLf)
    Dim FilterCharacter As String
        FilterCharacter = "."
        
    Function_FileList = Filter(seq, FilterCharacter)
End Function

Windows Scripting Host

ここから先は未だ学びが浅く、かき集めてきたことばかり。コマンドプロンプトから出来ることが、これで実行できるらしい。今後、学習が必要だ。
↓ こちらには、ファイルパスに空白が含まれる場合の対策として、パスを""で囲う必要性が示されている。
Excel VBA を学ぶなら moug モーグ | 即効テクニック | 拡張子関連づけでファイルを開く
それで、↓のような記述になっていたわけだ。

""" & FolderLocation & """
cmd /c

「文字列で指定されたコマンドを実行する」とのこと。つまり、

Dir """ & FolderLocation & """ /b /a-d"

この部分を実行せよということか。

/b

ディレクトリ名とファイル名のみを表示させる。

/a-d

表示する属性を指定。-dで、ディレクトリ「以外」となる。

従って「Dir関数で、指定パス内のディレクトリとファイル名のうち、ディレクトリを除くもの」といったところか。

StdOut

標準出力。Dir関数の結果を出力させている。
標準ストリーム - Wikipedia

ReadAll

TextStreamファイル全体を読み込み、その結果の文字列を返す。
ReadAll メソッド (FileSystemObject)

従って、Dir関数の結果を出力したうえで、読み込んだ文字列ということか。



これらが1行にギュッと詰め込まれていたわけで、これは中々読み込むのが大変だ。引き継いだツールなどにこれが含まれていた場合、恐らく後任者は往生することだろう。

ということで、1行に詰めたのは凄いけど、自己使用以外で展開するのは控えたほうが良さそうです。

参考まで。