Archive for the 'Keynote 7' Category

2017/11/30 Keynoteで最前面の書類の全スライドにマスタースライドを再適用する

Keynoteでオープン中の最前面の書類の全スライドにマスタースライドを再適用するAppleScriptです。

書類中の各スライド(ページ)上のタイトルの大きさや位置が、作業中にバラバラになってしまった場合に、本Scriptを実行するとスライドを再適用するため、位置や大きさがそろいます。

本当は各スライド上のタイトルオブジェクト(default title item)の大きさや位置をループで揃えようとしてこの何倍かの長さのScriptを書いていたのですが、ふと「マスターを再適用すれば簡単にすぐ終わるのでは?」と思い、やってみたらあっという間でした。

確認はKeynote v7.3.1+macOS 10.12.6で行っています。macOS 10.13(「macOS Vista」と呼んでいる)は検証用のサブマシンには入れてありますが、あまりにバグが多くて出来が悪いので、メイン環境には入れないつもりです。

AppleScript名:Keynoteで最前面の書類の全スライドにマスタースライドを再適用する
–http://piyocast.com/as/archives/5005
tell application “Keynote”
  tell front document
    set sList to every slide
    
repeat with i in sList
      tell i
        set curSlide to base slide
        
set base slide to curSlide
      end tell
    end repeat
  end tell
end tell

★Click Here to Open This Script 

2017/10/31 Keynote書類内の画像サイズを縮小

指定フォルダ内に入っているKeynote書類を順次オープンして、書類内の画像サイズを縮小(最適化)するAppleScriptです。

GUI Scriptingを用いているため、システム環境設定.app>セキュリティとプライバシー>プライバシー>アクセシビリティでScript Editorに対してGUI Scripting(アプリケーションにコンピュータの制御を許可)をオンにしておく必要があります。

Keynoteに搭載されている機能のうち、AppleScript用語辞書を通じてAppleScript側に機能が解放されていることが望ましい機能の筆頭に、「ファイル」メニューに存在している「ファイルサイズを減らす」コマンドがあります。

Keynote書類にペーストされた画像素材を適正サイズに縮小することで、大幅に書類のファイルサイズを小さくすることができ、Keynote書類の数が増えてくるとSSDの容量節約にかなり効果的です。

keynote1_resized.png

ただ、AppleScript用語辞書に記載されていないので、非正規のルート(GUI Scripting)でメニューなどを操作して呼び出すことになります。

GUI Scriptingは強制的なメニュー(GUI部品)操作なので、コマンド実行の結果を受け取ることもできませんし、その結果として何かアプリケーション側がメッセージを返してきたとしても、受信できません。

keynote2_resized.png

そして、アプリケーションがSheetで結果を返すと、通常だとそこでアプリケーションの実行が止まるので、強引にシート上のボタンをクリックして(リターンキーを押して)表示を解除しています。

実行直後、メニュー項目を走査するので少々待たされます。オブジェクトへの参照をテキスト化してInfo.plist内部にでも登録しておくとよいでしょう。

AppleScript名:Keynote書類内の画像サイズを縮小
– Created 2017-10-01 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4945

property menuItemRef1 : missing value

–Select target folder which contains Keynote documents
set aFol to choose folder with prompt “Keynote書類の入っているフォルダを選択してください”

tell application “Finder”
  tell folder (aFol as string)
    –File Kind is localized. UTI is better
    
set kList to (every file whose kind is equal to “Keynoteプレゼンテーション”) as alias list
  end tell
end tell

if menuItemRef1 = missing value then
  –Application Name, Root File Menu Item, target menu item (Localized)
  
set menuItemRef1 to returnMenuItemRef(“Keynote”, “ファイル”, “ファイルサイズを減らす”) of me
  
–We can get these texts from .strings file
end if

repeat with i in kList
  set j to contents of i
  
  
tell application “Keynote”
    open j
  end tell
  
  
–「ファイル」>「ファイルサイズを減らす」コマンドが使えるかどうか確認
  
set aRes to checkReduceFileSizeCommandEnabled() of me
  
  
if aRes = true then
    –ファイルサイズを減らす
    
clickReduceFileSizeMenuViaGUIScripting() of me
    
    
–「この書類のファイルサイズは減らせません」シートが表示されているかどうかチェック
    
