Archive for the '印刷関連(print)' Category

2015/08/24 ASOCでPDFを印刷するテスト

Cocoaの機能を用いてPDFをAppleScriptだけでアプリケーションに依存しないで印刷するscriptです。

pdfprint1.png
▲Script Editor上でCommand-Control-「R」でforeground実行すると、PDFを選択し、印刷ダイアログを表示します(Window非表示)

pdfprint2.png
▲プリンタも選択可能

AppleScript名:ASOCでPDFを印刷するテスト
– Created 2015-08-24 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “Quartz”
use framework “AppKit”

–Check If this script runs in foreground
if not (current application’s NSThread’s isMainThread()) as boolean then
  display alert “This script must be run from the main thread (Command-Control-R in Script Editor).” buttons {“Cancel”} as critical
  
error number -128
end if

–Choose a PDF to print
set aDoc to POSIX path of (choose file of type {“com.adobe.pdf”})
set aDocPath to current application’s NSString’s stringWithString:aDoc
set aPDF to current application’s PDFDocument’s alloc()’s initWithURL:(current application’s |NSURL|’s fileURLWithPath:aDocPath)

–Make PDFView
set aPDFView to current application’s PDFView’s alloc()’s init()
aPDFView’s setDocument:aPDF
aPDFView’s setAutoScales:true
aPDFView’s setDisplaysPageBreaks:false

–Make Window
set aWin to current application’s NSWindow’s alloc()’s init()
aWin’s setContentSize:(aPDFView’s frame()’s |size|())
aWin’s setContentView:aPDFView
aWin’s |center|()

–Print PDF
set sharedPrintInfo to current application’s NSPrintInfo’s sharedPrintInfo()
aPDFView’s printWithInfo:sharedPrintInfo autoRotate:true

★Click Here to Open This Script 

2014/11/27 10.10でプリンタの情報を取得する

ASOCでCocoaの機能を呼び出してプリンタの情報を取得するAppleScriptです。

NSPrinterのドキュメントをながめつつ、いろいろ突っついてみていますが・・・Deprecatedだと書かれている機能がまだ呼び出せるようで、プリンターがカラーかどうか、紙排出時に逆方向に(裏面?)出せるかなど調べられるようです。

AppleScript名:10.10でプリンタの情報を取得する
– Created 2014-11-27 by Takaaki Naganoya
– 2014 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ASObjCExtras”
use framework “AppKit”

–Get Printer Names
set pArray to current application’s NSPrinter’s printerNames
set pList to (pArray’s ASify()) as list
–> {”KING JIM TEPRA PRO SR3700P”, “NEC MultiWriter 5750C @ MBA13″, “PDFwriter”, “PM-T960-1″}

–Get Printer Type (Driver Name?)
set tArray to current application’s NSPrinter’s printerTypes
set tList to (tArray’s ASify()) as list
–> {”TEPRA PRO SR3700P”, “NEC MultiWriter 5750C v2.4″, “Lisanet PDFwriter”, “EPSON PM-T960″}

set colorPinterList to {}

repeat with i in pList
  set j to contents of i
  
  
–Is it a Printer?
  
set aPrinter to (current application’s NSPrinter’s printerWithName:j)
  
set aDesc to aPrinter’s deviceDescription
  
set aRec to aDesc’s ASify() as record
  
–> {NSDeviceIsPrinter:”YES”}
  
  
  
–Is it a Color Printer?
  
set aColor to (aPrinter’s isColor()) as boolean –isColor() deprecated? It works
  
if aColor = true then
    set the end of colorPinterList to j
  end if
  
end repeat

colorPinterList
–> {”NEC MultiWriter 5750C @ MBA13″, “PDFwriter”, “PM-T960-1″}

★Click Here to Open This Script 

2014/11/27 10.10でプリンタを選択して印刷

ASOCで、現在Macに接続されているプリンターの名称一覧を取得して、印刷を行うサンプルです。

一般的なアプリケーションでの印刷を意図しており、InDesignなどのAdobe系アプリケーションを意図しているものではありません(仕組みや機能が全然別物)。

LAN上で共有されているプリンター(”NEC MultiWriter 5750C @ MBA13”)を指定してみたところ、問題なく印刷できました。

プリンタ名称については、lpstatコマンドで取得した名称一覧とは返ってくる文字列が違う(”NEC_MultiWriter_5750C___MBA13”)のですが、、、どちらでも問題ありませんでした。

AppleScript名:10.10でプリンタを選択して印刷
– Created 2014-11-27 by Takaaki Naganoya
– 2014 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ASObjCExtras”
use framework “AppKit”

set pArray to current application’s NSPrinter’s printerNames
set pList to (pArray’s ASify()) as list
–> {”KING JIM TEPRA PRO SR3700P”, “NEC MultiWriter 5750C @ MBA13″, “PDFwriter”, “PM-T960-1″}

set aPrinter to first item of (choose from list pList with prompt “出力先のプリンタを選択してください”)

tell application “Safari”
  tell front document
    set aPrintSetting to {copies:1, starting page:1, ending page:9999, target printer:aPrinter}
    
