Keynote書類上でタイトルと(ボックスの領域が)重なるテキスト、および文字サイズが指定サイズと同じテキストを抽出してまとめるAppleScriptを書いてみました。Keynoteで作成した電子書籍の目次データ確認のためのものです。
実行はmacOS 15.5+Keynote v14.4上で行いましたが、とくにバージョン依存している箇所はないので、異なるバージョンであっても使えるはずです。分析対象の書類をKeynoteでオープンした状態で、解析対象のスライド(複数)を選択した状態でスクリプトエディタ上で実行することを前提にしています。
Keynoteのスライド(ページ)からのテキスト抽出は、Cocoaの機能が利用できるようになってからずいぶんと楽になりました。boundsが重なっているものを演算で判別するのも楽勝です。
以下は、執筆中の最新刊「AppleScript+Xcode GUIアプリソース集」の内容にもとづいています(未完成)。
# 同書の作業中、その暫定タイトル名からmacOS 15.5BetaのAppleScript処理系のクラッシュを誘発したといういわくつきのタイトルでもあります(同バグはリリース時に修正されました)
99ソースの部分はまだ添付Xcodeプロジェクトを確認していないので、「だいたいそのぐらいだろう」という暫定値でもあります。
この状態でウィンドウ左側のカバーページ部分だけを選択すると、selectionでカバーページだけを抽出できます。
カバーページに対して、デフォルトタイトルアイテム(ここでは章番号が入る)と、そのエリアに重なっているテキストアイテムを抽出。
さらに、中央に配置している96ポイントのテキストアイテムを抽出。
あとは、Keynote(iWorks Apps)でよくあるテキストアイテムから抽出したテキストに謎コード(iWork共通のオブジェクト内強制改行)が入っていて改行を解除できないという問題にも対処しています。
また、KeynoteなどのiWork Apps共通の問題点である「オブジェクト同士のIDによる識別ができない」点については、propertiesでまとめて属性値を取得し、この属性値でまとめて判定を行っています。少々遅くなりそうな感じでしたが、実際に試してみたら(マシンが速いので?)問題ありませんでした。
1章 さあ、はじめよう!
基礎的な内容のご説明
2章 ウィンドウ
各種部品を格納する基本的な部品
3章 ボタン
クリック操作を受け付けるもっとも基本的な部品
4章 テキストフィールド
文字や数値などの入力を受け付け、表示を行う
5章 テキストビュー
複数行のスタイルつきテキストを扱える入力・表示部品
6章 デートピッカー
カレンダー情報の入力を受け付ける
7章 イメージビュー
画像(色)の表示とドラッグ&ドロップ受け付け
8章 パスコントロール
フォルダやファイルパスのユーザーによる選択や表示
9章 スライダー
数値の入力、表示
10章 プログレスインジケータ
App Storeに出すなら必須の途中経過表示部品
11章 テーブルビュー
表データの表示、入力用ぜひ使いたい部品
12章 アウトラインビュー
階層化データの入力、表示用
13章 ブラウザ
ツリーデータ、フォルダ階層構造の表示・選択
14章 スプリットビューほか
複数のGUI部品をまとめて使いやすく
15章 メニュー
アプリの機能をひととおり呼び出す階層メニュー
16章 ポップオーバー
ボタンなどからオーバーレイ表示する簡易子ウィンドウ
17章 アドレスブックピープルピッカー
住所録データを表示・選択する
18章 AVキットプレイヤービュー
各種ムービーを再生表示
19章 マップキットビュー
場所と倍率と形式を指定して世界地図を表示
20章 OSAキットビュー
スクリプトエディタ部品でAS編集・実行
21章 PDFキットビュー
PDFとサムネイル表示
22章 ウェブキットビュー
Webコンテンツの表示と操作
23章 サービス
各アプリに対して共通で機能を提供する
24章 ドキュメントベースアプリ
「書類」を扱うアプリ形式
25章 外部アプリコントロール
AppleScriptで他のGUIアプリを操作
26章 スクリプタブル化
アプリ自体を外部からAppleScriptで操作可能に
27章 アプリアイコン
Dock上に表示するアプリアイコンを操作する
28章 ダイアログ
文字入力ダイアログを表示して文字入力
29章 アニメーション
GUI部品をアニメーションさせてユーザーの操作を促す
30章 その他
その他のこまごまとした実用的なノウハウ
あとがき、奥付 Author’s notes
ご愛読、ご協力感謝申し上げます。
すべて自分で作ったデータなので、非常に「ゆらぎ」が小さくなっており、そのデータ品質を前提に作っています。
実際にはもっとデータ品質が低いものと思われるため、そうした低品質データに対処するためには、もっといろいろな処理が必要になってくることでしょう。
処理対象データ(ここではKeynote書類)が事前に予想したとおりの構造(default title item使用)や品質(データのばらつきの存在)になっているかは、AppleScriptを何回か走らせてデータの内容を確認するものでもあるため、最初から一発で想定どおりの処理ができるわけではありません。
AppleScript名:デフォルトタイトルと重なっているものと指定サイズのものを抽出.scpt |
— – Created by: Takaaki Naganoya – Created on: 2025/05/26 — – Copyright © 2025 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" use scripting additions use framework "Foundation" set targSize to 96.0 –取り出し対象の文字サイズ set outList to "" tell application "Keynote" tell front document set aSel to selection repeat with i in aSel set j to contents of i tell j set tList to every text item set dItem to default title item set dProp to properties of dItem set dText to object text of dItem –テキスト set dPos to position of default title item set dHeight to height of default title item set dWidth to width of default title item set dList to dPos & {dWidth, dHeight} –座標領域が重なっているオブジェクトを抽出 set colList to {} repeat with ii in tList set jj to contents of ii set tPos to position of jj set tHeight to height of jj set tWidth to width of jj set ttList to tPos & {tHeight, tHeight} set tProp to properties of jj if dProp is not equal to tProp then set gCol to getCollision(dList, ttList) of me if gCol = true then set the end of colList to jj end if end if end repeat –指定フォントサイズのテキストアイテムを抽出 set sizeList to {} repeat with ii in tList set jj to contents of ii set tSize to size of object text of jj if tSize = targSize then set the end of sizeList to jj end if end repeat –出力用テキストの整形 set t1 to cleanUpKeynoteTextObj(dText) of me set t2 to cleanUpKeynoteTextObj(object text of item 1 of sizeList) of me set t3 to cleanUpKeynoteTextObj(object text of item 1 of colList) of me set outStr to t1 & tab & t3 & return & t2 set outList to outList & return & outStr end tell end repeat end tell end tell return outList –iWorkのtext itemのオブジェクト内改行を削除 on cleanUpKeynoteTextObj(tObj) set tObj to repChar(tObj, string id 10, "") of me –LF set tObj to repChar(tObj, string id 13, "") of me –CR set tObj to repChar(tObj, string id 8232, "") of me –強制改行? return tObj end cleanUpKeynoteTextObj on getCollision(aList, bList) copy aList to {aXn, aYn, aWn, aHn} copy bList to {bXn, bYn, bWn, bHn} set a4Rect to current application’s NSMakeRect(aXn, aYn, aWn, aHn) set b4Rect to current application’s NSMakeRect(bXn, bYn, bWn, bHn) set a4Res to detectRectanglesCollision(a4Rect, b4Rect) of me return a4Res end getCollision –NSRect同士の衝突判定 on detectRectanglesCollision(aRect, bRect) set a1Res to (current application’s NSIntersectionRect(aRect, bRect)) as {record, list} set tmpClass to class of a1Res if tmpClass = record then –macOS 10.10, 10.11, 10.12 return not (a1Res = {origin:{x:0.0, y:0.0}, |size|:{width:0.0, height:0.0}}) else if tmpClass = list then –macOS 10.13 or later return not (a1Res = {{0.0, 0.0}, {0.0, 0.0}}) end if end detectRectanglesCollision on repChar(origText as string, targStr as string, repStr as string) set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr} set temp to text items of origText set AppleScript’s text item delimiters to repStr set res to temp as text set AppleScript’s text item delimiters to txdl return res end repChar |