4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Config.xlsxは本当に必要か?UiPathの新機能でコード寄りのConfigの設定管理を試してみる

Last updated at Posted at 2025-07-11

【おさらい】そもそも「Dictionary」とは?

初心者向けにわかりやすく書いていますので、すでに知っているよっていう人は読み飛ばしてくださいmm

簡単に言うと、「名前と中身をセットで保存する箱」のようなものです。
このように、「名前を指定すれば、中身がすぐに取り出せる」のがDictionaryの特徴です。

名前(キー) 中身(値)
"System1_URL" "https://xxx..."
"RetryNumber" 3
"ShouldSendMail" True

■ なぜこの形が便利なの?

  1. 名前で中身をすぐに呼び出せる:たとえば Config("System1_URL") と書けば、すぐにURLが使えます。
  2. 全体で共通の設定を使いまわせる:一度読み込めば、別の処理からでも同じ設定を使えます。
  3. 設定が増えても整理しやすい:Excelのように「どこに書いたか」探す必要がなく、名前で管理できます。

【ExcelでConfigを管理するとは

UiPathのREFrameworkでは、InitAllSettings.xamlワークフローを通じて、Config.xlsxから設定値を読み込みます。
image.png

読み込まれた設定値は、その後 Dictionary 型として保持され、ワークフロー全体で参照できるようになります。

image.png

これは非常に便利で標準的な方法です。
REFrameworkがConfig.xlsxを標準として採用しているのには、以下のような理由があります。

  • 非エンジニアでも簡単に設定値を編集できる:Excelは誰でも扱えるツールであり、設定値を外部ファイルとして管理しやすい
  • 複数シートで用途を分けられる:Settings, Constants, Assetsなどの区分けが視覚的にでき、分類がしやすい
  • すぐに書き換え可能でリリースが早い:メインの変数やロジックを変更せずに、設定値の変更だけで値変換が可能。
  • ドキュメントとしても機能する:Configの内容が一覧で見られ、外部のレビュワーにも伝わりやすい

このように、「プログラムの外に設定を逃がしておく」という目的では非常に理にかなった設計と言えます。

逆に、Excelを使うデメリットとは?

が、一方で次のような疑問や不便さを感じる場面がありました。

Excelは一般的で扱いやすい反面、運用時の安定性という点ではいくつかの課題が残ります。特に、自動化の実行時に外部ファイルの状態に依存するというのは、RPAの安定性を考える上で無視できない問題です。

  • Excelが開きっぱなしだと実行時にエラーになる(特にデバッグ中は設定値を確認しながらExcelを開いていることが多く、そのまま閉じ忘れて実行するとエラーになるケースがある)

  • image.png

  • ハイパーリンクがあるとエラーの原因に、シート間の数式の複雑な参照などが原因で数式が更新されないエラーが稀に発生する

  • 読み込まれた値はすべてObject型のため、型安全性が低い
    ▼整数にそのまま代入した例
    image.png
    ▼明示的に型変換した例
    image.png

  • Configファイルを開くのが遅いと感じることがある
    ExcelをConfigファイルとして使う必要があるのかは再考の余地があります。というのも、非エンジニアでも扱いやすいとされる一方で、実際にはDictionary型変数との連携などで難易度が上がり、完全に非エンジニア向けとは言い切れません。さらに、Excelは見た目は表形式でも内部はZIP圧縮されたXML構造で、編集履歴や自動ハイパーリンク、意図しない数式、他ブックとのリンクといった“見えない情報”が蓄積されやすく、それが原因不明の読み込みエラーを引き起こすことがあります。私自身、数年に一度程度しか遭遇しない稀なケースですが、一度発生すると再発リスクが残り、エンジニアとしては非常に気持ち悪い“モヤモヤ”が残ります。UiPathでは「ワークブックアクティビティ」と「Excelプロセススコープ」の2種類があり、後者を使えばExcelが開きっぱなしでも安定性は増しますが、処理速度はやや落ちるため、安定性と速度のトレードオフを意識する必要があります。

JSONやYAMLといったファイルを使った運用はどうか

他にも、JSONやYAMLといった形式を使って設定ファイルを管理する方法もあります。これらはテキストベースでシンプルに書けるという利点がありますし、開発の現場ではよく使われています。

{
  "MaxRetryCount": 3,
  "TimeoutSeconds": 30,
  "IsFeatureEnabled": true,
  "ExcelPath": "C:\\data\\report.xlsx",
  "ApiSettings": {
    "BaseUrl": "https://api.example.com",
    "ApiKey": "your-api-key-here",
    "Timeout": 10
  },
  "NotificationEmails": [
    "admin@example.com",
    "support@example.com"
  ],
  "ReportSettings": {
    "IncludeTimestamp": true,
    "OutputFolder": "C:\\output\\reports"
  }
}

ただし、UiPathで扱う場合は、読み込んだ値がすべてObject型になってしまうため、明示的に型変換をしないと使いづらいという欠点があります。Config("RetryNumber")のようにDictionaryで設定値を取り出すと、型が明示されないため、明示的にキャストしないと整数として使えないのも不便でした。なので、実際のところは CInt(Config("RetryNumber")) みたいに明示的に型変換をかけてから使う、という運用になりがちです。

