Apex
暗号化シンプル例
private static final String cryptoKey = ‘1234567890123456’;
public static String encryptedData(String s) {
Blob encryptedData = Crypto.encryptWithManagedIV(‘AES128’, Blob.valueOf(cryptoKey), Blob.valueOf(s));
return EncodingUtil.base64Encode(encryptedData);
}
public static String decryptedData(String s) {
Blob decryptedData = Crypto.decryptWithManagedIV(‘AES128’, Blob.valueOf(cryptoKey), EncodingUtil.base64Decode(s));
return decryptedData.toString();
}
标准按钮的覆盖方法
如果想覆盖标准的button机能,只需要做一个VF,覆盖掉button调用就可以了
但是如果根据需要,例如: 客户A 需要看VF做的特殊画面
系统管理员看原来的标准画面
这种情况下,可以用下面的方法来解决
方法1:
<apex:page standardController="DistributorOrderItem__c" extensions="DistributorOrderEditForCSR" action="{!if($Profile.Name !='System Administrator', urlFor($Action.DistributorOrderItem__c.Edit, DistributorOrderItem__c.id, null, true), null)}">
利用urlFor跳转,可以防止死循环的调用
方法2:
vfPageRecordType=('/' + CallActivity_ID+ '?nooverride=1' + '&retURL=' + retURL );
注意:nooverride=1 意思是调用原来的标准画面,不要覆盖的意思
参考’
http://developer.force.com/cookbook/recipe/overriding-a-page-for-some-but-not-all-users
http://boards.developerforce.com/t5/Visualforce-Development/Visualforce-page-edit-button-override-and-page-redirect-not/td-p/88160/page/2
Salesforce小技巧和备注
-
WFの項目自動更新された項目に対して、項目入力規則はnot fire
- ProcessInstanceにて、[SELECT Id, (SELECT Id, StepStatus, Comments FROM Steps),TargetObjectId FROM ProcessInstance]で、該当データLockedされるどうか判断可能
- 数値VFに書式化:
<apex:outputText value="{0,number,#,###}"> <apex:param value="{!detailInfo.HokenKingaku__c/1000}" /> </apex:outputText>
- M-D関係構築
M-D1-DD1-DDD1 3階層まで構築可能です
M-D-Mの場合、DのオブジェクトはMになることができません - スケジュールクラス定義(秒まで定義する)
DateTime nowTime = DateTime.now().addSeconds(10); // 起動CRONを設定する String timeStr = nowTime.format('yyyyMMddHHmmss'); String yy = timeStr.substring(0,4); String mm = timeStr.substring(4,6); String dd = timeStr.substring(6,8); String hh = timeStr.substring(8,10); String ms = timeStr.substring(10,12); String ss = timeStr.substring(12,14); String sch = ss + ' ' + ms + ' ' + hh + ' ' + dd + ' ' + mm + ' ' + ' ? ' + yy; ApexClassXXX m = new ApexClassXXX(); String jobName = DateTime.now().format('yyyyMMddHHmmssSSS') + '|' + String.valueof(Crypto.getRandomLong()); String jobId = system.schedule(jobName, sch, m);
- 日付書式
《apex:outputText》 <apex:outputText value="{0,date,dd/MM/yyyy}"> <apex:param value="{!DATEVALUE(m_dtimSomeVar)}"/> </apex:outputText>
- 数値書式
《apex:outputText value="{0,number,#,###}"》 《apex:param value="{!detailInfo.HokenKingaku__c/1000}" /》 《/apex:outputText》
- 根据Salesforce Id 判断Sobject类型
参照文档:
Returns the three-character prefix code for the object. Record IDs are prefixed with three-character codes that specify the type of the object (for example, accounts have a prefix of 001 and opportunities have a prefix of 006).Schema.DescribeSObjectResult R = Account.SObjectType.getDescribe(); String a = R.getKeyPrefix(); String sid = 'a00d00000039F47'; String b = sid.substring(0,3); // the data is Account Type Data Type if (a == b) { System.debug('it is account data'); } else { }
- Visualforce to Excel
<apex:page standardController="Account" contenttype="application/vnd.ms-excel">
- ApexでFormat処理を行う
public static String paddingLeftZero(Decimal n, Integer len) { Integer nlen = (Math.floor(Math.log10(Double.valueOf(n))).intValue() + 1); if(nlen >= len) return n.format(); String s = ''; for(Integer i=0, l=len-nlen; i<l; i++) { s += '0'; } return s + n; }
Salesforce Link
下記URLから転載
http://blog.flect.co.jp/salesforce/2011/07/urlurl-9d6c.html
画面のURLとURLパラメータ
Salesforceは、URLとそのパラメータを指定するだけで、様々な画面を表示できます。
今回は代表的な画面のURLとそのパラメータをご紹介します。
○ベースURL
ベースとなるURLは、インスタンス毎に決まっており、↓のようになります。
https://<インスタンス名>.salesforce.com
以降のURLでは、ベースURLは省略して表記します。
例)/home/home.jsp ⇒ https://na7.salesforce.com/home/home.jsp
○代表的な画面のURL
画面 | URL |
---|---|
ホーム | /home/home.jsp |
すべてのタブ画面 | /home/showAllTabs.jsp |
高度な検索画面 | /search/AdvancedSearch |
設定画面 | /ui/setup/Setup |
システムログ画面 | /_ui/common/apex/debug/ApexCSIPage |
ヘルプ画面 | /help/doc/user_ed.jsp |
タブ画面 | /<オブジェクトPrefix>/o (URLFOR($Action.<オブジェクト名>.Tab) でURL作成可) |
新規画面 | /<オブジェクトPrefix>/e (URLFOR($Action.<オブジェクト名>.New) でURL作成可) |
詳細画面 | /<レコードID> (URLFOR($Action.<オブジェクト名>.View, <レコードID>) でURL作成可) |
編集画面 | /<レコードID>/e (URLFOR($Action.<オブジェクト名>.Edit, <レコードID>) でURL作成可) |
Visualforceページ | /apex/<Visualforceページ名> |
ファイルダウンロード画面 | https://c.<インスタンス名>.content.force.com/servlet/servlet.FileDownload?file=<ファイルID> |
○オブジェクトPrefix
各オブジェクトにはPrefixが割り当てられています。
標準オブジェクトは予め決まったPrefixが割り当てられています。
カスタムオブジェクトは作成時に任意の3桁のPrefixが割り当てられます。
割り当てられたPrefixは、Force.com IDEのスキーマブラウザで確認することができます。
オブジェクト名 | オブジェクトPrefix |
---|---|
ユーザ | 005 |
リード | 00Q |
取引先 | 001 |
取引先責任者 | 003 |
商談 | 006 |
契約 | 800 |
ケース | 500 |
ソリューション | 501 |
レポート | 00O(ゼロゼロオー) |
ダッシュボード | 01Z |
ドキュメント | 015 |
○URLパラメータ
URLパラメータは多数ありますが、利用する場面が多そうなものを↓に記載します。
1. 全般
URLパラメータ | 意味 | 値 |
---|---|---|
retURL | 遷移元画面のURL | |
isdtp | デスクトップモード | vw、mnなどを指定すると、ヘッダー、サイドバーが非表示になる。ビュー画面やレポート画面で使用可能。 |
2. 新規・編集画面
URLパラメータ | 意味 | 値 |
---|---|---|
cancelURL | キャンセル時に遷移するURL | |
saveURL | 保存時に遷移するURL | |
標準項目ラベル(※1) | デフォルト値 | 値を指定 例)acc9=Hot |
カスタム項目ラベル(※2) | デフォルト値 | 値を指定 例)00NA0000009ZZZZ=Hoge |
標準項目ラベル+_lkid(※3) | 標準項目の参照先レコードIDのデフォルト値 | レコードIDを指定 例)acc3_lkid=001A000000i1zzz |
カスタム項目ラベル+_lkid(※4) | カスタム項目の参照先レコードIDのデフォルト値 | レコードIDを指定 例)CF00NA0000009YYYY_lkid=001A000000i1yyy |
※1 標準項目ラベルは、lea9:リード.携帯、acc2:取引先名のように、あらかじめ決められているラベルを指定します(新規・編集画面のHTMLソースで確認可能)。
※2 カスタム項目ラベルは、項目の設定画面のURLに表示される項目IDを指定します。参照項目の場合は、CF+項目IDを指定します。
※3 標準項目ラベルと同時に指定します。
※4 カスタム項目ラベルと同時に指定します。
3. リストビュー
拡張リストビューは、「設定」→「カスタマイズ」→「ユーザインタフェース」で、「拡張リストを有効化」または「リストビューでのドラッグアンドドロップスケジュール設定を有効化」にチェックが入っている場合に表示されます。画面下部に、ページングの表示があるビューは、拡張リストビューです。
URLパラメータ | 意味 | 値 |
---|---|---|
fcf | ビューID | |
page | 表示するページ番号 | |
rowsperpage(リストビューのみ) | 1ページに表示する行数 | |
lsi(リストビューのみ) | ソート列番号 | 2:2列目で昇順ソート、-2:2列目で降順ソート |
lsc(リストビューのみ) | 頭文字(A,B,・・・Z,ア,カ・・と表示されている部分) | -1:すべて、2:C、26:ア |
rolodexIndex(拡張リストビューのみ) | 頭文字(A,B,・・・Z,ア,カ・・と表示されている部分) | -1:すべて、2:C、26:ア |
lsr(リストビューのみ) | 表示開始行番号 | |
rlid(リストビューのみ) | 関連リスト名 | 標準オブジェクト:RelatedContactList、RelatedOpportunityListなど カスタムオブジェクト:主従/参照項目のID(※5) |
※5 rlid=RelatedOpportunityList&id=<親レコードのID>のように指定すると、親レコードの関連リストが表示されます。
4. レポート
URLパラメータ | 意味 | 値 |
---|---|---|
break[n](nは番号) | 集計項目 | 項目名を指定 例)break0=OWNER |
colDt_c | 期間条件-日付項目 | 項目名を指定 例)colDt_c=DUE_DATE |
colDt_q | 期間条件-範囲 | curfy:当会計年度、current:当会計四半期、cury:本年、currentq:当四半期、thismonth:今月、thisweek:今週、today:今日、last7:過去7日間。custom:カスタム など |
sdate | 期間条件-開始 | yyyy/MM/dd |
edate | 期間条件-終了 | yyyy/MM/dd |
scope | 表示スコープ | user:私の○○○、team:私のチームの○○○、organization:すべての○○○ |
pc[n](nは番号) | 条件-項目 | 項目名を指定 例)pc0=LAST_ACTIVITY |
pn[n](nは番号) | 条件-条件 | eq:次の文字列と一致する、ne:次の文字列と一致しない、lt:<、gt:>、le:<=、ge:>=、co:次の文字列を含む、nc:次の文字列を含まない、sw:次の文字列で始まる、in:次の値を含む、ex:次の値を含まない |
pv[n](nは番号) | 条件-値 | |
details | 詳細表示 | yes:表示、no:非表示 |
sort | ソート項目 | 項目名を指定 例)sort=ACCOUNT.NAME |
5. ログイン画面
例えば、↓のURLにアクセスすると、自動的にログインし、レポートタブ画面を表示します(%2Fは「/」をURLエンコードしたもの)。
https://login.salesforce.com/?un=hoge@gmail.com&pw=hoge1234&startURL=%2F00O%2Fo
ユーザ名とパスワードが知られても問題ない場合は便利です。
URLパラメータ | 意味 | 値 |
---|---|---|
un | ユーザ名 | |
pw | パスワード | |
startURL | ログイン成功時に遷移するURL |
指定SIZE的ApexBatch
Each execution of a batch Apex job is considered a discrete transaction. For example, a batch Apex job that contains 1,000 records and is executed without the optional scope parameter from Database.executeBatch is considered five transactions of 200 records each. The Apex governor limits are reset for each transaction. If the first transaction succeeds but the second fails, the database updates made in the first transaction are not rolled back.
100条数据执行一次的话,利用下面的参数进行指定
ID jobId = Database.executeBatch(batch, 100);
deploy metafile by ant
部署做好的metafile到服务器有两种常用的方式, 利用IDE部署到服务器-> deploy to server 还有就是利用ant进行部署,下面记录一下,利用ant进行部署的几个关键点 准备工作:
- ANT(1.6以上) + J2SE(1.5以上) ←ant运行环境
- SFDC关联的部署插件 这个需要login到SFDC的环境里面,在设定-〉开发-〉tool里面下载
- 把2种下载的文件,解压,把ant-salesforce.jar文件copy到ant的lib下面
- 编写build.xml文件
文件结构 ant/bin/ant
build.xml
build.properties
src/package.xml
class/*****
objects/******
- 下面是一个例子
# build.properties # # Specify the login credentials for the desired Salesforce organization sf.username = xxxxxxxxx sf.password = xxxxx #sf.pkgName = <Insert comma separated package names to be retrieved> #sf.zipFile = <Insert path of the zipfile to be retrieved> #sf.metadataType = <Insert metadata type name for which listMetadata or bulkRetrieve operations are to be performed> # Use 'https://login.salesforce.com' for production or developer edition (the default if not specified). # Use 'https://test.salesforce.com for sandbox. sf.serverurl = https://test.salesforce.com # If your network requires an HTTP proxy, see http://ant.apache.org/manual/proxy.html for configuration. #
build.xml <project name="Sample usage of Salesforce Ant tasks" default="test" basedir="." xmlns:sf="antlib:com.salesforce"> <property file="build.properties"/> <property environment="env"/> <!-- Deploy the unpackaged set of metadata retrieved with retrieveUnpackaged --> <target name="deployUnpackaged"> <sf:deploy username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" deployRoot="src"/> </target> <!-- Shows check only; never actually saves to the server --> <target name="deployCodeCheckOnly"> <sf:deploy username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" deployRoot="src" checkOnly="true"/> </target> </project>
准备要部署的metafile文件和package.xml 编写package.xml 把这次要部署的文件列表写入到package.xml 例子: <?xml version="1.0" encoding="UTF-8"?> <Package xmlns="http://soap.sforce.com/2006/04/metadata"> <types> <members>xxx1</members> <members>xxx2</members> <name>ApexClass</name> </types> <types> <members>xxx1</members> <members>xxx2</members> <name>ApexPage</name> </types> <types> <members>xxx1</members> <members>xxx2</members> <name>ApexTrigger</name> </types> <types> <members>xxx1</members> <members>xxx2</members> <name>CustomApplication</name> </types> <types> <members>xxx1</members> <members>xxx2</members> <name>CustomLabels</name> </types> <types> <members>xxx1</members> <members>xxx2</members> <name>CustomObject</name> </types> <types> <members>xxx1</members> <members>xxx2</members> <name>CustomObjectTranslation</name> </types> <types> <members>xxx1</members> <members>xxx2</members> <name>Layout</name> </types> <types> <members>xxx1</members> <members>xxx2</members> <name>ReportType</name> </types> <types> <members>xxx1</members> <members>xxx2</members> <name>Profile</name> </types> <types> <members>xxx1</members> <members>xxx2</members> <name>StaticResource</name> </types> <types> <members>xxx1</members> <members>xxx2</members> <name>Translations</name> </types> <types> <members>xxx1</members> <members>xxx2</members> <name>Workflow</name> </types> <version>23.0</version> </Package>
进行部署检证
ant deployCodeCheckOnly
进行实际部署
ant deployUnpackaged
VFのCalendarの表示位置不正の対応
inputFiledコンポネットを使って、データタイプは日付・時間の場合、項目はonFocusの場合、Calendarを表示する
でも、一括入力画面など実装する場合、一列の項目は凄く多いので、下記方法で、横Scrollで画面を実装する
その場合、予想外問題が発生しました、ポップアップのCalendar位置は崩れた、原因を調べると、SalesforceのCalendarの表示位置の設定はOffset利用して、設定されているので、Scroll存在するDiv中に、Calendarの位置計算が問題ありました、そのため、offsetじゃなく、postionで利用して、Calendar表示位置を再設定を行う
改修方法:いろいろ方法をためました、最後、直接SalesforceのMain.jsのCalendarのPostion取得Methodを上書して、対応しました
詳しく方法は下記様に作る
CssでCalendarのPostion設定修正
.datePicker {
position:fixed;
}
// Salesforce Main.jsのMethod Modify DatePicker.prototype.position = function() { // 個別位置計算必要フラグを設定する var specialProcFlg = (this.myElement.id.indexOf(“:departTime”) >=0 || this.myElement.id.indexOf(“:timeofEntry”) >=0 || this.myElement.id.indexOf(“:entryTime”) >=0); // 個別処理 if (specialProcFlg) { a = $j(this.myElement).position().left; for (var b = 0, c = this.myElement; c != null && c != this.calendarDiv.offsetParent;) { //a += c.offsetLeft; b += c.offsetTop; c = c.offsetParent } } else { for (var a = 0, b = 0, c = this.myElement; c != null && c != this.calendarDiv.offsetParent;) { a += c.offsetLeft; b += c.offsetTop; c = c.offsetParent } } if (getObjY(this.myElement) + this.calendarDiv.offsetHeight > getScrollY() + getWindowHeight()) b -= this.calendarDiv.offsetHeight; else b += this.myElement.offsetHeight; c = “left”; if (LC.isRtlPage()) { c = “right”; a = this.calendarDiv.offsetParent.offsetWidth – a – this.myElement.offsetWidth } this.shim.setStyle(c, a + “px”); this.shim.setStyle(“top”, b + “px”) }
VFでテンプレート作成お例:
<messaging:emailTemplate subject=”xxxxxxxお知らせ {!relatedTo.Name} ” recipientType=”User” relatedToType=”Object/CustomObject”>
<messaging:htmlEmailBody >
<html>
<body>
{!recipient.xxxx}様
<p></p>
<apex:outputField value=”{!relatedTo.xxxxx}” />様からのxxxxxに関してお知らせします。
<p></p>
xxxxxxxxxxxxxxxxx
<br></br>
xxxxx:<apex:outputField value=”{!relatedTo.Name}” />
<br></br>
xxxxx:<apex:outputField value=”{!relatedTo.Status__c}” />
<p></p>
xxxxxxxxxxxxxxxxxxxx
<br></br>
xxxxxx:<apex:outputField value=”{!relatedTo.xxxx}” />
<br></br>
xxxxxx:<apex:outputField value=”{!relatedTo.xxxx}” />
<br></br>
xxxxxx:<apex:outputField value=”{!relatedTo.xxxx}” />
<p></p>
詳細はこちらのリンクをクリックし、ご確認ください。
<br></br>
{!recipient.xxxxxx}{!relatedTo.Id}
<p></p>
以上、よろしくお願いします。
</body>
</html>
</messaging:htmlEmailBody>
</messaging:emailTemplate>
————————————————–
注:テンプレートに、recipient と relatedTo利用して、関連オブジェクトの項目情報を差し込み出来ます
Apexから、下記方法でメール送信が可能
public static void sendMailByTemplate(String templateId, String objectId, String creatorId, List<String> sendMails) {
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
if (!sendMails.isEmpty()) mail.setToAddresses(sendMails);
mail.setTemplateId(templateId);
mail.setTargetObjectId(creatorId);
mail.saveAsActivity=false;
mail.setWhatId(objectId);
List<Messaging.SendEmailResult> rsList = Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
}
如何防止Salesforce的自动Focus
在画面的开头地方,加入下面的代码,就可以防止Salesforce的自动focus功能
<script type=”text/javascript”>
beenFocused = true;
</script>