print with properties aPrintSetting without print dialog
  end tell
end tell

★Click Here to Open This Script 

2014/08/27 ログイン中のユーザーのPDFWriterのPDF出力フォルダを求める

仮想プリンタを提供し、印刷結果をPDFとして出力する「PDFWriter」がPDFを出力するフォルダのパスを求めるAppleScriptです。

ただし、正常に動作するためにはいくつかの前提条件をクリアする必要があります。

 (1)マシンにPDFWriterがインストールしてあること
 (2)少なくとも一度はPDFWriter経由でPDF出力したことがあること

(1)はともかく、インストール直後の一度もPDFWriter経由でPDF出力していない環境では、PDF出力フォルダが作成されていない可能性があります。

スクリプト名:ログイン中のユーザーのPDFWriterのPDF出力フォルダを求める
set aPath to retPDFWriterOutputFolder()
–> “/var/spool/pdfwriter/me/”

–ログイン中のユーザーのPDFWriterのPDF出力フォルダを求める
on retPDFWriterOutputFolder()
  
  
–ログイン中のユーザーアカウント名を取得する
  
tell application “System Events”
    set aProp to properties of current user
    
set aName to name of aProp
  end tell
  
  
–pdfwriterのPDF出力フォルダのパスを組み立てる
  
set printCuePath to “/var/spool/pdfwriter/” & aName & “/”
  
  
–PDF出力フォルダが存在するかどうか確認
  
try
    do shell script “cd “ & quoted form of printCuePath
  on error
    return false –パスが存在しない場合にはfalseを返す
  end try
  
  
return printCuePath
  
end retPDFWriterOutputFolder

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2013/11/18 印刷可能なプリンタ一覧から選択してプリント実行 10.9

印刷可能なプリンター一覧から選択してプリントを実行するAppleScriptの改修版です。

昨日掲載したAppleScriptでは、PDF出力用のバーチャルプリンター(CUPS-PDF)にダイアログなしで印刷出力してPDFを作成するというワークフローがOS X 10.9上で確認できませんでした(ダイアログを表示させると出力できていました)。

また、接続されていても「一時停止中(省エネモード)」のレーザープリンターを指定できなかったため、若干処理内容を見直してみました。身の回りに動作確認が可能なOS X 10.9以外の環境が少なくなっているため、OS X 10.9上でのみ動作確認してあります。

まず、バーチャルプリンターとしてCUPS-PDFではいまひとつの様子なので、同様にオープンソース&フリーで配布されている「PDFwriter for Mac v1.2.1」をOS X 10.9にインストール。

print1.png

プリントキューの一覧を求めるのに「lpstat -p」ではなく「lpstat -v」を実行するようにしました。これでスリープ中(一時停止中)のレーザープリンターも指定できます。

テストで、印刷を実行するアプリケーションにSafariを指定していましたが、いまひとつ「そんな処理はなかなかしないだろー」感が強いので、Pages(v4.3)をコントロールして書類をPDFに出力させるようにしてみました。

print3.png
▲Pages v4.3上でPagesの書類をオープンした状態

print2.png
▲PDF出力したものをPDF Viewer(Skim)でオープンしたところ

print4.png
▲プリント(PDF)出力されたファイル

なお、PDFWriterを指定してPDF出力させると、/private/var/spool/pdfwriter/(ユーザー名) のフォルダ内にファイルが生成されることを確認しました。

スクリプト名:印刷可能なプリンタ一覧から選択してプリント実行 10.9
set pList to getPrintCues()
set aPrinter to first item of (choose from list pList with prompt “出力先のプリンタを選択してください”)

set aPrintSetting to {copies:1, starting page:1, ending page:9999, target printer:aPrinter}

tell application “Pages”
  activate
  
tell document 1
    try
      print with properties aPrintSetting without print dialog –ダイアログなしで印刷
    on error
      display dialog “プリント中になんかのエラーが発生しました。たぶん、キャンセルされたんでしょう” buttons {“OK”} default button 1
    end try
  end tell
end tell

(*
–とりあえずSafariで印刷してみた。Safariである必要はない
tell application “Safari”
  activate
  tell document 1
    try
      print with properties aPrintSetting without print dialog –ダイアログなしで印刷
    on error
      display dialog “プリント中になんかのエラーが発生しました。たぶん、キャンセルされたんでしょう” buttons {”OK”} default button 1
    end try
  end tell
end tell
*)

–プリントキューの名称一覧を取得(10.9用)
on getPrintCues()
  set aRes to do shell script “lpstat -v”
  
set aList to paragraphs of aRes
  
  
set bList to {}
  
  
repeat with i in aList
    set j to contents of i
    
set jj to trimStrings(j, “device for “, “:”) of me
    
set the end of bList to jj
  end repeat
  
  
return bList
  
end getPrintCues

–任意の文字列から指定開始子、指定終了子でトリミングした文字列を取り出す
on trimStrings(aString, fromStr, endStr)
  set fromLen to length of fromStr
  
set eLen to length of endStr
  
  
set sPos to offset of fromStr in aString
  
if sPos = 0 then return “”
  
