01/13 iCalで選択中のイベントのカレンダー情報を取得する
iCal上で選択中のイベントが所属しているカレンダーの名称を取得するAppleScriptです。
iCalのAppleScript用語辞書には致命的な欠陥が山のようにあって……GUI上で選択中のイベント(selection)を取得できません。普通のやり方では、選択中のイベントのカレンダー名を取得できません。もっと基本的なところで、いま表示中の月が何月なのかも分かりません。
日時を指定してイベントを登録したり、フィルタ参照でイベントを抽出したりするぐらいで、画面上で選択したイベントから対話的に何かの処理を行うようなAppleScriptを作りにくい(というよりも、作れない)状況にあります。

はい、おしまいおしまい〜
……などと言っていては海外の強豪Scripter連中に顔向けできません。
選択中のイベントが存在するのであれば、コピーを実行すると何らかの情報が得られるはずです。
実際にiCal上でコピーを実行してみると、
<ここから>
退去確認@ヴィラ山田
2011年1月22日 を 16:00 〜 17:00 にスケジュールしました
</ここまで>
のような内容が得られました。この情報から日付、開始時刻、終了時刻、イベント名 などを取得できます。
これらの情報を手がかりに、すべてのカレンダー上で検索(フィルタ参照による抽出)を行ってみました。
実行条件は、GUI Scriptingがオンになっていることと、iCal上でなにがしかのイベントが選択状態になっていることです。

GUI Scripting(UI Element Scripting)経由で選択イベントのコピー動作を行い、クリップボードの内容を解析。得られた情報をもとに今度はiCalに正攻法ですべてのカレンダーに対して「日付、開始時刻、終了時刻、イベント名」を手がかりにイベントの検索を行います。条件に合致するイベントが見つかったら、カレンダーの名称を取得して返します。これを複数のイベントに対してループで実行してみました。
実験してみたところ、複数のイベントを一度に選択した場合、その中に「繰り返しイベント」が含まれているとiCalがダイアログで警告します。このダイアログが邪魔なので、ダイアログのクローズ処理も行わなくてはなりません。

作成時間はトータルで40分程度でしょうか。かなり作り込みましたが、驚くべきことに、さほど実用性がありません、、、
| スクリプト名:iCalで選択中のイベントの情報を取得する |
| set aRes to retSelectedEvent() of me
set icalRes to {} repeat with i in aRes set j to contents of i set the end of icalRes to getCalName(j) of me end repeat icalRes –> {”ホーム”} –選択中のiCal上のイベントが所属しているカレンダーの名称を取得する on getCalName(aStr) set aList to paragraphs of aStr set aTitle to contents of item 1 of aList set dStr to contents of item 2 of aList set dOffset to offset of “日 を “ in dStr set dDate to text 1 thru dOffset of dStr –set dDateObj to date dDate set tSeparator to offset of ” 〜 “ in dStr if tSeparator = 0 then –「〜」がないことから、終日のスケジュールと判断 set timeFrom to “0:00″ set timeTo to “23:59:59″ else –開始時刻と終了時刻のあるスケジュールと判断 set timeFrom to text (dOffset + 4) thru (tSeparator - 1) of dStr set timeTo to text (tSeparator + 3) thru ((length of dStr) - 12) of dStr end if set timeFromObj to date (dDate & ” “ & timeFrom) set timeToObj to date (dDate & ” “ & timeTo) tell application “iCal” set cnList to name of every calendar set cList to every calendar set cCount to 1 set findF to false repeat with i in cList tell i set eList to (every event whose start date is not less than timeFromObj and start date is not greater than timeToObj and summary of it is aTitle) if eList is not equal to {} then set findF to true exit repeat end if end tell set cCount to cCount + 1 end repeat if findF = true then set aName to contents of item cCount of cnList else set aName to “” end if end tell return aName end getCalName –選択中のイベント情報をコピー(エラー時にはfalseをリターン) on retSelectedEvent() activate application “iCal” tell application “System Events” tell process “iCal” –「編集」メニューの項目「コピー」がイネーブルかどうかを取得 set copyEnabled to (enabled of menu item 5 of menu 1 of menu bar item 4 of menu bar 1) if copyEnabled = false then return false –コピーしてみる try keystroke “c” using {command down} on error –何らかの都合でコピー等の動作を行えなかった場合 return false end try –ダイアログ表示時のボタンクリック clickiCalDialog() of me –クリップボードから文字情報を取得 set aConList to the clipboard set aCon to aConList as string end tell end tell set aList to parseByDelim(aCon, (ASCII character 13) & (ASCII character 13)) of me return aList end retSelectedEvent –iCalでイベントをコピー時に、繰り返しイベントが選択されていた時に表示されるダイアログを乗り越えるためのルーチン –(「キャンセル」ではない方のボタンを押す) on clickiCalDialog() –ダイアログ検出 tell application “System Events” tell process “iCal” if (count every window) > 1 then if subrole of window 1 = “AXDialog” then tell window 1 –キャンセル「ではない」方のボタンを取得 set bList to every button whose title is not equal to “キャンセル” if bList is not equal to {} then set aButton to first item of bList tell aButton click end tell end if end tell end if end if end tell end tell end clickiCalDialog on parseByDelim(aData, aDelim) set curDelim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to aDelim set dList to text items of aData set AppleScript’s text item delimiters to curDelim return dList end parseByDelim |



