Menu

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

AppleScriptの穴

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

タグ: PDFDocument

新発売:Cocoa Scripting Course #6, PDFKit

Posted on 8月 22 by Takaaki Naganoya

Piymaru Softwareによる電子書籍の83冊目、「Cocoa Scripting Course #6, PDFKit」を発売しました。PDF560ページ+サンプルScript Zipアーカイブで構成されています。

→ 販売ページ

PDF処理は、Cocoa Scriptingの1つの価値ある到達点です。この処理が行いたいからCocoaの呼び出しについて苦労を重ねてきたと言えます。機械学習やREST API呼び出し、配列からの高速なデータ抽出など、Cocoa Scriptingの「おいしい用途」は星の数ほどありますが、PDF処理は間違いなくその中でもトップランクの攻略目標のうちの1つです。

日常的にPDFを扱っているScripterなら、Cocoa Scriptingによって得られるメリットが膨大なものであることをもれなく間違いなくいかんなく実感できることでしょう。

1章 入門編
2章 実践編
3章 PDFKit編

PDFKitの位置付けと役割
 用途別のフレームワークを知ろう
 PDFKit内の主要クラス
 PDFKit+AppleScriptのつかいどころ
 PDFKit+AppleScriptの注意点
 PDFKit.frameworkの利用宣言文
 (参考資料)PDFの座標系

PDFDocument Basic Samples
PDFPage Basic Samples
PDFOutline Basic Samples
PDFAnnotation Basic Samples

4章 PDF処理 基礎編

PDFの処理の流れ
 AppleScript+PDFKitでよく使う基礎的な処理
 AppleScript+PDFKitの基礎的な処理手順
 AppleScript+PDFKitでよく使う基礎的な処理の手順

PDFからの情報取得
 PDFのサイズをPointで取得
 PDFから各種情報をNSDictionaryで取得
 PDFから各種情報を文字列で取得

PDFページカウント
 PDFのページカウント(PDFDocument)
 PDFのページカウント(Metadata Lib経由)

PDF本文テキスト抽出
 PDFの全ページのテキストを抽出
 PDFのテキストをページ単位で抽出

PDFを回転
 PDFを回転させて新規保存

PDFを印刷
 PDFを印刷

RTFをPDFに変換
 RTFをPDFに変換

PDFからのテキスト検索
 PDFテキストからの指定キーワード検索

ページ単位でPDF分割
 ページ単位でPDF分割

複数PDF結合
 choose fileコマンドで選択した複数のPDFを結合

PDF→他形式画像変換
 ページ単位でJPEG画像に変換

画像連結してPDF作成
 フォルダ内のJPEG画像を新規PDFに連結
 指定フォルダ下のすべての画像を新規PDFに連結
 フォルダ内のJPEG画像を既存のPDFに連結

Multi Page TIFFからPDFへの変換
 Multi Page TIFFからPDFへの変換

アラートダイアログでPDFを表示
 アラートダイアログ+WkWebViewでPDFを表示
 アラートダイアログ+PDFViewでPDFを表示

5章 PDF処理 上級編

PDFのパスワード、暗号化設定
 PDFのアクセス権とパスワード
 パスワード設定をチェック
 設定されているパーミッションを取得
 PDFにパスワードを設定(1/2)
 PDFにパスワードを設定(2/2)
 PDFのパスワードを解除

PDFの空白ページ検出
 PDFから空白ページを削除(1/3)
 PDFから空白ページを削除(2/3)
 PDFから空白ページを削除(3/3)

PDFフォーム入力
 PDFフォームにテキスト入力して別名保存(1/2)
 PDFフォームにテキスト入力して別名保存(2/2)
 PDFフォームにチェックボックス入力(1/2)
 PDFフォームにチェックボックス入力(2/2)

Quartzフィルタ
 Quartzフィルタとは?
 QuartzFilter出力例一覧
 Quartzフィルタの一覧を出力
 白黒のQuartzフィルタをかけて出力
 ブルートーンのQuartzフィルタをかけて出力
 PDFX-3のQuartzフィルタをかけて出力
 グレートーンのQuartzフィルタをかけて出力
 明度低下のQuartzフィルタをかけて出力
 明度上昇のQuartzフィルタをかけて出力
 ファイルサイズ縮小のQuartzフィルタをかけて出力
 セピアトーンのQuartzフィルタをかけて出力

PDFアノテーションを取得、追加、書き換え、削除
 アノテーションについて
 アノテーションを取得
 サークル・アノテーションを追加
 スクウェア・アノテーションを追加
 ライン・アノテーションを追加
 テキスト・アノテーションを追加
 URLリンク・アノテーションを追加(1/2)
 URLリンク・アノテーションを追加(2/2)
 指定語群にハイライトを追加(1/2)
 指定語群にハイライトを追加(2/2)
 指定語群にアンダーラインを追加(1/2)
 指定語群にアンダーラインを追加(2/2)
 指定語群に打ち消し線を追加(1/2)
 指定語群に打ち消し線を追加(2/2)
 PDFからすべてのアノテーションを削除

PDFのリンク抽出、リンク置換
PDFのリンク先は?
リンクの各種情報を取得(1/2)
リンクの各種情報を取得(2/2)
リンク・アノテーションからURLを抽出
URLリンク・アノテーションを追加(1/2)
URLリンク・アノテーションを追加(2/2)
書類内リンク・アノテーションを追加(1/2)
書類内リンク・アノテーションを追加(2/2)
リンクアノテーションのURLを置換

PDFのOCR処理(OCRテキスト埋め込み)
 PDFのOCR処理(1/3)
 PDFのOCR処理(2/3)
 PDFのOCR処理(3/3)

PDFのしおり(TOC)を取得、追加、削除
 TOCの題名と階層が悩ましい(1/2)
 TOCの題名と階層が悩ましい(2/2)
 指定PDFのTOCを取得してレコード化(1/2)
 指定PDFのTOCを取得してレコード化(2/2)
 ノンブルだけのフラットなTOCを付加(1/2)
 ノンブルだけのフラットなTOCを付加(2/2)
 Recordデータから階層TOCを付加(1/3)
 Recordデータから階層TOCを付加(2/3)
 Recordデータから階層TOCを付加(3/3)
 Numbersの表データから階層TOCを付加(1/4)
 Numbersの表データから階層TOCを付加(2/4)
 Numbersの表データから階層TOCを付加(3/4)
 Numbersの表データから階層TOCを付加(4/4)
 指定PDFのTOCを削除

添付サンプルScript紹介

サンプルScript集

資料編

Posted in Books news PRODUCTS | Tagged 12.0savvy 13.0savvy PDFAnnotation PDFDocument PDFOutline PDFPage | Leave a comment

指定のPDFの本文テキストの文字数をカウント

Posted on 3月 9, 2022 by Takaaki Naganoya

指定のPDFの本文テキストを取り出し、文字数をカウントするAppleScriptです。


▲「AppleScriptによるWebブラウザ自動操縦ガイド」の文字数をカウントしようとした

300ページを超える、わりと大きな本のPDFデータから文字を取り出したので、それなりの文字数になりました。つまり、Cocoaの有効活用を考えないとデータサイズ的につらそうなデータ量になることが予想されました。

