Menu

Skip to content
AppleScriptの穴
  • Home
  • Products
  • Books
  • Docs
  • Events
  • Forum
  • About This Blog
  • License
  • 仕事依頼

AppleScriptの穴

Useful & Practical AppleScript archive. Click '★Click Here to Open This Script' Link to download each AppleScript

カテゴリー: list

2D List中から、複数アイテムが存在するマーカーのx番目のXYマーカーの交点のデータを返す v1

Posted on 2月 3, 2019 by Takaaki Naganoya

2D List中から、ヘッダー行とヘッダー列の(はずの)場所からマーカーを特定し、Xマーカー、Yマーカーの交点座標の値をピックアップして返すAppleScriptです。

これまでにも、2D List(2次元配列9からXマーカー、Yマーカーを個別に指定して、交点座標の値をピックアップするScriptは使っていました。

ところが、実際に投入してみたところXマーカーに該当する文字列が複数ピックアップされる例が出てきたため、「何個目のマーカーを使用するか」「ヘッダー行の何行目までサーチするか」といった追加の機能が必要になってきました。そのための試作品です。

ヘッダー行がユニーク化されていないCSVとか、驚きでアゴが外れそうになるデータにお目にかかったので、その対策のために作ったものです。

AppleScript名:2D List中から、複数アイテムが存在するマーカーのx番目のXYマーカーの交点のデータを返す v1
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/01/24
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use Bplus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

set anXItem to "a"
set anXItemNum to 3
set anYItem to "z"
set anYItemNum to 1
set aList to {{"b", "a", "a", "a"}, {"x", "1x", "2x", "3x"}, {"y", "1y", "2y", "3y"}, {"z", "1z", "2z", "3z"}}

set aRes to getItemFromList(aList, anXItem, anXItemNum, anYItem, anYItemNum) of me
–> "3z"

on getItemFromList(aList as list, anXItem, anXItemNum as integer, anYItem, anYItemNum as integer)
  set xRes to findDataFrom2DList(anXItem, aList, 2) of me –> {{2, 1}, {4, 1}}
  
if length of xRes < anXItemNum then error "X-item Fewer Hits"
  
  
set yRes to findDataFrom2DList(anYItem, aList, -1) of me –> {{1, 4}}
  
if length of yRes < anYItemNum then error "Y-item Fewer Hits"
  
  
set xPosRes to item 1 of contents of item anXItemNum of xRes
  
set yPosRes to item 2 of contents of item anYItemNum of yRes
  
  
set aRes to item xPosRes of item yPosRes of aList
  
  
return aRes
end getItemFromList

on findDataFrom2DList(anItem, aList as list, yMax as integer)
  script spd
    property aList : {}
    
property resList : {}
  end script
  
  
set (aList of spd) to aList
  
set (resList of spd) to {}
  
  
set yCount to 1
  
  
repeat with i in (aList of spd)
    
    
set aResList to (Bplus’s indexesOfItem:anItem inList:i inverting:false) as list
    
    
set tmpList to {}
    
if aResList is not equal to {} then
      repeat with ii in aResList
        set jj to contents of ii
        
set the end of tmpList to {jj, yCount}
      end repeat
      
set (resList of spd) to (resList of spd) & tmpList
    end if
    
    
set yCount to yCount + 1
    
if (yMax is not equal to -1) and (yCount > yMax) then exit repeat
  end repeat
  
  
return (resList of spd) –return {{x, y}…..} item list (1-based)
end findDataFrom2DList

★Click Here to Open This Script 

Posted in list | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy | Leave a comment

Pages書類の1ページ目の表の背景色を置換 v4

Posted on 1月 30, 2019 by Takaaki Naganoya

Pagesでオープン中の最前面の書類の1ページ目に存在する表オブジェクト中の背景色を置換するAppleScriptです。

例によって、Pages書類上の表オブジェクトは「配置」を「移動しない」に設定しないとAppleScriptからアクセスできないので、あらかじめ「移動しない」設定にしておく必要があります。

本バージョンでは、データの連続部分をrangeとしてまとめて処理する方法を、1行ずつ横方向に(左→右)スキャンした場合と、1列ずつ(上→下)縦方向にスキャンした場合の2パターンで処理し、より少ないデータ単位(より多くのセルを一括で指定)で処理できる方の方式を採用するようにしました。

このため、処理データによって塗りつぶし動作が変わってきます。横方向のみのスキャンでは大幅に遅くなるタイプのデータ(縦に処理対象セルが並んでいて、横方向にはつながっていない)でも「遅くならない」ことがテーマです。

ほかには、オープンソースの「DBColorNames」を利用して色から色名称を動的に取得したり、ポップアップメニューに表示する色イメージ画像を角丸にしたりしています。

–> dbColNamesKit.framework (To ~/Library/Frameworks)

これ以上の高速化は、「縦横混在のrangeシミュレーション」でも行わないとできないと思いますが、方法についてはいろいろ思いつくので論理的には可能だと思います。ただ、単に塗りつぶしを高速化するためだけに何日も試行錯誤するのはちょっと………なので、このぐらいにしておこうかと。

macOS 10.14上では、「csrutil disable」でSIPをオフにすると、ホームディレクトリ下の~/Library/Frameworksフォルダ内のFrameworkにアクセスでき、本Scriptをそのままスクリプトエディタで実行できました。アプレット形式で書き出して、アプレット内にFrameworkを入れればSIPをオフにしなくても実行できるはずです。Script Debugger/Script Menu上では実行できないというあたりが困りどころです。

AppleScript名:Pages書類の1ページ目の表の背景色を置換 v4.1
— Created 2017-07-15 by Takaaki Naganoya
— Modified 2019-01-29 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use framework "dbColNamesKit" –https://github.com/daniel-beard/DBColorNames/
use Bplus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

–v1:First Version
–v2:Pick Up target cells by calculate every background color (35% speed up)
–v3:Draw cells by range (x20 speed up)
–v3.1:Bug Fix (retRangeFromPosList)
–v3.1.1:Bug Fix (retRangeFromPosList)
–v4:Two-way Simulation (Horizontal / Vertical scan), Corner-Rounded NSImage, Dynamic Color Naming
–v4.1:Correct Vertical Scan simulation (Sort list for vertical range evaluation, at first)

property NSView : a reference to current application’s NSView
property NSColor : a reference to current application’s NSColor
property NSArray : a reference to current application’s NSArray
property NSMenu : a reference to current application’s NSMenu
property NSImage : a reference to current application’s NSImage
property NSScreen : a reference to current application’s NSScreen
property NSButton : a reference to current application’s NSButton
property NSWindow : a reference to current application’s NSWindow
property NSTextField : a reference to current application’s NSTextField
property NSMenuItem : a reference to current application’s NSMenuItem
property NSBezierPath : a reference to current application’s NSBezierPath
property NSPopUpButton : a reference to current application’s NSPopUpButton
property NSWindowController : a reference to current application’s NSWindowController
property NSTitledWindowMask : a reference to current application’s NSTitledWindowMask
property NSRoundedBezelStyle : a reference to current application’s NSRoundedBezelStyle
property NSFloatingWindowLevel : a reference to current application’s NSFloatingWindowLevel
property NSBackingStoreBuffered : a reference to current application’s NSBackingStoreBuffered
property NSMomentaryLightButton : a reference to current application’s NSMomentaryLightButton

property windisp : true
property wController : missing value
property pop1ind : 1

–初期化
set (my windisp) to true
set (my pop1ind) to 1
load framework

–Pagesの1ページ目にある表の塗り色を取得
tell application "Pages"
  tell front document
    tell table 1
      set c1List to background color of every cell
      
set aProp to properties
      
set xCount to column count of aProp
    end tell
  end tell
end tell

–色データをユニーク化(重複削除)
set bList to uniquifyList(c1List) of me

–Convert 1D List to 2D List
set c3List to (current application’s SMSForder’s subarraysFrom:c1List groupedBy:xCount |error|:(missing value)) as list

–missing value(背景色なし)を除外する
set c2List to (current application’s SMSForder’s arrayByDeletingBlanksIn:(bList)) as list

–Popup Menuで置換色選択
set paramObj to {c2List, 65535, "OK", "Select Target Color", 180} –Timeout = 180 sec, Color val range = 16bit
my performSelectorOnMainThread:"getPopupValues:" withObject:(paramObj) waitUntilDone:true
if pop1ind = false then return –timed out
set fromCol to (contents of item pop1ind of c2List)

–カラーピッカーで置換色選択
set tCol to choose color default color fromCol

set d1 to current date

–実際に表の背景色を置換する
set hitList to findDataFrom2DList(fromCol, c3List) of me –データ上で当該色のセル情報を計算する

–Rangeを横スキャンと縦スキャンの2通りで試算(Two way Simulation)
set rList1 to retRangeFromPosListHorizontal(hitList) of me –横方向へのrange評価
set rList2 to retRangeFromPosListVertival(hitList) of me –縦方向へのrange評価

–Simulationの結果、要素数の少ない方(=処理時間の短い方=高速な方)を採用する
log {"Simulation", (length of rList1), (length of rList2)}
if (length of rList1) < (length of rList2) then
  copy rList1 to rangeList
else
  copy rList2 to rangeList
end if

tell application "Pages"
  activate
  
tell front document
    tell table 1
      repeat with i in rangeList
        set j to contents of i
        
        
ignoring application responses –非同期実行モードで高速実行
          set background color of range j to tCol
        end ignoring
        
      end repeat
    end tell
  end tell
end tell

set d2 to current date
return d2 – d1

–カラーポップアップメニューをウィンドウ表示
on getPopupValues:paramObj
  copy (paramObj as list) to {ap1List, aColMax, aButtonMSG, aSliderValMSG, timeOutSecs}
  
  
set (my windisp) to true
  
  
set aView to NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 360, 100))
  
  
–Labelをつくる
  
set a1TF to NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(30, 60, 80, 20))
  
a1TF’s setEditable:false
  
a1TF’s setStringValue:"Color:"
  
a1TF’s setDrawsBackground:false
  
a1TF’s setBordered:false
  
  
–Ppopup Buttonをつくる
  
set a1Button to NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(80, 60, 200, 20)) pullsDown:false
  
a1Button’s removeAllItems()
  
  
set a1Menu to NSMenu’s alloc()’s init()
  
set aCDB to current application’s DBColorNames’s alloc()’s init()
  
  
set iCount to 1
  
repeat with i in ap1List
    copy i to {r1, g1, b1}
    
    
set nsCol to makeNSColorFromRGBAval(r1, g1, b1, aColMax, aColMax) of me
    
set anImage to makeRoundedNSImageWithFilledWithColor(64, 64, nsCol, 4) of me
    
    
set aTitle to "#" & (iCount as string) & " " & (aCDB’s nameForColor:nsCol) as string
    
set aMenuItem to (NSMenuItem’s alloc()’s initWithTitle:aTitle action:"actionHandler:" keyEquivalent:"")
    (
aMenuItem’s setImage:anImage)
    (
aMenuItem’s setEnabled:true)
    (
a1Menu’s addItem:aMenuItem)
    
    
set iCount to iCount + 1
  end repeat
  
  
a1Button’s setMenu:a1Menu
  
  
  
–Buttonをつくる
  
set bButton to (NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(80, 10, 140, 40)))
  
bButton’s setButtonType:(NSMomentaryLightButton)
  
bButton’s setBezelStyle:(NSRoundedBezelStyle)
  
bButton’s setTitle:aButtonMSG
  
bButton’s setTarget:me
  
bButton’s setAction:("clicked:")
  
bButton’s setKeyEquivalent:(return)
  
  
aView’s addSubview:a1TF
  
  
aView’s addSubview:a1Button
  
aView’s addSubview:bButton
  
aView’s setNeedsDisplay:true
  
  
–NSWindowControllerを作ってみた(いらない?)
  
set aWin to (my makeWinWithView(aView, 300, 100, aSliderValMSG))
  
  
set wController to NSWindowController’s alloc()
  
wController’s initWithWindow:aWin
  
  
wController’s showWindow:me
  
  
set aCount to timeOutSecs * 100
  
  
set hitF to false
  
repeat aCount times
    if (my windisp) = false then
      set hitF to true
      
exit repeat
    end if
    
delay 0.01
    
set aCount to aCount – 1
  end repeat
  
  
my closeWin:aWin
  
  
if hitF = true then
    set s1Val to ((a1Button’s indexOfSelectedItem() as number) + 1)
  else
    set s1Val to false
  end if
  
  
copy s1Val to my pop1ind
  
end getPopupValues:

on clicked:aSender
  set (my windisp) to false
end clicked:

–make Window for Display
on makeWinWithView(aView, aWinWidth as integer, aWinHeight as integer, aTitle as string)
  set aScreen to NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {aWinWidth, aWinHeight}}
  
  
set aBacking to NSTitledWindowMask
  
  
set aDefer to NSBackingStoreBuffered
  
  
— Window
  
set aWin to NSWindow’s alloc()
  (
aWin’s initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)
  
  
aWin’s setTitle:aTitle
  
aWin’s setDelegate:me
  
aWin’s setDisplaysWhenScreenProfileChanges:true
  
aWin’s setHasShadow:true
  
aWin’s setIgnoresMouseEvents:false
  
aWin’s setLevel:(NSFloatingWindowLevel)
  
aWin’s setOpaque:false
  
aWin’s setReleasedWhenClosed:true
  
aWin’s |center|()
  
  
aWin’s setContentView:aView
  
  
return aWin
end makeWinWithView

–close win
on closeWin:aWindow
  repeat with n from 10 to 1 by -1
    (aWindow’s setAlphaValue:n / 10)
    
delay 0.02
  end repeat
  
aWindow’s |close|()
end closeWin:

–Popup Action Handler
on actionHandler:sender
  set aTag to tag of sender as integer
  
set aTitle to title of sender as string
end actionHandler:

–aMaxValを最大値とする数値でNSColorを作成して返す
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

–指定サイズのNSImageを作成し、指定色で塗ってNSImageで返す
on makeNSImageWithFilledWithColor(aWidth as integer, aHeight as integer, fillColor)
  set anImage to NSImage’s alloc()’s initWithSize:(current application’s NSMakeSize(aWidth, aHeight))
  
anImage’s lockFocus()
  
—
  
set theRect to {{x:0, y:0}, {height:aHeight, width:aWidth}}
  
set theNSBezierPath to NSBezierPath’s bezierPath
  
theNSBezierPath’s appendBezierPathWithRect:theRect
  
—
  
fillColor’s |set|() –色設定
  
theNSBezierPath’s fill() –ぬりつぶし
  
—
  
anImage’s unlockFocus()
  
—
  
return anImage
end makeNSImageWithFilledWithColor

–指定サイズのNSImageを作成し、指定色で塗ってNSImageで返す、anRadiusの半径の角丸で
on makeRoundedNSImageWithFilledWithColor(aWidth as integer, aHeight as integer, fillColor, anRadius as real)
  set anImage to NSImage’s alloc()’s initWithSize:(current application’s NSMakeSize(aWidth, aHeight))
  
anImage’s lockFocus()
  
—
  
set theRect to {{x:0, y:0}, {height:aHeight, width:aWidth}}
  
set theNSBezierPath to NSBezierPath’s bezierPathWithRoundedRect:theRect xRadius:anRadius yRadius:anRadius
  
—
  
fillColor’s |set|() –色設定
  
theNSBezierPath’s fill() –ぬりつぶし
  
—
  
anImage’s unlockFocus()
  
  
return anImage
end makeRoundedNSImageWithFilledWithColor

on uniquifyList(aList as list)
  set aArray to NSArray’s arrayWithArray:aList
  
set bArray to aArray’s valueForKeyPath:"@distinctUnionOfObjects.self"
  
