CotEditorのメンテナーの@1024jp氏の談話によると、
https://x.com/1024jp/status/1896829943587508664
CotEditor v 5.1.0 → 5.1.1 でAppleScript経由のprint機能がうまく動作していなかったのを動作するように修正したとのこと。
ここのところ、macOS側の機能の不全により、AppleScript経由でのprint機能の実行がうまく動作していないケースが発生しており、それに対処したとのこと。
CotEditorのメンテナーの@1024jp氏の談話によると、
https://x.com/1024jp/status/1896829943587508664
CotEditor v 5.1.0 → 5.1.1 でAppleScript経由のprint機能がうまく動作していなかったのを動作するように修正したとのこと。
ここのところ、macOS側の機能の不全により、AppleScript経由でのprint機能の実行がうまく動作していないケースが発生しており、それに対処したとのこと。
CotEditorがバージョン5.1.0にアップデートしました(翌日、5.1.1にアップデートしましたが、AS的には差はありません)。
アップデート内容は多岐に渡っていますが、AppleScript的には、documentのcontentsにeditable(boolean)属性が追加されました。
実際に、AppleScriptからこの属性値を操作して、想定どおりの挙動を行うかどうかをチェックしてみました。こうしたテストは開発者側でも行なっているかどうか怪しいところなので(とくにAppleのノーチェックぶりが目に余る)、大事な作業です。
想定どおりの動作を行なっているので、確認OKです!
AppleScript名:v51.0 document editable test.scpt |
tell application "CotEditor" tell front document set editable of it to true set edF to editable –> true set contents of it to "ABC" set editable of it to false set edF to editable –> false set contents of it to "CDE" end tell end tell |
XcodeでオープンしているWorkspace Document(.xcodeproj)のパスを取得してクローズし、再度オープンするAppleScriptです。macOS 15.3上のXcode 16.2で動作をテストしました。
Xcodeでオープン中の.applescriptファイルの構文確認を行うために、いろいろ試行錯誤してみたものの、Xcodeでオープン中にはファイルへの書き込み権限を取得できない雰囲気が濃厚。Xcodeのエディタで表示中のコンテンツ(.applescript)の本文に文字列を突っ込んでみても、Xcodeに蹴られます。
# AppleScriptからの制御が封じられているので、まっとうな手口が使えません
これに対策するために、Xcode Projectをいったんクローズして、構文確認を行うとよさそうだったので、試作品を作ってみたものです。
AppleScript名:XcodeのWorkspace Documentをクローズ後、再オープン.scptd |
— – Created by: Takaaki Naganoya – Created on: 2025/02/21 — – Copyright © 2025 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions tell application "Xcode" set xcVer to version tell workspace document 1 set xWSprojPath to path close end tell end tell –delay 1 tell application "Xcode" open ((POSIX file xWSprojPath) as alias) end tell |
オープンソースのテキストエディタ「CotEditor」の「write to console」コマンドにオプションが追加されました。
title(実行したAppleScript名の表記)と、timestamp表示の有無を指定できるようになっています。
ただし、これらのオプションが効くには条件があります。CotEditorの外部から、スクリプトエディタやScript Debuggerなどで実行したAppleScript内でCotEditorに対してwrite to consoleコマンドを実行した場合には、これらのオプションを指定していても、とくにtitle(ファイル名)については効きません。
CotEditorの内蔵スクリプトメニュー内で実行したAppleScriptにおいて「write to console」コマンドを実行した場合にはtitle(ファイル名)、timestamp(日時)の指定が有効です。
AppleScript名:コンソールテスト1.scpt |
tell application "CotEditor" write to console "ぴよまるさんだよ" with title without timestamp write to console "ぴよぴよさんだよ" with title and timestamp end tell |
Keynote書類上で選択中のオブジェクトのリサイズを行うAppleScriptです。
本Scriptの作成とテストはKeynote 14.214.3上で行いました。
Keynote書類は、4:3の書類と16:9の書類が存在しており、4:3の書類を16:9にリサイズしても内容についてはとくに変更は加えられず、逆に16:9の書類を4:3に変換すると、中身がぐしゃぐしゃになります。
「じゃあ、オブジェクトをグループ化してリサイズすれば?」
という話になりますが、やってみるとこれはうまく動きません。
iWork Apps間でのオブジェクトのコピー&ペーストにも問題があります。
たとえば、KeynoteからPagesにペーストした瞬間に「文字の回り込み」がデフォルトでオンになってしまい(この挙動が邪魔)、隣接するオブジェクトを避けて文字が回り込み、おかしな状態になります。
Keynote書類のリサイズ、他のiWork Appへのデータ使い回しを便利に行うために、オブジェクトのリサイズ処理というのは重要なテーマであり続けています。ただ、重要ではあるものの、iWork App上のオブジェクトのコントロール機能がAppleScript側に公開されていないため、手作業なしに複数オブジェクトをまとめてリサイズすることは(現状では)不可能です。
▲処理後 本Scriptを実行したことにより、Keynote書類上の各種オブジェクトが1/2のサイズになっている。ただし、lineの太さがそのままだったり、text alignの都合でバランスが悪くなってしまった箇所がある
なので、ここに示したScriptは「あくまでも試作品」レベルのものであり、この困難な作業に対する「銀の弾丸」ではありません。
lineオブジェクトの線の太さを制御できないですし、テキストオブジェクトの左寄せ/右寄せといった制御がAppleScriptからできないため、テストデータを処理してみてもこれらの手作業が必要だと感じます。
それでも、100%すべて手作業で調整するよりは「いくぶんマシ」なものでしょう。
AppleScript名:選択中のオブジェクトのリサイズ.scptd |
— – Created by: Takaaki Naganoya – Created on: 2024/12/20 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions set aScale to 2 tell application "Keynote" tell front document set aSel to selection repeat with i in aSel set j to contents of i set aClass to class of j if aClass is not in {document, slide} then set aPos to position of j copy aPos to {xPos, yPos} set aWidth to width of j set aHeight to height of j if (aClass = text item) or (aClass = shape) then tell j try set firstSize to size of first character of object text set targSize to firstSize / aScale ignoring application responses set size of every character of object text to targSize end ignoring end try end tell else if aClass = table then tell j set cList to every cell repeat with ii in cList set jj to contents of ii set aSize to font size of jj ignoring application responses set font size of jj to (aSize / aScale) end ignoring end repeat end tell else if aClass = line then set lineW to width of j –set width of j to (lineW / aScale) end if ignoring application responses set j’s width to (aWidth / aScale) set j’s height to (aHeight / aScale) set j’s position to {xPos / aScale, yPos / aScale} end ignoring end if end repeat end tell end tell |
Excelでオープンしている最前面の書類の現在表示中のシート上に配置されているpicture(画像)をすべて削除するAppleScriptです。
pictureを大量に配置するScriptの後始末をするために作成したものです(書き捨てレベル)。
数万セルのデータを取得して、ふたたび書き戻すような処理を行っても数秒。セルのデータのI/Oが超高速なExcelですが、画像などのオブジェクト操作は時間がかかり、本Scriptで900個程度のpictureオブジェクト(画像)を削除すると、それなりに待たされます。しかも、ignoring responsesで非同期実行しても待たされます。
AppleScript名:現在のシート上に存在しているpictureをすべて削除する.scpt |
— – Created by: Takaaki Naganoya – Created on: 2024/12/07 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — tell application "Microsoft Excel" tell active workbook tell active sheet ignoring application responses delete every picture end ignoring end tell end tell end tell |
指定範囲(30×30)のセルの位置に画像を配置するAppleScriptです。
画像配置Scriptに対して「特定のセルを指定すると配置できずにエラーになる」という反応があったので、テストを行うために書いたものです。
結局、セルアドレスを「B5」ではなく「b5」と小文字で書いたことがエラーの原因でした。Excelのセルアドレスを小文字で書くなんて聞いたことがないのですが、たしかにこれに対処できないのは問題です。
なので、セルのcolumnを計算するルーチンで大文字/小文字を無視するように書き換えました。
AppleScript名:指定範囲のセルの上に画像を配置.scpt |
— – Created by: Takaaki Naganoya – Created on: 2024/12/06 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use framework "AppKit" use scripting additions property |NSURL| : a reference to current application’s |NSURL| property NSImage : a reference to current application’s NSImage –Select Image file and get width and height set anImagePath to choose file set anImagePOSIX to POSIX path of anImagePath set aURL to |NSURL|’s fileURLWithPath:anImagePOSIX set aImage to NSImage’s alloc()’s initWithContentsOfURL:aURL set overlaySize to aImage’s |size|() repeat with targCellRow from 1 to 30 repeat with targCellCol from 1 to 30 –Column No, & Row No. –> x position & y position set {targCellX, targCellY} to retExcelCellPositiont(targCellCol, targCellRow) of me –Place image on worksheet and resize and relocate it tell application "Microsoft Excel" activate tell active workbook tell active sheet ignoring application responses set newPic to make new picture at beginning with properties {file name:(anImagePOSIX), height:(overlaySize’s |height|), width:(overlaySize’s |width|), top:targCellY, left position:targCellX} end ignoring end tell end tell end tell end repeat end repeat –指定Row, ColumnのCellのpositionを返す on retExcelCellPositiont(x as integer, y as integer) tell application "Microsoft Excel" tell active workbook tell active sheet tell row y tell cell x set xMin0 to left position set yMin0 to top set xWidth0 to width set yHeight0 to height end tell end tell end tell end tell end tell return {xMin0, yMin0} end retExcelCellPositiont script AddressEncoder property parent : AppleScript use scripting additions — 数値からセルアドレス(A1形式)への変換 on numberToCell(columnNumber) set columnAddress to "" set tempNumber to columnNumber — 列番号をA-Z形式に変換 repeat while tempNumber > 0 set remainder to (tempNumber – 1) mod 26 set columnAddress to (character (remainder + 1) of "ABCDEFGHIJKLMNOPQRSTUVWXYZ") & columnAddress set tempNumber to (tempNumber – 1) div 26 end repeat — A1形式のアドレスを返す return columnAddress end numberToCell — セルアドレス(A1形式)から数値への変換 on cellToNumber(cellAddress) set columnPart to "" set rowPart to "" — 列部分と行部分を分離 repeat with char in cellAddress if char is in "0123456789" then set rowPart to rowPart & char else set columnPart to columnPart & char end if end repeat — 列部分を数値に変換 set columnNumber to 0 repeat with i from 1 to length of columnPart set char to character i of columnPart using terms from scripting additions ignoring case set columnNumber to columnNumber * 26 + (offset of char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ") end ignoring end using terms from end repeat — 数値を返す return {columnNumber, (rowPart as integer)} end cellToNumber end script |
Microsoft Excelで、ワークシートに貼り込んだ画像の左上のセルアドレスを求めるAppleScriptです。
AppleScript名:配置されている画像の左上のアドレスを取得してA1形式で返す.scpt |
— – Created by: Takaaki Naganoya – Created on: 2024/12/06 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — tell application "Microsoft Excel" tell active workbook tell active sheet set aPic to picture 1 set tlCell to top left cell of aPic set xCell to first column index of tlCell set yCell to first row index of tlCell set cellAdr to (numberToCell(xCell) of AddressEncoder) & (yCell as string) –> "B5" end tell end tell end tell script AddressEncoder property parent : AppleScript use scripting additions — 数値からセルアドレス(A1形式)への変換 on numberToCell(columnNumber) set columnAddress to "" set tempNumber to columnNumber — 列番号をA-Z形式に変換 repeat while tempNumber > 0 set remainder to (tempNumber – 1) mod 26 set columnAddress to (character (remainder + 1) of "ABCDEFGHIJKLMNOPQRSTUVWXYZ") & columnAddress set tempNumber to (tempNumber – 1) div 26 end repeat — A1形式のアドレスを返す return columnAddress end numberToCell — セルアドレス(A1形式)から数値への変換 on cellToNumber(cellAddress) set columnPart to "" set rowPart to "" — 列部分と行部分を分離 repeat with char in cellAddress if char is in "0123456789" then set rowPart to rowPart & char else set columnPart to columnPart & char end if end repeat — 列部分を数値に変換 set columnNumber to 0 repeat with i from 1 to length of columnPart set char to character i of columnPart using terms from scripting additions ignoring case set columnNumber to columnNumber * 26 + (offset of char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ") end ignoring end using terms from end repeat — 数値を返す return {columnNumber, (rowPart as integer)} end cellToNumber end script |
Microsoft Excelで、指定画像を指定セルに貼り込むAppleScriptです。指定セルの座標を求めて、そこを左上の位置として画像を貼り込みます。
前バージョンが「動かない」という話があって、「そんなバカな?!」と、半信半疑でユーザーと同じドライブ名、フォルダ名、ファイル名、画像形式を採用したら(JPEG形式)同様にエラーになりました。自分がテストしたのは内蔵SSDで、画像形式はPNGだったのですが……
そこで、書き換えてJPEG画像でも、外付けドライブでもエラーにならないように書き換えてみました。
AppleScript名:指定セルに指定画像を貼り込む v2.scpt |
— – Created by: Takaaki Naganoya – Created on: 2024/12/06 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use framework "AppKit" use scripting additions property |NSURL| : a reference to current application’s |NSURL| property NSImage : a reference to current application’s NSImage –Excel Cell Address (A1) –> Column No, & Row No. set targCellAddr to "C5" set {targCellCol, targCellRow} to cellToNumber(targCellAddr) of AddressEncoder log {targCellCol, targCellRow} –Column No, & Row No. –> x position & y position set {targCellX, targCellY} to retExcelCellPositiont(targCellCol, targCellRow) of me log {targCellX, targCellY} –Select Image file and get width and height set anImagePath to choose file set anImagePOSIX to POSIX path of anImagePath set aURL to |NSURL|’s fileURLWithPath:anImagePOSIX set aImage to NSImage’s alloc()’s initWithContentsOfURL:aURL set overlaySize to aImage’s |size|() –Place image on worksheet and resize and relocate it tell application "Microsoft Excel" activate tell active workbook tell active sheet set newPic to make new picture at beginning with properties {file name:(anImagePOSIX), height:(overlaySize’s |height|), width:(overlaySize’s |width|), top:targCellY, left position:targCellX} end tell end tell end tell –指定Row, ColumnのCellのpositionを返す on retExcelCellPositiont(x as integer, y as integer) tell application "Microsoft Excel" tell active workbook tell active sheet tell row y tell cell x set xMin0 to left position set yMin0 to top set xWidth0 to width set yHeight0 to height end tell end tell end tell end tell end tell return {xMin0, yMin0} end retExcelCellPositiont script AddressEncoder property parent : AppleScript use scripting additions — 数値からセルアドレス(A1形式)への変換 on numberToCell(columnNumber) set columnAddress to "" set tempNumber to columnNumber — 列番号をA-Z形式に変換 repeat while tempNumber > 0 set remainder to (tempNumber – 1) mod 26 set columnAddress to (character (remainder + 1) of "ABCDEFGHIJKLMNOPQRSTUVWXYZ") & columnAddress set tempNumber to (tempNumber – 1) div 26 end repeat — A1形式のアドレスを返す return columnAddress end numberToCell — セルアドレス(A1形式)から数値への変換 on cellToNumber(cellAddress) set columnPart to "" set rowPart to "" — 列部分と行部分を分離 repeat with char in cellAddress if char is in "0123456789" then set rowPart to rowPart & char else set columnPart to columnPart & char end if end repeat — 列部分を数値に変換 set columnNumber to 0 repeat with i from 1 to length of columnPart set char to character i of columnPart using terms from scripting additions set columnNumber to columnNumber * 26 + (offset of char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ") end using terms from end repeat — 数値を返す return {columnNumber, (rowPart as integer)} end cellToNumber end script |
Numbersの表を、書籍掲載用に体裁をととのえるAppleScriptのアップデート版です。書籍掲載時には、同じ値が横方向に連続している箇所は1つにまとめたいところなので、その作業を自動で行います。
新型のNumbers/Excelセルアドレス変換ルーチンを実際に使用してみました。モジュールを入れ替えただけです。
▲対象の表のいずれかのセルを選択してAppleScriptを実行
AppleScript名:Numbersで選択中の表を書籍掲載用にセル内容の整理(重複セルをまとめる)v2.scpt |
— – Created by: Takaaki Naganoya – Created on: 2024/12/03 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" use scripting additions use framework "Foundation" 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 headR to header row count set headC to header column count set rowC to count every row set colC to count every column repeat with y from (headR + 1) to (rowC) –1行分(ヘッダーカラムをのぞく)のデータを1D Listで取得 set tmpRangeStr to numberToCell(headC + 1) of AddressEncoder & (y as string) & ":" & numberToCell(colC) of AddressEncoder & (y as string) set tValList to value of cells of range tmpRangeStr –1D Listから値が連続している区間を求める set sameBlock to detectSameValueRepeatationBlockIn1DArray(tValList) of detectRepeatation –連続区間でループ repeat with i in sameBlock copy i to {startX, endX} –データ内の項目Indexであることに留意 –重複値のセルをクリアする(初出セルの値は残す) repeat with ii from (startX + 1) to endX set value of cell (ii + headC) of row y to "" end repeat –重複していたセルをマージする set mRangeStr to numberToCell(headC + startX) of AddressEncoder & (y as string) & ":" & numberToCell(headC + endX) of AddressEncoder & (y as string) set mRange to range mRangeStr merge mRange end repeat end repeat end tell end tell end tell end tell script detectRepeatation property parent : AppleScript use scripting additions use framework "Foundation" –巨大なデータの処理に向いていないかも? on detectSameValueRepeatationBlockIn1DArray(aList) set dList to returnDuplicatesOnly(aList) of me –> {"年間仕様", "YP仕様", "月間仕様"} set anArray to current application’s NSMutableArray’s arrayWithArray:aList anArray’s addObject:"" set resList to {} repeat with i in dList set j to contents of i set anIndex to (anArray’s indexOfObject:j) repeat with ii from (anIndex + 1) to ((length of aList)) set jj to (anArray’s objectAtIndex:ii) as string if jj is not equal to j then set the end of resList to {anIndex + 1, ii} exit repeat end if end repeat end repeat resList –> {{4, 6}, {7, 9}, {10, 17}} end detectSameValueRepeatationBlockIn1DArray on returnDuplicatesOnly(aList) set countedSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList set simpleSet to current application’s NSSet’s setWithArray:aList countedSet’s minusSet:simpleSet return countedSet’s allObjects() as list end returnDuplicatesOnly end script script AddressEncoder property parent : AppleScript use scripting additions — 数値からセルアドレス(A1形式)への変換 on numberToCell(columnNumber) set columnAddress to "" set tempNumber to columnNumber — 列番号をA-Z形式に変換 repeat while tempNumber > 0 set remainder to (tempNumber – 1) mod 26 set columnAddress to (character (remainder + 1) of "ABCDEFGHIJKLMNOPQRSTUVWXYZ") & columnAddress set tempNumber to (tempNumber – 1) div 26 end repeat — A1形式のアドレスを返す return columnAddress end numberToCell — セルアドレス(A1形式)から数値への変換 on cellToNumber(cellAddress) set columnPart to "" set rowPart to "" — 列部分と行部分を分離 repeat with char in cellAddress if char is in "0123456789" then set rowPart to rowPart & char else set columnPart to columnPart & char end if end repeat — 列部分を数値に変換 set columnNumber to 0 repeat with i from 1 to length of columnPart set char to character i of columnPart using terms from scripting additions set columnNumber to columnNumber * 26 + (offset of char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ") end using terms from end repeat — 数値を返す return {columnNumber, (rowPart as integer)} end cellToNumber end script |
Pages書類上の表を、書籍掲載用に体裁をととのえるAppleScriptです。書籍掲載時には、同じ値が横方向に連続している箇所は1つにまとめたいところなので、その作業を自動で行います。
▲Pages書類上の表のいずれかのセルを選択しておいて、本Scriptを実行します
AppleScript名:Pagesで選択中の表を書籍掲載用にセル内容の整理(重複セルをまとめる).scpt |
— – Created by: Takaaki Naganoya – Created on: 2024/12/02 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" use scripting additions use framework "Foundation" tell application "Pages" tell front document try set theTable to first table whose class of selection range is range on error return "" –何も選択されてなかった場合 end try –セルを選択中の表を処理する tell theTable set headR to header row count set headC to header column count set rowC to count every row set colC to count every column repeat with y from (headR + 1) to (rowC) –1行分(ヘッダーカラムをのぞく)のデータを1D Listで取得 set tmpRangeStr to numAdrToColumnEncode(headC + 1) of AddressEncoder & (y as string) & ":" & numAdrToColumnEncode(colC) of AddressEncoder & (y as string) set tValList to value of cells of range tmpRangeStr –1D Listから値が連続している区間を求める set sameBlock to detectSameValueRepeatationBlockIn1DArray(tValList) of detectRepeatation –連続区間でループ repeat with i in sameBlock copy i to {startX, endX} –データ内の項目Indexであることに留意 –重複値のセルをクリアする(初出セルの値は残す) repeat with ii from (startX + 1) to endX set value of cell (ii + headC) of row y to "" end repeat –重複していたセルをマージする set mRangeStr to numAdrToColumnEncode(headC + startX) of AddressEncoder & (y as string) & ":" & numAdrToColumnEncode(headC + endX) of AddressEncoder & (y as string) set mRange to range mRangeStr merge mRange end repeat end repeat end tell end tell end tell script detectRepeatation property parent : AppleScript use scripting additions use framework "Foundation" –巨大なデータの処理に向いていないかも? on detectSameValueRepeatationBlockIn1DArray(aList) set dList to returnDuplicatesOnly(aList) of me –> {"年間仕様", "YP仕様", "月間仕様"} set anArray to current application’s NSMutableArray’s arrayWithArray:aList anArray’s addObject:"" set resList to {} repeat with i in dList set j to contents of i set anIndex to (anArray’s indexOfObject:j) repeat with ii from (anIndex + 1) to ((length of aList)) set jj to (anArray’s objectAtIndex:ii) as string if jj is not equal to j then set the end of resList to {anIndex + 1, ii} exit repeat end if end repeat end repeat resList –> {{4, 6}, {7, 9}, {10, 17}} end detectSameValueRepeatationBlockIn1DArray on returnDuplicatesOnly(aList) set countedSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList set simpleSet to current application’s NSSet’s setWithArray:aList countedSet’s minusSet:simpleSet return countedSet’s allObjects() as list end returnDuplicatesOnly end script script AddressEncoder property parent : AppleScript –10進数数値をExcel 2004/2008的カラム表現にエンコードするサブルーチン(エンコード範囲:1~1351) on numAdrToColumnEncode(origNum) if origNum > 1351 then error "エラー:Numbersのカラム表現(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 numAdrToColumnEncode –Numbersの横方向アドレス(A~Zの26進数)文字列を10進数に変換 on colAddrToNumDecode(origStr) return aNthToDecimal(origStr, {"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"}) of me end colAddrToNumDecode –n進数文字列を10進数に変換する on aNthToDecimal(origStr, nTh) set resNumber to 0 set sList to reverse of (characters of origStr) set aLen to length of nTh set digitCount to 0 repeat with i in sList set j to contents of i set aRes to offsetInList(j, nTh) of me set resNumber to resNumber + (aLen ^ digitCount) * aRes set digitCount to digitCount + 1 end repeat return resNumber as integer end aNthToDecimal on offsetInList(aChar, aList) set anArray to NSArray’s arrayWithArray:aList set aInd to (anArray’s indexOfObject:aChar) if aInd = current application’s NSNotFound or (aInd as number) > 9.99999999E+8 then error "Invalid Character Error" else return (aInd as integer) + 1 –0 to 1 based index conversion end if end offsetInList end script |
Numbersの表を、書籍掲載用に体裁をととのえるAppleScriptです。書籍掲載時には、同じ値が横方向に連続している箇所は1つにまとめたいところなので、その作業を自動で行います。
いずれかのセルを選択した表に対して処理を行います。表の各行のデータを取得し、データ連続区間を検出。連続区間の2つ目以降のセルの内容を消去したうえで、当該区間のセルをまとめます。
そんなに大きな表を処理するようにはできていません。色をつけるところまで自動化しようかとも考えたのですが、色についてはケースバイケースだろうと考え、そこまでは処理していません。
▲対象の表のいずれかのセルを選択してAppleScriptを実行
AppleScript名:Numbersで選択中の表を書籍掲載用にセル内容の整理(重複セルをまとめる).scpt |
— – Created by: Takaaki Naganoya – Created on: 2024/12/02 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" use scripting additions use framework "Foundation" 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 headR to header row count set headC to header column count set rowC to count every row set colC to count every column repeat with y from (headR + 1) to (rowC) –1行分(ヘッダーカラムをのぞく)のデータを1D Listで取得 set tmpRangeStr to numAdrToColumnEncode(headC + 1) of AddressEncoder & (y as string) & ":" & numAdrToColumnEncode(colC) of AddressEncoder & (y as string) set tValList to value of cells of range tmpRangeStr –1D Listから値が連続している区間を求める set sameBlock to detectSameValueRepeatationBlockIn1DArray(tValList) of detectRepeatation –連続区間でループ repeat with i in sameBlock copy i to {startX, endX} –データ内の項目Indexであることに留意 –重複値のセルをクリアする(初出セルの値は残す) repeat with ii from (startX + 1) to endX set value of cell (ii + headC) of row y to "" end repeat –重複していたセルをマージする set mRangeStr to numAdrToColumnEncode(headC + startX) of AddressEncoder & (y as string) & ":" & numAdrToColumnEncode(headC + endX) of AddressEncoder & (y as string) set mRange to range mRangeStr merge mRange end repeat end repeat end tell end tell end tell end tell script detectRepeatation property parent : AppleScript use scripting additions use framework "Foundation" –巨大なデータの処理に向いていないかも? on detectSameValueRepeatationBlockIn1DArray(aList) set dList to returnDuplicatesOnly(aList) of me –> {"年間仕様", "YP仕様", "月間仕様"} set anArray to current application’s NSMutableArray’s arrayWithArray:aList anArray’s addObject:"" set resList to {} repeat with i in dList set j to contents of i set anIndex to (anArray’s indexOfObject:j) repeat with ii from (anIndex + 1) to ((length of aList)) set jj to (anArray’s objectAtIndex:ii) as string if jj is not equal to j then set the end of resList to {anIndex + 1, ii} exit repeat end if end repeat end repeat resList –> {{4, 6}, {7, 9}, {10, 17}} end detectSameValueRepeatationBlockIn1DArray on returnDuplicatesOnly(aList) set countedSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList set simpleSet to current application’s NSSet’s setWithArray:aList countedSet’s minusSet:simpleSet return countedSet’s allObjects() as list end returnDuplicatesOnly end script script AddressEncoder property parent : AppleScript –10進数数値をExcel 2004/2008的カラム表現にエンコードするサブルーチン(エンコード範囲:1~1351) on numAdrToColumnEncode(origNum) if origNum > 1351 then error "エラー:Numbersのカラム表現(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 numAdrToColumnEncode –Numbersの横方向アドレス(A~Zの26進数)文字列を10進数に変換 on colAddrToNumDecode(origStr) return aNthToDecimal(origStr, {"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"}) of me end colAddrToNumDecode –n進数文字列を10進数に変換する on aNthToDecimal(origStr, nTh) set resNumber to 0 set sList to reverse of (characters of origStr) set aLen to length of nTh set digitCount to 0 repeat with i in sList set j to contents of i set aRes to offsetInList(j, nTh) of me set resNumber to resNumber + (aLen ^ digitCount) * aRes set digitCount to digitCount + 1 end repeat return resNumber as integer end aNthToDecimal on offsetInList(aChar, aList) set anArray to NSArray’s arrayWithArray:aList set aInd to (anArray’s indexOfObject:aChar) if aInd = current application’s NSNotFound or (aInd as number) > 9.99999999E+8 then error "Invalid Character Error" else return (aInd as integer) + 1 –0 to 1 based index conversion end if end offsetInList end script |
たまにMac用のWebブラウザが新登場しているのですが、ほとんどがGoogle Chromiumの互換といいますか、Chromiumのぱちも……といいますか、ほぼそのまま利用して作られていたりして、そのおかげで割としっかりとAppleScript対応機能が実装されたまま多数のWebブラウザがリリースされるというメリットがありました。
そんな中、たまたま見つけた「Orion」。Kagiが作ったWebブラウザとのことです。
AppleScriptから見ると、見たこともないような挙動をするWebブラウザです。
用語辞書の傾向はChrome系というよりも、Safariからとんがったコマンドを削除したようなたたずまい。
そして、必要な機能がついていなくて、割と「何これ?」と首をひねってしまうような出来です。
SafariもGoogle Chromeも、現在のタブを指し示すactive tabとかcurrent tabといった予約語でアクセスできるのですが、それができません。一応、Windowのプロパティとしてcurrent tabがあるのですが、このtabからIDとかIndexが取得できません。
do JavaScriptコマンドがあるので、ちょっとOrion固有の制限が加わりつつもJavaScriptコマンドを実行してWebのソースコードやテキストを取得できたりはしつつ、Webブラウザ上で選択中の要素を取得できなかったりします。
そして、肝心のdo JavaScriptコマンドでtabを指定する必要があるものの、current tabが何であるかを特定できず……仕方ないので、tabから取得できるURLをもとにどのtabがcurrent tabであるかを探し回ってなんとか。
windowの新規作成は、documentを作成することで行うことに。
人間らしく、というレベルはクリアできていないような気がします。久しぶりに、挙動がここまで不完全というか不自然なWebブラウザを見かけました。
AppleScript名:Orionのアプリのプロパティを取得.scpt |
tell application "Orion" properties –> {frontmost:false, class:application, name:"Orion", version:"0.99"} end tell |
AppleScript名:OrionでWindowのtitleを取得.scpt |
–同じURLを持つTabが複数あった場合には処理が破綻する tell application "Orion" tell window 1 set aURL to URL of current tab set tList to URL of every tab set tInd to retIndexNumInArray(tList, aURL) of me if tInd = 0 then return tell tab tInd –current tabのindexを求める方法がないのに、current tabを指定できないし、具体的にtab idを指定しないといけない set aRes to do JavaScript "document.querySelector(’title’).textContent;" end tell end tell end tell –1Dimensionリスト中のシーケンシャルサーチ on retIndexNumInArray(aList, aTarget) set aCount to 1 set hitF to false repeat with i in aList set j to contents of i if aTarget = j then return aCount set aCount to aCount + 1 end repeat if hitF = false then return 0 end retIndexNumInArray |
AppleScript名:Orionで新規URLをオープン(新規Tab).scpt |
tell application "Orion" open location "https://www.apple.com/jp" –新規Tabでオープン end tell |
AppleScript名:Orionの最前面のWindowのcurrent tabで新規URLをオープン.scpt |
tell application "Orion" set URL of current tab of window 1 to "https://www.apple.com/jp" end tell |
AppleScript名:Orionでcurrent tabに対してJavaScript実行してソースを取得.scpt |
–同じURLを持つTabが複数あった場合には処理が破綻する tell application "Orion" tell window 1 set aURL to URL of current tab set tList to URL of every tab set tInd to retIndexNumInArray(tList, aURL) of me if tInd = 0 then return tell tab tInd –current tabのindexを求める方法がないのに、current tabを指定できないし、具体的にtab idを指定しないといけない set aRes to do JavaScript "document.getElementsByTagName(’html’)[0].innerHTML" end tell end tell end tell –1Dimensionリスト中のシーケンシャルサーチ on retIndexNumInArray(aList, aTarget) set aCount to 1 set hitF to false repeat with i in aList set j to contents of i if aTarget = j then return aCount set aCount to aCount + 1 end repeat if hitF = false then return 0 end retIndexNumInArray |
AppleScript名:Orion、WindowのCloseができるが、makeできない.scpt |
tell application "Orion" close every window end tell |
AppleScript名:Orionで新規document作成.scpt |
tell application "Orion" make new document end tell |
AppleScript名:新規tabの作成.scpt |
tell application "Orion" tell window 1 make new tab with properties {URL:"http://www.apple.com/jp"} end tell end tell |
Keynote書類上で複数Shapeないしtext itemが選択された状態で、一番上にあるitemの幅に、下にあるitemを等分割+位置合わせを行うAppleScriptです。
言葉で言い表すと難しいのですが、画面キャプチャで表現すると一目瞭然です。
▲処理後、上側のshapeの幅で下のshapeを等分割+ギャップ指定
電子書籍作成時によく行う作業をワンアクションで行えるようにしてみました。
2D ListのソートはVanilla AppleScriptで書かれたものを使っていますが、これはソートする対象のデータが極小なのと、本ScriptをmacOS標準搭載のScript Menuから呼び出すために作ったためです。
2D Listのソートを行うためだけに、BridgePlusを使用=Script DebuggerでEnhanced Appletに書き出す必要があるというのは面倒なので。
AppleScript名:最前面のKeynote書類で選択中のshapeを一番上のガイドオブジェクトの幅をもとに、残りを等分割 |
— – Created by: Takaaki Naganoya – Created on: 2024/11/15 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions property xGap : 8 –X軸方向のオブジェクトの隙間座標値 tell application "Keynote" tell front document set aSel to selection if aSel = {} then return set fClass to class of first item of aSel if fClass = slide then return –スライド上のオブジェクトではなく、スライドが選択されていた場合には処理しない set objList to {} set posList to {} set aCount to 1 repeat with i in aSel set j to contents of i set tmpClass to class of j –条件に合うオブジェクトのみ処理対象に if tmpClass is in {text item, shape} then set the end of objList to j set the end of posList to ((position of j) & (width of j) & aCount) set aCount to aCount + 1 end if end repeat set newPosList to shellSortListAscending(posList, 2) of sortLib –Y軸値をもとにソート set guideObj to first item of newPosList –Y軸座標が一番少ない(上)のものをガイドオブジェクトとしてみなす set newPosList to shellSortListAscending(rest of newPosList, 1) of sortLib –ガイドオブジェクト以外のオブジェクト座標値をX軸値でソート set guideWidth to contents of item 3 of guideObj set xStartPos to item 1 of item 1 of newPosList set yPos to item 2 of item 1 of newPosList set itemsCount to length of newPosList set itemWidth to (guideWidth – (xGap * (itemsCount – 1))) / itemsCount –下側オブジェクトの位置と幅修正処理 copy xStartPos to x repeat with i from 1 to itemsCount set y to item 2 of (item i of newPosList) set targObj to item (item 4 of (item i of newPosList)) of objList tell targObj set position of it to {x, y} set width of it to itemWidth end tell set x to x + itemWidth + (xGap) end repeat end tell end tell –Vanilla AppleScriptで書いた2D ListのSorting Lib script sortLib –シェルソートで入れ子のリストを昇順ソート on shellSortListAscending(aSortList, aKeyItem) script oBj property list : aSortList end script set len to count oBj’s list’s items set gap to 1 repeat while (gap ≤ len) set gap to ((gap * 3) + 1) end repeat repeat while (gap > 0) set gap to (gap div 3) if (gap < len) then repeat with i from gap to (len – 1) set temp to oBj’s list’s item (i + 1) set j to i repeat while ((j ≥ gap) and (contents of item aKeyItem of (oBj’s list’s item (j – gap + 1)) > item aKeyItem of temp)) set oBj’s list’s item (j + 1) to oBj’s list’s item (j – gap + 1) set j to j – gap end repeat set oBj’s list’s item (j + 1) to temp end repeat end if end repeat return oBj’s list end shellSortListAscending –シェルソートで入れ子のリストを降順ソート on shellSortListDescending(aSortList, aKeyItem) script oBj property list : aSortList end script set len to count oBj’s list’s items set gap to 1 repeat while (gap ≤ len) set gap to ((gap * 3) + 1) end repeat repeat while (gap > 0) set gap to (gap div 3) if (gap < len) then repeat with i from gap to (len – 1) set temp to oBj’s list’s item (i + 1) set j to i repeat while ((j ≥ gap) and (contents of item aKeyItem of (oBj’s list’s item (j – gap + 1)) < item aKeyItem of temp)) set oBj’s list’s item (j + 1) to oBj’s list’s item (j – gap + 1) set j to j – gap end repeat set oBj’s list’s item (j + 1) to temp end repeat end if end repeat return oBj’s list end shellSortListDescending end script |
現在オープン中の最前面のPages書類の内容を伏せ字に置き換えるAppleScriptの改良版です。電子書籍「Pages+AppleScriptで本をつくろう!」のために作成したScriptの改良版です。
–> Download Script Bundle With library
実行にはライブラリ「dynamicClicker」が必要なため、上記リンクからAppleScriptバンドル書類をダウンロードして実行してください。
Pagesの書類上のオブジェクトは、
のようになっており(iWork Scripting Book with AppleScriptより引用)、shapeとtext itemの区別ができないという「頭のおかしな仕様」になっていますが、オブジェクトのclassを求めれば、だいたいは区別できる状況です。
group itemについてはメニューを強制操作して(なくなるまで永久ループで)グループ解除を行い、そののちにshapeとtableについては伏せ字処理を行います。
image、chart、movieなどのオブジェクトについては伏せ字処理を行いませんが、そのあたりは処理したいユーザーの趣味次第でしょう。
AppleScript名:全ページを伏せ字に v2.scptd |
— – Created by: Takaaki Naganoya – Created on: 2024/10/02 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions use dLib : script "dynamicClicker" tell application "Pages" tell front document set pCount to count every page repeat with p from 1 to pCount tell page p –ひたすらグループ化されたアイテムを解除する。多重にグループ化が可能なので、ひたすら繰り返す repeat set gList to every group if gList = {} then exit repeat set gRes to ungroupPagesItems(gList) of me end repeat –通常処理 set aList to every iWork item repeat with i in aList set j to contents of i set tmpClass to class of j if tmpClass = shape then set aText to object text of j set mText to maskStrings(aText) of me set object text of j to mText else if tmpClass = table then tell j set tmpW to width set tmpH to height set tumeF to false set cColumn to count every column if tmpW = 0 or tmpH = 0 then — else set aRatio to tmpW / tmpH if aRatio < 0.125 then set tumeF to true if cColumn = 1 then set tumeF to true end if end tell –表がツメでない場合にのみ処理 if tumeF = false then tell j set aTitle to "" try set aTitle to name of it set mText to maskStrings(aTitle) of me set name of it to mText end try set cellList to every cell repeat with ii in cellList set jj to contents of ii set aValue to (value of jj) as string set mText to maskStrings(aValue) of me set value of jj to mText end repeat end tell end if end if end repeat end tell end repeat end tell end tell –Pagesで選択中のアイテムをグループ解除する on ungroupPagesItems(gList as list) set appName to "Pages" –Application Name set aList to {"配置", "グループ解除"} –Localized Menu Titles (menu title structure to "Ungroup") tell application "Pages" tell front document set selection to gList end tell end tell set aRes to clickSpecifiedMenuElement(appName, aList) of dLib return aRes end ungroupPagesItems –指定したルールのとおりの文字種の並びになっているか? on maskStrings(aStr) set aList to characters of aStr set chkList to {} repeat with i from 1 to (length of aList) set j1 to contents of item i of aList set tmpStr to j1 set j2 to (my chkNumeric:j1) set j3 to (my chkAlphabetCapt:j1) set j4 to (my chkAlphabetSmall:j1) if j2 = true then set tmpStr to "9" else if j3 = true then set tmpStr to "Z" else if j4 = true then set tmpStr to "z" else set tmpStr to "あ" end if set the end of chkList to tmpStr end repeat return chkList as string end maskStrings — アルファベット大文字か on chkAlphabetCapt:checkString set aStr to current application’s NSString’s stringWithString:checkString set allCharSet to current application’s NSMutableCharacterSet’s alloc()’s init() allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "A", 26)) set aBool to my chkCompareString:aStr baseString:allCharSet return aBool as boolean end chkAlphabetCapt: — アルファベット小文字か on chkAlphabetSmall:checkString set aStr to current application’s NSString’s stringWithString:checkString set allCharSet to current application’s NSMutableCharacterSet’s alloc()’s init() allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "a", 26)) set aBool to my chkCompareString:aStr baseString:allCharSet return aBool as boolean end chkAlphabetSmall: –数字のみか on chkNumeric:checkString set digitCharSet to current application’s NSCharacterSet’s characterSetWithCharactersInString:"0123456789" set ret to my chkCompareString:checkString baseString:digitCharSet return ret as boolean end chkNumeric: –アルファベットと数字のみか on chkAlphaNumeric:checkString set alnumCharSet to current application’s NSCharacterSet’s alphanumericCharacterSet() set ret to my chkCompareString:checkString baseString:alnumCharSet return ret as boolean end chkAlphaNumeric: –アルファベットと数字と記号のみか on chkAlphaNumericSymbol:checkString set muCharSet to current application’s NSCharacterSet’s alphanumericCharacterSet()’s mutableCopy() muCharSet’s addCharactersInString:"$\"!~&=#[]._-+`|{}?%^*/’@-/:;()," set ret to my chkCompareString:checkString baseString:muCharSet return ret as boolean end chkAlphaNumericSymbol: –記号のみか on chkSymbol:checkString set muCharSet to current application’s NSCharacterSet’s alloc()’s init() muCharSet’s addCharactersInString:"$\"!~&=#[]._-+`|{}?%^*/’@-/:;()," set ret to my chkCompareString:checkString baseString:muCharSet return ret as boolean end chkSymbol: –全角文字が存在するか on chkMultiByteChar:checkString set aStr to current application’s NSString’s stringWithString:checkString set aRes to aStr’s canBeConvertedToEncoding:(current application’s NSASCIIStringEncoding) return (aRes as boolean) end chkMultiByteChar: on chkCompareString:checkString baseString:baseString set aScanner to current application’s 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 chkCompareString:checkString characterSet:baseSet set anNSString to current application’s NSString’s stringWithString:checkString set theRange to anNSString’s rangeOfCharacterFromSet:baseSet return (|length| of theRange = 0) as boolean end chkCompareString:characterSet: |
現在オープン中の最前面のPages書類の内容を伏せ字に置き換えるAppleScriptです。
新刊「Pages+AppleScriptで本をつくろう!」の作成のために書いたものです。Pages書類を付録として電子書籍に添付する場合に、あくまでデザインテンプレートとしての利用を見込んでいるため、本文がそのまま入っていると困るわけです、私が。
そんなわけで、せっかく作ったPages書類の内容を伏せ字にして、ダミー書類化するためのAppleScriptが必要になったわけです。
一応、テキストを伏せ字にするAppleScriptは作ってあったので、これをPages書類相手に処理するよう書き換えたものがこれです。
ただし、すべてのPages書類内のオブジェクトに対応していません。groupオブジェクトについては、メニュー操作を行えばグループ解除を行えなくもないですが、未着手です。
ちょっと気をつけて処理したのが「表」の内部セルに入っている値です。空欄だと値(value)がmissing valueになるので、そこは触らないほうがよかったかもしれません。
自分だけの事情になりますが、ページ左右端に「ツメ」と呼ばれるマークを「表」オブジェクトを用いて記入しているため、この「ツメ」に相当する「表」については無視するようにしています。
AppleScript名:全ページを伏せ字に.scptd |
— – Created by: Takaaki Naganoya – Created on: 2024/10/02 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions tell application "Pages" tell front document set pCount to count every page repeat with p from 1 to pCount tell page p set aList to every iWork item repeat with i in aList set j to contents of i set tmpClass to class of j if tmpClass = shape then set aText to object text of j set mText to maskStrings(aText) of me set object text of j to mText else if tmpClass = group then else if tmpClass = table then tell j set tmpW to width set tmpH to height set tumeF to false set cColumn to count every column if tmpW = 0 or tmpH = 0 then — else set aRatio to tmpW / tmpH if aRatio < 0.125 then set tumeF to true if cColumn = 1 then set tumeF to true end if end tell –表がツメでない場合にのみ処理 if tumeF = false then tell j set aTitle to "" try set aTitle to name of it set mText to maskStrings(aTitle) of me set name of it to mText end try set cellList to every cell repeat with ii in cellList set jj to contents of ii set aValue to (value of jj) as string set mText to maskStrings(aValue) of me set value of jj to mText end repeat end tell end if end if end repeat end tell end repeat end tell end tell –指定したルールのとおりの文字種の並びになっているか? on maskStrings(aStr) set aList to characters of aStr set chkList to {} repeat with i from 1 to (length of aList) set j1 to contents of item i of aList set tmpStr to j1 set j2 to (my chkNumeric:j1) set j3 to (my chkAlphabetCapt:j1) set j4 to (my chkAlphabetSmall:j1) if j2 = true then set tmpStr to "9" else if j3 = true then set tmpStr to "Z" else if j4 = true then set tmpStr to "z" else set tmpStr to "あ" end if set the end of chkList to tmpStr end repeat return chkList as string end maskStrings — アルファベット大文字か on chkAlphabetCapt:checkString set aStr to current application’s NSString’s stringWithString:checkString set allCharSet to current application’s NSMutableCharacterSet’s alloc()’s init() allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "A", 26)) set aBool to my chkCompareString:aStr baseString:allCharSet return aBool as boolean end chkAlphabetCapt: — アルファベット小文字か on chkAlphabetSmall:checkString set aStr to current application’s NSString’s stringWithString:checkString set allCharSet to current application’s NSMutableCharacterSet’s alloc()’s init() allCharSet’s addCharactersInRange:(current application’s NSMakeRange(ASCII number of "a", 26)) set aBool to my chkCompareString:aStr baseString:allCharSet return aBool as boolean end chkAlphabetSmall: –数字のみか on chkNumeric:checkString set digitCharSet to current application’s NSCharacterSet’s characterSetWithCharactersInString:"0123456789" set ret to my chkCompareString:checkString baseString:digitCharSet return ret as boolean end chkNumeric: –アルファベットと数字のみか on chkAlphaNumeric:checkString set alnumCharSet to current application’s NSCharacterSet’s alphanumericCharacterSet() set ret to my chkCompareString:checkString baseString:alnumCharSet return ret as boolean end chkAlphaNumeric: –アルファベットと数字と記号のみか on chkAlphaNumericSymbol:checkString set muCharSet to current application’s NSCharacterSet’s alphanumericCharacterSet()’s mutableCopy() muCharSet’s addCharactersInString:"$\"!~&=#[]._-+`|{}?%^*/’@-/:;()," set ret to my chkCompareString:checkString baseString:muCharSet return ret as boolean end chkAlphaNumericSymbol: –記号のみか on chkSymbol:checkString set muCharSet to current application’s NSCharacterSet’s alloc()’s init() muCharSet’s addCharactersInString:"$\"!~&=#[]._-+`|{}?%^*/’@-/:;()," set ret to my chkCompareString:checkString baseString:muCharSet return ret as boolean end chkSymbol: –全角文字が存在するか on chkMultiByteChar:checkString set aStr to current application’s NSString’s stringWithString:checkString set aRes to aStr’s canBeConvertedToEncoding:(current application’s NSASCIIStringEncoding) return (aRes as boolean) end chkMultiByteChar: on chkCompareString:checkString baseString:baseString set aScanner to current application’s 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 chkCompareString:checkString characterSet:baseSet set anNSString to current application’s NSString’s stringWithString:checkString set theRange to anNSString’s rangeOfCharacterFromSet:baseSet return (|length| of theRange = 0) as boolean end chkCompareString:characterSet: |
新たにリリースされたSafari v18(macOS 13/14/15用)で、各Tabに「pid」属性が新設されました。
各Webコンテンツのブラウズを行う処理プロセスを、独立したプロセスで行うことで、メモリの食いすぎでプロセスが止まったような場合にでも他のWebブラウジングに影響を与えない、というあたりにメリットがあったとか。
▲Safari v17とv18のAppleScript用語辞書(sdef)を比較したところ
▲SafariでYouTube上のムービーを再生しているところ
pidがわかると、どういう「いいこと」があるのかが問題です。メモリの使用状況などを確認することはできますし、個別にプロセスをkillすることもできるわけですが、そこまでやるんだろうかと。そういうニーズがあって新設したのか、ちょっとわからないところです。
それはともかく、Safari(≒WebKit)系はゴミプロセスがメモリ上に残りまくるので(Mail.appもメッセージを表示するだけでゴミプロセスが残るし)、その点がちょっとどうなのかという点と、Webコンテンツ上の画像ボタンを文字認識しておかしな動作をしまくるので、そのあたりは勘弁してほしいところです。
AppleScript名:Safariのtabのpidを取得.scpt |
tell application "Safari" tell window 1 set aList to pid of every tab –> {33892} end tell end tell |
iWork Apps(Keynote、Pages、Numbers)にはAppleScript系の機能でいろいろ勘弁してほしい仕様がありますが、その中でも最大のものが、書類内の各オブジェクトがIndexで管理されていることです。
Indexというのは、1からはじまる連番の数値です。
iWork Apps(Keynote、Pages、Numbers)のドキュメント上でオブジェクトの削除を行おうとすると、「地獄」を見ることになります。
iWork Appsの書類上でオブジェクトの削除を行うと、このIndex値が振り直されてしまうために、正しく「対象」を指し示すことが(途中から)できなくなってしまうのです。あるいは、まったく関係のない別のオブジェクトが削除されるとか。
これが、idで管理されていれば、何かのオブジェクトを削除されても影響はありません。何かUUID的な重複しないidが割り振られて、最初から最後まで(アプリケーションが起動してから終了するまで、あるいは書類がオープンされてからクローズされるまで)個別に識別されます。
各オブジェクトを識別する場合に、それ専用の属性値を持たせることがあります。
Adobe InDesign:script label AppleScriptから設定・確認が可能なラベル(文字列)を設定できる
もともとある仕組みを本来の目的以外の用途に使うことができるケースもあります。
OmniGraffle:URL urlとかいいつつ、文字列だったらだいたいなんでも入った記憶が
そして、iWork Apps(Keynote、Pages、Numbers)。普段ほとんど使わなくて、AppleScriptから操作できて害のない属性値なんて便利なものがあるわけが……ありました。
Keynoteで使っている例は見かけましたが、他で使ったことのない「reflectin value」。つまり、「反射」属性。
PagesでもNumbersでも使ったことがありません。個人的には、Keynoteでも使ったことがないと思います。
選択状態にあるオブジェクトをもとに何らかの処理を行なって、選択していたオブジェクトを削除する場合に、普通に処理すると(オブジェクトがIndexで管理されているので)、地獄を見ます。
なので、削除対象のオブジェクトのreflection valueに100とか(1〜100のうち、0でないお好きな値を)を設定しておいて、ひととおり処理し終わったら、reflection valueが指定値になっているオブジェクトだけをフィルタ参照で削除する、といった対策が有効です。
前処理Scriptで、最初にreflection valueが何か設定されているオブジェクトが存在しないことを確認したうえで、選択中のオブジェクトのreflection valueに100を設定し……
AppleScript名:削除_前処理.scptd |
tell application "Pages" tell front document set reList to every iWork item whose reflection value is 100 if length of reList is not equal to 0 then return set aSel to selection repeat with i in aSel set j to contents of i set reflection value of j to 100 end repeat end tell end tell |
処理を行なったあとで、reflection valueに100と設定されているオブジェクトを削除します。
AppleScript名:削除_後処理.scptd |
tell application "Pages" tell front document tell current page set aSel to delete (every iWork item whose reflection value = 100) end tell end tell end tell |
Pixelmator Proがv3.6.8でHDR画像のサポートを追加しました。
AppleScript用語辞書の比較で確認された変化は以下のとおりです。
・予約語「JPEG」の類義語として「JPG」を追加定義
・HDR画像の予約語を追加(OpenExr、HDR JPEG、HDR HEIC、HDR AVIF、HDR PNG)
・applicationのプロパティとして「load hdr content」を新設
・documentのプロパティとして「display hdr content」を新設
Appleの公式資料によれば、現行機種はHDRに対応しているとのこと。
ただし、接続しているディスプレイによって、
「このディスプレイはHDRコンテンツをサポートしていません」(Mac mini M1+Apple Cinema Display)
「このディスプレイはHDRコンテンツのサポートが制限されています」(MacBook Air M2)
といったように、非対応/対応(不完全対応を含む)と状態が分かれるようです。
対応環境でPixelmator ProのHDRサポート状態を変更してHDR画像をオープンする実験は行なってみました。
▲Pixelmator Proの設定ウィンドウ HDRコンテンツのサポートが制限されている(MacBook Air M2)と表示
▲Pixelmator ProでサンプルのHDR JPEGをオープンしたところ
AppleScript名:HDR画像をオープン |
tell application "Pixelmator Pro" set load hdr content to true set aHDR2 to load hdr content –> true if aHDR2 = false then return set aHDRfile to choose file open aHDRfile end tell |
HDR画像をオープンしても、HDR表示が行われるかどうかは別の管理になっている(documentのプロパティ)ので、そこも設定する必要があるようです。変更すると画面上でわずかに階調表現に変化が見られました(ちょっとだけ)。
AppleScript名:オープン中のHDR画像をHDR表示する |
tell application "Pixelmator Pro" –環境チェック set appHDR to load hdr content if appHDR = false then return –HDR画像の表示状態を変更 tell front document set display hdr content to true set docHDR to display hdr content end tell end tell |
Pixelmator Proでたまに実行する「1024×1024の画像からアイコン用の各種解像度の画像を作成する」AppleScriptですが、Pixelmator Pro v3.6.4で久しぶりに動かしたら、エラーが出てうまく動かなくなっていました。
このAppleScriptは、1024×1024の画像をオープンした状態で実行するものです。
すぐに、各サイズにリサイズしつつ、ファイル名に解像度を反映させた状態で書き出しを行います。
AppleScript名:アイコン書き出しv2.scptd |
— – Created by: Takaaki Naganoya – Created on: 2020/10/19 — – Copyright © 2020 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions set resolList to {1024, 512, 256, 128, 64, 32, 16} set aTargFileBase to (choose file name with prompt "Select Export base name") as string tell application "Pixelmator Pro" if (exists of document 1) = false then display dialog "There is no document" buttons {"OK"} default button 1 with icon 1 return end if tell front document set aWidth to width set aHeight to height if {aWidth, aHeight} is not equal to {1024.0, 1024.0} then display dialog "Wrong Image Size (1024×1024 required)" buttons {"OK"} default button 1 with icon 2 with title "Size Error" return end if repeat with i in resolList resize image width i height i resolution 72 algorithm bilinear export to file (aTargFileBase & "_" & (i as string) & "x" & (i as string) & ".png") as PNG undo end repeat end tell end tell |
これが、macOS 13.6.8+Pixelmator Pro v3.6.4の組み合わせで実行したらエラーが出て実行できなくなっていました。
問題点は割と明らかです。documentへのtellブロック内で、documentをパラメータとして要求するexportといったコマンドを実行したときに、tellブロックを認識せず、コマンドの直後にdocumentオブジェクトを表記しないとエラーになります。
解決策は、tellブロックでdocumentを指定するのをやめて、コマンドのパラメータとしてfront documentといったオブジェクトを表記することです。または、「属性値 of it」のようにdocumentへの参照を記述しておくことです(他の言語のユーザーが腰を抜かすので、なるべくitは使わないで記述していますが……)。
これで解決できるものの、macOS側で問題を起こしているのか、Pixelmator Pro側で問題を起こしているのかがわかりにくいところ。
おそらく、Pixelmator Pro側の問題かと思われますが、言い切ることもできないでしょう。
AppleScript名:アイコン書き出しv3.scptd |
— – Created by: Takaaki Naganoya – Created on: 2020/10/19 – Modified on: 2024/07/11 — – Copyright © 2020-2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions set resolList to {1024, 512, 256, 128, 64, 32, 16} set aTargFileBase to (choose file name with prompt "Select Export base name") as string tell application "Pixelmator Pro" if (exists of document 1) = false then display dialog "There is no document" buttons {"OK"} default button 1 with icon 1 return end if tell the front document set aWidth to width set aHeight to height end tell if {aWidth, aHeight} is not equal to {1024.0, 1024.0} then display dialog "Wrong Image Size (1024×1024 required)" buttons {"OK"} default button 1 with icon 2 with title "Size Error" return end if repeat with i in resolList resize image front document width i height i resolution 72 algorithm bilinear export front document to file (aTargFileBase & "_" & (i as string) & "x" & (i as string) & ".png") as PNG undo end repeat end tell |