当初、(文字処理については)Cocoaの機能をあまり活用しないv2を作ったものの、処理にM1 Mac miniで30秒ほどかかりました。すべてNSStringのまま(AppleScriptのstringに型変換せずに)処理してみたら、案の定、大幅に処理が高速化され6秒あまりで完了。

ただし、両者でカウントした文字数が1万文字ぐらい違っていたので、(PDFから取得した文字の)Unicode文字のNormalize方式を変更したところ、両者で同じ結果になりました。また、処理速度に改変前から大幅な変化はありませんでした。

文字数を数えるという処理だとさすがにデータ数が膨大になるため、NSStringで処理したほうがメリットが大きいようです。

# あれ? 5文字ぐらい違う、、、、絵文字の部分か?

AppleScript名:指定のPDFの本文テキストの文字数を数える v2
use AppleScript version "2.8" –macOS 12 or later
use framework "Foundation"
use framework "PDFKit" –Comment Out under macOS 11
–use framework "Quartz"–Uncomment under macOS 11
use scripting additions

script spd
  property cRes : ""
  
property cList : {}
end script

set (cRes of spd) to ""
set (cList of spd) to {}

set (cRes of spd) to getTextFromPDF(POSIX path of (choose file of type {"pdf"})) of me
set (cList of spd) to current application’s NSArray’s arrayWithArray:(characters of (cRes of spd))
set cLen to (cList of spd)’s |count|()
return cLen
–> 256137 (24.763sec)

on getTextFromPDF(posixPath)
  set theURL to current application’s |NSURL|’s fileURLWithPath:posixPath
  
set thePDF to current application’s PDFDocument’s alloc()’s initWithURL:theURL
  
return (thePDF’s |string|()’s precomposedStringWithCompatibilityMapping()) as text
end getTextFromPDF

★Click Here to Open This Script 

AppleScript名:指定のPDFの本文テキストの文字数を数える v3
use AppleScript version "2.8" –macOS 12 or later
use framework "Foundation"
use framework "PDFKit" –Comment Out under macOS 11
–use framework "Quartz"–Uncomment under macOS 11
use scripting additions

script spd
  property cRes : ""
  
property cList : {}
end script

set (cRes of spd) to ""
set (cList of spd) to {}

set (cRes of spd) to getTextFromPDF(POSIX path of (choose file of type {"pdf"})) of me
set cLen to (cRes of spd)’s |length|
return cLen as anything
–> 256142 (6.28 sec)

on getTextFromPDF(posixPath)
  set theURL to current application’s |NSURL|’s fileURLWithPath:posixPath
  
set thePDF to current application’s PDFDocument’s alloc()’s initWithURL:theURL
  
return (thePDF’s |string|()’s precomposedStringWithCompatibilityMapping())
end getTextFromPDF

★Click Here to Open This Script 

わずかとはいえ、違いが出ていることは確かなので、1つのPDFに対して2つの処理方法でテキストを取り出して、それを配列に入れて集合演算して差分をとってみました。M1でも処理に1分少々かかりました。こういう処理は、M1 MaxでもM1 Ultraでも所要時間は変わらないことでしょう(逆にM1の方が処理時間が短い可能性まである)。

どうやら改行コードの解釈で文字数カウント結果に違いが出たようです。

AppleScript名:テキストの抽出方法による文字数の相違チェック.scptd
use AppleScript version "2.8" –macOS 12 or later
use framework "Foundation"
use framework "PDFKit" –Comment Out under macOS 11
–use framework "Quartz"–Uncomment under macOS 11
use scripting additions

script spd
  property cRes : ""
  
property cList : {}
end script

set (cRes of spd) to ""
set (cList of spd) to {}

set docPath to POSIX path of (choose file of type {"pdf"})

set (cRes of spd) to getTextFromPDF1(docPath) of me
set (cList of spd) to characters of (cRes of spd)
set anArray to current application’s NSArray’s arrayWithArray:(cList of spd)

set bStr to getTextFromPDF2(docPath) of me
set bArray to current application’s NSMutableArray’s new()
set bLen to (bStr’s |length|) as anything
repeat with i from 0 to (bLen – 1)
  set tmpStr to (bStr’s substringWithRange:(current application’s NSMakeRange(i, 1)))
  (
bArray’s addObject:(tmpStr))
end repeat

set aRes to diffLists(anArray, bArray) of me
set bRes to diffLists(bArray, anArray) of me
return {aRes, bRes}

on getTextFromPDF1(posixPath)
  set theURL to current application’s |NSURL|’s fileURLWithPath:posixPath
  
set thePDF to current application’s PDFDocument’s alloc()’s initWithURL:theURL
  
return (thePDF’s |string|()’s precomposedStringWithCompatibilityMapping()) as text
end getTextFromPDF1

on getTextFromPDF2(posixPath)
  set theURL to current application’s |NSURL|’s fileURLWithPath:posixPath
  
set thePDF to current application’s PDFDocument’s alloc()’s initWithURL:theURL
  
return (thePDF’s |string|()’s precomposedStringWithCompatibilityMapping())
end getTextFromPDF2

–1D List同士のdiffを計算する
on diffLists(aList, bList)
  set aSet to current application’s NSMutableSet’s setWithArray:aList
  
set bSet to current application’s NSMutableSet’s setWithArray:bList
  
set aRes to calcSetDifference(aSet, bSet) of me
  
return aRes
end diffLists

–2つのNSMutableSetの補集合を求める
on calcSetDifference(aSet, bSet)
  aSet’s minusSet:bSet –補集合
  
set aRes to aSet’s allObjects() as list
  
return aRes
end calcSetDifference

★Click Here to Open This Script 

Posted in PDF Text | Tagged 12.0savvy NSURL PDFDocument | Leave a comment

PDFにパスワードが設定されている場合には、そのパーミッション情報を取得する

Posted on 8月 31, 2020 by Takaaki Naganoya

指定のPDFをチェックし、オープンするのにパスワードが設定されているとか、コピーが禁止されていないかといったパーミッションを調査するAppleScriptです。

API Lebel in this script Desc
(no api) openPermission document allows opening
allowsCopying copyPermission document allows copying of content to the Pasteboard
allowsPrinting printPermission document allows printing
allowsCommenting commentPermission document allows to create or modify document annotations, including form field entries
allowsContentAccessibility contentAccessPermission document allows to extract content from the document
allowsDocumentAssembly assemblyPermission document allows manage a document by inserting, deleting, and rotating pages
allowsDocumentChanges docchangePermission document allows modify the document contents except for document attributes
allowsFormFieldEntry formPermission document allows modify form field entries even if you can’t edit document annotations

PDFのオープン自体にパスワードロックがかかっている状態を検出するAPIがとくになかったので、いろいろ試行錯誤してOpenをロックしてある状態を検出してみました。

検出は、パスワード未指定でUnlockを試みるというもので、実際にパスワードを設定したPDFを相手に試行錯誤して求めてみました。

このUnlock操作に対してfalseが返ってくることでPDFオープンに対してパスワードが設定されているものと判断しています。

AppleScript名:PDFにパスワードが設定されている場合には、そのパーミッション情報を取得する
— Created 2015-11-02 13:48:32 +0900 by Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "QuartzCore"

