SharepointLists: 進捗率表示のカスタマイズ。データバー ⊕ 色 ⊕ アイコン

# 背景
ある社内講習に参加した際
『学習状況の把握の為に Excel に入力してください。』・・と

ということで、Lists でならこんな簡単ですよ？という利用例を提示する為の設定の記録

とはいえ、自分自身ほとんど触ったことが無かったので学習から

# やりたいこと
リストで 進捗率(パーセント) を分かりやすく表示したい

普通にデータバーの設定のままでもいいんですが、どうやら把握したい段階があるようなので・・

- データバーを値によって色変え
- ついでにアイコンも  
- 段階は、とりあえず 5。多ければ適当に削ればいいだけだしってことで。
    - 未入力 or 0 ～ 10%
    - ～ 20%
    - ～ 50%
    - ～ 100%
    - 100%

結果イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/c2a8e853-a71f-e5d4-4039-42442a89691d.png)


# 実践
## 理解のすすめ
「例こそが人に伝える唯一の手段」信奉者なのでまずは実例を元に確認

単純にデータバーを設定して、JSON を見てみると
> ![2022-05-26_16h55_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645569/ec2ea951-5416-6a67-d653-5aa572794bc2.png)

operands が分かりづらい・・
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/6ba41574-f76d-4357-3542-6e85db586c8b.png)

[抽象構文ツリーの式](https://docs.microsoft.com/ja-jp/sharepoint/dev/declarative-customization/formatting-syntax-reference#abstract-syntax-tree-expressions) を見ると、PowerFx(?) で書けるものが、抽象構文ツリーで自動生成されてるらしい。
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/72ec9eb2-d921-e4c8-1ae7-8979677afd54.png)

ってことで、まずは慣れる為にも、データバーを、Power Fx っぽい式に変換してみる

## 抽象構文ツリーからPower Fx 式へ
ってことで、変換してみると、とっても分かりやすくなりました。

$comments で、コメント追記することで、分かりやすくしておくと吉

```json:変換後

{
    "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json",
    "elmType": "div",
    "children": [
      {
        "elmType": "span",
        "txtContent": "@currentField.displayValue",
        "style": {
          "position": "absolute",
          "white-space": "nowrap",
          "padding": "0 4px"
        },
        "attributes": {
          "class": "=if(@currentField.displayValue < 0 ,'sp-css-color-CoralFont','sp-css-color-MintGreenFont')",
          "$comments": "文字色を正負で変える"
        }
      },
      {
        "elmType": "div",
        "attributes": {
          "class": "=if(@currentField.displayValue >= 0 ,'sp-field-dashedBorderRight','')"
        },
        "style": {
          "min-height": "inherit",
          "box-sizing": "border-box",
          "padding-left": "=(abs(-50) - if(@currentField.displayValue < 0 , abs(if(@currentField.displayValue <= -50, abs(-50), @currentField.displayValue)), 0)) / 150 * 100 + '%'"
        },
        "$comments": "負側のデータバー"
      },
      {
        "elmType": "div",
        "attributes": {
          "class": "=if(@currentField.displayValue < 0 ,'sp-css-backgroundColor-BgCoral sp-css-borderTop-CoralFont','sp-css-backgroundColor-BgMintGreen sp-css-borderTop-MintGreenFont')"
        },
        "style": {
          "min-height": "inherit",
          "box-sizing": "border-box",
          "width": "=if(@currentField.displayValue <= -50, abs(-50), if(@currentField.displayValue >= 100, 100, abs(@currentField.displayValue)))/ 150 * 100 + '%'"
        },
        "$comments": "正側のデータバー"  
      },
      {
        "elmType": "div",
        "style": {
          "min-height": "inherit",
          "box-sizing": "border-box"
        },
        "attributes": {
          "class": "=if(@currentField.displayValue < 0, 'sp-field-dashedBorderRight', '')"
        },
        "$comments": "中央の点線描画（負数用"
      }
    ]
  }
```

一応差分確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/f4b034c7-9083-7239-ed19-5f7639764667.png)

## 機能追加
実際の変更点としては

- 不要箇所削除
    - 負数側のデータバーを削除
    - 中央の点線（０基準線）の削除
- 機能追加
    - アイコン追加
    - データバーの色変え
    - ついでに、文字色もデータバー同様に色変え
    - borderTop を下側にして、100% 表示基準へ
 
で、最終形態はこんな感じ
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/6916ddc7-ddab-038e-c76f-1fb90b526b3d.png)


