【SAC】Analytic Applicationsの概要と開発過程で困ったところ

# Analytic Applications(通称：AA)とは？

**SAP Analytics Cloud(SAC)**のダッシュボード機能の１つ。
GUIベースでダッシュボードを作成できるストーリーの機能に加え、
**Analytics Designer**を使用してUI、分析処理をスクリプト開発することができる。
従来のストーリーに比べカスタマイズ性が高いことが特徴。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/b9b7b6fb-3c78-fb31-2f69-6400ca2e8ff4.png)
※ストーリーについては下記の記事を参照
[【SAC】SAP Analytics Cloud でデモ環境を構築する　～前編～](https://qiita.com/iwa_gino/items/72be48318e897908303a)
[【SAC】SAP Analytics Cloud でデモ環境を構築する　～後編～](https://qiita.com/iwa_gino/items/14291f09fbb5c43ea4aa)


# Analytic Applicationsの作成～基本操作
１．SACのメインメニューから**[作成]→[アナリティクスアプリケーション]**を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/9d00459d-6927-5b48-9d2c-d2138e505d97.png)

２．Analytic Applications作成画面に遷移する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/e0e83179-08ea-600b-3a82-6793a710b204.png)

３．チャート、テーブル、テキスト等のオブジェクトは、従来のストーリー機能と同様「挿入」バーより追加できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/eb59d5b0-4fcc-b131-29e4-ba6f89229113.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/44e2423c-ca26-0342-722a-953677e36f29.png)

４．スクリプトの実装は、左のアウトラインからオブジェクトの**[fx]**を押下しスクリプトエディタを開いて行う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/39b56bc0-74c5-82c0-8c30-04552af46e76.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/7d873faa-e7af-22f3-2455-2c68a4504756.png)

５．保存はストーリー機能の操作と同様。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/54d09c5c-90fd-3734-0f96-0ac8eb7b1423.png)

# スクリプト実装について
Analytics Designerで使用できるスクリプトの基本的な実装例は下記のハンドブックを参照
[SAC Developer Handbook Analytics Designer](https://www.sapanalytics.cloud/wp-content/uploads/2020/07/SACDeveloperHandbookAnalyticsDesigner.pdf)


# 開発過程で困ったところ

## 1. フィルタ機能の実装

### 【事象】
ダッシュボードのフィルタ機能が標準でサポートされていない。

**【ストーリー】**
**入力コントロール**を使用することでフィルタ機能を実装することができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/84062792-5f37-a1d2-c184-fc405f013cbb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/0dc45e3e-90ae-6b04-c24c-6a0cb0a7746e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/f46f7b03-ca07-4a41-68b8-5270786fc7ad.png)


**【AA】**
入力コントロール機能がサポートされていない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/a673db63-7ec7-16e3-3f47-9c71cdfee7f4.png)



### 【対処法】
次のオブジェクトを使用してフィルタ機能を実装する必要がある。

+ **ドロップダウン**
+ **ラジオボタングループ**
+ **チェックボックスグループ**
+ **リストボックス**


### 【手順】
１．上記のいずれかのオブジェクトを挿入する。
２－１．**（フィルタ項目が固定値の場合）**ビルダパネルにて、フィルタ項目を手動追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/32253653-6051-fd64-60fe-11362c05cd80.png)

２－２．**（モデルのディメンションを参照してフィルタ項目を可変にしたい場合）** フィルタ項目の取得処理を実装する。

２－２－１．キャンバスの**[fx]**を押下し、**[onInitialization]**を選択してスクリプトエディタを開く。

※**onInitialization**：アナリティクスアプリケーションの初期ロード完了後に呼び出されるイベント
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/2cb28c62-4fdb-4147-fbd9-8e064a3affce.png)


２－２－２．onInitializationイベントに次の項目取得処理を記述する。

```
// フィルタ項目の取得（年度（階層設定あり））
var i = 0;
var vYear = Chart_1.getDataSource().getMembers("ID_1c4c1e06b5");

// vYearで取得したディメンションデータを確認
console.log(vYear);

for(i=0;i<vYear.length;i++)
{
	var id = vYear[i].id;
	// vYearの中からAll（全年度）とFISCAL_YEAR（年度）のみをフィルタ項目として取得
	if(id.indexOf('[ID_1c4c1e06b5].[FYQP].[All]') !== -1) {
	   	Dropdown_1.addItem(vYear[i].id,vYear[i].description);
		// 初期表示にはAll（全年度）をフィルタ適用する
		Chart_1.getDataSource().setDimensionFilter("ID_1c4c1e06b5",vYear[i].id);
	} else if(id.indexOf('[ID_1c4c1e06b5].[FYQP].[ID_1c4c1e06b5.FISCAL_YEAR]') !== -1) {
		Dropdown_1.addItem(vYear[i].id,vYear[i].description);	
	}
}
```

