フォルダ階層(子フォルダ)&クリップボード 対応 フォルダ内の全ファイル名を取得 AppleScript [02]
](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3z81HVOHZNRyWluWW-psaPRo-5Zqv1UiUj483PvV572r4GLSYpqb6CL46gF5iNv8T3QeEh1DBjV9rI_HNrBcky-Hy30c62Z8smRuQ9owhRyX0pQFJ9ScGPT9xa6Uhpz58dx7oMgYj8FQ/s320/20210828_05.png)
AppleScript [02] 前回作成したAppleScriptを フォルダ階層(子フォルダ)&クリップボード 対応に!
前回作製した AppleScript コードを見直したら、子フォルダ&クリップボード対応はマストかと思い改良
・オススメの "Finder" 設定
・子フォルダ対応で、より汎用的に! →拡張子指定、初期表示フォルダ、プロンプト文字列変更 にも対応
・クリップボード対応で、より便利に! →Excelやテキストエディタに貼り付け可能
・AppleScript 7ハンドラー + 「再帰の子」ハンドラーを 作製
(注) AppleScript にて、フォルダ選択ダイアログ あるいは ファイル選択ダイアログ を利用します!
2021/08/31 AppleScript を「フィルタ参照による指定拡張子の抽出」版に変更
→ 差替をお願い致します
・(おまけ) ActiveWorkbook.Path が https://〜 を返す場合
【補足】Macユーザー向け Windows環境等と ファイルをやり取りする場合の問題点
(1) ファイルやフォルダー名の濁点( UTF-8-MAC )問題
(2) macOSで圧縮したファイルが Windowsで文字化け
【準備】 AppleScript [02] 前回作成したAppleScriptを フォルダ階層(子フォルダ)&クリップボード 対応に!
まず、Excel メニューバーの [ヘルプ] - [更新プログラムのチェック] にて、適用されていないアップデートがあれば行ってください。
オススメの "Finder" 設定
"Finder" 画面でファイルの「拡張子」が表示されていない方は、メニュー [Finder]-[環境設定...] にて「Finder環境設定」ダイアログを表示。
[詳細]タブを選択し一番上に表示される「すべてのファイル名拡張子を表示」チェックボックスをオンにする。
![AppleScript[02] Png01](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX_eZhb3sN_slj3Qq5MrQnNXkodXGO9xXH-mbyYkvZPGu-WTE5mtQmUIYaTExxuKceyjD6eZFBYakt-oxsmzs-R1TrJcrNbIL0OykdgmWIfwRMbfpMTdkgIu9m0X2GZ3u9zk0G2LmPWOA/s0/20210828_01.png)
上記画面のようにフォルダ階層を解りやすく表示させるため、"Finder" 画面の最下部に「パスバー」を表示させておくと便利です。
"Finder" メニュー [表示]-[パスバーを表示/非表示] にて交互に切り替え可能。
![AppleScript[02] Png02](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj004UZ3oNfz-EX0JzEMzbwwKD8ggtVVh_HlHxmw4iFjpzgBb5NbCbLwVKKhLsUwnLpWwm_B7jWjObiMV2y-R9Uvp-LC-GKjlong0hMZnueOxQez6cHHuiBFDxtcboMRBXxREN-gIRuBSs/s0/20210828_02.png)
上記画面のように "Finder" でファイルを選択後、「パスバー」に表示されるファイル名を右クリックして表示されるメニューから ["ファイル名.拡張子"のパス名をコピー] を選ぶと、クリップボードにファイル名のフルパスを格納。
"テキストエディタ" や "ステッキーズ" 画面に貼り付けして確認しましょう! "ユーザ" や ”ダウンロード” 等(通常)日本語表示されるフォルダ名が「正規フォルダ名」で表示されることを確認してください。
同様の操作で 「パスバー」のフォルダ表示部分を右クリックするとそのフォルダのフルパスが判明しますが(残念な事に)、末尾に / が付加されていないため 手動で付け加えましょう。
(Unix系で利用されている)POSIXパスでデイレクトリ(フォルダ)を正規に示す場合、末尾に / が必要 なためで、フルパス表示の場合は 先頭も / (ルートフォルダ)から始まる ことになります。
ご存知の方も多いと思いますが Mac も osX 以降カーネルが Unix系に変更され、その影響で os9 以前の改行コード CR =0Dh:Chr(13) がUnix系の LF =0Ah:Chr(10) に変更されました!
os9 までは HFSパス(区切り文字 : )がメインで利用されていたため、(現状でも)HFSパスで表示される場面によく遭遇します。(表示はアプリ次第で、 osX以降も 相互変換が可能)
ちなみに Windows も WinNT以降カーネルが(内部的に) Unix系に変更されていますが、改行コードは CRLF = 0D0Ah のままです。 Unixであることを隠さない Apple と そうでない Microsoft の姿勢の違いが見て取れますね。
ウンチクは忘れて構いませんが、 ファイルパスと区別するため フォルダパスには 末尾に必ず / を付加 してください! フォルダフルパス なら 先頭と末尾が必ず / となります。
改良した VBA & AppleScript コードへの置換
(1) 前回 作成したExcelファイルをマクロを有効にして開き、続いて VBEウィンドウ を開く。
(2) 全VBAコードを以下のコードで置換し、 コンパイル後に Excelファイルを保存
(3) ~/ライブラリ/Application Scripts/com.microsoft.Excel/ フォルダ内に保存した filePath.scpt をダブルクリック等で("スクリプトエディタ"アプリにて)開き、 ファイル内の全AppleScriptコードを以下のコードで置換し、 コンパイル後に ファイルを保存 したら "スクリプトエディタ"アプリは終了してください。
上記の操作方法がよく解らない方は、 前回の投稿 をお読みください。
VBA、AppleScript 両方のコードに コメントをたくさん記述しておいたので、宜しければ ご覧ください!
2021/08/31 AppleScript を「フィルタ参照による指定拡張子の抽出」版に変更 → 差替をお願い致します
VBAコード の(一括)ダウンロード Download Here
( ダウンロードしてダブルクリックすると、 "デフォルトのテキストエディタ" を起動! )
上記リンクを右クリックして「リンク先のファイルをダウンロード」等を選択してダウンロード可能。
( "Google Chrome" ブラウザの場合、上記リンクを右クリックして「名前を付けてリンク先を保存」を選択してダウンロード )
(注) [ Unicode(UTF-8) 、改行コードは LF ] ファイル置き場として、筆者の旧ブログを利用
AppleScript "filePath.scpt" のダウンロード Download Here
( ダウンロードしてダブルクリックすると、 "スクリプトエディタ.app" を起動! )
ダウンロード方法は、上記と同様。
【解説】 AppleScript [02] 前回作成したAppleScriptを フォルダ階層(子フォルダ)&クリップボード 対応に!
![AppleScript[02] Png03](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFFasydNOiBewzEFOaKA81L3Cl55JoJGlwvgDJgZ2M1vSMmX-Dps5WiD28CPxN00GCV1IfUNwFHbp_A82qg25qjxH50ceDfNPKWDPj7j9g3KEPuuXCB1JrJYaWYueGuD4prKRDlJMMPXk/s0/20210828_03.png)
上記画面は 以下3つを実現するために作成したヘルパー用のプロシージャ!
(1) AppleScriptTaskコマンド 実行結果(文字列)を イミディエイト ウィンドウ に表示
(2) VBAで クリップボードの内容を [A1:An] セルに貼り付け
(3) クリップボードの内容をVBAの変数に格納し、 イミディエイト ウィンドウ に表示
AppleScriptTaskコマンド 実行結果(文字列)は Macで表示しやすいよう区切り文字に LF (Unix系の改行コード)を挟んでいましたが、クリップボード出力は CRLF (Windows系の改行コード)を挟みました。
Excel がセル内改行コードとして既に LF を利用していて、 CRLF にしないと [command]+[V] で複数行に正しく貼り付けできないからです。
ActiveSheet.Paste Destination:=Range("A1")
上記VBAコードにて、「[A1] セル選択後に [command]+[V] 貼り付け操作」を代替可能。
AppleScriptTaskコマンド 実行結果(文字列)と同様 何もしなくても UTF-8 文字コードがクリップボードにも適用されるので、フォルダ名やファイル名に日本語が含まれていても問題無し。 正直、拍子抜けくらいに...
実装後に テキストエディタに [command]+[V] で貼り付けしても全く問題は無く、超絶便利! 自動判別不可の場合も手動で「UTF-8文字コード & CRLF改行コード」を設定すれば そのまま編集も可能です。
AppleScript から クリップボードのクリアと クリップボードにテキストデータを格納できるだけで、利用範囲はぐっと拡がります。 AppleScript から ShellScript(Unix コマンドも含む)呼び出しも可能なので!(何と、逆も可能です) (テキストデータ形式だけでも)クリップボード対応させるだけで、他アプリとの連携操作の敷居が低くなります。
むしろ苦労したのは、クリップボードの中身を VBA 変数に取り込むコードの実行が不安定な点でした! VBAがクリップボードとやり取りをするための「橋渡し役」 MSForms.DataObject が時折エラーが出るがコードの実行を再開すると(問題無く)動作するため、エラー発生時に3秒間待機してからエラーが起きたステートメントを再実行するコードにて対処済み。 VBA初心者は忘れがちですが、大きなデータを保持する変数やオブジェクトは(必要無くなったら直ぐに)メモリを解放するよう努めてください。
(注1) イミディエイト ウィンドウ はFIFO方式のバッファで領域が限られているため、多くの内容を表示させた場合 (最初の方の出力が消えてしまい)最後の方の出力しか表示できないことがあります。
今回だと 100ファイルとかたくさん表示させた場合などです。
(注2) バックグラウンドで実行(他の作業と同時進行)させたい場合、クリップボードの中身を消してしまう可能性があるため AppleScript と VBAコードから クリップボード対応を外すことをオススメします! その場合、実行結果文字列のみを利用してください。
処理が終了するまでフォアグラウンドで実行(他の作業を同時に行わない)する場合は もちろん問題はありません。 また、実行結果文字列は クリップボード領域と比べて格納できるサイズが限られているため、何百とか多くのファイルを格納したフォルダを対象とする場合は クリップボード利用をオススメします。 問題があれば、 AppleScript と VBAコードにて 実行結果文字列には 正常終了なら "@Successful@"、異常終了なら "@Unsuccessful@" を返すとか 変更が必要です。
① 選択したフォルダ階層(子フォルダを含む)に含まれるフォルダフルパスと全ファイル名を取得 【拡張子の指定あり】
パラメータ[1] プロンプト文字列: ""なら、AppleScriptコード設定の初期値
パラメータ[2] 初期表示フォルダ: ""なら、無指定(前回と同じフォルダを開く)
POSIXフルパス指定のため、先頭と末尾に / が必要 ex) "/Users/username/Downloads/"
パラメータ[3〜n]ファイル拡張子: "css" "html"のように 複数指定可
【実行結果】list(0〜n) 「(POSIX)フォルダフルパス」
あるいは「(拡張子付きの)ファイル名」
Sub test1()
Dim scriptResult As String ' AppleScript 実行結果 (文字列)、区切り文字 LF
Dim scriptParam As String ' AppleScript パラメータ(文字列)、区切り文字 LF
Dim list() As String ' 「パスorファイル名」格納用として「文字列の配列」を定義
' scriptParam = "フォルダ選択!" & vbLf & "/Users/username/" & vbLf & LCase("css")
scriptParam = "" & vbLf & "" & vbLf & LCase("scpt") & vbLf & LCase("xml") & vbLf & LCase("css")
scriptResult = AppleScriptTask("filePath.scpt", "getFileListOfChildFoldersMultiExt", scriptParam)
If scriptResult <> "" Then '「キャンセル」ボタン押下時も、空文字列が返る
list = Split(scriptResult, vbLf) 'vbLf = Chr(10) 区切り文字に LF を利用
Call DispArray(list) '実行結果(文字列)の表示
Erase list '配列の初期化
Call GetClipBoard 'クリップボードに格納したテキストデータを取得&表示
End If
End Sub
呼び出しされた AppleScript ハンドラーから 選択フォルダを対象として 「foldersHierarchies ハンドラー」が呼び出しされ、フォルダ内に子フォルダが存在する場合 再帰的に 自分自身(「foldersHierarchies ハンドラー」)を呼び出しします!
結果文字列の配列にて POSIXフォルダパス を示す場合は 先頭と末尾に / が付いているので、「(拡張子付きの)ファイル名」と簡単に区別可能。 次にPOSIXフォルダパスが表示されるまで、元のPOSIXフォルダパス と 「(拡張子付きの)ファイル名」を文字列連結すれば ファイルフルパスとなります!
![AppleScript[02] Png04](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmTcAjS3nKr4xlGJk2N52tIFc0fDjAUMAee3Gl7k1GYRubfX0_GnRRd0EnqMN45HWrVAjm-KhDsxtR0Sc5aZDn3T0Pjfj6DfWJJZ3WaiFZ3mNPBfa-vV7mBB18Evxv1QYYO2rNMpCfok8/s0/20210828_04.png)
![AppleScript[02] Png05](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3z81HVOHZNRyWluWW-psaPRo-5Zqv1UiUj483PvV572r4GLSYpqb6CL46gF5iNv8T3QeEh1DBjV9rI_HNrBcky-Hy30c62Z8smRuQ9owhRyX0pQFJ9ScGPT9xa6Uhpz58dx7oMgYj8FQ/s0/20210828_05.png)
![AppleScript[02] Png06](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXlapHe-vLCEl0Tg-ilcqB9dm3IcFM-pvoSOwW1kETF6yAKEoeUoFQxpyGnqFmd8y5VyMcs-UzN53Kktsk_p_OQmLq3tHzxrHucCWmvm9ypT4pqIU6dGzy7xb2pwkGsMshfAQEqkpEOII/s0/20210828_06.png)
② 選択したフォルダ階層(子フォルダを含む)に含まれるファイルのフルパスを取得 【拡張子の指定あり】
パラメータ[1] プロンプト文字列: ""なら、AppleScriptコード設定の初期値
パラメータ[2] 初期表示フォルダ: ""なら、無指定(前回と同じフォルダを開く)
POSIXフルパス指定のため、先頭と末尾に / が必要 ex) "/Users/username/Downloads/"
パラメータ[3〜n]ファイル拡張子: "css" "html"のように 複数指定可
【実行結果】list(0〜n) 「(POSIX)ファイルフルパス」
Sub test2()
Dim scriptResult As String ' AppleScript 実行結果 (文字列)、区切り文字 LF
Dim scriptParam As String ' AppleScript パラメータ(文字列)、区切り文字 LF
Dim list() As String ' 「パスorファイル名」格納用として「文字列の配列」を定義
' scriptParam = "フォルダ選択!" & vbLf & "/Users/username/" & vbLf & LCase("css")
scriptParam = "" & vbLf & "" & vbLf & LCase("scpt") & vbLf & LCase("xml") & vbLf & LCase("css")
scriptResult = AppleScriptTask("filePath.scpt", "getPathListOfChildFoldersMultiExt", scriptParam)
If scriptResult <> "" Then '「キャンセル」ボタン押下時も、空文字列が返る
list = Split(scriptResult, vbLf) 'vbLf = Chr(10) 区切り文字に LF を利用
Call DispArray(list) '実行結果(文字列)の表示
Erase list '配列の初期化
Call GetClipBoard 'クリップボードに格納したテキストデータを取得&表示
End If
End Sub
呼び出しされた AppleScript ハンドラーから 選択フォルダを対象として 「foldersHierarchies ハンドラー」が呼び出しされ、フォルダ内に子フォルダが存在する場合 再帰的に自分自身(「foldersHierarchies ハンドラー」)を呼び出しします!
![AppleScript[02] Png07](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_KrvvOpquK3YZVeIu17mcTIIV1Jve-EVxnHrpubE_qMTr5GFU33v3I-kBQ57LkytvobIALqosSmdCi0illj7WNHwycaPZSsdTx5br11jeEZMhn1SAWN6IMtkTTXDuXJ_ITmoX9uTwiNA/s0/20210828_07.png)
![AppleScript[02] Png08](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwDvLX-29FtONAxSYYOFndsODBIuEAtr_9YkOrXKW0IXqOOs55jbyHxTXYKMOVVP26L0ZQ_7mNcRlagO7-hyC91DxVD_QVGlkR3UFC3-tIB9SpEU3WaoQ-2iJr0PiH6tHiaJwc4oNm0Ek/s0/20210828_08.png)
③ 選択フォルダフルパスと「(拡張子なしの)全ファイル名」を取得 【拡張子を1つだけ指定】
パラメータ[1] プロンプト文字列: ""なら、AppleScriptコード設定の初期値
パラメータ[2] 初期表示フォルダ: ""なら、無指定(前回と同じフォルダを開く)
POSIXフルパス指定のため、先頭と末尾に / が必要 ex) "/Users/username/Downloads/"
パラメータ[3〜n]ファイル拡張子: "css" のように 拡張子を1つだけ指定
【実行結果】list(0) 「(POSIX)フォルダフルパス」
list(1〜n)「(拡張子なしの)ファイル名」
Sub test3()
Dim scriptResult As String ' AppleScript 実行結果 (文字列)、区切り文字 LF
Dim scriptParam As String ' AppleScript パラメータ(文字列)、区切り文字 LF
Dim list() As String ' 「パスorファイル名」格納用として「文字列の配列」を定義
' scriptParam = "フォルダ選択!" & vbLf & "/Users/username/" & vbLf & LCase("css")
scriptParam = "" & vbLf & "" & vbLf & LCase("scpt")
scriptResult = AppleScriptTask("filePath.scpt", "getFileListOfFolderExt", scriptParam)
If scriptResult <> "" Then '「キャンセル」ボタン押下時も、空文字列が返る
list = Split(scriptResult, vbLf) 'vbLf = Chr(10) 区切り文字に LF を利用
Call DispArray(list) '実行結果(文字列)の表示
Erase list '配列の初期化
Call GetClipBoard 'クリップボードに格納したテキストデータを取得&表示
End If
End Sub
![AppleScript[02] Png09](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8ngGfNV-LU3HCfp4eEBVbKhLbNsCxULZkgR1ryzHT2qAJ83S_fTVqAJoP1OFmUA1FnQLpyCPpFIuy64eE8pkxQiNErxx5HfbQka6SSrKs5d8O1EXIsuAXBnD9n9RdT9omnr1c3uRAnoI/s0/20210828_09.png)
![AppleScript[02] Png10](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgllyhHdyUQYdNmYH8xPAgqWs55GR2nsPqs0B01_va-FyVp6C1LTTo-KUFBLtEkdN1uOCfQrwANcT85naeDD_OjhNG_XEQ3v7nRY8JgCJswy5MU7oqP0Z-9eUk_kZIjh_6dd1t1NKRi3cY/s0/20210828_10.png)
④ 選択フォルダフルパスと「(拡張子付きの)全ファイル名」を取得 【拡張子の指定あり】
パラメータ[1] プロンプト文字列: ""なら、AppleScriptコード設定の初期値
パラメータ[2] 初期表示フォルダ: ""なら、無指定(前回と同じフォルダを開く)
POSIXフルパス指定のため、先頭と末尾に / が必要 ex) "/Users/username/Downloads/"
パラメータ[3〜n]ファイル拡張子: "css" "html"のように 複数指定可
【実行結果】list(0) 「(POSIX)フォルダフルパス」
list(1〜n)「(拡張子付きの)ファイル名」
Sub test4()
Dim scriptResult As String ' AppleScript 実行結果 (文字列)、区切り文字 LF
Dim scriptParam As String ' AppleScript パラメータ(文字列)、区切り文字 LF
Dim list() As String ' 「パスorファイル名」格納用として「文字列の配列」を定義
' scriptParam = "フォルダ選択!" & vbLf & "/Users/username/" & vbLf & LCase("css")
scriptParam = "" & vbLf & "" & vbLf & LCase("scpt") & vbLf & LCase("xml") & vbLf & LCase("css")
scriptResult = AppleScriptTask("filePath.scpt", "getFileListOfFolderMultiExt", scriptParam)
If scriptResult <> "" Then '「キャンセル」ボタン押下時も、空文字列が返る
list = Split(scriptResult, vbLf) 'vbLf = Chr(10) 区切り文字に LF を利用
Call DispArray(list) '実行結果(文字列)の表示
Erase list '配列の初期化
Call GetClipBoard 'クリップボードに格納したテキストデータを取得&表示
End If
End Sub
![AppleScript[02] Png11](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdHpddH-YLL_sEHppmDI-wjsgDFe7HQGsM_i5e-MwIIe4zUv5vPurLnjcfnDzK9dmckrUKyupj9K1PVSpGEob144xlPdaShcuK4pKBj-qjioEzXR6MwErKgMJ8ckVbvZ-njscprvwA3Wc/s0/20210828_11.png)
![AppleScript[02] Png12](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNJlmtsGXm4ocTMcOyEnXmE1rBYSzwtw8ecs_w9fhgM0SL05DRYIKJqNuTC75Ldg1ml_4v4BFxnJVrytIqo0oy67ayd6P8szrDE1swz05n8hi9cLP7BiOWHcMPTOUTxW_6O2Wxo1U3PPA/s0/20210828_12.png)
⑤ 選択フォルダフルパスと「(拡張子付きの)全ファイル名」を取得 【拡張子の指定なし】
パラメータ[1] プロンプト文字列: ""なら、AppleScriptコード設定の初期値
パラメータ[2] 初期表示フォルダ: ""なら、無指定(前回と同じフォルダを開く)
POSIXフルパス指定のため、先頭と末尾に / が必要 ex) "/Users/username/Downloads/"
【実行結果】list(0) 「(POSIX)フォルダフルパス」
list(1〜n)「(拡張子付きの)ファイル名」
Sub test5()
Dim scriptResult As String ' AppleScript 実行結果 (文字列)、区切り文字 LF
Dim scriptParam As String ' AppleScript パラメータ(文字列)、区切り文字 LF
Dim list() As String ' 「パスorファイル名」格納用として「文字列の配列」を定義
' scriptParam = "フォルダ選択!" & vbLf & "/Users/username/"
scriptParam = "" & vbLf & ""
scriptResult = AppleScriptTask("filePath.scpt", "getFileListOfFolder", scriptParam)
If scriptResult <> "" Then '「キャンセル」ボタン押下時も、空文字列が返る
list = Split(scriptResult, vbLf) 'vbLf = Chr(10) 区切り文字に LF を利用
Call DispArray(list) '実行結果(文字列)の表示
Erase list '配列の初期化
Call GetClipBoard 'クリップボードに格納したテキストデータを取得&表示
End If
End Sub
![AppleScript[02] Png13](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_QbcOtlmt3h7VSM77e4Vec_bSFghxKL_aIHa3eW_FDCbcTnQ7umOaSLE5dS4bJxf8fbxSI3kWoDkybd4pOgZEKDIisEoHVJkXq0RAxgFjOCwz3NvF9YPh-RWel_-X8LiXoFMv0Vj8Ee8/s0/20210828_13.png)
![AppleScript[02] Png14](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgviCtTrjypRV9mvV_HnNDMEfhtYdgZU5Wp3U5JODHFYNxxNELvEBLRNZQNac4_LicJsgt-GdqXaIUWfXEQ7Sqpf9Tscry9hM5koJYekd2tPbTJLVAKbC7xJygFX_J0tp9oSK0szIrVgoY/s0/20210828_14.png)
⑥ 「単一」ファイル選択ダイアログで、フルパスを取得 【拡張子の限定あり】
パラメータ[1] プロンプト文字列: ""なら、AppleScriptコード設定の初期値
パラメータ[2] 初期表示フォルダ: ""なら、無指定(前回と同じフォルダを開く)
POSIXフルパス指定のため、先頭と末尾に / が必要 ex) "/Users/username/Downloads/"
パラメータ[3〜n]ファイル拡張子: "css" "html"のように 複数限定可 (厳密だとUTIを4つまで)
【実行結果】list(0) 「(POSIX)フォルダフルパス」
list(1) 「(拡張子付きの)ファイル名」
Sub test6()
Dim scriptResult As String ' AppleScript 実行結果 (文字列)、区切り文字 LF
Dim scriptParam As String ' AppleScript パラメータ(文字列)、区切り文字 LF
Dim list() As String ' 「フルパス」格納用として「文字列の配列」を定義
' scriptParam = "単一ファイル選択!" & vbLf & "/Users/username/" & vbLf & LCase("xml")
scriptParam = "" & vbLf & "" & vbLf & LCase("scpt") & vbLf & LCase("xml") & vbLf & LCase("css")
scriptResult = AppleScriptTask("filePath.scpt", "getFilePath", scriptParam)
If scriptResult <> "" Then '「キャンセル」ボタン押下時も、空文字列が返る
list = Split(scriptResult, vbLf) 'vbLf = Chr(10) 区切り文字に LF を利用
Call DispArray(list) '実行結果(文字列)の表示
Erase list '配列の初期化
Call GetClipBoard 'クリップボードに格納したテキストデータを取得&表示
End If
End Sub
![AppleScript[02] Png15](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY2FUMj9twiJaCjMWrYHu3pDEbqB4aOAEJHx5DSKDvYNyAQpkm9XwKhGcuySZG9d5vdCNzI0Vr0o13YEC3Ps10OWGfFAL2AYFLE1ukDkwwiJ3JmYVyybAHRA69wngvSDS3bz-sFnVS4yk/s0/20210828_15.png)
![AppleScript[02] Png16](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgDLd9WD9pnSZCND_KkSFwh03t72bcudOevWDiKyvHlfXOJk8KQ621CuIfY3pIZUA731U2ueEycCKeactWdfCrjVAAUUzC7ioiQ5dk84S-RjqrPDYmvGCT5CNz-PZXQZTi8HI09b8XTs4/s0/20210828_16.png)
⑦ 「複数」ファイル選択ダイアログで、フルパスを取得 【拡張子の限定あり】
パラメータ[1] プロンプト文字列: ""なら、AppleScriptコード設定の初期値
パラメータ[2] 初期表示フォルダ: ""なら、無指定(前回と同じフォルダを開く)
POSIXフルパス指定のため、先頭と末尾に / が必要 ex) "/Users/username/Downloads/"
パラメータ[3〜n]ファイル拡張子: "css" "html"のように 複数限定可 (厳密だとUTIを4つまで)
【実行結果】list(0) 「(POSIX)フォルダフルパス」
list(1〜n)「(拡張子付きの)ファイル名」
Sub test7()
Dim scriptResult As String ' AppleScript 実行結果 (文字列)、区切り文字 LF
Dim scriptParam As String ' AppleScript パラメータ(文字列)、区切り文字 LF
Dim list() As String ' 「フルパス」格納用として「文字列の配列」を定義
' scriptParam = "複数ファイル選択!" & vbLf & "/Users/username/" & vbLf & LCase("xml")
scriptParam = "" & vbLf & "" & vbLf & LCase("scpt") & vbLf & LCase("xml") & vbLf & LCase("css")
scriptResult = AppleScriptTask("filePath.scpt", "getMultiFilePath", scriptParam)
If scriptResult <> "" Then '「キャンセル」ボタン押下時も、空文字列が返る
list = Split(scriptResult, vbLf) 'vbLf = Chr(10) 区切り文字に LF を利用
Call DispArray(list) '実行結果(文字列)の表示
Erase list '配列の初期化
Call GetClipBoard 'クリップボードに格納したテキストデータを取得&表示
End If
End Sub
![AppleScript[02] Png17](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR7YICyyd1ATX90l3ojnLjfBdH5GMH933Yyxb0WVXfPFHZoX1rtmK6s7bLjtEm5nTdOgQ02groiYtJ4EhN92efSJxvl78xWZYfcwBMo0UNCO40my-COZrIdUgd6E2kjr9kas0uOSg0N0k/s0/20210828_17.png)
![AppleScript[02] Png18](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPMcdTD4mke82g7jpJbbG6tJatFQq9vQGp69_RPTXgI4784nFpZSJ_YrZW4oDVQE088iffhApmCchyphenhyphen2yagnd7GV2uyT9NOWZUD4PxG2ujxPlQWu271QtgN8_t57Zivzn5AHrYafeaRfII/s0/20210828_18.png)
![AppleScript[02] Png21](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5_yR26SKvH0VzTjxNaKEtLJYtk0xQ8-JEuFH5Rslw2bhyphenhyphenHIp5k-k1aH9vRKFPrfsywh1HK4oi03EHIQ4qdr1X4CrAVymQF_TLCqKoJMR0kahILgWB6WS06sL8u5ytTf90uBmuS6k0jQA/s0/20210828_21.png)
上の画面のように "png" "pdf" の拡張子で限定した場合は "ファイル選択ダイアログ" 画面上の「限定」が有効(グレーで選択不可のアイコンが見て取れます)ですが、 "scpt" "xml" "css" の場合は「限定」が無効で すべてのファイルが選択可能でした。
厳密には「拡張子」ではなく「UTI (Uniform Type Identifier)」による限定のため「無効」になる場合があるようですが、その仕組みを筆者が理解できてなくて申し訳ありません。 Mac の場合 デフォルトで起動されるアプリが「拡張子」のみでは決定されないためで、(Macintoshの頃からお使いの方はご存知だと思いますが)元々「拡張子」を付ける必要もありませんでした。 他OSとファイルをやり取りする時だけ、「拡張子」を付加した時代もあったのです!
「拡張子」と「UTI」の相互変換用 Cocoa関数が存在するので、「拡張子」から「UTI」へ変換された後に "ファイル選択ダイアログ" 画面上の「限定」が行われる過程に問題があるようです。 ちなみに「UTI」は階層構造で、 public.text の配下に public.html public.xml public.source-code など、public.image の配下に public.jpeg public.png などが存在し、 Mac の クリップボード でもデータ種別判別のために利用されているそうです。
[command] + [Q] にてまず VBE を終了し、Excel のウィンドウ内を選択して [command] + [Q] にて Excel も終了させます。 「作業中のブック」を保存するか確認のダイアログ画面が表示された場合は 「保存」しましょう。 「自動保存」済みの場合、保存するかどうかの確認ダイアログ画面は表示されません。
1日2時間くらい2週間 AppleScript を勉強した成果として、今回の記事を書きました。 AppleScript に関しては初心者のため、実行速度に問題があります!
1ファイルごと(拡張子取得後に拡張子を比較して)拡張子指定を行なっているため
2021/08/31 「フィルタ参照による指定拡張子の抽出」版に変更しましたが、 フォルダ内に100ファイルほど存在すると (C言語系で実装した高速なAPI利用でないと) それなりに時間がかかります。 Cocoa API を直利用したコード(Windows APIを直利用するようなもの)に書き換えると劇的に速くなるそうですので、もう少し学習してから実装する予定です。 また、クリップボード領域はアプリ間で共有する最上位のグローバルなメモリ領域 かつ 文字列と比べれば大容量なため、実行結果(文字列)は成功か失敗のみセット かつ クリップボードにのみ結果を格納すれば、もう少し簡潔なコードになるはず...
テストは結構しましたが、不具合があればコメント等で教えて頂けると嬉しいです。
ごく一部の操作だけですが、AppleScript にて Excelシート に直接アクセスして セルの値を参照もしくはセットとかできるみたいなので、次週は それを テストしてみるつもりです!
(おまけ) ActiveWorkbook.Path が https://〜 を返す場合
以下のVBAコードにて、実行しているExcelブックの ファイルフルパス が確認できるはずです。
MsgBox ActiveWorkbook.Path & Application.PathSeparator & ActiveWorkbook.Name
あるいは
Debug.Print ActiveWorkbook.Path & Application.PathSeparator & ActiveWorkbook.Name
下記画面は [OneDrive]-[ドキュメント] フォルダ内に保存した Excelブックを開いた場合の実行結果!
![AppleScript[02] Png19](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOquzTGUNVBrfgMqHShkDOvIjf32fMxlA9cZciU2MebFQkyNaf_T5tgH1B_rzMVRIIcSDCq0Qow_Tk8yhdDf12Kzy2-QAdcoRwIhytet43hY_mMV66idS1-lx2O-_Fk7F-GUZhKDjKcwo/s0/20210828_19.png)
Cloud 上に自動保存されない ローカル(コンピューター)領域に 上記ファイルをコピーして ダブルクリックで起動すれば、 ActiveWorkbook.Path が期待したパスを返すはずです。
下記は( Cloud 対象領域でない場合が多い) [共有] フォルダにコピーして、実行した例です。
「 https:// 〜 /ドキュメント/ 」までは「 OneDrive 配下の ドキュメント フォルダ」であることを示しているため、VBAにて「 /Users/username/OneDrive/ドキュメント/ 」に置き換える実装もありかと思います!
(注) 「ホームフォルダ」内に「OneDrive」フォルダを作成して、 OneDrive 利用の場合
ex) /Users/wito/OneDrive/ドキュメント/Test_AppleScript_1.xlsm
![AppleScript[02] Png20](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAaE7ElSOx4RIjwXnRTE1QSrbnMvM2yOoU8-FZ0H79lPHzGqVwBhMfI2wL43hZY_STkbNZ5lhAcURHFWQ8aQDmc0U1oJkunBKC5I6ipCP9uJc8fqduB07fG7rcS-YOYqx_dfiuXEzLV3M/s0/20210828_20.png)
ActiveWorkbook.Path が期待するローカル(コンピューター)のパスを返さない場合、OneDrive 等の Cloud保存のファイルを(ダウンロードして)直接開いている ケースがほとんどです!
あたかもローカル(コンピューター)のみに保存されているように見えますが、実体は Cloud上に保存(バックアップ)され オフライン(ネットにアクセスできない)状況に備えそのコピーがローカル(コンピューター)に保存される仕組みが主流ですので... ネットにさえ接続できれば、一定の間隔で Cloud 上に自動バックアップされるためファイルの保守も容易になり、他のパソコンから開くこともできるため欠点は少ないはずです。 オフラインで使用した場合 次にネットに接続された際に Cloud 上に保存され、ローカル(コンピューター)との同期が取られます。
特に OneDrive は Microsoft365(旧Office365)契約者に 1TB (1000GB) を付与しているため、設定を変更しないと デスクトップやユーザ領域(いわゆるホームフォルダ)に作成したファイルを OneDrive 対象にしがちです。 インターネット環境が高速になればなるほどこの流れは加速していき、OS自体も Cloud 上のサーバーで動作させる未来も近付きつつあります! Windows365 はまだビジネスユーザ向けですが「まさにそれ」で、モニタ(ディスプレイ)に結果が直ぐに表示されればOSを実行するマシンはどこに存在しても関係ありません。 むろん、セキュリティは重要ですが...
最後まで読んでいただき、ありがとうございます。 また、お越しくださいませ。
// アタル