PowerAutomate「ファイルの作成」で使用できない文字


# ユーザーが決めたファイル名のまま保存すると予期せぬトラブルに繋がる。
Power Automateの「ファイルの作成」アクションでSharePointにファイルを保存するとき、ファイル名の禁則文字があります。
SharePointに手動で保存する場合は問題なくても、Power Automateからファイルを保存する場合はより制限が厳しいようで、ユーザーがつけたファイル名で保存しようとするとフローが異常終了することがあります。

# どんなファイル名が利用できないか

SharePoint/OneDriveのドキュメントを見ると、SPOの場合はそもそもファイル名に使用できない```" * : < > ? / \ |```に加え、
```$```と```#```も環境により使用できないとの記載があります。

$も#もSharePointに手動で保存する場合は問題なく保存できます。
また、なぜか```_vti_```の名前も禁則文字で、これは手動でも保存できないようです。
https://support.microsoft.com/ja-jp/office/onedrive-%E3%81%A8-sharepoint-%E3%81%AE%E5%88%B6%E9%99%90%E4%BA%8B%E9%A0%85-64883a5d-228e-48f5-b3d2-eb39e07630fa#invalidfilefoldernames

しかしながら、前述の通りPower Automate経由で保存する場合は制限が厳しいようです。
以下は検証した限りでPower Automate経由で正しく保存でいない文字列の一覧です。

## Automate経由での保存でエラーが発生するもの
ファイル名に以下を含むファイルの作成アクションはNot Foundとなり失敗します。
%については、%25などのデコード可能な並びの場合は保存可能でした。

```
[
    "#",
    "%",
    "_vti_"
]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/0d33336e-44de-ee04-5bb4-fff3b71de96b.png)



## 保存はできるが勝手に「_」に変換されるもの
ファイルの作成アクションで以下の記号を含めて保存すると、記号が_に変換されて保存されました。
※確率は低いと思いますが、_に変換されることでファイル名が重複して失敗するパターンもあります。

```
[
    "~",
    "{",
    "}",
]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/52ef81a0-1c96-b4ac-9c65-c90bc3eb4ff6.png)



# 対策
ファイル名にこれらの記号は使うなと厳しく指導してください🙁

システム的にファイル名を決めたいところですが、
テクニック的な備忘録として、禁止文字をリネームする方法を考えましたので残しておきます。

# PowerAutomateで複数の文字列を置換する

## Apply to Eachを使った方法

### 全体像
- 禁則文字リストを作る
- それを to each で回す
- 置換して変数に格納

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/2066b207-dbe2-2aaf-fa02-e5c5242bf6c9.png)


### 詳細
まずは変数「元ファイル名」に保存したいファイル名を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/6ab173b4-7a44-0e1d-2f89-c437cb2b8456.png)

禁則文字を配列で定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/5ee6eec3-1663-7399-71d8-d071ad2b77eb.png)


禁則文字の配列をApply to each で回します。
一旦作成アクションで、変数のファイル名をreplaceして、
次に変数の設定アクションでこれをセットします。
※変数の設定が自己参照できないため。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/e9b69252-e314-0944-01e4-deb43ebf7acb.png)

置換後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/0b37581c-9f3e-a064-fe40-f4595384c140.png)


## Selectアクションの場合
選択アクションでやる方法も考えてみました。
1文字の記号ならこれでなんとか・・・

### 全体像
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/173d30ef-7c2f-78ef-9bc6-bbb04b9f88ff.png)

以下のようにファイル名と禁止文字マップを作成。
{"記号":"置換後文字"}の配列
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/0eb5b6ba-c275-3a01-9e49-865a9e403b79.png)

選択アクションで、ファイル名の文字列を一文字ずつ分解。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/507f0081-10ed-9349-5b66-687b95d9cf91.png)

```JS
//これで文字数分の配列を作り
range(0,length(outputs('作成：ファイル名')))
//1文字ずつ出力
substring(outputs('作成：ファイル名'),item(),1)
```

String.Split("")ができないのは不便。


もう一つの選択アクションで禁止文字をマッピング
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/0b0e4102-1378-2ba6-cf1c-017953d2fedc.png)

```js
//item()が禁止文字マップに存在しない場合→ item()を出力
//存在する場合→ 禁止文字マップから置換後文字列を出力
if(equals(empty(outputs('作成：禁止文字マップ')?[item()]),true),item(),outputs('作成：禁止文字マップ')?[item()])
```

最後は配列から文字列に戻します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/fc12546a-3d55-37de-cf4b-033f95ee7556.png)


一文字ずつに分解する都合上、`_vti_`は対応できませんでした。
方法思いついたら追記します。






Power Automateでファイルを保存する場合は注意ですね。
可能であれば、システム側で名前を付けて、元ファイル名は他の場所で保持してあげたいです。

# 関連記事

https://qiita.com/Rambosan/items/a272f3e56713e43575f9