return bArray as list
end uniquifyList

on findDataFrom2DList(anItem, aList as list)
  script spd
    property aList : {}
    
property resList : {}
  end script
  
  
set (aList of spd) to aList
  
set (resList of spd) to {}
  
  
set yCount to 1
  
  
repeat with i in (aList of spd)
    
    
set aResList to (Bplus’s indexesOfItem:anItem inList:i inverting:false) as list
    
    
set tmpList to {}
    
if aResList is not equal to {} then
      repeat with ii in aResList
        set jj to contents of ii
        
set the end of tmpList to {jj, yCount}
      end repeat
      
set (resList of spd) to (resList of spd) & tmpList
    end if
    
    
set yCount to yCount + 1
  end repeat
  
  
return (resList of spd) –return {{x, y}…..} item list (1-based)
end findDataFrom2DList

on retRangeFromPosListVertival(posList as list)
  script rangeSPD
    property posList2 : {}
  end script
  
  
–縦方向へのrange評価に都合がいいようにソート
  
set (posList2 of rangeSPD) to shellSortListAscending(posList, {1, 2}) of me
  
  
–先頭データをピックアップ
  
set firstData to first item of (posList2 of rangeSPD)
  
set (posList2 of rangeSPD) to rest of (posList2 of rangeSPD)
  
  
copy firstData to {curX1, curY1}
  
set tmpRangeStr to aNumToExcelColumn(curX1) of me & (curY1 as string) & ":"
  
  
set tmpRange to {}
  
set hitF to false
  
  
set outList to {}
  
  
repeat with i in (posList2 of rangeSPD)
    copy i to {tmpX, tmpY}
    
    
–log {"{curX1, curY1}", {curX1, curY1}}
    
–log {"{tmpX, tmpY}", {tmpX, tmpY}}
    
    
    
if (curX1 = tmpX) and (curY1 + 1 = tmpY) then
      –Y方向への連続値を拾っている最中
      
if hitF = false then
        –log "case 1a"
        
–log {"hitF", hitF}
        
set hitF to true
      else
        –log "case 1b"
        
–log {"hitF", hitF}
        
–横に連続しているブロックの途中
      end if
    else
      –直前の値と連続していない
      
if hitF = false then
        –log "case 2a"
        
–log {"hitF", hitF}
        
set tmpRangeStr to tmpRangeStr & aNumToExcelColumn(curX1) of me & (curY1 as string)
        
set the end of outList to tmpRangeStr
        
set tmpRangeStr to aNumToExcelColumn(tmpX) of me & (tmpY as string) & ":"
        
set hitF to false
      else
        –log "case 2b"
        
–log {"hitF", hitF}
        
–連続ブロックの末尾を拾った
        
set tmpRangeStr to tmpRangeStr & aNumToExcelColumn(curX1) of me & (curY1 as string)
        
set the end of outList to tmpRangeStr
        
set tmpRangeStr to aNumToExcelColumn(tmpX) of me & (tmpY as string) & ":"
        
set hitF to false
        
–log {"tmpRangeStr", tmpRangeStr}
      end if
    end if
    
    
copy {tmpX, tmpY} to {curX1, curY1}
  end repeat
  
  
–log {tmpRangeStr, hitF}
  
  
if (hitF = true) or (tmpRangeStr is not equal to "") then
    set tmpRangeStr to tmpRangeStr & aNumToExcelColumn(curX1) of me & (curY1 as string)
    
set the end of outList to tmpRangeStr
  end if
  
  
return outList
end retRangeFromPosListVertival

on retRangeFromPosListHorizontal(posList as list)
  script rangeSPD
    property posList2 : {}
  end script
  
  
copy posList to (posList2 of rangeSPD)
  
  
–先頭データをピックアップ
  
set firstData to first item of (posList2 of rangeSPD)
  
set (posList2 of rangeSPD) to rest of (posList2 of rangeSPD)
  
  
copy firstData to {curX1, curY1}
  
set tmpRangeStr to aNumToExcelColumn(curX1) of me & (curY1 as string) & ":"
  
  
set tmpRange to {}
  
set hitF to false
  
  
set outList to {}
  
  
repeat with i in (posList2 of rangeSPD)
    copy i to {tmpX, tmpY}
    
    
–log {"{curX1, curY1}", {curX1, curY1}}
    
–log {"{tmpX, tmpY}", {tmpX, tmpY}}
    
    
    
if (curX1 + 1 = tmpX) and (curY1 = tmpY) then
      –X方向への連続値を拾っている最中
      
if hitF = false then
        –log "case 1a"
        
–log {"hitF", hitF}
        
set hitF to true
      else
        –log "case 1b"
        
–log {"hitF", hitF}
        
–横に連続しているブロックの途中
      end if
    else
      –直前の値と連続していない
      
if hitF = false then
        –log "case 2a"
        
–log {"hitF", hitF}
        
set tmpRangeStr to tmpRangeStr & aNumToExcelColumn(curX1) of me & (curY1 as string)
        
set the end of outList to tmpRangeStr
        
set tmpRangeStr to aNumToExcelColumn(tmpX) of me & (tmpY as string) & ":"
        
set hitF to false
      else
        –log "case 2b"
        
–log {"hitF", hitF}
        
–連続ブロックの末尾を拾った
        
set tmpRangeStr to tmpRangeStr & aNumToExcelColumn(curX1) of me & (curY1 as string)
        
set the end of outList to tmpRangeStr
        
set tmpRangeStr to aNumToExcelColumn(tmpX) of me & (tmpY as string) & ":"
        
set hitF to false
        
–log {"tmpRangeStr", tmpRangeStr}
      end if
    end if
    
    
copy {tmpX, tmpY} to {curX1, curY1}
  end repeat
  
  
–log {tmpRangeStr, hitF}
  
  
if (hitF = true) or (tmpRangeStr is not equal to "") then
    set tmpRangeStr to tmpRangeStr & aNumToExcelColumn(curX1) of me & (curY1 as string)
    
set the end of outList to tmpRangeStr
  end if
  
  
return outList
end retRangeFromPosListHorizontal

–2008/05/01 By Takaaki Naganoya
–10進数数値をExcel 2004/2008的カラム表現にエンコードするサブルーチン を使いまわし
–1〜1351までの間であれば正しいエンコーディング結果を返す
on aNumToExcelColumn(origNum as integer)
  if origNum > 1351 then
    error "エラー:Excel 2004/2008的カラム表現(A1形式)への変換ルーチンにおいて、想定範囲外(1351以上)のパラメータが指定されました"
  end if
  
  
set upperDigitEncTable to {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "A"}
  
set lowerDigitEncTable to {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "A"}
  
  
set oNum to origNum
  
set nTh to 26
  
set stringLength to 4
  
  
–数字が1桁の場合の対応
  
if origNum < 27 then
    set aRes to (item origNum of upperDigitEncTable) as string
    
return aRes
  end if
  
  
  
if origNum > 702 then
    –3桁になる場合
    
set upupNum to oNum div 676 –整数除算–上の上の桁
    
set oNum to oNum – (upupNum * 676)
    
set upNum to oNum div 26 –整数除算–上の桁
    
set lowNum to oNum mod 26 – 1 –余剰計算–下の桁
    
    
–超つじつま合わせ処理
    
if lowNum = -1 then
      set upNum to upNum – 1
      
set lowNum to 25
    end if
    
    
set upupChar to (item upupNum of upperDigitEncTable) as string
    
set upChar to (item upNum of upperDigitEncTable) as string
    
set lowChar to (item (lowNum + 1) of lowerDigitEncTable) as string
    
set resText to upupChar & upChar & lowChar
    
  else
    –2桁の場合
    
set upNum to oNum div 26 –整数除算–上の桁
    
set lowNum to oNum mod 26 – 1 –余剰計算–下の桁
    
    
–超つじつま合わせ処理
    
if lowNum = -1 then
      set upNum to upNum – 1
      
set lowNum to 25
    end if
    
    
set upChar to (item upNum of upperDigitEncTable) as string
    
set lowChar to (item (lowNum + 1) of lowerDigitEncTable) as string
    
set resText to upChar & lowChar
    
  end if
  
  
return resText
end aNumToExcelColumn

–入れ子のリストを昇順ソート
on shellSortListAscending(a, keyItem)
  return sort2DList(a, keyItem, {true}) of me
end shellSortListAscending

–入れ子のリストを降順ソート
on shellSortListDecending(a, keyItem)
  return sort2DList(a, keyItem, {false}) of me
end shellSortListDecending

–2D Listをソート
on sort2DList(aList as list, sortIndexes as list, sortOrders as list)
  
  
–index値をAS流(アイテムが1はじまり)からCocoa流(アイテムが0はじまり)に変換
  
set newIndex to {}
  
repeat with i in sortIndexes
    set j to contents of i
    
set j to j – 1
    
set the end of newIndex to j
  end repeat
  
  
–Sort TypeのListを作成(あえて外部から指定する内容でもない)
  
set sortTypes to {}
  
repeat (length of sortIndexes) times
    set the end of sortTypes to "compare:"
  end repeat
  
  
–Sort
  
set resList to (current application’s SMSForder’s subarraysIn:(aList) sortedByIndexes:newIndex ascending:sortOrders sortTypes:sortTypes |error|:(missing value)) as list
  
  
return resList
end sort2DList

★Click Here to Open This Script 

Posted in Color GUI list | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy NSArray NSBezierPath NSButton NSColor NSImage NSMenu NSMenuItem NSPopUpButton NSScreen NSTextField NSView NSWindow NSWindowController Pages | 2 Comments

Pages書類の1ページ目の表の背景色を置換 v3.1(約20倍速)

Posted on 1月 29, 2019 by Takaaki Naganoya

Pagesでオープン中の最前面の書類の1ページ目に存在する表オブジェクト中の背景色を置換するAppleScriptの高速化版です。

初版では表中のセルをすべて取得し、すべてのセルについて順次背景色を求め、置換対象色であれば塗り直していました。セル1個ずつ塗っていたので、それなりの時間(テストデータでは20秒)がかかっていました。GUIアプリケーションを操作するために存在しているAppleScriptですが、アプリケーションとの通信はコストが高いので、この通信部分を減らすことが高速化の基本です。

ちなみに、「ignoring application responses」〜「end ignoring」で囲った範囲は非同期実行モードで実行され、2.5倍ぐらい高速になります。AppleScriptでは、GUIアプリケーションに対してコマンドを実行した場合、「コマンド実行」「コマンド処理」「コマンド結果受信」の3ステップを行なっています。非同期実行モードでは「コマンド実行」だけを行うので高速ですが、設定値や状態を知りたいような場合には(結果が返ってこないので)使う意味がありません。本Blogを「ignoring application responses」で検索しても、あまり出てこないはずです。

v2では、高速化のために全セルの背景色を抽出したあとに、2次元配列データ上で当該セルの座標を計算し、塗り替え対象セルのみ処理することで約35%のスピードアップを行いました。GUIアプリケーションにコマンドを送る(そして、処理を待って結果を受信する)よりも配列変数上で検索を行ったほうがはるかに高速です。

本v3では、さらなる高速化のために、2次元配列データ上で当該セルの座標を計算したあと、それらを横方向にスキャンして、点ではなく範囲(range)として評価し、極力複数のセルを連続する範囲(range)としてまとめて、rangeを一括塗りすることで初版から約20倍の高速化を行なったものです。v1やv2ではセルを1つずつ塗りつぶしていましたが、v3からは横方向に複数まとめてぬりつぶします。

実際のPages書類上の表の塗りつぶし領域が、ヘッダーや年表のような横方向に連続した塗りエリアを持つことが多いことに着目して、複数セルを一度に塗りつぶすことで高速化しました(1セル塗るのと複数セルを塗るのとで時間かわらず)。本Scriptでも1マスごとに塗りつぶしが存在するようなハッチング模様の表の塗りつぶし色を変更する場合にはパフォーマンスが最悪の状態に落ち込みますが、v2のレベル以下に落ちることはないでしょう。

この世のどこかには、さらにデータを1D Arrayではなく2D Arrayとして評価して、最大限まとめた面積のrangeとみなすことで本ルーチンの2倍ぐらいの速度で処理できるプログラムも存在しそうですが、人類の叡智のレベルを超えそうなので、自分はこのぐらいの速度が出れば満足です(総当たり的なアプローチで全パターンをシミュレーションして、一番いい結果が出るものを採用というのも考えないではないですが、シミュレーションをていねいに行うと処理時間が余計にかかるので、、、)。

1D Listに入っている座標値をX軸方向に評価して、連続値であればrangeに変換するルーチン「retRangeFromPosList」については、それほど真剣にテストしていないので処理が間違っている可能性もあります。
→ 処理に誤りがあったので修正しました(v3.1)

また、数値からExcelのA1形式のアドレスに変換するために作ってホコリをかぶっていた「aNumToExcelColumn」ルーチンも、一応テストはしてありますが変換できるアドレスの上限値が存在しているため注意が必要です。

AppleScript名:Pages書類の1ページ目の表の背景色を置換 v3.11
— Created 2017-07-15 by Takaaki Naganoya
— Modified 2019-01-29 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use Bplus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

–v1:First Version
–v2:Pick Up target cells by calculate every background color (35% speed up)
–v3:Draw cells by range (x20 speed up)
–v3.1:Bug Fix (retRangeFromPosList)
–v3.1.1:Bug Fix (retRangeFromPosList)

property NSView : a reference to current application’s NSView
property NSColor : a reference to current application’s NSColor
property NSArray : a reference to current application’s NSArray
property NSMenu : a reference to current application’s NSMenu
property NSImage : a reference to current application’s NSImage
property NSScreen : a reference to current application’s NSScreen
property NSButton : a reference to current application’s NSButton
property NSWindow : a reference to current application’s NSWindow
property NSTextField : a reference to current application’s NSTextField
property NSMenuItem : a reference to current application’s NSMenuItem
property NSBezierPath : a reference to current application’s NSBezierPath
property NSPopUpButton : a reference to current application’s NSPopUpButton
property NSWindowController : a reference to current application’s NSWindowController
property NSTitledWindowMask : a reference to current application’s NSTitledWindowMask
property NSRoundedBezelStyle : a reference to current application’s NSRoundedBezelStyle
property NSNormalWindowLevel : a reference to current application’s NSNormalWindowLevel
property NSBackingStoreBuffered : a reference to current application’s NSBackingStoreBuffered
property NSMomentaryLightButton : a reference to current application’s NSMomentaryLightButton

property windisp : true
property wController : missing value
property pop1ind : 1

–初期化
set (my windisp) to true
set (my pop1ind) to 1
load framework

–Pagesの1ページ目にある表の塗り色を取得
tell application "Pages"
  tell front document
    tell table 1
      set c1List to background color of every cell
      
set aProp to properties
      
set xCount to column count of aProp
    end tell
  end tell
end tell

–色データをユニーク化(重複削除)
set bList to uniquifyList(c1List) of me

–Convert 1D List to 2D List
set c3List to (current application’s SMSForder’s subarraysFrom:c1List groupedBy:xCount |error|:(missing value)) as list

–missing value(背景色なし)を除外する
load framework
set c2List to (current application’s SMSForder’s arrayByDeletingBlanksIn:(bList)) as list

–Popup Menuで置換色選択
set aButtonMSG to "OK"
set aSliderValMSG to "Select Target Color"
set paramObj to {c2List, 65535, aButtonMSG, aSliderValMSG, 20}
my performSelectorOnMainThread:"getPopupValues:" withObject:(paramObj) waitUntilDone:true
set fromCol to (contents of item pop1ind of c2List)

–カラーピッカーで置換色選択
set tCol to choose color default color fromCol

set d1 to current date

