はじめに
本連載では、Curl Apps Galleryで公開されている見積デモの主な機能について詳しく解説していきたいと思います。Curl Apps GalleryとはCurlのサンプルアプリケーションが公開されているサイトで、Curlの技術者がアプリケーションを自由に閲覧、投稿できます。
現在、Apps Galleryには100を超えるサンプルが公開されていますが、その中でも頻繁にダウンロードされているのが「見積デモ」です。このサンプルは業務アプリケーションに特化したCurlの特徴をよく捉えており、Curlのアプリケーションの基本的な動作を理解するには最適なものとなっています。
今回は、この見積デモについて説明を行います。しかし、このサンプルは古いCurlのバージョンで作成されており、またソースコードが冗長になっている部分があります。本説明では現行のバージョン(6.0)に基づき、機能に応じてソースコードを最適化しながら解説していきます。そのためダウンロード可能なソースと内容が異なる部分がありますのでご注意ください。
見積デモの基本的な機能について
具体的な説明に入る前に、まず見積デモの機能的な特徴から見ていきましょう。見積デモは上下2つの画面から構成されています。
画面の上部には見積書の基本情報を入力する欄があり、これらの入力欄はフォーカスの移動と共にIMEの設定が切り替わるようになっています。例えば、「見積書カナ」の欄にフォーカスが入るとIMEは自動的に全角カタカナに変更されます。また、入力補助の機能も提供されており、日付を入力する際には横のメモ帳アイコンをクリックするとカレンダーが表示されます。
画面の下部はタブによって切り替えられるようになっています。最初に表示されるのは見積入力画面です。見積入力画面では商品を選択入力でき、商品の一覧は、左上のプルダウンからカテゴリを選択することで表示されます。
ユーザーは表示された商品をダブルクリックしたり、ドラッグ&ドロップで右の表にコピーしたりすることで商品の入力が行えるようになります。この商品のカテゴリや金額の情報はXMLで管理されており、XMLファイルを読み込むことによって商品の一覧を表示しています。
入力が完了したあと、見積書タブを表示すると見積書のプレビューを表示できます。
見積書のプレビューには先程の見積入力画面や基本情報の欄で入力された情報が表示されています。プレビューの情報は、見積入力画面や上部の基本情報を更新されるたびに自動で更新されます。見積書の内容を確認して『見積書発行』ボタンを押すと、見積書が印刷されます。
見積デモの主な機能は以上です。今回は見積入力の際に使用するRecordGridという部品について詳しく見ていきたいと思います。
Excelのようなデータの表現と操作性を持つRecordGrid
RecordGridはCurlのGUIの1つで、その操作性の高さから多くのアプリケーションで利用されています。また、プロパティを変更することでRecordGridの操作性や概観を変えられるため、機能を変更するのも比較的容易です。
RecordGridを使用するときには、RecordSetというデータクラスを使用します。RecordSetとはデータを行・列の形式で2次元に管理し、操作するためのAPIで、コンピュータのメモリにもよりますが何十万というレコードを格納することも可能です。
RecordSetを作成するときは、RecordFieldを用いてデータの列名を定義します。以下は、RecordGridとRecordSetを用いた簡単なサンプルの例です。このソースコードを実行すると、上図のようなグリッドが表示されます。
{curl 6.0 applet} {curl-file-attributes character-encoding = "shift-jis"} ||データを管理するRecordSetを定義します。 {let people:RecordSet = {RecordSet {RecordFields {RecordField "Delete", domain = bool,caption = "削除"}, {RecordField "Code", domain = String,caption = "品名コード"}, {RecordField "Name", domain = String,caption = "品名"}, {RecordField "Count", domain = int,caption = "数量"}, {RecordField "Price", domain = int,caption = "売上単価"}, {RecordField "Subtotal", domain = int,caption = "売上合計"} }, {RecordData Code = "A01", Name = "Windowsデスクトップ", Count = 1, Price = 76000, Subtotal = 76000}, {RecordData Code = "A02", Name = "Windowsノート", Count = 7, Price = 155000, Subtotal = 1085000}, {RecordData Code = "A03", Name = "Macデスクトップ", Count = 1, Price = 83000, Subtotal = 83000} } } ||データを表示するRecordGridを定義します。 {let rg:RecordGrid = {RecordGrid height = 3cm, width = 10cm, record-source = people } } {value rg}
RecordGridのカスタマイズ
さて、このさまざまな機能を持っているRecordGridですが、プロパティの変更や部品のカスタマイズを行うことでさらに機能を拡張できます。1つの例として、下図の売上単価や売上合計のように、数値の表示を変更する方法について見ていきましょう。
データの表示形式を変更するにはformat-specを利用します。format-specプロパティはRecordGrid、RecordGridColumn、RecordGridCellそれぞれに存在しています。そのため、データの表示形式の範囲をグリッド全体、列単位、セル単位という形で設定することが可能です。format-specを指定するときには、データの変更するロジックをプロパティで指定します。
下記のサンプルでは、format-specにてデータを円表記に変換する処理を指定しています。
{import * from CURL.LANGUAGE.FORMAT} {let formatter:NumberFormatter = {NumberFormatter.create-currency-formatter locale = {Locale "ja"} } } {do set formatter.grouping-size = 3 } {let rg:RecordGrid = {RecordGrid record-source = people, height = 3cm, {RecordGridColumn "Delete"}, {RecordGridColumn "Code" }, {RecordGridColumn "Name" }, {RecordGridColumn "Count" ,halign = "right"}, {RecordGridColumn "Price" , halign = "right" }, {RecordGridColumn "Subtotal", halign = "right", format-spec = {proc {value:any}:String {return {formatter.format value} } } } } } {value rg}
データの集計
また、RecordSetを利用することでデータの集計を容易に行えます。RecordSetはデータを管理するためのクラスですが、このクラスを使用する大きな利点として「配列のようなイテレーションが可能」「データの変更をイベントで通知できる」という特徴が挙げられます。
これらの特徴を利用することによって、「RecordGridでデータが操作されたときに自動で合計金額を更新する」といった機能が実装できるようになります。下記のサンプルコードは、RecordSetにイベントを組み込むことで、売上合計(Subtotal)の合計値を自動で更新する処理を組み込んでいます。サンプルコードのコメントを記述している箇所がそれに該当します。
{let summary:int = 0} {let people:RecordSet = {RecordSet (省略), ||RecordsChangedでレコード更新のイベントを捕捉します。 {on RecordsChanged do set summary = 0 ||for文でRecordSetの内容を参照します。 {for record:Record in people do {if record.state != RecordState.deleted then set summary = summary + (record["Subtotal"] asa int) } } {popup-message summary} } } } ||データを表示するRecordGridを定義します。 {let rg:RecordGrid = {RecordGrid height = 3cm, width = 10cm, record-source = people } } {value rg}
このサンプルを実行してデータを更新すると、次のように合計額がポップアップ表示されます。
まとめ
見積デモはこのようなRecordGridとRecordSetの機能を利用してGUIの実装が行われています。
次回は見積デモのドラッグ&ドロップの機能について見ていきたいと思います。