アプリケーションの自動操作

AppleScriptも登場してほぼ2年経ち、多くのユーザが利用できる環境が整ってきた。そろそろこれをオフィスでも使いこなすときが来ているようだ。

ハイパーカードとAppleScript

ついにハイパーカード(Lite版)のバンドルがなくなり、マッキントッシュについてくるのはハイパーカードプレイヤーというただの再生装置になってしまった。ハイパーカードは強力な機能と柔軟な使いやすさを持ちながら「無料で」誰にでも利用できるという点が魅力だったのだが、この重要な条件が一つ欠落してしまうわけだ。残念というほかない。

さて、System 7から導入されたAppleScriptは、マッキントッシュに初めて標準的なスクリプト環境を提供する画期的なものだが(しかも無料である)、適切な文献がなかったり資料が手に入りにくいために、まだ十分に使いこなされているとは言いがたい。一方、登場からまもなく10年になるハイパーカードは、マッキントッシュで手軽に自動操作を行うためのほぼ唯一の手段として幅広く使われ、参考文献やフリーウェアのスタックも豊富だ。スクリプティング言語のHyperTalkは柔軟で強力であり、外部命令による拡張が可能なため、ハイパーカードの環境内で多彩なことが実現できる。とはいうものの、基本的にアプリケーションの遠隔操作はできないから、オフィスでの活用という意味ではやや物足りない。

それが、ハイパーカードのバージョン2.2からはスクリプト言語としてAppleScriptも利用可能となった。つまり、ハイパーカードではHyperTalkとAppleScriptを組み合わせ、ボタンのクリック一つで全ての作業を実行させることも可能になったのである。

アプリケーションをハイパーカードから操作する

AppleScript自身の使い方についてはここでは詳しく触れない。今回は、ハイパーカードからFileMakerProを操作するスクリプトを例に、HyperTalkとAppleScriptの違いやハイパーカードから外部アプリケーションを扱うに当たっての注意点などを見ていくことにする。

しかし、なぜここでFileMakerProなのか?

ハイパーカードは強力な環境ではあるが、いくつかの不得意な分野もある。そのひとつが文書のレイアウトと印刷であることは、ハイパーカードを利用していればすぐに気がつく。FileMakerのようなデータベースソフトの便利な点は、データの蓄積/検索だけでなく、印刷のための出力フォーマットを自由に設定できるところだ。この長所を生かして、テキストとして蓄えた情報をハイパーカード経由でFileMakerのフォーマットに送り込み、必要な書式で印刷できるようにしてみようというのが今回の主旨である。

同様にして、エクセルや他のアプリケーションをハイパーカードから利用することは十分考えられる。ただ、外部アプリケーションの利用はデータの加工や分析のためであって、あくまでもオリジナル情報はテキストとして保存べきだという考えは変わっていない。素材は調理しない活きのいい形で残すに越したことはないのだ。

電子メールからFileMakerのテンプレートへ

具体例として、テキストファイルとして蓄積した電子メールから必要なものを選びだし、FileMakerProのテンプレートを使って見栄えのする文書として印刷する方法を考えてみよう。これからは報告書を電子メールで送るというケースも増えるだろうが、まだ紙でないと受け付けない上司がいる場合は、こういう印刷フォーマットは重宝するはずだ。メールはとりあえず例によってHDB形式(注1)に保存しているものとして話を進めることにする。

ところで、HDBは1行目がタイトルとなり、残りの部分は全て本文とみなすというものであった。レコードを構成する要素としては2つしかなく、このままではデータベースの様々なフィールドを扱うには不十分だ。テキストファイルである利点を生かしたまま多フィールドに対応させるために、HDBを拡張し、1行目のタイトルの中に「アイテム」として複数の情報をもたせることにしよう。

ここでは、HDBのタイトル行を

日付 (TAB) 発信者名 (TAB) 題名

という形に設定しておく。そして2行目以降がメールの本文となるわけだ。受信したメールをこの形で保存しておけば、従来のHDBをそのままメール管理にも使えることになる。

多フィールドに対応したHDB