set aPath to (choose file of type {"com.adobe.pdf"} with prompt "Select PDF to check")

set aRes to my retProtectedPDFPermissions(aPath)
–>  missing value (パスワードは設定されていない)

–> {openPermission:false, copyPermission:true, printPermission:true, commentPermission:true, contentAccessPermission:true, assemblyPermission:true, docchangePermission:true, formPermission:true}–オープンするためにはパスワードが必要(openPermission)

–指定のPDFにパスワードが設定されているかどうかをチェック
on retProtectedPDFPermissions(aPath)
  set aURL to current application’s |NSURL|’s fileURLWithPath:(POSIX path of aPath)
  
set aPDFdoc to current application’s PDFDocument’s alloc()’s initWithURL:aURL
  
set anEncF to aPDFdoc’s isEncrypted()
  
if anEncF = false then return missing value
  
  
set passLocked to aPDFdoc’s unlockWithPassword:""
  
  
set cpPerm to aPDFdoc’s allowsCopying() as boolean
  
set prPerm to aPDFdoc’s allowsPrinting() as boolean
  
set cmPerm to aPDFdoc’s allowsCommenting() as boolean
  
set caPerm to aPDFdoc’s allowsContentAccessibility() as boolean
  
set daPerm to aPDFdoc’s allowsDocumentAssembly() as boolean
  
set dcPerm to aPDFdoc’s allowsDocumentChanges() as boolean
  
set ffPerm to aPDFdoc’s allowsFormFieldEntry() as boolean
  
  
return {openPermission:passLocked, copyPermission:cpPerm, printPermission:prPerm, commentPermission:cmPerm, contentAccessPermission:caPerm, assemblyPermission:daPerm, docchangePermission:dcPerm, formPermission:ffPerm}
end retProtectedPDFPermissions

★Click Here to Open This Script 

Posted in file PDF | Tagged 10.13savvy 10.14savvy 10.15savvy 11.0savvy NSURL PDFDocument | Leave a comment

指定のPDFからTOCを削除する

Posted on 6月 19, 2020 by Takaaki Naganoya

指定のPDFからTOCを削除して別名保存するAppleScriptです。

TOCを削除した新規ファイルは元ファイルと同じ場所に枝番つきで重複回避しつつ作成されます。

33MBで257ページほどあるPDFで、詳細に目次から記事へのリンクを手動で作成し、TOCを手動で作ったところ、Adobe Actobatが、

などというメッセージを出して保存ができなかったので、中途半端に1個だけエントリが残ったTOCを削除するために用意したものです(既存のScriptに機能があったので、削除機能だけ抽出)。

AppleScript名:指定のPDFからTOCを削除する.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2018/08/18
—
–  Copyright © 2018 Piyomaru Software, All Rights Reserved
—

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "Quartz"

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

–PDFの指定
set aFile to choose file of type {"pdf"} with prompt (progress additional description)
set filePath to aFile’s POSIX path

set fileURL to |NSURL|’s fileURLWithPath:filePath
set aPDFdoc to PDFDocument’s alloc()’s initWithURL:fileURL
set parentOL to aPDFdoc’s outlineRoot()

if parentOL is equal to missing value then
  display dialog "There is no TOC with this PDF"
  
return
end if

set outLineCount to parentOL’s numberOfChildren()
set outLineCount to outLineCount as number

–既存のTOCを削除
repeat with num from (outLineCount – 1) to 0 by -1
  (parentOL’s childAtIndex:num)’s removeFromParent()
end repeat

–保存
set progress description to "PDFを保存"
set progress additional description to "保存先の確認"
tell (NSString’s stringWithString:filePath)
  set parentPath to stringByDeletingLastPathComponent() –>親フォルダ
  
set longFileName to lastPathComponent() –>拡張子ありの名前
end tell
set newFilePath to my pathExists(parentPath, longFileName)

set progress additional description to "書き出し中: " & newFilePath
set newFileURL to |NSURL|’s fileURLWithPath:newFilePath
aPDFdoc’s writeToURL:newFileURL

–名前が重複していないか確認
on pathExists(currentPath as text, fileName as text)
  tell (NSString’s stringWithString:fileName)
    set shortFileName to stringByDeletingPathExtension() as text
    
set aSuffix to pathExtension() as text
  end tell
  
if aSuffix ≠ "" then set aSuffix to "." & aSuffix as text
  
  
set currentPath to NSString’s stringWithString:currentPath
  
set unkonwnPath to (currentPath’s stringByAppendingPathComponent:fileName)
  
  
set aSpace to space
  
set num to 0
  
  
repeat while ((NSFileManager’s defaultManager)’s fileExistsAtPath:unkonwnPath)
    set num to num + 1
    
set tmpName to shortFileName & aSpace & num & aSuffix as text
    
set unkonwnPath to (currentPath’s stringByAppendingPathComponent:tmpName)
  end repeat
  
  
return (unkonwnPath as text)
end pathExists

★Click Here to Open This Script 

Posted in file PDF | Tagged 10.13savvy 10.14savvy 10.15savvy NSFileManager NSString NSURL PDFDocument | Leave a comment

PDFフォームに入力して別名保存 v2

Posted on 12月 7, 2019 by Takaaki Naganoya

入力フォームつきのPDFにデータ入力して別名保存するAppleScriptです。

他のGUIアプリを操作してフォーム入力するのではなく、直接PDFKitの機能を利用してフォームPDFへの記入を行なっています。

テキスト入力フォーム、チェックボックス、コンボボックスへの入力に対処してみましたが、リストボックスの項目選択はまだ行えていません。


▲Adobe AcrobatでPDFフォームサンプルをオープンしたところ


▲本ScriptでサンプルフォームPDFを処理したところ


▲Script Debugger上で表示したPDFフォーム上の各種プロパティ。フォーム欄のタイプを名前ではなく各種属性値で判定したいところ

AppleScript名:PDFフォームに入力して別名保存(テキストフィールド、チェックボックス、コンボボックス)
— Created 2019-12-05 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "Quartz"

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

set aHFSPath to (choose file of type {"com.adobe.pdf"} with prompt "Choose a PDF with Form")
set aPOSIX to POSIX path of aHFSPath
set aURL to (|NSURL|’s fileURLWithPath:aPOSIX)

set aPDFdoc to PDFDocument’s alloc()’s initWithURL:aURL
set pCount to aPDFdoc’s pageCount()
set firstPage to (aPDFdoc’s pageAtIndex:0)

set anoList to (firstPage’s annotations()) as list
if anoList is not equal to {missing value} then –指定PDF中にAnotationが存在する場合のみ処理
  repeat with i in anoList
    set aName to (i’s fieldName()) as string
    
    
set adicList to i’s annotationKeyValues
    
set aType to (adicList’s valueForKey:"/Type") as string
    
set aSubType to (adicList’s valueForKey:"/Subtype") as string
    
set aFormType to (adicList’s valueForKey:"/FT") as string
    
    
log {aType, aSubType, aFormType}
    
if aName ends with "Text Box" then –OK
      set aState to (i’s widgetStringValue()) as string
      
      
if aState = "" then
        (i’s setWidgetStringValue:"Piyomaru")
        
