Pages

Showing posts with label Visualforce. Show all posts
Showing posts with label Visualforce. Show all posts

Thursday, January 26, 2017

Salesforce URLFOR()


URLFOR() function in Salesforce is not widely used as it is only available in custom buttons, links, s-controls, and Visualforce pages.

Syntax: {!URLFOR(target, id, [inputs], [no override])}
target: URL or action, s-control, or static resource merge variable
id: a reference to the record (depends on the “target”)
inputs: optional parameters with format: [param1="A", param2="B"]
no override: optional boolean flag - default false. Set to true to display a standard Salesforce page, regardless of whether you have defined an override for it elsewhere.

 The most common URLFOR() is used by developers in Visualforce pages to refer to a resource in Static resources, such as images or scripts.

Visualforce
<apex:image url="{!$Resource.ImagePba}" width="50" height="50" />
This ImagePba in the sample above is the Static Resource name, not the original image file name.

Optionally, you can add URLFOR()
<apex:image url="{!URLFOR($Resource.ImagePba)}" width="50" height="50" />

But when you use the resource in an archive file (such as a .zip or .jar file) in a static resource, URLFOR() is a must as a second parameter.
<apex:image url="{!URLFOR($Resource.Images,'pba.png')}" width="75" height="75" />
<apex:image url="{!URLFOR($Resource.ImagesFolder,'image/campaign1.png')}" width="100" height="100" />
<apex:includeScript value="{!URLFOR($Resource.LibraryJS, '/base/subdir/file.js')}"/>


Custom Button or Link
Admin can make use of URLFOR() function with $Action global variable in custom Button or Link. The $Action global variable provides methods such as View, Clone, Edit, and Delete. Some objects support other additional actions, see all valid actions here.

URLFOR() determines your base URL, and the $Action determines what view of a record to go to (the view page, edit page, etc.). For example, to edit the Account from the Contact page, add the custom button or link in Contact: {!URLFOR($Action.Account.View, Account.Id)}.

More samples
New Account -- {!URLFOR($Action.Account.New)}
View Account -- {!URLFOR($Action.Account.View, Account.Id)}
Edit Account -- {!URLFOR($Action.Account.Edit, Account.Id)}
Clone Contact -- {!URLFOR($Action.Contact.Clone, Contact.Id)}
Account Tab -- {!URLFOR($Action.Account.Tab, $ObjectType.Account)}

Thursday, July 7, 2016

Getting Started with Salesforce Visualforce Email Template

Follow the wizard to create Visualforce email template from: Setup | Communication Templates | Email Templates | New Template and select Visualforce in Step 1 "Choose the type of email template you would like to create". You will get a basic Visualforce email template with Subject, Recipient Type (Contact, Lead, or User), and Related To Type Object.

<messaging:emailTemplate subject="Account Name" recipientType="User" relatedToType="Account">
<messaging:plainTextEmailBody >
Congratulations!
This is your new Visualforce Email Template.
</messaging:plainTextEmailBody>
</messaging:emailTemplate>



Few simple things you can modify the email template without programming:

1. Change subject to include merge field
Example: <messaging:emailTemplate subject="Account Name" recipientType="User" relatedToType="Account">
to
<messaging:emailTemplate subject="Account Name - {!relatedTo.Name}" recipientType="User" relatedToType="Account">

2. Add a ReplyTo address 
Example: <messaging:emailTemplate subject="Account Name - {!relatedTo.Name}" recipientType="User" relatedToType="Account">
to
<messaging:emailTemplate subject="Account Name - {!relatedTo.Name}" recipientType="User" relatedToType="Account" replyTo="support@acme.com">

3. Change Email format from Text to HTML
Example: <messaging:plainTextEmailBody > to <messaging:htmlEmailBody >

4. Add new line
As this is now HTML email, you can add <br/> for new line.

5. You can add recipient name
Example: <p>Dear {!recipient.name},</p>

6. You can add related field, including custom field
Example: Account Owner: {!relatedTo.CreatedBy.Name}<br/><br/>

7. You can add full URL as email body
Example: URL detail: <a href="{!LEFT($Api.Partner_Server_URL_370, FIND(".com/",$Api.Partner_Server_URL_370)+3)}/{!relatedTo.Id}">{!relatedTo.Name}</a>

