Salesforce Advent Calendar 2022の8日目の記事です。
はじめに
この記事は@Aptenodytes9さんのSalesforceでカスタムメタデータ型を大量INSERTする方法
のオマージュです。
上記手順でハマったところ、改良したところを中心に書きます。
カスタムメタデータとは
カスタマイズ可能、リリース可能、パッケージ化可能、アップグレード可能なアプリケーションメタデータです。選択リストやリレーションが使えたり、レコードごとリリースできるのも良い。
詳しくこちら
Custom Metadata Loader
手法も同じく「Custom Metadata Loader」を使います。
Salesforce公式が提供しているのですが、
Salesforce CLIでカスタムメタデータが使えるようになったので、
もうメンテナンスは終了しています。
上記サイトにもCLIで利用できるようになったから、
サポートも終了したし、機能保証はしないよとあります。が、
運用担当者が非エンジニアでsfdxコマンドは厳しかったのでこの手法にしました。
インストール
インストールは元記事の通りでOKです(一応手順)
1.「Custom Meta Data Loader」のGithubにアクセス
2.「Deploy to Salesforce」ボタンをクリック
3.「Deploy to:」で環境を選択して「Login to Salesforce」をクリック(他の項目は変更不要です)
4.アクセスを許可
5.「Deploy」をクリック
「Deployment Complete」が表示されたら完了です。
インストール後の設定
途中までは元記事の通りでOKです(一応手順)
1.利用ユーザのプロファイルの「カスタムアプリケーション設定」で「Custom Metadata Loader」の「参照可能」にチェック
2.同じくプロファイルの「カスタムタブの設定」で「Custom Metadata Loader」を「デフォルトで表示」に変更
※ 「Custom Metadata Migrator」というカスタム設定、カスタムオブジェクトをカスタムメタデータに移行するツールもありますが今回は不要です。
4.「プレビュー」をクリック
5.URLのグレー部分を控える
https://d7f000005d9hsuas-dev-ed--c.vf.force.com
/apex/CustomMetadataRecordUploader
6.「リモートサイトの設定」で「新規リモートサイト」をクリックして以下設定して保存
項目 | 設定値 |
---|---|
リモートサイト名 | 任意 |
リモートサイトのURL | 手順5で控えたURL |
プロトコルセキュリティの無効化 | チェックなし |
説明 | 任意 |
有効 | チェックあり |
7.アプリケーションの「Custom Metadata Loader」をクリックして画面が表示されたら準備完了
CSVファイルの作成
以下フォーマットで作成
項目 | 設定値 |
---|---|
文字コード | UTF-8 |
改行コード | CRLF |
BOM | なし ※ExcelでCSV保存した場合はBOMがつくので注意 |
データ構成 | 1行目はヘッダー 2行目以降がデータ |
シングルクォーテーション ダブルクォーテーション |
なし |
ヘッダー | API参照名 |
必須の列 | 表示ラベル(Label) カスタムメタデータレコード名(DeveloperName) ※「表示ラベル」のAPI参照名は「MasterLabel」だがインポート時に設定するのは「Label」 ※Descriptionはなくても問題なし |
インポート
上記のようなカスタムメタデータ型に対して以下のようなCSVを用意します。
(インストール時にテスト用の「CountryMapping」というカスタムメタデータが生成されます)
1.「ファイルを選択」でCSVを選択し、
右上の選択リストから対象のカスタムメタデータ型を選択して「Create/Update custom metadata」をクリック
※正常終了すると登録済みのカスタムメタデータが表示されます(なぜか今回登録した分は表示されません)。
※カスタムメタデータレコード名(DeveloperName)が存在する場合は更新します。
ここから改良点になります。
改良1 空値を登録できるようにする
実は現状のままでは空値を登録することができません。
そこで以下のファイルを修正します。
split(regExp, limit)メソッドのlimitに負の数を設定することで空文字が破棄されなくなります。
- List<String> fields = line.split(',');
+ List<String> fields = line.split(',', -1);
改良2 カスタムメタデータを一括で削除できるようにする
現状のままだと1レコードずつ画面からしか削除できないので、
選択したカスタムメタデータ型のレコードをすべて削除するようにします。
+ public PageReference deleteCustomMetaData() {
+ ApexPages.getMessages().clear();
+ showRecordsTable = false;
+ deleteCustomMetadtaRecords();
+ // TODO: Add Success Message / Display Errors
+ return null;
+ }
+
+ private void deleteCustomMetadtaRecords() {
+ if(selectedType == 'Select type') {
+ ApexPages.Message errorMessage = new ApexPages.Message(ApexPages.severity.ERROR, 'Please choose a valid custom metadata type.');
+ ApexPages.addMessage(errorMessage);
+ return;
+ }
+
+ String query = 'SELECT DeveloperName FROM ' + selectedType;
+
+ List<sObject> customRecords = Database.query(query);
+ List<String> recordsToDelete = new List<String>();
+
+ for (sObject record : customRecords) {
+ recordsToDelete.add(selectedType + '.' + record.get('DeveloperName'));
+ }
+
+ MetadataUtil.deleteMetadata('CustomMetadata', recordsToDelete);
+ }
+ public static void deleteMetadata(String type_x,String[] fullNames) {
+ List<MetadataService.DeleteResult> results = getPort().deleteMetadata(type_x, fullNames);
+ if (results!=null) {
+ for (MetadataService.DeleteResult deleteResult : results) {
+ if (deleteResult==null || deleteResult.success) {
+ continue;
+ }
+ // Construct error message and throw an exception
+ if (deleteResult.errors!=null) {
+ List<String> messages = new List<String>();
+ messages.add((deleteResult.errors.size()==1 ? 'Error ' : 'Errors ') + 'occured processing component ' + deleteResult.fullName + '.');
+ for(MetadataService.Error error : deleteResult.errors){
+ messages.add(error.message + ' (' + error.statusCode + ').' + ( error.fields!=null && error.fields.size()>0 ? ' Fields ' + String.join(error.fields, ',') + '.' : '' ) );
+ }
+ if(messages.size()>0){
+ ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.Error, String.join(messages, ' ')));
+ System.debug(LoggingLevel.ERROR, String.join(messages, ''));
+ return;
+ }
+ }
+ if(!deleteResult.success){
+ ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.Error, 'Request failed with no specified error.'));
+ return;
+ }
+ }
+ }
+ }
+ <div align="center" draggable="false" >
+ <apex:ActionRegion >
+ <apex:commandButton value="Delete Custom MetaData Type" action="{!deleteCustomMetaData}" rendered="true"/>
+ <apex:actionSupport event="onclick" action="{!deleteCustomMetaData}" rendered="{!showRecordsTable}" oncomplete="window.opener.location.reload();"/>
+ </apex:ActionRegion>
+ </div>
+ <br/>
+ <br/>
これでカスタムメタデータ型を選択して「Delete Custom MetaData Type」をクリックするとレコードを全部消します。
まとめたものは以下