set bState to (i’s widgetStringValue()) as string
      end if
      
    else if aName ends with "Check Box" then –OK
      log {"Check Box"}
      
set aState to (i’s buttonWidgetState()) as boolean
      
if aState = false then
        (i’s setButtonWidgetState:true)
        
set bState to (i’s buttonWidgetState()) as boolean
      end if
      
    else if aName ends with "Combo Box" then
      log {"Combo Box"}
      
set tmpList to (i’s choices()) as list
      (
i’s setWidgetStringValue:(contents of some item of tmpList))
      
set cVal to (i’s widgetStringValue()) as string
      
log cVal
      
    else if aName ends with "List Box" then
      log {"List Box"}
      
set tmpList to (i’s choices()) as list
      
log {"tmpList", tmpList}
      
      
–(i’s setWidgetStringValue:(contents of some item of tmpList))
      
    end if
  end repeat
end if

–PDFの保存先のファイル名を入力させる(あらかじめパス文字列を作成しておいてもよい)
set newFileName to POSIX path of (choose file name with prompt "Input File name to save")
if newFileName does not end with ".pdf" then
  set newFileName to newFileName & ".pdf"
end if

–フォーム内容を変更したPDFを指定のパスに新規保存
set pdfRes to (aPDFdoc’s writeToFile:newFileName) as boolean

★Click Here to Open This Script 

Posted in file PDF | Tagged 10.13savvy 10.14savvy 10.15savvy NSURL PDFDocument | Leave a comment

PDFフォームに入力して別名保存

Posted on 12月 5, 2019 by Takaaki Naganoya

入力フォームつきのPDFにデータ入力して別名保存するAppleScriptです。

PDFフォームといっても、別に入力したその場でどこかのサーバーにデータが送信されるわけでもなく、ただ紙に筆記用具で名前を書き込むがごとく、記入欄にデータが入力されたPDFが出来上がるだけです。

サンプルのフォーム入りPDFをみつくろって、チェックボックス項目だけ値を変更して、別名保存してみました。

本AppleScriptではフォームのうちチェックボックスのものの値だけ書き換えてみましたが、テキスト入力型の記入欄に文字データを突っ込むのも難しくはありません(多値ポップアップメニューからの選択がめんどくさい)。

AppleScript名:PDFフォームに入力して別名保存
— Created 2019-12-05 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "Quartz"

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

set aHFSPath to (choose file of type {"com.adobe.pdf"} with prompt "Choose a PDF with Form")
set aPOSIX to POSIX path of aHFSPath
set aURL to (|NSURL|’s fileURLWithPath:aPOSIX)

set aPDFdoc to PDFDocument’s alloc()’s initWithURL:aURL
set pCount to aPDFdoc’s pageCount()
set firstPage to (aPDFdoc’s pageAtIndex:0)

set anoList to (firstPage’s annotations()) as list
if anoList is not equal to {missing value} then –指定PDF中にAnotationが存在する場合のみ処理
  repeat with i in anoList
    set aName to (i’s fieldName()) as string
    
    
if aName ends with "Check Box" then
      set aState to (i’s buttonWidgetState()) as boolean
      
if aState = false then
        (i’s setButtonWidgetState:true)
        
set bState to (i’s buttonWidgetState()) as boolean
      end if
    end if
  end repeat
end if

–PDFの保存先のファイル名を入力させる(あらかじめパス文字列を作成しておいてもよい)
set newFileName to POSIX path of (choose file name with prompt "Input File name to save")
if newFileName does not end with ".pdf" then
  set newFileName to newFileName & ".pdf"
end if

–フォーム内容を変更したPDFを指定のパスに新規保存
set pdfRes to (aPDFdoc’s writeToFile:newFileName) as boolean

★Click Here to Open This Script 

Posted in PDF | Tagged 10.14savvy 10.15savvy NSURL PDFDocument | Leave a comment

PDFのサイズをpointで取得 v2

Posted on 9月 28, 2019 by Takaaki Naganoya

指定PDFのサイズ(幅、高さ)をPointで取得するAppleScriptです。

以前に掲載したバージョンでは、macOS 10.13以降でboundsの値の返り方が変わったことに対応できていないので(それ以前に作ったので無理もないというか、勝手にAppleが仕様を変えたのが悪い)、対処してみました。

AppleScript名:PDFのサイズをpointで取得 v2.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/09/28
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "Quartz"
use framework "AppKit"

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

set aHFSPath to (choose file of type {"com.adobe.pdf"} with prompt "Select PDF")
set sizeRes to retPDFSizeInfo(aHFSPath) of me
–>  {​​​​​width:595.28, ​​​​​height:841.89​​​}

–PDFのサイズを取得する(単位:Point)
on retPDFSizeInfo(aHFSPath)
  set aPOSIX to POSIX path of aHFSPath
  
set aURL to (|NSURL|’s fileURLWithPath:aPOSIX)
  
  
set aPDFdoc to PDFDocument’s alloc()’s initWithURL:aURL
  
set pCount to aPDFdoc’s pageCount()
  
set aPage to aPDFdoc’s pageAtIndex:0
  
  
set aBounds to aPage’s boundsForBox:(current application’s kPDFDisplayBoxMediaBox)
  
  
set aClass to class of aBounds
  
if aClass = record then
    set aSize to |size| of aBounds
  else if aClass = list then
    set aWidth to item 1 of item 2 of aBounds
    
set aHeight to item 2 of item 2 of aBounds
    
set aSize to {width:aWidth, height:aHeight}
  else
    error "Wrong PDF….Can not get bounds from PDF"
  end if
  
  
return aSize
end retPDFSizeInfo

★Click Here to Open This Script 

Posted in list PDF Record | Tagged 10.12savvy 10.13savvy 10.14savvy NSURL PDFDocument | Leave a comment

Keynoteで選択中のスライドだけをデスクトップに画像で書き出す

Posted on 6月 20, 2019 by Takaaki Naganoya

Keynoteでオープン中の最前面の書類で、選択中のスライドだけをデスクトップにPNG画像で書き出すAppleScriptです。Keynote 9.xを必要とします(macOS 10.13以降)。

ちょっとした説明のためにKeynoteの資料の一部だけを画面上でキャプチャして、メールなどに添付して送ることはよくあります(全部送ると量がおおすぎたり、焦点がぼやけたり)。

そこで、複数枚のスライド(ページ)を選択しておくと、それらのみを画像書き出しするAppleScriptを作ってみました。Keynoteにそんな機能はないのですが、「選択中のページ番号」は取れるので、書類全体をPDF書き出ししておいて、書き出したPDFから指定ページを画像として再書き出しを行い、PDFを削除しています。

手品のように見える処理でも、実際に行える機能を組み合わせて地道に作っているだけです。問題は、「手品」が実は地道な調査と機能確認、こまごまとしたライブラリの整備の末に実現されていることが、一般の方にはわかりにくいということでしょうか(いきなり手品を求められて絶句すること多し)。

仕事の合間に作ったので、割と雑な作りです。書き出し画像のファイル名衝突チェックなどは入れていません。

それでも、スクリプトメニューに入れて利用するとなかなか便利です。