8. You can add logic to include field
Example: <apex:outputPanel rendered="{!relatedTo.RecordType.Name='Customer' || relatedTo.RecordType.Name='Alumni'}">
Total Revenue: {!relatedTo.Total_Revenue__c}<br/><br/>
</apex:outputPanel>


Sample of complete email template:
<messaging:emailTemplate subject="Account Name - {!relatedTo.Name}" recipientType="User" relatedToType="Account" replyTo="support@acme.com">
<messaging:htmlEmailBody >
<p>Dear {!recipient.name},</p>
Account Owner: {!relatedTo.CreatedBy.Name}<br/><br/>

<apex:outputPanel rendered="{!relatedTo.RecordType.Name='Customer' || relatedTo.RecordType.Name='Alumni'}">
Total Revenue: {!relatedTo.Total_Revenue__c}<br/><br/>
</apex:outputPanel>

URL detail: <a href="{!LEFT($Api.Partner_Server_URL_370, FIND(".com/",$Api.Partner_Server_URL_370)+3)}/{!relatedTo.Id}">{!relatedTo.Name}</a>

</messaging:htmlEmailBody>
</messaging:emailTemplate>


For advance page with apex controller, you can use Visualforce Component, and use apex class as Controller.
Example: <c:AccountNotification AcctId="{!relatedTo.Id}"/>

In the component specify the apex class as controller
<apex:component controller="AccountEmailNotify" access="global">
</apex:component>


Reference:

Sunday, November 1, 2015

Salesforce: How to call Flow from Visualforce page

In this blog, we are going to explain how to use Visualforce page to call Autolaunched Flow.

Use case: business would like to record Contacts deleted by user from Salesforce page layout to a custom object.

With apex trigger, this should be no issue, but is there any other way?

Solution:
Let's using Autolaunched Flow, Autolaunched Flow is famous to be used by Process Builder, but Process Builder cannot catch deletion process, it only support record creation and update.

Use Autolaunched Flow called from Visualforce page, and the Visualforce page to overwrite the Delete button.

1. Prepare Custom Object



2. Create Flow
  • Flow Unique Name = Delete_Contact_Flow
  • Type = Autolaunched Flow

A. Create 2 variables and 1 constant

Variable varContactId use to receive Contact Id from screen, type = Input Only

Variable varContactName use to query Contact Name using varContactId, type = Private

Constant consObject use to store the process for Contact object


B. Create 3 record processes: lookup, delete, create

Overall Flow Processes

Query Contact with variable varContactId to get Contact Name and store it to varContactName
** you may to skip this process if Contact Name passed in as parameter, but for this blog, we would like to show record lookup process.

Delete Contact record with variable varContactId


Create a custom Object record with necessary fields to record the Contact deleted

Save the Flow and remember to Activate it.


3. Create Visualforce Page
This would be a simple page to pass Contact Id and call the Flow. Name the page as Overwrite_Contact_Delete.

 <apex:page standardController="Contact">  
   <flow:interview name="Delete_Contact_Flow" finishLocation="{!URLFOR('/003')}">  
     <apex:param name="varContactId" value="{!Id}" />  
     <apex:param name="varContactName" value="{!Contact.Name}" />  
   </flow:interview>  
 </apex:page>  


4. Enable Visualforce Page for Profile
Go to users Profile and enable Overwrite_Contact_Delete Visualforce page.


5. Overwrite Delete button for Contact



6. Deleted Records log
Use custom tab or report to monitor deleted Contacts.



Reference:


Monday, October 26, 2015

Salesforce: Attach File with code

In previous blog, we discussed about how to attach file to a record using "File" and "Attachment". As you read in that blog, to attach file as Attachment, user need to have Edit permission on the parent record.

In some use cases, permission to edit record is not ideal, example: support users not supposed to edit an opportunity record, but they just need to read the opportunity and may need to attach file. Chatter File is a great option for this limitation, but for some reasons, company may just want to use Attachment, rather than split between Attachment and File.

In this blog, we will introduce to use Apex class for user to upload file as Attachment. Remember that when using Apex class, by default it will not check user permission for the record, as long as user able to open the record and the user profile have access to the Apex class and Visualforce page.

So, here are few items and steps needed to built custom attach file functionality as Attachment, in this example, we are going to use Opportunity object:

1. Create Apex Class
This is the core program to upload the file to Salesforce and attached to the parent record.
1:  public class TicketAttachment   
2:  {  
3:    /* Start - Variables */  
4:    public Id recId         {get;set;}   
5:    public Attachment objattachment {get{  
6:                      if(objattachment == null)  
7:                        return objattachment = new Attachment();  
8:                      return objattachment;    
9:                     }set;  
10:                   }  
11:    /* End - Variables */  
12:      
13:    /* Start - Constructor */  
14:    public TicketAttachment(ApexPages.StandardController ctlr)   
15:    {   
16:      recId = ctlr.getRecord().Id;      
17:    }   
18:     /* End - Constructor */  
19:       
20:    /*  
21:      * MethodName    : upload  
22:      * param       : -  
23:      * Description    : This function used to upload Attachment and redirect the user back to parent  
24:    */  
25:    public PageReference upload()   
26:    {  
27:      objattachment.OwnerId = UserInfo.getUserId();  
28:      objattachment.ParentId = recId;  
29:      try   
30:      {  
31:       insert objattachment;  
32:      }   
33:      catch (DMLException e)   
34:      {  
35:       ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,'Error uploading attachment'));  
36:       return null;  
37:      }   
38:      return new Pagereference('/'+recId);  
39:    }  
40:      
41:    /*  
42:      * MethodName    : cancel  
43:      * param       : -  
44:      * Description    : This function redirect the user back to parent.  
45:    */  
46:    public PageReference cancel()   
47:    {  
48:      return new Pagereference('/'+recId);  
49:    }  
50:  }  



2. Create Apex Text Class
Each Apex class in Salesforce need to have a test class with minimum of  75% test coverage.

1:  /**   
2:  * \arg Description   : Test class for TicketAttachment controller class.  
3:  */  
4:  @isTest  
5:  private class Test_TicketAttachment   
6:  {  
7:    static Opportunity objTicket;  
8:    static PageReference pageRef;  
9:      
10:    //Preparing data for testing the functioanlity  
11:    static testMethod void setUpData()  
12:    {  
13:      objTicket = new Opportunity(Name='SA', StageName='Prospecting', CloseDate=Date.newInstance(2016, 2, 17));  
14:      insert objTicket;  
15:    }  
16:      
17:    //checking for upload functionality  
18:    static testMethod void test_FileUpload()   
19:    {  
20:      Test.startTest();  
21:      setUpData();  
22:      system.debug('==objTicket==='+objTicket);  
23:        
24:      pageRef = new PageReference('/apex/TicketAttachmentVF?id=objTicket.Id');   
25:      Test.setCurrentPage(pageRef);  
26:      pageRef.getParameters().put('id', objTicket.Id);  
27:        
28:      ApexPages.StandardController stdCTR = new ApexPages.StandardController(objTicket);  
29:      TicketAttachment objController = new TicketAttachment(stdCTR);  
30:        
31:      Attachment objAtt = new Attachment(Body = Blob.valueOf('Test Body'), Name = 'Test Attachment', ParentId = objTicket.Id);  
32:      insert objAtt;  
33:        
34:      pageRef = objController.upload();  
35:      //System.assertEquals(pageRef.getUrl(),'/'+objTicket.Id);  
36:        
37:      pageRef = objController.cancel();   
38:      
39:      Test.stopTest();  
40:    }
41:  
42:  }  


3. Create Visualforce Page
This Visualforce page served as user interface for user to upload a file.
1:  <apex:page standardController="Opportunity" extensions="TicketAttachment">   
2:    <apex:sectionHeader subtitle="Attachment Upload Example"/>  
3:    <apex:form enctype="multipart/form-data">  
4:      <apex:pageMessages />  
5:      <apex:pageBlock title="Upload a Attachment">  
6:        <apex:inputFile value="{!objattachment.body}" filename="{!objattachment.name}" id="file"/>  
7:        <apex:pageBlockButtons location="bottom">  
8:          <apex:commandButton action="{!upload}" value="Save"/>  
9:          <apex:commandButton action="{!cancel}" value="Cancel"/>  
10:        </apex:pageBlockButtons>  
11:      </apex:pageBlock>  
12:    </apex:form>  
13:  </apex:page>  



4. Create Custom Button or Link
This is standard Custom Button or Link, select Content Source = Visualforce page


5. Add Custom Button or Link to Page Layout
Custom button or link created will not appear in page layout until you add them.