–実際に表の背景色を置換する
set hitList to findDataFrom2DList(fromCol, c3List) of me –データ上で当該色のセル情報を計算する

set rangeList to retRangeFromPosList(hitList) of me

tell application "Pages"
  tell front document
    tell table 1
      repeat with i in rangeList
        set j to contents of i
        
        
ignoring application responses –非同期実行モードで高速実行
          set background color of range j to tCol
        end ignoring
      end repeat
    end tell
  end tell
end tell

set d2 to current date
return d2 – d1

–カラーポップアップメニューをウィンドウ表示
on getPopupValues:paramObj
  copy (paramObj as list) to {ap1List, aColMax, aButtonMSG, aSliderValMSG, timeOutSecs}
  
  
set (my windisp) to true
  
  
set aView to NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 360, 100))
  
  
–Labelをつくる
  
set a1TF to NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(30, 60, 80, 20))
  
a1TF’s setEditable:false
  
a1TF’s setStringValue:"Color:"
  
a1TF’s setDrawsBackground:false
  
a1TF’s setBordered:false
  
  
–Ppopup Buttonをつくる
  
set a1Button to NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(80, 60, 200, 20)) pullsDown:false
  
a1Button’s removeAllItems()
  
  
set a1Menu to NSMenu’s alloc()’s init()
  
  
set iCount to 1
  
repeat with i in ap1List
    copy i to {r1, g1, b1}
    
    
set nsCol to makeNSColorFromRGBAval(r1, g1, b1, aColMax, aColMax) of me
    
set anImage to makeNSImageWithFilledWithColor(64, 64, nsCol) of me
    
    
set aTitle to "color_" & (iCount as string)
    
set aMenuItem to (NSMenuItem’s alloc()’s initWithTitle:aTitle action:"actionHandler:" keyEquivalent:"")
    (
aMenuItem’s setImage:anImage)
    (
aMenuItem’s setEnabled:true)
    (
a1Menu’s addItem:aMenuItem)
    
    
set iCount to iCount + 1
  end repeat
  
  
a1Button’s setMenu:a1Menu
  
  
  
–Buttonをつくる
  
set bButton to (NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(80, 10, 140, 40)))
  
bButton’s setButtonType:(NSMomentaryLightButton)
  
bButton’s setBezelStyle:(NSRoundedBezelStyle)
  
bButton’s setTitle:aButtonMSG
  
bButton’s setTarget:me
  
bButton’s setAction:("clicked:")
  
bButton’s setKeyEquivalent:(return)
  
  
aView’s addSubview:a1TF
  
  
aView’s addSubview:a1Button
  
aView’s addSubview:bButton
  
aView’s setNeedsDisplay:true
  
  
–NSWindowControllerを作ってみた(いらない?)
  
set aWin to (my makeWinWithView(aView, 300, 100, aSliderValMSG))
  
  
set wController to NSWindowController’s alloc()
  
wController’s initWithWindow:aWin
  
  
wController’s showWindow:me
  
  
set aCount to timeOutSecs * 100
  
  
set hitF to false
  
repeat aCount times
    if (my windisp) = false then
      set hitF to true
      
exit repeat
    end if
    
delay 0.01
    
set aCount to aCount – 1
  end repeat
  
  
my closeWin:aWin
  
  
if hitF = true then
    set s1Val to ((a1Button’s indexOfSelectedItem() as number) + 1)
  else
    set s1Val to false
  end if
  
  
copy s1Val to my pop1ind
  
end getPopupValues:

on clicked:aSender
  set (my windisp) to false
end clicked:

–make Window for Display
on makeWinWithView(aView, aWinWidth, aWinHeight, aTitle)
  set aScreen to NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {aWinWidth, aWinHeight}}
  
  
set aBacking to NSTitledWindowMask
  
  
set aDefer to NSBackingStoreBuffered
  
  
— Window
  
set aWin to NSWindow’s alloc()
  (
aWin’s initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)
  
  
aWin’s setTitle:aTitle
  
aWin’s setDelegate:me
  
aWin’s setDisplaysWhenScreenProfileChanges:true
  
aWin’s setHasShadow:true
  
aWin’s setIgnoresMouseEvents:false
  
aWin’s setLevel:(NSNormalWindowLevel)
  
aWin’s setOpaque:false
  
aWin’s setReleasedWhenClosed:true
  
aWin’s |center|()
  
  
aWin’s setContentView:aView
  
  
return aWin
end makeWinWithView

–close win
on closeWin:aWindow
  repeat with n from 10 to 1 by -1
    (aWindow’s setAlphaValue:n / 10)
    
delay 0.02
  end repeat
  
aWindow’s |close|()
end closeWin:

–Popup Action Handler
on actionHandler:sender
  set aTag to tag of sender as integer
  
set aTitle to title of sender as string
end actionHandler:

–aMaxValを最大値とする数値でNSColorを作成して返す
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

–指定サイズのNSImageを作成し、指定色で塗ってNSImageで返す
on makeNSImageWithFilledWithColor(aWidth, aHeight, fillColor)
  set anImage to NSImage’s alloc()’s initWithSize:(current application’s NSMakeSize(aWidth, aHeight))
  
anImage’s lockFocus()
  
—
  
set theRect to {{x:0, y:0}, {height:aHeight, width:aWidth}}
  
set theNSBezierPath to NSBezierPath’s bezierPath
  
theNSBezierPath’s appendBezierPathWithRect:theRect
  
—
  
fillColor’s |set|() –色設定
  
theNSBezierPath’s fill() –ぬりつぶし
  
—
  
anImage’s unlockFocus()
  
—
  
return anImage
end makeNSImageWithFilledWithColor

on uniquifyList(aList as list)
  set aArray to NSArray’s arrayWithArray:aList
  
set bArray to aArray’s valueForKeyPath:"@distinctUnionOfObjects.self"
  
return bArray as list
end uniquifyList

on findDataFrom2DList(anItem, aList)
  script spd
    property aList : {}
    
property resList : {}
  end script
  
  
set (aList of spd) to aList
  
set (resList of spd) to {}
  
  
set yCount to 1
  
  
repeat with i in (aList of spd)
    
    
set aResList to (Bplus’s indexesOfItem:anItem inList:i inverting:false) as list
    
    
set tmpList to {}
    
if aResList is not equal to {} then
      repeat with ii in aResList
        set jj to contents of ii
        
set the end of tmpList to {jj, yCount}
      end repeat
      
set (resList of spd) to (resList of spd) & tmpList
    end if
    
    
set yCount to yCount + 1
  end repeat
  
  
return (resList of spd) –return {{x, y}…..} item list (1-based)
end findDataFrom2DList

on retRangeFromPosList(posList as list)
  script rangeSPD
    property posList2 : {}
  end script
  
  
copy posList to (posList2 of rangeSPD)
  
  
–先頭データをピックアップ
  
set firstData to first item of (posList2 of rangeSPD)
  
set (posList2 of rangeSPD) to rest of (posList2 of rangeSPD)
  
  
copy firstData to {curX1, curY1}
  
set tmpRangeStr to aNumToExcelColumn(curX1) of me & (curY1 as string) & ":"
  
  
set tmpRange to {}
  
set hitF to false
  
  
set outList to {}
  
  
repeat with i in (posList2 of rangeSPD)
    copy i to {tmpX, tmpY}
    
    
–log {"{curX1, curY1}", {curX1, curY1}}
    
–log {"{tmpX, tmpY}", {tmpX, tmpY}}
    
    
    
if (curX1 + 1 = tmpX) and (curY1 = tmpY) then
      –X方向への連続値を拾っている最中
      
if hitF = false then
        –log "case 1a"
        
–log {"hitF", hitF}
        
set hitF to true
      else
        –log "case 1b"
        
–log {"hitF", hitF}
        
–横に連続しているブロックの途中
      end if
    else
      –直前の値と連続していない
      
if hitF = false then
        –log "case 2a"
        
–log {"hitF", hitF}
        
set tmpRangeStr to tmpRangeStr & aNumToExcelColumn(curX1) of me & (curY1 as string)
        
set the end of outList to tmpRangeStr
        
set tmpRangeStr to aNumToExcelColumn(tmpX) of me & (tmpY as string) & ":"
        
set hitF to false
      else
        –log "case 2b"
        
–log {"hitF", hitF}
        
–連続ブロックの末尾を拾った
        
set tmpRangeStr to tmpRangeStr & aNumToExcelColumn(curX1) of me & (curY1 as string)
        
set the end of outList to tmpRangeStr
        
set tmpRangeStr to aNumToExcelColumn(tmpX) of me & (tmpY as string) & ":"
        
set hitF to false
        
–log {"tmpRangeStr", tmpRangeStr}
      end if
    end if
    
    
copy {tmpX, tmpY} to {curX1, curY1}
  end repeat
  
  
–log {tmpRangeStr, hitF}
  
  
if (hitF = true) or (tmpRangeStr is not equal to "") then
    set tmpRangeStr to tmpRangeStr & aNumToExcelColumn(curX1) of me & (curY1 as string)
    
set the end of outList to tmpRangeStr
  end if
  
  
return outList
end retRangeFromPosList

–2008/05/01 By Takaaki Naganoya
–10進数数値をExcel 2004/2008的カラム表現にエンコードするサブルーチン を使いまわし
–1〜1351までの間であれば正しいエンコーディング結果を返す
on aNumToExcelColumn(origNum as integer)
  if origNum > 1351 then
    display dialog "エラー:Excel 2004/2008的カラム表現(A1形式)への変換ルーチンにおいて、想定範囲外(1351以上)のパラメータが指定されました" buttons {"OK"} default button 1
    
return ""
  end if
  
  
set upperDigitEncTable to {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "A"}
  
set lowerDigitEncTable to {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "A"}
  
  
set oNum to origNum
  
set nTh to 26
  
set stringLength to 4
  
  
–数字が1桁の場合の対応
  
if origNum < 27 then
    set aRes to (item origNum of upperDigitEncTable) as string
    
return aRes
  end if
  
  
  
if origNum > 702 then
    –3桁になる場合
    
set upupNum to oNum div 676 –整数除算–上の上の桁
    
set oNum to oNum – (upupNum * 676)
    
set upNum to oNum div 26 –整数除算–上の桁
    
set lowNum to oNum mod 26 – 1 –余剰計算–下の桁
    
    
–超つじつま合わせ処理
    
if lowNum = -1 then
      set upNum to upNum – 1
      
set lowNum to 25
    end if
    
    
set upupChar to (item upupNum of upperDigitEncTable) as string
    
set upChar to (item upNum of upperDigitEncTable) as string
    
set lowChar to (item (lowNum + 1) of lowerDigitEncTable) as string
    
set resText to upupChar & upChar & lowChar
    
  else
    –2桁の場合
    
set upNum to oNum div 26 –整数除算–上の桁
    
set lowNum to oNum mod 26 – 1 –余剰計算–下の桁
    
    
–超つじつま合わせ処理
    
if lowNum = -1 then
      set upNum to upNum – 1
      
set lowNum to 25
    end if
    
    
set upChar to (item upNum of upperDigitEncTable) as string
    
set lowChar to (item (lowNum + 1) of lowerDigitEncTable) as string
    
set resText to upChar & lowChar
    
  end if
  
  
return resText
end aNumToExcelColumn

★Click Here to Open This Script 

Posted in Color GUI list | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy NSArray NSBackingStoreBuffered NSBezierPath NSButton NSColor NSImage NSMenu NSMenuItem NSMomentaryLightButton NSNormalWindowLevel NSPopUpButton NSRoundedBezelStyle NSScreen NSTextField NSTitledWindowMask NSView NSWindow NSWindowController Pages | Leave a comment

2D List内で検索してヒットした情報をすべて返す

Posted on 1月 24, 2019 by Takaaki Naganoya

2D List内で項目を検索して、ヒットした項目をすべて{x,y}のアイテム番号リストで返すAppleScriptです。

# 年がら年中、この手のScriptを書き捨てているような気もしますが、、、

Excelのワークシート上の情報をすべて読み取って、2D Listの中をデータ検索するような処理で使うための部品です。

AppleScript名:2D List内で検索してヒットした情報をすべて返す.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/01/24
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use Bplus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

set anItem to "a"
set aList to {{"b", "a", "c", "a"}, {"a", "a", "c", "a"}, {"b", "v", "c", "a"}, {"b", "a", "c", "a"}}
set bRes to findDataFrom2DList(anItem, aList) of me
–> {{2, 1}, {4, 1}, {1, 2}, {2, 2}, {4, 2}, {4, 3}, {2, 4}, {4, 4}}

on findDataFrom2DList(anItem, aList)
  script spd
    property aList : {}
    
property resList : {}
  end script
  
  
set (aList of spd) to aList
  
set (resList of spd) to {}
  
  
set yCount to 1
  
  
repeat with i in (aList of spd)
    
    
set aResList to (Bplus’s indexesOfItem:anItem inList:i inverting:false) as list
    
    
set tmpList to {}
    
if aResList is not equal to {} then
      repeat with ii in aResList
        set jj to contents of ii
        
set the end of tmpList to {jj, yCount}
      end repeat
      
set (resList of spd) to (resList of spd) & tmpList
    end if
    
    
set yCount to yCount + 1
  end repeat
  
  
return (resList of spd) –return {{x, y}…..} item list (1-based)
end findDataFrom2DList

★Click Here to Open This Script 

Posted in list | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy | 1 Comment

指定の1D Listの要素数がaMaxLenに満たない場合には、1D Listの末尾のアイテムでaMaxLenまで埋める

Posted on 1月 3, 2019 by Takaaki Naganoya

指定の1D List(Array)の要素数が指定数に満たない場合には、List末尾のアイテムで指定要素数まで埋めるAppleScriptです。

{"1", "2", "3", "4", "5"}

のようなListがあって、最大数を10と指定してあった場合には、

{"1", "2", "3", "4", "5", "5", "5", "5", "5", "5"}

のように処理します。

AppleScript名:指定の1D Listの要素数がaMaxLenに満たない場合には、1D Listの末尾のアイテムでaMaxLenまで埋める
— Created 2019-01-03 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aList to {"11111", "22222", "33333", "44444", "55555"}
set aaList to fillByLastItemToMaxItems(aList, 6) of me
–> {"11111", "22222", "33333", "44444", "55555", "55555"}

–指定の1D Listの要素数がaMaxLenに満たない場合には、1D Listの末尾のアイテムでaMaxLenまで埋める
on fillByLastItemToMaxItems(aList as list, aMaxLen as integer)
  set aLen to length of aList
  
if aLen is not equal to aMaxLen then
    set anItem to contents of last item of aList
    
repeat aMaxLen – aLen times
      set the end of aList to anItem
    end repeat
  end if
  
  
return aList
end fillByLastItemToMaxItems

★Click Here to Open This Script 

Posted in list | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy | Leave a comment

指定の1D Listでゼロが入っていたら末尾のゼロの前の要素で埋める

Posted on 1月 3, 2019 by Takaaki Naganoya

指定の1D List(Array)でゼロが入っていたら、末尾のゼロの前の要素で埋めるAppleScriptです。

{"1", "2", "3", "4", "0", "0"}

のようなリストがあった場合に、

{"1", "2", "3", "4", "4", "4"}

のような処理を行います。

AppleScript名:指定の1D Listでゼロが入っていたら末尾のゼロの前の要素で埋める
— Created 2019-01-03 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aList to {"11111", "22222", "33333", "44444", "0", "0"}
set abList to fillByLastItemIfZero(aList)
–> {"11111", "22222", "33333", "44444", "44444", "44444"}

–指定の1D Listでゼロが入っていたらゼロの前の要素で埋める
on fillByLastItemIfZero(aList as list)
  set aLen to length of aList
  
set bList to {}
  
