Friday, September 17, 2010

How to edit records by selecting checkboxes?

Hi,

Create a VF page 
This page contains list of contacts.
By default these records are not editable.
Each record has a checkbox.
If user clicks on a checkbox, then corresponding record will become editable.
User can modify that reocrd
Like that user can select multiple records and can modify them.
After changes, save all only those records which are editable. 
After saving the records refresh page and display updated record.
All checkboxes now should become unchecked.

Read and Insert records from a CSV file - Using Visualforce

The Apex Data Loader is always there when you want to insert records into Salesforce from a CSV file. But, just in case if you don't want your users to install the Apex Data Loader and learn how to use it, then here is a simple example which tells you how to do the same using Visualforce.

Click here to view the demo.


Step 1:

Download the template from the DEMO URL above. Save the file in your desktop. Upload the file into Static Resources with the name "AccountUploadTemplate".

Step 2:

Create an Apex Class named "FileUploader". Paste the code below and save it.



public class FileUploader 
{
    public string nameFile{get;set;}
    public Blob contentFile{get;set;}
    String[] filelines = new String[]{};
    List<Account> accstoupload;
    
    public Pagereference ReadFile()
    {
        nameFile=contentFile.toString();
        filelines = nameFile.split('\n');
        accstoupload = new List<Account>();
        for (Integer i=1;i<filelines.size();i++)
        {
            String[] inputvalues = new String[]{};
            inputvalues = filelines[i].split(',');
            
            Account a = new Account();
            a.Name = inputvalues[0];
            a.ShippingStreet = inputvalues[1];       
            a.ShippingCity = inputvalues[2];
            a.ShippingState = inputvalues[3];
            a.ShippingPostalCode = inputvalues[4];
            a.ShippingCountry = inputvalues[5];

            accstoupload.add(a);
        }
        try{
        insert accstoupload;
        }
        catch (Exception e)
        {
            ApexPages.Message errormsg = new ApexPages.Message(ApexPages.severity.ERROR,'An error has occured. Please check the template or try again later');
            ApexPages.addMessage(errormsg);
        }    
        return null;
    }
    
    public List<Account> getuploadedAccounts()
    {
        if (accstoupload!= NULL)
            if (accstoupload.size() > 0)
                return accstoupload;
            else
                return null;                    
        else
            return null;
    }            
}

Step 3:

Create a Visualforce Page named "UploadAccounts". Paste the code below and save it.


<apex:page sidebar="false" controller="FileUploader">
   <apex:form >
      <apex:sectionHeader title="Upload data from CSV file"/>
      <apex:pagemessages />
      <apex:pageBlock >
             <center>
              <apex:inputFile value="{!contentFile}" filename="{!nameFile}" /> <apex:commandButton action="{!ReadFile}" value="Upload File" id="theButton" style="width:70px;"/>
              <br/> <br/> <font color="red"> <b>Note: Please use the standard template to upload Accounts. <a href="{!URLFOR($Resource.AccountUploadTemplate)}" target="_blank"> Click here </a> to download the template. </b> </font>
             </center>  
      
      
      <apex:pageblocktable value="{!uploadedAccounts}" var="acc" rendered="{!NOT(ISNULL(uploadedAccounts))}">
          <apex:column headerValue="Account Name">
              <apex:outputField value="{!acc.Name}"/>
          </apex:column>
          <apex:column headerValue="Shipping Street">
              <apex:outputField value="{!acc.ShippingStreet}"/>
          </apex:column>
          <apex:column headerValue="Shipping City">
              <apex:outputField value="{!acc.ShippingCity}"/>
          </apex:column>
          <apex:column headerValue="Shipping State">
              <apex:outputField value="{!acc.ShippingState}"/>
          </apex:column>
          <apex:column headerValue="Shipping Postal Code">
              <apex:outputField value="{!acc.ShippingPostalCode}"/>
          </apex:column>
          <apex:column headerValue="Shipping Country">
              <apex:outputField value="{!acc.ShippingCountry}"/>
          </apex:column>
      </apex:pageblocktable> 
      
      </apex:pageBlock>       
   </apex:form>   
</apex:page>



Screenshot:

Some pointers:
  • You can use only the standard template. Because, that's how we have done the mapping to the columns in excel and the fields in Salesforce. You can modify the mapping and use your own template.
  • Allowing the user to choose his own mapping is possible i believe, but may be a bit complex.
  • Also, we use a CSV file. So, you may have to use additional criteria if your data values itself have a comma in them (For ex: Billing Street = 'Mumbai, India ') . This would cause problems because Mumbai and India would be considered as seperate values because of the comma in between them.

