Tuesday, 20 January 2015

'Regex too complicated’ error for large volume of data


I saw Regex too complicated issue in batch process when I was process large string data like csv file data importing.

After my finding I analysis that  in such a case we need to use Iterable<string> in batch process. After that I am able to process large data in batch there was not a such error.

In that case I was created a custom Iterable class. As I had been mention in another blog.


http://solution401.blogspot.in/2014/10/csv-file-data-process-in-salesforce-apex.html




component controller communication in salesforce

public with sharing virtual class PageBaseController
{
    protected string lookUpSelectedValue{get;set;}
    public LookUpListUtil component{get;set;}
 
    public virtual void onValuechange(string SelectedLookUp)
    {
        /******
            On change event of pick list.
            If you want to create component picklist change event on page.
            Then overight this method on page (onValuechange)
        ************/
    }
 
    public void SetLookUpSelectedValue(string val)
    {
        lookUpSelectedValue=component.lookUpSelectedValue;
    }
 
}



// Custom controller for lookup control. 

public with sharing class LookUpListUtil 
{
    public PageBaseController pageController{get;
        set
        {
            if(value!=null)
                pageController=value;
                pageController.component=this;
         }
    }
    
    public string ObjectType{get;set;}
    public string objectField{get;set;}
    public string groupBy{get;set;}
    
    public List<selectOption> LookUpDataList{get; private set;}
    
    public string lookUpSelectedValue{get;set;}
    public sobject objAssignTo{get;set ;}
    public string AssignToField{get;set;}
    public LookUpListUtil()
    {
        LookUpDataList=new  List<selectOption>();
        //TODO : testing use only need to remove line no 22 to 29
        if(ObjectType==null)
        {
            ObjectType='Account';
            objectField='name';
          groupBy='Type';
        }
        
        try
        {
            string soqlQuery;
            if(groupBy=='')
                soqlQuery='SELECT ID,'+objectField+' FROM '+ type.forname(ObjectType).getName();
            else 
                soqlQuery='SELECT ID,'+objectField+','+ groupBy+' FROM '+ type.forname(ObjectType).getName()+' ORDER BY '+groupBy;
             string itemVal;
                for(sobject obj:DataBase.query(soqlQuery))
                {
                    if(groupBy=='')
                        LookUpDataList.Add(new selectOption(string.ValueOf(obj.get('id')),string.Valueof(obj.get(objectField))));
                    else
                    {
                       itemVal=string.Valueof(obj.get(groupBy))+'_'+string.Valueof(obj.get(objectField));
                       LookUpDataList.Add(new selectOption(string.ValueOf(obj.get('id')),itemVal));
                    }
                }
             
         }
         catch(exception ex)
         {
              apexPages.AddMessage(new apexPages.Message(ApexPages.severity.Error,'Can\'t able to fetch data in PickList. There is an issue. '+ex.getmessage()));
         }
        
        //return ReturnList;
    }
    
    public virtual void onValuechange()
    {
        //objAssignTo=lookUpSelectedValue;
        objAssignTo.put(AssignToField,lookUpSelectedValue);
        pageController.onValuechange(lookUpSelectedValue);
        pageController.SetLookUpSelectedValue(lookUpSelectedValue);
    }

  
    public string GetSelectedValue()
    {
        return this.lookUpSelectedValue;
    }
}





<apex:component controller="LookUpListUtil">
  <!-- Begin Default Content REMOVE THIS -->
  <apex:includeScript value="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" />
<apex:attribute type="string" assignTo="{!ObjectType}" name="LookUpObject" description="type of sobject." required="true"/>
<apex:attribute type="string" assignTo="{!objectField}" default="name" name="FieldName" description="Which field value you want to show on ui"/>
<apex:attribute type="PageBaseController" assignTo="{!pageController}"  name="Controller" description="Which field value you want to show on ui" required="true"/>
 <apex:attribute type="sobject" assignTo="{!objAssignTo}" name="AssignTo" description="Assign selected value" required="true" />
  <apex:attribute type="string" assignTo="{!AssignToField}" name="AssignToFieldname" description="Assign selected value" required="true" />
  
    <apex:selectList id="LookUpControl" value="{!lookUpSelectedValue}"    size="1" multiselect="false" >
        <apex:selectOption itemValue="" itemLabel="--Please Select--"/>
        <apex:selectoptions value="{!LookUpDataList}" >
    
    </apex:selectoptions>
 <apex:actionSupport event="onchange"  action="{!onValuechange}" rerender="sdf" />
</apex:selectList>

