読者です 読者をやめる 読者になる 読者になる

crmprogrammer38の日記

プログラマのメモ

【Salesforce】apexのstatic変数と、javaのstatic変数の違いでとまどったこと

私はjavaのプログラムを書くことが多いのですが、javaのstatic変数とapexのstatic変数の違いにとまどいました。

 

javaのstatic変数は、Classで保持する変数で、例えばWebアプリケーションであれば、そのWebアプリケーションの中で1つの値を保持できて、複数のユーザで1つの値を共有できます。

※厳密にはClassloader別ですが、いったんおいておきます。

 

ですが、apexのstatic変数は、トランザクションを開始してから終了するまでが変数のスコープで、トランザクション単位に管理されるため、ユーザ毎の値になります。

 

以下、原文

A static variable is static only within the scope of the Apex transaction. It’s not static across the server or the entire organization. The value of a static variable persists within the context of a single transaction and is reset across transaction boundaries. For example, if an Apex DML request causes a trigger to fire multiple times, the static variables persist across these trigger invocations.

 

 

【Salesforce】メモ & 添付ファイルの非公開のチェックボックスは本人に限定する場合に便利

メモ & 添付ファイルには、非公開のチェックがあります。

f:id:crmprogrammer38:20170414123249p:plain

この非公開にチェックを入れた後には、プロファイル>システム管理者権限の

・すべてのデータの参照

・すべてのデータの編集

の権限を持つ人は参照できますが、それを除くと、本人以外は見えなくなります。

共有ルールや階層を使用したアクセス制御とは無関係にこの制御がかかります。

 

本人というのは、所有者に指定した人になるので、システム管理者や、Apexプログラムなどからその人にだけ見せたいメモや、添付ファイルを作成することができます。

 

確実にその人だけが参照できる情報を登録する際には便利です。

 

下が、メモ & 添付ファイルをApexやAPIで使用する際の項目になります。

 

メモ

API名:Note

API ラベル タイプ
ParentId 参照先 ID reference
Title タイトル string
IsPrivate 非公開 boolean
Body 内容 textarea
OwnerId 所有者 ID reference

 

添付ファイル

API名:Attachment

API ラベル タイプ
ParentId 参照先 ID reference
Name ファイル名 string
IsPrivate 非公開 boolean
ContentType コンテンツタイプ string
Body 本文 base64
OwnerId 所有者 ID reference
Description 説明 textarea

【Salesforce】ページレイアウトの関連リストのレコードに条件をつける。

Salesforceの標準のページレイアウトの関連リストは、参照可能なレコード全て表示されますが、条件に該当するレコードだけ表示したい時があります。

 

例えば、その顧客の仕掛中の商談だけ表示する、または、現在対応中のケースだけ表示するなどの場合だったり、レコードは論理削除する設計としたが、関連リストには論理削除したレコードは表示したくないなどがあると思います。

 

現時点(APIバージョン39)では、ページレイアウトの関連リストに、条件を設定することはできないので次のように工夫することで対応できます。

 

関連リストに条件をつける方法

[手順概要]

参照関係、(もしくは主従関係)の項目に対応する参照関係項目をもう1つ用意します。

そして、表示する条件に合致した時に、トリガで用意した項目へ元の参照関係、および主従関係の項目の値をセットし、条件に合致しない時はnullをセットする処理を行います。

関連リストには用意した参照関係項目を使って表示します。

 

[手順詳細]

 例として、取引先と商談を使います。Salesforceの標準項目として、商談には、「取引先ID」があり、取引先への参照関係項目があります。

 

手順1.商談に、取引先への参照関係項目を作成します。仮に「取引先 ID(完了したものは除く)」項目とします。

 

手順2.商談にApexトリガを作成し、新規作成、更新時に、フェーズが"Closed Won" , "Closed Lost"以外のときに、「取引先ID」の値を、「取引先 ID(完了したものは除く)」にセットし、"Closed Won" , "Closed Lost"の時は、「取引先 ID(完了したものは除く)」にnullをセットします。

 

手順3.取引先のページレイアウトの関連リストに、取引先 ID(完了したものは除く)」の関連リストを表示します。(関連リストの表示ラベルを「商談 (完了したものは除く)」にします)

 

そうすると、次のように完了したもの以外で関連リストを表示できます。

(商談の関連リストは完了を含んでいて、商談(完了したものは除く)の関連リストは完了は除いています)

f:id:crmprogrammer38:20170405145126p:plain

【Salesforce】PDFで日本語で折り返しを行う

SalesforceのPDF出力で日本語を表示すると折り返しがされなくて、レイアウトが崩れてしまう現象があります。

 

結論としては、日本語の文字と文字の間にhtmlタグの<wbr/>を入れることで対処できます。

 

次がhtmlタグの<wbr/>を入れる前と入れた後での表示の違いになります。

入れる前と入れた後でhtmlタグは同じです。

f:id:crmprogrammer38:20170331151920p:plain

上記の通り、wbrタグを入れる前は、日本語の部分がレイアウトが崩れているのがわかります。ですが、wbrタグを入れた後は、折り返しされてレイアウトも崩れていません。

 

以下wbrを入れるソースコードです。

 文字と文字の間にwbrを入れると共に、次の文字「"<" ">" "&" "半角スペース"」のエスケープや改行コードからbrタグへの変換を行っています。

また、wbrが不要な半角文字にはwbrを入れていないため、元々の折り返しにまかせています。(英単語の間で改行はされないようにしています)

 

[ソースコード]

 //wbrタグをいれつつ、エスケープする文字を対応する。