set body1 to text (sPos + fromLen) thru -1 of aString
  
set ePos to offset of endStr in body1
  
if ePos = 0 then return “”
  
set body2 to text 1 thru (ePos - 1) of body1
  
  
return body2
end trimStrings

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2013/11/17 印刷可能なプリンタ一覧から選択してプリント実行 10.4〜10.9

印刷可能なプリンター一覧から選択してプリント実行するAppleScriptのMac OS X 10.9対応版です。GUI Scriptingは使用していません。

printdialog.png

lpstatコマンドを呼び出して、その結果をparseしてプリンタ名を取り出す……という、あまり工夫もへったくれもない内容ではありますが、このlpstatコマンドが返す文字列が、OSのメジャーアップデートごとに微妙にフラフラと変わっているため、メジャーアップデートのたびに地道に調査して反映するという作業が必要になっています。

例によって、出力する紙のサイズの指定はできません。

10.5から10.8まではlpstatの実行結果が(日本語環境では)日本語文字列で返ってきて「おいおい……」と、思っておりましたが、10.9でlpstatの実行結果が英語で返るように変更になりました(このほうが常識的)。

本当は、CUPS-PDFを指定してPDF出力を(プリントダイアログを非表示で)実行したかったのですが、なーぜかプリントダイアログを非表示にするとPDF出力が(/var/spool/cups-pdf/me に)行われなかったので、いろいろ試しているところです。

スクリプト名:印刷可能なプリンタ一覧から選択してプリント実行 10.4〜10.9
–要・Mac OS X 10.4以上
set pList to getPrintCues() of me
set aPrinter to first item of (choose from list pList with prompt “出力先のプリンタを選択してください”)

set aPrintSetting to {copies:1, starting page:1, ending page:1, target printer:aPrinter}

–とりあえずSafariで印刷してみた。Safariである必要はない
tell application “Safari”
  activate
  
tell document 1
    try
      print with properties aPrintSetting with print dialog –「with」を「without」にすると、ダイアログなしで印刷
    on error
      display dialog “プリント中になんかのエラーが発生しました。たぶん、キャンセルされたんでしょう” buttons {“OK”} default button 1
    end try
  end tell
end tell

(*
プロパティ:

copies integer — プリントする書類の部数
collating boolean — プリントの丁合をとるかどうか
starting page integer — 書類からプリントする最初のページ
ending page integer — 書類からプリントする最後のページ
pages across integer — 物理的なページ上に横方向に並べる論理ページの数
pages down integer — 物理的なページ上に縦方向に並べる論理ページの数
requested print time date — デスクトッププリンタが書類をプリントするべき時間
error handling standard/summarized/detailed — エラーの処理方法
fax number text — 書類の送信先ファックス番号
target printer text — 出力先のプリントキューの名前

–用紙サイズを指定できないのはどういうことなのか?(汗) 用紙サイズ指定できなかったら意味ないやんけ!
*)

–プリントキューの名称一覧を取得
–10.8, 10.9用に書き換え
on getPrintCues()
  set P to paragraphs of (do shell script “lpstat -p”)
  
set pList to {}
  
  
set osVer to (system attribute “sys2″) as number
  
  
repeat with i in P
    set j to contents of i
    
    
if osVer = 9 then
      –10.9
      
set aPName to trimStrings(j, “printer “, ” is idle. enabled since “) of me –また、10.4の仕様に戻しましたね
    else if osVer = 8 then
      –10.8
      
set aPName to trimStrings(j, “プリンタ”, ” は待機中です。”) of me
    else if osVer = 7 then
      –10.7
      
set aPName to trimStrings(j, “プリンタ”, ” は待機中です。”) of me
    else if osVer = 6 then
      –10.6
      
set aPName to trimStrings(j, “プリンター “, ” は待機中です。”) of me
    else if osVer = 5 then
      –10.5
      
set aPName to trimStrings(j, “プリンタ “, ” は待機中です。”) of me
    else if osVer = 4 then
      –10.4
      
set aPName to trimStrings(j, “printer “, ” is idle. enabled since “) of me
    end if
    
    
if aPName is not equal to “” then
      set the end of pList to aPName
    end if
  end repeat
  
  
return pList
end getPrintCues

–任意の文字列から指定開始子、指定終了子でトリミングした文字列を取り出す
on trimStrings(aString, fromStr, endStr)
  set fromLen to length of fromStr
  
set eLen to length of endStr
  
  
set sPos to offset of fromStr in aString
  
if sPos = 0 then return “”
  
set body1 to text (sPos + fromLen) thru -1 of aString
  
set ePos to offset of endStr in body1
  
if ePos = 0 then return “”
  
set body2 to text 1 thru (ePos - 1) of body1
  
  
return body2
end trimStrings

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2011/08/21 印刷可能なプリンタ一覧から選択してプリント実行 10.4〜10.7

印刷可能なプリンター一覧から選択してプリント実行するAppleScriptのMac OS X 10.7対応版です。