6. Add Apex Class and Visualforce Page to user profile
Each user need to use apex class and visualforce page functionality need to have apex class and visualforce added to their Profile or Permission Set.



Reference: Salesforce: Attach File to a Record



Sunday, October 19, 2014

Salesforce: Setup Landing Page & Force.com Quick Access Menu

Based on a best practice release by Salesforce on 2010, numbers of Salesforce administrator and business analyst depends on the size of your business, the complexity of your implementation, the volume of user requests, and so on. One common approach for estimating the number of administrators you need is based on the number of users.

Number of users Administration resources:
 001 – 030 users : < 1 full-time administrator  
 031 – 074 users : 1+ full-time administrator  
 075 – 149 users : 1 senior administrator; 1 junior administrator  
 140 – 499 users : 1 business analyst, 2–4 administrators  
 500 – 750 users : 1–2 business analysts, 2–4 administrators  
 > 750 users     : depends on a variety of factors  

For administrators who work a lot on Setup menu, here are 2 simple tips for you to access Setup menu faster (less click), both setting is available in your user detail.

Go to your user detail and activate this option:

1. Make Setup My Default Landing Page
When you enable this option for your user, once login to Salesforce, it will bring you directly to the Setup page rather than Home tab. Imagine if you mostly go to Setup page after login, how many clicks you save for a day, a week, a month... ?

2. Force.com Quick Access Menu
When you have this option enable to your user detail, you will see a small arrow at the right of the page when you click a tab, such as: Account Tab, or in page detail. Menu shown will be different in tab or page layout and also different based on the object.

Click the arrow and you will see the menu:

As admin, this will save you a lot of click as you can go directly to the Fields related to the object with one click, or go to the Object itself in Setup page, Record Type, Validation Rules, Edit Column, Edit Layout, Edit Tab until Import Data.

Note: if you override standard View page with visualforce page, Force.com Quick Access Menu will NOT shown up when you click object tab.



Thursday, October 2, 2014

Salesforce: Event Log Files

As of Winter '15 release, Event Log Files has been Generally Available. It contains useful information for assessing organizational usage trends and user behaviour.

However, there is no access through Salesforce user interface, you only can access the data through the Force.com REST API, this mean you can write visual force page with apex code for the UI, but fear not, I'll share few free app able to access the data.

Log files are generated asynchronous, one day after an event take place, but this should be good enough to understand your user usage. Log data is read-only, you can’t insert, update, or delete log data. It does NOT count towards org file storage.

For Production org (Enterprise, Unlimited, and Performance Edition), you need to purchase User Event Monitoring to get this feature fully activated, otherwise you will have free access to the login and logout log files with one-day data retention only. Once purchase, you can access all log file types with 30-day data retention.

Developer Edition (DE) organizations have free access to all log types with one-day data retention.
So, it is good idea to integrate this data to your back-end database for further analysis. Once it enabled, you will see object called EventLogFile from API.

Log Files have 29 event type:
• API
• Apex Callout
• Apex Execution
• Apex SOAP
• Apex Trigger
• Asynchronous Report Run
• Bulk API
• Change Set Operation
• Content Distribution
• Content Document Link
• Content Transfer
• Dashboard
• Document Attachment Downloads
• Login
• Login As
• Logout
• Metadata API Operation
• Multiblock Report
• Package Install
• Queued Execution
• Report
• Report Export
• REST API
• Sandbox
• Sites
• Time-Based Workflow
• UI Tracking
• URI
• Visualforce Request

Sample SOQL query:
Select Id, EventType, LogDate, LogFile, LogFileContentType from EventLogFile


As you can see in query result, it will create a record for each LogDate by EventType. The content is stored in LogFile and you need to read it with code, or you can use REST tool for testing. 

How to read the log file?

1. REST Explorer
Available for free from AppExchange. Once installed, you need to configure following: 
1) Configure Base URL as Custom Setting
 * Go to Setup | Develop | Custom Settings | Rest Explorer Configuration | Manage | New.
 * Set the name to 'baseUrl' and the value to your Salesforce instance, for example 'https://na1.salesforce.com'.

2) Configure a Remote Site Setting.
 * Go to Setup | Security Controls | Remote Site Settings | New Remote Site.
 * Set Remote Site Name to the name of your choice, and set Remote Site URL to the same value of the baseUrl above, for example 'https://na1.salesforce.com'.