新機能:JSONサンプルから自動でプロパティ生成を使ってみる

UiPathの新機能では、JSONを逆シリアル化する際に、サンプルJSONを入力するだけでプロパティを自動生成できる機能が登場しました。

image.png

たとえば、以下のようなJSONサンプルを指定すると:

{
  "Environment": "Prod",
  "RetryCount": 3
}

自動的に Config.EnvironmentConfig.RetryCount のような型付きプロパティとしてアクセスできるクラスが生成され、非常に便利です。

問題点:型名に乱数が含まれ、保守性に難あり

しかし、この自動生成される型には、毎回ランダムな識別子(乱数)付きのクラス名が付与されます。
さらに、JSONのキーを1つでも変更すると、型名の乱数部分が変わるため、プロジェクト中の参照箇所をすべて修正する必要が出てきます。

Config管理には不向き

Config情報は、開発の進行に伴ってキーの追加・変更が頻繁に発生します。

このような用途では、型名の乱数変更による影響範囲が大きくなるため、この機能を使い続けるのは現実的ではないと判断しました。

そこで、C#でクラス化してみた

こうした問題を解決するために、C#でConfigをクラスとして定義してみるというアプローチを試してみました。UiPathにはもともと提供されているワークフロー(InitAllSettings.xamlなど)がありますが、それではなく、最近登場した「コードソースファイル」という機能を使って、自分でクラスを定義してみたかたちです。

image.png

このコードSourcefileというのはC#専用の機能なのですが、これを活用すれば、ワークフローではなくコードでConfigを管理するという選択肢が出てきます。

正直、最初はこの機能のメリットや使いどころがいまいち掴めなかったのですが、今回のように設定値を保持するファイルの代替として活用してみることで、なるほどこういうときに使えるのか、という実感がわきました。

特に、小規模~中規模のプロジェクトでは、Configの規模もそれほど大きくないことが多いので、こういったC#クラス化による管理も十分現実的だと感じています。

image.png

// 必要なライブラリを読み込む(他の人が作った便利な機能を使うため)
using System; // 基本的なシステム機能を使う

// CTestという名前のグループを作る(他のプログラムと区別するため)
namespace CTest // 名前空間の開始
{
    // Configという名前のクラス(設計図)を作る
    public class Config // クラスの定義開始
    {
        public string NasServerPath { get; set; }  // NASサーバーのパスを保存する変数(プロパティ)
        public string ExcelPath { get; private set; } // Excelファイルのパスを保存する変数(プロパティ)
        
        // 以下はREFrameworkからの引用プロパティ
        public int MaxRetryNumber { get; set; } = 0; // Orchestratorキュー利用時は0。0より大きい場合、システム例外時にリトライ回数。
        public int MaxConsecutiveSystemExceptions { get; set; } = 0; // 許容される連続システム例外数。0で無効化。
        public string ExScreenshotsFolderPath { get; set; } = "Exceptions_Screenshots"; // 例外時のスクリーンショット保存先パス。
        public string LogMessage_GetTransactionData { get; set; } = "Processing Transaction Number: "; // トランザクション取得時のログメッセージ(通常)。
        public string LogMessage_GetTransactionDataError { get; set; } = "Error getting transaction data for Transaction Number: "; // トランザクション取得時のログメッセージ(エラー)。
        public string LogMessage_Success { get; set; } = "Transaction Successful."; // トランザクション成功時のログメッセージ。
        public string LogMessage_BusinessRuleException { get; set; } = "Business rule exception."; // ビジネスルール例外時のログメッセージ。
        public string LogMessage_ApplicationException { get; set; } = "System exception."; // システム例外時のログメッセージ。
        public string ExceptionMessage_ConsecutiveErrors { get; set; } = "The maximum number of consecutive system exceptions was reached. "; // 連続システム例外数上限到達時のエラーメッセージ。
        public int RetryNumberGetTransactionItem { get; set; } = 2; // Get Transaction Itemアクティビティのリトライ回数(1以上の整数)。
        public int RetryNumberSetTransactionStatus { get; set; } = 2; // Set Transaction Statusアクティビティのリトライ回数(1以上の整数)。
        public bool ShouldMarkJobAsFaulted { get; set; } = false; // TRUEの場合、初期化エラーや連続システム例外上限時にジョブをFaultedにする。
        public string logF_BusinessProcessName { get; set; } = "Framework"; // 2つ以上のサブプロセスのログデータを同じビジネスプロセス名でグルーピングするためのログ用フィールド

