PowerAppsでCSVログを読み込んで集計してCSVで整形して表示させる。

# はじめに
PowerAppsで文字列操作の練習をするために、FWログの集計をしてみました。
実用性はなさそうです。

# やりたいこと

以下のようなログがあった場合に、 10分区切りの同じ時刻において、ポートごとの、転送Byte数を算出する

```
'Receive Time'      , 'Destination Port' , 'Bytes'
2020/04/01 10:13:00 ,  22                , 100
2020/04/01 10:15:00 ,  22                , 120
2020/04/01 10:43:00 ,  23                ,  30
2020/04/01 10:45:00 , 445                , 300
2020/04/01 10:48:00 ,  23                ,  80
2020/04/01 10:49:00 ,  22                ,  90
```

|'Receive Time'      | 'Destination Port' | 'Bytes'|
|:-:|--:|--:|
|2020/04/01 10:13:00 |  22                | 100|
|2020/04/01 10:15:00 |  22                | 120|
|2020/04/01 10:43:00 |  23                |  30|
|2020/04/01 10:45:00 | 445                | 300|
|2020/04/01 10:48:00 |  23                |  80|
|2020/04/01 10:49:00 |  22                |  90|

これを以下のように表示させたい

```
LOG , 10:1X , 10:4X
 22 ,   220 ,   90
 23 ,       ,  110
445 ,       ,  300
```


|LOG | 10:1X | 10:4X|
|--:|--:|--:|
| 22 |   220 |   90|
| 23 |       |  110|
|445 |       |  300|

# 画面の準備

元ログを表示するラベル、集計ログを表示するラベル、集計ボタンを配置
[![Screenshot from Gyazo](https://gyazo.com/92fe5ef87384c258dd95a73f3b688dff/raw)](https://gyazo.com/92fe5ef87384c258dd95a73f3b688dff)

## 元ログを表示するラベル
もとのデータソースをカラムごとに表示させるだけです。

```元ログを表示するラベル.Text
Concat(ColDataSource,'Receive Time'&","&'Destination Port'&","&Bytes,Char(13)&Char(10))
```

## 集計ログを表示するラベル
集計ボタンで処理した結果を表示させるだけです。

```集計ログを表示するラベル.Text
strLog
```

## 集計処理を行うボタン
ボタンが押されると処理が走ります。

```集計処理を行うボタン.OnSelect
// 本チャンのデータソースを読み込む場合は、適当なコネクタを入れて、データを読み込みます。
// 今回はテスト表示なので、コメント
// ClearCollect(ColDataSource,[@FWlog])

// テスト用のログを設定
ClearCollect(ColDataSource,Table( { 'Receive Time': DateTimeValue("2020/04/01 10:13:00") , 'Destination Port': "22" , 'Bytes': 100 }, { 'Receive Time': DateTimeValue("2020/04/01 10:15:00") , 'Destination Port': "22" , 'Bytes': 120 }, { 'Receive Time': DateTimeValue("2020/04/01 10:43:00") , 'Destination Port': "23" , 'Bytes': 30 }, { 'Receive Time': DateTimeValue("2020/04/01 10:45:00") , 'Destination Port': "445" , 'Bytes': 300 }, { 'Receive Time': DateTimeValue("2020/04/01 10:48:00") , 'Destination Port': "23" , 'Bytes': 80 }, { 'Receive Time': DateTimeValue("2020/04/01 10:49:00") , 'Destination Port': "22" , 'Bytes': 90 } ))

//
// 集計対象とするデータソースを、以下の４つのカラムを持つコレクションにコピーします
//   COLUMN    : 横方向の要素（この場合、'Receive Time'の YYYY/MM/DD hh:mm:ss のうち、時刻の部分の先頭４バイト分、 ）
//   ROW       : 縦方向の要素（この場合、'Destication Port'）
//   VALUE     : 集計対象にする数値（この場合、'Bytes'）
//   SUM_TARGET: 集計対象を判断するための仮のカラム（COLUMNとROWをカンマ区切りにする）
//
;ClearCollect( ColLog, 
               ForAll( ColDataSource,{ 
                                      COLUMN:     Left(Text('Receive Time',ShortTime24),4)&"X" ,
                                      ROW:        Text('Destination Port'),
                                      VALUE:      Value('Bytes'),
                                      SUM_TARGET: Left(Text('Receive Time',ShortTime24),4)&"X"&","&Text('Destination Port')
                                     }
               ) 
)

// ColLog_ALL_ROWs
// 期間中の行方向の全成分を単一列にまとめる
// ログに存在しない行方向の成分を含める場合は、ここに追加する
;ClearCollect( ColTemp,ForAll(ColLog,{ROW:ROW}))
;ClearCollect( ColLog_ALL_ROWs,
               SortByColumns( 
                   RenameColumns( Distinct(ColTemp,ROW) , "Result" , "ROW_check") ,
                   "ROW_check"
               )
)

// ColLog_ALL_COLUMNs
// 期間中の列方向の全成分を単一列にまとめる
// ログに存在しない列方向の成分を含める場合は、ここに追加する
;ClearCollect( ColTemp,ForAll(ColLog,{COLUMN:COLUMN}))
;ClearCollect( ColLog_ALL_COLUMNs, 
               SortByColumns( 
                   RenameColumns( Distinct(ColTemp,COLUMN) , "Result" , "COLUMN_check") ,
                   "COLUMN_check"
               )
)

// ColLog_VALUEsum_PER_COLUMNs
// VALUEを合算したい対象カラム（SUM_TARGET）をグループ化して、SUMる
;ClearCollect( ColLog_VALUEsum_PER_COLUMNs, 
               AddColumns( GroupBy(ColLog,"SUM_TARGET","GROUP_SUM_TARGET"),
                           "TOTAL VALUE PER COLUMN" , Sum( GROUP_SUM_TARGET, VALUE ) ,
                           "COLUMN"                 , First(Split(SUM_TARGET,",")).Result ,
                           "ROW"                    ,  Last(Split(SUM_TARGET,",")).Result
              )
)

// strLogに吐き出す
;Set(strLog,
  // 最初の行はヘッダ
  "LOG,"&Concat(ColLog_ALL_COLUMNs,COLUMN_check,",")&Char(13)&Char(10)&
  // 行方向でループさせつつ、
  Concat(ColLog_ALL_ROWs,
  // -------------------> 列方向でループさせ
         ROW_check & ","& Concat(ColLog_ALL_COLUMNs, 
  // --------------------------> 行＆列が合致した集計済数値を表示させる
                                 Text( LookUp(ColLog_VALUEsum_PER_COLUMNs,ROW=ROW_check&&COLUMN=COLUMN_check).'TOTAL VALUE PER COLUMN'),
                                 "," ) , 
         Char(13)&Char(10)
  )
)
```

# さいごに
これを、「CSVで出力」できるとうれしいのですが、Export/Importの機能は、コレクションをPowerAppsアプリ同士で交換するための機能のようで、強制的にJSONになっちゃうんですね。

単純なループの処理ができないので、とっても文字列操作がやりにくいですね。
果たしてこんな処理をPowerAppsの中でやる意味はあるのか。。。
まぁ、練習です。