set aRes to chkSheetDialogAndDismissIt() of me
    
    
delay 1
    
    
–保存&クローズ
    
tell application “Keynote”
      close every document with saving
    end tell
  end if
end repeat

–「この書類のファイルサイズは減らせません」シートが表示されているかどうかチェック
on chkSheetDialogAndDismissIt()
  activate application “Keynote”
  
tell application “System Events”
    tell process “Keynote”
      tell window 1
        set sEXT to exists of sheet 1
      end tell
    end tell
  end tell
  
  
activate application “Keynote”
  
tell application “System Events”
    tell process “Keynote”
      if sEXT = true then
        –「この書類のファイルサイズは減らせません」シートが表示されていた場合
        
tell button 1 of sheet 1 of window 1
          keystroke return –なぜかクリックできない。ふしぎ
        end tell
      end if
    end tell
  end tell
  
  
return (not sEXT)
end chkSheetDialogAndDismissIt

–メニューから「ファイル」>「ファイルサイズを減らす」を実行
on clickReduceFileSizeMenuViaGUIScripting()
  activate application “Keynote”
  
tell application “System Events”
    tell process “Keynote”
      click menuItemRef1
    end tell
  end tell
end clickReduceFileSizeMenuViaGUIScripting

–「ファイル」>「ファイルサイズを減らす」が実行可能か確認
on checkReduceFileSizeCommandEnabled()
  activate application “Keynote”
  
tell application “System Events”
    tell process “Keynote”
      return (enabled of menuItemRef1)
    end tell
  end tell
end checkReduceFileSizeCommandEnabled

on returnMenuItemRef(appName, menubarMenuItem, lastMenuItemName)
  tell application “System Events”
    tell process appName
      set menuList to name of every menu of menu bar 1
      
set aMenuInd to offsetInList(menubarMenuItem, menuList) of me
    end tell
    
    
set aList to entire contents of (menu bar item aMenuInd of menu bar 1 of process appName)
    
    
repeat with i in aList
      set j to contents of i
      
try
        set aNameVal to value of attribute “AXTitle” of j
        
if (aNameVal = lastMenuItemName) then
          return j
        end if
      end try
    end repeat
  end tell
  
  
return false
end returnMenuItemRef

on offsetInList(aStr, aList)
  set anArray to current application’s NSArray’s arrayWithArray:aList
  
set aInd to (anArray’s indexOfObject:aStr)
  
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

★Click Here to Open This Script 

2017/10/30 Keynoteでオープン中の書類のページをPDFに書き出してオープン

Keynoteでオープン中の書類の現在表示中のページをPDFに書き出して、オープンするAppleScriptです。

Keynoteで仕様書などのおおきめの(ページ数の多い)書類を(修正や追記をしながら)開いていて、同時に複数のページを見ておく必要があるときに、現在のページのみPDFに書き出して表示させてみたものです。

指定のページのみPDFに書き出す機能はKeynoteに存在していないので、とりあえず書類をまるごとPDFに書き出して、現在表示中のページ以外を削除するようにしてみました。

AppleScript名:Keynoteでオープン中の書類のページをPDFに書き出してオープン
– Created 2017-10-30 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “Quartz”
–http://piyocast.com/as/archives/4942

property |NSURL| : a reference to current application’s |NSURL|
property PDFDocument : a reference to current application’s PDFDocument

tell application “Keynote”
  tell front document
    tell current slide
      set curPage to slide number
    end tell
    
    
set dtPath to ((path to desktop) as string) & (do shell script “uuidgen”) & “_” & (curPage as string) & “.pdf”
    
    
export to file dtPath as PDF
  end tell
end tell

set targAlias to (dtPath as alias)
set aRes to stripSpecificPageInPDF(targAlias, curPage) of me

tell application “Finder” to open targAlias

–指定PDFから指定ページを残して他を削除
on stripSpecificPageInPDF(inFileAlias, targPageNum)
  set inNSURL to |NSURL|’s fileURLWithPath:(POSIX path of inFileAlias)
  
set theDoc to PDFDocument’s alloc()’s initWithURL:inNSURL
  
  
set pRes to theDoc’s pageCount()
  
  
repeat with i from pRes to 1 by -1
    if i is not equal to targPageNum then
      (theDoc’s removePageAtIndex:(i - 1))
    end if
  end repeat
  
  
