はじめに
OutSystems自体には帳票出力の機能が備わっていません。OSSレポジトリであるForgeにはUltimate PDFを初め、いくつかコンポーネントもありますが、大量の帳票を作成したり、細かい要件がある場合は不足を感じたりすることも多いでしょう。そのため、多くのOutSystems導入企業は何らかの帳票ソフトウェアまたはサービスを導入し、連携させて使うことになります。
本記事では、JavaScript帳票開発ライブラリのActiveReportsJSをOutSystemsと連携させる方法を紹介します。
対象読者
- OutSystemsに帳票ソリューションを導入することを検討している方
- OutSystemsにActiveReportsJSを組み込む方法を知りたい方
- OutSystemsの開発知識を取得したい方
必要な環境
本記事のサンプルプログラムを試すためには、以下が必要です。
- OutSystems 11の環境(動作検証はPersonal EnvironmentのVersion 11.27.0(Build 42818)を使用しました)
- Service Studio 11(IDE)(動作検証はVersion 11.54.66 / Build 63364を使用しました)
- OutSystemsがサポートするブラウザ (OutSystems system requirements > End user requirements > Reactive Web apps- OutSystems 11 Documentation)
- ActiveReportsJS V5J
OutSystems 11の環境は、無償のPersonal Environmentで問題有りません。環境を持っていない方は、アカウントをサインアップすると作ることができます。
ActiveReportsJSは、専用のツールでデザインしたレポートを、WebブラウザのJavaScriptのみで出力できるライブラリです。以降、ActiveReportsJSで作る帳票のことを、ActiveReportsJSにあわせてレポートと呼びます。
サンプルアプリケーションのセットアップ
Service Studio上で、「New Application」をクリックしてアプリケーション作成を開始します。
用意されているテンプレートを基にアプリケーション作成を始める「From an app」を選択してアプリケーションを作ります。
Order Managementのテンプレートを選択し、「Install」ボタンをクリックします。
インストールが終わったら「Customize app」ボタンをクリックして、アプリケーションを開いてください。
アプリケーションに属するモジュール一覧が表示されます。
Order Managementモジュールに参照整合性の問題が発生しているので修正します。OrderManagementモジュールを開いてください。
参照整合性の問題があるので、Manage Dependenciesダイアログを開きます。ダイアログ右下の「Refresh all」ボタンをクリックし、続いて「Apply」ボタンをクリック。これで今開いているモジュールの参照は更新されました。
ダイアログが閉じたら、忘れずにPublishもしておきましょう。
実装シナリオ
サンプルアプリケーションで管理されている注文データを使い、請求書レポートを作成していきます。
シナリオ実装後の操作の流れ
この記事で紹介する手順を行った後のアプリケーションでの、レポート表示までの操作手順を確認しておきましょう。
OrderManagementモジュールをブラウザで開きます。
トップメニューから「Orders」をクリックしてOrderManagement画面を、続いて一覧上の適当な行のNumber列に表示されるリンクを開きます。
1件の注文の詳細を示すOrderDetail画面が開きます。この画面右上、「Delete Order」ボタンの隣に、「Report」ボタンを追加します(※)。
※詳しくは解説しませんが、ボタンを追加し、画面を開く処理を実装します。ボタン動作の実装に関する内容はリファレンスを参照の上、実装してください。
クリックしたらActiveReportsJSのビューワーを配置したOrderDetailReport画面が開きます。
作成するもの
上記のシナリオを実装するために、以下の要素を作成します。
- p2で作成:ActiveReportsJSをOutSystemsアプリケーションから利用するためのUI部品(ActiveReportsJS_Patモジュール)
- p3で作成:ActiveReportsJSのレポート定義
- p4で作成:OrderDetailReport画面(OrderManagementモジュール)
OutSystemsのアーキテクチャ設計図であるArchitecture Canvasを使って表すと以下のようになります。
ActiveReportsJS部品(Block)を用意
アプリケーションとモジュールを作成する
OutSystemsにおいて、モジュールがWebやMobileの一塊のソフトウェア、あるいはそれらから参照するライブラリを表します。アプリケーションは、複数のモジュールをまとめて管理するフォルダ的な位置づけです。リリース単位でもあります。
部品は、すでに作成したサンプルアプリケーションとは別に作ります。帳票出力部品は通常複数のアプリケーションから利用されるため、利用側のサンプルアプリケーションと独立させ、独自のライフサイクルで開発・保守を行いたいからです。
Service Studioで、サンプルアプリケーションのときと同じく「New Application」をクリックしてダイアログを表示します。今度はテンプレートが無いので、「From scratch」のオプションを選択します。次に、Reactive Web Appを選択してください。SPAのWebアプリケーションを作成するオプションです。
Name=ActiveReportsJSとしました。
続いて、モジュールを作成します。
Name=ActiveReportsJS_Pat、module type=Blankを選択(Blankを選択するのは、UI部品用モジュールに不要な要素を含めないため)。
ライセンスを保持するSite Propertyを用意する
Site Propertyは、運用中に変更される可能性のある設定値を定義する方法です。LicenseKeyという名前でSite Propertyを作成します。Data TypeはText、Is secretはYesにします(ライセンスキーは一般にセキュアに保つべき情報であるため。ActiveReportsJSはクライアント側で動作するため、実行時には知識のあるユーザーには見えてしまいますが)。
いったん、Publishします。管理コンソールのService CenterでActiveReportsJS_Patのページを開いてください。Site Propertiesタブ > LicenseKeyリンクの順にクリック。
ActiveReportsJSのライセンスキーをEffective Valueに設定し、「Apply」ボタンをクリックしてください。これで部品にライセンスキーの設定ができました。
ライブラリのCSSを読み込むためのBlock
ActiveReportsJSのビューワーを表示するには、2つの.cssファイルを読み込む必要があります(ダウンロードしたライブラリ内の、activereportsjs-5\dist\css)。
- ar-js-ui.css
- ar-js-viewer.css
以下、ar-js-ui.cssを例に作成手順を説明します。ar-js-viewer.cssにも同じ手順を行ってください。
UI FlowをStylesという名前で追加します。作成したStylesに、CSSを配置するBlockを作成し、NameはArJsUiCssとしました。Descriptionは保守のために設定しておきましょう。
Block内に以下のように配置します。
Condition=FalseのIfはBlockを部品提供するときによく使う方法です。True Branchに、他のBlockやScreenに配置したときに見せたい要素、False Branchに実際に使う要素を配置します(このBlockの場合は空なので何も表示されません)。
画面上部のCSSアイコンをクリックして開いたダイアログに、ar-js-ui.cssの中身を貼り付けて完成。
ライブラリのJavaScriptを登録
以下のライブラリをactivereportsjs-5\dist\scriptsフォルダからScriptsフォルダにImportしてください。
-
必須のスクリプト
- ar-js-core.js
- ar-js-viewer.js
-
任意のスクリプト(エクスポート機能で使用)
- ar-js-pdf.js
- ar-js-xlsx.js
- ar-js-html.js
- ar-js-tabular-data.js
-
UIの日本語化用スクリプト
- locales\ar-js-locales.js
上記のファイルをすべて登録すると、以下のようになります(見やすいようにフォルダ分けしています)。
ActiveReportsJSビューワーBlock
イメージ画像
他のアプリケーションに配置した際に、どういった機能がそこに置かれているかを示す画像が表示されるとわかりやすいです。後で使うので、ビューワーのイメージ画像をImagesにImportしておきましょう。
Block定義
CSSの場合と同じように、UI FlowとBlockを用意します。
①Blockのプロパティ
Name=ActiveReportsJS_Viewerとしました。他のモジュールから参照されるときは、この名前で見えます。他のモジュールから参照できるように、Public=Yesに。
②スクリプトを参照
登録しておいたJavaScriptファイルを参照します。ここで指定したJavaScriptファイルは、Blockを実行するときに自動で読み込まれます。
③Input Parameter
以下2つのInput Parameterを追加します。Input Parameterを追加するには、③の位置でActiveReportsJS_Viewer Blockを右クリックし、「Add Input Parameter」を選択します。
-
ReportDefinitionJSON
- Name: ReportDefinitionJSON
- Description: ActiveReportsJSのレポート定義ファイルに含まれるJSON
- Data Type: Text
- Is Mandatory=Yes
-
DataSourceJSONs
- Name: DataSourceJSONs
- Description: 実行時に埋め込み形式のデータソースに連結したいJSONのリスト
- Data Type: Text List
- Is Mandatory=No
前者にActiveReportsJSのレポート定義ファイルのJSON形式、後者にはレポートに渡すデータをJSON化したものをListで渡します(レポート定義によって必要なデータソースの数は可変であるためListにしています)。
Block内部には以下のようにWidgetを配置します。CSSのBlockと同じ理由でIfを使っています。True BranchにおいたImageにはImagesにImportしておいた画像を指定。False Branchには、CSSを読み込むBlockを2つ、ビューワーを表示するためのContainerを配置します。
Style設定
ar-js-ui.css を読み込むBlockを作ったときと同じく、Service Studio上部のcssボタンをクリックし、外観定義用classを作成します。このcssボタンはBlockのUI編集中でないと表示されないため、もし表示されていなかったら、Block名(ActiveReportsJS_Viewer)をダブルクリックしてUI編集状態にしてみてください。
.activereports-viewer-host { margin: 0 auto; width: 100%; height: 100vh; }
ContainerのStyle Classesプロパティに設定します。Containerに対応するHTMLタグにこのclass名がつくようになります。
ライセンスキー取得
ActiveReportsJSは実行時にライセンスキーを必要とします。そこで、Data ActionでSite Propertyから設定値を取得していきましょう。Data Actionは画面専用のサーバーサイド処理で、サーバー側からデータを取得してくるのに使います。
ActiveReportsJS_Viewer Blockを右クリックし、Fetch Data from Other Sourcesを選択して作成します。
FetchプロパティはAt startのままにします(画面を開くと自動でデータ取得を開始する)。
Output Parameter LicenseKeyには、Site PropertyのLicenseKeyの値をそのまま編集してください。Output Parameterは、作成したData Action(上の例ではDataActionGetLicenseKey)を右クリックし、Add Output Parameterを選択すると作れます。
ビューワーのロード
LicenseKeyの取得を待ちたいのでData ActionのOn After Fetch(Data Action取得終了時に発生するイベント)イベントハンドラーを作成します。
On After Fetchイベントに対するハンドラーを作成するには、Data Actionを選択するとService Studio右下に表示されるプロパティから、Events > On After Fetchのドロップダウンリストを展開し、New Client Actionを選択します。
- Service Studio左側にあるツールボックスから、JSON SerializeとJavaScriptをドラッグ&ドロップで、作成されたイベントハンドラーのフローに配置します。
- JSON SerializeでInput ParameterのList DataSourceJSONsをJSON形式の文字列に変換します(ListのままではJavaScriptに渡せないため)。
-
JavaScript要素には、図のようにJavaScriptのInput Parameterを設定します。
- LicenseKey: Data Actionから取得したActiveReportsJSのライセンスキー
- ViewerHostId: ビューワーを表示するHTMLタグのId。ContainerのIdは<ContainerのName>.Idで取得できます(このためにNameプロパティは設定必須)
- ReportDefinitionJSON: Blockの同名のInput Parameter (レポート定義)をそのまま渡す
- DataJSON: JSON Serializeの結果
JavaScript要素内の設定は以下の通り。Input Parameterは全て、Data Type=Textです。
// ライセンスキー MESCIUS.ActiveReportsJS.Core.setLicenseKey($parameters.LicenseKey); // ビューワー初期化 const viewer = new MESCIUS.ActiveReportsJS.ReportViewer.Viewer("#" + $parameters.ViewerHostId, { language: "ja" }); // レポート定義をJSONからオブジェクトに変換 const report = JSON.parse($parameters.ReportDefinitionJSON); // レポートオブジェクトに、データソースを読み込む const dataArray = JSON.parse($parameters.DataJSON); for (let i = 0; i < dataArray.length; i++) { report.DataSources[i].ConnectionProperties.ConnectString = "jsondata=" + dataArray[i]; } // ビューワーを開く viewer.open(report);
開発が終了したら、Publishしておきましょう。
ActiveReportsJSのレポート定義
ActiveReportsJSが提供するデザイナーアプリケーションを使ってレポート定義を作っていきます。
作成するレポート
個別の注文情報に対する請求書を、以下のようなレポートとして作成します。
サンプルアプリケーションのOrderDetail画面で持っている以下のAggregateがデータソースとして使えます。
- GetOrder: 見出し部分のデータソースとして
- GetOrderItemsByOrderId: 一覧部分のデータソースとして
サンプルデータを準備する
ActiveReportsJSのレポートへのデータソース設定には、以下の方法があります。
- 外部URLから取得する
- レポート自体に埋め込む
OutSystemsは簡単にREST APIを作成できますが、REST APIとWebアプリケーションは、ユーザーの認証を共有しないので、レポート自体に埋め込む方法を取ります。このとき、レポートにデータ構造を知らせるため、サンプルデータが必要になります。
OrderDetailのAggregateをレポート用画面に一時的にコピーし、結果をJSON Serializeすることでサンプルデータを取得しましょう。OrderManagementモジュールを開き、Order UI Flowに新しい画面を作り、名前はOrderDetailReportに変更。続いて、OrderDetail画面から、Input ParameterのOrderId、AggregateのGetOrder(見出しデータ)とGetOrderItemsByOrderId(一覧データ)をコピーして下さい。
ここまでで、作成したOrderDetailReport画面を開く際に、必要なデータが取得されるようになっています。続いて、このデータをJSONに変換したうえで画面に表示しましょう。
以下の手順は見出しデータ(GetOrder)、一覧データ(GetOrderItemsByOrderId)それぞれに対して行います。ここでは一覧データを例に説明します。
GetOrderItemsByOrderId AggregateにOn After Fetchイベントハンドラーを作成(GetOrderItemsByOrderIdを選択し、画面右下のプロパティから、Events > On After Fetchのドロップダウンリストを展開、New Client Actionを選択)。
On After Fetchでは、JSONSerializeによって、GetOrder Aggregateの結果をJSON文字列に変換し、画面表示用のLocal VariableにAssignします(JSONSerializeとAssignはService Studio左側のToolboxからドラッグ&ドロップでFlowに配置)。
JSONSerializeでは、Aggregateの結果(Aggregate名.Listで、DBから出力したレコードのリストを表す)を指定します。
JSON Serializeした結果を後続のAssignで画面のLocal Variableに保存します(Local Variableは、画面を選択して右クリックし、Add Local Variableを選択。Data TypeはText)。
Local Variableを画面上にドラッグ&ドロップすると、値を表示するExpressionが配置されます。ここまで実装したらPublishし、ブラウザで画面を表示します(※)。画面に表示されたJSON文字列をテキストエディタなどに一時保存しておいて下さい。
(※)Service Studio上で画面を選択して右クリック、Open in Browserでその画面がブラウザで開きます。Input Parameter OrderIdが必要なので、ブラウザが開いたら、URLの末尾に「&OrderId=1」を追加してください。1は実在するOrderレコードのIdにする必要があるので、もしIdがお使いの環境でずれて発番されているようなら合わせてください。
レポート定義ファイルを作成
ActiveReportsJS Designerアプリケーションを起動します。画面上部のファイルメニューをクリックし、新規作成 > 新規レポートの作成からページレポートを選択します。
データを連結
コピーしておいたサンプルデータのJSONをレポートに埋め込みます。見出しデータで説明しますが、一覧データでも同じ手順を行って下さい。どこからデータを取得するかを定義するデータソースを作成します。画面右上のデータタブを開き、データソース右側の「+ 追加」をクリック。
表示されたダイアログで、以下を入力し、「変更を保存」ボタンをクリック。
- 名前:DataSource見出し
- 形式:埋め込みを選択(ダイアログの下半分がJSONデータ入力用に変わる)
- JSONデータ:用意しておいた見出しデータのサンプルを貼り付ける
次に、データソースからデータセットを作成します。作成したデータソース右側の「+」アイコンをクリック。
- 名前:DataSource見出し
- JSONパス:全てのデータを指す「$.*」
と入力し、「検証」ボタンをクリック。データソースに含まれるフィールドの数が、データベースフィールド項目に反映されます。「変更を保存」ボタンをクリックして入力を保存。
一覧データでも同じことをすると、以下のようになります。
レポートデザイン
ActiveReportsJSのレポートデザインは、OutSystemsで画面をデザインする操作と似ています。画面左側のメニューからレポートコントロールをUI上にドラッグ&ドロップで配置し、画面右側でプロパティを設定します。
固定の文字列にはTextBoxコントロール
画面左側からTextBoxコントロール(コントロール名はマウスオーバーすると表示される)をドラッグ&ドロップして、レポート内に配置します。
配置したコントロールを選択した状態で、画面上部のツールバーや右側のプロパティタブを使って表示内容を調整します。
「請求書」項目の場合の設定例。
画像はImageコントロールで
画像を配置したい場所にImageコントロールをドラッグ&ドロップ。
手元の画像をレポート内に埋め込みたいときは、外観 > 画像プロパティのリストを展開し、「埋め込み」を選択します。「+ 読み込む」から、使いたい画像ファイルを選択して下さい。
この記事のサンプルレポートでは以下の画像を使っています。
動的な文字列をTextBoxに表示する
以下の2か所を、見出しデータセットから動的に表示します。
①注文番号
見出しデータセットの、注文番号(Order.Code)を表示する設定を行います。TextBoxコントロールを選択し、プロパティの値項目右の「●」と式をクリックすると、式エディタが開きます。
式欄に出力したい文字列を設定しますが、波括弧({})で囲んだ部分(補間構文)は実行時に評価された結果で置き換えられます。また、ダイアログ左のツリーからデータセット > DataSet見出しと展開し、その下にあるOrder.Codeをダブルクリックすると、この項目を出力する補間構文を式のカーソル位置に挿入してくれます。
First関数呼び出しが挿入されますが、見出しデータには1件しかデータがないはずなので問題ないでしょう。実際の出力は「注文番号:ORD0001」のようになります。
②宛先
こちらは請求書送付先となる企業名(Account.Company)を出力します。式は「{First([Account.Company], "DataSet見出し")} 御中」、実行結果例は「Business fluence 御中」のようになります。
Tableへのバインディング
一覧データには、Tableコントロールを使います。他のコントロールと同じようにドラッグ&ドロップで配置します。
配置したTable上でクリックすると以下の状態になります。
列間にマウスオーバーし、現れた+のアイコンをクリックして5列に増やして下さい。次に行ヘッダの位置にあるヘッダ、詳細、フッタを表すアイコンの内、フッタを表すものを選択し、Deleteキーで削除します。このレポートでは一覧内に集計行を表示しないためです。
各セルにはTextBoxコントロールがあるため、値の設定を行います。ヘッダ行のセルには、固定の文字列を入力して下さい。詳細行には式を入力します。
- 商品名の詳細: {[Product.Name]}
- 単価の詳細: {[Product.Price]}
- 数量の詳細: {[OrderItem.Quantity]}
- 値引の詳細: {IIF([OrderItem.Discount] = 0, "", ToString([OrderItem.Discount]) + "%")}
- 小計の詳細: {PricePerRow}
「値引」項目は、IIF(条件式,条件がTrueのときの式, 条件がFalseのときの式)という関数を使っています。OutSystemsにもIfという同じ役割を果たすBuilt-in Functionがありますね。
「小計」項目は、計算フィールドという機能を使って、DataSetにあらかじめ計算式結果に対応する項目をPricePerRowという名前で用意しておき、その値を表示する指定です。
計算フィールドを追加するには、一覧データのDataSet右側の編集アイコン(ペンのアイコン)をクリックしてダイアログを表示し、計算フィールド右側の表示アイコン(ハンバーガーアイコン)をクリック。
フィールド名=PricePerRow、値={[OrderItem.Quantity] * [Product.Price] * ((100 - [OrderItem.Discount]) / 100)}と入力し、「変更を保存」ボタンをクリックして確定します。式の意味は、数量 × 単価 × (1-割引率)で割引適用後の小計を出しています。
集計項目
Table内で計算フィールドを作っておいたのはここで計算結果を流用するためです。「ご請求金額」の右隣のTextBoxコントロールの値に以下の式を入力して下さい。
{Sum(PricePerRow, "DataSet一覧")}
DataSet一覧というDataSet内のPricePerRowをSumという関数で足し合わせた結果を表示する式です。
レポート画面を実装する
レポート画面は、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の部品を用意することも考えられます。