レポート画面を実装する
レポート画面は、p2でサンプルデータ取得に使ったOrderDetailReportを修正して作ります。
レポート定義ファイルをJSONとして保存する
作成したレポートは、アプリケーションからJSON形式のデータとして部品に渡します。そこで、レポート定義をJSONファイルとして保存しておきましょう。デザイナーで、ファイルメニュー > 名前をつけて保存を選択し、ファイル名を「Invoice.rdlx-json」として保存します。保存後、ファイルの拡張子をjsonに変更します(OutSystemsのResourcesに登録するときに許可された拡張子でないとアクセスできないため)。
レポート定義ファイル配置
Service StudioでOrderManagementモジュールを開き、保存しておいたInvoice.jsonをResourcesにImportします。
レポート定義とデータを取得するData Actionを用意
用意しておいたBlockには、以下2つのInput Parameterが必要です。
- レポート定義のJSON (Text型)
- データ(JSON)のList(Text List型)
そこで、画面にData Actionを作成し、この2つの値を返すことにします。名前はGetJsonにしました。
レポート定義のJSON取得部分
GetJSON Data Actionの中身を作っていきます。Resourcesに登録したInvoice.jsonのContentプロパティでファイルのバイナリを取り出しますが、欲しいのはJSON文字列なのでBinaryDataにあるBinaryDataToTextでText型に変換します。
BinaryDataはOutSystems公式から提供されている部品で、文字通り、Binary Data型を操作する機能を提供するものです。参照を追加するには、ショートカットキー「Ctrl+Q」か画面上部の電源プラグのアイコンをクリックして「Manage Dependencies」ダイアログを使います。参照手順は次のスクリーンショットをご覧ください。
追加が終わったら、画面左のToolboxからServer Actionのアイコンをドラッグ&ドロップでFlowに追加し、Actionプロパティで今参照したBinaryDataToTextを指定してください。指定するプロパティは次のスクリーンショットを参照します。
データ(JSON)のList取得部分
上の行が見出しデータ、下の行が一覧データの取得に対応しています。どちらも以下の流れです。
- Aggregateでデータを取得、
- JSON SerializeでAggregate結果のListをJSONに変換
- ListAppendでData ActionのOutput ParameterにSerializeしたJSONを追加
画面にBlockを配置
ActiveReportsJS_PatモジュールのActiveReportsJS_Viewer Blockへの参照を追加しておきます。追加手順はBinaryDataToText Actionのときと同じです。参照を追加すると、以下のようにツリービューにどのモジュールから参照したかがわかるように表示されます。ここに表示されたActiveReportsJS_Viewer Blockを画面にドラッグ&ドロップして配置してください。
追加したら、Blockを画面に配置し、Input Parameterには、Data Actionで取得した値(Output Parameter)を設定します。
このBlockはIf Widgetで囲んでおきます。IfのConditionはData Actionの取得終了を表す「GetJSON.IsDataFetched」です。
Data Actionの取得が終わる前にBlockのロード処理が進んでしまうと、画面から渡すレポート定義が空文字列の状態でビューワーを表示しようとして、エラーになってしまいます。
CSPの設定
ActiveReportsJSでは、帳票生成をバックグラウンドで行うためにWeb Workerを使用しています。そのため、以下の設定が必要になることがあります。
ActiveReportsJSのビューワーを表示する際に、「Refused to create a worker from 'blob'」「Failed to construct 'workder': Access to the script at 'blob'」のようなJavaScriptのエラーが出ることが有りました。これはCSP(Content Security Policy) の設定によるエラーなので、LifeTimeで、特定のディレクティブを許可する必要があります。
ActiveReportsJSはWeb Workerを動的に生成されたスクリプトからロードするので、worker-src
ディレクティブにblob:
スキームを含める必要があります。
LifeTimeを開き、Environments > More Security Settingsとリンクをクリックします。
画面を一番下までスクロールします。
Other-Directivesに「worker-src blob:;」を追加して「Save」ボタンをクリックします。OutSystemsのOrderManagementモジュールをPublishしなおすと動作するようになりました。
OutSystemsのCSP設定では、worker-srcディレクティブに対する専用の設定場所がなく(上位に当たるchild-srcの設定はある)、任意のディレクティブを設定できるOther-Directoriesを使っています。上記の設定の代わりに、child-srcディレクティブに「blob:」を追加してもうまくいきます。
動作確認
ここまでの作業が終わったら、Publishして動作を確認します。OrderDetail画面上で、「Report」ボタンをクリックして、OrderDetailReport画面を開いてみて下さい。以下のようにレポートが埋め込まれた状態で表示されたら、完成です。
PDFへのエクスポート
PDFへのエクスポート機能そのものは、特に設定しなくても使えますが、日本語フォントを使うには準備が必要です。
フォントファイルを準備
以下のgithubレポジトリにあるフォントを例に手順を説明します。
ActiveReportsJS-Invoice-IPA-Sampleのレポジトリからfontsフォルダをダウンロードして下さい。Personal Environmentでもテストできるように、フォントファイルをモジュールのResourcesフォルダへ登録する手順で説明します。
ダウンロードしたフォルダにある、ipag.ttfをActiveReportsJS_PatモジュールのResourcesにインポートして下さい。URLでアクセスできるように、Deploy Actionを「Deploy to Target Directory」に設定します。
レポート定義へのフォント適用
レポート定義内の項目を、用意したファイル内のフォントを利用するように設定します。デザイナーはデフォルトでは用意したフォントファイルを選択できません。
以下のドキュメントに従って、設定ファイルを修正していきましょう。
Windowsの場合は、「C:\Users\\<ユーザ名>\AppData\Roaming\ActiveReportsJS Designer\fontsConfig.json」を開き、"descriptors"配列の最後に以下のように追記して下さい (追加したのは最後のIPAゴシック項目。配列なので、前の項目末尾に「,」を加えるのを忘れずに。また、<OutSystemsのドメイン名>の部分は実際のドメイン名で置き換えて下さい)。
(前略) { "name": "游ゴシック", "locals": [ "游ゴシック", "Yu Gothic" ] }, { "name": "IPAゴシック", "source": "https://<OutSystemsのドメイン名>/ActiveReportsJS_Pat/ipag.ttf" } ] }
設定ができたら、レポート定義ファイル(invoice.rdlx-json)をデザイナーで開き、各項目のフォント名の値をIPAゴシックに変更します。変更が終わったら、レポート定義ファイル保存後、invoice.jsonに名前を変え、OrderManagementモジュールのResourcesへインポートし直して下さい。
実行時にライブラリへフォントを適用
使いたいフォントが標準のものではない場合、以下のドキュメントの手順で、実行時にライブラリに登録する必要があります。
p2で作成した、ActiveReportsJS_Patモジュール > ActiveReportsJS_Viewer Block > DataActionGetLicenseKeyOnAfterFetch Actionに配置したJavaScriptのコードを修正します。
ライセンスキー登録とビューワー初期化の間にフォント登録処理を追加しました。
// ライセンスキー MESCIUS.ActiveReportsJS.Core.setLicenseKey($parameters.LicenseKey); // IPAゴシックフォント登録(PDFエクスポートに使うフォント) const font = { name: "IPAゴシック", source: $parameters.FontURL }; MESCIUS.ActiveReportsJS.Core.FontStore.registerFonts(font); // ビューワー初期化 const viewer = new MESCIUS.ActiveReportsJS.ReportViewer.Viewer("#" + $parameters.ViewerHostId, { language: "ja" }); (後略)
JavaScriptのInput ParameterとしてFontURLを追加しています(この値はfontオブジェクトのsourceプロパティへの設定に使用)。
このパラメータには、以下の通り、Resourcesに登録したttfファイルのURLを渡します。
動作確認
Publishしたら動作確認してみましょう。ビューワーを開いたら、左側のサイドバーの上から3番目にあるエクスポートのアイコンをクリックし、ファイル形式でPDFファイル(PDF)を選択します。
最下部にある「エクスポート」ボタンをクリックすると、PDFファイルを出力できます。
今後の展開
Blockはこのままの状態でも十分に使えると思いますが、業務アプリケーションで使う帳票にはさまざまな要件があります。その要件を収集し、共通部品として機能を拡張していくともっといいでしょう。
以下にいくつかの修正例を示します。
必要な帳票の要件を整理し、Blockに不足する機能を追加する
現在は、ビューワーをデフォルト設定で表示していますが、不要な機能を隠したり、Blockのパラメータで表示する機能を制御したりする要望が出てくるかもしれません。Structureで設定値を受け取るInput Parameterを追加し、その値に応じてビューワーをカスタマイズするといいでしょう。
レポート定義を管理する機能を共通部品に持つ
この記事では、レポート定義をResourcesに登録していましたが、この方法では、レポート定義の追加・変更に常にプログラムのリリースを伴ってしまいます。レポート定義格納用のEntityを共通部品に保持し、開発者はそのIdを指定することで出力するという変更が考えられます。こうすることで、Publishせずに運用中にレポート定義を追加したり変更したりできるようになります。
APIをラップするAction
APIを使ってレポートを出力するオプションもあるようです。場合によっては、そのAPIをラップしたClient Actionの部品を用意することも考えられます。