set aRes to (theDoc’s writeToURL:inNSURL) as boolean
  
  
return aRes
end stripSpecificPageInPDF

★Click Here to Open This Script 

2017/10/07 Keynoteで現在表示中のスライド上にある表のカラム幅を自動調整 v2

Keynoteでオープン中の最前面のドキュメントの現在表示中のスライド上にある表のカラム幅を自動調整するAppleScriptのアップデート版です。

Keynote v7.3+macOS 10.12.6/macOS 10.13.1で動作検証を行なっています。

前バージョンでは「わかりやすさ」を強調したので、実行速度がいまひとつでした。

表のセル幅程度であれば「ちょっと動きが見える」程度のかわいらしい「遅さ」でしたが、これがInDesign上のTextFrame中の数百個の連続する文字だった場合には、属性情報を変更するだけでもうんざりするほど時間がかかります。

しかし、アホのようにループで順次処理しなくても、範囲を指定してまとめて命令を投げれば大幅に実行速度が向上するケースがあります(アプリケーション側の対応次第なので、実際にためしてみる必要はあります)。

Keynote 7.3で実際にScriptを動かしてみたところ、

 ループで列幅変更:0.146sec
 範囲指定して一括変更:0.06sec

と、ずいぶん処理時間が短縮されました。前バージョンは動作が目で見てわかる程度でしたが、本バージョンでは実行するとすぐに動作が終わって列幅が変更される感じです。

実際にためして有効かどうかチェックを行なっておく必要はありますが、オブジェクトへのアクセス方法次第で処理速度が大幅に変わることがあるので知っておいて損はないでしょう。

AppleScript名:Keynoteで現在表示中のスライド上にある表のカラム幅を自動調整 v2
– Created 2017-10-06 by Takaaki Naganoya
– 2017 Piyomaru Software
–http://piyocast.com/as/archives/4889
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

tell application “Keynote”
  tell front document
    tell current slide
      
      
set tCount to count every table
      
if tCount = 0 then return
      
      
tell table 1
        
        
set cCount to count every column
        
set cWidth to width of every column
        
set aWidth to width –table width
        
        
set aveWidth to (aWidth - (first item of cWidth)) / (cCount - 1)
        
        
tell columns 2 thru cCount
          set width to aveWidth
        end tell
        
      end tell
    end tell
  end tell
end tell

★Click Here to Open This Script 

2017/10/06 Keynoteで現在表示中のスライド上にある表のカラム幅を自動調整

Keynoteでオープン中の最前面のドキュメントの現在表示中のスライド上にある表のカラム幅を自動調整するAppleScriptです。

Keynote v7.3+macOS 10.12.6/macOS 10.13.1で動作検証を行なっています。

keynote_before.png
▲実行前(表のカラム幅が不均一)

keynote_after.png
▲実行後(表のカラム幅が均一)

最前面のドキュメント(front document)の、現在選択中のスライド(current slide)の上にある表(table)の一番左のカラムをヘッダーカラムとして実行前のままの状態を保持して、残りのカラムを均等幅になるよう幅(width)を計算して設定します。

KeynoteのScriptingについては、電子書籍「Keynote Control 廖Keynote Control◆廚脳楮戮望匆陲靴討い泙后6縮のある方はぜひお求めください。

AppleScript名:Keynoteで現在表示中のスライド上にある表のカラム幅を自動調整
– Created 2017-10-06 by Takaaki Naganoya
– 2017 Piyomaru Software
–http://piyocast.com/as/archives/4888
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

tell application “Keynote”
  tell front document
    tell current slide
      
      
set tCount to count every table
      
if tCount = 0 then return
      
      
tell table 1
        
        
set cCount to count every column
        
set cWidth to width of every column
        
set aWidth to width –table width
        
        
set aveWidth to (aWidth - (first item of cWidth)) / (cCount - 1)
        
        
repeat with i from 2 to cCount –Skip Header Column
          tell column i
            set width to aveWidth
          end tell
        end repeat
        
      end tell
    end tell
  end tell
end tell

★Click Here to Open This Script 

2017/09/08 iTunes Library上のsongでライブラリへの追加年を集計してKeynote書類上にグラフ作成

