Cocoa AppleScript テキストファイルの入出力 UTF-8 TSVデータ作成 AppleScript [07]
AppleScript [07] Cocoa AppleScript 第3版 テキストファイルの入出力 UTF-8 TSVデータ作成
友人から「せっかくだから、テキストファイル入出力も...」と要望があったので、最後に「UTF-8 テキストファイル入出力」機能を付加。 (クリップボードと同一フォーマットの)タブ区切りの「TSVデータ」を作成するオリジナル関数と併せて公開!
Excel とのデータ受け渡しは、今までと同様テキスト あるいは クリップボードを利用。 データフォーマットは「UTF-8 CRLF改行コード タブ区切り」を想定! パラメータ区切りにも今回 LFではなく CRLF を利用したのは、「 Excelのセル内改行コードが LF 」のため区別が付くように...
(注) AppleScript にて、フォルダ選択ダイアログ あるいは ファイル選択ダイアログ を利用します!
2021/10/03 Ver. 3.2「Cocoa AppleScript 第3版」に改良!
→ AppleScript は "filePath.scpt" ファイル内のコード全て「差し替え」、VBAコードは「追加となります。(インターフェースとヘルパー用プロシージャ)
テキストエディタ等で閉じるのを忘れた場合(つまり、ファイルをオープンしたままだと)、メモリ不足など Mac が深刻な症状に陥る場合があります。 筆者もテストの際2、3度「やっちまった」次第で、いきなり Safari や Excelが終了してビックリ...
【AppleScriptの差し替え】 AppleScript [07] Cocoa AppleScript 第3版 テキストファイルの入出力 UTF-8 TSVデータ作成
まず、Excel メニューバーの [ヘルプ] - [更新プログラムのチェック] にて、適用されていないアップデートがあれば行ってください。
VBA の AppleScriptTask コマンド パラメータの注意点
ファイルパスと区別するため フォルダパス指定には 末尾に必ず / を付加 してください! フォルダフルパス なら 先頭と末尾が必ず / となります。
OneDrive や iCloud、Dropbox、Box 等のサービスをブラウザ利用でなくフォルダにリンクしている場合も(リンク)パスが判れば指定可能ですが、https:// が先頭に付いたり ネットワーク経由のアクセスのためとんでも無く時間がかかりますので ローカルPC(Mac本体内の高速なSSDやHDDドライブ)上のフォルダパスを指定してください。
第3版 Cocoa AppleScript コードの全置換(一部はVanilla AS記述)
(1) 以前に 作成したExcelファイルをマクロを有効にして開き、続いて VBEウィンドウ を開く。
(2) ~/ライブラリ/Application Scripts/com.microsoft.Excel/ フォルダ内に保存した filePath.scpt をダブルクリック等で("スクリプトエディタ"アプリにて)開き、 ファイル内の全AppleScriptコードを以下のコードで置換し、 コンパイル後に ファイルを保存 したら "スクリプトエディタ"アプリは終了してください。
上記の操作方法がよく解らない方は、 以前の投稿 をお読みください。
VBA、AppleScript 両方のコードに コメントをたくさん記述しておいたので、宜しければ ご覧ください!
2021/10/03 Ver. 3.2「Cocoa AppleScript 第3版」に改良!
→ AppleScript は "filePath.scpt" ファイル内のコード全て「差し替え」、VBAコードは「追加となります。(インターフェースとヘルパー用プロシージャ)
全置換となるため 以下の全AppleScriptコードを コピー&ペースト(貼り付け)後、 コンパイル後に ファイルを保存 してください。 VBAコード に関しては「次章」に記載します。
補足ですが、 AppleScript 44行目の「 property HIDDEN_FILES : true 」の true を fasle に置換して コンパイル後に ファイルを保存 すると、フォルダ階層(子フォルダ)に対応したパスやファイル名を返す AppleScriptTask の場合、 隠しファイルも表示 されるようになります。 確認後は、 true に戻すことをオススメします!
AppleScript "filePath.scpt" をダウンロード可能にしました。 Download Here
( ダウンロードしてダブルクリックすると、 "スクリプトエディタ.app" を起動! )
上記リンクを右クリックして「リンク先のファイルをダウンロード」等を選択してダウンロード可能。
( "Google Chrome" ブラウザの場合、上記リンクを右クリックして「名前を付けてリンク先を保存」を選択してダウンロード )
(注) [ Unicode(UTF-8) 、改行コードは LF ] ファイル置き場として、筆者の旧ブログを利用
ちなみに、 ret で始まる AppleScript の ハンドラー (VBAのプロシージャ相当の呼び出し単位)は Cocoa AS で主処理が実装されていますので、カスタマイズは慎重にお願いします。 その他の ハンドラー も Cocoa AS 実装の部分が判るように記述 しています。(何も記述が無ければ、Vannila AS ということ) Vanilla AS 部分はカスタマイズが楽で「 AppleScriptTask コマンド経由の呼び出し」ではなく、「 filePath.scpt をダブルクリック後に起動される スクリプトエディタ.app にて実行」すれば( Vanilla AS 部分の場合 )エラー発生箇所が判ります。 先頭部分の on test() から end test 内にサンプルのデバッグ用コードを記述済みのため、変更後に [command]+[K] でコンパイル、 test() の実行は [command]+[R] で可能です。 動作に問題が無い場合は [command]+[S] にて保存を忘れないように!
VBA だけでなく AppleScript コードも テキスト保存が可能なため、変更前に [command]+[A] にて全選択後 [command]+[C] でコピー してテキストエディタ等に [command]+[V] にてペースト(貼り付け)しておけば元に戻せます。 カスタマイズ作業前に filePath.scpt と AppleScriptTaskコマンドを記述したExcelファイル を ローカルPC上か クラウド領域にバックアップしておくと なお良いでしょう。
【VBA I/F追加】 AppleScript [07] Cocoa AppleScript 第3版 テキストファイルの入出力 UTF-8 TSVデータ作成
VBAコード の追加のため、末尾に 以降のコードを順番にコピー&ペースト(貼り付け)
'「Selection範囲」をクリップボードにコピー 後、「完了」メッセージを表示する
Sub CopyToClipboard()
Selection.Copy ' クリップボードにコピー
Application.CutCopyMode = False 'コピー範囲の解除
MsgBox "クリップボードにコピー【完了】" & vbNewLine & _
"[ " & Selection.Address(False, False) & " ]"
End Sub
テキストデータは今回 Selection(Excelシート上でセル選択した)範囲を対象として、タブ区切りのTSVデータを作成後に 書き込みます!
【注意】実行前に、データを作成する「対象シート(ActiveSheet)」を選択!
【TSVデータ作成、オリジナル関数】「クリップボードへコピー」されたTSVデータで、不都合がある場合の対処
'Selection範囲内の「Excel用TSVデータ」を作成する、オリジナル関数
'Excel TSV書式(UTF-8 CRLF改行コード 「列」毎に水平タブ[chr(09)]を挟む セル内改行コードはLF)
'クリップボードによるTSVデータ作成結果で、以下2つの問題に対処(必要なら対処を追加して下さい)
'[1] 1行単位で、「末尾の余分なタブコード」を削除
'[2] #NAME? 対策 → Cells(row, col).Formula「計算式」を利用(ただし、先頭の"="は削除)
Function CreateTsvDataFromSelection(newLineCode As String) As String
CreateTsvDataFromSelection = ""
Dim HT As String: HT = Chr(9) '「列」(フィールド)区切り用「水平タブ」コード HT
Dim row As Long, col As Long
Dim textData As String: textData = "" 'TSV(タブ区切りの)テキストデータ
Dim lineData As String: lineData = "" 'work用の「行」テキストデータ
'HT & 改行コード を挿入し、TSV(タブ区切りの)フォーマットのテキストデータを作成
'Excelの場合セル内改行コードは LF となるため、Macでも改行コード CRLF を利用すべき
'Selection(1)はSelection範囲の左上のセル、Selection(Selection.Count)は(同)右下のセルを示す
For row = Selection(1).row To Selection(Selection.Count).row
For col = Selection(1).Column To Selection(Selection.Count).Column
If col = Selection(Selection.Count).Column Then '「最終列」の処理
If IsError(Cells(row, col)) Then ' #NAME? 対策
lineData = lineData & Mid(CStr(Cells(row, col).Formula), 2) '先頭の"="を削除
Else
lineData = lineData & CStr(Cells(row, col).Text)
End If
Else '「最終列」以外の処理(末尾に、タブ区切りのコードを挿入)
If IsError(Cells(row, col)) Then ' #NAME? 対策
lineData = lineData & Mid(CStr(Cells(row, col).Formula), 2) & HT
Else
lineData = lineData & CStr(Cells(row, col).Text) & HT
End If
End If
Next col
'(1行単位で)末尾の余分な HT を削除
Do While (Len(lineData) <> 0 And (Right(lineData, 1) = HT))
lineData = Left(lineData, Len(lineData) - 1) '末尾の1文字(HT)を削除
Loop
If row = Selection(Selection.Count).row Then
textData = textData & lineData '最終行
Else
textData = textData & lineData & newLineCode '最終行以外は末尾に改行コードを挿入
End If
lineData = "" 'work用の「行」テキストデータを初期化
Next row
CreateTsvDataFromSelection = textData
End Function
↑ 「クリップボード」内に格納されるTSVデータで問題がある場合は、オリジナルなVBAコードでTSVデータを作成します!
① 行単位で「末尾の余分なタブコード」を削除
② #NAME? 対策
以上2つの問題に対処済みで、 必要なら対処を追加・変更して下さい!
【テキストファイル書き込み】Selection範囲を対象として、「クリップボードへコピー」または「TSVデータを自実装で作成」にて書き込みデータを作成
'UTF-8エンコードで、テキストデータをファイル書き込み(既に存在する場合は、置き換え)
' パラメータ[1] useCB As Boolean: false or true(クリップボードを利用するかどうか?)
' パラメータ[2] append As String: "create"(書き込み) or "append"(追記)
' パラメータ[3] newLineCode As String:"CRLF" or "LF" or "CR"(テキストデータ内の改行コード)
' 結果 true(書き込み成功 or 置き換え成功)、 false(失敗)
Function WriteTextFile(useCB As Boolean, append As String, newLineCode As String) As Boolean
On Error GoTo myError
WriteTextFile = False
Dim textData As String
Dim CRLF As String: CRLF = Chr(13) & Chr(10) 'vbCrLfで、 (0d0a)h がセットされなかったため
'Selection範囲の指定(1行目は「見出し行」を想定し、2行目以降を対象とする)
ActiveSheet.Select
Range("A2", ActiveCell.SpecialCells(xlLastCell)).Select '"A2" TSV出力したいセル範囲の開始セル
'MsgBox Selection.Address(False, False) ' ex) A2:D2039 1行目は「見出し」行のため
'ExcelTSVデータ UTF-8 CRLF改行コード 「列」毎に水平タブ[chr(09)]を挟む セル内改行コードはLF
If useCB Then
textData = ""
Call CopyToClipboard 'データの受け渡しに、クリップボードを利用する(範囲:Selection)
Else
textData = CreateTsvDataFromSelection(CRLF) '範囲:Selection、引数は(挿入)改行コード
End If
Dim filePath As Variant
Dim extList(2) As String '拡張子を2つ指定する場合
extList(0) = "tsv"
extList(1) = "txt" 'Excelで「タブ区切り」を選ぶと、拡張子は txt となるため
filePath = ""
' 指定した拡張子(配列)でない場合、再度ダイアログを表示
Do Until (filePath = False Or filePath <> "")
filePath = MAC_GetSaveAsFilename("fileName", extList)
Loop
If filePath = False Then 'ダイアログで「キャンセル」した場合、コピー保存しない
MsgBox "処理が「キャンセル」されました!" & vbCrLf & "( GetSaveAsFilename )"
Exit Function
End If
'以下は、AppleScriptTaskコマンドのパラメータ説明
' パラメータ区切りは、LF ではなく CRLF を利用!(Excel TSVファイルデータ対応)
' パラメータ[1] (書き込む)ファイルのフルパス
' パラメータ[2] Appendなら "append" 、Createなら "create" 文字列指定
' パラメータ[3] 改行コード "CRLF" 又は "LF" 又は "CR"
' パラメータ[4〜n]パラ3指定の改行コード区切りのUTF-8テキストデータ 連結してテキストデータとする
' 【注意】"" の場合は、クリップボード内のUTF-8テキストデータを書き込む
' 実行結果 書き込み(置き換え)エラー時は""、正常終了なら該当ファイルの「ファイル名」が返る
'Excel用TSVファイル(CRLF改行コード、タブ区切り「HT:Chr(09)」、セル内改行はLF)にて テスト済み
Dim scriptResult As String ' AppleScript 実行結果 (文字列)
Dim scriptParam As String ' AppleScript パラメータ(文字列)
'クリップボード利用時は、textData = ""
scriptParam = filePath & CRLF & LCase(append) & CRLF & UCase(newLineCode) & CRLF & textData
scriptResult = AppleScriptTask("filePath.scpt", "putTextFileAsUTF8", scriptParam)
If scriptResult <> "" Then
Rem MsgBox scriptResult '正常終了時、書き込みファイルの「ファイル名」が返る
WriteTextFile = True
End If
Exit Function
myError:
MsgBox "エラー発生!(WriteTextFile)"
End Function
WriteTextFile関数の利用方法(イミディエイト ウィンドウからテスト可!)
パラメータ[3]の改行コードは、 append 選択時 データの追記前に 挿入されます。
① ? WriteTextFile(True, "create", "CRLF") CB利用、ファイル作成時
② ? WriteTextFile(True, "append", "CRLF") CB利用、ファイル追記時
③ ? WriteTextFile(False, "create", "CRLF") 自実装、ファイル作成時
④ ? WriteTextFile(False, "append", "CRLF") 自実装、ファイル追記時
【注意】実行前に、データを作成する「対象シート(ActiveSheet)」を選択!
【テキストファイル読み込み】ファイル選択ダイアログで、指定テキストデータをUTF-8で読み込む(クリップボードにもセット)
' ファイル選択ダイアログで、指定テキストデータをUTF-8で読み込む(クリップボードにもセット)
Function ReadTextFile() As String
'Openダイアログを利用して、テキストデータをUTF-8エンコードで読み込む【クリップボードにもセット】
On Error GoTo myError
ReadTextFile = ""
'以下は、AppleScriptTaskコマンドのパラメータ説明
' パラメータ[1] プロンプト文字列:""なら、AppleScriptハンドラー設定の初期値
' パラメータ[2] 初期表示フォルダ:""なら、無指定(前回と同じフォルダを開く)
' パラメータ[3〜6]UTIを4つまで指定可能 ""(無指定)なら"public.plain-text"を利用→ *.tsv対象
' 実行結果[0〜n] エラー時は""、 正常終了なら テキストファイル全体を文字列として返す(改行コードに注意)
'Excel用TSVファイル(CRLF改行コード、タブ区切り「HT:Chr(09)」、セル内改行はLF)にて テスト済み
Dim scriptResult As String ' AppleScript 実行結果 (文字列)
Dim scriptParam As String ' AppleScript パラメータ(文字列)
'scriptParam = "ReadTextFile!" & vbLf & "/Users/username/" & vbLf & "public.plain-text"
scriptParam = "" & vbLf & "" & vbLf & ""
scriptResult = AppleScriptTask("filePath.scpt", "getTextFileAsUTF8", scriptParam)
'Debug.Print scriptResult 'for Debug【結果だけでなく、クリップボードにもセット】
ReadTextFile = scriptResult '改行コードに注意( CRLF 又は LF 又は CR を想定)
Exit Function
myError:
MsgBox "エラー発生!(ReadTextFile)"
End Function
ReadTextFile() を実行すると、 全件分 全行分のテキストデータが一度に「結果文字列」として返されます。 (クリップボードにも、同一結果を格納)
結果データは、 CRLF 又は LF 、CR の3種類想定している改行コードに注意して (Split関数等)処理する必要あり!
改行コードが CRLF かつ フィールド(項目)の区切りとして「タブコード HT:Chr(09)」を利用している場合は、クリップボードの中身をそのまま Excelワークシート上に [command]+[V] にて貼り付け可能です。
( macOS10以降、 Mac のデフォルトの改行コードは Unix系と同じ LF )
Office2016以降の Excel から AppleScriptTaskコマンドを利用すれば Windows版VBA と大差無く実装可能なことが、今回までの AppleScript 学習で判明しました! AppleScript まで覚えるのは Excelのみの連携であれば 負荷がかかりますが、AppleScript は Mac のデフォルトアプリのみではなく Adobe アプリ等との連携機能も豊富なため 覚えておいて損する事はないと思います。 Windows版VBA ではできるけど Mac版ではできないことや PDF操作連携などを実現する方法として、「Excel2019版 VBA入門」連載後に「AppleScript入門」もありかなと思いました。 次週以降は「VBA入門」に戻る予定ですが、必要であれば AppleScript で補完する方向で進めたいと思います。
[command] + [Q] にてまず VBE を終了し、Excel のウィンドウ内を選択して [command] + [Q] にて Excel も終了させます。 「作業中のブック」を保存するか確認のダイアログ画面が表示された場合は 「保存」しましょう。 「自動保存」済みの場合、保存するかどうかの確認ダイアログ画面は表示されません。
AppleScriptTask コマンドの結果文字列(エラーがあれば、空文字 "" を返す)だけでなく、クリップボードにも同じ内容(改行コードは異なる場合あり)をセットしているため、必要があれば「片方のみ」に変更してください。 ただし、「フルパスやファイル名以外」を返す結果文字列の場合 クリップボードにはセットしないため、「イミディエイト ウィンドウ」にて確認してください!
AppleScript から VBA に数百ファイル以上結果が返されるのであれば、大量データが渡されるオーバーヘッドも含め、クリップボードのみの利用(結果文字列は、正常終了/異常終了のみ判れば良い)がオススメです。 また、バックグラウンド処理前提の場合は 相互で クリップボードの中身を消してしまう可能性 があるため、結果文字列のみの利用が良いでしょう。
1日2時間くらい2ヶ月 AppleScript を勉強した成果として、今回の記事を書きました。 Cocoa AppleScript に関しては初心者のため、不具合があればコメント等で教えて頂けると嬉しいです。
最後まで読んでいただき、ありがとうございます。 また、お越しくださいませ。
// アタル
--Copyright 2021- ataruchi. [ https://twitter.com/ataruchi ]
--「スクリプトエディタ.app」に以下のAppleScriptを貼り付け後 [command]+[R] を実行すると、クリップボード内のテキストデータを「ファイル出力」【無条件、ReWrite】
--予め、Excelにてワークシート上の「セル領域を選択」後、[command]+[C] でクリップボードへコピー
--Excelでセル範囲を対象としてコピーすると、TSVデータ(UTF-8、CRLF改行コード、タブ区切り「HT:Chr(09)」、セル内改行はLF)がクリップボードに格納される
--テキストエディタでフィールドごとにタブで区切ったデータを、クリップボード格納してもOK
------------------------------------------------------------
use AppleScript version "2.4" -- macOS10.10 [Yosemite] ~
use scripting additions -- use OSAX
use framework "Foundation" -- use AppleScriptObjC (ASOC) = Cocoa AppleScript
activate
set theAlias to (choose file name default name "test.tsv") --「Save file」ダイアログ
return write_to_text_file_asUTF8(POSIX path of theAlias)
--UTF-8指定で、テキストデータのファイル書き出し
--クリップボード内のテキストデータを「出力」【無条件、ReWrite】そのままの改行コードを適用
--①ファイルのフルパス (POSIX path、UTF-8)
on write_to_text_file_asUTF8(filePath as text)
try
set textData to "" --初期化
--初期4096Byte(自動拡張)の NSMutableString object を生成
set mutableStr to (current application's NSMutableString's stringWithCapacity:4096)
-- 書き込むテキストデータの形式:(UTF-8、複数「列」なら「水平タブ:HT」を挟む)
if (clipboard info for «class utf8») is {} then --UTF-8テキストデータ?
activate
display dialog "★エラー★ クリップボードが空、又はUTF-8テキスト形式以外"
return false --実行を中断
else
set textData to (the clipboard as string) --そのままの改行コードが適用される
end if
mutableStr's appendString:textData --textDataを、NSMutableString に変換
--atomically:true→データは一時ファイルに書き込まれ、エラーが発生しなければ指定パス名にリネーム!
--つまり、ファイルの書き込みに失敗した場合、(既に同一ファイルが存在時)元のファイルのまま
set theResult to mutableStr's writeToFile:filePath atomically:true encoding:(current application's NSUTF8StringEncoding) |error|:(missing value) --UTF-8指定で出力
if (theResult as boolean) then
return true
else
activate
display dialog "★エラー★ テキストファイル書き出し 失敗"
return false
end if
on error --その他のエラー時
activate
display dialog "★エラー★ テキストファイル書き出し 失敗"
return false
end try
end write_to_text_file_asUTF8
------------------------------------------------------------
--Copyright 2021- ataruchi. [ https://twitter.com/ataruchi ]
--「スクリプトエディタ.app」に以下のAppleScriptを貼り付け後 [command]+[R] を実行すると、指定テキストファイルを読み込み、テキストデータをクリップボードにセット!
--実行後、Excelワークシート上に [command]+[V] で貼り付け可能
--Excelに貼り付け可能なテキストデータは、TSVデータ(UTF-8、CRLF改行コード、タブ区切り「HT:Chr(09)」、セル内改行はLF)
--テキストエディタ上にも [command]+[V] で貼り付け可能
------------------------------------------------------------
use AppleScript version "2.4" -- macOS10.10 [Yosemite] ~
use scripting additions -- use OSAX
use framework "Foundation" -- use AppleScriptObjC (ASOC) = Cocoa AppleScript
activate
set theAlias to (choose file) --「File」ダイアログ
return read_text_file_asUTF8(POSIX path of theAlias)
--テキストファイル(UTF-8)を読み込み、そのデータ全体をクリップボード(UTF-8)へ格納
--Excel用TSVファイル(CRLF改行コード、タブ区切り「HT:Chr(09)」、セル内改行はLF)にて テスト済み
on read_text_file_asUTF8(filePath as text) --POSIX path
try
set textData to "" --初期化
--テキストデータファイルを UTF-8 で読み込み【そのままの改行コードが適用される】
set theNSString to (current application's NSString's stringWithContentsOfFile:filePath encoding:(current application's NSUTF8StringEncoding) |error|:(missing value))
if theNSString is (missing value) then --NSString object の生成に失敗
error -128 --on error処理へ [注] -128 は、キャンセル時のエラー番号
end if
set textData to (theNSString as string) --(UTF-8)
set the clipboard to {} --クリップボードの初期化
set the clipboard to textData --読み込みファイルデータを、クリップボードへ格納(UTF-8)
return true --テキストファイル読み込み 成功
on error --エラー時
activate
display dialog "★エラー★ テキストファイル読み込み 失敗"
return false
end try
end read_text_file_asUTF8
------------------------------------------------------------