Archive for 10月, 2008

2008/10/30 Microsoft Office 2008用の「VBAからAppleScriptへの移行支援ガイド」が公開

マイクロソフトから、「VBA から AppleScript への移行支援ガイド」が公開されました。

ながらく、公開が待たれていたドキュメントであり、これでOffice 2008のAppleScriptによるカスタマイズやワークフローの自動化が楽にできるようになることでしょう。

2008/10/24 オープン中のデータベースでソート

FileMaker Pro v9でキーとなるフィールドを指定してソートを行います。
(more…)

2008/10/24 オープン中のデータベース中のテーブルの特定レコードにおけるフィールドのデータのバイト数を取得

FM v9で、オープン中の(最前面の)データベースのテーブル1の、特定のレコード(最初のレコード)における特定フィールドのデータサイズを取得します。
(more…)

2008/10/24 オープン中のデータベースで条件検索(複数条件)

FMv9で、オープン中の(最前面の)データベースの、テーブル1に対してshow命令によって検索を行います。
(more…)

2008/10/24 オープン中のデータベースのレイアウトの名称を取得する

FM v9で、オープン中の(最前面の)データベースの、レイアウトの名称一覧を取得するサンプルです。
(more…)

2008/10/24 オープン中のデータベースのレイアウト(画面)を数える

FM v9で、オープン中の最前面のデータベースに含まれるレイアウト(画面)を数えます。
(more…)

2008/10/24 オープン中のデータベース中のテーブル1にあるフィールドを数える

FM v9で、database 1(document 1)というのは最前面のデータベースを指すことになります。
(more…)

2008/10/24 オープン中のデータベースの中にあるテーブル数を数える

FileMaker Proで、オープン中のデータベース(のうちの最前面にあるもの)の中にいくつテーブルが存在するかをカウントします。
(more…)

2008/10/23 FM v7〜9で、オープン中のデータベースを数える

FileMaker Proは6までと7以降で別物と考えてよいほど変わりました。AppleScriptから見ると、データベース(書類)の中に複数のテーブルを持てるようになったことと、1つのデータベースのウィンドウを複数開けるようになったこと、FileMaker Scriptステップの中にAppleScriptを記述して実行すると、画面を書き換えないでScriptを実行するため、外部からFileMakerをコントロールするよりもはるかに高速に制御できるようになりました。
(more…)

2008/10/21 PDFのページ数を数えるv3

PDFのページ数を数えるScriptを久しぶりに動かしてみたら、Mac OS X 10.5.5上で期待どおりの動作を行わなかったので、修正を行ってみました。

画面上のウィンドウの文字やメニューの状態を検出して処理を行うUI Element Scripting(GUI Scripting)を用いた場合に、アプリケーションの画面構成が変更になると当初の想定どおりの動作が期待できなくなってしまう、その実例といえるでしょうか。

preview_app.jpg

Mac OS X 10.4と10.5のPreview.appでは、PDFのページ数表示が異なります。Mac OS X 10.5では当初は異なる表示を行っていたのですが、途中で変更になったようです。

とりあえず、極力バージョンに依存しないよう配慮して修正してみました。

→ こちらの方がおすすめです

スクリプト名:PDFのページ数を数えるv3
set a to choose file
set pNumStr to getPDFPages(a) of me
set pNum to pNumStr as number

指定PDFのページ数をPreview.appを使って数える。要・GUI Scriptingオン
Mac OS X 10.4および10.5対応
ただし、日本語環境であることが動作の前提条件
on getPDFPages(aFile)
  tell application Preview to open aFile
  
activate application Preview
  
tell application System Events
    tell process プレビュー
      tell window 1
        set aTitle to title
      end tell
      
keystroke w using command down
    end tell
  end tell
  
  
このあたりを変更した(v3) 10.4 & 10.5で共通ルール
  
set pRes to trimStrings(aTitle, “, “) of me
  
set pRes to repChar(pRes, ページ“, “”) of me
  
if pRes contains / then
    set aPos to offset of / in pRes
    
set pRes to text (aPos + 1) thru -1 of pRes
  end if
  
  
return pRes
end getPDFPages

任意の文字列から指定開始子、指定終了子でトリミングした文字列を取り出す
あんまり出来がよくないのでちょっと直した
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
  
set body1 to text (sPos + fromLen) thru -1 of aString
  