iTunesのMusic Libraryで楽曲のライブラリへの追加年で集計を行ってKeynote上にグラフを作成するAppleScriptです。6,775曲が登録されている自分のライブラリで集計→グラフ作成で3秒程度です。

itunes_usic.png

iTunes LibraryへのアクセスをiTunesLibrary framework経由で行い、NSCountedSetで集計を行うことで高速に処理を行ないます。

iTunesの基礎的な操作については電子書籍「iTunes Control」にて、Keynoteのグラフ作成については、電子書籍「Keynote Control with AppleScript」 △脳楮戮望匆陲靴討い泙后6縮がある方はぜひお買い求めください。

年々、楽曲を聴かない&買わなくなっている様子が見てとれますが、ほかの人はどんなもんなのか興味があります。

AppleScript名:iTunes Library上のsongでライブラリへの追加年で集計してKeynote書類上にグラフ作成
– Created 2017-09-06 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “iTunesLibrary”
–http://piyocast.com/as/archives/4816

property NSString : a reference to current application’s NSString
property NSArray : a reference to current application’s NSArray
property NSSortDescriptor : a reference to current application’s NSSortDescriptor
property NSDictionary : a reference to current application’s NSDictionary
property NSCountedSet : a reference to current application’s NSCountedSet
property ITLibrary : a reference to current application’s ITLibrary
property NSMutableArray : a reference to current application’s NSMutableArray

set yRec to retSongAddedYear() of me
–>  {{theName:2005, numberOfTimes:1907}….}

–楽曲のiTunesライブラリへの追加「年」のみ抽出
set yList to ((NSArray’s arrayWithArray:yRec)’s valueForKeyPath:“theName”) as list
–>  {2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017}

–楽曲のiTunesライブラリへの追加「年」ごとのカウントを抽出
set vList to ((NSArray’s arrayWithArray:yRec)’s valueForKeyPath:“numberOfTimes”) as list
–>  {1907, 1125, 853, 319, 638, 353, 351, 241, 605, 344, 71, 76, 28}

tell application “Keynote”
  set adoc to (make new document with properties {document theme:theme “ホワイト”, height:768, width:1024}) –Caution: theme name is **localized** (”White”)
  
tell front document
    set base slide of current slide to master slide “空白” –Caution: master slide name is **localized** (”Blank”)
    
tell current slide
      add chart row names {“ライブラリ追加年”} column names yList data {vList} type vertical_bar_2d group by chart row –row name is “iTunes Library Added Year”
    end tell
  end tell
  
activate
end tell

on retSongAddedYear()
  set library to ITLibrary’s libraryWithAPIVersion:“1.0″ |error|:(missing value)
  
if library is equal to missing value then return {}
  
  
set allTracks to library’s allMediaItems()
  
set allCount to allTracks’s |count|()
  
  
set anEnu to allTracks’s objectEnumerator()
  
set newArray to NSMutableArray’s alloc()’s init()
  
  
repeat
    set aPL to anEnu’s nextObject()
    
if aPL = missing value then exit repeat
    
try
      set aKind to (aPL’s mediaKind) as integer
      
if (aKind as integer) is equal to 2 then –Music, Song
        set pMonth to ((aPL’s addedDate() as date)’s year) as integer
        
newArray’s addObject:(pMonth)
      end if
    on error
      set aLoc to (aPL’s location’s |path|()) as string
    end try
  end repeat
  
  
return countItemsByItsAppearance(newArray) of me
end retSongAddedYear

–出現回数で集計
on countItemsByItsAppearance(aList)
  set aSet to NSCountedSet’s alloc()’s initWithArray:aList
  
set bArray to NSMutableArray’s array()
  
set theEnumerator to aSet’s objectEnumerator()
  
  
repeat
    set aValue to theEnumerator’s nextObject()
    
if aValue is missing value then exit repeat
    
bArray’s addObject:(NSDictionary’s dictionaryWithObjects:{aValue, (aSet’s countForObject:aValue)} forKeys:{“theName”, “numberOfTimes”})
  end repeat
  
  
–出現回数(numberOfTimes)で降順ソート
  
set theDesc to NSSortDescriptor’s sortDescriptorWithKey:“theName” ascending:true
  
bArray’s sortUsingDescriptors:{theDesc}
  
  
return bArray as list
end countItemsByItsAppearance

