プログラム講座 中級編10
- クリップボード経由でエクセルのデータを読み込む -
中級編10です。今回はマイクロソフトエクセル(Microsoft Excel Ver 5)とのデータをやりとりします。やりとりといっても今回は一方的にエクセルからデータを受け取るだけでエクセル側には何も返しません。
データのやりとりはファイル等で行われる場合がほとんどですが、今回は「クリップボードを経由」してデータのやりとりを行います。
◆クリップボード
Macintoshは「コピー」「カット」を行うと自動的に「クリップボード」に、その内容が入ります。一旦クリップボードに入れておけば、あとは「ペースト」するとクリップボードの内容がドキュメントに貼り付く仕組みになっています。
クリップボードには「テキスト」「サウンド」「ピクチャ(グラフィック)」「ムービー」など、ありとあらゆるもの、そしてそれらが混在したものが入ります。つまり何のデータでも入ると思って良いでしょう。
以下にテキストとピクチャ(グラフィック)をコピーした場合のクリップボードの内容を示します。
ウィンドウの中に「クリップボードの内容 テキスト」、「クリップボードの内容 ピクチャ」と表示されているのがわかるでしょう。これがクリップボードに入っているデータの種類を示しています。
今回はMacユーザーには嫌われている(?)マイクロソフトのソフトである「エクセル」からFuture BASICにクリップボード経由で数値データを読み込み表示するプログラムを作成します。まずはエクセルで数値データをコピーした時にクリップボードにどんな内容が入るか確認してみましょう。
◆エクセルで数値データをコピーすると?
まずはエクセルを起動して数値データを入力しコピーしてみましょう。
− エクセルを起動 −
− 数値データを入力しコピー −
− クリップボードの内容 −
クリップボードに入った内容を調べてみると以下のようになっています。
横方向のデータ | タブコード(TAB:09)で区切られている |
縦方向のデータ | 改行コード(CR:13)で区切られている |
エクセルで数値で入力してもクリップボードに入るのは数値を文字列化した「テキスト」になります。クリップボードに入るデータ内容が分かれば後はクリップボードから読み出して表示するだけです。
◆クリップボードからテキストを読み込む
幸いクリップボードからテキストを読み込むサンプルがハンドブックマニュアルの150頁にありますので、それを参考にしてプログラムを作成します。
クリップボードのデータは「ハンドル」で返されますので、あらかじめ空っぽのハンドルを用意しておきます。空のハンドルを用意するには
myHandle& = FN NEWHANDLE(0)
のように0を指定します。次にクリップボードからデータがあるハンドルを取得します。クリップボードに入っているデータハンドルを得るには以下のようにします。
theLength& = FN GETSCRAP(myHandle&,_"TEXT",dataOffset&)
theLength&にはデータのサイズが入ります。今回のテキストの場合はテキストの長さが入ります。パスカル文字列やC言語の文字列とも異なり、文字列の長さを示すコードやエンドコードは入っていませんので注意してください。
myHandle&は実際のデータが格納されているハンドルが入ります。_"TEXT"は取得したいデータのタイプを指定します。テキストなら"TEXT"、ピクチャ(グラフィック)ならばPICT"といった具合になります。
dataOffset&は取得したいデータのオフセットを返します。データが先頭にある場合は0になります。エクセルから数値データをコピーした場合データの種類は"TEXT"で1まとまりで入りますのでデータオフセットは必ず0になります。
取得したハンドルから今度はテキストデータを読み出さなければなりません。まず、最初にハンドルを「ロック」しなければいけません。ロックしない場合、正常に動作せずシステムエラーを引き起こすこともあります。
データを1バイト読み込むには
c = PEEK([ myHandle& ])
とします。cには0〜9までの文字のアスキーコードや+、−(プラス、マイナス)を示すアスキーコードが入ります。データは数値ではなくテキストで入っているため「テキスト→数値」に変換しなければなりません。変換方法は今回のプログラムで使用したVAL()関数を使う方法と毎回 d = d + (c - &H30)*10のように加算していく方法があります。手間は変わりませんので好きな方を使えばよいでしょう。
データの区切りはタブコードか改行コードですが、チェックする場合は「タブか?改行コードか?」では判別せずに空白のアスキーコード(&H20)未満かどうかで「区切りかどうか」判断しています。区切りだったらWHILE〜WENDループを抜けるという具合になっています。
正常にデータを読み出すことが出来たらretFlag%を_trueにし、そうでない場合は_falseにします。
◆終わりに
この講座では初めて他のソフトとの連携ネタです。連携といっても今度はFuture BASICからエクセル側にデータを渡さないと一方通行になってしまいます。実際にはクリップボードよりもファイルを使ってデータをやりとりする方が楽です。次回はクリップボードではなくファイルを経由してエクセルとやりとりしてみましょう。
◆今回のプログラムリスト
'
' "マイクロソフトエクセルからクリップボード経由でデータを受け取る"
'
' "定数を定義"
_spaceCode = &H20: ' "空白のアスキーコード"
' "グローバル変数を定義"
scrapOffset& = 0: ' "データオフセット"
retFlag% = _false: ' "データエンドフラグ"
END GLOBALS
' "クリップボードからシリアルにセルデータを読み込む"
LOCAL FN getExcelText!
sa& = 0
myHandle& = FN NEWHANDLE(0): '"ハンドルのみを確保する"
textLen& = FN GETSCRAP(myHandle&,_"TEXT",sa&): ' "クリップボードのデータを求める"
LONG IF textLen& <= scrapOffset&
retFlag% = _false: ' "クリップボードのデータサイズがオフセット以下ならデータ終了"
XELSE
err% = FN HLOCK(myHandle&): ' "ハンドルをロックする"
c = 999: ' "ダミーの値"
A$ = "": ' "空文字にしておく"
WHILE c > _spaceCode: ' "空白やタブ、改行コード以外だったら文字を連結"
c = PEEK([ myHandle& ] + scrapOffset&): ' "1バイト読み出す"
A$ = A$ + CHR$(c): ' "文字として変換し連結する"
INC(scrapOffset&): ' "オフセットアドレスを加算する"
WEND
err% = FN HUNLOCK(myHandle&): ' "ハンドルロックを解除する"
retFlag% = _true: ' "無事にデータを取得できたのでTRUEを返す"
END IF
err% = FN DISPOSHANDLE(myHandle&): ' "ハンドルを破棄する"
END FN = VAL(A$): ' "文字列を変換し数値として返す"
scrapOffset& = 0: ' "オフセットを0に初期化する"
retFlag% = _true: ' "フラグはTRUEにしておく"
WHILE retFlag% = _true: ' "フラグがTRUEの間繰り返す"
v! = FN getExcelText!: ' "戻り値がデータの値"
LONG IF retFlag% = _true
PRINT v!: ' "retFlag%がTRUEの時は正しくデータを取得した"
END IF
WEND