Numbers上でデータを整理しているときに、必要になって組んでみたものです。少し大きいAppleScriptですが、ありもののルーチンをつなぎ合わせて書いたので、とくに画期的な何かを書いたということはありません。
もともと、Numbers上にまとめたデータ(2列分)があって、それらを同じものは同じ行に並べ、削除されたものは空欄、追加されたものは下に列挙するという整理を行なっていました。
▲処理前の状態。2列x処理を行う分の行を選択した状態で本AppleScriptを実行する(スクリプトメニューなどを推奨)
この作業をまとめて行うものです。そんなに高速化に配慮しているわけではないので、巨大なデータを扱うのには(このままでは)向いていないかもしれません。ただ、高速化の余地はいろいろあります。
もう、これは分かりきっていた話ですが、Numbers向けに凝ったAppleScriptを書くと、Numbersの機能はほとんど使わずに、AppleScriptの配列やらNSObjectのNSArrayやらを使いまくった「Cocoaの機能のオンパレード」みたいなAppleScriptになります。これは、Numbersに絶望的に何も機能がないためで、データの入出力しか行う余地がありません。
AppleScript名:選択中の2列のセルを比較して並べ直して書き戻す v2 |
— – Created by: Takaaki Naganoya – Created on: 2024/10/14 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" use scripting additions use framework "Foundation" set curTable to getCurTable() of me if curTable = "" then return set {s1Row, s1Column, e1Row, e1Column} to getSelectionRange(curTable) of me –> {73, 3, 86, 4} set colWidth to e1Column – s1Column + 1 –> 2 if colWidth is not equal to 2 then display dialog "Numbers上の表の選択幅が2ではないので、処理終了します" buttons {"OK"} default button 1 return end if set rowHeight to e1Row – s1Row + 1 –> 15 –縦方向に列のセルの値を取得(左側) set v1List to getValueByRange(curTable, s1Column, s1Row, e1Row) of me –スイープ(空白セルのmissing valueを除去) set v1aList to sweepList(v1List, missing value) of me –> {"com.apple.eloquence.fr-CA.Grandpa", "com.apple.eloquence.fi-FI.Grandpa", " com.apple.eloquence.de-DE.Grandpa", " com.apple.eloquence.pt-BR.Grandpa", "com.apple.eloquence.en-US.Grandpa", "com.apple.eloquence.es-ES.Grandpa", " com.apple.eloquence.en-GB.Grandpa", " com.apple.eloquence.it-IT.Grandpa", " com.apple.eloquence.es-MX.Grandpa"} –縦方向に列のセルの値を取得(右側) set v2List to getValueByRange(curTable, e1Column, s1Row, e1Row) of me –スイープ(空白セルのmissing valueを除去) set v2aList to sweepList(v2List, missing value) of me –> {"com.apple.eloquence.de-DE.Grandpa", "com.apple.eloquence.en-GB.Grandpa", "com.apple.eloquence.en-US.Grandpa", "com.apple.eloquence.es-ES.Grandpa", "com.apple.eloquence.es-MX.Grandpa", "com.apple.eloquence.fi-FI.Grandpa", "com.apple.eloquence.fr-CA.Grandpa", "com.apple.eloquence.fr-FR.Grandpa", "com.apple.eloquence.it-IT.Grandpa", "com.apple.eloquence.pt-BR.Grandpa", "com.apple.eloquence.ja-JP.Grandpa", "com.apple.eloquence.ko-KR.Grandpa", "com.apple.eloquence.zh-CN.Grandpa", "com.apple.eloquence.zh-TW.Grandpa"} set dList to getDiffBetweenLists(v1aList, v2aList) of me –> {addItems:{"com.apple.eloquence.zh-TW.Grandpa", "com.apple.eloquence.ko-KR.Grandpa", "com.apple.eloquence.ja-JP.Grandpa", "com.apple.eloquence.zh-CN.Grandpa"}, minusItems:{}} set newList to {} set minusList to minusItems of dList repeat with i in v1aList set j to contents of i if j is not in minusList then if j is in v2aList then set the end of newList to j else set the end of newList to "" end if else set the end of newList to "" end if end repeat set addList to addItems of dList set addList to sort1DNumList(addList, true) of me –昇順ソート set new2List to newList & addList set newLen to length of new2List if newLen > rowHeight then display dialog "新規データが大きいため(" & (rowHeight as string) & "行に対して、データが" & (newLen as string) & "件)データをNumbersに描き戻せません" return –元のデータ範囲よりも、新規データ範囲(行)が多かったら処理を打ち切る(将来アップデート予定。行挿入などで対処) end if repeat (rowHeight – newLen + 1) times set the end of new2List to "" end repeat setValueByRange(curTable, e1Column, s1Row, e1Row, new2List) of me on setValueByRange(curTable, s1Column, s1Row, e1Row, vList) tell application "Numbers" tell curTable tell column s1Column set cList to cells s1Row thru e1Row end tell set aCount to 1 repeat with i in cList set aVal to item aCount of vList set value of i to aVal set aCount to aCount + 1 end repeat end tell end tell end setValueByRange on getValueByRange(curTable, s1Column, s1Row, e1Row) tell application "Numbers" tell curTable tell column s1Column set vList to value of cells s1Row thru e1Row return vList end tell end tell end tell end getValueByRange on getCurTable() tell application "Numbers" tell front document tell active sheet try set theTable to first table whose class of selection range is range on error return "" –何も選択されてなかった場合 end try return theTable end tell end tell end tell end getCurTable on getSelectionRange(theTable) tell application "Numbers" tell theTable set aSel to properties of selection range set selName to name of aSel set {s1, s2} to parseByDelim(selName, ":") of me –始点の情報を取得する set s1Row to (address of row of range s1) as integer set s1Column to (address of column of range s1) as integer –終点の情報を取得する set e1Row to (address of row of range s2) as integer set e1Column to (address of column of range s2) as integer return {s1Row, s1Column, e1Row, e1Column} end tell end tell end getSelectionRange 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 on sweepList(aList, sweepItem) set bList to {} repeat with i in aList if contents of i is not equal to sweepItem then set the end of bList to contents of i end if end repeat return bList end sweepList –リストの差分を取得_v2 on getDiffBetweenLists(aArray as list, bArray as list) 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) –重複部分を削除する allSet’s minusSet:duplicateSet set resArray to (allSet’s allObjects()) as list set aSet to current application’s NSMutableSet’s setWithArray:aArray set bSet to current application’s NSMutableSet’s setWithArray:resArray aSet’s intersectSet:bSet –積集合 set addRes to aSet’s allObjects() as list set cSet to current application’s NSMutableSet’s setWithArray:bArray cSet’s intersectSet:bSet –積集合 set minusRes to cSet’s allObjects() as list return {addItems:minusRes, minusItems:addRes} end getDiffBetweenLists –1D List(数値)をsort / ascOrderがtrueだと昇順ソート、falseだと降順ソート on sort1DNumList(theList as list, aBool as boolean) tell current application’s NSSet to set theSet to setWithArray_(theList) tell current application’s NSSortDescriptor to set theDescriptor to sortDescriptorWithKey_ascending_(missing value, aBool) set sortedList to theSet’s sortedArrayUsingDescriptors:{theDescriptor} return (sortedList) as list end sort1DNumList |