lpstatコマンドを呼び出して、その結果をparseしてプリンタ名を取り出す……という、あまり工夫もへったくれもない内容ではありますが、このlpstatコマンドが返す文字列が、OSのメジャーアップデートごとに微妙にフラフラと変わっているため、メジャーアップデートのたびに地道に調査して反映するという作業が必要になっています。

また、日本語以外のユーザー環境で利用する場合には、lpstatコマンドの返り値を調べて微調整する必要があります。Mac OS X 10.4の時には日本語環境でも英語メッセージが出ていたのですが、10.5以降は出力結果もローカライズされてしまって、本当にこれでいいのか疑問が残ります。

例によって、出力する紙のサイズを指定できないようになっています。

# 出力先のプリンタ名称取得ぐらいの機能は、標準で持っていてほしいところですが……

とりあえず、実際にMac OS X 10.7の稼働するMacBook Airで動作を確認しました。

スクリプト名:印刷可能なプリンタ一覧から選択してプリント実行 10.4_10.7
要・Mac OS X 10.4以上
set pList to getPrintCues() of me
set aPrinter to first item of (choose from list pList with prompt 出力先のプリンタを選択してください)

set aPrintSetting to {copies:1, starting page:1, ending page:1, target printer:aPrinter}

とりあえずSafariで印刷してみた。Safariである必要はない
tell application “Safari”
  activate
  
tell document 1
    try
      print with properties aPrintSetting with print dialog with」を「without」にすると、ダイアログなしで印刷
    on error
      display dialog プリント中になんかのエラーが発生しました。たぶん、キャンセルされたんでしょう buttons {“OK”} default button 1
    end try
  end tell
end tell

(*
プロパティ:

copies integer — プリントする書類の部数
collating boolean —
プリントの丁合をとるかどうか
starting page integer —
書類からプリントする最初のページ
ending page integer —
書類からプリントする最後のページ
pages across integer —
物理的なページ上に横方向に並べる論理ページの数
pages down integer —
物理的なページ上に縦方向に並べる論理ページの数
requested print time date —
デスクトッププリンタが書類をプリントするべき時間
error handling standard/summarized/detailed —
エラーの処理方法
fax number text —
書類の送信先ファックス番号
target printer text —
出力先のプリントキューの名前

用紙サイズを指定できないのはどういうことなのか?(汗) 用紙サイズ指定できなかったら意味ないやんけ!
*)

プリントキューの名称一覧を取得
–10.7用に書き換え
on getPrintCues()
  set P to paragraphs of (do shell script “lpstat -p”)
  
set pList to {}
  
  
set osVer to (system attribute “sys2″) as number
  
  
repeat with i in P
    set j to contents of i
    
    
if osVer = 7 then
      –10.7
      
set aPName to trimStrings(j, プリンタ, は待機中です。) of me
    else if osVer = 6 then
      –10.6
      
set aPName to trimStrings(j, プリンター, は待機中です。) of me
    else if osVer = 5 then
      –10.5
      
set aPName to trimStrings(j, プリンタ, は待機中です。) of me
    else if osVer = 4 then
      –10.4
      
set aPName to trimStrings(j, “printer “, ” is idle. enabled since “) of me
    end if
    
    
if aPName is not equal to “” then
      set the end of pList to aPName
    end if
  end repeat
  
  
return pList
end getPrintCues
任意の文字列から指定開始子、指定終了子でトリミングした文字列を取り出す
on trimStrings(aString, fromStr, endStr)
  set fromLen to length of fromStr
  
set eLen to length of endStr
  
  
set sPos to offset of fromStr in aString
  
if sPos = 0 then return “”
  
set body1 to text (sPos + fromLen) thru -1 of aString
  
set ePos to offset of endStr in body1
  
if ePos = 0 then return “”
  
set body2 to text 1 thru (ePos - 1) of body1
  
  
return body2
end trimStrings

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/09/05 印刷可能なプリンタ一覧から選択してプリント実行 10.4_10.6

Mac OS X 10.4用のプリント用AppleScriptが、そのままではMac OS X 10.5/10.6では使えなくなっていたので、書き換えました。

getPrintCues()ハンドラ内でlpstatコマンドの帰り値を処理しており、Mac OS X 10.5と10.6でも微妙にコマンドが返してくるメッセージが違っていたりしたので、その3つのバージョンのOSで個別の処理を行っています。

print1.jpg

なお、printコマンドで「with print dialog」と指定しているところを「without print dialog」と書き換えるとダイアログなしで印刷を実行します。

スクリプト名:印刷可能なプリンタ一覧から選択してプリント実行 10.4_10.6
–要・Mac OS X 10.5以上
set pList to getPrintCues() of me
set aPrinter to first item of (choose from list pList with prompt "出力先のプリンタを選択してください")

set aPrintSetting to {copies:1, starting page:1, ending page:1, target printer:aPrinter}

–とりあえずSafariで印刷してみた。Safariである必要はない
tell application "Safari"
  activate
  
tell document 1
    try
      print with properties aPrintSetting with print dialog –「with」を「without」にすると、ダイアログなしで印刷
    on error
      display dialog "プリント中になんかのエラーが発生しました。たぶん、キャンセルされたんでしょう" buttons {"OK"} default button 1
    end try
  end tell
