著作一覧 |
自分のふりかえりは上に書いたので、他の発表者のセッションで印象的だったのはというと、桑田さんのマクロならクォート一発な処理をDSLとして……というやつなのだが、聞いているときはおもしろかったが、考えてみるとちょっと違うのではないだろうか。
マクロのエラーは(多くの場合)単なる文法エラーだが、DSLのエラーはアプリケーションエラーにできるからだ。
ということはどういうことか。
まず、SQLは別に文字列で書けば良いというのがある。埋め込みパラメータがあるかどうかにかかわらず。効率も良いし、それがネイティブインターフェイスだ。
わざわざそれを元の言語に組み込もうというからには、そこに何かのメリットがなければしょうがない。
そのメリットが何かといえば、書き間違いに対する手厚いケアではないかと思う。他に何かあるか? (ソースの見てくれというのはある)
としたら、ここに書き間違いがあるということが、一発でわかるような仕組みが良い。
それがマクロで可能なのか、というあたり。
aikeさんのexelsv.htaを見ていて、ちょっと気になったのでいじってみた。というか、さっそくこういうのを作れるってのはすごいなぁ。かくありたいね。
気になったのは、「ブラウザに制御が戻らないや」のところ。いや、確かに戻らないし、逆に戻すとrubyを離れるのでdRubyが今度は動けない。だから正しいのだけど、HTMLのレンダラで、しかもScriptHostだということは、Windowsオブジェクトを持つということで、つまりはsetIntervalとsetTimerが利用できる。
というわけで、あまりかっこは良くないのだけど、次のように、シャットダウンボタンをつけることも可能。ついでに統計情報をちょっと取ってみるようにしてみたり。
<html> <head><title>Excel Server</title> <script language="RubyScript"> # ver 0.2 (correct ex order of counts, see #c01) require 'drb/drb' class ExcelServer def initialize @excel = WIN32OLE.new("Excel.Application") @excel.Visible = true @excel.SheetsInNewWorkbook = 1 @book = @excel.WorkBooks.Add() @book.Application.DisplayAlerts = nil @sheet = @excel.Worksheets(1) @@singleton = self end def put(cell, str) count('put') @sheet.Range(cell).Value = str end def get(cell) count('get') @sheet.Range(cell).Value end def count(m) e = Window.document.getElementById("#{m}call") e.innerHTML = (e.innerHTML.to_i + 1).to_s end def shutdown Window.clearInterval($timer) Thread.new do close end.join Window.setTimeout(Proc.new{Window.close}, 1000, 'RubyScript') end def close @book.Close() @excel.Quit() end def self.instance @@singleton end end def server_start() Window.resizeTo 400, 300 uri = "druby://localhost:12345" DRb.start_service(uri, ExcelServer.new) $timer = setInterval(Proc.new{sleep(0.2)}, 200, 'RubyScript') end </script> </head> <body onload="server_start" language="RubyScript"> <h1> <center> <input type="button" onclick="ExcelServer.instance.close;Window.close" value="shutdown" language="RubyScript"/> </center> </h1> statistics <table> <tr><th>method</th><th>call</th></tr> <tr><td>put</td><td id="putcall">0</td></tr> <tr><td>get</td><td id="getcall">0</td></tr> </table> </body> </html>
setIntervalを使う場合は、最初はインターバルをうんと長め(5秒とか10秒とか)にしておいて、デバッグが終わってから本来の長さにすると良いです。というのは、タイプミスなどがあると、あっというまにブラウザクラッシャー状態になってしまうからです。
#途中でcloseメソッドを共通化したくてシングルトンに無理やりしたのでおかしいけど気にしないように。いくらでもnewできるし。
#追記:aikeさんの指摘箇所を修正
#追記2:@timerってどう考えてもバグ。あとで修正予定。→直した。グローバル変数を使う
ジェズイットを見習え |
さすが!そうそう、こういうことがやりたかったのです。<br>当日実演されたsamples\hta\evlog.htaもソースを読むと<br>setTimeoutを上手いこと使ってますね。<br><br>ところでgetメソッドの<br> @sheet.Range(cell).Value<br> count('get')<br>は上下入れ替えないとセルの値ではなく<br>カウンタ値が返っちゃう気がします。<br><br>また機会がありましたら札幌にいらしてください。
これ、いいですね。dRubyで遊ぶときって、コンソール×2で切り替えてやっていたのですが、サーバーをHTAにすると最初にサーバーを実行しておいて、あとからクライアントを実行するというのが1つのコンソールでできるので、目からうろこでした。<br>>カウンタ値が返っちゃう気がします。<br>ありがとうございます。文句なしのバグです。修正しました。