色々なソースコードを記載してきましたが、自分の記載したソースコードをコピーして使おうとして気がつきました。
html編集で「 」にすると文字コードで「C2A0」という文字で表示されるんですね。。
わざわざ半角スペースを「 」に変換して貼り付けていたのが仇となりました。
今までのせてきたものは全部直そうと思います。
良い機会だから<code></code>ではさむようにしとこ。
150程度しか記事はないけど意外と大変です。。
CSVファイルは、大体Excelに関連付けがされていてダブルクリックするとExcelで開きます。
Excelで中身を確認できるのはとても便利ですが、次のようになってしまい使いづらいことがあります。
・CSVの文字は「0001」なのに、Excelでは「1」となる
・CSVの文字は「2000-01」なのに、Excelでは日付の「2000/1/1」となる
この現象は数式扱いにすると回避できます。
テキストが変換されてしまうCSVの中身
"0001","2000-01"
Excelで開いた場合の表示
ゼロサプレスされるのと、勝手に日付変換されてしまいます。
テキストを数式扱いにしたCSVの中身
="0001",="2000-01"
Excelで開いた場合の表示
セルは数式の値でcsvの文字列がそのまま表示されます。
ただし、数式扱いにしなければ正しく表示される値でも、数式扱いにすると表示がおかしくなる場合があります。
おかしくなるのは、文字列中にカンマ(,)や改行( )がはいる場合です。
通常のCSV
"000,000,000","AAAAA
BBBBB"
Excel表示
正しく表示されます
数式に変更
="000,000,000",="AAAAA
BBBBB"
Excel表示
表示が崩れてしまいます。
この現象を回避するため、テキスト内のカンマと改行も数式で表現しておく必要があります
="000" & char(44) & "000" & char(44) & "000",="AAAAA" & char(10) & "BBBBB"
※カンマはchar(44) で、改行はchar(10)で表現しています。
Excel表示
テキストを数式扱いしたCSVは連携用途で扱えません、Excelでの表示用途に限定したやり方になります。
業務ユーザにCSVを配布した際にゼロサプレスされては困る、勝手に日付変換されたら困る項目に限定して数式扱いにするのがいいのかなと思います。
レイアウトの一覧とレイアウト項目 を取得するExcelマクロを以前作成しました。
レイアウト項目は、詳細項目と関連リストを対象としていたのですが、ミニページレイアウトの項目の追加しました。
ダウンロードはこちら からになります。
次のようにレイアウト項目でミニページレイアウト項目とミニページレイアウトの関連リストを表示を追加しました。
[前回作成時の記事]
crmprogrammer38.hatenablog.com
ページレイアウトを設定する時に、ミニページレイアウトの設定はあまり深く考えないで項目を置いておくことが多いです。
そして、レコードタイプの追加にあわせてレイアウトを増やしていくと、見直し作業が意外と手間な時があります。
そんな時に使えるかなーと思います。
結論として、Lightningレコードページの割り当てをリリースするには、「オブジェクト」「Lightning アプリケーション」をリリースする必要があります。
メタデータでLightningレコードページの割り当てがどこに記載されているかを確認したところ、オブジェクトとLightning アプリケーション(メタデータのCustomApplication)に情報が記載されていました。
まず、Lightningレコードページの割り当ては次の内容です。
表示の優先度は下からなので、「アプリケーション、レコードタイプ、プロファイル」を指定していれば、組織のデフォルトより優先されて表示されます。
上記の内容はメタデータ上では次のようになっています。
<actionOverrides>
<actionName>View</actionName>
<comment>Action override created by Lightning App Builder during activation.</comment>
<content>LightningレコードページのAPI名</content>
<formFactor>Large</formFactor>
<skipRecordTypeSelect>false</skipRecordTypeSelect>
<type>Flexipage</type>
</actionOverrides>
<actionOverrides>
<actionName>View</actionName>
<comment>Action override created by Lightning App Builder during activation.</comment>
<content>LightningレコードページのAPI名</content>
<formFactor>Large</formFactor>
<skipRecordTypeSelect>false</skipRecordTypeSelect>
<type>Flexipage</type>
<pageOrSobjectType>オブジェクトのAPI名</pageOrSobjectType>
</actionOverrides>
<profileActionOverrides>
<actionName>View</actionName>
<content>LightningレコードページのAPI名</content>
<formFactor>Large</formFactor>
<pageOrSobjectType>オブジェクトのAPI名</pageOrSobjectType>
<recordType>オブジェクトのAPI名.レコードタイプのAPI名</recordType>
<type>Flexipage</type>
<profile>プロファイル名</profile>
</profileActionOverrides>
今までのプロファイル・レコードタイプ別のレイアウト割り当てで、ページの項目の表示を変更した後に、さらに、アプリケーション・レコードタイプ・プロファイルでLighningレコードページで表示の使い分けができて便利です。
が、リリース時の確認も本当に大変だなーと思いました。(アプリケーションをリリースしないとなると手動になってしまいますし)
SalesforceがSummer18(APIVer43)にバージョンアップしたので、次のツールのバージョンをあげました。
Excel VBA : オブジェクト一覧と項目一覧の取得マクロ
使い方は前回の内容から変更はありません。
crmprogrammer38.hatenablog.com
crmprogrammer38.hatenablog.com
Api43から、SOAP APIでオブジェクトの数式項目「空白項目の処理(formulaTreatNullNumberAsZero)」を項目の属性として取得できるようになったのでオブジェクト項目の一覧マクロで表示を追加しました。
他に、excelマクロには表示していませんがaiPredictionFieldという属性も追加されています。これからAI用の項目も追加されていくのか楽しみです。
また、Api43で次のオブジェクトなどが追加されています。
・アプリケーション定義[AppDefinition]
・タブ定義[TabDefinition]
・アプリケーションタブメンバー[AppTabMember]
標準のアプリケーションの物理名などがわかりやすくなったなーと思いました。
Javaコードを書いていて、for each 内で、Mapのremoveを行いjava.util.ConcurrentModificationExceptionエラーになるのをすっかり忘れてました。
エラーになるコード
HashMap<String, String> map = new HashMap<String, String>();
map.put("k1", "v1");
map.put("k2", "v2");
map.put("k3", "v3");
for(String k : map.keySet()){
if( k.endsWith("2")){
map.remove(k);
}
}
エラーにならないコード
HashMap<String, String> map = new HashMap<String, String>();
map.put("k1", "v1");
map.put("k2", "v2");
map.put("k3", "v3");
for(Iterator<String> i = map.keySet().iterator();i.hasNext();){
String k = i.next();
if( k.endsWith("2")){
i.remove();
}
}
Iteratorで要素を順に取得する場合は、要素の削除は Iterator.remove で行う必要がありました。(拡張for文はコンパイル時にIteraterのコードに展開されるようです)
すっかり拡張for文に慣れてしまいIteratorなんてほぼ目にしなくなっているのに、removeするときだけIteratorで回すのは面倒くさいなーと思いました。
removeではなく、新しいMapを作成する
処理に問題がなければ、removeした結果と同じMapを新規に作成しとけば問題ないですよね。
HashMap<String, String> map = new HashMap<String, String>();
map.put("k1", "v1");
map.put("k2", "v2");
map.put("k3", "v3");
HashMap<String, String> newmap = new HashMap<String, String>();
for(String k : map.keySet()){
if( k.endsWith("2") == false){
newmap.put(k, map.get(k));
}
}
map = newmap;
さらにStreamAPIで綺麗に書けるようになってます。
HashMap<String, String> map = new HashMap<String, String>();
map.put("k1", "v1");
map.put("k2", "v2");
map.put("k3", "v3");
map = map.entrySet().stream()
.filter(m-> m.getKey().endsWith("2")==false)
.collect(
Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1,HashMap::new)
);
でもラムダ式に慣れてなくて、いちいち調べないとまともに書けないですねー。ちゃんと把握しようかな。。と思いました。