set ePos to offset of endStr in body1
  
set body2 to text 1 thru (ePos - 1) of body1
  
  
return body2
end trimStrings

文字置換
on repChar(origText, targChar, repChar)
  set origText to origText as string
  
set targChar to targChar as string
  
set repChar to repChar as string
  
  
set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to targChar
  
set tmpList to text items of origText
  
set AppleScript’s text item delimiters to repChar
  
set retText to tmpList as string
  
set AppleScript’s text item delimiters to curDelim
  
return retText
end repChar

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

2008/10/19 アドレスブックで選択中のPersonの情報を取得する

アドレスブックで、選択中のPersonの情報を取得します。AppleScriptにおいて、アプリケーションの画面上で選択中のオブジェクトの情報を取得する機能は、最も重要で欠かせないものです。

選択中のオブジェクトを取得するにあたり、3つほど考慮すべき重要なポイントがあります。

1つ目は、アプリケーションが複数のウィンドウを表示可能なタイプかどうかということです。エディタやワープロのように「書類」を1つのウィンドウで扱うものだけでなく、Mail.appのように複数のビューワーウィンドウをオープンできるものもあります。こうしたアプリケーションの場合、最前面のdocumentやviewerを求め、それらに対してselectionを取得することになります。

2つ目は、選択中のオブジェクトが複数同時に選択可能かどうか、ということです。1つのオブジェクトのみ選択されるアプリケーションであれば、selectionの情報をそのまま使えますが、複数選択が可能な場合には複数のオブジェクトに対応できるように処理を記述しておくことになります。

3つ目は、選択中のオブジェクトの種類です。selectionで取得されるオブジェクトの種類(=class)が一定の場合(アドレスブックなど)と、そうでない場合(InDesignなど)があります。

アプリケーションの開発者側がこうした状況をきちんと認識していないと、対応が中途半端でScriptingしづらくなり、「AppleScriptを正しく書いたつもりなのに、期待した結果が得られない」ことになったりもします。これが、AppleScriptの習得を困難にしているケースもあり、海外のScripterと情報を共有することがたいへん重要です。

スクリプト名:アドレスブックで選択中のPersonの情報を取得する
tell application "Address Book"
  set aPerson to selection
  
set aSel to item 1 of aPerson
  
tell aSel
    properties
  end tell
end tell

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

2008/10/19 アドレスブックで所有者の情報を取得する

アドレスブックで、所有者(ログイン中のユーザー)の情報を取得するサンプルです。AddressBookの登場当初、この機能がなくてずいぶんと苦労させられましたが……。

スクリプト名:アドレスブックで所有者の情報を取得する
tell application "Address Book"
  set myCard to my card
  
> person id "094F257D-ED10-4844-B9FD-59FD995D3A69:ABPerson"
  
  
tell myCard
    set fName to first name
    
set lName to last name
    
set yomiganaF to phonetic first name
    
set yomiganaL to phonetic last name
    
    
set nameText to lName & fName > 長野谷隆昌
    
set phoneticTect to yomiganaL & yomiganaF >ナガノヤタカアキ
    
  end tell
end tell

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

2008/10/19 指定フォルダ以下のすべてのフォルダ、ファイルを求める(例外処理に対応)

指定フォルダ以下のすべてのファイルおよびフォルダを取得するのに、entire contentsを使用することがありますが、これをentire contents as listで取得すると大幅に高速化できます。

ところが、entire contents as listを使うと、指定フォルダ以下にファイルが1つしか存在しない場合にはエラーになってしまいます。AppleScript処理系のバグ……というよりは、仕様に見えます。

そこで、entire contents as listを実行する前に、ファイルの数を数えておき、ファイルがない場合とファイルが1つの場合に例外処理を行うようにしてみました。

ただし、指定フォルダの直下に数十万ファイル以上存在しているような場合、ファイル数をカウントした場合の挙動が分りません。そうした状況が想定される場合には、ファイルのカウントをshell scriptで行っておくなど、より慎重な対応が必要になります。

スクリプト名:Entire Contentsをas alias listで取得する場合に、ファイルが1つだけだとエラーになる
set tmpPath to choose folder
set allFile to getEntireContets(tmpPath) of me

on getEntireContets(anAlias)
  tell application "Finder"
    tell folder anAlias
      set fCount to count every file
      
      