end tell

(*
プロパティ:

copies integer — プリントする書類の部数
collating boolean — プリントの丁合をとるかどうか
starting page integer — 書類からプリントする最初のページ
ending page integer — 書類からプリントする最後のページ
pages across integer — 物理的なページ上に横方向に並べる論理ページの数
pages down integer — 物理的なページ上に縦方向に並べる論理ページの数
requested print time date — デスクトッププリンタが書類をプリントするべき時間
error handling standard/summarized/detailed — エラーの処理方法
fax number text — 書類の送信先ファックス番号
target printer text — 出力先のプリントキューの名前

–用紙サイズを指定できないのはどういうことなのか?(汗) 用紙サイズ指定できなかったら意味ないやんけ!
*)

–プリントキューの名称一覧を取得
–10.6用に書き換え
on getPrintCues()
  set P to paragraphs of (do shell script "lpstat -p")
  
set pList to {}
  
  
set osVer to (system attribute "sys2") as number
  
  
repeat with i in P
    set j to contents of i
    
    
if osVer = 6 then
      –10.6
      
set aPName to trimStrings(j, "プリンター ", " は待機中です。") of me
    else if osVer = 5 then
      –10.5
      
set aPName to trimStrings(j, "プリンタ ", " は待機中です。") of me
    else if osVer = 4 then
      –10.4
      
set aPName to trimStrings(j, "printer ", " is idle. enabled since ") of me
    end if
    
    
if aPName is not equal to "" then
      set the end of pList to aPName
    end if
  end repeat
  
  
return pList
end getPrintCues
–任意の文字列から指定開始子、指定終了子でトリミングした文字列を取り出す
on trimStrings(aString, fromStr, endStr)
  set fromLen to length of fromStr
  
set eLen to length of endStr
  
  
set sPos to offset of fromStr in aString
  
if sPos = 0 then return ""
  
set body1 to text (sPos + fromLen) thru -1 of aString
  
set ePos to offset of endStr in body1
  
if ePos = 0 then return ""
  
set body2 to text 1 thru (ePos - 1) of body1
  
  
return body2
end trimStrings

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/02/04 Preview.appで用紙サイズおよび用紙方向を指定して印刷 v2

GUI Scripting経由でPreview.appで印刷を実行。プリンタ名、用紙サイズ、用紙方向を指定して印刷を行うAppleScriptです。

GUI Scriptingを使用しているため、「システム環境設定」の「ユニバーサルアクセス」で、「補助装置にアクセスできるようにする」をオンにしている必要があります。

ただし、使用プリンタは各ユーザー環境によって異なるため、そのまま使えるものとは思わないでください。

また、Preview.appで「画像オープン→印刷→画像クローズ」といった連続したフローを実現するものでもありません。Preview.appで画像をオープンすると、WindowのIDが画像をオープンするたびに+1されるようで、画像を1枚しかオープンしていないのにwindow 2を指定する必要があるとか、そういう状況を考慮した作りにはなっていません。

スクリプト名:Preview.appで用紙サイズおよび用紙方向を指定して印刷 v2
(*
2010/1/19

v2
Preview.appでは、書類をオープンするたびにWindowのインデックスがインクリメントされるらしく、
1枚目の書類はwindow 1でアクセスできるが、2枚目の書類(1枚しかウィンドウは開いていない)に
対しては、Window 2でアクセスする必要がある。これに対処する必要がある(問題未解決)

v1
シンプルタイプのプリントダイアログから拡張プリントダイアログに大きさをひろげたケースと、
最初から拡張プリントダイアログが表示されているケースでは、ポップアップメニューのIDが異なる。

拡張ダイアログが表示されていなかったら、拡張表示にして一度キャンセルし、再試行するようにした(10回まで)

*)

–set directionF to "V" –用紙方向=たて方向
set directionF to "H" –用紙方向=たて方向

set printerName to "PS-NX650"
set paperSize to "A4"

printViaGUI(directionF, printerName, paperSize) of me

on printViaGUI(directionF, printerName, paperSize)
  activate application "Preview"
  
tell application "System Events"
    tell process "プレビュー"
      
      
set goF to false
      
repeat 10 times
        –メニューから印刷を実行
        
click menu item "プリント…" of menu 1 of menu bar item "ファイル" of menu bar 1
        
        
tell window 1
          tell sheet 1
            –拡張プリントダイアログを表示させる
            
set sheetClosed to value of checkbox 1
            
if sheetClosed = 0 then
              click checkbox 1
              
click button "キャンセル"
            else
              set goF to true
              
exit repeat
            end if
          end tell
        end tell
        
      end repeat
      
      
if goF = false then return
    end tell
  end tell
  
  
  
  
  
activate application "Preview"
  
tell application "System Events"
    tell process "プレビュー"
      
      
–メニューから印刷を実行
      
click menu item "プリント…" of menu 1 of menu bar item "ファイル" of menu bar 1
      
      
tell window 1
        tell sheet 1
          
          
–出力先のプリンタを指定
          
tell pop up button 4 –「プリンタ」ポップアップボタン
            set aTitle to value
            
