Numbersでオープン中の書類の現在のシート上にある表の選択範囲のセルに対して、背景色(Background color)で登場頻度の集計を行って、どの色が何回登場しているかを色プレビューしつつ表示するAppleScriptです。
集計をRGB値で数値的に行うことは容易ですが、結局のところ色なんてRGB値で見せられてもわからず、実際に目で見える色で表示しないと判断できません。そのため、アラートダイアログを作成してその上にColorWellで表示しています。
▲Numbersの表でセルを選択
▲Numbersの表のセルに指定されている背景色の登場頻度で集計し、色プレビューと登場回数を表示(スクリプトエディタ@macOS 10.14.5上の表示、Dark Mode)
▲Numbersの表のセルに指定されている背景色の登場頻度で集計し、色プレビューと登場回数を表示(Script Debugger@macOS 10.14.5上の表示、Dark Mode)
上記サンプル表は本Blog上での説明用のために簡略化した表ですが、実際には数十行の入り組んだNumbersの表を相手にしており、かつ、手作業で色付きセルだけを数えるなんて考えたくもないレベルで頻繁に確認しなくてはならなかったために、本Scriptを作ってみました。
Numbersにかぎらず、iWorkアプリケーション(Keynote、Pages、Numbers)で共通の仕様ですが、背景色を塗らないセルから背景色を取得するとmissing valueが返ります。
本ScriptはScript Menuに入れて実行するとアラートダイアログが最前面に出てこないなど、Script書類(.scpt、.scptd)のままで実行すると問題が発生。Script Menuに入れる場合にはアプレット(.app)書き出しする必要があります。
▲スクリプトメニューにアプレット書き出しした実行ファイルを入れて呼び出し(macOS 10.14.5)。スクリプトメニューは最前面にあるGUIアプリケーションに応じて、それぞれのアプリケーション用のメニューを表示できるようになっている
AppleScript名:選択中の表のセルの範囲を背景色で頻度集計.scptd |
— – Created by: Takaaki Naganoya – Created on: 2019/06/06 — – Copyright © 2019 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use framework "AppKit" use scripting additions property NSView : a reference to current application’s NSView property NSAlert : a reference to current application’s NSAlert property NSColor : a reference to current application’s NSColor property NSIndexSet : a reference to current application’s NSIndexSet property NSTextField : a reference to current application’s NSTextField property NSColorWell : a reference to current application’s NSColorWell property NSScrollView : a reference to current application’s NSScrollView property NSMutableArray : a reference to current application’s NSMutableArray property NSRunningApplication : a reference to current application’s NSRunningApplication property theResult : 0 property returnCode : 0 property theDataSource : {} 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 "No Selection" –何も選択されてなかった場合 end try tell theTable set bgColList to background color of every cell of selection range –> {{18572, 45937, 65452}, {18572, 45937, 65452}, {3001, 24801, 44056}, {18572, 45937, 65452}, {18572, 45937, 65452}, {64899, 33134, 31509}, {64899, 33134, 31509}, {18572, 45937, 65452}, {18572, 45937, 65452}, {3001, 24801, 44056}, {18572, 45937, 65452}, {18572, 45937, 65452}, {26149, 65534, 58650}, {26149, 65534, 58650}, {26149, 65534, 58650}, {26149, 65534, 58650}, {18572, 45937, 65452}, {18572, 45937, 65452}} end tell end tell end tell end tell set bgColList to countItemsByItsAppearance(bgColList) of me –> {{theName:{65535, 65533, 65534}, numberOfTimes:73}, {theName:{65535, 65535, 21706}, numberOfTimes:73}, {theName:missing value, numberOfTimes:27}} set paramObj to {mainDat:bgColList, myTitle:"色別集計", mySubTitle:"Numbers上で選択したセルの背景色の頻度集計"} –my browseColors:paramObj–for debug my performSelectorOnMainThread:"browseColors:" withObject:(paramObj) waitUntilDone:true on browseColors:paramObj set aParamList to (mainDat of (paramObj as record)) as list set winTitle to (myTitle of (paramObj as record)) as string set subTitle to (mySubTitle of (paramObj as record)) as string set aLen to length of aParamList set aHeight to 100 set aWidth to 300 –NSViewをつくる set aNSV to NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight * 1.5)) aNSV’s setNeedsDisplay:true — NSScroll Viewをつくる set aScroll to NSScrollView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight)) aScroll’s setDocumentView:aNSV aNSV’s enclosingScrollView()’s setHasHorizontalScroller:true aNSV’s enclosingScrollView()’s setHasVerticalScroller:true –NSColorWell+ NSTextFieldをつくる set aStep to 1 repeat with i in aParamList set aColorWell to (NSColorWell’s alloc()’s initWithFrame:(current application’s NSMakeRect(10, ((aLen – aStep + 1) * 30), 60, 20))) set myName to (theName of i) set myTimes to (numberOfTimes of i) if myName is not equal to missing value then copy (myName as list) to {rNum, gNum, bNum} set myTimes to numberOfTimes of i set myColor to makeNSColorFromRGBAval(rNum, gNum, bNum, 65535, 65535) of me (aColorWell’s setColor:myColor) (aColorWell’s setBordered:false) (aNSV’s addSubview:aColorWell) set aTF to makeNSTextField(80, ((aLen – aStep + 1) * 30), 100, 20, false, myTimes as string, true, true) of me (aNSV’s addSubview:aTF) set aStep to aStep + 1 end if end repeat –NSScrollViewを強制的にトップにスクロール set aPT to current application’s NSMakePoint(0.0, aHeight) aScroll’s documentView()’s scrollPoint:aPT — set up alert set theAlert to NSAlert’s alloc()’s init() tell theAlert its setMessageText:winTitle its setInformativeText:subTitle its addButtonWithTitle:"OK" its addButtonWithTitle:"Cancel" its setAccessoryView:aScroll end tell — show alert in modal loop NSRunningApplication’s currentApplication()’s activateWithOptions:0 my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true if (my returnCode as number) = 1001 then error number -128 end browseColors: on doModal:aParam set (my returnCode) to aParam’s runModal() end doModal: on makeNSColorFromRGBAval(redValue as integer, greenValue as integer, blueValue as integer, alphaValue as integer, aMaxVal as integer) set aRedCocoa to (redValue / aMaxVal) as real set aGreenCocoa to (greenValue / aMaxVal) as real set aBlueCocoa to (blueValue / aMaxVal) as real set aAlphaCocoa to (alphaValue / aMaxVal) as real set aColor to NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa return aColor end makeNSColorFromRGBAval –1D Listを要素別に出現回数で集計 on countItemsByItsAppearance(aList as list) set aSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList set bArray to current application’s NSMutableArray’s array() set theEnumerator to aSet’s objectEnumerator() repeat set aValue to theEnumerator’s nextObject() if aValue is missing value then exit repeat bArray’s addObject:(current application’s NSDictionary’s dictionaryWithObjects:{aValue, (aSet’s countForObject:aValue)} forKeys:{"theName", "numberOfTimes"}) end repeat –出現回数(numberOfTimes)で降順ソート set theDesc to current application’s NSSortDescriptor’s sortDescriptorWithKey:"numberOfTimes" ascending:false bArray’s sortUsingDescriptors:{theDesc} return bArray as list end countItemsByItsAppearance on makeNSTextField(xPos as integer, yPos as integer, myWidth as integer, myHeight as integer, editableF as boolean, setVal as string, backgroundF as boolean, borderedF as boolean) set aNSString to NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(xPos, yPos, myWidth, myHeight)) aNSString’s setEditable:(editableF) aNSString’s setStringValue:(setVal) aNSString’s setDrawsBackground:(backgroundF) aNSString’s setBordered:(borderedF) return aNSString end makeNSTextField |