Then you can access it through a new tab created REST Explorer. Enter LogFile value from query above to the textbox provided.


This is the result for API EventType
 Raw Response  
 Sforce-Limit-Info: api-usage=36/15000  
 Date: Wed, 01 Oct 2014 23:38:12 GMT  
 Transfer-Encoding: chunked  
 Expires: Thu, 01 Jan 1970 00:00:00 GMT  
 Set-Cookie: BrowserId=Ouz260FsTl6kC3LUW7VTQg;Path=/;Domain=.salesforce.com;  
 Expires=Sun, 30-Nov-2014 23:38:12 GMT  
 Content-Type: text/csv  
 "EVENT_TYPE","TIMESTAMP","REQUEST_ID","ORGANIZATION_ID","USER_ID","RUN_TIME","CLIENT_IP","URI","REQUEST_STATUS","API_TYPE","API_VERSION","CLIENT_NAME","METHOD_NAME","ENTITY_NAME","ROWS_PROCESSED","REQUEST_SIZE","RESPONSE_SIZE","QUERY"  
 "API","20140929223903.454","3tX96QXMYovdpU0CcVVk6-","00DB00000000Vgy","005B0000000ybnD","18","a.b.c.d","/services/data/v32.0/tooling/query/","S","","32.0","devconsole","query","UserPreference","0","","",""  
 "API","20140929223903.516","3tX96QRNJyk4QU0CcVgkAk","00DB00000000Vgy","005B0000000ybnD","105","a.b.c.d","/services/data/v32.0/tooling/sobjects/User/005B0000000ybnD","S","","32.0","devconsole","retrieve","User","1","","",""  
 "API","20140929223904.043","3tX96Se_dRhYFSHyqUDgI-","00DB00000000Vgy","005B0000000ybnD","34","a.b.c.d","/services/data/v32.0/tooling/query/","S","","32.0","","query","ApexExecutionOverlayAction","0","","",""  
 "API","20140929223904.444","3tX96U8AoglYZSHyqU0xdk","00DB00000000Vgy","005B0000000ybnD","38","a.b.c.d","/services/data/v32.0/tooling/query/","S","","32.0","","query","ApexLog","0","","",""  
 "API","20140929223905.164","3tX96WmjfEhYFhHyqUDgI-","00DB00000000Vgy","005B0000000ybnD","47","a.b.c.d","/services/data/v32.0/tooling/query/","S","","32.0","devconsole","query","IDEWorkspace","1","","",""  
 "API","20140929223905.441","3tX96Xv75g988xHyqUCmFF","00DB00000000Vgy","005B0000000ybnD","21","a.b.c.d","/services/data/v32.0/tooling/query/","S","","32.0","devconsole","query","TraceFlag","1","","",""  
 "API","20140929223905.671","3tX96YlO2KdYFhHyqUDgI-","00DB00000000Vgy","005B0000000ybnD","23","a.b.c.d","/services/data/v32.0/tooling/query/","S","","32.0","devconsole","query","MetadataContainer","1","","",""  
 "API","20140929223906.008","3tX96ZnGj1T88xHyqUCmFF","00DB00000000Vgy","005B0000000ybnD","84","a.b.c.d","/services/data/v32.0/tooling/sobjects/TraceFlag/7tfB00000000J0zIAE","S","","32.0","devconsole","update","TraceFlag","1","","",""  
 "API","20140929223906.032","3tX96Ywqmkt7BU0CcVFeSk","00DB00000000Vgy","005B0000000ybnD","337","a.b.c.d","/services/data/v32.0/tooling/sobjects/User/005B0000000ybnDIAQ","S","","32.0","devconsole","update","User","1","","",""  
 "API","20140929223906.475","3tX96a4QSch7BU0CcVFeSk","00DB00000000Vgy","005B0000000ybnD","206","a.b.c.d","/services/data/v32.0/tooling/query/","S","","32.0","devconsole","query","MetadataContainerMember","0","","",""  
 "API","20140929224424.784","3tX9P7Yw7Er2QxHyqUDeZk","00DB00000000Vgy","005B0000000ybnD","23","a.b.c.d","/services/data/v32.0/tooling/query/","S","","32.0","devconsole","query","ApexCodeCoverage","0","","",""  
 "API","20140929224425.792","3tX9P8CnQYT8ISHyqUCmFF","00DB00000000Vgy","005B0000000ybnD","856","a.b.c.d","/services/data/v32.0/tooling/sobjects/ApexClass/01pB0000000AJ6QIAW","S","","32.0","devconsole","retrieve","ApexClass","1","","",""  
 "API","20140929224426.238","3tX9PCh0VJnduE0CcVVk6-","00DB00000000Vgy","005B0000000ybnD","98","a.b.c.d","/services/data/v32.0/tooling/query/","S","","32.0","devconsole","query","ApexClass","10","","",""  
 "API","20140929224426.430","3tX9PCnNTY34WE0CcVgkAk","00DB00000000Vgy","005B0000000ybnD","262","a.b.c.d","/services/data/v32.0/tooling/query/","S","","32.0","devconsole","query","ApexClass","1","","",""  
 "API","20140929224512.669","3tX9RuvnfjKePE0CcVVMjk","00DB00000000Vgy","005B0000000ybnD","26","a.b.c.d","/services/data/v32.0/tooling/query/","S","","32.0","","query","ApexLog","1","","",""  
 "API","20140929224527.721","3tX9Sn1k6qKYfhHyqU0xdk","00DB00000000Vgy","005B0000000ybnD","17","a.b.c.d","/services/data/v32.0/tooling/query/","S","","32.0","","query","ApexLog","2","","",""  
 "API","20140929225015.272","3tX9iX7wbcq8TSHyqUCmFF","00DB00000000Vgy","005B0000000ybnD","47","a.b.c.d","/services/data/v32.0/tooling/sobjects/ApexPage/066B00000001YGXIA2","S","","32.0","devconsole","retrieve","ApexPage","1","","",""  
 "API","20140929225905.190","3tXACN8ylBSehU0CcVVMjk","00DB00000000Vgy","005B0000000ybnD","69","a.b.c.d","/services/data/v32.0/tooling/sobjects/TraceFlag/7tfB00000000J0zIAE","S","","32.0","devconsole","update","TraceFlag","1","","",""  
 "API","20140929230507.422","3tXAXSXhhkZ50U0CcVgkAk","00DB00000000Vgy","005B0000000ybnD","79","a.b.c.d","/services/data/v32.0/tooling/sobjects/IDEWorkspace/1deB00000000JIgIAM","S","","32.0","devconsole","update","IDEWorkspace","1","","",""  