if fCount > 1 then
        set fList to entire contents as alias list
      else if fCount = 0 then
        ファイルがなかった場合
        
set fList to {}
      else
        ファイルが1つしかなかった場合
        
set fList to every file as alias
        
set fList to fList as list
      end if
    end tell
  end tell
  
  
return fList
end getEntireContets

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

2008/10/12 ColorSync Scriptingで各種情報を取得

ColorSync関連の情報を取得するサンプルです。ここらへんの情報は、Mac系の開発者でも取得する方法を知っている人が少なくて……Cocoa系のMLでもColorSync系のMLでも答えが見つからなかった(質問もしてみたものの、誰も分らない)のですが、ふつーにAppleScriptを書いてみたらアッサリ求められた(脱力)ということがありました。

スクリプト名:ColorSync Scriptingで各種情報を取得
tell application ColorSyncScripting
  run
  
system profile location
  
> file “Cherry:Library:ColorSync:Profiles:Displays:Color LCD-4271840.icc”
  
  
default RGB profile location
  
> file “Cherry:System:Library:ColorSync:Profiles:Generic RGB Profile.icc”
  
  
default CMYK profile location
  
> file “Cherry:System:Library:ColorSync:Profiles:Generic CMYK Profile.icc”
  
  
default Lab profile location
  
> file “Cherry:System:Library:ColorSync:Profiles:Generic Lab Profile.icc”
  
  
default XYZ profile location
  
> file “Cherry:System:Library:ColorSync:Profiles:Generic XYZ Profile.icc”
  
  
default Gray profile location
  
> file “Cherry:System:Library:ColorSync:Profiles:Generic Gray Profile.icc”
  
  
system profile
  
> profile “カラー LCD”
  
  
default RGB profile
  
> profile “一般 RGB プロファイル”
  
  
default CMYK profile
  
> profile “一般 CMYK プロファイル”
  
  
default Lab profile
  
> profile “一般 Lab プロファイル”
  
  
default XYZ profile
  
> profile “一般 XYZ プロファイル”
  
  
default Gray profile
  
> profile “一般グレイプロファイル”
  
  
preferred CMM
  
> “appl”
  
  
profile folder
  
> file “Cherry:System:Library:ColorSync:Profiles:”
  
end tell

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

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/10/06 Keynoteでslideの情報を取得する

Keynoteで、現在開いている書類(slideshow 1)の情報を取得するAppleScriptです。

slideshow 1の中に複数枚のslideがあって、現在選択中のslideは「current slide」、ファイルのパスは「path」で取得できるものの、なぜかPOSIX pathが返ってきます。

Apple純正のアプリケーションでも、書類のfile pathについては統一がとられておらず、POSIX pathだったりMac OS形式のFile Pathが帰ってくることがあったりと、気をつけておかなくてはならない部分です。きちんと、AppleScriptチームがアプリの仕上がりについて目を光らせてチェックしておく必要があるはずですが、そこまで手が回っていないようです。

スクリプト名:Keynoteでslideの情報を取得する
tell application Keynote
  tell slideshow 1
    properties
  end tell
end tell

> {modified:false, current slide:slide “0″ of document “test” of application “Keynote”, class:document, path:”/Users/maro/Desktop/test.key”, playing:false, name:”test”}

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

2008/10/06 デスクトップ上のピクチャファイルを指定フォルダに移動

デスクトップに散らかってしまったスクリーンショットのファイル(例:ピクチャ 1)を指定フォルダ内に移動させるAppleScriptです。

いつも持ち歩いている17インチMacBook Proのデスクトップにスクリーンショットのファイルがたまっていたので、喫茶店ですぐに組んで使ってみた「使い捨て」系のAppleScriptです。

スクリプト名:デスクトップ上のピクチャファイルを指定フォルダに移動
set aFol to choose folder with prompt "デスクトップ上の画像ファイルの移動先フォルダを選択してください。"
set dtFol to path to desktop from user domain
set dtFolStr to dtFol as string

tell application "Finder"
  tell folder dtFolStr
    set fList to every file whose name begins with "ピクチャ"
    
move fList to aFol まとめてファイル移動
  end tell
end tell

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

2008/10/04 リストの一部を取り出す