if aTitle is not equal to printerName then
              click
              
tell menu 1
                set mList to title of every menu item
                
set aRes1 to retIHitItem(mList, printerName as Unicode text) of me
                
if aRes1 = false then
                  return mList
                end if
                
click menu item aRes1
                
              end tell
            end if
          end tell
          
          
          
–用紙サイズを変更
          
tell pop up button 1
            
            
set aTitle to value as string
            
if aTitle is not equal to paperSize then
              click
              
tell menu 1
                set mList to value of every menu item
                
                
set aLen to length of mList
                
select menu item 1 –最終アイテムを選択しておく
                
                
set aRes2 to retIHitItem(mList, paperSize as string) of me
                
if aRes2 = false then
                  return false
                end if
                
click menu item aRes2
              end tell
            end if
          end tell
          
          
–用紙方向を指定
          
if directionF = "V" then
            click radio button 1 of radio group 3
          else if directionF = "H" then
            click radio button 2 of radio group 3
          end if
          
          
–「用紙サイズに合わせる」をクリック
          
click radio button 2 of radio group 1
          
          
–「プリント」ボタンをクリック
          
–click button "プリント"–ここをコメントアウトすると印刷を行う。
          
beep
        end tell
      end tell
    end tell
  end tell
end printViaGUI

–指定リスト中の何アイテム目かを調べて返す
on retIHitItem(aList, anItem)
  set aCount to 1
  
set hitF to false
  
repeat with i in aList
    set j to contents of i
    
if j = anItem then
      set hitF to true
      
exit repeat
    end if
    
set aCount to aCount + 1
  end repeat
  
  
if hitF = false then return false
  
  
return aCount
end retIHitItem

–GUI Scriptingの命令が続く中でdelayコマンドをエラーになるので、
–wait部分だけサブルーチン化
on waitSec(aNum)
  delay aNum
end waitSec

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/02/03 Preview.appでプリンタと用紙サイズを指定して印刷

一般的なAppleScriptの命令を使用して、特定のプリンタへの印刷は実行できますが、用紙サイズまでは指定できません。そこで、仕方なくGUI Scriptingを使用して印刷を実行することになります。

ここで、「仕方なく」という前置きが入るのは、GUI Scriptingという仕組みが通常のAppleScriptによる命令よりも遅く、また確実性が劣るためです。確実性が高くないといっても、OSやアプリのクラッシュを伴うようなレベルではなく、アプリケーション側の状態を詳細に調べながら操作しないと「思い通りに動かない」という話です。

■GUI Scriptingを使えるようにするために

GUI Scriptingが動作するためには、システム環境設定の「ユニバーサルアクセス」で「補助装置にアクセスできるようにする」にチェックが入っている必要があります。GUI Scriptingは使用に注意を要する機能であるため、デフォルト状態ではオフになっています。

sysprop.jpg

このチェックボックスをオンにすれば、GUI Scripting系の命令を実行できるようになります(プログラムを作成するだけであれば、オンにする必要はありません)。

■GUI Scriptingとは何なのか?

OS標準で搭載されているSystem Events.appが持っている「Process Suites」という命令群が、GUI Scripting(=UI Element Scripting)の命令です。他のSystem Eventsの命令については、システム環境設定/ユニバーサルアクセスでオンにしなくても普通に使えます。

sys2.jpg

一般的なAppleScriptでは、アプケーション内部のオブジェクトを経由して機能を呼び出すのに対し、GUI Scriptingはアプリケーションの外部からGUI部品を指定して命令を行います。このため、あるボタンを押そうとしたときに、もちろんオンになっていないと押せないですし、アプリケーション内部の状態がそのボタンがオンになる条件を満たしている必要もあります。

簡単な記述でアプリケーションをコントロールできるというのがGUI Scriptingの「理想」ではあるものの、実際に書いてみると……通常のAppleScriptとはまた別のマニアックなノウハウが必要な記法、と見るべきです。内部命令を経由しないでGUI ScriptingだけですべてのAppleScriptのプログラムを作成するというのが「幻想」というより「無理」であることはよく覚えておいてほしいと思います。通常のAppleScriptの「補助」的に使うのがGUI Scriptingの正しい使い方です。

■GUI Scriptingをはじめる前に

いろいろと前置きが長くなってしまいましたが、アプリケーションを無理矢理操作するため、「奥の手」としてGUI Scriptingが必要になるケースは確実にあります。そういう意味では、不完全なソリューションではあるものの、「じゃあいらないんだね?」とGUI Scriptingになくなられると困ります。ものすごく困ります。

GUI Scriptingでは、画面上のGUI部品を指定して命令を記述することになりますが、この部品の番号や並び順を知るためには、どうしてもツールが必要です。

(1)PreFab UI Browser
仕事でScriptを書く必要があるとか、確実かつ迅速にGUI Scriptingによるプログラムを作成する場合には必要です。ただし、このソフトでカバーできるのは8割程度であり、あとの残り2割をカバーするためには後述の「Accessibility Inspector」が必要になります(同ツールはXcode Toolsに含まれるため、Xcode Toolsのインストールが必須です)。