CLIENT_IP has been masked.

This is the result for Report Event Type
 Raw Response  
 Sforce-Limit-Info: api-usage=37/15000  
 Date: Wed, 01 Oct 2014 23:46:38 GMT  
 Transfer-Encoding: chunked  
 Expires: Thu, 01 Jan 1970 00:00:00 GMT  
 Set-Cookie: BrowserId=Xcteq7xKS0uNZylaeBBafg;Path=/;Domain=.salesforce.com;  
 Expires=Sun, 30-Nov-2014 23:46:38 GMT  
 Content-Type: text/csv  
 "EVENT_TYPE","TIMESTAMP","REQUEST_ID","ORGANIZATION_ID","USER_ID","RUN_TIME","CLIENT_IP","URI","REQUEST_STATUS","ENTITY_NAME","DISPLAY_TYPE","RENDERING_TYPE","REPORT_ID","NUMBER_EXCEPTION_FILTERS","NUMBER_COLUMNS","SORT","NUMBER_BUCKETS"  
 "Report","20140929224335.668","3tX9MEjMd8xeOE0CcVVMjk","00DB00000000Vgy","005B0000000ybnD","520","222.165.97.180","/00OB0000000YEn2","S","","S","W","00OB0000000YEn2","0","10","","0"  
 "Report","20140929224340.773","3tX9MZQw71teOE0CcVVMjk","00DB00000000Vgy","005B0000000ybnD","68","222.165.97.180","/00OB0000000YEn2","S","","S","X","00OB0000000YEn2","0","10","","0"  
 "Report","20140929224344.199","3tX9MkwB0pk4Vz0CcVgkAk","00DB00000000Vgy","005B0000000ybnD","139","222.165.97.180","/00OB0000000YEn2","S","","S","W","00OB0000000YEn2","0","10","","0"  

Credit and thanks to Adam Torman for sharing sample code, how to access Event Log File via Visualforce and Apex code.


