【UiPath】ファイルリネーム実装について

# はじめに
ロボでは処理完了後に処理ファイルを指定されたフォルダに格納するケースが多々あります。
ロボで処理するファイル名が固定値の場合、処理完了後そのまま指定したフォルダに移動させる場合とファイル名重複によるエラーが起こり得ます。
業務要件によっては、業務側が管理しやすい形式は変わってきます。業務側とどのような形式なら管理または再鑑する運用が取りやすいか要件ヒアリングを実施して取り決めます。
今回の記事は、過去にロボ開発で使用したファイルリネームのナレッジとして残します。

# この記事の対象者
- UiPath初学者
- UiPath Studioロボ実行にて、ファイルリネーム処理実装を検討したい方

# 目次
1. 開発環境紹介
1. 処理要件確認
1. 実装
1. 解説


# 開発環境紹介
- OS：Windows11
- 開発ツール：UiPath Studio
- バージョン：2023.10.0
- ライセンス：Community License
- モダン デザイン エクスペリエンス：いいえ
- Microsoft Excel：2310

:::note warn
- 本投稿の開発環境になっております
- バージョンによっては画面が一部異なる可能性はございます
:::

### UiPath 依存関係
| パッケージ名 | バージョン |
|:--|:--|
| UiPath.Excel.Activities | 2.22.2 |
| UiPath.Mail.Activities | 1.21.1 |
| UiPath.System.Activities | 23.10.2 |
| UiPath.Testing.Activities | 23.10.0 |
| UiPath.UIAutomation.Activities | 23.10.3 |

# 処理要件確認
- ロボ処理完了後にファイル名を変更して指定されたフォルダに移動を行いたい

### リネームパターン
| No. | リネームパターン | 設定箇所  | ロボ実行回数：1回 | ロボ実行回数：2回以上 |備考 |
|:--|:--|:--|:--|:--|:--|
| 1 | _yyyyMMdd | ファイル名末尾 | ○ | × | yyyyMMdd…年月日 |
| 2 | _yyyyMMddHHmmss | ファイル名末尾 | ○ | ○ | yyyyMMddHHmmss…年月日時分秒 |
| 3 | _x | ファイル名末尾 | ○ | ○ | x…数値　<br>リネーム先のファイル名が既に存在する場合、重複しないように数値カウントアップを行う。 |
| 4 | _n_yyyyMMddHHmmss | ファイル名末尾 | ○ | ○ | n…ロボが複数台存在する場合の識別番号　<br>ex.プロセス番号  |
| 5 | 【xxx】_ | ファイル名先頭 | ○ | × | xxx…固定文言　<br>ex.完了,未完了,要確認  |

:::note info
- ロボ開発時に実際に使用したことがあるリネームパターンになります
- 業務側の目的に合わせて設計することが重要です
:::

# 実装
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524399/8d3db177-edf2-34a1-f69b-050472d39249.png)


  ### 「コードを呼び出し」アクティビティを利用したDictionaryの設定値 (コードを呼び出し：処理データセット)
~~~vb:コードを呼び出し：処理データセット　
'====================
'処理概要：ファイル操作情報をセット

'IN：
'OUT：なし
  'OutDicInputItem：ファイル操作情報
    'KEY：インプットファイルパス
    'KEY：ファイル名
    'KEY：ファイル拡張子
    'KEY：処理完了格納パス
    'KEY：プロセス番号
    'KEY：ファイルリネーム設定
    'KEY：処理日
    'KEY：現在時刻
    'KEY：データ数
'IO：なし
'====================

OutDicInputItem = New Dictionary(Of String,String)

'dicInputItem
OutDicInputItem("インプットファイルパス") = "C:\RPA\UiPath\入力"
OutDicInputItem("ファイル名") = "処理台帳"
OutDicInputItem("ファイル拡張子") = ".xlsx"
OutDicInputItem("処理完了格納パス") = "C:\RPA\UiPath\出力\FileRename\処理完了"
OutDicInputItem("プロセス番号") = "1"
OutDicInputItem("ファイルリネーム設定") = "【完了】"
OutDicInputItem("処理日") = DateTime.Now.ToString("yyyyMMdd")
OutDicInputItem("現在時刻") = DateTime.Now.ToString("yyyyMMddHHmmss")
OutDicInputItem("データ数") = System.IO.Directory.GetFiles(OutDicInputItem("処理完了格納パス") , "*").Count.ToString
~~~

