Thursday, November 24, 2011

Start working with Command Line Data Loader in 5 minutes, Cheers!!

About Cliq(CLI Quickstart):
CLIq provides a simple wizard to create directory structures and configuration files for the Salesforce Data Loader Command Line Interface. You can spend hours configuring the CLI manually, or use CLIq and you will have a working configuration in less than 5 minutes. After creating a CLIq configuration, you can reference the Data Loader documentation and make adjustments as needed.


Installation Instructions: 
  1. Install GUI version of Apex data loader in a directory other than program files(Actually, windows7 does not let you create any files in the data loader directory in program files).
  2. Make sure you have JRE installed.
  3. Extract the zip file from the above link and paste the folder in the data loader installation directory.
  4. Execute Cliq.bat to run Cliq!!

How to use: 
Login with your salesforce.com username, password + security token.
If you face any issues while logging in, try changing the following in cliq.properties file in Cliq directory:
(remember you have to replace the version of your data loader you are using)
sfdc.endpoint=https://www.salesforce.com/services/Soap/u/21.0
sfdc.endpoint=https://login.salesforce.com/services/Soap/u/21.0  (for production)
sfdc.endpoint=https://test.salesforce.com/services/Soap/u/21.0    (for sandbox)


  
Select the operation and enter the name of the process. Cliq will create various directories(Config, read, write and log) in this folder named as "cliq_process" under GUI data loaders parent dir.





Select the object(for example, if you have selected Insert operation)



Click on "Create Data Loader CLI Files". If you have given the process name as "InsertProcess_" in step2 then you will find a dir named as "InsertProcess_" and a batch file(.bat) of the same name within that directory. Double click on it and you are done!






You can change the various values and parameters in process-conf.xml created in the "config" dir in "InsertProcess_" dir.


Try it and let me know how you feel after using it.

 

Monday, November 21, 2011

Where to download all versions of ApexDataLoader?


Here is an archive of all versions of Apex Data Loader. So for anyone having issues with any of the versions of data loader, they can download a different version and investigate.

All thanks to Cloud Success :)





Saturday, November 19, 2011

Custom Pagination in Visualforce made eady