使うときは以下をコピーで。@currentField として指定しているので、そのまま使える筈。

:::note info
- 段階を切り替える数値は固定埋め込みなので全置換で・・
- Iconは、IconName を[**ここ**](https://uifabricicons.azurewebsites.net/)で拾ってきて置換
- 色とか見た目は、[**ここ**](https://zerg00s.github.io/sp-modern-classes/)で確認して置き換え
:::

```json:データバー ⊕ 色 ⊕ アイコン の例
{
    "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json",
    "elmType": "div",
    "children": [
        {
            "elmType": "span",
            "txtContent": "=' ' + if(@currentField == '', '未', @currentField.displayValue)",
            "style": {
                "position": "absolute",
                "white-space": "nowrap",
                "padding": "0 4px",
                "text-indent": "2px"
            },
            "attributes": {
                "class": "=if(@currentField >= 1.0 , 'sp-css-color-MintGreenFont' , if(@currentField >= 0.9 , 'sp-css-color-CornflowerBlueFont' , if(@currentField >= 0.6 , 'sp-css-color-GoldFont' , if(@currentField >= 0.3 , 'sp-css-color-PeachFont' , 'sp-css-color-CoralFont'))) )",
                "iconName": "=if(@currentField >= 1.0 , 'Completed12' , if(@currentField >= 0.9 , 'CoffeeScript' , if(@currentField >= 0.6 , 'Running' , if(@currentField >= 0.3 , 'HazyDay' , 'SearchNearby'))) )",
                "$comments": "文字色を正負で変える"
            }
        },
        {
            "elmType": "div",
            "attributes": {
                "class": "=if(@currentField >= 1.0 , 'sp-field-borderBottomSolid sp-css-color-MintGreenFont' , if(@currentField >= 0.9 , 'sp-field-borderBottomSolid sp-css-color-CornflowerBlueFont' , if(@currentField >= 0.6 , 'sp-field-borderBottomSolid sp-css-color-GoldFont' , if(@currentField >= 0.3 , 'sp-field-borderBottomSolid sp-css-color-PeachFont' , 'sp-field-borderBottomSolid sp-css-color-CoralFont'))) )",
                "$comments": "データバーそのもの"
            },
            "style": {
                "min-height": "inherit",
                "box-sizing": "border-box",
                "width": "100%",
                "$comments": "データバーの長さ指定"
            },
            "children": [
                {
                    "elmType": "div",
                    "attributes": {
                        "class": "=if(@currentField >= 1.0 , 'sp-css-backgroundColor-BgMintGreen sp-css-borderColor-MintGreenFont' , if(@currentField >= 0.9 , 'sp-css-backgroundColor-BgCornflowerBlue' , if(@currentField >= 0.6 , 'sp-css-backgroundColor-BgGold sp-css-borderColor-GoldFont sp-css-color-GoldFont' , if(@currentField >= 0.3 , 'sp-css-backgroundColor-BgPeach sp-css-borderColor-PeachFont sp-css-color-PeachFont' , 'sp-css-backgroundColor-BgCoral sp-css-borderColor-CoralFont'))) )",
                        "$comments": "データバーそのもの"
                    },
                    "style": {
                        "min-height": "inherit",
                        "box-sizing": "border-box",
                        "width": "=if(@currentField >= 1.0, 100, @currentField / 1.0 * 100) + '%'",
                        "$comments": "データバーの長さ指定"
                    }
                }
            ]
        }
    ]
}
```

# 参考
## 基本
https://docs.microsoft.com/ja-jp/sharepoint/dev/declarative-customization/column-formatting

## Lists の JSON 設定の概要確認

https://qiita.com/Momono_gg/items/58bf768fb83bddfbdca1

## IconName はここで確認して取得
https://uifabricicons.azurewebsites.net/

## CSS Style はここで確認して取得

https://zerg00s.github.io/sp-modern-classes/


# デバッグ用途補足
プレビューを使って確認しながらするわけだけど、他の列を一緒に見たくなる時には、子要素追加が便利だった
```json: 子要素追加
      "children": [
          {
              "elmType": "div",
              "txtContent": "[${他の列名とか}]"
          }
      ]
```

# あとがき
JSON 内の自己参照が出来たら、固定値を一か所に集められるのに、と思うんですが・・
Adaptive Card の \\$data のような形で持てないものかと試してみたけど、そもそも \\$data をどこに定義するのか？と

良い解決策があれば教えてほしいです。

# keyword
json customize sample of percent column with data bar, color, and icon.