AppleScript名:Keynoteで選択中のスライドだけをデスクトップに画像で書き出す.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/06/20
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.7" — 10.13 or later
use framework "Foundation"
use framework "Quartz"
use framework "AppKit"
use scripting additions

set dtPath to (path to desktop) as string

tell application "Keynote"
  set aVer to version
  
  
considering numeric strings
    if aVer < "9.0" then
      display dialog "Too old version for this Script." buttons {"OK"} default button 1 with icon 1
      
return
    end if
  end considering
  
  
tell front document
    set aSel to selection –選択中のスライドオブジェクトへの参照がリストで入る
    
set pList to {}
    
repeat with i in aSel
      set tmpPage to slide number of i
      
set the end of pList to tmpPage
    end repeat
    
  end tell
end tell

–Keynote書類を指定フォルダにPDF書き出し(全ページ書き出し)
set savedPDFPath to exportKeynoteDocToPDF(dtPath) of me
if savedPDFPath = false then return –Error

set aPOSIXpath to POSIX path of savedPDFPath

–書き出したPDFから、部分的にPNG画像に書き出す
repeat with p in pList
  –PDFの指定ページをNSImageとして取り出す
  
set tmpNSImage to getNSImageFromPDFPage(aPOSIXpath, p) of me
  
  
–PDFの書き出しファイル名に子番号にスライド番号をつける
  
set bPath to addStringbeforeExtension(aPOSIXpath, "_" & (p as string)) of me
  
  
–PDF書き出しファイル名に
  
set newPath to repFilePathExtension(bPath, ".png") of me
  
  
–指定のNSImageを指定のパスにPNG形式で保存
  
set sRes to saveNSImageAtPathAsPNG(tmpNSImage, newPath) of me
end repeat

–書き出したPDFを削除
tell application "Finder"
  delete savedPDFPath
end tell

–Keynote書類からPDF書き出し
on exportKeynoteDocToPDF(targFolderPath as string)
  tell application "Keynote"
    set dCount to count every document
    
if dCount = 0 then
      return false
    end if
    
set aPath to file of document 1
  end tell
  
  
set curPath to (current application’s NSString’s stringWithString:(POSIX path of aPath))’s lastPathComponent()’s stringByDeletingPathExtension()’s stringByAppendingString:".pdf"
  
set outPath to (targFolderPath & curPath)
  
  
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
  
  
return (outPath as alias)
  
end exportKeynoteDocToPDF

–指定のPDFから、指定のページをNSImageで返す
on getNSImageFromPDFPage(aPOSIX, aPage as number)
  set aURL to (current application’s |NSURL|’s fileURLWithPath:aPOSIX)
  
  
set aPDFdoc to current application’s PDFDocument’s alloc()’s initWithURL:aURL
  
set pCount to aPDFdoc’s pageCount()
  
  
set compFactor to 1.0 –1.0 — 0.0 = max jpeg compression, 1.0 = none
  
  
–Detect Retina Environment
  
set retinaF to current application’s NSScreen’s mainScreen()’s backingScaleFactor()
  
if retinaF = 1.0 then
    set aScale to 2.0 –Non Retina Env
  else
    set aScale to 1.0 –Retina Env
  end if
  
  
set thisPage to (aPDFdoc’s pageAtIndex:(aPage – 1))
  
set anNSImage to (current application’s NSImage’s alloc()’s initWithData:(thisPage’s dataRepresentation()))
  
  
if anNSImage = missing value then error "Error in getting imagerep from PDF"
  
  
return anNSImage
end getNSImageFromPDFPage

–ファイル名の拡張子の直前に子番号的な文字列を入れる
on addStringbeforeExtension(aPath, extraString)
  set pathString to current application’s NSString’s stringWithString:aPath
  
set theExtension to pathString’s pathExtension()
  
set thePathNoExt to pathString’s stringByDeletingPathExtension()
  
set newPath to (thePathNoExt’s stringByAppendingString:extraString)’s stringByAppendingPathExtension:theExtension
  
return newPath as string
end addStringbeforeExtension

–与えられたパスの拡張子を付け替える
on repFilePathExtension(origPath, newExt)
  set aName to current application’s NSString’s stringWithString:origPath
  
set theExtension to aName’s pathExtension()
  
if (theExtension as string) is not equal to "" then
    set thePathNoExt to aName’s stringByDeletingPathExtension()
    
set newName to (thePathNoExt’s stringByAppendingString:newExt)
  else
    set newName to (aName’s stringByAppendingString:newExt)
  end if
  
return newName as string
end repFilePathExtension

–NSImageを指定パスにPNG形式で保存
on saveNSImageAtPathAsPNG(anImage, outPath)
  set imageRep to anImage’s TIFFRepresentation()
  
set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:imageRep
  
set pathString to current application’s NSString’s stringWithString:outPath
  
set newPath to pathString’s stringByExpandingTildeInPath()
  
set myNewImageData to (aRawimg’s representationUsingType:(current application’s NSPNGFileType) |properties|:(missing value))
  
set aRes to (myNewImageData’s writeToFile:newPath atomically:true) as boolean
  
return aRes –true/false
end saveNSImageAtPathAsPNG

★Click Here to Open This Script 

Posted in file File path Image PDF | Tagged 10.13savvy 10.14savvy Finder Keynote NSBitmapImageRep NSImage NSScreen NSString NSURL PDFDocument | Leave a comment

PDFのしおり(TOC)の内容を取得する v3

Posted on 4月 11, 2019 by Takaaki Naganoya

指定のTOCつきPDFからTOCをrecord in listで取得するAppleScriptです。各TOC項目のページ数、アウトラインレベル、ラベル(ページ名称)を順次取得して配列に出力します。

先日発売したBlogアーカイブ本のTOCを本Scriptで取得すると、以下のようになります(抜粋)。

{{pageIndex:1, outlineLevel:1, outLabel:"表紙"}, {pageIndex:2, outlineLevel:1, outLabel:"商標について"}, {pageIndex:3, outlineLevel:1, outLabel:"本書をご覧になるために"}, ... {pageIndex:34, outlineLevel:1, outLabel:"2011/1"}, {pageIndex:35, outlineLevel:2, outLabel:"リスト同士のdiffをとる"}, {pageIndex:40, outlineLevel:2, outLabel:"日本の月呼称を返す"}, {pageIndex:42, outlineLevel:2, outLabel:"指定の月を1月分リスト化"},...... {pageIndex:450, outlineLevel:1, outLabel:"奥付"}}

あれ? 「本書について」(2P)という記事が掲載もれしているのを、TOC出力から見つけてしまった、、、、、、、、

AppleScript名:PDFのしおり(TOC)の内容を取得する v3
— Created 2017-01-09 by Takaaki Naganoya
— Modified 2019-04-10 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "Quartz"

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

set my titleList to {}

set aFile to POSIX path of (choose file of type {"com.adobe.pdf"})

set fileURL to |NSURL|’s fileURLWithPath:aFile
set aPDFdoc to PDFDocument’s alloc()’s initWithURL:fileURL

–TOCの読み込み
set parentOL to aPDFdoc’s outlineRoot() –あらかじめTOCが存在していないとmissing valueになる
if parentOL is equal to missing value then
  display dialog "本PDFにはTOCが添付されていないため、処理を終了します" with title "No TOC Error:"
  
