tamuです。

商品情報のような、環境に依存しないマスタデータを入れていきたいと思います。 このとき画面から一つ一つ設定するのは面倒です。 といってデータインポートウィザードやデータローダで複数のオブジェクトを投入するのもスクラッチ組織を作るたびに行うのは面倒なので、データファイルやスクリプトでやってみます。


CSVで投入

データローダのようにCSVで投入する方法です。

Name,ProductCode,IsActive
Sales Cloud導入,IMPL_SALESCLOUD,TRUE
Service Cloud導入,IMPL_SERVICECLOUD,TRUE

このCSVファイルを data/product2.csv に配置します。

以下のコマンドを実行するとデータが投入されます。

1
2
3
$ sfdx force:data:bulk:upsert -s Product2 -f data/product2.csv -i Name -u mywork
sfdx force:data:bulk:status -i 7505h000002bPwhAAE -b 7515h000003OVu6AAG
Bulk Upsert... done

オプション

  • -s: UPSERT対象のSObject
  • -f: CSVファイル
  • -i: UPSERTに使用するキー項目
  • -u: targetの組織

実行が完了するとこのようにデータが作成されます。

商品オブジェクトに商品が登録された図


この方式だとオブジェクトとかCSVファイルなどを指定するのが面倒なので、こんな感じのスクリプトを用意すると良いんだろうなと思います。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#/bin/bash