★Click Here to Open This Script 

2017/07/07 Keynoteの現ページと次ページで場所が被っていても始点座標が異なるオブジェクトの始点座標をそろえる

編集中のKeynote書類で現在のスライドと次のスライド上の指定した種類のオブジェクトの座標情報をスキャンして、「重なっているが原点座標が異なる」ものを検出して原点座標を同じにそろえるAppleScriptです。

2017-07-07-13_06_20.gif

Keynoteで資料を使っていて、(複数ページ間で同じ場所に存在すべき)オブジェクトの位置が微妙にズレていることが気になることがあります。

ただ、いちいち座標情報をひろって手で修正するのは面倒なので、AppleScriptで自動修正させてみました。

重なっているオブジェクト同士であっても、始点座標が同じものは無視します(修正する必要はないので)。

Script実行時にチェック対象の2ページのうち、最初のページを表示していることを想定しています。

オブジェクトの領域の重なり判定は2つだけを想定しています。それ以上の個数のオブジェクトの重なりは無視しています。

KeynoteのAppleScript用語辞書がselection(選択中のオブジェクト)を取得できないという「残念な点」があるので、そこが重ね重ねも残念です。

AppleScript名:Keynoteの現ページと次ページで場所が被っていても始点座標が異なるオブジェクトの始点座標をそろえる
– Created 2017-07-07 by Takaaki Naganoya
– 2017 Piyomaru Software
– v1:オーバーラップしているオブジェクトの個数が2個のみの状況を想定
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4718

tell application “Keynote”
  tell front document
    set sNum to slide number of (current slide)
  end tell
end tell

–表示中のページ(slide)と、その次のページ(slide)で、
–指定オブジェクト(shape)の座標情報をリストアップ
set {rect1, obj1} to getObjInfoList(sNum, “shape”) of me –現在のページ(slide)
set {rect2, obj2} to getObjInfoList(sNum + 1, “shape”) of me –現在+1ページ

set hitRect to {} –衝突していつつもイコールではないオブジェクトの座標情報を入れる
set hitObj to {} –衝突しているオブジェクト(最初のページ、次のページ)をペアで入れる

set p1Count to 1

–表示中のページ(slide)と、その次のページ(slide)で、
–重なっていつつも始点座標が異なるオブジェクト(shape)を総当たりでリストアップ
tell application “Keynote”
  tell front document
    repeat with i in rect1
      set j to contents of i
      
      
set p2Count to 1
      
      
repeat with ii in rect2
        set jj to contents of ii
        
        
–指定オブジェクト同士の領域が重なっているかどうかチェック
        
set aRes to detectRectanglesCollision(j, jj) of me
        
–始点座標がイコールかどうかチェック(イコールのものは修正不要)
        
set origRes to (origin of j) = (origin of jj)
        
        
if (aRes = true) and (origRes = false) then
          set the end of hitRect to j
          
set the end of hitObj to {contents of item p1Count of obj1, contents of item p2Count of obj2}
        end if
        
        
set p2Count to p2Count + 1
        
      end repeat
      
      
set p1Count to p1Count + 1
    end repeat
  end tell
end tell

–current slideを2ページ目に変更
set cRes to changeCurrentSlide(sNum + 1) of me

–オーバーラップしていつつも始点座標が異なるアイテムの個数を数える
set tCount to count every item of hitRect

tell application “Keynote”
  tell front document
    tell current slide
      repeat with i from 1 to tCount
        set curPos to contents of item i of hitRect
        
set curOrig to origin of curPos
        
set curOrigX to x of curOrig
        
set curOrigY to y of curOrig
        
        
set curObj to contents of second item of item i of hitObj
        
set position of curObj to {curOrigX, curOrigY}
      end repeat
    end tell
  end tell
end tell

–最前面のKeynote書類の指定スライド(page)上の指定オブジェクトの情報(座標情報、オブジェクト情報)を返す
on getObjInfoList(aPage, objClassStr as string)
  set rectList to {}
  
set objList to {}
  
  
set cRes to changeCurrentSlide(aPage) of me
  
if cRes = false then error “Slide Range Error”
  
  
tell application “Keynote”
    tell front document
      tell current slide
        set aList to every iWork item
        
        
repeat with i in aList
          set aClass to (class of i) as string
          
          