画面 データファイルの準備やインデックスの作成は1995/7号の通りなので繰り返さない。この拡張版では、タイトル行が複数フィールドにわたる情報を保持しているので、その扱いについて簡単に触れておこう。違いは一覧をクリックしてデータを表示する時に、フィールドに分けるという操作が加わる点だ。リスト1の1〜5行目は従来と同じ。今回は、6行目でitemDelimiterをTABにセットした上でitem1, item2...と拾っていき、レコードをフィールドに振り分けてカード上に表示する(画面1)。この方法なら、メールアドレスなどのフィールドを後で追加するのも簡単だ。

このようにしてあらかじめフィールドごとに分解したレコードを、FileMakerProのテンプレートに送り込んで、対応するデータベースのフィールドに情報を流し込み、好みのレイアウトで印刷する。たとえば画面2のようなレイアウトを用意するとしよう。このフィールドにきちんとデータをコピーするのがAppleScriptの役割である。

スクリプトをAppleScriptで書く

ハイパーカードのスクリプトとしてAppleScriptを選ぶためには、画面3のように、スクリプトエディタのポップアップメニューでスクリプティング言語を切り替える。

エディタで言語を「選択」することから分かるように、一つのスクリプトの中でHyperTalkとAppleScriptを混在させることはできない。しかし、例えばボタンスクリプトをHyperTalkにしておき、そこからAppleScriptで書いたカードやバックグラウンドのサブルーチン(注2)を呼び出すことは可能である。戦略としては、手慣れたHyperTalkでデータ処理を行い、AppleScriptはそれにしかできないこと(例えば外部アプリケーションの制御)のみを任せるという使い分けを工夫したい。

サンプルではバックグラウンドにAppleScriptを置いた。リスト2は、ボタンから呼び出されてFileMakerProのフィールドデータを設定するサブルーチンである。一見HyperTalkのハンドラのようだが、AppleScriptのサブルーチンの場合は引数を()で囲まなければならない。ここでは引数として各フィールドのデータとデータベースファイルの名前を渡している。2行目はAppleScriptがFileMakerProに対して働くことの宣言文。3〜4行目では、もし準備ができていなければFileMakerProを起動し、目的のデータベースを開く。既に立ち上がっている場合は、これを前面に出す働きをする。

各フィールドへのデータのコピーは、5〜8行でSet命令を使って行う。ここでField "When"ではなく、Cell "When"とすることに注意して欲しい(注3)。

外部アプリケーションのデータについて

あとはこのサブルーチンに、ボタンスクリプトからハイパーカード上のフィールドの内容を渡せば良さそうに見える。基本的にはその通りなのだが、単純にフィールドのデータを与えてしまうと、FileMakerProには肝心の本文が1行だけしかコピーされない。これは、アプリケーションごとにデータ処理のルールがあり、それに合わせたデータを送り出なければ正しく理解してもらえないことが原因だ。この辺りが、ハイパーカードを離れて外部アプリケーションを操作するときの難しさと言えるだろう。

ここで本文が1行だけしかコピーされないのは、FileMakerProがフィールド内での改行を特殊な方法で処理しているからだ。FileMakerProでデータの書き出しを行ってみれば分かるように、通常の改行はFileMakerProにとってはレコードの区切りという意味を持つ。そのため、フィールド内の改行はRETURN(ASCIIコード13)ではなく、ASCIIコード11という記号によって表されている。したがって、ハイパーカード(テキストファイル)の情報をFileMakerProに渡す前に、この改行コードの処理を行わなければならないのである。

といっても大袈裟なことではなく、リスト3のような簡単な処理をボタンスクリプトに加えればよい。データを1行ずつ拾って、それらをnumToChar(11)で得られるASCIIコード11の記号でつないでやるわけだ。このデータをFileMakerProにコピーすると、そのフィールド内では改行された文章として表示される。

2つのスクリプト言語を使い分ける

このような作業は手慣れたHyperTalkならわけなくこなせるが、同じことをAppleScriptで行おうとすると思わぬ苦労をする羽目になる。たとえば、リスト3の処理を考えた場合、AppleScriptにはlineというコンテナが存在しない。これをparagraphと書き換えればよいと分かるまでには、参考書や雑誌記事をあちこちひっくり返す必要がある。今後の応用範囲を考えた場合、AppleScriptを勉強しておくのも一つの手かもしれないが、せっかくHyperTalkで簡単にできるなら、これを使わない手はないだろう。

