May 31, 2011

Picklist Describe Component

I was working over my custom visualforce page where I am displaying some fields including picklist field , text fields etc. Values filled in these fields are used as a search criteria to fetch records from my organization. There were around 30 picklist fields on this page.


Everything was working fine then I suddenly recognize that this search can be used by all users of my application. Then I logged in as user of different profile other than system admin. Pretty amazing for me that most of the picklist and text fields were not visible, then I jumped into the field level security of my object and found that these fields are not visible to this profile. I traversed back to my visualforce page where I saw that I have used input fields to display picklist and text fields. I changed all text inputFields to inputText but it was very difficult to create 30 select list after describing all picklist values from object.


So I have create a component in which we will pass Object API name and Field API name and drop down will be created with all values of that picklist.


Now how to use this component :


1) Get the component downloaded from app exchange : http://bit.ly/liFjUf
2) Install this package to your organization : http://bit.ly/mgPpaq
3) Now create a visualforce page and class code is provided below :


Apex :
public class TestPicklistController
{
    //Property to hold the selected value of component
    public String SelectedVal {get; set;}
    
    public TestPicklistController()
    {
        SelectedVal = '' ;
    }
    
    public void simpleDebug()
    {
        System.debug(':::::::: ' + selectedVal) ;
    }
}
Visualforce :
<apex:page controller="TestPicklistController">

    <apex:form >

        <apex:pageBlock >

            <apex:pageBlockButtons >
                <apex:commandButton value="Check Selected Value" action="{!simpleDebug}" />
            </apex:pageBlockButtons>

            <apex:outputLabel value="Industry"/>
            <arora:PicklistToPicklist value="{!SelectedVal}" objectName="Account" picklistFieldAPI="Industry" useDefaultValue="true" />

        </apex:pageBlock>

    </apex:form>

</apex:page>
Value (Required) : Selected Picklist Value


objectName (Required) : API Name of Object


picklistFieldAPI(Required) : API Name of picklist value


useDefaultValue(Optional) : True (--None-- will be displayed) , False (Only picklist values will be shown)


Feedbacks are always welcomed, also please let me know if there is any problem.


Cheers

May 27, 2011

Validation Over Apex

Explaining a small example why we should use validations over apex. The key benefit is we don't have to write test class for it. Also if salesforce provide powerful tools like validations and workflows then why write APEX.


I was jumping here and there in my code to find places where I can re-factor it to reduce code lines, what I got is this.

public boolean validatePhone(account acc)
{
 if (acc.Phone != null)
 {
  String phoneNumber = acc.Phone ;
  Pattern phonePattern = Pattern.compile('\\D*?(\\d\\D*?){10}');
        Pattern numericPattern = Pattern.compile('[0-9]{10}');
        Matcher phoneMatcher = phonePattern.matcher(phoneNumber);
            
  if(phoneNumber.length() == 10)
  {
   Matcher numericMatcher = numericPattern.matcher(phoneNumber);
   if(numericMatcher.matches())
   {
    return true;
   }
   else
   {
    return false;
   }
  }
  else
  {
   return false ;
  }
 }
}


A apex code which validates a phone number, I am posting with some alterations as removing some unwanted code so please don't blame me if this code doesn't work after copy and paste.


Why I have written this code? Because if any user entering value in phone field then I want them to enter value in particular format i.e. (XXX)XXX-XXXX and it should be of 10 digit.


Then I just gave a thought over using validations and came up with a solution, writing a validation on account :


IF( ISBLANK(Phone) , false , NOT(REGEX(Phone, "\\D*?(\\d\\D*?){10}")) )


Now I don't need to write any code and any test class for it. I know there are some flaws in it but what my point is how we can reduce the apex code. Now don't just give a devil smile and start looking for the flaws.


Cheers

Calculating Age From Birth Date

It looks very simple but a bit complicated question, what if I need to calculate the age from birth date in formula field whose return type is text?


Answer for Calculating Age From Birth Date :


Just copy paste this in your formula field, it will provide you the exact age calculated from birth date.
IF(MONTH(TODAY())>MONTH(DOB_API),YEAR(TODAY())-YEAR(DOB_API),IF(AND(MONTH(TODAY())=MONTH(DOB_API),DAY(TODAY())>=DAY(DOB_API)),YEAR(TODAY())-YEAR(DOB_API),(YEAR(TODAY())-YEAR(DOB_API))-1))
First simply if the month of present year is greater than date of birth than age will be calculated as the difference between present year and year of birth.


Secondly if the first scenario fails two options comes in my mind, if the month of present year is same then is day of birth is same or not so if day of birth is greater than or equals to day of birth than age is calculated as we have done in the first scenario.


Thirdly if above both scenarios fails that means month of present year and month of birth date is same but day of birth is smaller than day of present day. So age is calculated as the difference between present year and year of birth -1


See I told you it looks simple but bit complicated.


Cheers

May 17, 2011

Encrypted Fields

How to maintain sensitive data in salesforce?
Answer is using Encrypted Fields.