**【補足】**

+ ディメンションのIDはモデラ画面から確認することができる。
+ ディメンションデータを全件フィルタ項目として使用する場合は`if(id.indexOf('[ID_1c4c1e06b5].[FYQP].[All]') !== -1 || ...`のIF文は不要。

３．フィルタをダッシュボード内のグラフに適用する処理を実装する。
３－１．１で追加したフィルタオブジェクトの**[fx]**を押下し、**[onSelect]**を選択してスクリプトエディタを開く。

３－２．onSelectイベントに次のフィルタ適用処理を記述する。

```
// 選択したフィルタ項目のキーを取得
var selection = this.getSelectedKey();

// フィルタを一旦解除
Chart_1.getDataSource().removeDimensionFilter("ID_1c4c1e06b5");

// 選択したフィルタ項目を適用
Chart_1.getDataSource().setDimensionFilter("ID_1c4c1e06b5",selection);
```


###【結果】
次の通りフィルタ機能を実装できる。
いずれのフィルタオブジェクトも実装方法は同様のため、ニーズに応じて使い分けること。

+ ドロップダウン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/e1b6e40d-db62-1d1f-6230-bde34fe323f8.png)

+ （左から）チェックボックスグループ、ラジオボタングループ、リストボックス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/3a78adc1-de17-7da5-9f21-ec195af350a1.png)


## 2. ロード中の制御

### 【事象】
アナリティクスアプリケーションのロードが終わると、操作制御が自動で外れる。
（＝後続で走るonInitializationイベントの処理中にダッシュボードの操作が出来てしまう）

### 【対処法】
**ロードインジケータ**を使用して操作制御する。

ロードインジケータには次の2種類の挿入方法があるため、ニーズに合ったものを使用すること。

+ **自動ロードインジケータ**：指定のミリ秒以上の処理時間が発生した際に自動でインジケータを表示する。
+ **ロードインジケータ**：スクリプトにより特定の処理の前後に表示、非表示を設定する。

###【手順（自動ロードインジケータ）】

１．キャンバスを選択した状態で**[デザイナ]**を押下する。
２．表示されたスタイルパネル内の**「必要な場合にロードインジケータを有効化」**にチェックを入れる。
３．次の設定値に任意の値を入力する。
　(1) **情報テキスト（任意）**：ロードインジケータに表示するテキスト
　(2) **ロードインジケータの遅延（単位 ミリ秒）**：指定のミリ秒以上の処理時間が発生した際に自動でインジケータを表示する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/67197975-0682-f56f-1c84-65547dc8d5b3.png)

４．スクリプト内で自動ロードインジケータを**有効化/無効化**することもできる。
※ 常時有効化していると却って操作性が悪くなるため、処理時間が長い箇所以外は無効化しておくことが望ましい。

```
Application.setAutomaticBusyIndicatorEnabled(true); //有効化
Application.setAutomaticBusyIndicatorEnabled(false); //無効化
```

###【手順（ロードインジケータ）】

局所的にロードインジケータを表示させる場合にはこちらがおすすめ。

１．インジケータを表示したい処理の前後に次のスクリプトを追加する。

```
// ロードインジケータの表示
Application.showBusyIndicator("ロード中"); 

// （・・・イベント処理・・・）

// ロードインジケータの非表示
Application.hideBusyIndicator();
```

###【結果】
いずれの挿入方法でも次のようなインジケータが表示され、ダッシュボード操作が制御される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/146d55f0-6d57-f188-7a5b-a8b93ae70366.png)


## 3. 比較値の挿入（増減率表記、前年比表記）

###【事象】

前年売上との比較を前年比表記で挿入したい。

### 【対処法】

**差分計算**を使用して比較値を算出する。

###【手順（増減率表記）】

１．挿入バーから**[チャート]**を押下し、新規グラフを挿入する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/41e36955-8eb1-65a5-38ac-7c5499fe7f23.png)


２．チャート構造を**[数値ポイント]**に設定する。

３．**[メジャー]**→**[一次値]**より**[＋計算の作成...]**を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/ef862f03-e372-2a7c-c420-2c75143b58ed.png)

４．計算タイプに**[差分]**を選択し、次の通り設定する。（前年比の例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/d03facaa-df06-1c1b-ceba-eba83841c591.png)


###【結果（増減率表記）】

