DataLoaderで、CSVから日付項目をUploadする、注意点

普通は 日付書式:YYYY-MM-DDで、設定して、SFへInsert/Update場合、TimeZone存在するので、SFに予想以外の実際の日付をDBにインサートされる

例:DateLoaderのTimeZone: Asia/Japan その場合、2012-05-01で、SFへInsertすると、実際2012-04-30 15:00でSFに更新しました

対応方法:

DataLoaderのTimeZoneは GMT に設定する

—————-参考——————–
http://help.salesforce.com/apex/HTViewSolution?id=000047804&language=ja

AppExchange データローダで日付データをインポートすると1日前の日付が登録される

ナレッジ記事番号: 000047804

説明
AppExchange データローダで日付項目にデータをインポート(Insert/Update)すると1日前の日付が登録されます。
例えば、「2011-11-20」というデータをインポートすると、Salesforce上では「2011/11/19」と表示されます。これはなぜでしょうか。

解決策

まず、Saleforceのデータベースでは、日付型、日付時間型項目のデータは内部的に全てGMT(グリニッジ標準時)に変換され格納される仕様になっています。

日付型、日付時間型項目へのDataLoaderによるデータ挿入更新時には、DataLoaderのタイムゾーン設定が考慮され、データベースにはGMTへ変換後の値が格納されます。

例えばDataLoaderのタイムゾーン設定がGMT+9:00となっている場合、日付型項目を2011-11-20という値で更新すると、 DataLoaderではこの値を暗黙的に2011/11/20 0:00(GMT+9:00) と解釈しGMTに変換するため2011/11/19 15:00(GMT) になります。日付型項目では時・分が切り捨てられるため、結果として2011/11/19という、マイナス1日された日付で格納されることになります。

DataLoaderのタイムゾーン設定をたとえばGMT-9:00とされて日付型項目を更新した場合に2011-11-20という値は  2011/11/20 9:00(GMT)に変換されるので、日付型でもマイナスされることはありません。同様にタイムゾーン設定をGMTとされていれば、格納時の時差変換は発 生しません。

なお日付時間型項目に関しては、GMT変換後の値が時・分単位を含め格納されており、画面から参照される場合には再度ユーザ毎のタイムゾーン設定を考慮して時差変換されますため、日付がマイナスされて見えるという現象が起きません。

上記が現状のDataLoaderおよびSalesforceのデータベースの仕様となっております。日付型へのデータ挿入更新時にはこの点を考 慮していただき、下記のようないずれかの方法を採って頂きますようお願い申し上げます。

<「2011/09/01」をSalesforceに登録する方法>
・1日足した日付をインポートする: “2011-09-02”
・9時間足した日時をインポートする: “2011-09-01T09:00:00”
・GMT指定でインポートする: “2011-09-01T00:00:00.000Z” (※「Z」はGMTをあらわします)
・データローダのタイムゾーンを(GMT)グリニッジ標準時に設定してインポートする (下記の手順を参照下さい)

<データローダのタイムゾーン変更手順>
1)データローダのツールバーからSettingsを開く
2)Time Zone に”GMT” を入力する。(日本標準時にするためには”GMT+9:00″あるいは”Asia/Tokyo”と入力する)
3)OKボタンをクリックして設定を保存する。

SalesforceのVFからExcelダウンロード機能作成

VFのPageタグに、[contenttype=”application/vnd.ms-excel#{!filename}.xls”]追加して

STEP1:

<apex:page title=”xxx Download” Controller=”XXXXXXX”
contenttype=”application/vnd.ms-excel#{!filename}.xls” cache=”true”
showHeader=”false” sidebar=”false” readOnly=”true” >

STEP2:

Excel Downloadファイル作成する場合、VFに指定CSSのColorは必ずExcelの色設定がありの色が必要、内の場合、ダウンロードしたExcelの色設定が不正になり

STEP3:

<Apex:Form>が設定しないてください

STEP4:

ApexClassに、下記方式で、書いてください

public void goDownload() {
Pagereference pg = Page.xxxxxxx;   <- Download VF Page
return pg;
}

————————————————————————————————
Note: some browsers will not open the resulting file unless you specify the filename and set the cache attribute on the page to “true”.
————————————————————————————————

标准按钮的覆盖方法

如果想覆盖标准的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小技巧和备注

  1. WFの項目自動更新された項目に対して、項目入力規則はnot fire
  2. ProcessInstanceにて、[SELECT Id, (SELECT Id, StepStatus, Comments FROM Steps),TargetObjectId FROM ProcessInstance]で、該当データLockedされるどうか判断可能
  3. 数値VFに書式化:
    <apex:outputText value="{0,number,#,###}"> 
    <apex:param value="{!detailInfo.HokenKingaku__c/1000}" />  
    </apex:outputText>
  4. M-D関係構築
    M-D1-DD1-DDD1 3階層まで構築可能です
    M-D-Mの場合、DのオブジェクトはMになることができません
  5. スケジュールクラス定義(秒まで定義する)
    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);
  6. 日付書式
    《apex:outputText》
    <apex:outputText value="{0,date,dd/MM/yyyy}">
    <apex:param value="{!DATEVALUE(m_dtimSomeVar)}"/>
    </apex:outputText>
  7. 数値書式
    《apex:outputText value="{0,number,#,###}"》
    《apex:param value="{!detailInfo.HokenKingaku__c/1000}" /》
    《/apex:outputText》
  8. 根据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 {
    
        }
  9. Visualforce to Excel
    <apex:page standardController="Account" contenttype="application/vnd.ms-excel">
  10. 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进行部署的几个关键点
准备工作:
  1. ANT(1.6以上) + J2SE(1.5以上)  ←ant运行环境
  2. SFDC关联的部署插件 这个需要login到SFDC的环境里面,在设定-〉开发-〉tool里面下载
  3. 把2种下载的文件,解压,把ant-salesforce.jar文件copy到ant的lib下面
  4. 编写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 });

}