【未経験・初心者向け】標準機能で限界を感じたら?フロー×カスタムメタデータ型で柔軟な入力規則を作ってみた!

今回は「フロー×カスタムメタデータ型」で作成する入力規則をご紹介します。

はじめに

みなさん、こんにちは!新卒3年目のTです。
Salesforceのデータ品質を保つために欠かせないものといえば、「入力規則」。基本的には標準機能で設定することが多いですが、要件が複雑になると「標準機能だけでは実現できない…!」と壁にぶつかることはありませんか?

本記事では、IT未経験で入社した私が実際にぶつかったこの壁を、「レコードトリガーフロー」と「カスタムメタデータ型」を組み合わせて解決した事例をご紹介します!
標準機能の限界に悩む未経験・初心者の方の参考になれば嬉しいです。

立ちはだかった「標準機能」の限界と、代替案「入力規則」の落とし穴

今回は、読者の皆様がイメージしやすいように「商談オブジェクトにおける製品と契約の組み合わせチェック」という架空のシナリオを例に私が実際にぶつかった壁について解説します。

第1の壁 仕様変更で使えなくなった「項目の連動関係」

まず前提として、Salesforceの標準機能である「項目の連動関係」とは、片方の項目の値(制御項目)に基づいて、もう一方の選択リスト(連動項目)で選べる選択肢を動的に絞り込むことができる便利な機能です。
もともと、この機能を活用して以下のような連動関係を組んでいました。
制御項目:「製品カテゴリ」(例:ハードウェア、クラウド)
連動項目①:「対象製品」(例:カテゴリがハードウェアなら「PC」「サーバー」のみ表示)
連動項目②:「契約形態」(例:カテゴリがクラウドなら「月額」「年額」のみ表示)
これにより、ユーザーの入力ミスを防ぎスムーズな操作を実現していたのですが、ここでシステム改修が入ります。

「『製品カテゴリ』は別のルールをもとにフローで自動セットさせたい。かつ、ユーザーには勝手にいじらせたくない」という要件が追加されたのです。

これを実現するため、大元の「製品カテゴリ」のデータ型は『選択リスト』のまま、画面上でのアクセス権を「参照のみ」に変更し、編集をロックしました。
しかし、ここで大きな壁にぶつかります。

Salesforceの仕様上、制御項目を「参照のみ」にしてユーザーが触れないようにしてしまうと、連動項目もグレーアウトして選べなくなってしまうのです。

第2の壁 二重管理と制限を防ぐ、将来の「メンテナンス性の壁」

標準の連動関係が使えないとなれば、別の方法で入力チェックを行わなければなりません。
そこで代替案として考えたのが、「カスタム表示ラベル×入力規則のCONTAINS関数」というアプローチでした。

具体的には、以下のように設定します。
① カスタム表示ラベルに「許可する値」をカンマ区切りで登録する
表示ラベル名:Allowed_Hardware_Products
値:ノートPC,デスクトップPC,サーバー
表示ラベル名:Allowed_Cloud_Products
値:CRM,グループウェア,Web会議システム
② 入力規則の数式で、選択された値がラベル内に含まれているか判定する
▼参考数式
AND(
/* 対象製品が入力されている場合のみチェック */
NOT(ISBLANK(TEXT(TargetProduct__c))),
OR(
/* カテゴリが「ハードウェア」なのに、ラベル内の値と一致しない場合はエラー */
AND(
  ISPICKVAL( ProductCategory__c , "ハードウェア"),
  NOT(CONTAINS($Label.Allowed_Hardware_Products, TEXT(TargetProduct__c)))
),
/* カテゴリが「クラウド」なのに、ラベル内の値と一致しない場合はエラー */
AND(
  ISPICKVAL( ProductCategory__c , "クラウド"),
  NOT(CONTAINS($Label.Allowed_Cloud_Products, TEXT(TargetProduct__c)))
)
)
)
しかし、今回の要件でこの方法を使おうとすると、将来の「メンテナンス性の壁」が立ちはだかりました。理由は大きく2つありました。

懸念①:文字数制限・拡張性の低さと、誤判定のリスク
今後、新しい製品が追加されるたびにカンマ区切りの文字列を継ぎ足していく必要がありますが、カスタム表示ラベルには文字数制限(最大1,000文字)があり、すぐに限界を迎えます。
さらに、「製品カテゴリ」自体が新しく増えた場合(例:「ソフトウェア」カテゴリの新設)、新しいカスタム表示ラベルを作成したうえで、入力規則の数式自体も改修しなければなりません。
また、CONTAINS関数は「指定した文字列の中に、検索したい文字が含まれているか」を判定するため、似たような製品名が含まれた場合に誤判定を起こすリスクも潜んでいます。例えば、表示ラベル側に「タブレットPC」とだけ登録されている場合、ユーザーが「PC」と入力すると、システムは『「タブレットPC」の中に「PC」が含まれている』と判断し、本来エラーにしたいのにチェックをすり抜けてしまうリスクがあります。

懸念②:画面フローでの使い回しが困難
今回は裏側の入力規則(エラーチェック)だけでなく、ユーザーが入力する「画面フロー」でも、この条件をもとに選択肢を動的に出し分ける必要がありました。カンマ区切りの文字列を、画面フローの選択肢として1つずつ綺麗にバラして表示させるのは至難の業です。

「チェック用と画面用で別々に設定を持つと、二重管理になって将来のメンテナンスが地獄になる……」と頭を抱えました。

壁を壊した突破口:「カスタムメタデータ型」

