Power Apps からCSVテキストを作成するための汎用的な関数

# はじめに
これまでは、Power Apps でコレクションからCSVを作成する方法として、大きく2つあったと思います。

今回は、「新しい関数を使って従来の方法の弱点を克服した」という内容です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/6a70232d-f637-2ace-c140-a5c95fa013ce.png)


## ①フローの使用
1つはフローにコレクションを渡す方法です。
こちらは一度JSONへの変換を挟む必要こそありますが、コレクションの中身をあまり意識せずに使用することができるので、使いやすい方法です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/6ad4fcef-d1ca-9020-7ed9-8ab5f023d359.png)

Appsからの呼び出しもシンプルです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/b1f576ae-7afe-92dd-171d-e05aefd29277.png)

ただし、一度フローを挟む必要があるので、Power Apps だけで完結させたいという場合には使えません。

また、CSVとしての出力形式を指定すること、例えばExcelにそのまま貼り付けられるように、カンマ区切りではなくタブ区切りに変えたいという要望には答えられないという欠点もあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/ca142449-28d1-0861-ad46-9cd9998bf084.png)


## ②関数の使用
もう1つはPower Apps 内の関数でコレクションの中身を文字列として結合して作成する方法です。

```plaintext:
Copy(
    With(
        {
            delimiter: Char(9),
            quotechar: """"
        },
        Concatenate(
                    quotechar,"ひらがな",quotechar,
                    delimiter,
                    quotechar,"アルファベット",quotechar,
                    delimiter,
                    quotechar,"数字",quotechar
                )&Char(10)&
        Concat(
            ForAll(
                col As X,
                Concatenate(
                    quotechar,X.ひらがな,quotechar,
                    delimiter,
                    quotechar,X.アルファベット,quotechar,
                    delimiter,
                    quotechar,X.数字,quotechar
                )
            ),
            Value,
            Char(10)
        )
    )
)
```


ただし、この方法はあらかじめ列名がわかっていなければ関数を作成することができないという問題がありました。

また、列が多い場合は1つ1つ列を指定して関数を作るのがとても手間であるという問題もありました。
今回は例として列が3つだけの場合を作成しましたが、列が増えれば増えるほど関数が長くなっていきます。

# ColumnNames関数、Column関数 
Power Apps に新しい関数として、`ColumnNames`関数と`Column`関数が追加されました。
これにより、コレクションの列を動的に取得することができるようになったため、あらかじめ列をすべて指定するという必要がなくなりました！

https://powerplatformnikki.com/columnnamescolumn/


# 最終的に出来上がった式
ということで出来上がったのがこちらです。
`collection: col`の部分を、CSVに変換したい任意のコレクションに変更することでお使いいただけると思います。

```plaintext:ColumnNames関数・Column関数を使用したCSV出力関数
Copy(
    With(
        {
            collection: col,   //ここが任意のコレクション
            delimiter: Char(9) //区切り文字。Char(9)はタブ文字
        },
        With(
            {names: ColumnNames(ParseJSON(JSON(First(collection))))},
            Concat(
                names,
                Value,
                delimiter
            ) & Char(10) & Concat(
                ForAll(
                    collection As C,
                    Concat(
                        ForAll(
                            names As N,
                            Column(
                                ParseJSON(JSON(C)),
                                N.Value
                            )
                        ),
                        Value,
                        delimiter
                    )
                ),
                Value,
                Char(10)
            )
        )
    )
);
```


# おまけ
値を引用符で囲み、元の値の中に引用符があった場合は、引用符2文字分に変換してエスケープするバージョンです。

```plaintext:コレクションからCSVを作成してクリップボードにコピーする関数
Copy(
    With(
        {
            collection: col,     //ここが任意のコレクション
            delimiter: Char(9),  //区切り文字。Char(9)はタブ文字
            quotechar: """"      //引用符。""""はダブルクォーテーション1文字分
        },
        With(
            {names: ColumnNames(ParseJSON(JSON(First(collection))))},
            Concat(
                names,
                quotechar & Substitute(
                    Value,
                    quotechar,
                    quotechar & quotechar
                ) & quotechar,
                delimiter
            ) & Char(10) & Concat(
                ForAll(
                    collection As C,
                    Concat(
                        ForAll(
                            names As N,
                            Column(
                                ParseJSON(JSON(C)),
                                N.Value
                            )
                        ),
                        quotechar & Substitute(
                            Value,
                            quotechar,
                            quotechar & quotechar
                        ) & quotechar,
                        delimiter
                    )
                ),
                Value,
                Char(10)
            )
        )
    )
);

```

# 申し訳程度の解説
詳細な解説は省略いたしますが、やってることだけサクッと述べておきます。
1. `ColumnNames`関数で列名一覧の配列を取得
1. 取得した列名一覧を`Concat`関数で区切り文字で挟みながらつなげる
1. 外側の`ForAll`でコレクションの行ごとにループ
1. コレクションの各行ごとに内側の`ForAll`で列ごとにループ
1. 内側のループでは列ごとの値を`Colunm`関数で取り出して区切り文字で結合
1. 外側のループでは区切り文字で結合した各行を、改行文字で結合

解説は以上です！