+ 前年売上との比較値を挿入できた。
+ ただし、差分計算のみだと増減率表記**（±％）**しかできない。
+ 前年比表記(今回の例だと**「98.75％」**と表示したい)で挿入するには、後述の対処法を踏む必要がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/e0b9d5e4-8c4c-7ea2-f3c0-26842b4d3faa.png)

### 【対処法】

**計算メジャー**を使用して**「1 + [差分計算を使用して算出した比較値] 」**の数式を組み込む。

###【手順（前年比表記）】

１．挿入バーから**[チャート]**を押下し、新規グラフを挿入する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/41e36955-8eb1-65a5-38ac-7c5499fe7f23.png)


２．チャート構造を**[数値ポイント]**に設定する。

３．**[メジャー]**→**[一次値]**より**[＋計算の作成...]**を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/ef862f03-e372-2a7c-c420-2c75143b58ed.png)

４．計算タイプに**[計算メジャー]**を選択し、次の通り設定する。（前年比の例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/b795705d-f1ef-7c7f-3ac9-7a0f658ccb26.png)

###【結果（前年比表記）】

前年売上との比較値を前年比表記で挿入することができた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/b1000c23-355f-aa0b-8b7f-1332d06370e7.png)

###【補足】

値による文字色の変更は**「しきい値」**を登録することで表現することができる。

**【増減率表記の例】** （+0%以上で緑、+0%未満で赤）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/ffa2fea5-27bb-764e-5556-d4c5af8306ae.png)

**【前年比表記の例】** （100%以上で緑、100%未満で赤）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/61e1dfd5-4c31-63a9-bb54-c02d6f773d1e.png)


## 4. ｎ秒ごとにグラフを自動更新

###【事象】
指定の秒数毎にダッシュボード内のグラフを自動更新する仕組みを作りたい。

###【対処法】
**タイマー**オブジェクトを活用する。

**タイマー**：指定の秒数をカウントし、タイムアップ時に**onTimeout**イベントを走らせることができるオブジェクト

① 初期ロード時（**onInitialization**）にタイマーをスタート 
② **onTimeout**イベント内でグラフ更新
③ 再度タイマーをスタート 
・・・
以降②③をループさせることにより、一定時間毎にグラフを自動更新をさせることができる。


###【手順】

１．アウトラインより**[タイマー]**の追加ボタンを押下する。
２．タイマーオブジェクトの名前を入力し、**[完了]**を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/cae744eb-daf0-bcd8-dcf3-9889ec76e1a8.png)

３．タイマーを開始したい箇所に次のスクリプトを追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/3c85e6a4-c298-8ed2-5429-5437689ec808.png)

```
// タイマー開始
Timer_1.start([カウントさせる秒数]);

// 以下補足 -----

// タイマーの停止
Timer_1.stop();

// タイマーの起動の有無を確認（boolean）
Timer_1.isRunning();

```

４．**onTimeout**イベントにグラフ更新とタイマーの再スタートを実装する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/252cdeac-69c6-81a7-3786-740a70aed01b.png)


###【結果】
指定した秒数毎にグラフを自動更新するダッシュボードを作成することができた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/d41b9163-c293-7ea3-3d1a-c793e897b5e0.png)

###【補足】

+ SAC標準のグラフの場合、更新時にロード用の描写が表示される。
+ 短いスパン（1秒毎など）でグラフ更新させると画面のちらつきが気になるが、現状この描写を取り除く方法が見つからなかった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137780/18f1f72b-0210-3ef8-9ba5-f6ebec7f9608.png)

+ ロード時の描写を無くす１つの方法として、サードパーティの**カスタムウィジェット**を組み込むという手がある。
+ **「Google Charts」**は商用利用無料で、提供しているグラフの種類も多いためオススメ。
+ カスタムウィジェットの利用にはウィジェットコンポーネントを配置するためのWebサーバが別途必要。（ローカルでの利用のみであれば、下記リンクの方法で仮想サーバーを立てて試験的に実装することは可能。）

**【参考リンク】**

・**Build a Custom Widget using 3rd Party Libraries in SAP Analytics Cloud**
（カスタムウィジェット導入のチュートリアル。ローカルで仮想サーバーを立てて実装する方法。）
https://blogs.sap.com/2020/02/27/build-a-custom-widget-using-3rd-party-libraries-in-sap-analytics-cloud/

・**Build a Custom Widget in SAP Analytics Cloud, Analytics Application**
（カスタムウィジェットとして使用できるライブラリの一覧）
https://blogs.sap.com/2019/12/06/build-a-custom-widget-in-sap-analytics-cloud-analytics-application/