<script>
   
    jQuery.noConflict();

    (function (componentName) {
        // get a reference to the select component in the page
        var selectList = jQuery('[id="' + componentName + '"]');

        // a javascript object to collect the elements in each region
        var regions = {};

        // iterate all of the options and collect them by region
        jQuery('option', selectList).each(function (i) {
            if (i === 0) {
                return; // skip the first element in the list
            }
            var oElement = jQuery(this);
            var regionCountryArray = oElement.text().split('_');

            // create an array entry for the region name if there is not one
            if (!regions[regionCountryArray[0]]) {
                regions[regionCountryArray[0]] = [];
            }

            // add the item to the array for this region
            regions[regionCountryArray[0]].push(oElement);
        });

        // iterate all of the names in the regions object
        for (var region in regions) {

            // make sure the name did not come from the prototype
            if (regions.hasOwnProperty(region)) {

                // turn the array of items into a single jQuery collection
                var groupElements = jQuery(regions[region]).map(function () {
                    return this.toArray();
                });

                // create the group and set the label
                var optgroup = jQuery('<optgroup/>');
                optgroup.attr('label', region);

                // wrap the option elements in an optgroup
                groupElements.wrapAll(optgroup);

                // remove the region text from the label
                groupElements.each(function () {
                    jQuery(this).text(function () {
                        return jQuery(this).text().replace(region + '_', '');
                    });
                });
            }
        }
    })('{!$Component.LookUpControl}'); // immediate function execution - pass in the id of the select list
</script>
</apex:component>







public with sharing class LookUpListUtilTestPagecontroller extends PageBaseController
{
    /****** lookUpSelectedValue containing current selected value of pickList ***/
    public LookUpListUtilTestPagecontroller ()
    {
        acc=new account();
    }
    public string selectedValue{get;set;}
    public account acc{get;set;}
    public pagereference Button_click()
    {
        
   
       system.assert(false,' value on page'+lookUpSelectedValue + ' acc='+acc.name);
        return null;
    }
    
    public override void onValuechange(string SelectedLookUp)
    {
   //val=get('cntr');
    //insert 
      // system.assert(false,' value on page'+lookUpSelectedValue);
      
      
    }
    public LookUpListUtilTestPagecontroller GetThis(){ return this;}
}







<apex:page controller="LookUpListUtilTestPagecontroller" >
  <!-- Begin Default Content REMOVE THIS -->
  <h1>Congratulations</h1>
  <br/> <br/>
  <apex:form >
  <c:LookUp LookUpObject="Account" Controller="{!this}" AssignTo="{!acc}" AssignToFieldname="name"/>
  
  <br/>
   
  <apex:commandButton action="{!Button_click}" title="Button" style="width:50px;"  value="Page Btn"> </apex:commandButton>
</apex:form>
  This is your new Page
  <!-- End Default Content REMOVE THIS -->
</apex:page>

Wednesday, 22 October 2014

Create Dynamically File And Attach In Mail Using Apex (Salesforce)



Here I am going to share code to create a run time document in apex code. and then attaching this document (txt file) in mail address.

Below in the code first creating a document then creating a instance of Messaging.EmailFileAttachment class then creating instance of Messaging.SingleEmailMessage class. EmailFileAttachment is used to add attachment in mail.


Document d = new Document();
     d.Name = 'ImportBatchResult';
     String myContent = 'this is a simple data. just testing use only. Right now we are testing the attechment file';
     d.Body = Blob.valueOf(myContent);
     d.ContentType = 'text/plain';
     d.Type = 'txt';
   
     Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
     efa.setFileName('BatchResultLog.txt');
     efa.setBody(d.Body );
   
     String[] toAddresses = new String[] {a.CreatedBy.Email};
     Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
     mail.setToAddresses(toAddresses);
     mail.setFileAttachments(new Messaging.EmailFileAttachment[]{efa} );
 
     mail.setSubject('BatchImport Status: ' + a.Status);
     mail.setPlainTextBody('The batch Apex job processed ' + a.TotalJobItems +
      ' batches with '+ a.NumberOfErrors + ' failures. ExtendedStatus: ' + a.ExtendedStatus);
       
     Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });

Wednesday, 1 October 2014

CSV File Data Import In Salesforce Apex

CSV File Data Import In Salesforce Apex(upload csv).importing data

Here I am going to share some piece of code. Which is use full to import csv file data in salesforce. In my case I need to import bank statement csv file data in custom object. So here I am processing csv data in batch process and inserting in sobject.

Here I am using  Batch process in following manner

 global Iterable<string>  start(Database.BatchableContext BC)
   {
   }

 So I am creating a  CSVIterator class. By using this Process I am not facing 'Regex too complicated’ error for large volume of data.

