お気に入りのMP3を何曲か集めて音楽CDを焼くようなとき、演奏時間が全部で何分になるかを事前に知りたい場合があります。他の人はどうだか知りませんが、私にはあります。もちろん、そうした情報を提供してくれるフリーソフトなどはたくさんあるでしょうけど、できればチャチャっと、自分で簡単に調べられたら幸せです。
そうした情報は、MP3ファイルの末尾や先頭に記録されているのは知っていましたし、適当に当たりをつけて力わざで抜き出そうかとも思いました。しかし、WSHを使うと簡単に取得できるのを発見したので(備忘録として)書いておきます。そのうち、使いやすいUIを作るかもしれませんが、とりあえずはExcelのシートに出力するVBAサンプルです。ExcelのGetOpenFilenameメソッドを使っていますので、VB6では動きません。
Sub Sample1() Dim FSO As Variant, SHell As Variant, Folder As Variant Dim Songs As Variant, i As Long, Target As String Songs = Application.GetOpenFilename(FileFilter:="MP3ファイル,*.mp3", MultiSelect:=True) If Not IsArray(Songs) Then Exit Sub Set FSO = CreateObject("Scripting.FileSystemObject") Set SHell = CreateObject("Shell.Application") Set Folder = SHell.Namespace(FSO.GetFile(Songs(1)).ParentFolder.Path) For i = 1 To UBound(Songs) Target = FSO.GetFile(Songs(i)).Name Cells(i, 1) = Folder.GetDetailsOf(Folder.ParseName(Target), 0) Cells(i, 2) = Folder.GetDetailsOf(Folder.ParseName(Target), 21) Next i Set Folder = Nothing Set SHell = Nothing Set FSO = Nothing End Sub
思いのほか長くなったので、ちょっと解説します。
最初の2行は変数の宣言。これはいいですね。
Songs = Application.GetOpenFilename(FileFilter:="MP3ファイル,*.mp3", MultiSelect:=True)
If Not IsArray(Songs) Then Exit Sub
は、MP3ファイルを選択するところです。MultiSelect:=Trueで複数選択可にしていますので、[キャンセル]ボタンがクリックされたかどうかは、返り値が配列かどうかで見ています。
続く
Set FSO = CreateObject("Scripting.FileSystemObject")
Set SHell = CreateObject("Shell.Application")
Set Folder = SHell.Namespace(FSO.GetFile(Songs(1)).ParentFolder.Path)
は、オブジェクト(インスタンス)の生成です。最初のFSOは、おなじみのFileSystemObjectです。今回のメイン処理である「MP3のタグ情報」は、WSHのShellオブジェクトを使います。それが、CreateObject("Shell.Application")です。
「MP3のタグ情報」は、MP3ファイルを右クリックして[プロパティ]を実行し、表示される[○○のプロパティ]ダイアログボックスの[概要]タブで確認することができます。
この[概要]タブの情報を取得するには、WSHのShellオブジェクト配下にある、FolderオブジェクトのGetDetailsOfメソッドを使います。たとえば「C:\Music」フォルダにある「001.mp3」というMP3ファイルのタグ情報を取得したいときは、次のようにします。
C:\Musicを示すFolderオブジェクト.GetDetailsOf(001.mp3を示すFolderItemオブジェクト, _ タグ情報の番号)
任意のFolderオブジェクトを取得するには、ShellオブジェクトのNamespaceメソッドを使って、たとえば次のようにします。
Set Folder = SHell.Namespace("C:\Music")
今回は、GetOpenFilenameメソッドの返り値を利用しますので、[ファイルを開く]ダイアログボックスで選択されたフォルダのパス名を、Namespaceメソッドの引数にしてやります。[ファイルを開く]ダイアログボックスで選択されたファイルは「C:\Music\001.mp3」のようにフルパスが返りますから、FSOを使ってパスだけを抜き出しました。
Set Folder = SHell.Namespace(FSO.GetFile(Songs(1)).ParentFolder.Path)
もしかすると、他にもっと良い手があるかもしれませんが、とりあえず今回はこれで。
以上の処理を除いて、実際にタグ情報を取得しているのが下記の部分です。
Sub Sample1() Dim FSO As Variant, SHell As Variant, Folder As Variant Dim Songs As Variant, i As Long, Target As String Songs = Application.GetOpenFilename(FileFilter:="MP3ファイル,*.mp3", MultiSelect:=True) If Not IsArray(Songs) Then Exit Sub Set FSO = CreateObject("Scripting.FileSystemObject") Set SHell = CreateObject("Shell.Application") Set Folder = SHell.Namespace(FSO.GetFile(Songs(1)).ParentFolder.Path) For i = 1 To UBound(Songs) Target = FSO.GetFile(Songs(i)).Name Cells(i, 1) = Folder.GetDetailsOf(Folder.ParseName(Target), 0) Cells(i, 2) = Folder.GetDetailsOf(Folder.ParseName(Target), 21) Next i Set Folder = Nothing Set SHell = Nothing Set FSO = Nothing End Sub
選択されたMP3ファイル群は、配列Songsに格納されています。
For i = 1 To UBound(Songs)
で、順番に選択されたファイルを取り出します。
配列Songsに格納されているのは「C:\Music\001.mp3」のようにパスを含んでいますので、
Target = FSO.GetFile(Songs(i)).Name
とファイル名(だけ)を取得して、変数Targetに格納します。
変数Targetは、このままでは単なる文字列ですから、
Folder.ParseName(Target)
として、FolderItemオブジェクトに変換します。
MP3ファイルのタグ情報のうち「ファイル名」を表すヘッダ番号は「0」で、「曲の長さ」を表すヘッダ番号が「21」ですので、
Cells(i, 1) = Folder.GetDetailsOf(Folder.ParseName(Target), 0) Cells(i, 2) = Folder.GetDetailsOf(Folder.ParseName(Target), 21)
として抜き出しています。
※Windows Vistaではヘッダ番号が異なります。ヘッダ番号を調べる方法は、このページの最後に追記します。上の実行結果画面では、SUM関数で合計時間を計算していますが、それは手で入力した方が簡単なのでコード化していません。ツールバーの[オートSUM]ボタンを押したときのように、自動的にSUM関数を入力するには、Alt+Shift+「=」キーを押します。同様に、前回の出力結果をクリアする処理も手動としました。Ctrl+Shift+「*」キーを押して全体を選択してDeleteキーを押せば済みますからね。
ちなみに、GetDetailsOfメソッドを使うと、MP3のタグ情報だけでなく、ファイルの「作成者」や「更新日時」などを取得できますし、画像ファイルでしたら「カメラの名前」や「画像の大きさ」なども取得できます。要するに、エクスプローラの[表示]-[詳細]で表示される情報を取得できるわけですね。
(追記)
このマクロ、便利に使っていたのですが、Windows Vistaで実行したら演奏時間を取得できませんでした。Windows XPに比べて、Windows Vistaはフォルダに表示できる詳細表示情報が変更になったようです。調べてみたら、写真関係や、プロフィール関係などの詳細が、ずいぶん追加されていました。
すべてのヘッダ番号を調べるには次のようにします。なお、演奏時間を表す「長さ」のところで、MsgBoxを出すようにしています。
Sub Sample2() Dim objShell, objFolder, i As Long Set objShell = CreateObject("Shell.Application") Set objFolder = objShell.Namespace("C:\") For i = 0 To 1000 ''十分に大きい数字 Debug.Print i, objFolder.GetDetailsOf("", i) If objFolder.GetDetailsOf("", i) = "長さ" Then MsgBox "長さ:" & i Next i Set objFolder = Nothing Set objShell = Nothing End Sub
ヘッダのタイトルを取得するには、GetDetailsOfメソッドの第1引数に「""」を指定します。ネットで調べた情報では「Nullを指定する」と書かれていたものもありました。Excel VBAでは、とりあえず「""」で正常に動作しましたが、VBなどから実行して取得できないときは、vbNullやNothingなども試してください。
ちなみにWindows Vistaで演奏時間を取得するには、ヘッダ番号「27」を指定します。