文字列で与えたAppleScriptを実行し、その実行結果をテキストで取得したうえにラベルと値に分割してNumbersの「表」に組み立てるAppleScriptです。
仕様書の作成とかテストデータの評価とかそういう仕事を行うさいに、プログラムコード(AppleScriptが出力するrecordとかlistとか)が読めない人向けに確認してもらうために作成したものです。
Numbersに出力すること自体にはさほど意味はありませんが(ExcelでもREST API経由でGoogle Spread Sheetに出力したっていいわけで)、とりあえずプログラムの結果出力になじみのない方々に計算結果を見ていただくためのものです。
AppleScriptの実行結果をスクリプトエディタではなくOSAScriptControllerなどから受け取る部品などが揃ってきたので、こういう加工も割とすぐにできていい感じです。
ちなみに、Numbersの表のセルに対して直接AppleScriptからデータを突っ込んでいますが、これはあらかじめ出力するデータ数が少ないことが見込まれているためです。多い場合(100件前後がひとつの基準に)には、CSVファイルに書き出してNumbersにオープンさせることになるでしょう。
例によって、Numbersの表セルに対してデータを突っ込むさいには非同期モードで実行して速度を稼いでいます。
AppleScript名:ASの実行結果をNumbersの表に出力する |
— Created 2019/04/05 by Takaaki Naganoya — 2019 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "OSAKit" use framework "AppKit" use bLus : script "BridgePlus" property NSString : a reference to current application’s NSString property NSThread : a reference to current application’s NSThread property OSAScript : a reference to current application’s OSAScript property NSTextView : a reference to current application’s NSTextView property OSAScriptView : a reference to current application’s OSAScriptView property OSAScriptController : a reference to current application’s OSAScriptController property SMSForder : a reference to current application’s SMSForder property theResult : "" –result set origStr to " tell application \"Numbers\" tell front document properties end tell end tell " my performSelectorOnMainThread:"execASandReturnString:" withObject:origStr waitUntilDone:true set aStr to (my theResult) set aList to my getListFromText:aStr makeNewNumbersDocumentAndTable(length of aList, 2) of me fillCurrentTable(aList) of me –リストに入れたレコードを、指定の属性ラベルの値で抽出 on filterRecListByLabel(aRecList as list, aPredicate as string) –ListからNSArrayへの型変換 set aArray to current application’s NSArray’s arrayWithArray:aRecList –抽出 set aPredicate to current application’s NSPredicate’s predicateWithFormat:aPredicate set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate –NSArrayからListに型変換して返す set bList to filteredArray as list return bList end filterRecListByLabel –リストに入れたレコードを、指定の属性ラベルの値で抽出。値が別途指定のリストの中に存在していることが条件 on filterRecList:(aRecList as list) byLabel:(aPredicate as string) andSublist:(aSubList as list) –ListからNSArrayへの型変換 set aArray to current application’s NSArray’s arrayWithArray:aRecList set aSubArray to current application’s NSArray’s arrayWithArray:aSubList –抽出 set aPredicate to current application’s NSPredicate’s predicateWithFormat_(aPredicate, aSubArray) set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate –NSArrayからListに型変換して返す set bList to filteredArray as list return bList end filterRecList:byLabel:andSublist: –listの共通項を返す on getSameItemsInLists:(aList as list) withList:(bList as list) –ASオブジェクトをCocoaオブジェクトに変換 set aArray to current application’s NSArray’s arrayWithArray:aList set bArray to current application’s NSArray’s arrayWithArray:bList — まとめる set allSet to current application’s NSMutableSet’s setWithArray:aArray allSet’s addObjectsFromArray:bArray –重複する要素のみ抜き出す set duplicateSet to current application’s NSMutableSet’s setWithArray:aArray duplicateSet’s intersectSet:(current application’s NSSet’s setWithArray:bArray) –重複部分だけを返す set resArray to duplicateSet’s allObjects() set resList to resArray as list return resList end getSameItemsInLists:withList: –スクリプトエディタのresult欄に返ってきたテキストをリストに変える on getListFromText:aText script getListFromTextO property aaText : "" property gList : {} property outList : {} property aG : "" property valList : {} end script copy aText to (aaText of getListFromTextO) set (gList of getListFromTextO) to {} set (outList of getListFromTextO) to {} set (aG of getListFromTextO) to "" set (valList of getListFromTextO) to {} if (aaText of getListFromTextO) does not start with "{" and (aaText of getListFromTextO) does not end with "}" then return {} end if set aLen to length of (aaText of getListFromTextO) set (aG of getListFromTextO) to text 2 thru -2 of (aaText of getListFromTextO) set (gList of getListFromTextO) to characters of (aG of getListFromTextO) set sPos to 2 –1文字目は\"{\"なので2文字目からスキャンを開始する set ePos to 2 set imdF to false –Immediate Data Flag(文字列中を示すダブルクォート内の場合にはtrueになる) set listF to 0 –stacking段数が入る set attrF to true –属性ラベルスキャン時にtrue、データ末尾スキャン時にfalse repeat with i in (gList of getListFromTextO) set j to contents of i if attrF = true and imdF = false and listF = 0 then –属性値部分の末尾検出 if j = ":" then if text sPos thru sPos of (aaText of getListFromTextO) = " " then set sPos to sPos + 1 end if set anOut to text sPos thru ePos of (aaText of getListFromTextO) set sPos to ePos + 1 set the end of (valList of getListFromTextO) to anOut set attrF to false –データのスキャンを開始する set imdF to false set listF to 0 end if else if imdF = false and listF = 0 and j = "," then –データ部分の末尾検出 set anOut to text sPos thru (ePos – 1) of (aaText of getListFromTextO) set sPos to ePos + 1 set the end of (valList of getListFromTextO) to anOut set the end of (outList of getListFromTextO) to (valList of getListFromTextO) set (valList of getListFromTextO) to {} set attrF to true –次が属性値ラベルであることを宣言 set imdF to false set listF to 0 else if j = "{" then if imdF = false then set listF to listF + 1 –1段スタックにpush end if else if j = "}" then if imdF = false then set listF to listF – 1 –1段スタックからpop end if else if j = "\"" then if imdF = true then set imdF to false else set imdF to true end if end if set ePos to ePos + 1 end repeat –ラストのデータ部分を出力 try set the end of (valList of getListFromTextO) to text sPos thru (ePos – 1) of (aaText of getListFromTextO) set the end of (outList of getListFromTextO) to (valList of getListFromTextO) on error return false end try return contents of (outList of getListFromTextO) end getListFromText: on execASandReturnString:(srcStr as string) set targX to 500 –View Width set targY to 200 –View Height if srcStr = missing value or srcStr = "" then –Error display dialog "Error in reading script source…." buttons {"OK"} default button 1 with icon 1 return end if –Make AppleScript Controller & Script Editor View set osaCon to OSAScriptController’s alloc()’s init() set osaView to OSAScriptView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, targX, targY)) –Make Result View set resView to NSTextView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, targX, targY)) resView’s setRichText:true resView’s useAllLigatures:true –Connect OSAScriptController to Editor View & Result View osaCon’s setScriptView:osaView osaCon’s setResultView:resView –Set AppleScript Source to Editor View & Execute it osaView’s setString:srcStr osaCon’s runScript:(missing value) –Get AppleScript’s Result as string set aRes to resView’s |string|() as list of string or string –as anything set my theResult to aRes –Return the result as string end execASandReturnString: on fillCurrentTable(aList) set aLen to length of aList set aWidth to length of first item of aList tell application "Numbers" tell front document tell active sheet tell table 1 repeat with i from 1 to aLen tell row (i + 1) set aRowList to contents of item i of aList repeat with ii from 1 to aWidth tell cell ii set aTmpData to contents of item ii of aRowList ignoring application responses set value to aTmpData end ignoring end tell end repeat end tell end repeat end tell end tell end tell end tell end fillCurrentTable on makeNewNumbersDocumentAndTable(aHeight, aWidth) tell application "Numbers" make new document tell front document tell active sheet delete every table end tell end tell tell front document tell active sheet set tRes to make new table with properties {row count:aHeight, column count:aWidth} return tRes end tell end tell end tell end makeNewNumbersDocumentAndTable |
More from my site
(Visited 113 times, 1 visits today)