return
end if

getChilds(parentOL) of me
return (my titleList)
–> {{pageIndex:1, outlineLevel:1, outLabel:"表紙"}, {pageIndex:2, outlineLevel:1, outLabel:"商標について"}, {pageIndex:3, outlineLevel:1, outLabel:"本書をご覧になるために"}, {pageIndex:5, outlineLevel:1, outLabel:"まえがき"},…… {pageIndex:33, outlineLevel:1, outLabel:"2011年"}, {pageIndex:34, outlineLevel:1, outLabel:"2011/1"}, {pageIndex:35, outlineLevel:2, outLabel:"リスト同士のdiffをとる"}, {pageIndex:40, outlineLevel:2, outLabel:"日本の月呼称を返す"},…….}

–PDFOutlineを再帰で取得する
on getChilds(parentOL)
  set outLineStr to parentOL’s label()
  
set outLineCount to (parentOL’s numberOfChildren()) as number
  
  
repeat with i from 0 to (outLineCount – 1)
    set anOut to (parentOL’s childAtIndex:i)
    
    
–Label (Page Title)
    
set tmpOut to (anOut’s label()) as string
    
    
–Page Indel Label
    
set tmpInd to (anOut’s destination()’s page()’s label()) as integer
    
    
–Outline Level
    
set outlevel to 0
    
copy anOut to aTmpOut
    
repeat
      set aTmpOut to aTmpOut’s |parent|()
      
if aTmpOut = missing value then exit repeat
      
set outlevel to outlevel + 1
    end repeat
    
    
set the end of my titleList to {pageIndex:tmpInd, outlineLevel:outlevel, outLabel:tmpOut}
    
    
set tmpChild to (anOut’s numberOfChildren()) as integer
    
    
if tmpChild is not equal to 0 then
      getChilds(anOut) of me
    end if
  end repeat
end getChilds

★Click Here to Open This Script 

Posted in list PDF Record recursive call | Tagged 10.12savvy 10.13savvy 10.14savvy NSURL PDFDocument | Leave a comment

PDFのしおり(TOC)の内容を取得する v2

Posted on 4月 10, 2019 by Takaaki Naganoya

指定のTOCつきPDFからTOCを1Dリスト(1次元配列)で取得するAppleScriptです。各TOC項目のlabelの文字列を順次取得して1次元配列に出力します。

AppleScript名:PDFのしおり(TOC)の内容を取得する v2
— Created 2017-01-09 by Takaaki Naganoya
— 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "Quartz"

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

set my titleList to {}

set aFile to POSIX path of (choose file of type {"com.adobe.pdf"})

set fileURL to |NSURL|’s fileURLWithPath:aFile
set aPDFdoc to PDFDocument’s alloc()’s initWithURL:fileURL

–TOCの読み込み
set parentOL to aPDFdoc’s outlineRoot() –あらかじめTOCが存在していないとmissing valueになる
if parentOL is equal to missing value then
  display dialog "本PDFにはTOCが添付されていないため、処理を終了します" with title "No TOC Error:"
  
return
end if

getChilds(parentOL) of me
return (my titleList)

–再帰処理してみた
on getChilds(parentOL)
  set outLineStr to parentOL’s label()
  
set outLineCount to (parentOL’s numberOfChildren()) as number
  
  
repeat with i from 0 to (outLineCount – 1)
    set anOut to (parentOL’s childAtIndex:i)
    
set tmpOut to (anOut’s label()) as string
    
set the end of my titleList to tmpOut
    
set tmpChild to (anOut’s numberOfChildren()) as integer
    
    
if tmpChild is not equal to 0 then
      getChilds(anOut) of me
    end if
  end repeat
end getChilds

★Click Here to Open This Script 

Posted in list PDF recursive call | Tagged 10.12savvy 10.13savvy 10.14savvy NSURL PDFDocument | Leave a comment

Appleがいまだに直さないPDFViewのバグを回避する

Posted on 4月 10, 2019 by Takaaki Naganoya

PDFViewからcurrentPage()が取れないという、最低最悪レベルのバグが放置されたOSがリリースされ続けて2年。Devlopper Supportに報告しても返事の1つもない今日このごろです。

Apple Developper Connectionのインシデントを消費して質問しても返答がないので、本当に頭にきています。

この、macOS 10.13のBetaでは存在しなかったのにRelease版で作られた画期的なバグを回避するために、いろいろ工夫をしてみました。

テストしてみたところ、Objective-CやSwiftでは発生していないため、Scripting Bridgeのみで発生しているらしきバグのようです。こんな基本的な箇所でバグを作って直さない連中の気が知れません。

AppleのDevelopper Supportが役立たずで仕事をしないのは今日にはじまった話ではないので(Mailing Listが落ちた状態で、報告しても1か月放置した事件など)、仕方なく回避策を検討してみました。

(1)PDFViewまわりのWrapping ClassをObjective-Cで書いて使う
(2)Objective-Cでユーティリティを書いて、パラメータとして与えたPDFViewからObjective-CでcurrentPageを取得する
(3)今後もAppleがバグを作り続けることが予想されるため、サードパーティのPSPDFKitを導入する

といった対策を検討していたのですが、最も手短なものとして、

(4)表示中のページを自前で管理して、PDFViewに指定ページの内容を随時切り出して表示する

という対処を行ってみました。

PDFをオープンしてPDFViewで表示させ、左右の矢印キーでページをめくることができます。なお、macOS 10.14.5beta+Xcode 10.2上でビルドと確認を行いましたが、内容的にはXcodeのバージョンは関係ありません。

–> Download Xcode Project Archive (pdfTestZ)

AppleScript名:AppDelegate.applescript
—
— AppDelegate.applescript
— pdfTestZ
—
— Created by Takaaki Naganoya on 2019/04/09.
— Copyright © 2019 Piyomaru Software. All rights reserved.
—

script AppDelegate
  property parent : class "NSObject"
  
  
— IBOutlets
  
property theWindow : missing value
  
property aView : missing value
  
property maxPageNum : 0
  
property curPageIndex : 0
  
property aPDFDoc : missing value
  
property pLabelField : missing value
  
  
  
on applicationWillFinishLaunching:aNotification
  
end applicationWillFinishLaunching:
  
  
on applicationShouldTerminate:sender
    return current application’s NSTerminateNow
  end applicationShouldTerminate:
  
  
  
on clicked:aSender
    set aTag to (tag of aSender) as integer
    
    
if aTag = 100 then
      set aPath to choose file of type {"com.adobe.pdf"}
      
      
set pPath to POSIX path of aPath
      
set aURL to current application’s |NSURL|’s fileURLWithPath:pPath
      
set my aPDFDoc to current application’s PDFDocument’s alloc()’s initWithURL:aURL
      
      
set myFileName to (current application’s NSString’s stringWithString:pPath)’s lastPathComponent()
      
theWindow’s setTitle:myFileName
      
      
set maxPageNum to ((aPDFDoc’s pageCount()) as integer) – 1
      
set curPageIndex to 0
      
      
log {"maxPageNum", maxPageNum}
      
      
aView’s setAutoScales:true
      