This was an assignment given by one of my friend on Nov 12th, 2011. I thought it was an easy task, just making a visual force page with pagination it, but to my surprise, it was not -:(

So, here is the objective, putting it in exact words of my dear friend:

“You have accounts and a number of opportunities at different stages are associated to them. You have to design an inline Visualforce page on account detail page that shows a dropdown containing various opportunity stages. When user selects any of the listed stage, the PageBlockTable should show the all the Opportunities with the selected stage.”

This was the basic requirement, now comes the tough part:
      1. It should also use the pagination with first, last, previous, next and page size options.
      2. It should also use sorting and the entire functionality should be ajaxified.

I started designing the page and finished the basic functionality in 2 hours. Then came the pagination part for which I knew I cannot use standard list controllers, so I decided to use a custom class, SObjectPaginator from the package Apex-lang(http://code.google.com/p/apex-lang/). All thanks to Richard Vanhook for developing Apex-lang and making our lives easier.

It’s very easy to use to SObjectPaginator, you just need to implement the interface and the method handlePageChange(List newPage) and call the SObjectPaginator.setRecords(List) to set the records in pagination.

Solution: Here is the screenshot of what came out after 8 hours of hard work.

Inline visualforce page on account detail page




The Visualforce Page:
<apex:page standardController="Account" extensions="OpportunityOnAccountDetailExtension">
  <apex:form >
    <apex:pageBlock mode="edit" >
      <apex:pageBlockSection columns="1">
         <apex:outputText >
           <B>Select an Opportunity stage to view opportunities related to this account:</B>
         </apex:outputText>
         
   <apex:actionRegion >
            <apex:selectList size="1" multiselect="false" value="{!selectedStage}"  >
                <apex:selectOptions value="{!Items}"  />
                   <apex:actionSupport event="onchange"
                            action="{!handleAccountSelected}"
                            rerender="pbs1"
                            status="status"/ >
            </apex:selectList>
         </apex:actionRegion>
      </apex:PageBlockSection>
      
 <apex:pageBlockSection columns="1" id="pbs1">
      <apex:actionstatus id="status" startText="testing...">
        <apex:facet name="stop">
           Opportunity Stage Selected: <apex:outputText value="{!selectedStage}" />
    
  <apex:pageBlockTable value="{!accounts}" var="opp" id="pb1">
            <apex:column value="{!opp.obj.name}" />
            <apex:column value="{!opp.obj.StageName}" />
            <apex:column value="{!opp.obj.Amount}" />
            <apex:column value="{!opp.obj.CloseDate}" />                        
                    
            <apex:facet name="footer">
              <apex:outputPanel layout="block">
 
    <!-- PAGE X OF X IN X RESULTS -->
                Page {!IF(paginator.pageCount=0, 0, paginator.pageNumberDisplayFriendly)} of {!paginator.pageCount} in {!paginator.recordCount} results
                &nbsp;&nbsp;       
                
    <!-- FIRST --> 
                <apex:outputText value="First"
                                 rendered="{!NOT(paginator.hasPrevious)}" />
                    <apex:commandLink value="First"
                                      rendered="{!paginator.hasPrevious}"
                                      action="{!paginator.first}" />
                &nbsp;&nbsp;
                                    
     <!-- PREVIOUS -->    
                <apex:outputText value="Previous"
                                 rendered="{!NOT(paginator.hasPrevious)}" />
                    <apex:commandLink value="Previous"
                                      rendered="{!paginator.hasPrevious}"
                                      action="{!paginator.previous}" />
                &nbsp;&nbsp;
                                            
     <!-- PAGE SHORTCUTS -->
    <apex:repeat value="{!paginator.previousSkipPageNumbers}" var="skipPageNumber">
                    <apex:outputPanel >
                        <apex:commandLink value="{!skipPageNumber+1}" action="{!skipToPage}">
                           <apex:param name="pageNumber" id="pageNumber" value="{!skipPageNumber}" assignto="{!pageNumber}" />
                        </apex:commandLink>
              
           </apex:outputPanel>
                &nbsp;&nbsp;
                </apex:repeat>
                
    <apex:outputText style="text-decoration:none; font-weight:bold; background-color: #FFFF00"
                                 value="{!paginator.pageNumber+1}"/>
                &nbsp;&nbsp;
                <apex:repeat value="{!paginator.nextSkipPageNumbers}" var="skipPageNumber">
                    <apex:outputPanel >
                    <apex:commandLink value="{!skipPageNumber+1}" action="{!skipToPage}">
                       <apex:param name="pageNumber" id="pageNumber" value="{!skipPageNumber}" assignto="{!pageNumber}" />
                    </apex:commandLink>
                    </apex:outputPanel>
                &nbsp;&nbsp;
                </apex:repeat>
                                               
    <!-- NEXT -->
                <apex:outputText value="Next"
                                 rendered="{!NOT(paginator.hasNext)}" />
                    <apex:commandLink value="Next"
                                      rendered="{!paginator.hasNext}"
                                      action="{!paginator.next}" />
                &nbsp;&nbsp;
                                                      
    <!-- LAST -->
                <apex:outputText value="Last"
                                 rendered="{!NOT(paginator.hasNext)}" />
                    <apex:commandLink value="Last"
                                      rendered="{!paginator.hasNext}"
                                      action="{!paginator.last}" />
                &nbsp;&nbsp;
                                                                 
     <!-- Page Size Options -->
                Page Size:
                  <apex:actionRegion >
                    <apex:selectList value="{!paginator.pageSize}"
                                     size="1">
                      <apex:selectOptions value="{!paginator.pageSizeOptions}" />
                          <apex:actionSupport event="onchange"
                                              rerender="pbs1"
                                              status="status" />
                    </apex:selectList>
                  </apex:actionRegion>
              </apex:outputPanel>
            </apex:facet>
        </apex:pageBlockTable>
     </apex:facet>
      </apex:actionstatus>
 </apex:PageBlockSection>
 </apex:pageBlock>
 </apex:form>
</apex:page>


The Controller Code:



global class OpportunityOnAccountDetailExtension implements SObjectPaginatorListener {

String selectedStage;
Account acc;
    
    global List accounts   {get;set;}
    global SObjectPaginator paginator  {get;set;} 
    global Integer          pageNumber {get;set;}
    private String sortDirection = 'ASC';
    private String sortExp = 'name';
    
List oppList = new List();

    public OpportunityOnAccountDetailExtension(ApexPages.StandardController controller) {
        this.acc = (Account)controller.getRecord();
        oppList = null;
        this.accounts = new List();
        this.paginator = new SObjectPaginator(
            2,                          //pageSize
            new List{2,5,10, 25, 50, 100, 200},  //pageSizeIntegerOptions
            this                        //listener
        ); 
        //this.paginator.setRecords(getoppList());
        
    }
    
    public String getselectedStage() {
        return selectedStage;
    }
 
    public void setselectedStage(String selectedStage) {
        system.debug('%%%%%%%%%%%% ' + this.selectedStage);
        this.selectedStage = selectedStage;
        system.debug('%%%%%%%%%%%% ' + this.selectedStage);
    }
    
    public List getItems() {
            List options = new List();
            options.add(new SelectOption('','--SELECT Opportunity Stage--'));
            
            Schema.DescribeFieldResult field = Opportunity.StageName.getDescribe();
 
        for (Schema.PicklistEntry f : field.getPicklistValues())
          options.add(new SelectOption(f.getLabel(),f.getLabel()));
          
            return options;
        }
    
    /*    
    public List getoppList(){
        system.debug('$$$$$$$$$$$$$$$$$$ ' + selectedStage);
            if(selectedStage==null){
                oppList  = null;
            }else{
            oppList  = [select name, stageName, Amount, CloseDate from Opportunity where AccountId =: acc.id and StageName =: String.escapeSingleQuotes(selectedStage)];
            }
            
            return oppList;
                
    }
    */
    
   public PageReference handleAccountSelected(){
        system.debug('$$$$$$$$$$ in handleAccountSelected()');
        string sortFullExp = sortExpression  + ' ' + sortDirection;
        string query = 'select name, stageName, Amount, CloseDate from Opportunity where AccountId =';
        query = query + ' ' + acc.id + ' ' + ' ';
        query = query + 'and StageName =' + ' '  + String.escapeSingleQuotes(selectedStage) + ' '+ ' order by ' + sortFullExp;
        system.debug('################## ' + query);
        this.paginator.setRecords([select name, stageName, Amount, CloseDate from Opportunity where AccountId =: acc.id and StageName =: String.escapeSingleQuotes(selectedStage)]);
        
        return null;
    }
    
    
    public PageReference test(){
        return null;
    } 


    global void handlePageChange(List newPage){
        this.accounts.clear();
        if(newPage != null && newPage.size() > 0){
            for(Integer i = 0; i < newPage.size(); i++){
                this.accounts.add(
                    new OppWrapper(
                        (Opportunity)newPage.get(i)
                        , i + this.paginator.pageStartPosition + 1
                    )
                );
            }
        }
    }
    
    
    global PageReference skipToPage(){
        this.paginator.skipToPage(pageNumber);
        return null;
    }
    
       public String sortExpression
   {
     get
     {
        return sortExp;
     }
     set
     {
       //if the column is clicked on then switch between Ascending and Descending modes
       if (value == sortExp)
         sortDirection = (sortDirection == 'ASC')? 'DESC' : 'ASC';
       else
         sortDirection = 'ASC';
       sortExp = value;
     }
   }

 public String getSortDirection()
 {
    //if not column is selected 
    if (sortExpression == null || sortExpression == '')
      return 'ASC';
    else
     return sortDirection;
 }

 public void setSortDirection(String value)
 {  
   sortDirection = value;
 }
 
    
       
    public class OppWrapper{
        
        public Opportunity obj{get;set;}
        public Integer serialNumber{get;set;}
        public Boolean selected{get;set;}
        
        public OppWrapper(Opportunity obj, Integer serialNumber){
            this.obj = obj;
            this.serialNumber = serialNumber;
            system.debug('@@@@@@@@@@@@@@@@ ' + obj.Name);
        }

        
    }
    
    
}