Friday, September 17, 2010

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.

2 comments:

  1. Actuvally i completed the csv file uploading. but test case is 61% covered my application.any help with me. my test case code is
    @isTest(SeeAllData=true)
    public class FileUploader_TestMethod

    {
    //public static Blob contentFile{get;set;}
    //public static string nameFiles{get;set;}
    //static String[] filelines = new String[]{};
    static Account ac;
    static List accstoupload=new List();

    public static testMethod void TestCase() {

    {
    Test.startTest();
    ac=new Account();ac.Name='rakuten12345';
    insert ac;
    String resourceName = 'Csvfiles';






    StaticResource defaultResource = [Select id,name,Body From StaticResource where Name='Csvfiles'];
    Blob content= defaultResource.Body;
    String myCSVFile = defaultResource .Body.toString();
    System.debug('myCSVFile = ' + myCSVFile);
    FBR_FileUploader file=new FBR_FileUploader();

    file.contentFile = content;
    file.ReadFile();
    file.getuploadedAccounts();



    file.nameFiles=content.toString();

    String nameFiles= content.toString();


    String[] filelines = nameFiles.split('\n');

    accstoupload=new List();

    for(Integer i=1;i<filelines.size();i++)
    {
    String[] inputvalues = new String[]{};
    inputvalues = filelines[i].split(',');
    WorkMonthly__c a = new WorkMonthly__c ();
    a.Name = 'rakuten';
    a.Unit__c= 'ten';
    a.Date__c= System.today();
    a.ImportCount__c= double.valueOf('15');
    a.Account_Name__c = ac.id;

    accstoupload.add(a);
    try{

    insert accstoupload;


    System.assertEquals(1,accstoupload.size());
    Test.stopTest();
    }
    catch (Exception e)
    {
    ApexPages.Message errormsg = new ApexPages.Message(ApexPages.severity.ERROR,'An error has occured. Please check the template');
    ApexPages.addMessage(errormsg);
    }
    }
    }
    }
    }

    ReplyDelete