aView’s setDisplaysPageBreaks:true
      
      
my dispCurPageDoc()
      
set tmpStr to ((maxPageNum + 1) as string) & "/" & ((curPageIndex + 1) as string)
      
pLabelField’s setStringValue:tmpStr
      
    else if aTag = 200 then
      
      
set tmpPage to my (aPDFDoc’s pageAtIndex:(curPageIndex))
      
set curPageLabel to tmpPage’s label()
      
      
tell current application
        display dialog (curPageLabel as string)
      end tell
      
    else if aTag = 1000 then
      my decPage()
      
my dispCurPageDoc()
      
    else if aTag = 1010 then
      my incPage()
      
my dispCurPageDoc()
      
    end if
    
  end clicked:
  
  
on dispCurPageDoc()
    set tmpPage to my (aPDFDoc’s pageAtIndex:(curPageIndex))
    
set tmpDoc to (current application’s PDFDocument’s alloc()’s initWithData:(tmpPage’s dataRepresentation()))
    
aView’s setDocument:tmpDoc
    
    
set tmpStr to ((maxPageNum + 1) as string) & "/" & ((curPageIndex + 1) as string)
    
pLabelField’s setStringValue:tmpStr
  end dispCurPageDoc
  
  
  
on incPage()
    if curPageIndex = maxPageNum then
      –何もしない
    else if curPageIndex < maxPageNum then
      set curPageIndex to curPageIndex + 1
    end if
  end incPage
  
  
on decPage()
    if curPageIndex = 0 then
      –何もしない
    else if curPageIndex > 0 then
      set curPageIndex to curPageIndex – 1
    end if
  end decPage
end script

★Click Here to Open This Script 

Posted in AppleScript Application on Xcode PDF | Tagged 10.13savvy 10.14savvy NSString NSURL PDFDocument PDFPage | 1 Comment

PDFから指定ページ以降を削除

Posted on 7月 10, 2018 by Takaaki Naganoya

PDFから指定ページ以降を削除するAppleScriptです。

こんな(↑)418ページもあるPDFから、おためし版の、冒頭から40ページだけ抽出したPDFを作成する際に使用したものです。

もともとは418ページありましたが、、、

実行後は40ページに、、、

AppleScript名:PDFから指定ページ以降を削除
— Modified 2018-07-08 by Takaaki Naganoya
–Original By Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use framework "QuartzCore"
use aBplus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

property NSSet : a reference to current application’s NSSet
property |NSURL| : a reference to current application’s |NSURL|
property NSArray : a reference to current application’s NSArray
property SMSForder : a reference to current application’s SMSForder
property NSIndexSet : a reference to current application’s NSIndexSet
property PDFDocument : a reference to current application’s PDFDocument
property NSSortDescriptor : a reference to current application’s NSSortDescriptor

load framework

set sPage to 41 –ここから末尾までのページを削除
set inFile to (choose file of type {"pdf"} with prompt "Choose your PDF files:")
set pRes to removePDFPageAfter(inFile, sPage) of me

–指定パスのPDFの指定ページ以降をすべて削除
on removePDFPageAfter(inFile, sPage)
  set pCount to pdfPageCount(inFile) of me
  
set eCount to pCount – sPage + 1
  
  
set aindexSet to NSIndexSet’s indexSetWithIndexesInRange:(current application’s NSMakeRange(sPage, eCount))
  
set targPageList to (SMSForder’s arrayWithIndexSet:aindexSet) as list
  
  
return removeSpecificPagesFromPDF(inFile, targPageList) of me
end removePDFPageAfter

–指定PDF書類の複数ページの一括削除
on removeSpecificPagesFromPDF(inFileAlias, targPageNumList as list)
  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()
  
set t3List to relativeToAbsNumList(targPageNumList, pRes) of me
  
  
repeat with i in t3List
    copy i to targPageNum
    (
theDoc’s removePageAtIndex:(targPageNum – 1))
  end repeat
  
  
–Overwrite Exsiting PDF
  
set aRes to (theDoc’s writeToURL:inNSURL) as boolean
  
  
return aRes
end removeSpecificPagesFromPDF

–絶対ページと相対ページが混在した削除対象ページリストを絶対ページに変換して重複削除して降順ソート
on relativeToAbsNumList(aList, aMax)
  set newList to {}
  
  
repeat with i in aList
    set j to contents of i
    
if i < 0 then
      set j to aMax + j
    end if
    
    
if (j ≤ aMax) and (j is not equal to 0) then
      set the end of newList to j
    end if
  end repeat
  
  
set t1List to uniquify1DList(newList, true) of me
  
set t2List to sort1DNumListWithOrder(t1List, false) of me
  
  
return t2List
end relativeToAbsNumList

–1D/2D Listをユニーク化
on uniquify1DList(theList as list, aBool as boolean)
  set aArray to NSArray’s arrayWithArray:theList
  
set bArray to aArray’s valueForKeyPath:"@distinctUnionOfObjects.self"
  
return bArray as list
end uniquify1DList

–Sort 1-Dimension List(String Number List)
on sort1DNumListWithOrder(theList as list, aBool as boolean)
  tell NSSet to set theSet to setWithArray_(theList)
  
tell NSSortDescriptor to set theDescriptor to sortDescriptorWithKey_ascending_("floatValue", aBool)
  
set sortedList to theSet’s sortedArrayUsingDescriptors:{theDescriptor}
  
return (sortedList) as list
end sort1DNumListWithOrder

–指定PDFのページ数をかぞえる(10.9対応。普通にPDFpageから取得)
–返り値:PDFファイルのページ数(整数値)
on pdfPageCount(aFile)
  set aFile to POSIX path of aFile
  
set theURL to |NSURL|’s fileURLWithPath:aFile
  
set aPDFdoc to PDFDocument’s alloc()’s initWithURL:theURL
  
set aRes to aPDFdoc’s pageCount()
  
return aRes as integer
end pdfPageCount

★Click Here to Open This Script 

Posted in file PDF | Tagged 10.11savvy 10.12savvy 10.13savvy NSArray NSIndexSet NSSet NSSortDescriptor NSURL PDFDocument | Leave a comment

Skimで現在表示中のPDFのページをJPEG画像で書き出す

Posted on 6月 30, 2018 by Takaaki Naganoya

オープンソースのPDFビューワー「Skim」で現在表示中のPDFの現在表示中のページをJPEG画像で書き出すAppleScriptです。

macOS標準装備のPreview.appはつい最近AppleScriptからの制御が公式に行えるようになった程度で、対応度も最低限です。Skimであれば、こうした「現在オープン中のPDFの表示中のページ」の番号を取得することもできます。

macOS標準装備のScript Menuから呼び出して利用することを前提に作成してあります。

Skimでオープン中の最前面のPDFと同じフォルダに、元ファイル名に対してページの数値をゼロパディングして追加したものをJPEG画像のファイル名に指定しています。ファイル名の重複回避などは行っていません。

ただし、Skimで表示モードが「単一」(1ページ分のみビューワーに表示)以外になっていると、カレントページ(現在表示中のページ)が画面上とアプリケーション側で管理しているものがズレることがあるので、表示モードを「単一」に切り替えてから「このページでよいか?」といった確認をユーザーに対して行うとよいかもしれません。