Inline Google Maps using Visualforce

Sometime ago we’ve seen how to integrate Google Maps in a Salesforce.com page to pinpoint a specific address on the map, more precisely, how to add an inline map to pinpoint an Account Billing Address. I revisited the script I wrote more than a year ago and produced it as a Visualforce page, here’s the result.

The finished product

Here’s a screenshot of what we are going to get:
Inline Google Maps using Visualforce

 

Improvements

  • I’m now using Google Maps API v3, which makes the map faster to load and doesn’t require an API key anymore.
  • I removed the search term {!Account.BillingState}, so the script should now correctly map any address, not only US ones.
  • It degrades nicely if the Account Billing Address isn’t found, as shown below:

Setup

Follow the 3 steps below:
  1. In Salesforce.com, navigate to Setup > Customize > Develop > Pages and create a new Visualforce Page with the following code:
     



     <apex:page standardController="Account">
    
    <head>
    
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> 
    <script type="text/javascript"> 
    
    $(document).ready(function() {
      
      var myOptions = {
        zoom: 15,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        mapTypeControl: false
      }
      
      var map;
      var marker;
      
      var geocoder = new google.maps.Geocoder();
      var address = "{!Account.BillingStreet}, " + "{!Account.BillingCity}, " + "{!Account.BillingPostalCode}, " + "{!Account.BillingCountry}";
      
      var infowindow = new google.maps.InfoWindow({
        content: "<b>{!Account.Name}</b><br>{!Account.BillingStreet}<br>{!Account.BillingCity}, {!Account.BillingPostalCode}<br>{!Account.BillingCountry}"
      });
    
      geocoder.geocode( { address: address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK && results.length) {
          if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
          
            //create map
            map = new google.maps.Map(document.getElementById("map"), myOptions);
          
            //center map
            map.setCenter(results[0].geometry.location);
            
            //create marker
            marker = new google.maps.Marker({
                position: results[0].geometry.location,
                map: map,
                title: "{!Account.Name}"
            });
            
            //add listeners
            google.maps.event.addListener(marker, 'click', function() {
              infowindow.open(map,marker);
            });
            google.maps.event.addListener(infowindow, 'closeclick', function() {
              map.setCenter(marker.getPosition()); 
            });
            
          }
          
        } else {
          $('#map').css({'height' : '15px'});
          $('#map').html("Oops! {!Account.Name}'s billing address could not be found, please make sure the address is correct.");
          resizeIframe();
        }
      });
      
      function resizeIframe() {
        var me = window.name;
        if (me) {
          var iframes = parent.document.getElementsByName(me);
          if (iframes && iframes.length == 1) {
            height = document.body.offsetHeight;
            iframes[0].style.height = height + "px";
          }
        }
      }
      
    });
    </script>
    
    <style>
    #map {
      font-family: Arial;
      font-size:12px;
      line-height:normal !important;
      height:250px;
      background:transparent;
    }
    </style>
    
    </head>
     
    <body>
    <div id="map"></div> 
    </body> 
    </apex:page>
    

    Add the Visualforce page on the Account page layout (in a single-column section) and set it’s height to be 250px.
  2. All done! :) Navigate to one of your Account records and verify the map is displaying correctly!
Let me know if you have any questions/comments!

Passing parameters to a visualforce page and between pages

Many a times you would want to pass parameters to a visualforce page..

Well, there are two situations in which you would want this.. One is when you want to pass parameters on the click of a custom button.. Other is when you want to pass parameters from one visualforce page to another....

Situation 1
You will see that when you create a custom button and select the source as visualforce page you would see only the page selection and no other option... Well there is a work around for this..

Select the content source as URL and not visualforce... Then you can type the URL as \apex\yourpage.. And what more you can now pass as many parameters as you need using merge fields... There is one more advantage in this method.. You are not forced to use a standard controller with an extension just for your page to appear in the list when you actually do not need a standard controller..



Situation 2
When you want to pass parameters between visualforce pages use the <apex:param> tag....

Here is a small sample program

Step 1: First we create a Visualforce page called SamplePage1....

<apex:page >
<apex:outputlink value="/apex/SamplePage2"> Click Here <apex:param name="msg" value="success"/> </apex:outputlink>
</apex:page>



Step 2: Save this page and now click on " Click Here" link. You will see that when you click on the link you will navigate to a new page called SamplePage2. Check the URL now..


