« メモ.appインポートAppleScriptを作ってみた[更新] | トップページ | Mac用Gimp2.8.2の公式Native版[更新] »

2012年8月23日 (木)

メモ.appエクスポートAppleScriptを作った[更新]

先日のインポート Script に引き続き、メモ.app の各メモをエクスポートする AppleScript を作った。

メモ.app の1つのフォルダ内にあるすべてのメモを書き出す、という仕様である。

リッチテキスト形式で書き出すか、プレーンテキスト形式で書き出すかを選べるようになっており、プレーンテキストの場合は更に1つのファイルに結合させることもできる。

但し、リッチテキストの場合でも画像は書き出せない。

また、既知の問題として、一件のメモが 100KB を超えている場合、うまく書き出せない。結合する場合も、結合後のファイルのサイズが 100KB を超えているなら結合に失敗する。

なお万が一、このスクリプトを使用して損害を被ったとしても、筆者は一切の責任は負わないので、あしからずご了承願います。

※注記(2016-09-21):
macOS Sierra 10.12.0 の時点では下の画像の通り Apple Script の選択ダイアログボックスにバグがある

今後、10.12.1 以降で修正されるかもしれない。その場合はこの注記は無視してくだきたい。



(2014/04/14更新:各メモのタイトル(=一行目)にコロンやスラッシュが含まれているとエクスポートに失敗する問題を修正)