前に述べた原則を最後に繰り返しておく。データ処理をHyperTalkで、アプリケーションの操作をAppleScriptで。これが複合スクリプトによるハイパーカードオフィス実現のポイントである。

*注1

1995/7号で作成したHyperDB形式のデータのこと。レコードをハイフン2つの行(--)で区切り、各レコードの最初の1行を見出しとするテキストファイル。添付CD-ROMに、これまでの連載のテキストをこの形式で収録している。

*注2

AppleScriptの命令のブロック(on xxx〜end xxx)をサブルーチン(subroutine)と呼ぶ。HyperTalkのようなコマンドと関数の区別はなく、全てのサブルーチンは関数と同じように結果を呼び出し側に返し、引数を取るときは()で囲む必要がある。

*注3

FileMakerProにおいては、Field "When"は全レコードの"When"というフィールドの内容全体、Cell "When"は現在のレコードにおける"When"の内容を指すというように定められている。こうしたルールはアプリケーションごとに異なり、これを調べるには「スクリプト編集プログラム」の「用語説明...」メニューを使うしかない。このような複雑さと情報の不足が、AppleScriptを使う上での障害となっている。

用語

HyperTalkとAppleScriptの違い

HyperTalkとAppleScriptは、全体的によく似た感じだが、細かい部分でかなり違いがあり、スクリプトを記述するときに躓きやすい。例えばHyperTalkではitという変数はget命令などの結果が収められる便利な入れ物だが、AppleScriptではitは現在対象となっているオブジェクトを指す。そしてget命令の結果はresultという変数に納められる。また、変数Xに数字20を代入する場合、HyperTalkでは

put 20 into X

とするが、AppleScriptでは

copy 20 to X (またはset X to 20)

となる。

itemDelimiter

通常ハイパーカードのアイテムはカンマ(,)によって分けられているが、このプロパティを変更することで他の文字をアイテム区切り文字として指定することができる。これによって、例えばTABで区切られた情報をハイパーカードのアイテムとみなすことが可能となり、データベースや表計算ソフトとのデータ交換が容易になる。

NumToChar

全ての半角文字はASCIIコードと呼ばれる1〜255までの数字に対応している。NumToChar()はこのASCIIコードを文字に変換する関数で、これを使うとASCII 11のようなキーボードから直接入力できないコントロール文字もスクリプト内で指定することが可能。この逆を行う関数がCharToNum()で、文字を与えると対応するASCIIコードが得られる。

リスト

リスト1

--一覧フィールドのスクリプト
--fld "Index"にはHDBの区切り行の位置がある
--ReadFile()はファイルを読み出す関数

 1: on mouseUp
 2:   put (word 2 of the clickLine) into lineNo
 3:   put line lineNo to LineNo + 1 of fld "Index" into pos
 4:   put ReadFile(fld "FileInfo") into str
 5:   get line (line 1 of pos + 1) to (line 2 of pos - 1) of str
 6:   set itemDelimiter to TAB
 7:   put item 1 of line 1 of it into fld "When"
 8:   put item 2 of line 1 of it into fld "Who"
 9:   put item 3 of line 1 of it into fld "Subject"
10:   delete line 1 of it
11:   put it into fld "Text"
12: end mouseUp

リスト2

 1: on FMPrint(aDate, aName, aSubject, aText, aFile)
 2:   tell application "FileMakerPro"
 3:     activate
 4:     Open file aFile
 5:     Set Data Cell "When" To aDate
 6:     Set Data Cell "Who" To aName
 7:     Set Data Cell "Subject" To aSubject
 8:     Set Data Cell "Text" To aText
 9:   end tell
10: end FMPrint

リスト3

 1: get fld "Text"
 2: put "" into aText
 3: repeat with i=1 to number of lines of it
 4:   put line i of it & numToChar(11) after aText
 5: end repeat

(MacUser Japan, March 1996)