set prevDat to -1
  
  
set aFirst to (contents of first item of aList) as string
  
if aFirst = "0" then error "First Item is 0 in a list"
  
  
repeat with i in aList
    set aTmp to i as string
    
    
if aTmp = "0" then
      copy prevDat to aTmp
    else
      copy aTmp to prevDat
    end if
    
    
set the end of bList to aTmp
  end repeat
  
  
return bList
end fillByLastItemIfZero

★Click Here to Open This Script 

Posted in list | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy | Leave a comment

1D Listのうち指定文字種(複数指定可)で構成される要素のみ抽出 v2

Posted on 1月 1, 2019 by Takaaki Naganoya

1D List(配列)に入れた文字要素を文字種類で該当するものだけ抽出するAppleScriptの改良版です。

プログラムを見ていただくとわかるとおり、

 数字:”9″
 英字:”A”
 半角記号:”$”
 ひらがな:”ひ”
 カタカナ:”カ”
 漢字:”漢”

で文字種類を指定します。

ルーチンは2種類用意しており、

filterByMultipleCharKindStrictly:文字種別を判定して指定文字種のみから構成されるものを抽出(厳密に文字種別を遵守)
filterByMultipleCharKind:文字種別を判定して指定文字種のみから構成されるものを抽出

前者は複数の文字種リストを指定したら、その文字種リストと等しいパターンの文字列だけを抽出します。
後者は複数の文字種リストを指定したら、その文字種のうちどれかだけで構成される文字列だけを抽出します。

 {"Naganoya", "ながのや", "ナガノヤ", "長野谷", "ぴよまるソフトウェア", "ぴよまるSoftware", "Piyomaru12345", "123456789", "ぴよまる1234"} 

  
という文字列を与え、

{"ひ", "カ"}--Hiragana, Katakana

  
という抽出パターンを指定すると、

filterByMultipleCharKindStrictly --> {"ぴよまるソフトウェア"}
filterByMultipleCharKind --> {"ながのや", "ナガノヤ"}

  
のように抽出します。

スピードを考えなければ、機能は実用レベルにあると思われます。

高速化する場合には、

(1)Cocoaの機能を一切使わない(小さいデータを小分けにしてCocoaの機能を呼び出しているので、Cocoaの機能を使って高速化するのに最悪の処理パターンになっている。データ量のわりに時間がかかる。むしろCocoaの機能を使わない方が高速)

(2)Cocoaで一括処理できるように検討する(NSPredicatesで文字種別を同時に指定して抽出するなど)

といったところでしょうか。長い割にはそんなによくないプログラムですね。機能すること以外に取り柄がないというか、、、

AppleScript名:1D Listのうち指定文字種(複数指定可)で構成される要素のみ抽出 v2
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/01/01
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

property NSArray : a reference to current application’s NSArray
property NSString : a reference to current application’s NSString
property NSScanner : a reference to current application’s NSScanner
property NSNumber : a reference to current application’s NSNumber
property NSDictionary : a reference to current application’s NSDictionary
property NSOrderedSet : a reference to current application’s NSOrderedSet
property NSCountedSet : a reference to current application’s NSCountedSet
property NSCharacterSet : a reference to current application’s NSCharacterSet
property NSMutableArray : a reference to current application’s NSMutableArray
property NSSortDescriptor : a reference to current application’s NSSortDescriptor
property NSNumberFormatter : a reference to current application’s NSNumberFormatter
property NSMutableCharacterSet : a reference to current application’s NSMutableCharacterSet
property NSRegularExpressionSearch : a reference to current application’s NSRegularExpressionSearch
property NSNumberFormatterRoundUp : a reference to current application’s NSNumberFormatterRoundUp
property NSStringTransformFullwidthToHalfwidth : a reference to current application’s NSStringTransformFullwidthToHalfwidth

set aList to {"Naganoya", "ながのや", "ナガノヤ", "長野谷", "ぴよまるソフトウェア", "ぴよまるSoftware", "Piyomaru12345", "123456789", "ぴよまる1234"} –Alphabet, Hiragana, Katakana, Kanji, Hiragana+Katakana, Hiragana + Alphabet, Alphabet + Numeric, Numeric

set aRes to filterByMultipleCharKind(aList, {"A"}) of me –アルファベットで構成される要素のみ抽出
–> {"Naganoya"}

set bRes to filterByMultipleCharKind(aList, {"ひ"}) of me –ひらがなだけで構成される要素のみ抽出
–> {"ながのや"}

set cRes to filterByMultipleCharKind(aList, {"カ"}) of me –カタカナだけで構成される要素のみ抽出
–> {"ナガノヤ"}

set dRes to filterByMultipleCharKind(aList, {"漢"}) of me –漢字だけで構成される要素のみ抽出
–> {"長野谷"}

set eRes1 to filterByMultipleCharKindStrictly(aList, {"ひ", "カ"}) of me –ひらがな+カタカナで構成される要素のみ抽出
–> {"ぴよまるソフトウェア"}

set eRes2 to filterByMultipleCharKind(aList, {"ひ", "カ"}) of me –ひらがな or カタカナ だけで構成される要素のみ抽出
–> {"ながのや", "ナガノヤ"}

set fRes1 to filterByMultipleCharKindStrictly(aList, {"A", "9"}) of me –Alphabet + Numericだけで構成される要素のみ抽出
–> {"Piyomaru12345"}

set fRes2 to filterByMultipleCharKind(aList, {"A", "9"}) of me –Alphabet or Numericだけで構成される要素のみ抽出
–> {"Naganoya", "123456789"}

set gRes1 to filterByMultipleCharKindStrictly(aList, {"ひ", "9"}) of me –Hiragana + Numericだけで構成される要素のみ抽出
–> {"ぴよまる1234"}

–文字種別を判定して指定文字種のみから構成されるものを抽出(厳密に文字種別を遵守)
on filterByMultipleCharKindStrictly(aList as list, targCharKindList as list)
  set dList to {}
  
set paramList to sort1DStringList(targCharKindList, true) of me
  
  
repeat with i in aList
    set j to contents of i
    
set tmpPat to retAtrPatternFromStr(j) of me
    
if tmpPat is equal to paramList then
      set the end of dList to j
    end if
  end repeat
  
  
return dList
end filterByMultipleCharKindStrictly

–文字種別を判定して指定文字種のみから構成されるものを抽出
on filterByMultipleCharKind(aList as list, targCharKindList as list)
  set dList to {}
  
  
repeat with i in aList
    set j to contents of i
    
set tmpPat to retAtrPatternFromStr(j) of me
    
if tmpPat is in targCharKindList then
      set the end of dList to j
    end if
  end repeat
  
  
return dList
end filterByMultipleCharKind

–Objective-Cライクなパラメータ記述
on makeUniqueListOf:theList
  set theSet to NSOrderedSet’s orderedSetWithArray:theList
  
return (theSet’s array()) as list
end makeUniqueListOf:

–Pure AS風のパラメータ記述
on makeUniqueListFrom(theList)
  set aList to my makeUniqueListOf:theList
  
return aList
end makeUniqueListFrom

–1D Listを文字列長でソート v2
on sort1DListByStringLength(aList as list, sortOrder as boolean)
  set aArray to NSArray’s arrayWithArray:aList
  
set desc1 to NSSortDescriptor’s sortDescriptorWithKey:"length" ascending:sortOrder
  
set desc2 to NSSortDescriptor’s sortDescriptorWithKey:"self" ascending:true selector:"localizedCaseInsensitiveCompare:"
  
set bArray to aArray’s sortedArrayUsingDescriptors:{desc1, desc2}
  
return bArray as list of string or string
end sort1DListByStringLength

–1D List(文字)をsort / ascOrderがtrueだと昇順ソート、falseだと降順ソート
on sort1DStringList(theList as list, aBool as boolean)
  set aDdesc to NSSortDescriptor’s sortDescriptorWithKey:"self" ascending:aBool selector:"localizedCaseInsensitiveCompare:"
  
set theArray to NSArray’s arrayWithArray:theList
  
return (theArray’s sortedArrayUsingDescriptors:{aDdesc}) as list
end sort1DStringList

–文字種別の判定
on retAtrPatternFromStr(aText as string)
  set b1List to {"9", "A", "$", "漢", "ひ", "カ"} –数字、アルファベット、記号、全角漢字、全角ひらがな、全角カタカナ
  
  
set outList to {}
  
set cList to characters of (aText)
  
  
repeat with i in cList
    set j to contents of i
    
    
set chk1 to ((my chkNumeric:j) as integer) * 1
    
set chk2 to ((my chkAlphabet:j) as integer) * 2
    
set chk3 to ((my chkSymbol:j) as integer) * 3
    
set chk4 to ((my chkKanji:j) as integer) * 4
    
set chk5 to ((my chkHiragana:j) as integer) * 5
    
set chk6 to ((my chkKatakana:j) as integer) * 6
    
    
set itemVal to (chk1 + chk2 + chk3 + chk4 + chk5 + chk6)
    
    
–if itemVal > 0 then
    
set aVal to (contents of item itemVal of b1List)
    
    
if aVal is not in outList then
      set the end of outList to aVal
    end if
    
–end if
  end repeat
  
  
set out2List to sort1DStringList(outList, true) of me
  
  
return out2List
end retAtrPatternFromStr

–全角→半角変換
on zenToHan(aStr)
  set aString to NSString’s stringWithString:aStr
  
return (aString’s stringByApplyingTransform:(NSStringTransformFullwidthToHalfwidth) |reverse|:false) as string
end zenToHan

–数字か
on chkNumeric:checkString
  set digitCharSet to NSCharacterSet’s characterSetWithCharactersInString:"0123456789"
  
set ret to my chkCompareString:checkString baseString:digitCharSet
  
return ret as boolean
end chkNumeric:

–記号か
on chkSymbol:checkString
  set muCharSet to NSCharacterSet’s alloc()’s init()
  
muCharSet’s addCharactersInString:"$\"!~&=#[]._-+`|{}?%^*/’@-/:;(),"
  
set ret to my chkCompareString:checkString baseString:muCharSet
  
return ret as boolean
end chkSymbol:

–漢字か
on chkKanji:aChar
  return detectCharKind(aChar, "[一-龠]") of me
end chkKanji:

–ひらがなか
on chkHiragana:aChar
  return detectCharKind(aChar, "[ぁ-ん]") of me
end chkHiragana:

–カタカナか
on chkKatakana:aChar
  return detectCharKind(aChar, "[ァ-ヶ]") of me
end chkKatakana:

–半角スペースか
on chkSpace:checkString
  set muCharSet to NSCharacterSet’s alloc()’s init()
  
muCharSet’s addCharactersInString:" " –半角スペース(20h)
  
set ret to my chkCompareString:checkString baseString:muCharSet
  
return ret as boolean
end chkSpace:

— アルファベットか
on chkAlphabet:checkString
  set aStr to NSString’s stringWithString:checkString
  
set allCharSet to NSMutableCharacterSet’s alloc()’s init()
  
allCharSet’s addCharactersInRange:({location:97, |length|:26}) –97 = id of "a"
  
allCharSet’s addCharactersInRange:({location:65, |length|:26}) –65 = id of "A"
  
set aBool to my chkCompareString:aStr baseString:allCharSet
  
return aBool as boolean
end chkAlphabet:

on chkCompareString:checkString baseString:baseString
  set aScanner to NSScanner’s localizedScannerWithString:checkString
  
aScanner’s setCharactersToBeSkipped:(missing value)
  
aScanner’s scanCharactersFromSet:baseString intoString:(missing value)
  
return (aScanner’s isAtEnd()) as boolean
end chkCompareString:baseString:

on detectCharKind(aChar, aPattern)
  set aChar to NSString’s stringWithString:aChar
  
set searchStr to NSString’s stringWithString:aPattern
  
set matchRes to aChar’s rangeOfString:searchStr options:(NSRegularExpressionSearch)
  
if matchRes’s location() = (current application’s NSNotFound) or (matchRes’s location() as number) > 9.99999999E+8 then
    return false
  else
    return true
  end if
end detectCharKind

★Click Here to Open This Script 

Posted in list Text | Tagged 10.11savvy 10.12savvy | Leave a comment

iTunesライブラリ中の楽曲のみしぼりこんでアルバム名と曲名を出力 v2

Posted on 12月 23, 2018 by Takaaki Naganoya

iTunesライブラリ(+Apple Book)のメディアから楽曲(mediaKind=ITLibMediaItemMediaKindSong)のみ抽出してアルバムのタイトル+曲名の一覧を取得するAppleScriptです。

--> {{albumTitle:"アルバムタイトル名", songTitle:"曲名"}....}

のように、アルバム名と曲名のレコードをリスト化して返します。

iTunesLibrary.framework経由でメデイアアイテムの情報にアクセスするため、iTunes.appが起動していてもいなくても関係ありません。開発環境のマシン(MacBook Pro Retina 2012 Core i7 2.66GHz)でiTunesに6,871曲の楽曲が存在している状態で3.12秒程度です。

iTunes.appとプロセス間通信していないため、macOS 10.14でSecurityダイアログが表示されることもありません。

AppleScript名:iTunesライブラリ中の楽曲のみしぼりこんでアルバム名と曲名を出力 v2.scptd
— Created 2018-10-16 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "iTunesLibrary"

script spdList
  property albmList : {}
  
property outList : {}
end script

property ITLibrary : a reference to current application’s ITLibrary
property NSPredicate : a reference to current application’s NSPredicate

set library to ITLibrary’s libraryWithAPIVersion:"1.0" |error|:(missing value)
if library is equal to missing value then return

set playLists to library’s allPlaylists()
set gArray to (library’s allMediaItems())

set aPredicate to NSPredicate’s predicateWithFormat:"self.mediaKind = 2" –ITLibMediaItemMediaKindSong
set filteredArray to gArray’s filteredArrayUsingPredicate:aPredicate

set albmArray to (filteredArray’s album’s title)
set (albmList of spdList) to (albmArray’s valueForKeyPath:"@distinctUnionOfObjects.self") as list
set songArray to (filteredArray’s title) as list
set aLen to length of songArray
set albmArray to albmArray as list

repeat with i from 1 to aLen
  set tmpItem1 to contents of item i of albmArray
  
set tmpItem2 to contents of item i of songArray
  
set the end of (outList of spdList) to {albumTitle:tmpItem1, songTitle:tmpItem2}
end repeat

★Click Here to Open This Script 

Posted in list Record | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy ITLibrary iTunes NSPredicate | Leave a comment

iTunesライブラリ中の楽曲のみしぼりこんでアルバムのtitle一覧を取得

Posted on 12月 22, 2018 by Takaaki Naganoya

iTunesライブラリ(+Apple Book)のメディアから楽曲(mediaKind=ITLibMediaItemMediaKindSong)のみ抽出してアルバムのタイトル一覧を取得するAppleScriptです。

iTunesLibrary.framework経由でメデイアアイテムの情報にアクセスするため、iTunes.appが起動していてもいなくても関係ありません。開発環境のマシン(MacBook Pro Retina 2012 Core i7 2.66GHz)でiTunesに6,871曲の楽曲が存在している状態で0.03秒程度です。

iTunes.appとプロセス間通信していないため、macOS 10.14でSecurityダイアログが表示されることもありません。

AppleScript名:iTunesライブラリ中の楽曲のみしぼりこんでアルバムのtitle一覧を取得.scptd
— Created 2018-10-16 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "iTunesLibrary"

property ITLibrary : a reference to current application’s ITLibrary
property NSPredicate : a reference to current application’s NSPredicate

set library to ITLibrary’s libraryWithAPIVersion:"1.0" |error|:(missing value)
if library is equal to missing value then return

set playLists to library’s allPlaylists()
set gArray to (library’s allMediaItems())