global with sharing class CSVIterator implements Iterator<string>, Iterable<string>
{
   private String m_CSVData;
   private String m_introValue;
   public CSVIterator(String fileData, String introValue)
   {
      m_CSVData = fileData;
      m_introValue = introValue;
   }
   global Boolean hasNext()
   {
      return m_CSVData.length() > 1 ? true : false;
   }
   global String next()
   {
      String row = m_CSVData.subString(0, m_CSVData.indexOf(m_introValue));
      m_CSVData = m_CSVData.subString(m_CSVData.indexOf(m_introValue) + m_introValue.length(),m_CSVData.length());
      return row;
   }
   global Iterator<string> Iterator()
   {
      return this;
   }
}


HERE I am using Database.Stateful in batch because I don't want to reset static variables in batch process.

 global class UploadBankStatementBatch implements Database.Batchable<string>, Database.Stateful
{

   global final blob dataDocuments;
   id BankAccountId;
   id CompanyId;
   BankStatement__c statement;
   global UploadBankStatementBatch (blob data,id BankAccountId,id CompanyId)
   {
             this.dataDocuments=data;
             this.BankAccountId=BankAccountId;
             this.companyId=companyId;
   }

   global Iterable<string>  start(Database.BatchableContext BC)
   {
       string nameFile=this.dataDocuments.toString();
       List<BankStatementLineItem__c> accstoupload = new List<BankStatementLineItem__c>();
     
        statement=new BankStatement__c();
        statement.name='import'+date.today();
        statement.BankAccountId__c=BankAccountId;
        statement.companyId__c=companyId;
        insert statement;
        system.debug(' Batch started bankStatment new created '+statement.id);
      return new CSVIterator(this.dataDocuments.toString(), '\n');
   }

   global void execute(Database.BatchableContext BC,List<String> scope)
   {
       //integer i=0;
       List<BankStatementLineItem__c> lst=new list<BankStatementLineItem__c>();
        for(String row : scope)
       {

         List<String> fields = row .split(',');
         IF(fields[0]!='*Date')
         {
             BankStatementLineItem__c li=new BankStatementLineItem__c();
         
             li.date__C=date.parse(fields[0]);
             IF(fields[1]!='')
             {
                li.Amount__c=decimal.valueof(fields[1]);
             }ELSE
             {
                li.Amount__c=0;
             }
             li.Payee__c=fields[2];
             li.Description__c=fields[3];
                 li.Status__c='open';
                 li.companyId__c=companyId;
                // li.CompanyId__C='';
                li.BankStatementId__c=statement.id;
              lst.add(li);

              }
       }
       insert lst;

   }

   global void finish(Database.BatchableContext BC){
 
     system.debug(' Batch finish bankStatment new created '+statement.id);
   }

 
 
}




Have a Good Day :)

Friday, 19 September 2014

Data Access On VF Page From Custom Component

                              

In a scenario I was using a custom component on a custom visualforce page. That custom component was containing pick list and populating data from component controller using dynamic soql query.

But the case was that I need to access pick list selected value on page side. I did little bit struggle with it but final get way that is following :-

<apex:component controller="LookUpListUtil">

<apex:attribute type="string" assignTo="{!QueryObject}" name="LookUpObject" description="Pick list data query on which object." required="true"/>

<apex:attribute type="string" assignTo="{!labelField}" default="name" name="label" description="which field of LookUpObject you want to populate in pick list " required="true"/>

<apex:attribute type="sobject" assignTo="{!objAssignTo}" name="AssignToObject" description="Object name on which you want to set selected value of pick list " required="true" />

<apex:attribute type="string" assignTo="{!AssignToField}" name="AssignToFieldname" description="field name of objAssignTo Object on which you want to set selected value of pick list " required="true" />
  
    <apex:selectList id="LookUpControl" value="{!PicklistData()}"    size="1" multiselect="false" >
        <apex:selectOption itemValue="" itemLabel="--Please Select--"/>
        <apex:selectoptions value="{!LookUpDataList}" >
    
    </apex:selectoptions>
 <apex:actionSupport event="onchange"  action="{!onValuechange}" rerender="sdf" />
</apex:selectList>



// Custom controller for lookup control. 

