Keynote、Pages、NumbersのiWork appsがバージョン14.3にアップデートしていました(気づかなかった)。
アップデート内容もたいしてありませんし、Apple Inteligenceを利用した機能なので、日本語環境では利用できません。
AppleScript用語辞書についても、とくに前バージョンから変更はありません。
Keynote、Pages、NumbersのiWork appsがバージョン14.3にアップデートしていました(気づかなかった)。
アップデート内容もたいしてありませんし、Apple Inteligenceを利用した機能なので、日本語環境では利用できません。
AppleScript用語辞書についても、とくに前バージョンから変更はありません。
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 |
指定フォルダ以下の画像(種別問わず)をすべてピックアップして、それぞれMD5チェックサムを計算し、重複しているものをピックアップしてデータとして出力するAppleScriptです。実行にはScript Debuggerを必要とします。内蔵のMD5計算Frameworkはx64/Apple Silicon(ARM64E)のUniversal Binaryでビルドしてあります。
–> –> Download photoDupLister(Script Bundle with Framework in its bundle)
# 本Scriptのファイル収集ルーチンが、再帰で下位フォルダの内容をすべてピックアップするものではありませんでした
# 実際に指定フォルダ以下すべての画像を収集する(Spotlightで)ようにしてみたら5.5万ファイルの処理に26分ほどかかりました
MD5チェックサムが同じということは、同じ画像である可能性が高いものです。
ここで、各画像のチェックサムを計算するさいに、サムネイルを生成してからチェックサムを計算するかどうかという話があります。
サムネイルを作成すべき派の言い分は、そのほうが計算量が減らせるし、同一画像の縮尺違い(拡大/縮小率違い)を求めることもできるというものです。
サムネイル作成否定派の言い分は、そんなもん作る前に画像のチェックサムを計算してしまえ、逆に手間だというものでした。
これは、どちらの意見ももっともだったので、実際にシミュレーションを行ってみるしかないでしょう。そこで、ありもののルーチンを集めて実際に作ってみたのが本Scriptです。サムネイルは作らないで処理してみました。
自分のMacBook Air M2のPicturesフォルダに入っていた約5,000の画像ファイルを処理したところ、16ペアの重複画像がみつかりました。処理にかかる時間はおよそ9秒です(実行するたびに所要時間が若干変化)。おそらく、Intel Macで実行すると数十秒から数分かかるのではないかと。
実用性を確保したい場合には、画像を回転しつつチェックサムを1画像あたり4パターン求めるとか、やはり同じサイズのサムネイル画像を生成してサムネイルに対してMD5チェックサムを計算するとか、画像の類似度を計算するオプションなども欲しいところです。
また、処理内容が並列処理向きなので、並列で処理してみてもよいでしょう。マシン環境を調べてSoCのPコアの個数をかぞえて、Pコアと同数の処理アプレットを生成して並列実行。……余計な処理を行うせいで速くならない可能性が高そうです。
| AppleScript名:指定フォルダ以下の画像のMD5チェックサムを求めて、重複しているものをピックアップ |
| — Created 2015-10-01 by Takaaki Naganoya — Modified 2015-10-01 by Shane Stanley–With Cocoa-Style Filtering — Modified 2018-12-01 by Takaaki Naganoya — Modified 2024-12-19 by Takaaki Naganoya use AppleScript version "2.8" use scripting additions use framework "Foundation" use framework "AppKit" use framework "md5Lib" –https://github.com/JoeKun/FileMD5Hash property |NSURL| : a reference to current application’s |NSURL| property NSArray : a reference to current application’s NSArray property NSPredicate : a reference to current application’s NSPredicate property NSCountedSet : a reference to current application’s NSCountedSet property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey script spd property fList : {} property fRes : {} property md5List : {} property fmdList : {} property dupRes : {} property outList : {} end script set anUTI to "public.image" set aFol to choose folder –set aFol to path to pictures folder set (fList of spd) to getFilePathList(aFol) of me –指定のFile listのうち画像のみ抽出 set (fRes of spd) to filterAliasListByUTI((fList of spd), "public.image") of me if (fRes of spd) = {} then return –すべての画像のMD5チェックサムを計算 set (md5List of spd) to {} set (fmdList of spd) to {} repeat with i in (fRes of spd) set j to contents of i set md5Res to (current application’s FileHash’s md5HashOfFileAtPath:(j)) as string set the end of (md5List of spd) to md5Res set the end of (fmdList of spd) to {filePath:j, md5:md5Res} end repeat –チェックサムが重複している画像を取り出す set fmdArray to NSArray’s arrayWithArray:(fmdList of spd) set (dupRes of spd) to returnDuplicatesOnly((md5List of spd)) of me set (outList of spd) to {} set procMDs to {} repeat with i in (dupRes of spd) set j to contents of i if j is not in procMDs then set aRes to filterDictArrayByLabel(fmdArray, "md5 == ’" & j & "’") of me set tmpMD5 to filePath of (first item of aRes) set tmpRes to {} repeat with ii in aRes set jj to contents of ii set the end of tmpRes to filePath of jj end repeat set aRec to {md5:j, fileRes:tmpRes} set the end of (outList of spd) to aRec set the end of procMDs to j end if end repeat return (outList of spd) –リストに入れたレコードを、指定の属性ラベルの値で抽出 on filterDictArrayByLabel(aArray, aPredicate as string) –抽出 set aPredicate to current application’s NSPredicate’s predicateWithFormat:aPredicate set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate –NSArrayからListに型変換して返す set bList to filteredArray as list return bList end filterDictArrayByLabel on getFilePathList(aFol) set aURL to current application’s |NSURL|’s fileURLWithPath:(POSIX path of aFol) set aFM to current application’s NSFileManager’s defaultManager() set urlArray to aFM’s contentsOfDirectoryAtURL:aURL includingPropertiesForKeys:{} options:(current application’s NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value) return urlArray as anything end getFilePathList –Alias listから指定UTIに含まれるものをPOSIX pathのリストで返す on filterAliasListByUTI(aList, targUTI) set newList to {} repeat with i in aList set j to POSIX path of i set tmpUTI to my retUTIfromPath(j) set utiRes to my filterUTIList({tmpUTI}, targUTI) if utiRes is not equal to {} then set the end of newList to j end if end repeat return newList end filterAliasListByUTI –指定のPOSIX pathのファイルのUTIを求める on retUTIfromPath(aPOSIXPath) set aURL to |NSURL|’s fileURLWithPath:aPOSIXPath set {theResult, theValue} to aURL’s getResourceValue:(reference) forKey:NSURLTypeIdentifierKey |error|:(missing value) if theResult = true then return theValue as string else return theResult end if end retUTIfromPath –UTIリストが指定UTIに含まれているかどうか演算を行う on filterUTIList(aUTIList, aUTIstr) set anArray to NSArray’s arrayWithArray:aUTIList set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr) set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list return bRes end filterUTIList on returnDuplicatesOnly(aList as list) set aSet to NSCountedSet’s alloc()’s initWithArray:aList set bList to (aSet’s allObjects()) as list set dupList to {} repeat with i in bList set aRes to (aSet’s countForObject:i) if aRes > 1 then set the end of dupList to (contents of i) end if end repeat return dupList end returnDuplicatesOnly |
md5、sha-1、sha-3などのチェックサムを計算するAppleScriptです。
AppleScript、といいつつ、これらの処理の主体はすべてObjective-Cで書かれたプログラム(を、Cocoa Framework化したもの)です。
この種類の、ファイルの内容をすべて加算して計算するような処理は、インタプリタ型言語であるAppleScriptは苦手な処理です。何か、頭を使って処理量を減らすような工夫が通じません。
その結果、これらのScriptはScript Debugger上か、Script Debuggerから書き出したEnhanced Applet、その他のFramework呼び出しをサポートしているいくつかのAppleScript実行環境でしか実行できません。
Xcodeを用いてGUIなしヘルパーアプリを作って、他のAppleScript実行環境から呼び出しやすいようにSDEFを介して動かすようにすることも可能ですが、フリーで配布するほどの何かがあるわけでもありません。
なので、現状はこのままです。これらすべてのFrameworkを各ユーザー環境の~/Library/Frameworksフォルダにインストールして使用してください。x64/ARM64EのUniversal Binaryでビルドしてあります。
–> Download md5Lib.framework(To ~/Libraries/Frameworks)
–> Download md5FromDataKit.framework(To ~/Libraries/Frameworks)
–> Download SHA3Kit.framework(To ~/Libraries/Frameworks)
| AppleScript名:ファイルのMD5、SHA1、SHA512のハッシュ値を求める |
| — Created 2016-02-11 by Takaaki Naganoya — 2016 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "md5Lib" –https://github.com/JoeKun/FileMD5Hash set aPath to POSIX path of (choose file) set a to (current application’s FileHash’s md5HashOfFileAtPath:aPath) as string –> "329e854b9993405414c66faac0e80b86" set b to (current application’s FileHash’s sha1HashOfFileAtPath:aPath) as string –> "50847286df61f304d142c6a0351e39029f010fc2" set c to (current application’s FileHash’s sha512HashOfFileAtPath:aPath) as string –> "5132a7b477652db414521b36……..1a6ff240e861752c" return {a, b, c} |
| AppleScript名:NSStringからSHA-3のハッシュ値を求める |
| — Created 2017-08-09 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "SHA3Kit" –https://github.com/jaeggerr/NSString-SHA3 set origData to (current application’s NSString’s stringWithString:"hello") set aHash1 to (origData’s sha3:256) as string –> "1C8AFF950685C2ED4BC3174F3472287B56D9517B9C948127319A09A7A36DEAC8" set aHash2 to (origData’s sha3:224) as string set aHash3 to (origData’s sha3:384) as string set aHash4 to (origData’s sha3:512) as string |
| AppleScript名:NSDataからMD5値を計算する |
| — Created 2016-02-11 by Takaaki Naganoya — 2016 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "md5FromDataKit" –https://github.com/siuying/NSData-MD5 set aStr to "ぴよまるソフトウェア" set aNSStr to current application’s NSString’s stringWithString:aStr set aData to aNSStr’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set aMD5Hex to (current application’s NSData’s MD5HexDigest:aData) as string –> "2d0b4e205f274f20b17dc8ca4870f1db" set aMD5 to (current application’s NSData’s MD5Digest:aData)’s |description|() as string –> <2d0b4e20 5f274f20 b17dc8ca 4870f1db> |
2024年に使用していたmacOS:macOS 13+macOS 15
毎年行なっている、Piyomaru Softwareが書いたAppleScriptの1年を振り返る記事の2024年版です。
2008年から10年ほど運営を続けてきた旧「AppleScriptの穴」Blogが2018年の年初にホスティング会社との行き違いでシャットダウンされ、ゼロから再構築したのがこの現行の「AppleScriptの穴」Blogです。
→ 2018年に書いた価値あるAppleScript
→ 2019年に書いた価値あるAppleScript
→ 2020年に書いた価値あるAppleScript
→ 2021年に書いた価値あるAppleScript
→ 2022年に書いた価値あるAppleScript
→ 2023年に書いた価値あるAppleScript
旧「AppleScriptの穴」Blogの内容については、データベースから抜き出したデータをもとに再構成した「Blogアーカイブ本」にまとめています。
AppleScriptの穴Blogアーカイブvol.1
AppleScriptの穴Blogアーカイブvol.2
AppleScriptの穴Blogアーカイブvol.3
AppleScriptの穴Blogアーカイブvol.4
AppleScriptの穴Blogアーカイブvol.5
AppleScriptの穴Blogアーカイブvol.6
本Blogは、もともとは、2000年代初頭に開発していた「人工知能インタフェース Newt On」のソースコード部品バラバラにして掲載し、用いた部品を個別にメンテナンスすることを「隠れた目的」としていました。また、Scripter間のノウハウの共有を推進することも目的としています。
AppleScript以外の一般的なテーマの記事については、こちらにいろいろ投稿しています。
前述のとおり、2018年1月にいちど本Blogは消えていました。その際に、「本Blogが存在しない場合にはどのような現象が起こるのか」を観察。その結果、AppleScriptについて知識を持たない人たちが好き勝手に「嘘」を流布しはじめる、という現象が観測されました。本Blogはそうした「嘘つき」を封じ込めるためのキーストーンとしての役割を果たしているといえます。
本Blogを公開しているだけでは、ホスティング費用やドメイン費用がかかるだけで、何も収益が生まれません。そこで、本Blog+αの情報を整理してまとめた電子書籍を発行しています。本Blog読者のみなさまにおかれては、電子書籍を購入することで本Blog運営を支えていただけますと幸いです。
電子書籍の2024年における刊行は、現時点で95冊。年間8冊となっています。
Cocoa Scripting Course #7 NSColor
Cocoa Scripting Course #8 File path Processing
Cocoa Scripting Course #9 File Processing
AppleScriptでたのしむ レトロ・グラフィックス プログラム集
Pages+AppleScriptで本をつくろう!
AppleScript基礎テクニック集(32)複数のアプリをコントロール
AppleScript基礎テクニック集(33)選択中のオブジェクト取得
AppleScript 基礎テクニック集(34)電源制御
目下、既刊本の最新環境へのアップデートを実行中です。
余白トリミング実験 v3
2024年に書いたScriptのうちで一番気合いが入っているのが、この画像の余白トリミングです。AppleScriptでそんな画像処理ができるとは思ってもいませんでしたが、実際にやってみたらそれなりに機能して、それなりの速度で動きました。
Outline View Lib
NSOutlineViewを手軽に使えるライブラリです。他のアプリで作った階層データ(Keynoteのマスターページ名など)をプレビューするなどの用途に使えます。
書式つきテキストを組み立てて、画像を追加し、RTFDとして保存 v2
電子書籍用にまとめていたScriptの中のひとつです。RTFDの新規保存については書いたことがなかったので、「書いておいたほうがよいだろう」と。同様にScptd(バンドル形式AppleScript)の作成Scriptも書いておきたいところ&scptdの実行Script(Script Viewを自前で作成して)も書いておきたいところですが、公表されているAPIの範囲では実行できるものが見当たりません。
アラートダイアログ上にWebViewで3Dコンテンツを表示(WebGL+three.js)v4
これも、ずいぶん前に試作品を見ていたのですが、前バージョンが動かなくなって久しかったのでアップデートしておきました。あくまで、デモ用で実用性が皆無ですが、そういうものなんでしょう。
Pagesで、現在表示中のページから離れたページのオブジェクト情報を取得できない
Pagesが怪奇現象を起こすことについては、ずいぶん前から知っていたのですが、その発生条件と範囲を明確にできたことは意義深いことです。
指定のSDEFファイルからコマンドを抽出
SDEF処理系AppleScriptはいろいろ組んでいますが、電子書籍作成時にアプリのアップデート履歴を表で示すためにこうしたScriptが必要です。
Chat GPTに書かせたQuickSort(昇順・降順ソート)2D
ChatGPTに書かせたAppleScriptです。バージョン依存しなかったり、他の言語で書いてあるものを翻訳するようなScriptだと割とまともなAppleScriptを出力してくれます。ただし、高速化の余地があるレベルの(遅い)Scriptだったので、自前で高速化してみました。
Excel__Numbersセルアドレスの相互変換
ChatGPTに書かせたAppleScriptです。こちらも、OSのバージョンに依存せず、他の言語でも書ける内容だったので、問題なく処理できるScriptが出力されました。
NaturalLanguage.frameworkのごくごく入門的なオブジェクト「NLEmbedding」を利用できるか、各言語でチェックを行ったところ、macOS 13、14で予想外の結果が返ってきた内容をmacOS 15で再確認してみました。
ラテン系言語を中心に中国語がサポートされているあたりがあまりにも特徴的なNaturalLanguage.framework。多くの機能を日本語で利用できないことは分かりきっていたのですが、macOS 14で対応言語が激減。このまま廃止されるのかと驚いていたのですが、macOS 15で復旧していました。
どうしてmacOS 14.x台で復旧していなかったのか。ひたすら不思議です。
| AppleScript名:指定言語でNLEmbeddingを処理できるかチェック_13_14_15.scpt |
| — – Created by: Takaaki Naganoya – Created on: 2024/03/13 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.8" use framework "Foundation" use framework "NaturalLanguage" use scripting additions –The result is on macOS 13.6.5 / 14.4 / 15.2 set aRes to testNLLanguage("NLLanguageEnglish") of me –> true–> true –true set aRes to testNLLanguage("NLLanguageFrench") of me –> true–>false (macOS 14)—> true set aRes to testNLLanguage("NLLanguageGerman") of me –> true–>false (macOS 14)–> true set aRes to testNLLanguage("NLLanguageItalian") of me –> true–>false (macOS 14)–> true set aRes to testNLLanguage("NLLanguagePortuguese") of me –> true–>false (macOS 14)–> true set aRes to testNLLanguage("NLLanguageSimplifiedChinese") of me –> true–>false (macOS 14)–> true set aRes to testNLLanguage("NLLanguageSpanish") of me –> true–>false (macOS 14)–> true set aRes to testNLLanguage("NLLanguageUndetermined") of me –> true –>Natural Language framework doesn’t recognize(macOS 14).–> true –macOS 14.7.2で再確認したところtrueに set aRes to testNLLanguage("NLLanguageAmharic") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageArabic") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageArmenian") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageBengali") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageBulgarian") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageBurmese") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageCatalan") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageCherokee") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageCroatian") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageCzech") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageDanish") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageDutch") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageFinnish") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageGeorgian") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageGreek") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageGujarati") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageHebrew") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageHindi") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageHungarian") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageIcelandic") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageIndonesian") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageJapanese") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageKannada") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageKazakh") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageKhmer") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageKorean") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageLao") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageMalay") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageMalayalam") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageMarathi") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageMongolian") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageNorwegian") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageOriya") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguagePersian") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguagePolish") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguagePunjabi") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageRomanian") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageRussian") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageSinhalese") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageSlovak") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageSwedish") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageTamil") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageTelugu") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageThai") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageTibetan") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageTraditionalChinese") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageTurkish") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageUkrainian") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageUrdu") of me –> false–> false–> false set aRes to testNLLanguage("NLLanguageVietnamese") of me –> false–> false–> false on testNLLanguage(aLangName) set aText to "use AppleScript use framework \"Foundation\" use framework \"NaturalLanguage\" set targLang to (current application’s " & aLangName & ") set aEmb to current application’s NLEmbedding’s wordEmbeddingForLanguage:(targLang) if aEmb = missing value then return false return true " return run script aText end testNLLanguage |
AppKit系のオブジェクトで最難関との呼び声も高い、NSOutlineViewをAppleScriptから呼び出しやすく機能をまとめたものです。
edama2さんと数年前に「Outline Viewがどうにかならないものか」と相談し、まとめていただいたものです。本当はもっとシンプルに書いてあったのですが、データを外部から指定できるようにしたり、デフォルト状態でNSOutlineViewを展開状態で表示する機能を追加したり、行ごとの背景色を変更できるようにしたり……と、機能が増えました。
本UIをAppleScript上で利用する用途は、データ選択や階層データのプレビュー(PDFのTOCなど)などです。
NSTreeControllerの使い方だったり、Cocoa Bindingをプログラマティックに実行していたりと、そのあたりが見どころでしょう。
スクリプトエディタとScript Debuggerの両方で動作確認していますし、スクリプトメニュー上で動作しています。
CotEditorの内蔵スクリプトメニューに入れたところ最前面にダイアログ表示されませんでした。
| AppleScript名:Outline View Lib.scpt |
| — – Created by: edama2 & Piyomaru – Created on: 2024/12/16 — – Copyright © 2024 edama2 & Piyomaru, All Rights Reserved — use AppleScript use framework "Cocoa" property dRes : missing value –Selection property _data_source : missing value set aRecord to {} set aRecord’s end to {|name|:"🟥 格闘機", isLeaf:false, children:{{|name|:"RGM-79(G)陸戦型ジム", isLeaf:true}, {|name|:"RB-79KボールK型", isLeaf:true}, {|name|:"RGM-79Lジム・ライトアーマー", isLeaf:true}, {|name|:"RGM-79ジム(指揮官機)", isLeaf:true}, {|name|:"RGM-79FPジム・ストライカー", isLeaf:true}, {|name|:"RGM-79Vジム・ナイトシーカー", isLeaf:true}, {|name|:"RX-77-3ガンキャノン重装型", isLeaf:true}, {|name|:"RX-78XXピクシー", isLeaf:true}}} set aRecord’s end to {|name|:"🟧 近距離機", isLeaf:false, children:{{|name|:"RGM-79ジム", isLeaf:true}, {|name|:"TGM-79ジム・トレーナー", isLeaf:true}, {|name|:"RAG-79アクア・ジム", isLeaf:true}, {|name|:"RGM-79ジム(WD隊)", isLeaf:true}, {|name|:"MS-06F-2ザクII(F2)", isLeaf:true}}} set aRecord’s end to {|name|:"🟩 射撃型機", isLeaf:false, children:{{|name|:"RGC-80Sジム・キャノン(空間突撃仕様)", isLeaf:true}, {|name|:"RGM-79Fデザート・ジム", isLeaf:true}, {|name|:"RX-79(G)陸戦型ガンダム(ジム頭)", isLeaf:true}}} set aRecord’s end to {|name|:"🟪 支援型機", isLeaf:false, children:{{|name|:"RGM-79SCジム・スナイパーカスタム", isLeaf:true}, {|name|:"RGM-79SCジム・スナイパーカスタム(SP)", isLeaf:true}, {|name|:"RX-77-2ガンキャノン", isLeaf:true}, {|name|:"RGM-79SPジム・スナイパーII", isLeaf:true}, {|name|:"FA-78-2ヘビーガンダム", isLeaf:true}, {|name|:"FA-78-1フルアーマーガンダム", isLeaf:true}}} set aRecord’s end to {|name|:"🟦 遠距離型機", isLeaf:false, children:{{|name|:"RB-79ボール", isLeaf:true}, {|name|:"RGM-79(G)ジム・スナイパー", isLeaf:true}, {|name|:"RGC-80ジム・キャノン", isLeaf:true}, {|name|:"RX-75量産型ガンタンク", isLeaf:true}, {|name|:"RGC-80ジム・キャノン(WD隊)", isLeaf:true}, {|name|:"RTX-440陸戦強襲型ガンタンク", isLeaf:true}, {|name|:"RX-75ガンタンク", isLeaf:true}, {|name|:"RX-77D量産型ガンキャノン", isLeaf:true}, {|name|:"FA-78-1Bフルアーマーガンダム(TYPE-B)", isLeaf:true}}} set mainMes to "戦場の絆MS選択" set subMes to "以下のリストから希望の機体を選択してください" set aRes to displayOutline(aRecord, mainMes, subMes, true, 400, 700) of me on displayOutline(treeData, messageText, informativeText, isExpand, aWidth, aHeight) set (my _data_source) to missing value –init set paramObj to {treeData:treeData, messageText:messageText, informativeText:informativeText, isExpand:isExpand, aWidth:aWidth, aHeight:aHeight} my performSelectorOnMainThread:"raizeAlert:" withObject:(paramObj) waitUntilDone:true return dRes end displayOutline on raizeAlert:paramObj –Initialize return value set dRes to missing value –Recieve Parameters set treeData to (treeData of paramObj) as list set messageText to (messageText of paramObj) set informativeText to (informativeText of paramObj) set isExpand to (isExpand of paramObj) as boolean set aWidth to (aWidth of paramObj) as integer set aHeight to (aHeight of paramObj) as integer –Make Accessory View set accessoryView to makeAccessoryView(treeData, isExpand, aWidth, aHeight) of me tell current application’s NSAlert’s new() current application’s NSApplication’s sharedApplication()’s setActivationPolicy:(current application’s NSApplicationActivationPolicyRegular) current application’s NSApp’s activateIgnoringOtherApps:(true) setMessageText_(messageText) setInformativeText_(informativeText) setAccessoryView_(accessoryView) runModal() end tell set selectedObject to (my _data_source)’s selectedObjects()’s firstObject() set dRes to {selectedObjects:selectedObject as {record, anything}} end raizeAlert: on makeAccessoryView(treeData as list, isExpand as boolean, aWidth as integer, aHeight as integer) set my _data_source to current application’s NSTreeController’s alloc()’s initWithContent:treeData (my _data_source)’s setChildrenKeyPath:"children" (my _data_source)’s setLeafKeyPath:"isLeaf" set scrollView to (current application’s NSScrollView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight))) tell (current application’s NSOutlineView’s alloc()’s initWithFrame:(current application’s NSZeroRect)) addTableColumn_(current application’s NSTableColumn’s alloc()’s initWithIdentifier:"name") bind_toObject_withKeyPath_options_(current application’s NSContentBinding, (my _data_source), "arrangedObjects", missing value) bind_toObject_withKeyPath_options_(current application’s NSSelectionIndexPathsBinding, (my _data_source), current application’s NSSelectionIndexPathsBinding, {}) expandItem_expandChildren_(missing value, isExpand) scrollView’s setDocumentView:it setHeaderView_(missing value) setOutlineTableColumn_(tableColumns()’s firstObject()) setUsesAlternatingRowBackgroundColors_(true) tell tableColumns()’s firstObject() bind_toObject_withKeyPath_options_(current application’s NSValueBinding, (my _data_source), ("arrangedObjects." & its identifier()), missing value) setTitle_(its identifier()) setWidth_(current application’s NSWidth(tableView()’s superview()’s |bounds|())) end tell end tell return scrollView end makeAccessoryView |
3年ぐらい前に書いてあった、Mac本体にペアリングして接続しているBluetoothのデバイス名を取得するAppleScriptです。
| AppleScript名:Bluetoothに接続中のデバイス名を取得するv6.scptd |
| — – Created by: Takaaki Naganoya – Created on: 2024/12/13 — – Copyright © 2024 Piyomaru Software, All Rights Reserved — use AppleScript version "2.8" use scripting additions use framework "Foundation" use framework "IOBluetooth" set pRes to getBluetoothPowerState() of me if pRes = false then return set dArray to current application’s IOBluetoothDevice’s pairedDevices() set dRes to my filterRecListByLabel1(dArray, "isConnected != 0") set dNameList to (dRes’s valueForKeyPath:"name") as list –> {"Logicool Z600", "Takaaki Naganoya のキーボード #1", "Takaaki Naganoya のマウス"} –> {"Logicool Z600", "AirPods Pro", "DUALSHOCK 4 Wireless Controller"} –リストに入れたレコードを、指定の属性ラベルの値で抽出 on filterRecListByLabel1(aRecList, aPredicate as string) set aArray to current application’s NSArray’s arrayWithArray:aRecList set aPredicate to current application’s NSPredicate’s predicateWithFormat:aPredicate set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate return filteredArray end filterRecListByLabel1 –Mac本体のBluetoothのパワー状態を取得 on getBluetoothPowerState() set aCon to current application’s IOBluetoothHostController’s alloc()’s init() set pRes to (aCon’s powerState()) as boolean end getBluetoothPowerState |
オープンソースのPDFリーダー「Skim」のバージョン1.7.6において「open location」コマンドが実装されましたが、実際に試してみると動きません。確認は最新版の1.7.7で行いました。
これまでにも追加したコマンドを次のバージョンで廃止して、翌々バージョンで復活させたりと、いろいろその歴史をひもとくと「おっとっと」な動きが見られるので、そういうものなんでしょう。
本Blog上に存在するPDFのURLを指定。open locationでダウンロード+表示を試みるものの、表示されずにエラーになる。
→ Skimが「http://」をサポートしていないとのこと。https://からのダウンロードおよび表示は確認しました。
| AppleScript名:Skim v17.6で追加されたopen locationのテスト.scpt |
| set aURL to "http://piyocast.com/as/wp-content/uploads/2018/09/GUNDAM-UI.pdf"
tell application "Skim" set erRes to (open location aURL with error reporting) end tell |
新刊電子書籍「AppleScript基礎テクニック(34)電源制御」を刊行しました。全57ページ、サンプルAppleScriptアーカイブつき。Piyomaru Softwareによる電子書籍の95冊目です。
→ 販売ページ
ちょっとAppleScriptを書けるようになった方が、必要に感じてふりかえる「基礎」的な内容をプレゼン資料風に絵でご紹介する「AppleScript基礎テクニック集」の34冊目、Macの電源制御に関する1冊です。 スリープ、シャットダウン、スリープ解除日時指定、バッテリー残量取得、電源種別の判定など、電源制御系の機能は、AppleScriptに添える「気の利いた」スパイス。知っておくと役立つ、実際に動かすと楽しい電源制御機能について、詳細にご紹介します。 いまはMacBook Airで1日中バッテリーで駆動できるのでシビアな計算が必要な場面は減ったように感じますが、それでもバッテリー残量を取得する処理はAppleScriptでも欠かせません。電源制御は使って動かすと面白い処理です。
■最初に:macOS 13以降では最初にステージマネージャを必ずオフにしてください
macOS 13.x
macOS 14.x
macOS 15.x
その他、オフにすることが望ましい機能
■電源制御 関連機能
macOSの各種電源コントロール機能
AppleScriptからスリープ実行
指定日時にスリープ解除
電源種別判定
バッテリー残量データ取得
■スリープ
2つのスリープ処理
スリープ処理
ディスプレイ消灯処理
■スリープ解除
スリープ解除(スケジュール登録)
スリープ解除日時設定のAppleScript①〜③
■スリープ解除検出
スリープ解除検出、2つの方法
一番単純なスリープ解除検出
システム通知を利用したスリープ解除検出①〜③
■電源オフ
電源オフは2コース
■電源種別判定
電源種別判定
■Mac本体のバッテリー残量取得
バッテリー情報を取得する前に
デスクトップ機とノート機の区別①〜③
取得できるMac本体のバッテリー仕様
Mac本体のバッテリー残量を取得
■その他資料
ログアウト処理
再起動
CPU種別判定
CPU動作クロック取得
Apple Siliconの各種温度センサーの値を取得①〜③
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 |
アラートダイアログ上にWkWebViewを作成して、さまざまなグラフや3Dアニメーションを表示してきた「箱庭ダイアログ」の1つの到達点、「periodictable」(元素周期表)選択UIの表示デモAppleScriptです。
実行は掲載リストではなく上記のリンクからダウンロードしたAppleScriptバンドルを、かならずスクリプトエディタでオープンして(Script Debugger不可)、Controlキーを押しながらスクリプトエディタの「スクリプト」メニューから「フォアグラウンドで実行」コマンドで実行してください。
「フォアグラウンド」はApple(の外注のローカライズ業者による)ローカライズ内容が間違っていて、実際には「メインスレッドで実行」が正しいのですが、まあいいです。
以前に掲載したバージョン(v3)は、掲載後しばらくはそのまま動いていることが確認されたのですが、その後のCDN上のJavaScriptライブラリのアップデートにともない、動作しなくなっていました。本v4はその点を解決したもので、技術的により進化したというよりも、「勝手に動かなくなる点に対処した」程度のものとお考えください。
periodictableのUser Interface自体、目を惹くものであり、とても楽しいものです。ただ、真剣にその内容を解析し、汎用的に利用できるかどうかを検討してみると、おおよそ120個程度の要素に対して、重みづけを与えずに自由選択するような用途でないと実用性が得られないことがわかりました。たいてい、情報には重要度などの重みがありますが、本User Interfaceはそれがあると邪魔な感じです。
また、少ないデータ……2個や3個の要素から選択するのでは、用をなしません。用途が限定されすぎているというべきなのか、この用途にしか合わないというべきなのか。
JavaScriptとAppleScriptの間での選択項目のやり取りを行う手段についても、edama2氏が実際に稼働するデモを作ったのを見せてもらい、たしかにそうした処理ができることを確認しています。
それでも、いまひとつ実用性がないので、あくまで本プログラムは「デモ用」と割り切っています。
「CDN上のJavaScriptライブラリがアップデートして動かなくなる問題」についても、1つの解決策が見えてきました。ローカルにJavaScriptライブラリを配置して読み込んで使えばいいというものです。実際に、本ScriptバンドルのResourceフォルダ内にそれらのファイルが入っています。
これで勝手にアップデートされないため、放っておくと動かなくなるといった問題への解決策となっています。ただ、その一方でメイン処理を呼び出すさいに強制的なメインスレッド実行を行わせても、実行できないという謎の現象が発生。これについては、問題解決の手段自体はあるはずです(たぶん)。
| AppleScript名:アラートダイアログ上にWebViewで3Dコンテンツを表示(WebGL+three.js)v4.scptd |
| — – Created by: Takaaki Naganoya – Created on: 2020/06/13 – Modified on: 2023/03/07 — – Copyright © 2020-2023 Piyomaru Software, All Rights Reserved — use AppleScript version "2.7" use framework "Foundation" use framework "AppKit" use framework "WebKit" use scripting additions property |NSURL| : a reference to current application’s |NSURL| property NSAlert : a reference to current application’s NSAlert property NSString : a reference to current application’s NSString property NSButton : a reference to current application’s NSButton property WKWebView : a reference to current application’s WKWebView property WKUserScript : a reference to current application’s WKUserScript property NSURLRequest : a reference to current application’s NSURLRequest property NSRunningApplication : a reference to current application’s NSRunningApplication property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding property WKUserContentController : a reference to current application’s WKUserContentController property WKWebViewConfiguration : a reference to current application’s WKWebViewConfiguration property WKUserScriptInjectionTimeAtDocumentEnd : a reference to current application’s WKUserScriptInjectionTimeAtDocumentEnd property returnCode : 0 on run –https://www.cresco.co.jp/blog/entry/7427/ — By sgi-chang @ UX Design Center set myStr to (POSIX path of (path to me)) & "/Contents/Resources/index.html" set paramObj to {myMessage:"WebGL & three.js Test", mySubMessage:"This is a WebGL UI using three.js", htmlPath:myStr} my browseFileWebContents:paramObj –for debug –my performSelectorOnMainThread:"browseFileWebContents:" withObject:(paramObj) waitUntilDone:true end run on browseFileWebContents:paramObj set aMainMes to myMessage of paramObj set aSubMes to mySubMessage of paramObj set htmlPathStr to (htmlPath of paramObj) set aWidth to 1600 set aHeight to 900 –WebViewをつくる set aConf to WKWebViewConfiguration’s alloc()’s init() –指定HTML内のJavaScriptをFetch tell current application set htmlString to read ((POSIX file htmlPathStr) as alias) as «class utf8» end tell set jsSource to pickUpFromToStr(htmlString, "<script src", "</script>") of me set userScript to WKUserScript’s alloc()’s initWithSource:jsSource injectionTime:(WKUserScriptInjectionTimeAtDocumentEnd) forMainFrameOnly:true set userContentController to WKUserContentController’s alloc()’s init() userContentController’s addUserScript:(userScript) aConf’s setUserContentController:userContentController set aWebView to WKWebView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight)) configuration:aConf aWebView’s setNavigationDelegate:me aWebView’s setUIDelegate:me aWebView’s setTranslatesAutoresizingMaskIntoConstraints:true using terms from scripting additions set bURL to |NSURL|’s fileURLWithPath:(POSIX path of (path to me)) end using terms from set htmlURL to current application’s |NSURL|’s fileURLWithPath:htmlPathStr aWebView’s loadFileURL:(htmlURL) allowingReadAccessToURL:(bURL) — set up alert set theAlert to NSAlert’s alloc()’s init() tell theAlert its setMessageText:aMainMes its setInformativeText:aSubMes its addButtonWithTitle:"OK" –its addButtonWithTitle:"Cancel" its setAccessoryView:aWebView set myWindow to its |window| end tell — show alert in modal loop NSRunningApplication’s currentApplication()’s activateWithOptions:0 my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true –Stop Web View Action set bURL to |NSURL|’s URLWithString:"about:blank" set bReq to NSURLRequest’s requestWithURL:bURL aWebView’s loadRequest:bReq if (my returnCode as number) = 1001 then error number -128 end browseFileWebContents: on doModal:aParam set (my returnCode) to (aParam’s runModal()) as number end doModal: on viewDidLoad:aNotification return true end viewDidLoad: on fetchJSSourceString(aURL) set jsURL to |NSURL|’s URLWithString:aURL set jsSourceString to NSString’s stringWithContentsOfURL:jsURL encoding:(NSUTF8StringEncoding) |error|:(missing value) return jsSourceString end fetchJSSourceString on pickUpFromToStr(aStr as string, s1Str as string, s2Str as string) set a1Offset to offset of s1Str in aStr if a1Offset = 0 then return false set bStr to text (a1Offset + (length of s1Str)) thru -1 of aStr set a2Offset to offset of s2Str in bStr if a2Offset = 0 then return false set cStr to text 1 thru (a2Offset – (length of s2Str)) of bStr return cStr as string end pickUpFromToStr –リストを任意のデリミタ付きでテキストに on retArrowText(aList, aDelim) set aText to "" set curDelim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to aDelim set aText to aList as text set AppleScript’s text item delimiters to curDelim return aText end retArrowText on array2DToJSONArray(aList) set anArray to current application’s NSMutableArray’s arrayWithArray:aList set jsonData to current application’s NSJSONSerialization’s dataWithJSONObject:anArray options:(0 as integer) |error|:(missing value) –0 is set resString to current application’s NSString’s alloc()’s initWithData:jsonData encoding:(current application’s NSUTF8StringEncoding) return resString end array2DToJSONArray on parseByDelim(aData, aDelim) set curDelim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to aDelim set dList to text items of aData set AppleScript’s text item delimiters to curDelim return dList end parseByDelim |
Microsoft Excelで、指定画像を指定セルに貼り込むAppleScriptです。指定セルの座標を求めて、そこを左上の位置として画像を貼り込みます。
本Scriptで、セルアドレスの指定時に「B4」などとアルファベット大文字で指定してください。英小文字で指定するとエラーになります(以後のバージョンでは、ignoring caseで判断部分を囲って対処しています)。
| AppleScript名:指定セルに指定画像を貼り込む.scpt |
| — – Created by: Takaaki Naganoya – Created on: 2024/12/05 — – 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 "A2" 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 aPicShape to make new shape at the beginning set width of aPicShape to (overlaySize’s |width|) set height of aPicShape to (overlaySize’s |height|) set top of aPicShape to targCellY set left position of aPicShape to targCellX user picture of aPicShape picture file anImagePOSIX 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 |
2D List(2次元配列)のソートルーチンをChatGPTに書かせてみました。1,000項目のソートで0.6秒(MacBook Air M2)、10,000項目のソートで329秒(MacBook Air M2)。
そのままでは使い物にならないので、listの持ち方を変えて高速化対応を行い、10,000項目のソートで0.32秒まで速くなりました。
Cocoaの機能を利用して10,000項目の2D Listソートすると、0.08秒ほど(MacBook Air M2)でしたが、Cocoaでソートする場合にはList中にアプリケーションのオブジェクト情報を入れられないので、Vanilla Scriptのソートルーチンもそれなりに高速なものをそろえておく必要があります。
ChatGPTにソートルーチンを書かせてみたら、AppleScriptのListは遅いとか言い訳をしだしたので、「こうしたら速くなるよ、100倍ぐらい」と言い返したら、少しマシな内容を返してきました。人間だと思って相手をすると腹が立ちますが、人間だと思わず、あらかじめ正解を知っていればそちらに誘導するぐらいはできそうです。
| AppleScript名:Chat GPTに書かせたQuickSort(昇順・降順ソート_高速化改造版)2D.scpt |
| use AppleScript use scripting additions use framework "Foundation" script spd property aList : {} end script set (aList of spd) to {} repeat 10000 times set end of (aList of spd) to {(random number 1000 from 1 to 9999), (random number 1000 from 1 to 9999)} end repeat –昇順ソート set a1Dat to current application’s NSDate’s timeIntervalSinceReferenceDate() set sortedList to quickSort2DArray((aList of spd), 2, true) –ソート set b1Dat to current application’s NSDate’s timeIntervalSinceReferenceDate() set c1Dat to b1Dat – a1Dat –降順ソート set a2Dat to current application’s NSDate’s timeIntervalSinceReferenceDate() set sortedList to quickSort2DArray((aList of spd), 2, false) –ソート set b2Dat to current application’s NSDate’s timeIntervalSinceReferenceDate() set c2Dat to b2Dat – a2Dat display dialog (c1Dat as number as text) & return & (c2Dat as number as text) –> 0.01 sec @MacBook Air M2 (1,000 items) –> 0.32 sec @MacBook Air M2 (10,000 items) return {c1Dat, c2Dat} — クイックソートの関数(高速化対応版) on quickSort2DArray(array2D, columnIndex, ascendingOrder) script oBj property list : array2D property lessList : {} property greaterList : {} end script if (length of (oBj’s list)) ≤ 1 then return (oBj’s list) — 要素が1つ以下の場合はそのまま返す else — ピボットを選択(最初の要素を基準) set pivot to item 1 of (oBj’s list) set pivotValue to item columnIndex of pivot — ピボットより小さい要素のリスト set (oBj’s lessList) to {} — ピボット以上の要素のリスト set (oBj’s greaterList) to {} repeat with i from 2 to length of (oBj’s list) — ピボットを除いたリストを処理 set currentItem to item i of (oBj’s list) set currentValue to item columnIndex of currentItem — 昇順または降順で分岐 if (ascendingOrder and currentValue ≤ pivotValue) or ((not ascendingOrder) and currentValue ≥ pivotValue) then set end of (oBj’s lessList) to currentItem else set end of (oBj’s greaterList) to currentItem end if end repeat — 再帰的にソートして結合 return (quickSort2DArray((oBj’s lessList), columnIndex, ascendingOrder) & {pivot} & quickSort2DArray((oBj’s greaterList), columnIndex, ascendingOrder)) end if end quickSort2DArray |
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 |
ExcelやNumbersで使われているセルのアドレス表記方法「A1形式」と数値の相互変換を行うAppleScriptです。
一応、自分でも昔に書いたルーチンを使い回していますが、26進数と10進数との間の変換で桁が増えたときの処理に難があって、上限値を設けてその間であれば変換できる、という感じになっていました。
もともと、このルーチンはExcel 2008でVBAの処理系を搭載しないことになったのを好機ととらえ、AppleScriptをエンコードしてExcelの隠しワークシート上に格納しておいて外部から実行する「ExcelAS」プロジェクトのために作成したものです。
実際に調布のMicrosoftでデモを行なって、US Microsoftに掛け合ってもらったものの、次バージョンでVBAの処理系を復活させることになって、(Visual BASIC互換の)「REALbasic」のエンジンを書いていたエンジニアをMSがヘッドハント。常識的に考えればVBAの廃止自体がおかしな決定だったので、その隙を狙えるかも? と企画して作ったものの、残念な結果になってしまいました。ただ、現在に至るもMac上のVBAの処理系、とくにエディタは作りが残念(Retina解像度に合ってないとか、日本語入力できないとか、フォームが使えないとか)なので、もうちょっとなんとかならないものかと思ってしまいます。
話をアドレス変換ルーチンに戻しましょう。実際に、そんなに大きな値の相互変換はしていないので問題視していませんでしたが、変換ルーチンに上限値のしばりがあるのはうっとおしいとは思っていました。ただ、ExcelASプロジェクトの頓挫により、アドレス変換処理を書き換えるほどのインセンティブがなかったので、ながらく放置状態に。
そこで、定期的に行なっているChatGPTによるAppleScript記述実用性チェックの「お題」としてこのセルアドレスの相互変換を行わせてみました。
ちゃんと動いているように見えます。こういうデータ変換系のプログラムは、割とChatGPTで書かせるのは「アリ」だと思います。本ルーチンの注意点は、Excelアドレス(カラム名指定)はアルファベット大文字で記述する必要があるということです。小文字のアルファベットで記述すると本バージョンではエラーになります。
ただ、アプリケーションの詳細なコントロールを行わせると、首をひねってしまうような書き方を返してきます。
| AppleScript名:Excel__Numbersセルアドレスの相互変換.scpt |
| — 数値 → A1形式 set result1 to numberToCell(2024, 5) — "BYV5" display dialog "Number to Cell: " & result1 — A1形式 → 数値 set result2 to cellToNumber("BYV5") — {2024, 5} display dialog "Cell to Number: Column: " & item 1 of result2 & ", Row: " & item 2 of result2 — 数値からセルアドレス(A1形式)への変換 on numberToCell(columnNumber, rowNumber) 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 & rowNumber 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 set columnNumber to columnNumber * 26 + (offset of char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ") end repeat — 数値を返す return {columnNumber, (rowPart as integer)} end cellToNumber |
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 |