set aPredicate to NSPredicate’s predicateWithFormat:"self.mediaKind = 2" –ITLibMediaItemMediaKindSong
set filteredArray to gArray’s filteredArrayUsingPredicate:aPredicate
set tArray to (filteredArray’s album’s title)
set bList to (tArray’s valueForKeyPath:"@distinctUnionOfObjects.self") as list
–> {"アニメる", "庄野真代ゴールデン☆ベスト: シングル・コレクション & 筒美京平作品集", "ウォンテッド(指名手配) [Original Cover Art] – Single", "君が人生の時…", "3年B組金八先生 THEME SONG COLLECTION", "HOLD ME", "Piano Stories", "にんじゃりばんばん – Single", …..}

★Click Here to Open This Script 

Posted in list | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy ITLibrary iTunes NSPredicate | Leave a comment

Keynoteで指定の表をX LabelとY Labelの交差するセルにデータを設定する v2

Posted on 12月 22, 2018 by Takaaki Naganoya

オープン中のKeynote書類のうち、指定タイトルのスライド中の表の値を取得したり設定するAppleScriptです。

シート名(タイトル)、表Yラベル、表Xラベル

の3つのパラメータをもとに、Keynote書類中の指定スライドの表の中のセルにアクセスして、値を取得/設定します。

処理対象のKeynote書類はKeynoteでオープンしている必要があり、各スライド中の表は1つのみ存在していることを処理の前提条件としています。

一応、再利用性を高めるためにScriptオブジェクト化しています。これがベストな方法なわけではありませんが、こんなもんでしょう。

AppleScript名:Keynoteで指定の表をX LabelとY Labelの交差するセルに設定する v2
— Created 2018-12-20 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set targCellNameX to "Col2"
set targCellNameY to "Row4"
set storeVal to "9999"

set keynoteSlide to "Page 2 Title"

set keynoteSlideObj to getTitleStringFromFrontKeynoteDocumentFilterByString(keynoteSlide) of getKeynoteSlideKit
–set aRes to getValueOnKeynoteTableByXYLabels(targCellNameY, targCellNameX, keynoteSlideObj) of getKeynoteSlideKit
setValueOnKeynoteTableByXYLabels(targCellNameY, targCellNameX, storeVal, keynoteSlideObj) of getKeynoteSlideKit

script getKeynoteSlideKit
  –Keynote タイトル指定してslideを取得する
  
on getTitleStringFromFrontKeynoteDocumentFilterByString(targString)
    set repTargList to {string id 10, string id 11, string id 13} –LF,CR,VTab一括置換
    
    
tell application "Keynote"
      if (count every document) = 0 then return
      
      
tell front document
        set tList to object text of default title item of every slide
      end tell
    end tell
    
    
–タイトルごとにゴミ取り(改行文字の削除)
    
set outList to {}
    
set sCount to 1
    
set hitF to false
    
repeat with i in tList
      set j1 to contents of i
      
set jTmp to (paragraphs of j1) as string –しつこい改行文字(?)を除去するための処理
      
      
set j2 to replaceTextMultiple(jTmp, repTargList, "") of me as string
      
if j2 is equal to targString then
        set hitF to true
        
exit repeat
      end if
      
      
set sCount to sCount + 1
    end repeat
    
    
if hitF = false then return false
    
    
tell application "Keynote"
      tell front document
        return item sCount of (every slide)
      end tell
    end tell
    
  end getTitleStringFromFrontKeynoteDocumentFilterByString
  
  
  
–リストを指定デリミタで区切ったテキストに変換
  
on listToStringUsingTextItemDelimiter(sourceList as list, textItemDelimiter as string)
    set anArray to current application’s NSArray’s arrayWithArray:sourceList
    
set aString to anArray’s componentsJoinedByString:textItemDelimiter
    
return (aString as string)
  end listToStringUsingTextItemDelimiter
  
  
  
–任意のデータから特定の文字列を複数パターン一括置換
  
on replaceTextMultiple(origData as string, origTexts as list, repText as string)
    set curDelim to AppleScript’s text item delimiters
    
set AppleScript’s text item delimiters to origTexts
    
set origData to text items of origData
    
set AppleScript’s text item delimiters to {repText}
    
set origData to origData as text
    
set AppleScript’s text item delimiters to curDelim
    
return origData
  end replaceTextMultiple
  
  
–行ラベルと列ラベルを個別に指定し、交点のセルに指定の値を入れる
  
on setValueOnKeynoteTableByXYLabels(targCellNameY, targCellNameX, storeVal, keynoteSlideObj)
    tell application "Keynote"
      tell keynoteSlideObj
        tell table 1
          
          
tell row 1
            set cList to value of every cell
            
set xRes to getOffsetFromList(targCellNameX, cList) of me
          end tell
          
          
tell column 1
            set dList to value of every cell
            
set yRes to getOffsetFromList(targCellNameY, dList) of me
          end tell
          
          
tell row yRes
            tell cell xRes
              set its value to storeVal
            end tell
          end tell
          
        end tell
      end tell
    end tell
  end setValueOnKeynoteTableByXYLabels
  
  
  
–行ラベルと列ラベルを個別に指定し、交点のセルに指定の値を入れる
  
on getValueOnKeynoteTableByXYLabels(targCellNameY, targCellNameX, keynoteSlideObj)
    tell application "Keynote"
      tell keynoteSlideObj
        tell table 1
          
          
tell row 1
            set cList to value of every cell
            
set xRes to getOffsetFromList(targCellNameX, cList) of me
          end tell
          
          
tell column 1
            set dList to value of every cell
            
set yRes to getOffsetFromList(targCellNameY, dList) of me
          end tell
          
          
tell row yRes
            tell cell xRes
              set tmpFormat to format
              
set its format to text
              
set aRes to its value
              
set its format to tmpFormat
              
              
if aRes = missing value then
                return ""
              else
                return aRes
              end if
            end tell
          end tell
          
        end tell
      end tell
    end tell
  end getValueOnKeynoteTableByXYLabels
  
  
  
on getOffsetFromList(aTarg, aList)
    using terms from scripting additions
      set aRes to offset of aTarg in aList
    end using terms from
    
return aRes
  end getOffsetFromList
  
  
  
  
—-Offset command overwrapper
  
on offset of bArg in anArg
    set aClass to class of anArg
    
set bClass to class of bArg
    
    
if {aClass, bClass} = {text, text} then –case 1
      return getOffset(anArg, bArg) of me
    else if {aClass, bClass} = {list, list} then –case 2 (The target case)
      return execOffsetList(bArg, anArg) of me
    else if {aClass, bClass} = {text, list} then –case 3 (Illegular case)
      return execOffsetList(bArg, {anArg}) of me
    else if {aClass, bClass} = {list, text} then –case 4 (Illegular case)
      return execOffsetList({bArg}, anArg) of me
    end if
  end offset
  
  
  
–1D List同士のoffset演算を行うルーチンの本体
  
on execOffsetList(aList as list, bList as list)
    set resList to {}
    
repeat with i in aList
      set j to contents of i
      
set aCount to 1
      
      
repeat with ii in bList
        set jj to contents of ii
        
if jj = j then
          set the end of resList to aCount
          
exit repeat
        end if
        
set aCount to aCount + 1
      end repeat
    end repeat
    
    
–見つかったItem No.が連続値かどうかチェック
    
set sRes to chkSequential(resList) of me
    
if sRes = true then
      return contents of first item of resList
    else
      return false
    end if
  end execOffsetList
  
  
  
–与えられた1D Listが連続値かどうかをチェックする
  
on chkSequential(aList)
    if length of aList = 1 then return true
    
if aList = {} then return false
    
    
set aFirst to first item of aList
    
set aList to rest of aList
    
    
repeat with i in aList
      set j to contents of i
      
if j is not equal to (aFirst + 1) then
        return false
      end if
      
copy j to aFirst
    end repeat
    
    
return true
  end chkSequential
  
  
  
–テキスト同士のoffset ofを(2.5x fasterで)実行する
  
on getOffset(str, searchStr)
    set d to divideBy(str, searchStr)
    
if (count d) is less than 2 then return 0
    
return (length of item 1 of d) + 1
  end getOffset
  
  
on divideBy(str, separator)
    set delSave to AppleScript’s text item delimiters
    
set the AppleScript’s text item delimiters to separator
    
set strItems to every text item of str
    
set the AppleScript’s text item delimiters to delSave
    
return strItems
  end divideBy
  
end script

★Click Here to Open This Script 

Posted in list Text | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy Keynote NSArray | Leave a comment

タイトルを指定して該当するKeynoteのスライドにアクセス

Posted on 12月 22, 2018 by Takaaki Naganoya

オープン中のKeynote書類のうち、指定タイトルのスライドを取得するAppleScriptです。

Keynoteには、ページにScript Labelを付ける機能が用意されておらず、一意にスライドを指定する方法がありません。先頭から●ページ目、というアクセスはできますが、それだけのことです。

そこで、各スライドのタイトルを指定して、該当するタイトルを持つスライドを取得するAppleScriptを作成して使用しています。ただし、タイトルについては途中に強制改行が入っていたりするケースもあるので、改行を削除した状態に変換してから指定文字列とのマッチングを行っています。

ただし、表紙のタイトルに長い題名を入力した場合など、ユーザーが意図して入れたものではない改行が途中で入ることもあるため、そのあたりでいろいろゴニョゴニョと改行削除のための悪あがきをしています。

さらに、スライド上の表(table)の指定文字のヘッダーのセルのデータを取り出したり、設定したりするScriptを作成し、最終的にはこれらを配列変数のようにパラメータを指定するだけでストレージ的にアクセスできるようにルーチンを整備しました。

AppleScript名:タイトルを指定して該当するスライドにアクセス.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2018/12/21
—
–  Copyright © 2018 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.5" — El Capitan (10.11) or later
use framework "Foundation"
use scripting additions

set keynoteSlideObj to getSlideFromFrontKeynoteDocumentByTitleString("用途別のフレームワークを知ろう") of me
–> slide 4 of document id "EFC0FE62-C92E-471E-82C7-DE7298AB083C"

if keynoteSlideObj = false then return

tell application "Keynote"
  tell keynoteSlideObj
    properties
  end tell
end tell

–Keynote タイトル指定してslideを取得する
on getSlideFromFrontKeynoteDocumentByTitleString(targString)
  set repTargList to {string id 10, string id 11, string id 13} –LF,CR,VTab一括置換
  
  
tell application "Keynote"
    if (count every document) = 0 then return false
    
    
tell front document
      set tList to object text of default title item of every slide
    end tell
  end tell
  
  
–タイトルごとにゴミ取り(改行文字の削除)
  
set outList to {}
  
set sCount to 1
  
set hitF to false
  
  
repeat with i in tList
    set j1 to contents of i
    
set jTmp to (paragraphs of j1) as string –しつこい改行文字(?)を除去するための処理
    
    
set j2 to replaceTextMultiple(jTmp, repTargList, "") of me as string
    
if j2 is equal to targString then
      set hitF to true
      
exit repeat
    end if
    
    
set sCount to sCount + 1
  end repeat
  
  
if hitF = false then return false
  
  
tell application "Keynote"
    tell front document
      return item sCount of (every slide)
    end tell
  end tell
  
end getSlideFromFrontKeynoteDocumentByTitleString

–リストを指定デリミタで区切ったテキストに変換
on listToStringUsingTextItemDelimiter(sourceList as list, textItemDelimiter as string)
  set anArray to current application’s NSArray’s arrayWithArray:sourceList
  
set aString to anArray’s componentsJoinedByString:textItemDelimiter
  
return (aString as string)
end listToStringUsingTextItemDelimiter

–任意のデータから特定の文字列を複数パターン一括置換
on replaceTextMultiple(origData as string, origTexts as list, repText as string)
  set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to origTexts
  
set origData to text items of origData
  
set AppleScript’s text item delimiters to {repText}
  
set origData to origData as text
  
set AppleScript’s text item delimiters to curDelim
  
return origData
end replaceTextMultiple

★Click Here to Open This Script 

Posted in list Text | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy Keynote | Leave a comment

1D Listのうち指定文字種で構成される要素のみ抽出

Posted on 12月 20, 2018 by Takaaki Naganoya

1D List(配列)に入れた文字要素を文字種類で該当するものだけ抽出するAppleScriptです。

文字種類でデータ抽出する、という用途はけっこう多いので、単体で使えるようにしておきました。プログラムを見ていただくとわかるとおり、

 数字:”9″
 英字:”A”
 半角記号:”$”
 ひらがな:”ひ”
 カタカナ:”カ”
 漢字:”漢”

で文字種類を指定します。

以前のバージョンではありもののルーチンを組み合わせただけなので、全体的に無駄があって処理速度についてはあまり感心できないレベルだったので、若干の高速化を図りました(繰り返し処理部分で無駄な演算を省略)。

ただし、「ひらがな+カタカナは許容する」というふうに、複数の文字種を許可する例が多いので、これではまだ実用レベルには達していないと思います。

AppleScript名:1D Listのうち指定文字種で構成される要素のみ抽出
—
–  Created by: Takaaki Naganoya
–  Created on: 2018/12/20
—
–  Copyright © 2018 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

property NSString : a reference to current application’s NSString
property NSScanner : a reference to current application’s NSScanner
property NSNumber : a reference to current application’s NSNumber
property NSDictionary : a reference to current application’s NSDictionary
property NSCountedSet : a reference to current application’s NSCountedSet
property NSCharacterSet : a reference to current application’s NSCharacterSet
property NSMutableArray : a reference to current application’s NSMutableArray
property NSNumberFormatter : a reference to current application’s NSNumberFormatter
property NSMutableCharacterSet : a reference to current application’s NSMutableCharacterSet
property NSRegularExpressionSearch : a reference to current application’s NSRegularExpressionSearch
property NSNumberFormatterRoundUp : a reference to current application’s NSNumberFormatterRoundUp
property NSStringTransformFullwidthToHalfwidth : a reference to current application’s NSStringTransformFullwidthToHalfwidth

set aList to {"Naganoya", "ながのや", "ナガノヤ", "長野谷"} –Alphabet, Hiragana, Katakana, Kanji

set aRes to filterByCharKind(aList, "A") of me –アルファベットで構成される要素のみ抽出
–> {"Naganoya"}

set bRes to filterByCharKind(aList, "ひ") of me –ひらがなだけで構成される要素のみ抽出
–> {"ながのや"}

set cRes to filterByCharKind(aList, "カ") of me –カタカナだけで構成される要素のみ抽出
–> {"ナガノヤ"}

set dRes to filterByCharKind(aList, "漢") of me –漢字だけで構成される要素のみ抽出
–> {"長野谷"}

–文字種別を判定して指定文字種のみから構成されるものを抽出
on filterByCharKind(aList as list, targCharKind as string)
  set dList to {}
  
repeat with i in aList
    set j to contents of i
    
set tmpPat to retAtrPatternFromStr(j) of me
    
if tmpPat is equal to {targCharKind} then
      set the end of dList to j
    end if
  end repeat
  
  
return dList
end filterByCharKind

–Objective-Cライクなパラメータ記述
on makeUniqueListOf:theList
  set theSet to current application’s NSOrderedSet’s orderedSetWithArray:theList
  
return (theSet’s array()) as list
end makeUniqueListOf:

–Pure AS風のパラメータ記述
on makeUniqueListFrom(theList)
  set aList to my makeUniqueListOf:theList
  
return aList
end makeUniqueListFrom

–1D Listを文字列長でソート v2
on sort1DListByStringLength(aList as list, sortOrder as boolean)
  set aArray to current application’s NSArray’s arrayWithArray:aList
  