if aClass = objClassStr then
            set aWidth to width of i
            
set aHeight to height of i
            
set {aPosX, aPosY} to position of i
            
set aRect to {origin:{x:aPosX, y:aPosY}, |size|:{|width|:aWidth, |height|:aHeight}}
            
            
set the end of rectList to aRect
            
set the end of objList to i
          end if
        end repeat
      end tell
    end tell
  end tell
  
  
return {rectList, objList}
end getObjInfoList

–NSRect同士の衝突判定
on detectRectanglesCollision(aRect, bRect)
  set a1Res to current application’s NSIntersectionRect(aRect, bRect)
  
return not (a1Res = {origin:{x:0.0, y:0.0}, |size|:{width:0.0, height:0.0}})
end detectRectanglesCollision

–表示中のスライド(ページ)を変更する
on changeCurrentSlide(targPageNum as integer)
  try
    tell application “Keynote”
      tell front document
        set sCount to count every slide
        
if targPageNum < 1 then return false –under check
        
if sCount < targPageNum then return false –over check
        
set current slide to slide targPageNum
        
return true
      end tell
    end tell
  on error
    return false
  end try
end changeCurrentSlide

★Click Here to Open This Script 

2017/06/29 Keynote Control 2冊同時刊行

Piyomaru Softwareによる電子書籍、AppleScriptえほんシリーズの続刊を2冊同時に販売開始しました(お試し版もご用意しました)。

いきなり難しくならない「ホップ」「ステップ」「ジャンプ」の3段階難易度設定。
difficulty_resized.png

どこからどこまでが1行かを明示的に示す行番号表示などで、わかりやすく説明しています。

linenumbers.png

「Keynote Control 1」(47ページ)と「Keynote Control 2」(45ページ)です。BOOTH.pmにて委託販売しており、BOOTH上での価格は両方とも1,000円です。

同時に、既刊の「iTunes Control」についてもBOOTH上での販売価格を1,000円に改定しています。

ぜひお買い求めください。

keynote_control1_cover_resized.png

keynote_control2_cover_resized.png

2017/03/28 Keynote/Pages/Numbersがアップデート

Keynote/Pages/Numbersがアップデートし、それぞれKeynote 7.1、Pages 6.1、Numbers 4.1になりました(要macOS 10.12)。

■Keynote 7.1.0
–AppleScript用語辞書の変更点
・current slideがread only属性ではなくなった
・image formatで指定できる値が変更された
small / medium / large –> 60p / 540p / 720p / 1080p / 2160p / native size
・movie formatで指定できる値が変更された
small / medium / large –> 360p / 540p / 720p / 1080p / 2160p / native size
–機能上の変更点
・PDF書き出しをmacOS 10.12.4上で行えるようになった(権限エラーが出なくなった)

■Pages 6.1.0
–AppleScript用語辞書の変更点
・exportコマンドで指定できるフォーマットとして「formatted text」が追加された(RTF?)
–機能上の変更点
・PDF書き出しをmacOS 10.12.4上で行えるようになった(権限エラーが出なくなった)

2017/01/10 Keynote書類の画像書き出しテスト

Keynote書類をデスクトップに画像書き出し(PNG形式)するAppleScriptです。動作確認はmacOS 10.12.3beta+Keynote 7.0.5で行っています。

macOS 10.12.x+Keynote 7.0.5ではSandbox化の影響を受けてexportコマンドがうまく動作していないようで、そのままPDF書き出しを実行するとError 6に遭遇しました。これを回避するために、PDF書き出し前にPDFと同名の空のファイルを作るとよいことがわかりました。

sandboxed_export.png

AppleScriptからKeynoteに書類の画像書き出しを行うとError 6に遭遇するのはPDF書き出しと事情は変わりません。何らかの対策を行う必要があります。

画像書き出しは指定の場所にフォルダが作成されて、さらにその中にスライド画像が連番つきで書き出されます。1つのPDFができるPDF書き出しとは若干動作が異なるわけです。

試行錯誤したところ、書き出しフォルダと同じ名前のフォルダを、画像書き出し前にあらかじめ作っておけばエラーを回避できることがわかりました。