### コードを呼び出し：処理データセット　 「呼び出されたコード引数」
| Name | Direction | Type | Value |
|:--|:--|:--|:--|
| OutDicInputItem | 出力 | Dictionary<String,String> | dicInputItem |

### 本ロボで利用する変数情報
| 名前 | 変数の型 | スコープ | 規定 | 注釈 |
|:--|:--|:--|:--|:--|
| dicInputItem | Dictionary<String,String> | FileRename | | ファイル操作情報　|
| inputFilePath | String | FileRename | | 入力ファイルパス　|
| outputFilePath | String | FileRename | | 出力ファイルパス　|

# 解説

### リネームパターン1
~~~vb:代入：アウトプットファイル
'====================
'リネームパターン1
'_yyyyMMdd
'====================
outputFilePath = Path.Combine(dicInputItem("処理完了格納パス"), dicInputItem("ファイル名") & "_" & dicInputItem("処理日") & dicInputItem("ファイル拡張子"))
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524399/26b5118f-adb0-a2ee-bbd6-4221a8dc9829.png)
【メリット】
・ファイル名が実行日(yyyyMMdd)の形式なためシンプル
・実行日(yyyyMMdd)毎に格納するため毎日一回実行の場合は有用
【デメリット】
・1日に複数回実行の場合、ファイル名が重複して移動できないケースがある

### リネームパターン2
~~~vb:代入：アウトプットファイル　
'====================
'リネームパターン2
'_yyyyMMddHHmmss
'====================
Path.Combine(dicInputItem("処理完了格納パス"), dicInputItem("ファイル名") & "_" & dicInputItem("現在時刻") & dicInputItem("ファイル拡張子"))
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524399/5192f46a-a014-52e7-71ce-e83c3ed7f9bd.png)
【メリット】
・ファイル名1ロボの場合、重複するケースが起こりにくい
・1日2回以上実行する場合でもファイルリネーム対応が可能
【デメリット】
・リネーム時のファイル名が長くなる


### リネームパターン3
~~~vb:代入：アウトプットファイル　
'====================
'リネームパターン3
'_x
'====================
Path.Combine(dicInputItem("処理完了格納パス"), dicInputItem("ファイル名") & "_" & dicInputItem("データ数") & dicInputItem("ファイル拡張子"))
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524399/a18e1054-6667-4262-dd19-515636aa39da.png)
【メリット】
・ファイル数に対してカウントアップする
【デメリット】
・ファイル数に応じてカウントアップするため、業務担当者側でファイル番号を変えた場合、重複するケースがある
※ファイル名をチェックして繰り返しカウントアップする記事は別途作成予定です。


### リネームパターン4
~~~vb:代入：アウトプットファイル　
'====================
'リネームパターン4
'_n_yyyyMMddHHmmss
'====================
Path.Combine(dicInputItem("処理完了格納パス"), dicInputItem("ファイル名") & "_" & dicInputItem("プロセス番号") & "_" & dicInputItem("現在時刻") & dicInputItem("ファイル拡張子"))
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524399/cb8e3141-2f99-0081-1e26-ee9930cd3eb5.png)
【メリット】
・Uipath Orchestrator等で複数のロボ実行時に、どのロボで実行したか識別が可能
・1日2回以上実行する場合でもファイルリネーム対応が可能
【デメリット】
・リネーム時のファイル名が長くなる


### リネームパターン5
~~~vb:代入：アウトプットファイル　
'====================
'リネームパターン5
'【xxx】_
'====================
Path.Combine(dicInputItem("処理完了格納パス"), dicInputItem("ファイルリネーム設定") & dicInputItem("ファイル名") & dicInputItem("ファイル拡張子"))
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524399/b4c9c54c-b011-dded-c823-84d0ad64f911.png)
【メリット】
・ロボ実行状況が一目で確認ができる
【デメリット】
・2回以上の実行の場合、ファイル名が重複するので、人の目で再鑑後に移動などの工程を挟む必要がある

# おわりに
今回は実務で実際に使用したことがあるフィルリネームをまとめました。個人的にはNo.2「_yyyyMMddHHmmss」を使いたい場面が多いですが、ユーザー側からしたらファイル名が長い、処理結果をファイル名だけで判断したいという要望の声も実務で多々ありました。ユーザー側がどのようにすれば管理しやすいかパターンはそれぞれあるので、寄り添ってベストな方法に導けるのが大事です。今回のナレッジで誰かの参考になれば幸いです。

# 参考サイト
- [Path.Combine メソッド](https://learn.microsoft.com/ja-jp/dotnet/api/system.io.path.combine?view=net-8.0)