set desc1 to current application’s NSSortDescriptor’s sortDescriptorWithKey:"length" ascending:sortOrder
  
set desc2 to current application’s NSSortDescriptor’s sortDescriptorWithKey:"self" ascending:true selector:"localizedCaseInsensitiveCompare:"
  
set bArray to aArray’s sortedArrayUsingDescriptors:{desc1, desc2}
  
return bArray as list of string or string
end sort1DListByStringLength

–文字種別の判定
on retAtrPatternFromStr(aText as string)
  set b1List to {"9", "A", "$", "漢", "ひ", "カ"} –数字、アルファベット、記号、全角漢字、全角ひらがな、全角カタカナ
  
  
–set cStr to zenToHan(aText) of me
  
  
set outList to {}
  
set cList to characters of (aText)
  
  
repeat with i in cList
    set j to contents of i
    
    
set chk1 to ((my chkNumeric:j) as integer) * 1
    
set chk2 to ((my chkAlphabet:j) as integer) * 2
    
set chk3 to ((my chkSymbol:j) as integer) * 3
    
set chk4 to ((my chkKanji:j) as integer) * 4
    
set chk5 to ((my chkHiragana:j) as integer) * 5
    
set chk6 to ((my chkKatakana:j) as integer) * 6
    
    
set itemVal to (chk1 + chk2 + chk3 + chk4 + chk5 + chk6)
    
    
–if itemVal > 0 then
    
set aVal to (contents of item itemVal of b1List)
    
    
if aVal is not in outList then
      set the end of outList to aVal
    end if
    
–end if
  end repeat
  
  
return outList
end retAtrPatternFromStr

–全角→半角変換
on zenToHan(aStr)
  set aString to NSString’s stringWithString:aStr
  
return (aString’s stringByApplyingTransform:(NSStringTransformFullwidthToHalfwidth) |reverse|:false) as string
end zenToHan

–数字か
on chkNumeric:checkString
  set digitCharSet to NSCharacterSet’s characterSetWithCharactersInString:"0123456789"
  
set ret to my chkCompareString:checkString baseString:digitCharSet
  
return ret as boolean
end chkNumeric:

–記号か
on chkSymbol:checkString
  set muCharSet to NSCharacterSet’s alloc()’s init()
  
muCharSet’s addCharactersInString:"$\"!~&=#[]._-+`|{}?%^*/’@-/:;(),"
  
set ret to my chkCompareString:checkString baseString:muCharSet
  
return ret as boolean
end chkSymbol:

–漢字か
on chkKanji:aChar
  return detectCharKind(aChar, "[一-龠]") of me
end chkKanji:

–ひらがなか
on chkHiragana:aChar
  return detectCharKind(aChar, "[ぁ-ん]") of me
end chkHiragana:

–カタカナか
on chkKatakana:aChar
  return detectCharKind(aChar, "[ァ-ヶ]") of me
end chkKatakana:

–半角スペースか
on chkSpace:checkString
  set muCharSet to NSCharacterSet’s alloc()’s init()
  
muCharSet’s addCharactersInString:" " –半角スペース(20h)
  
set ret to my chkCompareString:checkString baseString:muCharSet
  
return ret as boolean
end chkSpace:

— アルファベットか
on chkAlphabet:checkString
  set aStr to NSString’s stringWithString:checkString
  
set allCharSet to NSMutableCharacterSet’s alloc()’s init()
  
allCharSet’s addCharactersInRange:({location:97, |length|:26}) –97 = id of "a"
  
allCharSet’s addCharactersInRange:({location:65, |length|:26}) –65 = id of "A"
  
set aBool to my chkCompareString:aStr baseString:allCharSet
  
return aBool as boolean
end chkAlphabet:

on chkCompareString:checkString baseString:baseString
  set aScanner to NSScanner’s localizedScannerWithString:checkString
  
aScanner’s setCharactersToBeSkipped:(missing value)
  
aScanner’s scanCharactersFromSet:baseString intoString:(missing value)
  
return (aScanner’s isAtEnd()) as boolean
end chkCompareString:baseString:

on detectCharKind(aChar, aPattern)
  set aChar to NSString’s stringWithString:aChar
  
set searchStr to NSString’s stringWithString:aPattern
  
set matchRes to aChar’s rangeOfString:searchStr options:(NSRegularExpressionSearch)
  
if matchRes’s location() = (current application’s NSNotFound) or (matchRes’s location() as number) > 9.99999999E+8 then
    return false
  else
    return true
  end if
end detectCharKind

★Click Here to Open This Script 

Posted in list regexp Text | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy NSCharacterSet NSCountedSet NSDictionary NSMutableArray NSMutableCharacterSet NSNumber NSNumberFormatter NSNumberFormatterRoundUp NSRegularExpressionSearch NSScanner NSString NSStringTransformFullwidthToHalfwidth | Leave a comment

住所録から苗字を抽出して1文字以上の苗字をリスト出力

Posted on 12月 20, 2018 by Takaaki Naganoya

固有名詞を抽出するために、住所録から苗字を抽出して1文字以上の長さの苗字をリスト出力するAppleScriptです。

簡易形態素解析を行うさいに、みのまわりの人物の苗字を認識してくれないと知性を感じられないため(例:”長野”,”谷”)、逆に住所録に登録があるぐらい身の回りの人物の苗字を固有名詞として認識してくれるよう、住所録から苗字を抽出させてみました。

抽出した苗字は、missing valueが返ってきたものを除去し、重複を排除し、文字列長でソートして長いものから短いものへと並べ替え。

さらに、文字種別を判定して漢字のみで構成されているものを抽出。さらに、1文字の苗字を排除。

こうして得られたリストの先頭に自分の苗字を入れて、真っ先に自分の名前が認識されるようにしてみました。

住所録へのアクセスは、macOS標準装備の「連絡先.app」にアクセスしてみました。最近はmacOS標準装備のFrameworkにアクセスしてこの手のデータを取得していたりしましたが、その際に利用していたAddressBook.frameworkが廃止になる見込みであるため、新設されたContacts.frameworkを使ったほうが好ましいところです。

ただ、Contacts.frameworkの各種メソッドはObjective-CのBlocks構文の記述を必要とするため、AppleScriptからそのまま呼び出すことができません。

そのため、連絡先.app(Contacts.app)にアクセスすることになった次第です。

固有名詞抽出については、簡易形態素解析を実行するたびに実行するのではなく、1日に1回ぐらいの頻度で実行すればよいと考えています。

AppleScript名:住所録から苗字を抽出して1文字以上の苗字をリスト出力
—
–  Created by: Takaaki Naganoya
–  Created on: 2018/12/20
—
–  Copyright © 2018 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use bPlus : script "BridgePlus"

property NSString : a reference to current application’s NSString
property NSScanner : a reference to current application’s NSScanner
property NSNumber : a reference to current application’s NSNumber
property NSDictionary : a reference to current application’s NSDictionary
property NSCountedSet : a reference to current application’s NSCountedSet
property NSCharacterSet : a reference to current application’s NSCharacterSet
property NSMutableArray : a reference to current application’s NSMutableArray
property NSNumberFormatter : a reference to current application’s NSNumberFormatter
property NSMutableCharacterSet : a reference to current application’s NSMutableCharacterSet
property NSRegularExpressionSearch : a reference to current application’s NSRegularExpressionSearch
property NSNumberFormatterRoundUp : a reference to current application’s NSNumberFormatterRoundUp
property NSStringTransformFullwidthToHalfwidth : a reference to current application’s NSStringTransformFullwidthToHalfwidth

tell application "Contacts"
  set lastNames to last name of every person
  
set myName to last name of my card
end tell

load framework

–Remove missing value (Cleaning)
set aList to (current application’s SMSForder’s arrayByDeletingBlanksIn:(lastNames)) as list

–重複部分の削除
set bList to makeUniqueListFrom(aList) of me

–文字列長でソート。長い文字列→短い文字列
set cList to sort1DListByStringLength(bList, false) of me –降順

–文字種別を判定して漢字のみから構成されるものを抽出し、1文字のものを除外
set dList to {}
repeat with i in cList
  set j to contents of i
  
set tmpPat to retAtrPatternFromStr(j) of me
  
if tmpPat is equal to "漢" then
    –1文字以上の苗字のみ出力
    
if length of j > 1 then
      set the end of dList to j
    end if
  end if
end repeat

set the beginning of dList to myName
return dList
–> {"長野谷", "久保田", "三津田", "小笠原", "上田平", "大久保", "長谷川", "長野谷", "伊賀", "伊勢","伊東", "伊藤", "井上", "稲葉" …}

–Objective-Cライクなパラメータ記述
on makeUniqueListOf:theList
  set theSet to current application’s NSOrderedSet’s orderedSetWithArray:theList
  
return (theSet’s array()) as list
end makeUniqueListOf:

–Pure AS風のパラメータ記述
on makeUniqueListFrom(theList)
  set aList to my makeUniqueListOf:theList
  
return aList
end makeUniqueListFrom

–1D Listを文字列長でソート v2
on sort1DListByStringLength(aList as list, sortOrder as boolean)
  set aArray to current application’s NSArray’s arrayWithArray:aList
  
set desc1 to current application’s NSSortDescriptor’s sortDescriptorWithKey:"length" ascending:sortOrder
  
set desc2 to current application’s NSSortDescriptor’s sortDescriptorWithKey:"self" ascending:true selector:"localizedCaseInsensitiveCompare:"
  
set bArray to aArray’s sortedArrayUsingDescriptors:{desc1, desc2}
  
return bArray as list of string or string
end sort1DListByStringLength

–文字種別の判定
on retAtrPatternFromStr(aText)
  set a1List to {"100000", "010000", "001000", "000100", "000010", "000001"}
  
set b1List to {"9", "A", "$", "漢", "あ", "ア"} –数字、アルファベット、記号、全角漢字、全角ひらがな、全角カタカナ
  
set aDict to NSDictionary’s dictionaryWithObjects:b1List forKeys:a1List
  
  
set aStr to NSString’s stringWithString:aText
  
set bStr to aStr’s stringByDeletingPathExtension()
  
set cStr to zenToHan(bStr) of me
  
  
set outList to {}
  
set cList to characters of cStr
  
  
repeat with i in cList
    set j to contents of i
    
set chk1 to ((my chkNumeric:j) as integer) as string
    
set chk2 to ((my chkAlphabet:j) as integer) as string
    
set chk3 to ((my chkSymbol:j) as integer) as string
    
set chk4 to ((my chkKanji:j) as integer) as string
    
set chk5 to ((my chkHiragana:j) as integer) as string
    
set chk6 to ((my chkKatakana:j) as integer) as string
    
    
set allKey to (chk1 & chk2 & chk3 & chk4 & chk5 & chk6) as string
    
set aVal to (aDict’s valueForKeyPath:allKey) as string
    
    
if aVal is not in outList then
      set the end of outList to aVal
    end if
  end repeat
  
  
return outList as string
end retAtrPatternFromStr

–全角→半角変換
on zenToHan(aStr)
  set aString to NSString’s stringWithString:aStr
  
return (aString’s stringByApplyingTransform:(NSStringTransformFullwidthToHalfwidth) |reverse|:false) as string
end zenToHan

–数字か
on chkNumeric:checkString
  set digitCharSet to NSCharacterSet’s characterSetWithCharactersInString:"0123456789"
  
set ret to my chkCompareString:checkString baseString:digitCharSet
  
return ret as boolean
end chkNumeric:

–記号か
on chkSymbol:checkString
  set muCharSet to NSCharacterSet’s alloc()’s init()
  
muCharSet’s addCharactersInString:"$\"!~&=#[]._-+`|{}?%^*/’@-/:;(),"
  
set ret to my chkCompareString:checkString baseString:muCharSet
  
return ret as boolean
end chkSymbol:

–漢字か
on chkKanji:aChar
  return detectCharKind(aChar, "[一-龠]") of me
end chkKanji:

–ひらがなか
on chkHiragana:aChar
  return detectCharKind(aChar, "[ぁ-ん]") of me
end chkHiragana:

–カタカナか
on chkKatakana:aChar
  return detectCharKind(aChar, "[ァ-ヶ]") of me
end chkKatakana:

–半角スペースか
on chkSpace:checkString
  set muCharSet to NSCharacterSet’s alloc()’s init()
  
muCharSet’s addCharactersInString:" " –半角スペース(20h)
  
set ret to my chkCompareString:checkString baseString:muCharSet
  
return ret as boolean
end chkSpace:

— アルファベットか
on chkAlphabet:checkString
  set aStr to NSString’s stringWithString:checkString
  
set allCharSet to NSMutableCharacterSet’s alloc()’s init()
  
allCharSet’s addCharactersInRange:(current application’s NSMakeRange(id of "a", 26))
  
allCharSet’s addCharactersInRange:(current application’s NSMakeRange(id of "A", 26))
  
set aBool to my chkCompareString:aStr baseString:allCharSet
  
return aBool as boolean
end chkAlphabet:

on chkCompareString:checkString baseString:baseString
  set aScanner to NSScanner’s localizedScannerWithString:checkString
  
aScanner’s setCharactersToBeSkipped:(missing value)
  
aScanner’s scanCharactersFromSet:baseString intoString:(missing value)
  
return (aScanner’s isAtEnd()) as boolean
end chkCompareString:baseString:

on detectCharKind(aChar, aPattern)
  set aChar to NSString’s stringWithString:aChar
  
set searchStr to NSString’s stringWithString:aPattern
  
set matchRes to aChar’s rangeOfString:searchStr options:(NSRegularExpressionSearch)
  
if matchRes’s location() = (current application’s NSNotFound) or (matchRes’s location() as number) > 9.99999999E+8 then
    return false
  else
    return true
  end if
end detectCharKind

★Click Here to Open This Script 

Posted in list Natural Language Processing Record Sort | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy Contacts | Leave a comment

easyJParse v4

Posted on 12月 14, 2018 by Takaaki Naganoya

簡易的な日本語テキストのParse(辞書なし)を行うAppleScriptです。

詳細な説明はこちら。

本バージョンでは、かっこ( “「”, “」”, “『”, “』”, “【”, “】”, “《”, “》”, “〈”, “〉”, “(”, “))で区切られた文字列を区分けしないで1かたまりで出力させたものです。

コマンド解釈用に作成した本Script、パラメーターとして区分けしてほしくない情報(フィールド情報やデータベース名など)をかたまりのまま出力する必要があって、そのように処理させてみました。

かっこがクロスしたりネスティング(入れ子)していることは検出していますが、そのまま連結せずに出力しています。

このプログラムを作ったことにより、固有名詞への対応のメドが立ちました。

前処理で何かの記号で固有名詞を囲えばいいんじゃないか、などと思っています。何を固有名詞とするか、ということになりますが、とりあえず住所録(Contacts.app)から人名(Last Name)や会社名をすべて出力させるのがよいだろうか、といったところです。

AppleScript名:easyJParse v4(かぎかっこ内の単語を1つの単語としてみなす)
— Created 2018-09-26 by Takaaki Naganoya
— Modified 2018-12-14 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.5" — El Capitan (10.11) or later
use framework "Foundation"
use scripting additions
use bPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

property NSArray : a reference to current application’s NSArray
property NSSortDescriptor : a reference to current application’s NSSortDescriptor

load framework
set aTargName to "曲のアーティスト名を変更"
–set aTargName to "<満喜子>さんの実家から半径300メートル以内にあるコンビニを取得"
–set aTargName to "Finderで選択中のAI書類上の「製品名」レイヤーから抜き出したコードをもとにスペック情報をGoogle Spreadsheet「製品コード表」から展開して保存。"
set aList to parseJ(aTargName, true) of me
–> {"Finder", "で", "選択", "中", "の", "AI", "書類", "上", "の", "「", "製品名", "」", "レイヤー", "から", "抜き出し", "た", "コード", "を", "もと", "に", "スペック", "情報", "を", "Google", " ", "Spreadsheet", "「", "製品コード表", "」", "から", "展開", "し", "て", "保存", "。"}
return aList