同様に、macOS 10.12上ではSandbox化されたアプリケーション上でのexportコマンドの挙動に問題があることが報告されており、ここで示したようなやり方で回避できているようです。具体的には、Mailの添付ファイルの書き出しがこれでSandbox由来のエラーを回避できた事例が報告されています。

一方で、Microsoft Word 2016/Excel 2016においてAppleScriptからExportを行わせたときに上記の回避策ではSandbox由来のエラーを回避できず、海外のScripter連中と回避策を相談しているところです。

Appleにはフィードバック済みですが、かなり問題のある動作に見えます。

AppleScript名:Keynote書類の画像書き出しテスト
– Created 2017-01-10 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4384

tell application “Keynote”
  if (count every document) = 0 then error “There is no Keynote Document”
  
set aDoc to document 1
end tell
set kRes to exportImagesFromKeynote(aDoc) of me

on exportImagesFromKeynote(aDoc)
  tell application “Keynote”
    set aPath to file of aDoc
  end tell
  
  
set tmpPath to (path to desktop) as string
  
set curPath to (current application’s NSString’s stringWithString:(POSIX path of aPath))’s lastPathComponent()’s stringByDeletingPathExtension()
  
set outPath to (tmpPath & curPath)
  
  
–This preliminary process may be no use if macOS or Keynote fixed in the future
  
do shell script “mkdir “ & quoted form of POSIX path of outPath –To Avoid “Error 6″ (Keynote 7.0.5+macOS 10.12.2/3)
  
–This preliminary process may be no use if macOS or Keynote fixed in the future
  
  
tell application “Keynote”
    set anOpt to {class:export options, compression factor:1.0, image format:PNG, export style:IndividualSlides, all stages:false, skipped slides:true}
    
export document 1 to file outPath as slide images with properties anOpt
  end tell
  
  
return (outPath as alias)
end exportImagesFromKeynote

★Click Here to Open This Script 

2017/01/09 Keynote書類をデスクトップにPDFで出力する

Keynote書類をデスクトップにPDFで出力するAppleScriptです。動作確認はKeynote v7.0.5で行いました(初回掲載分からアップデート)。

Keynoteから出力したPDFに対し、Keynote書類の構造を確認しつつ、階層構造つきのTOC(しおり)を付加するAppleScriptを作成したときに作ったものです(KeynoteでPDF書き出ししただけでは、階層構造つきのTOCなんて気のきいたものはついてきませんので)。

keynote_leveled_toc.png

exportコマンドによる出力先のフォルダに、当初temporary items folderを指定してみたのですが、ユーザー権限がないと言われて書き込めませんでした。Keynoteはサンドボックス化されたアプリケーションなので、ホームディスレクトリの下のどこかを一時作業フォルダとして使うように運用を変更する必要があることでしょう(temporary items folderの存在意義が、、、、)。

【重要! 生死に関わるレベル】

macOS 10.12.3beta上で、exportコマンド実行時にエラー(Error 6)になることがあり、原因 を調査したところ、すでにexport先に同名のファイルが存在する場合にはエラーにならないことがわかりました。Sandbox化の影響を受け、Keynote自体がファイルを書き出せない状態にあったようなので、shellのtouchコマンドで書き出すPDFと同名の(空っぽの)ファイルをあらかじめ作成しておいてからexportコマンドを実行したところうまく行きました。

AppleScript名:Keynote書類をデスクトップにPDFで出力する v1.1
– Created 2017-01-09 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4380

tell application “Keynote”
  set dCount to count every document
end tell

if dCount = 0 then
  display dialog “オープン中のKeynote書類はありません” with icon 0 with title “No Document Error”
  
return
end if

tell application “Keynote”
  set aPath to file of document 1
end tell

–Keynote書類のファイル名だけを取り出し、拡張子を外し、別の拡張子(.pdf)を追加する
set curPath to (current application’s NSString’s stringWithString:(POSIX path of aPath))’s lastPathComponent()’s stringByDeletingPathExtension()’s stringByAppendingString:“.pdf”

set tmpPath to (path to desktop) as string
set outPath to tmpPath & (curPath as string)

do shell script “touch “ & quoted form of POSIX path of outPath

tell application “Keynote”
  set anOpt to {class:export options, export style:IndividualSlides, all stages:false, skipped slides:true, PDF image quality:Best}
  
export document 1 to file outPath as PDF with properties anOpt
end tell

★Click Here to Open This Script