Encrypted Custom Fields are a new field type (released after winter 08) that allows users to store sensitive data in encrypted form and apply a mask when the data is displayed (e.g., Credit Card Number: XXX-XXX-XX-1234)


Now how I can use encrypted fields in my organisation?
You need get Encrypted Field Enabled from salesforce.com. Once you get it enabled from salesforce, you will see a new data type option when creating a new custom field.




We can also specify the mask for the field.




Some important points :

  1. User profiles who have the “View Encrypted Data” configuration enabled will be able to view the field normally.
  2. Users who do not have the “View Encrypted Data” profile will see the mask.
  3. User profiles that have the “Modify All Data” permission will not be able to see the value of encrypted data fields.
  4. The field length is restricted to 175 characters in size.
  5. Encrypted Field cannot be type cast as Unique or External ID.
  6. An encrypted field cannot be configured with a default value.
  7. You can’t use encrypted fields in report filters and list views.
  8. You can’t use the encrypted fields in SOQL “where/order” clauses.
  9. Also we can not use encrypted field formula fields, workflow rules, workflow field updates, approval process entry criteria, and approval step criteria.
  10. If you clone a record that has encrypted custom fields, Salesforce will copy the data from the field ONLY if the user has the “view encrypted data” permission.
  11. You can access the data of encrypted field in apex, i.e value is always unmasked.

*Search the Salesforce.com Help & Training section, searching for “Encrypted Custom Fields” for more details.

Cheers

May 16, 2011

Salesforce Certification 401

Want to become Salesforce Certified Developer?

Here are some key points to be taken care of, which may help you to crack the bone of 401.For that you should have firm knowledge about :

  1. Sharing Rules / Org-Wide Default
  2. Approval Processes (Unanimous / Parallel / Skipping Steps / Dynamic Routing)
  3. Junction Object
  4. Master-Detail / Lookup / Hierarchical relationships
  5. Report / Report Types / Dashboards
  6. Data Loader / Import Wizard
  7. Formula Fields
  8. Analytical Snapshot
  9. Workflows
  10. Encrypted Fields / External Ids
  11. Governor Limits
Most of the questions are from the above topics, and are listed in order of their weightage. Also it is very important to know about the recruiting app, you can find details on recruiting app in most of the salesforce PDFs.

I will be covering some of the topics which I found interesting in my next blog post.

*Please note that this blog post if helpful for 401 only and new topics may add with the new release. So please do refer the latest Salesforce.com Certified Force.com Developer - Study Guide for latest updates.

Best Of Luck.

Apr 26, 2011

System Debug

Its very hectic to debug when we have too many script statements. Most of the time when we apply System.debug in our code with many script statement we get :


*********** MAXIMUM DEBUG LOG SIZE REACHED ***********


I get frustrated with this and started rolling over the pdf which says there is a solution for this. Now if I want to see a specific line debug which is coming almost in the end of our code so I will simply write this where I want to get the debug in my code :
System.debug(Logginglevel.ERROR , ' ::::::: My Debug :::::::::::::') ;
And after this some steps to be done
  1. Create Debug logs from "Monitoring"
  2. Create Filters :
    • Database : NONE
    • Workflow : NONE
    • Validation : NONE
    • Callouts : NONE
    • Apex Code : ERROR
    • Apex Profiling : NONE
    • Visualforce : NONE
So when I execute my code only debug with Logginglevel.ERROR will be displayed. Isn't this useful. 

Enjoy the power of salesforce.

Apr 15, 2011

Pagination in Salesforce

We sometimes need to display many records on UI, so it doesn't look good when you display 10000 records on single page. Pagination is the best option you can opt for.


Now question is how you can apply pagination in salesforce with native salesforce look and feel. So here is the answer of this.