        /// <summary>
        /// Config
        /// </summary>
        /// <param name="environmentNo">環境番号(0: Prd[本番環境], 1: Test[テスト環境], 2: Dev[開発環境])</param>
        public Config(int environmentNo) // コンストラクタの定義
        {
            // environmentNoが0,1,2以外の場合は例外をスローする
            if (environmentNo != 0 && environmentNo != 1 && environmentNo != 2)
            {
                throw new ArgumentOutOfRangeException(nameof(environmentNo), "environmentNoは0: Prd[本番環境], 1: Test[テスト環境], 2: Dev[開発環境])のいずれかで指定してください。");
            }
            switch (environmentNo)   // 環境番号によってNASサーバーのパスを分岐させる
            {
                case 0: // 本番環境用の設定
                    NasServerPath = @"\\nas-server\folder"; // 本番環境のパス
                    break;
                case 1: // テスト環境用の設定
                    NasServerPath = @"\\nas-server\folder-dev"; // 開発環境のパス
                    break; 
                case 2: // 開発環境用の設定
                    NasServerPath = @"\\nas-server\folder-test"; // テスト環境のパス
                    break; 
            } 
            
            // NasServerPathが設定された後にExcelPathを自動計算
            ExcelPath = $"{NasServerPath}\\Main.xlsx"; // 文字列補間でパスを結合
        } 
    } 
} 

利用方法

作成したクラスは、ワークフロー内で変数として利用可能です。

  1. 変数の作成
    UiPath Studio上で変数を追加する際、型の選択画面から Namespace > Config をクリックし、クラス型を指定します。
    image.png
    image.png

  2. インスタンスの生成
    代入アクティビティを使用し、次のように記述するだけで Config を生成できます:

    Config = New CTest.Config(EnvironmentNo)
    

さらにクラスにプロパティや引数の説明などを下記のようにつけることで、可読性を向上することができます。

     /// <summary>
     /// Config
     /// </summary>
     /// <param name="environmentNo">環境番号(0: Prd[本番環境], 1: Test[テスト環境], 2: Dev[開発環境])</param>

image.png

image.png

  1. 設定値の利用
    これで Config.MaxRetryNumber など、プロパティ形式で型補完付きの設定値アクセスが可能になります。
    image.png
    image.png

メリット

  • UiPath上で完結した編集が可能:ソースコードをUiPath Studio上で直接表示・編集できるため、別途IDEを開く必要がなく、簡易的な操作で完結します。
    • IDE上で型補完が効くConfig.MaxRetryNumber のように記述するだけで済み、コーディング効率が向上
  • 値の検証や初期値の設定が容易:あらかじめ型付きプロパティとして定義しておくことで、誤入力を防げる
  • Excelの読み込みエラーと無縁になるConfig.xlsx の構造に依存せず、ワークフローが安定する
  • 環境ごとの切り替え(Prd, Test, Dev)も簡潔に記述できる:設定の切り替えをコード内で制御可能
  • 構成をコード上で完結できるのでGit管理も容易:構成変更の差分が明確になり、レビューもしやすい
  • Object型からの解放CInt(Config("MaxRetryNumber")) のようなキャスト不要で、Config.MaxRetryNumber と書くだけで整数として扱える
    Before
    Before
    After
    After

デメリット

  • Configの内容を変更するにはコードを開く必要がある:非エンジニアの利用には向かず、設定変更のたびに開発者の手を借りる必要がある
  • 初学者にとっては直感的でない:Excelに比べて、どこに何が定義されているか把握しにくい
  • REFrameworkの標準ではない方法である:公式テンプレートに含まれておらず、導入には独自判断が求められる

とくに複数人で開発を行う場合や、保守・運用フェーズに入った後には、「誰がどこを変えるべきか」が明確でないとトラブルのもとになります。

注意点

本番業務でいきなり採用するのは慎重になるべきですが、学習用途やPoCでの検証などには非常に相性が良いと感じています。

最後に、Excelファイル、JSONファイル、C#クラスを使った設定管理の比較表を作ってみました。

項目 Excelファイル JSONファイル C#クラス
編集のしやすさ ◎ 非エンジニアでも扱いやすい ◯ テキストエディタで編集可能 △ コードを書く必要あり
UiPath Studioの対応バージョン ◎ すべてのバージョンで対応 ◎ すべてのバージョンで対応 △ v23.10.0以降でのみ対応(Sourcefile機能)
型安全性 × すべてObject型 × すべてObject型 ◎ プロパティ型が明示されている
実行時エラーの起きにくさ △ 開きっぱなしや数式エラーに注意 ◯ パース時のエラーに注意 ◎ コード側で制御可能
処理速度 △ 読み込みがやや遅い ◯ 軽量で高速 ◎ コードなので高速
バージョン管理との相性 ◯ Git管理可能だが比較が難しい ◎ テキスト形式なので差分が見やすい ◎ ソースコードとして管理可能
学習コスト ◎ 低い ◯ JSON/YAMLに慣れていれば簡単 △ C#の理解が必要

それぞれに良し悪しがあるので、プロジェクトの規模やメンバー構成、保守体制などを踏まえて選択するのがよいと思います。

AI時代に見直されるソースコードの価値 〜ローコードから再びハードコードへ〜

クラスやC#といった機能は従来から存在していましたが、ローコード時代の到来により、その使用頻度は一時的に下がりました。
しかし、CursorのようなAIエディタの登場によって、むしろコードを書くハードルは下がりつつあります。
さらに、コードはAIにとって理解しやすい形式であることから、クラスやC#を選択肢として再評価する価値があると考えます。

最後に、みなさんのおすすめの設定ファイルの定義方法もぜひ教えてください。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?