要件
Apex,Trigger,Flowが使われているオブジェクト項目を洗い出したい
参照
Workbenchで調査
https://qiita.com/richard_hcq/items/6b627e6383b6115675f4
詳細資料
https://blog.bessereau.eu/assets/pdfs/api_tooling.pdf
※ワークルールについて
案
VsCodeでSfdxコマンドからToolingApiのSoqlから関連情報のCsvを出力する
関連オブジェクト
MetadataComponentDependencyから依存項目をみれますが、なんのオブジェクトの項目かを調べるため、CustomObjectとCustomFiledの内容をダウロードし、突き合わせる必要がある
上記の例で、バッチがRmBusinessSectionListの法人番号をつかっていることがわかる。
実施ポイント
① MetadataComponentDependencyの実施Soql
sfdx force:data:soql:query -q
"select MetadataComponentId,MetadataComponentName,MetadataComponentType,
RefMetadataComponentId,RefMetadataComponentName,RefMetadataComponentType
from MetadataComponentDependency
where MetadataComponentType in ('ApexClass') and
RefMetadataComponentType in ('CustomField','CustomObject','ApexClass')
Order by MetadataComponentName" -r csv -t >ApexAndField.csv
※ -t --toolingapi このオプションはSfdxで使える。Dataloaderはまた使えないようです。
ちなみにDeveloperコンソールのQueryに使える(Optionにチェックする)
該当関係オブジェクトは一Queryで2000行の制御がある。
※ TriggerまたFlowの場合、 MetadataComponentType in ('ApexTrigger','Flow')
※ 別のオブジェクトで下記設定で、2000行以上が取れるが、
MetadataComponentDependencyができない
sfdx config:set maxQueryLimit=20000000
取引先の200万レコードがとりますが、遅くて1時間以上がかかってしまった。
(select id from account)
※ 漢字名がある場合、VsCodeのTerminalで文字ばけ、普通のCmdのPromptで実行する
Apexと使われている項目の一覧ができました。
② 上記①に項目は何のオブジェクトの項目は下記二つ情報が必要です。
カスタムオブジェクト一覧
select
Id,DeveloperName,NamespacePrefix
from CustomObject
where NamespacePrefix = null
Order by DeveloperName
※「NamespacePrefix = null」は別Packageのものを除外している
実行コマンド
sfdx force:data:soql:query -q "select Id,DeveloperName,NamespacePrefix from CustomObject where NamespacePrefix = null Order by DeveloperName" -r csv -t >CustomObject.csv
カスタム項目一覧
select
Id,DeveloperName,NamespacePrefix,TableEnumOrId
from CustomField
where NamespacePrefix = null
実行コマンド
sfdx force:data:soql:query -q "select Id,DeveloperName,NamespacePrefix,TableEnumOrId from CustomField where NamespacePrefix = null Order by TableEnumOrId" -r csv -t >CustomField.csv
※補足 Flow & ProcessBuilder
sfdx force:data:soql:query -q "select Id ,DefinitionId,Status,ProcessType,VersionNumber from Flow where Status in ('Active') Order by MasterLabel" -r csv -t >Flow.csv
※補足 ApexTrigger
sfdx force:data:soql:query -q "select Id,Name,NamespacePrefix from ApexTrigger Order by Name" -r csv -t >ApexTrigger.csv
※補足 WorkflowRule
sfdx force:data:soql:query -q "select Id,ManageableState,Name,TableEnumOrId from WorkflowRule" -r csv -t >workflowrule.csv
※補足 WorkflowFieldUpdate
sfdx force:data:soql:query -q "select Id,Name,EntityDefinitionId,FieldDefinitionId,LiteralValue,LookupValueId,SourceTableEnumOrId from WorkflowFieldUpdate" -r csv -t >WorkflowFieldUpdate.csv
関係マットリックス
上記三つ情報はExcelシートに張り付け、マクロで突き合わせで、Apexが横並べ、縦はオブジェクト、項目を並べ、使われているところに「O」をつけ、関係マットリックスが作成できる
VBA Macro
Sub fillApexName()
Set rfSht1 = Sheets("CustomObject")
Set rfSht2 = Sheets("CustomField")
Set srcSht = Sheets("ApexAndApexField")
Set objDic = CreateObject("Scripting.Dictionary")
Set fieldDic = CreateObject("Scripting.Dictionary")
Set MatrixDicX = CreateObject("Scripting.Dictionary")
Set MatrixDicY = CreateObject("Scripting.Dictionary")
'obj
ii = 3
While rfSht1.Cells(ii, 2).Value <> ""
objDic.Add rfSht1.Cells(ii, 2).Value, rfSht1.Cells(ii, 3).Value
ii = ii + 1
Wend
'field
ii = 3
While rfSht2.Cells(ii, 2).Value <> ""
vv = rfSht2.Cells(ii, 5).Value
If Left(vv, 1) = "0" Then
fieldDic.Add rfSht2.Cells(ii, 2).Value, objDic.Item(vv)
Else
fieldDic.Add rfSht2.Cells(ii, 2).Value, vv
End If
ii = ii + 1
Wend
'MatrixDicX
'MatrixDicY
ii = 3
xcol = 6
yrow = 4
While srcSht.Cells(ii, 2).Value <> ""
'x col
vv = srcSht.Cells(ii, 3).Value
If Not MatrixDicX.Exists(vv) Then
MatrixDicX.Add vv, xcol
xcol = xcol + 1
End If
'yrow
tp = srcSht.Cells(ii, 7).Value
fn = srcSht.Cells(ii, 6).Value
fid = srcSht.Cells(ii, 5).Value
If tp = "CustomField" Then
key1 = tp & "#" & fieldDic.Item(fid) & "#" & fn
Else
If tp = "ApexClass" Then
key1 = tp & "#" & fn & "#"
End If
End If
If Not MatrixDicY.Exists(key1) Then
MatrixDicY.Add key1, yrow
yrow = yrow + 1
End If
ii = ii + 1
Wend
'xy
Set ToSht = Sheets("MatrixApex")
ToSht.Range("A4:AAX20000").ClearContents
ToSht.Range("E3:AAX3").ClearContents
'ii = 4
For Each vKey In MatrixDicY
item2 = MatrixDicY.Item(vKey)
arr = Split(vKey, "#")
ToSht.Cells(item2, 2) = arr(0)
ToSht.Cells(item2, 3) = arr(1)
ToSht.Cells(item2, 4) = arr(2)
Next
'x-ray
For Each vKey In MatrixDicX
item2 = MatrixDicX.Item(vKey)
ToSht.Cells(3, item2) = vKey
Next
'mark the point
ii = 3
xcol = 6
yrow = 4
While srcSht.Cells(ii, 2).Value <> ""
'x col
apx = srcSht.Cells(ii, 3).Value
'yrow
tp = srcSht.Cells(ii, 7).Value
fn = srcSht.Cells(ii, 6).Value
fid = srcSht.Cells(ii, 5).Value
If tp = "CustomField" Then
key1 = tp & "#" & fieldDic.Item(fid) & "#" & fn
Else
If tp = "ApexClass" Then
key1 = tp & "#" & fn & "#"
End If
End If
ToSht.Cells(MatrixDicY.Item(key1), MatrixDicX.Item(apx)).Value = "O"
ii = ii + 1
Wend
MsgBox ("Apex and field mapping OK")
End Sub