//エスケープは < > & 半角スペースとする。
public String insWBR(String value){
if( String.isempty(value) ){
return '';
}

String retstr = '';
for(integer i=0; i< value.length() ; i++ ){
if( i > 0 ){
if( value.substring(i-1, i).isAsciiPrintable() ){
if( ' ' == value.substring(i-1, i) || ' ' == value.substring(i-1, i)){
retstr += '<wbr/>';
}
} else {
retstr += '<wbr/>';
}
}

String charval = value.substring(i, i+1);
if( charval == '\n' ){
retstr += '<br/>';
} else if( charval == '&' ){
retstr += '&amp;';
} else if( charval == ' ' ){
retstr += '&nbsp;';
} else if( charval == '>' ){
retstr += '&gt;';
} else if( charval == '<' ){
retstr += '&lt;';
} else {
retstr += charval ;
}
}

return retstr;
}

もちろん、htmlタグを含んだ文字列を表示するので、escape="false"の指定が必要です。( <apex:outputtext value="{!wbrvalue}" escape="false"/> )

【Salesforce】編集ページで初期値をセットする際の項目IDの一覧を取得する。

エンティティ定義(EntityDefinition)の子オブジェクトに、項目定義(FieldDefinition )があって、項目定義(FieldDefinition )をselectすると、編集画面で初期値をセットする時に使う項目IDが取得できます。

 

Select
EntityDefinitionId
,DurableId
,QualifiedApiName
,Label
,Length
,DataType
From
FieldDefinition
where EntityDefinition.QualifiedApiName='Opportunity'

 取得するとこんな結果がとれます。

f:id:crmprogrammer38:20170330175419p:plain

取得結果の"DurableId"のピリオド以降が項目IDです。これで新規ボタンクリック後の編集画面や、編集ボタンクリック後の編集画面で、初期値をセットする時に、動的に項目IDを取ることができます。(参照関係、主従関係の項目IDの頭にCFをついていないので、自分でつける必要があります)

 

※そもそもサポートされているやり方ではないのがつらいですが、環境依存の項目IDが散乱するとリリース時に大変なことになるよりはましといったところだと思います。

 

注意点としては、

APIバージョンは33以上で使えます。

・項目レベルセキュリティが設定されてないとselect結果に含まれません。

・必ずオブジェクトの検索条件が必要です。(一度に複数オブジェクトの検索が可能です)

項目定義(FieldDefinition )には他にも便利な項目がたくさんありますが、一部オブジェクトで、ServiceDataTypeId , ValueTypeId をselectすると内部エラーが発生します。うっかり全項目selectするとはまります。
(今のところContactとOpportunityでエラーとなりました)

 

【Salesforce】オブジェクトのキープレフィックス(KeyPrefix:IDの頭3桁)の一覧を取得する方法

Salesforceの開発をしているとオブジェクトを特定する3文字のKeyPrefixが必要な時があります。自分のよく使う方法を書こうと思います。

 

1.オブジェクト情報の格納しているオブジェクトをselectする。

オブジェクト情報は、エンティティ定義(EntityDefinition)に格納されています。

一覧で取得するのにSOQLを実行するのみなので、一番シンプルな方法です。

例えば、次のSOQLで、オブジェクトのAPI名、表示ラベル、KeyPrefixが取得できます。

 Select
QualifiedApiName
,Label
,KeyPrefix
From
EntityDefinition

この方法だと、DataLoaderなどでも取得できます。エンティティ定義(EntityDefinition)には、その他にも項目があるので使いやすいと思います。

 

使用する際には次を注意しておく必要があります。

・エンティティ定義(EntityDefinition)はAPIバージョンは33以上で使えます。

・SOQLの発行をするので、Apex内でSOQLの発行件数にカウントされます。

・キープレフィックスは一意ではない。キープレフィックスが指定されていないオブジェクトの他に、項目変更履歴の履歴オブジェクトなど同一のキープレフィックスのものがあります。

・プロファイル(および権限セット)で参照以上の権限がついてないとSOQLの結果に含まれない。

 

2.ApexのdescribeGlobalを使う

ApexやAPIで用意されているdescribeGlobalを使います。コードを書かないといけないですが、SOQLは発行しないのが良い点だと思います。

Map<String, Schema.SObjectType> ret = Schema.getGlobalDescribe();

for(String key : ret.keySet() ){

Schema.DescribeSObjectResult[] descResult = Schema.describeSObjects(new String[]{key});
System.debug(key);
System.debug(descResult[0].getKeyPrefix());
System.debug(descResult[0].getLabel());
}

注意事項はSOQL発行の時と一部かぶります。

・キープレフィックスは一意ではない。キープレフィックスが指定されていないオブジェクトの他に、項目変更履歴の履歴オブジェクトなど同一のキープレフィックスのものがあります。

・プロファイル(および権限セット)で参照以上の権限がついてないとSOQLの結果に含まれない。

 

 

 

【Excel】セルの値を数式で比較する時に、=(比較) と exact関数の違いではまったこと

私はプログラマーなので、プログラムの処理結果を期待値と比較する作業をかなりの頻度で行います。

 

そういう作業ではExcelのセルとセルの値を比較するのですが、

=( セル1 = セル2 )  での比較と、 = exact( セル1 , セル2 ) の比較で挙動が違いはまりました。

f:id:crmprogrammer38:20170309173532p:plain

 

#3では、=( セル1 = セル2 )  で比較すると数値の0と文字列"0"は異なっています。

#5にいたっては、数値の0 と 空白(いわゆるnull)が=( セル1 = セル2 )  で比較すると同じになってしまいます。

#6だと、=( セル1 = セル2 )  で比較だと大文字の小文字を区別しません。

 

めんどくさくても、exact関数を使っていこうと思いました。