-- スクリプト次行から --

 (*
 メモ.appの特定のフォルダー内のテキストをプレーンテキストに変換し、書き出すスクリプト。
 リッチテキストとして書き出すか、プレーンテキストとして書き出すか、選択できる。
 1つのファイルにまとめて書き出すこともできる。
 
 既知の問題:
 ファイルサイズが大きすぎると書き込めない?ようだ(大きなファイルを分割したら書き込めた)。
 105000くらいまで可?105128 OK だった。
 *)
 
 tell application "Notes"
   set folderList to name of every folder of account "iCloud"
   --「メモ」フォルダーの実体は Notes という名前なので、考慮する
   set modified_folderList to {}
   repeat with fL in folderList
     if (fL as text) = "Notes" then set fL to "メモ"
     if (fL as text) = "false" then set fL to "false\t" --falseというフォルダー名だとキャンセルされてしまうので回避
     set the end of modified_folderList to fL
   end repeat
   
   repeat
     set folderName to (choose from list modified_folderList with prompt "「メモ」アプリ内のメモをエクスポートします。\n\nまず対象となる「メモ」アプリ内のフォルダ名を指定してください。\n\n※注意:\n一件のメモのサイズが100KBを超えている場合、エクスポートに失敗します。")
     set folderName to (folderName as text)
     if folderName is "false" then error number -128 --キャンセルボタンを押した場合の処理
     if folderName is "false\t" then set folderName to "false"
     set display_fname to folderName --あとで表示する際、「メモ」フォルダが「Notes」になるのを回避
     if folderName is "メモ" then set folderName to "Notes"
     
     set all_note_ids to id of every note of folder folderName of account "iCloud"
     
     set exnotes_count to length of all_note_ids
     if exnotes_count > 50 then
       display dialog "50件以上のメモが含まれたフォルダが指定されました。エクスポートに時間がかかるかもしれません。続けますか?" buttons {"中止", "やり直す", "続ける"} default button 3
       set bReturned to button returned of result
       if bReturned is "中止" then
         error number -128
       else if bReturned is "続ける" then
         exit repeat
       end if
     else if exnotes_count < 1 then
       display dialog "指定されたフォルダにはメモが含まれていません。" buttons {"中止", "やり直す"} default button 2
       set bReturned2 to button returned of result
       if bReturned2 is "中止" then
         error number -128
       end if
     else
       exit repeat
     end if
   end repeat
   
   set export_folder to choose folder with prompt "エクスポートされるメモをどこに保存しますか?"
   tell application "Finder"
     set export_folder_name to name of export_folder --あとで表示する
   end tell
   
   set exfolder_items to list folder export_folder
   set new_folder to folderName
   if new_folder as string is "Notes" then set new_folder to "メモ"
   if (new_folder as string) starts with "." then set new_folder to "dot" & new_folder --ドットで始まるフォルダの不可視化を回避
   --作成するフォルダー名にコロンやスラッシュが含まれるのを回避する。
   if ((new_folder as string) contains ":") or ((new_folder as string) contains "/") then
     set new_folder to my replace_text(new_folder, ":", "_")
     set new_folder to my replace_text(new_folder, "/", "_")
   end if
   
   repeat --作成するフォルダの名前の重複チェック
     set nf_tmp to new_folder
     set repeat_flag to 0
     repeat with ei in exfolder_items
       if ((ei as text) = nf_tmp) then
         set new_folder to new_folder & " (メモエクスポート)"
         set repeat_flag to repeat_flag + 1
       end if
     end repeat
     if repeat_flag < 1 then exit repeat
   end repeat
   
   display dialog "リッチテキストとして書き出しますか? それともプレーンテキストとして書き出しますか?\n\nプレーンテキストの場合、あとで1つに統合することもできます。" buttons {"リッチテキスト", "プレーンテキスト"} default button 1
   set bReturned3 to button returned of result
   if bReturned3 is "リッチテキスト" then
     set conv_form to "rtf"
   else
     set conv_form to "txt"
   end if
   
   display dialog "最終確認です。\n\n「メモ」アプリの「" & display_fname & "」フォルダの全メモを、「" & export_folder_name & "」内の「" & new_folder & "」内に " & conv_form & " 形式でエクスポートします。"
   
   tell application "Finder"
     make new folder at export_folder with properties {name:new_folder}
   end tell
   set newf_path to ((export_folder as text) & new_folder & ":")
   
   repeat with note_id in all_note_ids
     set note_name to name of note id note_id
     
     --作成するテキストファイルの名前の重複チェック
     set newf_items to list folder newf_path
     set new_txt to note_name
     repeat
       set tx_tmp to (new_txt & ".txt")
       set rt_tmp to (new_txt & ".rtf")
       set repeat_flag2 to 0
       repeat with nfi in newf_items
         if ((nfi as text) = tx_tmp) or ((nfi as text) = rt_tmp) then
           set new_txt to new_txt & " 2"
           set repeat_flag2 to repeat_flag2 + 1
         end if
       end repeat
       if repeat_flag2 < 1 then exit repeat
     end repeat
     
     set bodyText to body of note id note_id
     
     if bodyText contains "</head" then
       set bodyText to my replace_text(bodyText, "</head", "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\"></head")
     else if bodyText contains "<html>" then
       set bodyText to my replace_text(bodyText, "<html>", "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\"></head>")
     else if bodyText contains "<body" then
       set bodyText to my replace_text(bodyText, "<body", "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\"><body")
     else
       set bodyText to "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\"></head>" & bodyText
     end if
     
     -- new_txt にコロンやスラッシュが含まれているとエラーが出るので回避する。
     set tmp_txt to new_txt
     if ((tmp_txt as string) contains ":") or ((tmp_txt as string) contains "/") then
       set tmp_txt to my replace_text(tmp_txt, ":", "_")
       set tmp_txt to my replace_text(tmp_txt, "/", "_")
     end if
     
     set tmp_file_path to "/private/tmp/" & tmp_txt & ".html"
     delay 0.25
     try
       do shell script "/bin/echo -n " & quoted form of (bodyText as Unicode text) & " > " & quoted form of tmp_file_path
     on error
       display dialog "エラー!\n\n" & tmp_file_path & " への書き込みができない。"
     end try
     
     set output_path to POSIX path of (newf_path & tmp_txt & "." & conv_form)
     try
       do shell script "textutil -convert " & conv_form & " -output " & quoted form of output_path & " " & quoted form of tmp_file_path
     on error
       display dialog "エラー!\n\n" & tmp_file_path & " のコンバートができない。"
     end try
     delay 0.25
     try
       do shell script "rm " & quoted form of tmp_file_path
     on error
       display dialog "エラー!\n\n" & tmp_file_path & " の削除ができない。"
     end try
   end repeat
   if conv_form is "rtf" then
     display dialog "完了しました。" buttons {"終了"} default button 1
   else
     display dialog "完了しました。\n\n\n\nエクスポートされた全ファイルを1つにまとめることもできます。まとめる場合は 結合ボタン を押してください。\n\n※注意:\n結合後のサイズが100KBを超えている場合、結合に失敗します。" buttons {"結合", "終了"} default button 2
     set bReturned4 to button returned of result
     if bReturned4 is "終了" then
       error number -128
     else
       (* これより結合モード *)
       set newf_items to list folder newf_path
       --ここでアイテムを決めておく。結合されたファイルを除外できる
       --結合ファイルの名前を決める
       set new_txt to "(結合) " & new_folder & ".txt"
       repeat
         set tx_tmp to new_txt
         set repeat_flag3 to 0
         repeat with nfi in newf_items
           if (nfi as text) = tx_tmp then
             set new_txt to "(結合) " & new_txt
             set repeat_flag3 to repeat_flag3 + 1
           end if
         end repeat
         if repeat_flag3 < 1 then exit repeat
       end repeat
       set output_path to POSIX path of (newf_path & new_txt)
       
       set all_text to {}
       repeat with nfi in newf_items
         if (nfi as text) ends with ".txt" then
           set p_path to POSIX path of (newf_path & nfi)
           try
             set text_contents to do shell script "cat < " & quoted form of p_path without altering line endings
           on error
             display dialog "エラー!\n\n" & p_path & " が読み込めない。"
           end try
           set the end of all_text to text_contents
         end if
       end repeat
       
       --配列を一定の文字列で結合する
       set join_tmp to AppleScript's text item delimiters
       set ost_items to every text item of all_text
       set AppleScript's text item delimiters to "-----\n"
       set one_all_text to ost_items as string
       set AppleScript's text item delimiters to join_tmp
       
       try
         do shell script "/bin/echo -n " & quoted form of one_all_text & " > " & quoted form of output_path
       on error
         display dialog "エラー!\n\n" & output_path & " に書き込めない。"
       end try
       
       display dialog "完了しました。\n\n結合されたテキストは\n\n「" & new_txt & "」\n\nという名前です。各項目は「改行-----改行」で区切られています。" buttons {"終了"} default button 1
     end if
   end if
 end tell
 
 on replace_text(obj_text, search_str, replace_str)
   set astid_tmp to AppleScript's text item delimiters
   set AppleScript's text item delimiters to search_str
   set astid_texts to every text item of obj_text
   set AppleScript's text item delimiters to replace_str
   set obj_text to astid_texts as string
   set AppleScript's text item delimiters to astid_tmp
   return obj_text
 end replace_text

-- スクリプト前行まで --


« メモ.appインポートAppleScriptを作ってみた[更新] | トップページ | Mac用Gimp2.8.2の公式Native版[更新] »

コメント

ありがとうございます。
まさに私がしたかったことが実現できました。
大変便利です。
ありがとうございました。

ものすごく助かりました。
おかげさまで、350件超のデータをRTFに変換→evernoteに移行することができました。
ありがとうございました。

ネット上ではgmail経由の変換が主流のようですが、全く上手くいきませんでした。
このスクリプトを利用して、evernoteに経由する方法が最速だと思います。もっとみんなに知って欲しい内容です。

コメントを書く

(ウェブ上には掲載しません)

« メモ.appインポートAppleScriptを作ってみた[更新] | トップページ | Mac用Gimp2.8.2の公式Native版[更新] »