public with sharing class LookUpListUtil 
{
   
    
  
    public string QueryObject{get;set;}
    public string labelField{get;set;}

    public string groupBy{get;set;}
    
    public List<selectOption> LookUpDataList{get; private set;}
    
    public string lookUpSelectedValue{get;set;}
    public sobject objAssignTo{get;set ;}
    public string AssignToField{get;set;}
    
    public new  List<selectOption> GetPicklistData()
    {
        LookUpDataList=new  List<selectOption>();

        try
        {
// fetching to populate in pick list
            string soqlQuery;
            if(groupBy=='')
                soqlQuery='SELECT ID,'+labelField+' FROM '+ type.forname(QueryObject).getName();
            else 
                soqlQuery='SELECT ID,'+labelField+','+ groupBy+' FROM '+ type.forname(QueryObject).getName()+' ORDER BY '+groupBy;
             string itemVal;
                for(sobject obj:DataBase.query(soqlQuery))
                {
                    if(groupBy=='')
                        LookUpDataList.Add(new selectOption(string.ValueOf(obj.get('id')),string.Valueof(obj.get(labelField))));
                    else
                    {
                       itemVal=string.Valueof(obj.get(groupBy))+'_'+string.Valueof(obj.get(labelField));
                       LookUpDataList.Add(new selectOption(string.ValueOf(obj.get('id')),itemVal));
                    }
                }
             
         }
         catch(exception ex)
         {
              apexPages.AddMessage(new apexPages.Message(ApexPages.severity.Error,'Can\'t able to fetch data in PickList. There is an issue. '+ex.getmessage()));
         }

    }
    
    public void onValuechange()
    {
try
{
        objAssignTo.put(AssignToField,lookUpSelectedValue);
}
catch(exception ex)
         {
              apexPages.AddMessage(new apexPages.Message(ApexPages.severity.Error, ex.getmessage()));
         }
        
    }

  
   
}


Here I am using parameters in custom component which is objAssignTo  and AssignToField 
objAssignTo  is sobject data type parameters. And updating value in sobject's field. which is passing from vf page. So I am able to access values on vf page from custom component. 


<apex:page controller="LookUpListUtilTestPagecontroller" >


  <br/> <br/>
  <apex:form >
  <c:LookUp LookUpObject="Account" AssignToObject="{!acc}" AssignToFieldname="name" label ="name"/>
  
  <br/>
   
  <apex:commandButton action="{!Button_click}" title="Button" style="width:50px;"  value="Page Btn"> </apex:commandButton>
</apex:form>

</apex:page>




public with sharing class LookUpListUtilTestPagecontroller 
{
    public LookUpListUtilTestPagecontroller ()
    {
        acc=new account();
    }

    public account acc{get;set;}

    public pagereference Button_click()
    {
        
   
       system.assert(false,' Selected value is ='+acc.name);
        return null;
    }
    
  
    public LookUpListUtilTestPagecontroller GetThis(){ return this;}
}




Wednesday, 10 September 2014

ForURL() Method On VisaulForce page

                                      URLFOR()  Method

URLFOR() method is use to access the url in visualforce page with respect to passed method parameter's.

Here I am going to demonstrate for URLFOR method with some scenario . Some time we have requirement to redirect on page,redirect on action of particular object, perform a action with return url and access a resources.

1. Access css from zipfile resource.

                   <apex:stylesheet value="{!URLFOR($Resource.Bootstrap,'bootstrap-3.2.0-dist/css/bootstrap.min.css')}"/>

2. Access css file resource.
                   <apex:stylesheet value="{!URLFOR($Resource.Bootstrap)}"/>     

3. Redirect on customPage.

                 <a href="{!URLFOR($Page.SetUp)}">Accounting Hub</a>

4.  Redirect on Action.
               <a tabindex="-1" href="{!URLFOR($action.BankAccount__c.New,$ObjectType.BankAccount__c)}">Bank Account</a>.

5.  Redirect on page with return url.

                <apex:commandButton action="{!URLFOR($Action.Account.view, ID, [retURL=myRet])}" value="New Opportunity" id="theButton"/>
           



Tuesday, 9 September 2014

Mini Page Layout Using Apex Code


Suppose to we need to show a salesforce mini page layout on link tag in VF page. Here I showing some line of code which will be responsible to show a mini page layout.

e.g.

    <a href=”/{!acc.Id}” id=”{!acc.Id}” onblur=”LookupHoverDetail.getHover(‘{!acc.Id}’).hide();” onfocus=”LookupHoverDetail.getHover(‘{!acc.Id}’, ‘/{!acc.Id}/m?retURL=%2F{!acc.Id}&isAjaxRequest=1′).show();” onmouseout=”LookupHoverDetail.getHover(‘{!acc.Id}’).hide();” onmouseover=”LookupHoverDetail.getHover(‘{!acc.Id}’, ‘/{!acc.Id}/m?retURL=%2F{!acc.Id}&isAjaxRequest=1′).show();”>{!acc.Name}</a>


In above the code LookupHoverDetail.getHover().hide() and LookupHoverDetail.getHover().show() these method will show and hide mini page layout.

Here I am showing pagelayout onfocus and onMousOver on link. and hiding on onblur and onmouseout();