set aTargName to "私の名前は「長野谷」です。"
set aList to parseJ(aTargName, true) of me
–> {"私", "の", "名前", "は", "「", "長野谷", "」", "です", "。"}

–カッコのネスティングとクロス(エラー)については、処理せずにそのまま出力
on parseJ(aTargStr as string, pickupPhraseByBracketPair as boolean)
  copy aTargStr to tStr
  
  
set cList to characters of tStr
  
set wList to words of tStr
  
  
set cLen to length of cList
  
  
set w2List to {}
  
set w3List to {}
  
set aCount to 0
  
  
set lastPos to 0
  
  
repeat with i in wList
    set j to contents of i
    
    
using terms from scripting additions
      set anOffset to offset of j in tStr
    end using terms from
    
    
if anOffset is not equal to 1 then
      set aChar to character (lastPos + 1) of aTargStr
      
      
set the end of w3List to {wordList:aChar, characterList:{aChar}, startPos:(lastPos + 1), endPos:(lastPos + 1)}
    end if
    
    
set aLen to length of j
    
    
set w2List to w2List & (characters of j)
    
set startPointer to (anOffset + aCount)
    
set endPointer to (anOffset + aCount + aLen – 1)
    
    
set the end of w3List to {wordList:j, characterList:(characters of j), startPos:startPointer, endPos:endPointer}
    
    
set trimStart to (anOffset + aLen)
    
    
if trimStart > (length of tStr) then
      set trimStart to 1
    end if
    
    
set tStr to text trimStart thru -1 of tStr
    
    
set aCount to aCount + anOffset + aLen – 1
    
copy endPointer to lastPos
  end repeat
  
  
–句読点など。文末の処理
  
if endPointer is not equal to cLen then
    set the end of w3List to {wordList:tStr, characterList:(characters of tStr), startPos:(lastPos + aCount), endPos:aLen}
  end if
  
  
set bArray to sortRecListByLabel((w3List), "startPos", true) of me
  
set cArray to (bArray’s valueForKeyPath:"wordList") as list
  
  
–カッコでくくった範囲を1つの塊として連結する
  
set bracketList to {"「", "」", "『", "』", "【", "】", "《", "》", "〈", "〉", "(", ")"}
  
set bList to jointItemsBetweenBrackets(cArray, bracketList) of me
  
  
return bList
end parseJ

–リストに入れたレコードを、指定の属性ラベルの値でソート
on sortRecListByLabel(aRecList as list, aLabelStr as string, ascendF as boolean)
  set aArray to NSArray’s arrayWithArray:aRecList
  
set sortDesc to NSSortDescriptor’s alloc()’s initWithKey:aLabelStr ascending:ascendF
  
set sortDescArray to NSArray’s arrayWithObject:sortDesc
  
set sortedArray to aArray’s sortedArrayUsingDescriptors:sortDescArray
  
return sortedArray
end sortRecListByLabel

on offset of bArg in anArg
  set aClass to class of anArg
  
set bClass to class of bArg
  
  
if {aClass, bClass} = {text, text} then –case 1
    return getOffset(anArg, bArg) of me
  else if {aClass, bClass} = {list, list} then –case 2 (The target case)
    return execOffsetList(bArg, anArg) of me
  else if {aClass, bClass} = {text, list} then –case 3 (Illegular case)
    return execOffsetList(bArg, {anArg}) of me
  else if {aClass, bClass} = {list, text} then –case 4 (Illegular case)
    return execOffsetList({bArg}, anArg) of me
  end if
end offset

–1D List同士のoffset演算を行うルーチンの本体
on execOffsetList(aList as list, bList as list)
  set resList to {}
  
repeat with i in aList
    set j to contents of i
    
set aCount to 1
    
    
repeat with ii in bList
      set jj to contents of ii
      
if jj = j then
        set the end of resList to aCount
        
exit repeat
      end if
      
set aCount to aCount + 1
    end repeat
  end repeat
  
  
–見つかったItem No.が連続値かどうかチェック
  
set sRes to chkSequential(resList) of me
  
if sRes = true then
    return contents of first item of resList
  else
    return false
  end if
end execOffsetList

–与えられた1D Listが連続値かどうかをチェックする
on chkSequential(aList)
  if length of aList = 1 then return true
  
if aList = {} then return false
  
  
set aFirst to first item of aList
  
set aList to rest of aList
  
  
repeat with i in aList
    set j to contents of i
    
if j is not equal to (aFirst + 1) then
      return false
    end if
    
copy j to aFirst
  end repeat
  
  
return true
end chkSequential

–テキスト同士のoffset ofを(2.5x fasterで)実行する
on getOffset(str, searchStr)
  set d to divideBy(str, searchStr)
  
if (count d) is less than 2 then return 0
  
return (length of item 1 of d) + 1
end getOffset

on divideBy(str, separator)
  set delSave to AppleScript’s text item delimiters
  
set the AppleScript’s text item delimiters to separator
  
set strItems to every text item of str
  
set the AppleScript’s text item delimiters to delSave
  
return strItems
end divideBy

–カッコでくくった範囲を1つの塊として連結する
on jointItemsBetweenBrackets(aList as list, bracketList as list)
  load framework
  
  
–リスト内のブラケット位置の検出
  
set aRes to (current application’s SMSForder’s indexesOfItems:bracketList inArray:aList inverting:false) as list
  
–> {9, 12, 15, 18, 22, 25, 27, 29}–0 based
  
  
if aRes = {} then return aList
  
  
–位置情報リストを開始位置, 終了位置のペアの2D Listに変換する
  
set cList to (current application’s SMSForder’s subarraysFrom:(aRes) groupedBy:2 |error|:(missing value)) as list
  
–> {{9, 12}, {15, 18}, {22, 25}, {27, 29}}–0 based
  
  
–カッコの位置がクロスしていないかチェック(入れ子状態はエラーになる)
  
set dRes to checkCrossRange(cList) of me
  
if dRes = false then return aList
  
  
set ccList to reverse of cList –順次、ブラケットに囲まれた要素を連結していくので、アイテム数が随時変化する。アイテム番号が狂わないよう後方から処理する必要がある。そのために、リストの要素を逆順に組み替える
  
–> {{27, 29}, {22, 25}, {15, 18}, {9, 12}}–0 based
  
  
—
  
copy aList to aaList
  
  
repeat with i in ccList
    copy i to {s2Dat, e2Dat}
    
    
set s2Dat to s2Dat + 1 –Array index conversion from 0 to 1 based
    
set e2Dat to e2Dat + 1 –Array index conversion from 0 to 1 based
    
    
set tmp1 to items 1 thru s2Dat of aaList
    
set tmp2 to (items (s2Dat + 1) thru (e2Dat – 1) of aaList) as string
    
set tmp3 to items e2Dat thru -1 of aaList
    
    
set aaList to tmp1 & tmp2 & tmp3
  end repeat
  
  
return aaList
end jointItemsBetweenBrackets

–{始点, 終点}のペアの2D Listが違いにクロスしていないかチェック
on checkCrossRange(aList as list)
  set rList to {}
  
repeat with i in aList
    copy i to {sRange, eRange}
    
set tmpRange to current application’s NSMakeRange(sRange, eRange – sRange + 1)
    
set the end of rList to tmpRange
  end repeat
  
  
repeat with ii in rList
    set jj to contents of ii
    
repeat with i in rList
      set j to contents of i
      
      
if jj is not equal to j then
        set aRes to current application’s NSIntersectionRange(jj, j)
        
        
if aRes is not equal to {location:0, |length|:0} then
          return false
        end if
      end if
      
    end repeat
  end repeat
  
  
return true
end checkCrossRange

★Click Here to Open This Script 

Posted in list Natural Language Processing Text | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy 10.15savvy 11.0savvy | 1 Comment

{始点, 終点}の2D Listがお互いにクロスしていないかチェック

Posted on 12月 14, 2018 by Takaaki Naganoya

{始点, 終点}のペアからなる2D Listがお互いにクロスしていないかチェックするAppleScriptです。

{{9, 12}, {15, 18}, {17, 25}, {27, 29}}

のような場合には、NG(false)。

 {{9, 12}, {15, 18}, {19, 25}, {27, 29}}

のような場合には、OK(true)と判定します。

{{9, 12}, {15, 18}, {18, 25}, {27, 29}}

のように、接している場合にもNG(false)と判定します。

もともとの用途は、

あいうえお「かきく『けこ」さしす』せそ

のように、本来記述してはいけないカッコの記法が行われたことを検出するものです。

ただし、文法的には本来許容すべきカッコのネスティング

あいうえお「かきく『けこ』さしす」せそ

についてもエラー検出してしまっているので、その点は一考の余地がありそうです。

AppleScript名:{始点, 終点}の2D Listがお互いにクロスしていないかチェック.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2018/12/14
—
–  Copyright © 2018 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set aList to {{9, 12}, {15, 18}, {17, 25}, {27, 29}}
set aRes to checkCrossRange(aList) of me
–> false

set bList to {{9, 12}, {15, 18}, {18, 25}, {27, 29}}
set bRes to checkCrossRange(bList) of me
–> false

set cList to {{9, 12}, {15, 18}, {19, 25}, {27, 29}}
set cRes to checkCrossRange(cList) of me
–> true

–{始点, 終点}のペアの2D Listが違いにクロスしていないかチェック
on checkCrossRange(aList as list)
  set rList to {}
  
repeat with i in aList
    copy i to {sRange, eRange}
    
set tmpRange to current application’s NSMakeRange(sRange, eRange – sRange + 1)
    
set the end of rList to tmpRange
  end repeat
  
  
repeat with ii in rList
    set jj to contents of ii
    
repeat with i in rList
      set j to contents of i
      
      
if jj is not equal to j then
        set aRes to current application’s NSIntersectionRange(jj, j)
        
        
if aRes is not equal to {location:0, |length|:0} then
          return false
        end if
      end if
      
    end repeat
  end repeat
  
  
return true
end checkCrossRange

★Click Here to Open This Script 

Posted in list | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy | Leave a comment

offset of list in list v3

Posted on 12月 14, 2018 by Takaaki Naganoya

1D List(Array)中における指定項目の出現位置(offset)を求めるAppleScriptです。標準命令「offset of ① in ②」を拡張して、本来はテキスト同士の処理であったものを、リスト同士で処理するようにしています。

サポートしているのは4つのパターンです。

(1)offset of string1 in string2

標準パターンですが、例によって標準命令よりも2.5倍速に高速化してあります。

(2)offset of list1 in list2

想定ターゲットのパターンです。1D Listと1D Listのoffsetを計算します。

(3)offset of list1 in string2

(2)を指定しようとして間違ったケースです。

(4)offset of string1 in list2

ASOC(use framework “Foundation”宣言時)では、そのままではoffset命令がだましにくくなるので(パラメータが文字列ではないとしてエラーになる)、using terms from scripting additionsで囲う必要がありました。

パラメータにヌルリストを指定した場合に、エラーになる件を修正(chkSequential)してあります。

AppleScript名:offset of list in list v3
— Created 2018-09-18 by Takaaki Naganoya
— Modified 2018-12-14 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

–case 1
using terms from scripting additions –ここ、AppleScriptObjC(use framework "Foundation"宣言時)では必要になる
  set bRes to offset of "a" in "bcdefa"
end using terms from
–> 6

–case 2 (The target case)
set aTargList to {"Finder", "で", "選択", "中", "の", "AI", "書類", "上", "の", "「", "製品", "名", "」", "レイヤー", "から", "抜き出し", "た", "コード", "を", "もと", "に", "スペック", "情報", "を", "Google", " ", "Spreadsheet", "から", "展開", "し", "て", "保存", "。"}
set bList to {"の", "メニュー", "で"}
using terms from scripting additions
  set aRes to offset of bList in aTargList
end using terms from
–> 2

–case 3 (Illegular case)
set aTargList to {"Finder", "で", "選択", "中", "の", "AI", "書類", "上", "の", "「", "製品", "名", "」", "レイヤー", "から", "抜き出し", "た", "コード", "を", "もと", "に", "スペック", "情報", "を", "Google", " ", "Spreadsheet", "から", "展開", "し", "て", "保存", "。"}
set bList to "で"
using terms from scripting additions
  set aRes to offset of bList in aTargList
end using terms from
–> 4

–case 4 (Illegular case)
set aTargList to "で"
set bList to {"で"}
using terms from scripting additions
  set aRes to offset of bList in aTargList
end using terms from
—> 1

–case 3a (Illegular case)
set aTargList to {}
set bList to "で"
using terms from scripting additions
  set aRes to offset of bList in aTargList
end using terms from
–> false

–case 2a (The target case)
set aTargList to {"Finder", "で", "選択", "中", "の", "AI", "書類", "上", "の", "「", "製品", "名", "」", "レイヤー", "から", "抜き出し", "た", "コード", "を", "もと", "に", "スペック", "情報", "を", "Google", " ", "Spreadsheet", "から", "展開", "し", "て", "保存", "。"}
set bList to {}
using terms from scripting additions
  set aRes to offset of bList in aTargList
end using terms from
–> false

on offset of bArg in anArg
  set aClass to class of anArg
  
set bClass to class of bArg
  
  
if {aClass, bClass} = {text, text} then –case 1
    return getOffset(anArg, bArg) of me
  else if {aClass, bClass} = {list, list} then –case 2 (The target case)
    return execOffsetList(bArg, anArg) of me
  else if {aClass, bClass} = {text, list} then –case 3 (Illegular case)
    return execOffsetList(bArg, {anArg}) of me
  else if {aClass, bClass} = {list, text} then –case 4 (Illegular case)
    return execOffsetList({bArg}, anArg) of me
  end if
end offset

–1D List同士のoffset演算を行うルーチンの本体
on execOffsetList(aList as list, bList as list)
  set resList to {}
  
repeat with i in aList
    set j to contents of i
    
set aCount to 1
    
    
repeat with ii in bList
      set jj to contents of ii
      
if jj = j then
        set the end of resList to aCount
        
exit repeat
      end if
      
set aCount to aCount + 1
    end repeat
  end repeat
  
  
–見つかったItem No.が連続値かどうかチェック
  
set sRes to chkSequential(resList) of me
  
if sRes = true then
    return contents of first item of resList
  else
    return false
  end if
end execOffsetList

–与えられた1D Listが連続値かどうかをチェックする
on chkSequential(aList)
  if length of aList = 1 then return true
  
if aList = {} then return false
  
  
set aFirst to first item of aList
  
set aList to rest of aList
  
  
repeat with i in aList
    set j to contents of i
    
if j is not equal to (aFirst + 1) then
      return false
    end if
    
copy j to aFirst
  end repeat
  
  
return true
end chkSequential

–テキスト同士のoffset ofを(2.5x fasterで)実行する
on getOffset(str, searchStr)
  set d to divideBy(str, searchStr)
  
if (count d) is less than 2 then return 0
  
return (length of item 1 of d) + 1
end getOffset

on divideBy(str, separator)
  set delSave to AppleScript’s text item delimiters
  
set the AppleScript’s text item delimiters to separator
  
set strItems to every text item of str
  
set the AppleScript’s text item delimiters to delSave
  
return strItems
end divideBy

★Click Here to Open This Script 

Posted in list Text | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy | Leave a comment

1Dリストの内容が連続値かどうかチェック v2

Posted on 12月 14, 2018 by Takaaki Naganoya

1D List(Array)の内容が数値の連続値かどうかチェックするAppleScriptです。