https://na5.salesforce.com/apex/SamplePage2?msg=success&msg2=Story...

You can see that the parameter " msg" with value "success" has been passed to the new page.


Now, how will you retrieve this value in your APEX CLASS for processing.... see below....


Step3: We will put the following code in our SamplePage2

<apex:page controller="Sampleclass"> </apex:page>


The Apex Class code would be


public class Sampleclass
{
Public String message = System.currentPagereference().getParameters().get('msg'); 
Public String message = System.currentPagereference().getParameters().get('msg2');  
}



So now, the variable "message" would store the value of your parameter "msg"....


TEST Method?????


public class Sampleclass
{
Public String message = System.currentPagereference().getParameters().get('msg');
public static testmethod void SampleclassTest()
{
System.currentPagereference().getParameters().put('msg','success');
}
}



And at last some suggestions...


Be careful with the values you pass in the URL.. Special Characters will cause problems
when passed in the URL.. For ex if you pass the Account Name "Shah & shah".. this would'nt
pass properly as the special character "&" cant get into the URL..



So as a best practice always pass ID's.. you can write a query and retrieve any other field
in the APEX Class


Wednesday, September 15, 2010

Checkbox in DataTable

Displaying the check box in a data table or page block table is a general requirement in every project. with the help of wrapper class we can display the checkboxes in a data table (Which Fetches the records automatically on check box selected). For the select all checkbox we need to add small javascript so that if we select the header checkbox it will select all the checkboxes.
Please watch the below figure for details.

Image:Checkbox_in_DataTable.PNG


Page Code as follows:

<apex:page controller="Checkbox_Class" Tabstyle="Account">
<apex:form>
 
<apex:pageBlock Title="Accounts with CheckBoxes">
<apex:pageBlockSection Title="List of Available Accounts">
<apex:dataTable value="{!accounts}" var="a" columnswidth="50px,50px" cellpadding="4" border="1">
<apex:column >
<apex:facet name="header"> <apex:inputCheckbox >
<apex:actionSupport event="onclick" action="{!GetSelected}" onsubmit="checkAll(this)" rerender="Selected_PBS"/>
</apex:inputCheckbox></apex:facet>
<apex:inputCheckbox value="{!a.selected}" id="checkedone">
<apex:actionSupport event="onclick" action="{!GetSelected}" rerender="Selected_PBS"/>
</apex:inputCheckbox></apex:column>
<apex:column headervalue="Account Name" value="{!a.acc.Name}" />
<apex:column headervalue="Account Number" value="{!a.acc.AccountNumber}" />
<apex:column headervalue="Phone" value="{!a.acc.Phone}" />
</apex:dataTable>
</apex:pageBlockSection>

<apex:pageBlockSection Title="Selected Accounts" id="Selected_PBS">
<apex:dataTable value="{!SelectedAccounts}" var="s" columnswidth="50px,50px" cellpadding="4" border="1">
<apex:column headervalue="Account Name" value="{!s.Name}" />
<apex:column headervalue="Account Number" value="{!s.AccountNumber}" />
<apex:column headervalue="Phone" value="{!s.Phone}" />
</apex:dataTable>
</apex:pageBlockSection>

</apex:pageBlock>
</apex:form>
<script>
function checkAll(cb)
{
var inputElem = document.getElementsByTagName("input");
for(var i=0; i<inputElem.length; i++)
{
if(inputElem[i].id.indexOf("checkedone")!=-1)
inputElem[i].checked = cb.checked;
}
}    
</script>
</apex:page> 

Controller Code is:

public class Checkbox_Class 
{ 
    List<accountwrapper> accountList = new List<accountwrapper>();
    List<Account> selectedAccounts = new List<Account>();
        
    public List<accountwrapper> getAccounts()
    {
        for(Account a : [select Id, Name, AccountNumber, Phone from Account limit 5])
        accountList.add(new accountwrapper(a));
        return accountList;
    }
    
    public PageReference getSelected()
    {
        selectedAccounts.clear();
        for(accountwrapper accwrapper : accountList)
        if(accwrapper.selected == true)
        selectedAccounts.add(accwrapper.acc);
        return null;
    }
    
    public List<Account> GetSelectedAccounts()
    {
        if(selectedAccounts.size()>0)
        return selectedAccounts;
        else
        return null;
    }    
    
    public class accountwrapper
    {
        public Account acc{get; set;}
        public Boolean selected {get; set;}
        public accountwrapper(Account a)
        {
            acc = a;
            selected = false;
        }
    }
} 

 Cheers!!!