sys4.jpg

(2)Accessibility Inspector
Xcode Toolsをインストールすると、一緒に入ってきます。PreFab UI Browserでカバーできない一部のGUI部品の情報を調べるために必要です。具体的に言ってしまうと、PreFab UI Browserではポップアップメニューの内容までは追えません。とくに、ポップアップボタン「ではない」GUI部品からポップアップメニューを表示させるようなイレギュラーなプログラムでは本ツールの併用が必要です。

sys3.jpg

(3)「強引GUI Scripting」のためのツール
記述のために情報を調べるツールではなく、AppleScriptから命令して強引にマウスカーソルを移動させたりクリック動作させるようなツールです。ツールによって一長一短があるので、複数用意して用途に応じて使い分けるのが理想的です。プロのScripterはこの手のツールをいくつも手元に置いてあった、いざという時に備えています。何を使っているか、どの程度のAppleScriptライブラリを書きためているか等の情報はもちろんのこと、存在自体が門外不出のノウハウといえます。

これらのツールがそろってはじめて安心してGUI Scriptingのプログラムを作りはじめられます。……ない環境では、とても書く気になれません。

■アプリケーションの挙動を追う

GUI Scriptingでは、アプリケーションの状態を正確に認識した上で記述を行う必要があります。特定のウィンドウ上の特定のTabの中にあるGUI部品を操作する場合には、そのTabが表示されていなければなりません。ポップアップメニュー上の項目を選択するためには、ポップアップメニューを表示させておかなければなりません。通常のAppleScriptによるアプリケーション内部オブジェクト経由のコントロールの方が簡単と思えるほど、アプリケーションによってGUI部品の挙動が異なるため、正確な状況把握は欠かせません(PreFab UI Browser必須)。

■GUI部品の指定はIDか名前で

GUI ScriptingでGUI部品を指定する際には、window 1やmenu 1のように番号(ID)で指定する場合と、button “OK”のように名前で指定する場合があります。

名前で指定できたほうが、何を意味しているのか分りやすくてよさそうなものなのですが、名前で指定できるケースはあまり多くありませんし、だいたい……現在使用中の言語(日本語とか、英語とか)から別の言語環境でScriptを実行するような場合にはまったく動かなくなってしまいます。

このため、IDで指定することが多いのですが……アプリケーションがバージョンアップしたら、そのIDそのものも変わってしまうことが多々あり……GUI部品を検索して実行するような対策を行うケースもあります。

■実際に「プレビュー.app」のGUI Scriptingを行ってみよう

まずは、プレビュー.appで何も画像を開いていない状態で作業をはじめましょう。何もオープンしていない状態と画像をオープンしている状態でWindowの枚数がどう違うか、確認を行います。

何か画像をプレビュー.appでオープンすると、visibleなWindowの枚数が増えます。invisibleなwindowはほかにも何枚か用意しているようなので、ここでvisibleを指定しないで枚数を数えるとひどい目に遭います。

Windowの枚数だけでなく、画像をオープンしていない状態ではメニューの「プリント」の項目が有効になっていません。このため、「プリント」をGUI Scriptingで操作しようとしても、実行できません。このあたりで(オープンされている画像の有無を)判断するという手もあるわけです。

画像をオープンしている状態でメニューから「プリント」を実行できることを確認できたら、プリントダイアログの制御に入ります。

プリントダイアログは、デフォルトの小さいダイアログと拡張ダイアログで切り換えができるようになっており、この切り換えボタンの状態を取得して、「いま、どちらのダイアログが表示されているのか」を調べなければなりません。拡張ダイアログが表示されていないと、用紙サイズなどの詳細な情報にアクセスできません。

sys5.jpg

sys6.jpg

拡張ダイアログを表示して、用紙サイズやプリンタ名などを指定できるようになって、ようやくこれで出来上がった……と、安心していたのもつかの間……標準ダイアログの状態から拡張ダイアログに切り替えた後で、ポップアップメニューの操作が行えない。最初から拡張ダイアログが出ている分には問題ないのに……。

結論からいえば、同じGUI部品でも標準ダイアログと拡張の上でIDが異なっていました。さりとて、GUI部品に名前がついておらず名前による指定ができなかったので……拡張ダイアログが「出ていない」場合には、拡張ダイアログに切り換えたあとで、一度プリントをキャンセルし、再度プリント操作を行って拡張ダイアログ上の各種GUI部品をコントロールする……という方法で対処しました。

ちょっとしたことであれば、GUI Scriptingを少々かじったぐらいで処理できるかもしれません。ただし、そこに柔軟性を加えようとか、確実に動くようにしたい場合には、このぐらいの処理が必要になります。少々極端な例に見えるかもしれませんが、決して珍しいレベルではありません。

PreFab UI Browserを使って状態やIDを確認し、試行錯誤した末に最適な方法を見つけるなど、地道な……何かプログラミングとは別の作業のような気もするのですが、GUI Scriptingの実戦的なノウハウというのは、こういう感じのものです。

2008/10/12 10.5で(登録してある)プリンタ名称の一覧を取得するv3