この2つの壁を根本から解決するためにたどり着いたのが、「複数の条件を『レコード』として一元管理できる、カスタムメタデータ型の活用」でした。

💡 そもそも「カスタムメタデータ型」って?
初心者の方に向けて少し補足します。簡単に言うと「設定値やマスタデータを保存しておける、特別なカスタムオブジェクト」のようなものです。通常のレコードとは違い、Sandboxで作成したレコード(データ)をそのまま変更セットなどで本番環境にリリースできるのが最大の特徴です。

この選択により、2つの強力なメリットが生まれました!
比較ポイント 代替案(カスタム表示ラベル) 解決策(カスタムメタデータ型)
画面フロー(UI)との連動 文字列の分割が困難 選択肢としてそのまま利用可能
拡張性・メンテナンス性 数式の改修や文字数制限あり レコードの追加・修正のみで完結
判定の正確性 CONTAINSによる誤判定リスクあり 完全一致でのマスタ照合が可能
効果1:画面フロー(UI)と入力規則(裏側のチェック)のマスタ完全共通化
今回の要件では、ユーザーが入力する「画面フロー」と、裏側でデータ保存時にチェックする「レコードトリガーフロー(入力規則代わり)」の2つが動いています。

カスタムメタデータ型を使えば、値が「1レコード」として独立しているため、画面フローの選択肢としてそのまま美しく出し分けられます。さらに、保存時のチェック用トリガーフローでも全く同じマスタを参照できるため、設定の二重管理がゼロになりました!

効果2:運用フェーズでの「究極のメンテナンス性」
文字列判定ではないため誤判定リスクがありません。今後「新しい製品」や「新しい契約形態」が増えても、カスタムメタデータ型にレコードを1行追加・修正するだけで、すべてのフロー(画面・チェック共)が自動で対応してくれます。フロー側の修正は一切不要です!

実装時の落とし穴!作成時に困った・気を付けるべき3つのポイント

では実際にフローを組んでみて、引っかかったポイントや工夫した点について触れていきます!

ポイント1:カスタムメタデータ型の「レコード取得」におけるOR条件の罠!

フロー構築において最初につまずいたのが、カスタムメタデータ型の取得条件です。
「レコードを取得」要素で ((1 OR 2) AND (3 OR 4)) のような条件を組んで保存を試みたところ……

「論理和はサポートされていません」というエラーが発生してしまいました。
Salesforceの仕様上、カスタムメタデータ型に対するクエリ(SOQL)では、「同じ項目」に対するOR条件(例: Type__c = 'A' OR Type__c = 'B')はサポートされていますが、「異なる項目」をまたぐOR条件(例:IsCommon__c = true OR Department__c = X)はサポートされておらず、エラーとなってしまいます。

【解決策】
「レコードを取得」要素ではOR条件を使わずに広めにレコードを取得しておき、その後フロー内の「コレクション検索条件」要素を用いて、絞り込み(OR条件)を行うことで無事に要件を実現できました。

ポイント2:忘れがちな「Null(空白)」処理

今回の要件では「値が入力されている場合のみチェックする(未入力は許容する)」という仕様でした。そのため、「対象項目が未入力(Null)なら、エラーチェックには引っかからずそのまま保存されるだろう」と想定してフローを組んでいました。

しかし実際にテストしてみると、Nullのまま保存しようとした際に自作したフローのカスタムエラーに引っかかってしまい、保存できなくなってしまったのです。

原因は、フローが「未入力(Null)」という状態のまま、カスタムメタデータへ照合しに行ってしまったことでした。当然マスタ側にNullというレコードは存在しないため、「許可されていない値が入力された」と判定され、エラーを出すルートに進んでしまっていたのです。

【解決策】
判定ロジックに進む前に、決定要素などで「対象の値がNullではないか(空白チェック)」の確認処理を必ず挟むように修正しました。基本的な実装作法ですが、運用時の予期せぬエラーを防ぐ上で非常に重要です。

ポイント3:複数カスタムエラー設定時の保存エラーと表示場所

最後の注意点は、フロー全体を「保存」する際に発生しました。

フローの「カスタムエラー」要素は、1つの要素内で複数のエラーメッセージを設定できて便利ですが、表示場所を「レコードページのウィンドウ全体」に指定している場合、2つ以上のエラーを設定するとフローの保存時にエラーとなってしまいます。

【解決策】
複数のエラーメッセージを設定する場合は、表示場所を対象となる「特定の項目」に設定する必要があります。これによりフローが正常に保存できるだけでなく、ユーザーにとっても「どの項目を修正すべきか」が直感的に分かりやすいUIとなります。

まとめ

入力規則は標準機能で設定するケースが大半であり、今回のようにフローで複雑な入力チェックを構築する機会はそれほど多くないかもしれません。

しかし、「項目の連動関係の制限に抵触した」「条件が複雑で将来のメンテナンス性に懸念がある」「画面フローでも同じ条件を使い回したい」といった場面では、今回ご紹介した「フロー × カスタムメタデータ型」の組み合わせが非常に強力な解決策になります!

▼余談:こんな応用もできます!
今回は選択リスト値のマスタとして使いましたが、実際の案件では「画像マスタ」として使うこともあります。カスタムメタデータ型に画像URL(または静的リソース名)を持たせておき、数式項目のIMAGE()関数から呼び出したり、画面フローで動的に画像を出し分けたりと、知っておくと非常に便利な機能です!(※静的リソースを利用する場合は、アクセス権限にご注意を)

標準機能の限界に直面した際のアプローチとして、本記事の内容が、同じような悩みにぶつかった皆様の参考になれば幸いです。