Visualforce Page Code :
<apex:page controller="pagingControllerForUser">
    <apex:form >
        <apex:pageBlock >
            
            <apex:pageMessages id="pgm"/>
            
            <apex:pageBlockButtons >
                <apex:commandButton value="Search" action="{!Search}"/>
            </apex:pageBlockButtons>
            
            <apex:pageBlockSection >
                <apex:pageBlockSectionItem >
                    <apex:outputLabel value="User Name"/>
                    <apex:inputText value="{!usr.Name}"/>
                </apex:pageBlockSectionItem>
            </apex:pageBlockSection>

        </apex:pageBlock>

        <apex:pageBlock rendered="{!IF(AllSearchUsers.size != null && AllSearchUsers.size > 0, true , false)}">
            <apex:outputPanel layout="block" styleClass="pSearchShowMore" id="otpNav2">
              Total Records Found: <apex:outputText rendered="{!IF(Con.resultSize==10000,true,false)}">10000 +</apex:outputText><apex:outputText rendered="{!IF(Con.resultSize < 10000,true,false)}">{!Con.resultSize}</apex:outputText>
                  <apex:image url="/img/search_prevarrow_disabled.gif" styleClass="prevArrow" rendered="{!NOT(Con.HasPrevious)}"/>
                  <apex:image url="/img/search_prevarrow.gif" title="Previous Page" styleClass="prevArrow" rendered="{!Con.HasPrevious}"/>
                  <apex:commandLink action="{!Previous}" title="Previous Page" value="Previous Page" rendered="{!Con.HasPrevious}"/>
                  <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasPrevious)}">Previous Page</apex:outputPanel>         
                  &nbsp;({!IF(Con.PageNumber == 1,1,((Con.PageNumber -1) * Con.PageSize)+1)}-{!IF(Con.resultSize < Con.PageSize,Con.resultSize,Con.PageNumber * Con.pageSize)})&nbsp;
                  <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasNext)}">Next Page</apex:outputPanel>         
                  <apex:commandLink title="Next Page" value="Next Page" rendered="{!Con.HasNext}" action="{!Next}"/>&nbsp;
                  <apex:image url="/img/search_nextarrow.gif" title="Next Page" styleClass="nextArrow" rendered="{!Con.HasNext}"/>
                  <apex:image url="/img/search_nextarrow_disabled.gif" rendered="{!NOT(Con.HasNext)}"/>          
              </apex:outputPanel>
            
            <apex:pageBlockSection columns="1">
                <apex:pageBlockTable value="{!AllSearchUsers}" var="UR">
                    <apex:column headerValue="Name" value="{!UR.Name}"/>
                    <apex:column headerValue="Email" value="{!UR.Email}"/>
                    <apex:column headerValue="Phone" value="{!UR.Phone}"/>
                    <apex:column headerValue="Department" value="{!UR.Department}"/>
                </apex:pageBlockTable>
            </apex:pageBlockSection>
            
            <apex:outputPanel layout="block" styleClass="pSearchShowMore" id="otpNav">
              Total Records Found: <apex:outputText rendered="{!IF(Con.resultSize==10000,true,false)}">10000 +</apex:outputText><apex:outputText rendered="{!IF(Con.resultSize < 10000,true,false)}">{!Con.resultSize}</apex:outputText>
                  <apex:image url="/img/search_prevarrow_disabled.gif" styleClass="prevArrow" rendered="{!NOT(Con.HasPrevious)}"/>
                  <apex:image url="/img/search_prevarrow.gif" title="Previous Page" styleClass="prevArrow" rendered="{!Con.HasPrevious}"/>
                  <apex:commandLink action="{!Previous}" title="Previous Page" value="Previous Page" rendered="{!Con.HasPrevious}"/>
                  <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasPrevious)}">Previous Page</apex:outputPanel>         
                  &nbsp;({!IF(Con.PageNumber == 1,1,((Con.PageNumber -1) * Con.PageSize)+1)}-{!IF(Con.resultSize < Con.PageSize,Con.resultSize,Con.PageNumber * Con.pageSize)})&nbsp;
                  <apex:outputPanel styleClass="pShowLess noLink" style="color:grey" rendered="{!NOT(Con.HasNext)}">Next Page</apex:outputPanel>         
                  <apex:commandLink title="Next Page" value="Next Page" rendered="{!Con.HasNext}" action="{!Next}"/>&nbsp;
                  <apex:image url="/img/search_nextarrow.gif" title="Next Page" styleClass="nextArrow" rendered="{!Con.HasNext}"/>
                  <apex:image url="/img/search_nextarrow_disabled.gif" rendered="{!NOT(Con.HasNext)}"/>          
              </apex:outputPanel>

        </apex:pageBlock>

    </apex:form>
</apex:page>


This page will show a input field where you can enter user name to be searched. Now when you click search all user by that name get searched, lets say I search with "Test Test". I have 8 users with that name in my organisation. 5 record will be shown at a time on screen, it will be displayed like this.





When we click "Next Page" next 5 records will be displayed, in this case 3 records. Screen will come up like this.





Apex Code :
public class pagingControllerForUser
{
    public List<User> AllSearchUsers
    {
        get
        {
            if(con != null)
                return (List<User>)con.getRecords();
            else
                return null ;
        }
        set;}
    
    public User usr {get; set;}
    
    //Controller
    public pagingControllerForUser()
    {
        AllSearchUsers = new List<User>() ;
        usr = new User() ;
    }
    
     public PageReference Search()
    {   
        if(usr.Name != null)
        {
            con = new ApexPages.StandardSetController(Database.getQueryLocator([select Id , name , email , phone, Department from User where name = :usr.Name]));
 
            // sets the number of records in each page set
            con.setPageSize(5);
        }
        else
        {
            con = null;
        }
        return null ;
    }
    
    //Instantiate the StandardSetController
    public ApexPages.StandardSetController con{get; set;}
    
    //Boolean to check if there are more records after the present displaying records
    public Boolean hasNext
    {
        get
        {
            return con.getHasNext();
        }
        set;
    }
 
    //Boolean to check if there are more records before the present displaying records
    public Boolean hasPrevious
    {
        get
        {
            return con.getHasPrevious();
        }
        set;
    }
 
    //Page number of the current displaying records
    public Integer pageNumber
    {
        get
        {
            return con.getPageNumber();
        }
        set;
    }

    //Returns the previous page of records
    public void previous()
    {
        con.previous();
    }
 
    //Returns the next page of records
    public void next()
    {
        con.next();
    }
}


Any query about this is welcomed.


Cheers