Excelのワークシート上で選択した範囲からデータを取得して処理を行う……というのは定番ですが、取得したデータのうち一番上の方はヘッダー行だったり、一番左の方はヘッダー列だったりして、処理時には削除できたほうがメリットが大きい場合もあります。
(more…)

2008/10/02 DragThingで、最前面のDock上で現在選択されているレイヤーの名称を返す

DragThingで、最前面のDockのうち現在選択されているレイヤーの名称を取得するAppleScriptです。

現在選択中のDockの名称……の部分の記法が一番難しかった部分で、AppleScriptの世界では各アプリケーションの最前面のドキュメントに対する指定方法があったりなかったり(まさに、アプリケーション側の対応次第)するわけで、だいたいは「Window 1」にアクセスしてみると大丈夫な場合が多いのですが、これを明示的にfront windowとかfront documentといったアクセス方法が提供されているケースもあり、なかなか悩まされるポイントです。

アプリケーションによっては、Window 1にアクセスできたとしても、Window 1がどのドキュメント(ファイル名)に該当するものなのか、情報を取得できない場合があったり……また、windowではなくdocumentオブジェクト経由でアクセスしてdocument 1で最前面の書類にアクセスできることもあります(これは例外中の例外であり、だいたいdocumentはオープンした順に番号がつきます)。

結局、このScriptを試作できた結果、「選択中のレイヤーで起動回数ランキングを表示」という大物Scriptを作ることができました。

スクリプト名:DragThingで、最前面のDock上で現在選択されているレイヤーの名称を返す
tell application DragThing
  最前面のDockの名称を取得
  
tell window 1
    set curDock to name
  end tell
  
  
最前面のDock上で現在選択されているレイヤーの名称を返す
  
tell dock curDock
    set curLayer to current layer
    
tell layer curLayer
      set curLayerName to name
    end tell
  end tell
end tell

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

2008/10/02 DragThingの特定のDock中で現在選択中のレイヤーを求める

DragThingの特定のDock中で、現在選択中のレイヤー名を求めるAppleScriptです。DragThing上で現在選択中のDockの中の現在選択中のレイヤーを求めるための試作品です。

スクリプト名:DragThingの特定のDock中で現在選択中のレイヤーを求める
tell application "DragThing"
  tell dock "AppDock" 任意のDock名称。各ユーザーごとに違う
    set curLayer to current layer
    
tell layer curLayer
      set aName to name
    end tell
  end tell
end tell

aName
> "環境設定"

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

2008/10/02 DragThingで表示しているDock名称を取得する

アプリケーションランチャーといえばDragThing、というのが一昔前(1999年ごろ)の定番だったのですが、Mac OS XにDockが標準搭載され、ライトユーザーとかビギナーはこれしか(Dock)しか知らないというのが昨今の状況。しかし、手になじんだDragThingはいまだに手放せないアプリケーションのうちのひとつです。

DragThingは昔から(Classic Mac OSの時代から)AppleScriptに対応していたのですが、DragThingをAppleScriptからコントロールする「意義」については疑問視していました。

それが……起動回数のランキングを表示したり、DragThingのDockの中をキーワード検索したりといったAppleScriptを組んでみたら、これが予想外に便利で……最近ではDragThing向けのAppleScriptも書くようになりました。とりあえず、本Scriptはオープン中のDragThingのDockの名称について取得するものです。name of every dock……でも名称一覧を取得できるような気もしますが、次のプログラムのための試作品としての性格が強いものであり、あえてこう書いています。

スクリプト名:DragThingで表示しているDock名称を取得する
tell application DragThing
  set a to count every dock
  
set nameList to {}
  
repeat with i from 1 to a
    tell dock i
      set the end of nameList to name
    end tell
  end repeat
end tell

nameList
> {”URLどっく”, “AppDock”}

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

2008/10/02 1年分のカレンダーリストを作成して指定日が何週目かを求める v2.1

このサブルーチンを利用して、さらに高機能な処理を書いていたところ……「おかしい、結果が0(指定日がカレンダー中に見つからないエラー)になる日がある」ということに気付き、1/1から順に総当たりでチェックしたところ、バグの存在を確認しました。

バグの発生箇所は、予想どおり高速化処理を行った部分。スキップする週の数を「(月-1) *4」とすべきところを「月*4」としていました。その部分をv2.0から修正しました。
(more…)