if [ $# -eq 0 ]
then
  echo '組織を指定してください'
  echo 'load_product2.sh target'
  exit 1
fi

sfdx force:data:bulk:upsert -s Product2 -f data/product2.csv -i Name -u $target

JSONで投入

取引先と取引先責任者のように関連があるデータを一気に投入できる方法です。 もちろん関連がないデータも投入できます。

主な使い方としては、ある環境からある環境へデータをコピーです。 データを自分で作ることで投入することもできますが、JSON形式で準備するのがちょっと面倒です。

この例ではある環境からデータをエクスポートして、ある環境にインポートする方法をやってみようと思います。

参考: https://github.com/trailheadapps/easy-spaces-lwc

データのエクスポート

このような取引先と取引先責任者があるときに、

取引先と取引先責任者

以下のコマンドでデータをエクスポートします。

1
2
3
4
$ sfdx force:data:tree:export -q "SELECT Id, Name, (SELECT Id, FirstName, LastName FROM Contacts) FROM Account" -d data --plan -u mywork
Wrote 2 records to data/Accounts.json
Wrote 3 records to data/Contacts.json
Wrote 0 records to data/Account-Contact-plan.json

これだとIdNameしかエクスポートしていませんが、SOQLの部分を必要に応じて追加することで他の項目もエクスポートすることができます。

エクスポートしたデータはこんな感じです

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
$ cat data/Accounts.json
{
    "records": [
        {
            "attributes": {
                "type": "Account",
                "referenceId": "AccountRef1"
            },
            "Name": "取引先2"
        },
        {
            "attributes": {
                "type": "Account",
                "referenceId": "AccountRef2"
            },
            "Name": "取引先1"
        }
    ]
}

$ cat data/Contacts.json
{
    "records": [
        {
            "attributes": {
                "type": "Contact",
                "referenceId": "ContactRef1"
            },
            "LastName": "タム",
            "AccountId": "@AccountRef1"
        },
        {
            "attributes": {
                "type": "Contact",
                "referenceId": "ContactRef2"
            },
            "FirstName": "タム2",
            "LastName": "セールスフォース",
            "AccountId": "@AccountRef2"
        },
        {
            "attributes": {
                "type": "Contact",
                "referenceId": "ContactRef3"
            },
            "FirstName": "タム1",
            "LastName": "セールスフォース",
            "AccountId": "@AccountRef2"
        }
    ]
}

$ cat data/Account-Contact-plan.json
[
    {
        "sobject": "Account",
        "saveRefs": true,
        "resolveRefs": false,
        "files": [
            "Accounts.json"
        ]
    },
    {
        "sobject": "Contact",
        "saveRefs": false,
        "resolveRefs": true,
        "files": [
            "Contacts.json"
        ]
    }
]

データのインポート

以下のコマンドでデータをインポートします。

1
2
3
4
5
6
7
8
9
$ sfdx force:data:tree:import -p data/Account-Contact-plan.json -u mywork2
=== Import Results
Reference ID  Type     ID
────────────  ───────  ──────────────────
AccountRef1   Account  0011mXXXXXXXXXXXXX
AccountRef2   Account  0011mXXXXXXXXXXXXX
ContactRef1   Contact  0031mXXXXXXXXXXXXX
ContactRef2   Contact  0031mXXXXXXXXXXXXX
ContactRef3   Contact  0031mXXXXXXXXXXXXX

無事に移行できました(レポートからだとわかりにくいですが)。

インポート後

関連が3段階の場合

この方法は関連が3段階まで対応しているようです。

SOQLでは3階層目のデータをエクスポートすることはできないので、一度手直しする必要があるようです。

参考: https://salesforce.stackexchange.com/questions/240042/sfdx-forcedatatreeexport-beyond-1-level-deep

Apexで作成

JSONで作るのと同じように、関連のあるデータを一気に投入できます。 単体テストで作るような感じでデータを作ります。

データ投入用コード

scripts/apex/accounts-contacts.apex というファイル名でApexを作成します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Account account = new Account(Name = 'サンプル');
insert account;

Contact[] contacts = new List<Contact>();

for (Integer i = 0; i < 10; i++) {
    Contact c = new Contact(FirstName = '名' + i,
                            LastName = '姓' + i,
                            AccountId = account.ID);
    contacts.add(c);
}

insert contacts;

取引先を1レコード作って、それに紐づく取引先責任者を10レコード作るサンプルです。

Apexの実行

上記のApexを実行します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
sfdx force:apex:execute -f scripts/apex/acccounts-contacts.apex -u mywork
Compiled successfully.
Executed successfully.

52.0 APEX_CODE,DEBUG;APEX_PROFILING,INFO
Execute Anonymous: Account account = new Account(Name = 'サンプル');
Execute Anonymous: insert account;
Execute Anonymous:
Execute Anonymous: Contact[] contacts = new List<Contact>();
Execute Anonymous:
Execute Anonymous: for (Integer i = 0; i < 10; i++) {
Execute Anonymous:     Contact c = new Contact(FirstName = '名' + i,
Execute Anonymous:                             LastName = '姓' + i,
Execute Anonymous:                             AccountId = account.ID);
Execute Anonymous:     contacts.add(c);
Execute Anonymous: }
Execute Anonymous:
Execute Anonymous: insert contacts;
21:08:54.37 (37424677)|USER_INFO|[EXTERNAL]|0050l000004pu84|test-1xxxxxxxxxxx@example.com|(GMT+09:00) 日本標準時 (Asia/Tokyo)|GMT+09:00
21:08:54.37 (37450095)|EXECUTION_STARTED
21:08:54.37 (37459435)|CODE_UNIT_STARTED|[EXTERNAL]|execute_anonymous_apex
21:08:54.37 (151092942)|CODE_UNIT_STARTED|[EXTERNAL]|DuplicateDetector
21:08:54.37 (191153995)|CODE_UNIT_FINISHED|DuplicateDetector
21:08:54.37 (403234928)|CODE_UNIT_STARTED|[EXTERNAL]|DuplicateDetector
21:08:54.37 (447494751)|CODE_UNIT_FINISHED|DuplicateDetector
21:08:54.37 (726402561)|CODE_UNIT_STARTED|[EXTERNAL]|DuplicateDetector
21:08:54.37 (747985994)|CODE_UNIT_FINISHED|DuplicateDetector
21:08:54.37 (748074889)|CODE_UNIT_STARTED|[EXTERNAL]|DuplicateDetector
21:08:54.37 (761584020)|CODE_UNIT_FINISHED|DuplicateDetector
21:08:54.761 (761741290)|CUMULATIVE_LIMIT_USAGE
21:08:54.761 (761741290)|LIMIT_USAGE_FOR_NS|(default)|
  Number of SOQL queries: 0 out of 100
  Number of query rows: 0 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 2 out of 150
  Number of Publish Immediate DML: 0 out of 150
  Number of DML rows: 11 out of 10000
  Maximum CPU time: 0 out of 10000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 0 out of 100
  Number of Email Invocations: 0 out of 10
  Number of future calls: 0 out of 50
  Number of queueable jobs added to the queue: 0 out of 50
  Number of Mobile Apex push calls: 0 out of 10

21:08:54.761 (761741290)|CUMULATIVE_LIMIT_USAGE_END

21:08:54.37 (761782664)|CODE_UNIT_FINISHED|execute_anonymous_apex
21:08:54.37 (761792508)|EXECUTION_FINISHED

sfdx force:org:open -u mywork で実際に投入されたか確認してみます。

Apexで投入したデータ

ちゃんと取引先責任者が10レコード紐づく形でつくられていました。