AppleScript名:Skimで現在表示中のPDFのページをJPEG画像で書き出す
— Created 2018-06-30 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "Quartz"
use framework "AppKit"

property |NSURL| : a reference to current application’s |NSURL|
property NSString : a reference to current application’s NSString
property NSImage : a reference to current application’s NSImage
property NSScreen : a reference to current application’s NSScreen
property NSNumber : a reference to current application’s NSNumber
property NSZeroPoint : a reference to current application’s NSZeroPoint
property PDFDocument : a reference to current application’s PDFDocument
property NSJPEGFileType : a reference to current application’s NSJPEGFileType
property NSCompositeCopy : a reference to current application’s NSCompositeCopy
property NSGraphicsContext : a reference to current application’s NSGraphicsContext
property NSBitmapImageRep : a reference to current application’s NSBitmapImageRep
property NSNumberFormatter : a reference to current application’s NSNumberFormatter
property NSImageInterpolationHigh : a reference to current application’s NSImageInterpolationHigh

tell application "Skim"
  set docCount to count every document
  
if docCount = 0 then return
  
  
tell front document
    set curInd to index of current page
    
set docFile to file of it
  end tell
end tell

set aPOSIX to POSIX path of docFile
set aURL to (|NSURL|’s fileURLWithPath:aPOSIX)

set aPDFdoc to PDFDocument’s alloc()’s initWithURL:aURL
set pCount to aPDFdoc’s pageCount()

set compFactor to 1.0 –1.0 — 0.0 = max jpeg compression, 1.0 = none

–Detect Retina Environment
set retinaF to NSScreen’s mainScreen()’s backingScaleFactor()
if retinaF = 1.0 then
  set aScale to 2.0 –Non Retina Env
else
  set aScale to 1.0 –Retina Env
end if

–PDFをページごとに分割してJPEGでファイル書き出し
set i to (curInd – 1) –AppleScript index (1 based) to Cocoa index (0 based) conversion

–Pick Up a PDF page as an image
set thisPage to (aPDFdoc’s pageAtIndex:(i))
set thisDoc to (NSImage’s alloc()’s initWithData:(thisPage’s dataRepresentation()))
if thisDoc = missing value then error "Error in getting imagerep from PDF in page:" & (i as string)

–Resize Image
set pointSize to thisDoc’s |size|()
set newSize to current application’s NSMakeSize((pointSize’s width) * aScale, (pointSize’s height) * aScale)
set newImage to (NSImage’s alloc()’s initWithSize:newSize)

newImage’s lockFocus()
(
thisDoc’s setSize:newSize)
(
NSGraphicsContext’s currentContext()’s setImageInterpolation:(NSImageInterpolationHigh))
(
thisDoc’s drawAtPoint:(NSZeroPoint) fromRect:(current application’s CGRectMake(0, 0, newSize’s width, newSize’s height)) operation:(NSCompositeCopy) fraction:2.0)
newImage’s unlockFocus()

–Save Image as JPEG
set theData to newImage’s TIFFRepresentation()
set newRep to (NSBitmapImageRep’s imageRepWithData:theData)
set targData to (newRep’s representationUsingType:(NSJPEGFileType) |properties|:{NSImageCompressionFactor:compFactor, NSImageProgressive:false})
set zText to retZeroPaddingText((i + 1), 4) of me
set outPath to addString_beforeExtensionIn_addingExtension_("_" & zText, aPOSIX, "jpg")

(targData’s writeToFile:outPath atomically:true) –書き出し

–ファイルパス(POSIX path)に対して、文字列(枝番)を追加。任意の拡張子を追加
on addString:extraString beforeExtensionIn:aPath addingExtension:aExt
  set pathString to NSString’s stringWithString:aPath
  
set theExtension to pathString’s pathExtension()
  
set thePathNoExt to pathString’s stringByDeletingPathExtension()
  
  
set newPath to (thePathNoExt’s stringByAppendingString:extraString)’s stringByAppendingPathExtension:aExt
  
return newPath as string
end addString:beforeExtensionIn:addingExtension:

on retZeroPaddingText(aNum as integer, aDigitNum as integer)
  if aNum > (((10 ^ aDigitNum) as integer) – 1) then return "" –Range Check
  
set aFormatter to NSNumberFormatter’s alloc()’s init()
  
aFormatter’s setUsesGroupingSeparator:false
  
aFormatter’s setAllowsFloats:false
  
aFormatter’s setMaximumIntegerDigits:aDigitNum
  
aFormatter’s setMinimumIntegerDigits:aDigitNum
  
aFormatter’s setPaddingCharacter:"0"
  
set aStr to aFormatter’s stringFromNumber:(NSNumber’s numberWithFloat:aNum)
  
return aStr as string
end retZeroPaddingText

★Click Here to Open This Script 

Posted in Image PDF | Tagged 10.11savvy 10.12savvy 10.13savvy NSBitmapImageRep NSImage NSNumber NSNumberFormatter NSScreen NSString NSURL PDFDocument Skim | Leave a comment

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

Google Search

Popular posts

  • macOS 13, Ventura(継続更新)
  • アラートダイアログ上にWebViewで3Dコンテンツを表示(WebGL+three.js)v3
  • UI Browserがgithub上でソース公開され、オープンソースに
  • Xcode 14.2でAppleScript App Templateを復活させる
  • macOS 13 TTS Voice環境に変更
  • 2022年に書いた価値あるAppleScript
  • ChatGPTで文章のベクトル化(Embedding)
  • 新発売:AppleScriptからSiriを呼び出そう!
  • iWork 12.2がリリースされた
  • 従来と異なるmacOS 13の性格?
  • 新発売:CotEditor Scripting Book with AppleScript
  • macOS 13対応アップデート:AppleScript実践的テクニック集(1)GUI Scripting
  • AS関連データの取り扱いを容易にする(はずの)privateDataTypeLib
  • macOS 13でNSNotFoundバグふたたび
  • macOS 12.5.1、11.6.8でFinderのselectionでスクリーンショット画像をopenできない問題
  • ChatGPTでchatに対する応答文を取得
  • 新発売:iWork Scripting Book with AppleScript
  • Finderの隠し命令openVirtualLocationが発見される
  • macOS 13.1アップデートでスクリプトエディタの挙動がようやくまともに
  • あのコン過去ログビューワー(暫定版)

Tags

10.11savvy (1101) 10.12savvy (1242) 10.13savvy (1390) 10.14savvy (586) 10.15savvy (434) 11.0savvy (277) 12.0savvy (185) 13.0savvy (55) CotEditor (60) Finder (47) iTunes (19) Keynote (98) NSAlert (60) NSArray (51) NSBezierPath (18) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (51) NSDictionary (27) NSFileManager (23) NSFont (18) NSImage (41) NSJSONSerialization (21) NSMutableArray (62) NSMutableDictionary (21) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (117) NSURL (97) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (56) Pages (37) Safari (41) Script Editor (20) WKUserContentController (21) WKUserScript (20) WKUserScriptInjectionTimeAtDocumentEnd (18) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

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

アーカイブ

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

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

メタ情報

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

Forum Posts

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

メタ情報

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