地味ですが、超一級に重要な部品です。このルーチンが存在することで、1D List同士の要素の存在確認を手軽に行えています。

いろいろ便利に使っていたのですが、引数のリストが要素数=0のヌルリスト({})を渡した場合にエラーになることがわかったので、そのエラー対処を追加しています。

AppleScript名:1Dリストの内容が連続値かどうかチェック v2
set aList to {2, 3, 4}
set aRes to chkSequential(aList) of me
–> true

set aList to {}
set aRes to chkSequential(aList) of me
–> false

–与えられた1D Listが連続値かどうかをチェックする
on chkSequential(aList as list)
  if length of aList = 1 then return true
  
if aList = {} then return false
  
  
set aFirst to first item of aList
  
set aList to rest of aList
  
  
repeat with i in aList
    set j to contents of i
    
if j is not equal to (aFirst + 1) then
      return false
    end if
    
copy j to aFirst
  end repeat
  
  
return true
end chkSequential

★Click Here to Open This Script 

Posted in list | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy | Leave a comment

Keynoteでオープン中の最前面の現在のページのテキストアイテムを取得してテキスト化

Posted on 12月 6, 2018 by Takaaki Naganoya

Keynoteでオープン中の最前面の書類の、現在表示中のスライド(ページ)上に存在する文字情報を取得して、macOS標準装備のテキストエディタ「テキストエディット」の新規書類上に取得した文字情報をすべて転送するAppleScriptです。

Keynote書類上に配置できるオブジェクトには、

このようなものがあります。

これらのうち文字情報が直接入力可能なtext itemおよびshapeを包括したiWork itemというオブジェクト、およびtableオブジェクトから文字情報を取得し、いろいろごみ取り(改行文字削除)を行なったりしたものをmacOS標準装備のテキストエディタに出力するものです。

Keynoteで作業中に編集中の書類内から文字情報を再利用したい場合のために作成したものです。


▲このようなKeynoteのスライド(ページ)上の文字情報を


▲一括で取得してテキストエディタの新規書類上に転送

macOS標準装備のスクリプトメニューに入れて呼び出しています。

AppleScript名:Keynoteでオープン中の最前面の現在のページのテキストアイテムを取得してテキスト化
— Created 2018-11-28 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set repTargList to {string id 10, string id 11, string id 13} –LF,CR,VTab一括置換

set t1List to {}
set t2List to {}

tell application "Keynote"
  if (count every document) = 0 then return
  
  
tell front document
    tell current slide
      if (count every iWork item) > 0 then
        set t1List to object text of every iWork item –text item, shapeなどを包括したオブジェクト
      end if
      
      
if (count every table) > 0 then
        set t2List to value of every cell of every table
      end if
      
    end tell
  end tell
end tell

set tList to t1List & t2List
set tList to FlattenList(tList) of me –force lists to 1D list

–タイトルごとにゴミ取り(改行文字の削除)
set outList to {}
repeat with i in tList
  set j1 to contents of i
  
  
if (j1 is not equal to missing value) and (j1 is not equal to "") then
    set jTmp to (paragraphs of j1) as string –しつこい改行文字(?)を除去するための処理
    
    
set j2 to replaceTextMultiple(jTmp, repTargList, "") of me as string
    
if j2 is not equal to "" then
      set the end of outList to j2
    end if
  end if
end repeat

–リストを改行で区切ったテキストに変換
set aStr to listToStringUsingTextItemDelimiter(outList, return) of me

–得られたテキストをTextEditの新規書類上に出力
tell application "TextEdit"
  activate
  
make new document
  
set text of front document to aStr
end tell

–リストを指定デリミタで区切ったテキストに変換
on listToStringUsingTextItemDelimiter(sourceList as list, textItemDelimiter as string)
  set anArray to current application’s NSArray’s arrayWithArray:sourceList
  
set aString to anArray’s componentsJoinedByString:textItemDelimiter
  
return (aString as string)
end listToStringUsingTextItemDelimiter

–任意のデータから特定の文字列を複数パターン一括置換
on replaceTextMultiple(origData as string, origTexts as list, repText as string)
  set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to origTexts
  
set origData to text items of origData
  
set AppleScript’s text item delimiters to {repText}
  
set origData to origData as text
  
set AppleScript’s text item delimiters to curDelim
  
return origData
end replaceTextMultiple

–多次元配列の強制1次元配列化 By Paul Berkowitz
on FlattenList(aList as list)
  set oldDelims to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to {"????"}
  
set aString to aList as text
  
set aList to text items of aString
  
set AppleScript’s text item delimiters to oldDelims
  
return aList
end FlattenList

★Click Here to Open This Script 

Posted in list Text | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy Keynote | Leave a comment

Keynoteでオープン中の最前面の書類のすべてのページのタイトルを取得してテキスト化 v2

Posted on 12月 6, 2018 by Takaaki Naganoya

オープン中の最前面のKeynoteの書類の各スライド(ページ)のタイトルを取得して、改行文字を削除し、テキストエディット上の新規書類にタイトル一覧文字を入れるAppleScriptです。

Keynote書類は、きちんと各スライドのマスタースライドでタイトル入りのものを使用し、各スライドでタイトル用のテキストアイテムにタイトルを入れてあれば、AppleScriptからタイトルを取得できます。

もしも、スライド(ページ)上にタイトルが存在しない場合には、座標がどこどこ以上で文字サイズがXXXポイント以上のテキストアイテムのうち、もっとも上の方に存在しているものをタイトルとみなして取得する、といった処理も可能なので、そういう対策を行なってもよいでしょう。

ここでは、単にタイトル内容の再利用や内容確認などのためOS標準装備のテキストエディタに出力していますが、Keynote書類上に目次を作成するといった処理も普通に行なっています(仕様書の目次をつける場合など)。

Keynote書類に対する処理は、割と自分的に業務の効率化に寄与しています。毎月作成する説明用資料を、さまざまな書類のデータから数値を集めてKeynote書類を自動作成するといったAppleScriptも実際に存在しています。


▲このようなKeynote書類を……


▲本Scriptで処理するとテキストエディット上にタイトル一覧が展開される

AppleScript名:Keynoteでオープン中の最前面の書類のすべてのページのタイトルを取得してテキスト化 v2
— Created 2018-11-28 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set repTargList to {string id 10, string id 11, string id 13} –LF,CR,VTab一括置換

tell application "Keynote"
  if (count every document) = 0 then return
  
  
tell front document
    set tList to object text of default title item of every slide
  end tell
end tell

–タイトルごとにゴミ取り(改行文字の削除)
set outList to {}
repeat with i in tList
  set j1 to contents of i
  
set jTmp to (paragraphs of j1) as string –しつこい改行文字(?)を除去するための処理
  
  
set j2 to replaceTextMultiple(jTmp, repTargList, "") of me as string
  
if j2 is not equal to "" then
    set the end of outList to j2
  end if
end repeat

–リストを改行で区切ったテキストに変換
set aStr to listToStringUsingTextItemDelimiter(outList, return) of me

–得られたテキストをTextEditの新規書類上に出力
tell application "TextEdit"
  activate
  
make new document
  
set text of front document to aStr
end tell

–リストを指定デリミタで区切ったテキストに変換
on listToStringUsingTextItemDelimiter(sourceList as list, textItemDelimiter as string)
  set anArray to current application’s NSArray’s arrayWithArray:sourceList
  
set aString to anArray’s componentsJoinedByString:textItemDelimiter
  
return (aString as string)
end listToStringUsingTextItemDelimiter

–任意のデータから特定の文字列を複数パターン一括置換
on replaceTextMultiple(origData as string, origTexts as list, repText as string)
  set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to origTexts
  
set origData to text items of origData
  
set AppleScript’s text item delimiters to {repText}
  
set origData to origData as text
  
set AppleScript’s text item delimiters to curDelim
  
return origData
end replaceTextMultiple

★Click Here to Open This Script 

Posted in list Text | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy Keynote | Leave a comment

Numbersで選択中のデータを2D Listで取得し、ユニーク化

Posted on 12月 3, 2018 by Takaaki Naganoya

Numbersの最前面の書類の選択中のシートの選択中のセルの値を2D List(Array)で取り出して、ユニーク化するAppleScriptです。

上記のような状態で本AppleScriptを実行すると、

{{"iMac4,1", "Yonah"}, {"iMac4,2", "Yonah"}, {"iMac5,2", "Merom"}, {"iMac5,1", "Merom"}, {"iMac6,1", "Merom"}, {"iMac7,1", "Merom"}, {"iMac8,1", "Penryn"}, {"iMac9,1", "Penryn"}, {"iMac10,1", "Wolfdale"}, {"iMac11,1", "Wolfdale, Lynnfield"}......} 

のような2D Listで結果が得られます。Numbersの選択中のセルからそのまま情報を取得すると1D Listとして結果が返ってきますが、別途selection rangeの情報を取得し、それをもとに2D Listに変換。得られた2D Listに対して重複データの除去をCocoaの機能を用いて行なっています。

特定のフィールド上の選択中のデータを1D Listとして取得し、重複データを検出するようなScriptは日常的に使っていますが、行データをすべて取得して2D Listとして取り出し、重複データ部分を除去するようなものは使っていませんでした。

AppleScript名:Numbersで選択中のデータを2D Listで取得し、ユニーク化
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aList to get2DListFromNumbersSelection() of me
if aList = "" then return "No Selection"

set bList to uniquifyList(aList) of me

on get2DListFromNumbersSelection()
  –Numbersで選択範囲を縦に区切ったリストを返す
  
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
        
        
tell theTable
          set selList to value of every cell of selection range –選択範囲のデータを取得
          
          
set selName to name of selection range –選択範囲のrange情報を取得
          
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 s2Row to (address of row of range s2) as integer
          
set s2Column to (address of column of range s2) as integer
          
          
–選択範囲の情報を取得する
          
set selHeight to s2Row – s1Row + 1 –高さ(Height of selection range)
          
set selWidth to s2Column – s1Column + 1 –幅(Width of selection range)
          
        end tell
      end tell
    end tell
  end tell
  
  
set aLen to length of selList
  
set aaLen to selHeight
  
  
set bList to {}
  
repeat with i from 1 to aaLen
    set aHoriList to {}
    
    
repeat with ii from 1 to selWidth
      set j1 to ii + (i – 1) * selWidth
      
set tmpCon to contents of item j1 of selList
      
      
set aClass to class of tmpCon
      
if aClass = number or aClass = integer or aClass = real then
        set tmpCon to tmpCon as integer
      end if
      
      
set the end of aHoriList to tmpCon
    end repeat
    
    
set the end of bList to aHoriList
  end repeat
  
  
return bList
end get2DListFromNumbersSelection

–テキストを指定デリミタでリスト化
on parseByDelim(aData, aDelim)
  set aText to current application’s NSString’s stringWithString:aData
  
set aList to aText’s componentsSeparatedByString:aDelim
  
return aList as list
end parseByDelim

–1D/2D Listのユニーク化
on uniquifyList(aList as list)
  set aArray to current application’s NSArray’s arrayWithArray:aList
  
set bArray to aArray’s valueForKeyPath:"@distinctUnionOfObjects.self"
  
return bArray as list
end uniquifyList

★Click Here to Open This Script 

Posted in list | Tagged 10.11savvy 10.12savvy 10.13savvy 10.14savvy NSArray NSString Numbers | Leave a comment

Post navigation

  • Older posts
  • Newer posts

電子書籍(PDF)をオンラインストアで販売中!

Google Search

Popular posts

  • 開発機としてM2 Mac miniが来たのでガチレビュー
  • macOS 15, Sequoia
  • Pages本執筆中に、2つの書類モード切り替えに気がついた
  • Numbersで選択範囲のセルの前後の空白を削除
  • メキシカンハットの描画
  • Pixelmator Pro v3.6.4でAppleScriptからの操作時の挙動に違和感が
  • AppleScriptによる並列処理
  • macOS 15でも変化したText to Speech環境
  • Safariで「プロファイル」機能を使うとAppleScriptの処理に影響
  • AppleScript入門③AppleScriptを使った「自動化」とは?
  • デフォルトインストールされたフォント名を取得するAppleScript
  • 【続報】macOS 15.5で特定ファイル名パターンのfileをaliasにcastすると100%クラッシュするバグ
  • macOS 15 リモートApple Eventsにバグ?
  • Script Debuggerの開発と販売が2025年に終了
  • AppleScript入門① AppleScriptってなんだろう?
  • macOS 14で変更になったOSバージョン取得APIの返り値
  • NSObjectのクラス名を取得 v2.1
  • macOS 15:スクリプトエディタのAppleScript用語辞書を確認できない
  • 有害ではなくなっていたSpaces
  • AVSpeechSynthesizerで読み上げテスト

Tags

10.11savvy (1101) 10.12savvy (1242) 10.13savvy (1391) 10.14savvy (587) 10.15savvy (438) 11.0savvy (283) 12.0savvy (212) 13.0savvy (195) 14.0savvy (148) 15.0savvy (137) CotEditor (66) Finder (51) Keynote (119) NSAlert (61) NSArray (51) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (53) NSDictionary (28) NSFileManager (23) NSFont (21) NSImage (41) NSJSONSerialization (21) NSMutableArray (63) NSMutableDictionary (22) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (119) NSURL (98) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (76) Pages (55) Pixelmator Pro (20) Safari (44) Script Editor (27) WKUserContentController (21) WKUserScript (20) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

  • 2D Bin Packing
  • 3D
  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • Beginner
  • Benchmark
  • beta
  • Bluetooth
  • Books
  • boolean
  • bounds
  • Bug
  • Calendar
  • call by reference
  • check sum
  • Clipboard
  • Cocoa-AppleScript Applet
  • Code Sign
  • Color
  • Custom Class
  • date
  • dialog
  • diff
  • drive
  • Droplet
  • exif
  • file
  • File path
  • filter
  • folder
  • Font
  • Font
  • GAME
  • geolocation
  • GUI
  • GUI Scripting
  • Hex
  • History
  • How To
  • iCloud
  • Icon
  • Image
  • Input Method
  • Internet
  • iOS App
  • JavaScript
  • JSON
  • JXA
  • Keychain
  • Keychain
  • Language
  • Library
  • list
  • Locale
  • Localize
  • Machine Learning
  • Map
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • parallel processing
  • PDF
  • Peripheral
  • process
  • PRODUCTS
  • QR Code
  • Raw AppleEvent Code
  • Record
  • rectangle
  • recursive call
  • regexp
  • Release
  • Remote Control
  • Require Control-Command-R to run
  • REST API
  • Review
  • RTF
  • Sandbox
  • Screen Saver
  • Script Libraries
  • sdef
  • search
  • Security
  • selection
  • shell script
  • Shortcuts Workflow
  • Sort
  • Sound
  • Spellchecker
  • Spotlight
  • SVG
  • System
  • Tag
  • Telephony
  • Text
  • Text to Speech
  • timezone
  • Tools
  • Update
  • URL
  • UTI
  • Web Contents Control
  • WiFi
  • XML
  • XML-RPC
  • イベント(Event)
  • 未分類

アーカイブ

  • 2025年7月
  • 2025年6月
  • 2025年5月
  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2024年2月
  • 2024年1月
  • 2023年12月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年12月
  • 2019年11月
  • 2019年10月
  • 2019年9月
  • 2019年8月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年11月
  • 2018年10月
  • 2018年9月
  • 2018年8月
  • 2018年7月
  • 2018年6月
  • 2018年5月
  • 2018年4月
  • 2018年3月
  • 2018年2月

https://piyomarusoft.booth.pm/items/301502

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org

Forum Posts

  • 人気のトピック
  • 返信がないトピック

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org
Proudly powered by WordPress
Theme: Flint by Star Verte LLC