Mac OS X 10.5で、システムに登録してあるプリンタの一覧を取得し、さらにデフォルトプリンタとして登録してあるプリンタ名を取得。ダイアログでプリンタ名一覧を表示し、デフォルトプリンタを選択状態にしておきます。

ダイアログで選択されたプリンタ名を返すサブルーチンです。デフォルトプリンタの設定もルーチン内で行っています。

スクリプト名:10.5で(登録してある)プリンタ名称の一覧を取得するv3
set pRes to setDefaultPrinter() of me

マシンにエントリされているプリンタから1つを選択してデフォルトプリンタに設定する
設定したプリンタの名称を文字列で返す
on setDefaultPrinter()
  tell application Printer Setup Utility
    set curPr to name of current printer
    
set curPrList to {curPr}
    
set myList to name of every printer
    
tell me
      set aRes to (choose from list myList default items curPrList)
    end tell
    
if aRes = false then return
    
set newPrinterName to item 1 of aRes
    
set current printer to printer newPrinterName
  end tell
  
return newPrinterName
end setDefaultPrinter

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2008/10/12 10.5で(登録してある)プリンタ名称の一覧を取得するv1

Mac OS X 10.5で、システムに登録してあるプリンタの一覧を取得します。

スクリプト名:10.5で(登録してある)プリンタ名称の一覧を取得するv1
tell application Printer Setup Utility
  set myList to name of every printer
end tell

> {”DC4055P”, “PM-T960″, “PS-NX650_Print”}

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2008/04/10 印刷可能なプリンタ一覧から選択してプリント実行

Mac OS X 10.4で拡張されたプリントオプション関連の命令を使ってみました。この例では登録されているプリントキューの一覧を取得して選ぶようにしてみましたが、デフォルトプリンタに出力するようにした方が実戦的でしょう。

ただ……用紙サイズの指定ができないのは、かなりこまりますね(ーー;;; このサンプルの方法以外にも、shellのlprコマンドを使ってプリンタに書類を送りつけるという方法があります。

スクリプト名:印刷可能なプリンタ一覧から選択してプリント実行
要・Mac OS X 10.4以上
set pList to getPrintCues() of me
set aPrinter to choose from list pList with prompt出力先のプリンタを選択してください

set aPrintSetting to {copies:1, starting page:1, ending page:1, target printer:aPrinter}

とりあえずSafariで印刷してみた。Safariである必要はない
tell applicationSafari
  tell document 1
    try
      print with properties aPrintSetting with print dialog「with」を「without」にすると、ダイアログなしで印刷
    on error
      display dialogプリント中になんかのエラーが発生しました。たぶん、キャンセルされたんでしょうbuttons {”OK“} default button 1
    end try
  end tell
end tell

(*
プロパティ:

copies integer — プリントする書類の部数
collating boolean — プリントの丁合をとるかどうか
starting page integer — 書類からプリントする最初のページ
ending page integer — 書類からプリントする最後のページ
pages across integer — 物理的なページ上に横方向に並べる論理ページの数
pages down integer — 物理的なページ上に縦方向に並べる論理ページの数
requested print time date — デスクトッププリンタが書類をプリントするべき時間
error handling standard/summarized/detailed — エラーの処理方法
fax number text — 書類の送信先ファックス番号
target printer text — 出力先のプリントキューの名前

–用紙サイズを指定できないのはどういうことなのか?(汗) 用紙サイズ指定できなかったら意味ないやんけ!
*)

プリントキューの名称一覧を取得
on getPrintCues()
  set P to paragraphs of (do shell scriptlpstat -p“)
  
set pList to {}
  
repeat with i in P
    set j to contents of i
    
set aPName to trimStrings(j, “printer “, “ is idle. enabled since “) of me
    
if aPName is not equal to “” then
      set the end of pList to aPName
    end if
  end repeat
  
  
return pList
end getPrintCues
任意の文字列から指定開始子、指定終了子でトリミングした文字列を取り出す
on trimStrings(aString, fromStr, endStr)
  set fromLen to length of fromStr
  
set eLen to length of endStr
  
  
set sPos to offset of fromStr in aString
  
if sPos = 0 then return “”
  
set body1 to text (sPos + fromLen) thru -1 of aString
  
set ePos to offset of endStr in body1
  
if ePos = 0 then return “”
  
set body2 to text 1 thru (ePos - 1) of body1
  
  
return body2
end trimStrings

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2008/03/09 デフォルトの出力先のプリンタ名称(キュー名称?)を取得

スクリプト名:デフォルトの出力先のプリンタ名称(キュー名称?)を取得

set a to retDefaultPrinter() of me
a

デフォルトの出力先のプリンタ名称(キュー名称?)を取得
on retDefaultPrinter()
  set aShellText tolpstat -s | head -n 1
  
set aRes to do shell script aShellText
  
if aRes does not start withsystem default destination:then
    return “”
  else
    set aPos to offset of:in aRes
    
if aPos is not equal to 0 then
      set aText to text (aPos + 2) thru -1 of aRes
      
return aText
    else
      return “”
    end if
  end if
end retDefaultPrinter

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に