2. Developer Workbench
From https://workbench.developerforce.com login with API version 32.0 or beyond. Go to utilities | Rest Explorer, query with 
/services/data/v32.0/query?q=SELECT+Id+,+EventType+,+LogFile+,+LogDate+,+LogFileLength+FROM+EventLogFile
Click Execute button, it will show total record the same as you query from Developer Console.

From here, click Expand All link to see all record in detail, then click link at LogFile


It will display Raw Result the same as using Rest Explorer installed package above. You can copy and paste the result from header "EVENT_TYPE","TIMESTAMP" ... into Notepad and save as CSV file.

Sample CSV file for Event Type = ReportExport.


3. Salesforce Event Log File Browser
Go to URL https://salesforce-elf.herokuapp.com
This application is pretty simple, open the URL above, select login to Production or Sandbox and allow Salesforce Event Log File Browser to access your Salesforce data.
Once you are in, you can download each event log into CSV file.



Reference: 



Tuesday, September 23, 2014

Visualforce Area for Home Page Custom Component

By Summer '15 release, Home Page Custom Component contains code will no longer supported. Salesforce will remove non-supported code from HTML Area home page components. As a result, components with JavaScript or other advanced HTML elements may stop working properly.

Salesforce advise to use Visualforce Area to replace it, so if you have any exisiting HTML Area component, convert them Visualforce Area. You need to add the new component (and remove HTML Area components) to all Home Page Layouts.

Example: this is your HTML in HTML Area component
<marquee><b style="color: rgb(204, 0, 0); font-family: Arial, Helvetica, sans-serif; font-size: medium;">Salesforce will be conducting emergency maintenance tonight, 14-Oct-14, from 7:00-8:00PM Pacific Time.&nbsp; Salesforce.com will not be available during this time.&nbsp; We extend Salesforce's apologies for this inconvenience.</b></marquee>


1. Create Visualforce page
Setup - Develop - Pages (you can create new Visualforce page directly in Production (although you should built it in Sandbox for testing and approval, and do not need Apex Test Method to deploy from Sandbox instance)

2. Copy the HTML
Put the HTML from existing component into <apex:page>HTML</apex:page> and Save.
Example:
1:  <apex:page>   
2:  <marquee>   
3:  <b style="color: rgb(204, 0, 0); font-family: Arial, Helvetica, sans-serif; font-size: medium;">Salesforce will be conducting emergency maintenance tonight, 14-Oct-14, from 7:00-8:00pm Pacific Time.&nbsp; Salesforce.com will not be available during this time.&nbsp; We extend Salesforce's apologies for this inconvenience.</b>   
4:  </marquee>   
5:  </apex:page>   
3. Create Home Page Components
  • Setup - Customize - Home - Home Page Components, type a name and select Visualforce Area
  • Choose Visualforce Page created above.
  • Set the height, tick Show scrollbars and Label as needed.
  • Save


4. Set Home Page Layouts
  • Setup - Customize - Home - Home Page Layouts
  • Edit each Home Page Layout,  you should see new Visualforce Area component created in Components to Show, enable that component
  • Next
  • Adjust the order Up / Down
  • Save



Saturday, March 15, 2014

How to change Salesforce text colour?

As you all aware, Salesforce text in web user interface (UI) is only with black and dark grey colour, that's all and you not able to configure it.
But, is it possible if I need to have a red colour for some text or text with some conditions in the page layout so my user can notice something quickly?

Yes, but it is not easy, meaning you need to do something. Visualforce and with apex code if necessary.

Here a sample visualforce page using standard Account controller for account page layout:

<apex:page standardController="Account">
<apex:outputText value="The unformatted time right now is: {!NOW()}" />
<br/>
<font color="red">
<apex:outputText value="The formatted time IN GMT IS : 
{0,date,yyyy.MM.dd G 'at' HH:mm:ss z}">
<apex:param value="{!NOW()}" />
</apex:outputText>
</font>
</apex:page>

As you can see, we just use standard HTML <font> color attribute, this mean you can use other standard HTML tags in visualforce as needed.

Add this visualforce page into Account page layout and you are done.


This is the result, see text in red:


Make sure your visualforce is using standardController rather than Controller, if you need logic with apex class, add extensions in vf page, example: <apex:page standardController="Account" extensions="MyController">
Otherwise, you will not able to add the visualforce page into standard page layout.


Reference: How to embed Visual Force page in a page layout?


Page-level ad