Total Pageviews

Monday, September 17, 2012

Simple Row Counter while using Iterators/ Repeats in Visual Force

A simple way to display serial number in a repeater (Visual Force):-
I have always found it a bit awkward to use either javascript or wrapper class to display serial numbers while using repeaters in apex. Its a basic requirement in any VF UI involving iterators but till now I had been taking the torturous route of "wrapper class" or "Javascript".
In case you too faced the same issue, perhaps the following code snippet will resolves your coding owes and make things easier and simpler for you.
=====================================================
The counter variable used here " rowCtr  " has to be defined as a property in your controller class.

VF Page code snippet using the Iterator (repeater) and the row counter:-
<apex:variable value="{!1}" var="  rowCtr  "/>
<apex:repeat value="{!RepeaterVar}" var="cb">
<tr>
<td>{!FLOOR(  rowCtr  )}</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
<apex:variable var=" rowCtr " value="{!  rowCtr  + 1}"/>
</tr>
</apex:repeat>
Controller Code Snippet:-
public with sharing class TestController {
public integer rowNum;
public integer getrowNum()
{
return rowNum;
}
}
======================================================

Sunday, September 2, 2012

Reading makes you Smarter But Practice makes 1 perfect!!

Well you might say who doesn't know - that its through practice that one achieves perfection. True everyone is aware of that truth- still its worth repeating when one realizes the efficacy of the above statement the hard way ~ through real life incidents.
Now you may say what does that philosophy has to do with salesforce ? This is how it unfolds ... Read on ...
As a rule the salesforce documentation of any function follows the following pattern:-

Function NameArgumentReturn TypeDescription
getContentBlobReturns the output of the page, as displayed to a user in a Web browser. The content of the returned Blob is dependant on how the page is rendered. If the page is rendered as a PDF, it returns the PDF. If the page is not rendered as a PDF, it returns the HTML.
To access the content of the returned HTML as a string, use the toString Blob method.
Note
If you use getContent in a test method, a blank PDF is generated when used with a Visualforce page that is supposed to render as PDF.
This method can't be used in:
Triggers
Scheduled Apex
Batch jobs
Test methods
Apex email services
If there's an error on the Visualforce page, an ExecutionException is thrown.

As a rule any function is defined with a short brief about what is does, arguments it takes and the return type , etc. Also the situations where it may fail is highlighted. This is the area where the practice part gets highlighted - I might have parroted ( act of repeating like a parrot) that many times without realizing the impact of the statement in blue and red. Last weekend I learned the hard way...
As I was trying to provide coverage to a class which refused the budge the 66% mark , I realized my use of the getContent() method in a test method which returned a blank PDF was the culprit and was ideally no way to maneuver that unless I restructured the   class to provide the minimum threshold coverage.
Another classic example would be if your apex code in controllers or triggers have condition which are based on system fields like "Created Date" etc.
Say if I have a query:-
Account[] Acc=[ Select id, name from where createddate< system.today()- 30];
if(Acc.size()>0)
{
..............................
..............................
Some code
}
else
{
Some code

}
Now in the above example if you have not got the editing of system fields activated there is no way you can create back-dated data and hence in such a test method (involving system fields like created data or modified date which works on past data) increasing the coverage or providing appropriate coverage is a challenge !!! Also these points should be kept in mind while designing your classes and trigger logic... hence as I keep on repeating planning before plunging head long into coding is very essential ... planning is like an antacid which prevents future heart burn while coding ...
Also remember it was only when I encountered the actual situation I realized the import of the text in blue above...:)
=============================Additions =============================
This is the flaw with freestyle or freewheel writing . You set off with something in mind but ultimately the final outcome is something else...
I had  thought of writing this piece to highlight some of the issues one encounters with getContent() function.
So here's the gist w.r.t. getContent() method:-
1. We at times use our VF pages rendered as PDF to send out email with PDF attachments. The getContent() method w.r.t. PDF VFs shows inconsistent behavior. So this route is best avoided.
2. Never use getContent() in a scheduler class , it returns empty content. So either HTML content on the fly or get a document generated via some synchronous action and pick that up via scheduler code.

Next blog will be probably on setRedirect attribute of a page and its implications . That reminds me the next one on Conga Merge w.r.t. excels is pending on me .Watch the space ...   

Sunday, June 10, 2012

Conga Composer - A how to do guide for first time users (2) (Basic Use)


In my last blog we went about the process of installation of Conga Composer in your Org from scratch.
Now comes the real thing using Conga Composer for your various reporting and document generation needs.
Once installation is complete you will notice that a button with following particulars has been added to most of the standard/native objects in your org:-
1. Label -Conga Composer
2. Name- Conga_Mail_Merge
Please refer to the screenshot below for clarity:-



With exception of some standards objects the above button is added to all the standard objects. Standard objects in which the above button is not added automatically:-
1. Asset
2. Product
3. Ideas
4. Campaign
5. Campaign Member
6. Task
Now lets analyze this button a bit closely. For that we can investigate the details of this button from the button detail page.


The button URL of the Conga Button is  -  https://www.appextremes.com/apps/Conga/PointMerge.aspx?sessionId={!API.Session_ID}&serverUrl={!API.Partner_Server_URL_80}&id={!Account.Id}
The above is the very basic "Conga Button" which has the following components :-
1. The URL of Conga Server - https://www.appextremes.com/apps/Conga/PointMerge.aspx
2. The parameters which accompany this button viz. 
a. Sessionid - Provides the sessionid of the active salesforce session provided by the global variable -     !API.Session_ID
b. serverURL - This is the URL of the salesforce org which is unique for each org - furnished by -{!API.Partner_Server_URL_80}
c. id - This is the id of the master object through which all the data / information will be fetched.
d. There will be other parameters too like reportid and queryid which we will take up when we dig deeper into queries and reports as a data source.
Now let try to use this button and see what data is returned using the above button - notice the above button is placed on account object hence the data returns will that of the account record corresponding to the id specified in the button URL . Lets put the button on the account detail page layout and navigate to an account record. 








Now lets click on the "Conga Composer" button and see what happens.When we click the button the following screen appears:-

The "View Data" link on the above screen shows you the data which is available for generating document and /or reports.When we click on "View Data" link the available data in the form of an excel is downloaded to your system/ computer . For Clarity refer to the following screenshots.

When you save the excel as prompted by the above screen the following data is shown in the form of an excel. 

In the above screen shot the data of the master object which is available for merge and document generation is shown.


 In the above screen shot the data of the Org  (Like orgid, address,etc) which is available for merge and document generation is shown


 In the above screen shot the data of the Logged-in User  (Like username, address,etc) which is available for merge and document generation is shown

The column headings in the above generated excels is used for creating the word template for creating merge documents. We will dive into "Template Creation" in my next blog in this series.




  


Saturday, June 2, 2012

Conga Composer - A how to do guide for first time users

What is Conga Composer?
As per the Official Site of Conga Composer - Conga Composer is the most popular document generation and reporting solution for Salesforce. With Conga Composer, Salesforce user and administrators are more productive, more in control, and more effective with everything they do.
Very truly so it provides the flexibility which at times is not available when using Salesforce's standard mail merge functionality. The data which one can pull out with Conga is incredible
The positives of using Conga are innumerable:-
1. Huge data set is at one's disposal
2. One can summarize data
3. Write complex queries for deriving data in a particular condition
4. Since one can upload a wide variety of documents created using word and excel so all the formatting richness provided by MS office can also be availed of in Conga.
5. Rapid report generation ( Though there is an initial learning curve)
So far so good but if you are using Conga for the first time the ride is bit bumpy and hence I will try to pen a route which will prove to be less hassle-some,but  that at no point means that the documentation provided by Conga is not good - its excellent. Its just that we humans are a bit lazy by nature and prefer quick-fix recipes ( at least I fall in that category at times) .
Hence let me put together what needs to be done from scratch to get Conga Up and running.
The steps for preparing (Having all the Packages installed for generating documents with Conga) the salesforce org are as follows:-
1. You need to go to AppExchange  - https://sites.secure.force.com/appexchange/homeSearch for "Conga". In the search results click for the app named "Conga Composer" . Alternatively just use the following link:-
https://sites.secure.force.com/appexchange/listingDetail?listingId=a0N300000016b7FEAQ

2. Now since you have found the Conga App - click on the "get It now" button. Follow the wizard . If you already have a salesforce org click the options a) that you have a salesforce account b) you are the administrator  c) you want to install Conga in your existing production org (which may be your developer org too). You may change responses depending upon what you want to do.

3.Once you provide the credentials of the org where you want to install Conga you will be redirected to page which provides information about the application being installed and  the details of the org provided by you. Refer to the attached screenshot for clarity:-
Click on the install button to complete the installation and follow the installation wizard. Once installation is complete you will see that "Conga Composer" is shown in the drop down of apps in your salesforce org. See the attached diagram for clarity.
4. Once installation is complete and you click on the "All Tabs" you will notice two tabs have been added to your org viz:-
     a. Conga Mail Merge
     b. Conga Templates (v5)
Please refer to the attached screenshot.


5. In order to exploit the full prowess of  "Conga Composer" you will need "Conga Queries" and "Conga Query Manager". In order to find "Query Manager" follow the this link - http://home.appextremes.com/support/ here you will find listings of all the sister products of Conga. Click on "Get it now" linl next to "Conga Query Manager". You will be redirected to the "Salesforce Login Page" . Provide the credentials and follow the "Query Manager Installation" wizard.Refer to the attached screenshot.
Once the installation is complete , click on the "All tabs" again. You will notice another tab by the name "Conga Queries" has been added to your org. Refer to the screenshot for clarity.
Now we have everything ready to dive into "Generation of documents and /or Reporting" using Conga Composer. That we will cover in a follow-up blog of mine. Watch this space for a follow on this one ....







Friday, May 25, 2012

Unit Test Methods - demystified

Unit Test Methods more often than not baffles new converts to salesforce as a platform. Even I had my share of hiccups. This prompted me to pen few simplistic lines on Unit Test Methods and to demystify them. 
I remember once someone in my Team asked me what are Unit Test Methods and I went ahead with a very bookish definition, the enquirer seemed a bit lost in the technical jargon. As I was trying to simplify the gist of my verbal diarrhea on Test Methods another colleague of mine described it as follows - It is something which visits all lines of your code w.r.t. if else statements and/or for loops . Quite simple isnt it?  
But for the sake of structure I will provide both perspective the technical bookish as well as the layman's simplistic version.
Unit Test Methods Defined
To facilitate and promote the development of robust, error-free code, Apex Code requires the creation and execution of unit tests. Unit tests are class methods that verify whether a particular piece of code is working properly. Unit tests are written in Apex Code and annotated with the testMethod keyword .
Why do we need Unit Test Methods
1. We need them for deploying code from either developer account or sandbox  to production.
2. Also in order to package and publish your code on AppExchange you need to provide coverage to your code using Test Methods.
What is coverage?
Test Methods are blocks of code or code statements which visit/passes the code written by you either in triggers or VF page and associated apex classes.
How much code coverage is  needed?
A minimum of 75% has to be covered to one's overall code in one's organization (salesforce instance)
What is the language used?
Its written using Apex.
What is the basic syntax used?
You can either write your Test Methods inline with your code using the "TestMethod" keyword . Alternatively you can group your test methods in Apex classes and use the @isTest keyword to point that the class being defined contains test methods.
Lets discuss these 2 approaches in detail.
  1. Defining a Test Method using the testMethod keyword - Lets assume you have a trigger on Account object.                                                                                                                                                   
    trigger myAccountTrigger on Account(before delete, before insert, after delete, after insert) {
    if (Trigger.isBefore) {
        if (Trigger.isDelete) {
    
            // In a before delete trigger, the trigger accesses the records that will be deleted with the Trigger.old list. 
        
            for (Account a : Trigger.old) {
                if (a.name != 'okToDelete') {
                    a.addError('You can\'t delete this record!');
                } 
            }
        } else {
    
        // In before insert or before update triggers, the trigger accesses the new records with the Trigger.new list. 
        
            for (Account a : Trigger.new) {
                if (a.name == 'bad') {
                    a.name.addError('Bad name');
                }
        }
        if (Trigger.isInsert) {
            for (Account a : Trigger.new) {
                System.assertEquals('xxx', a.accountNumber); 
                System.assertEquals('industry', a.industry); 
                System.assertEquals(100, a.numberofemployees);
                System.assertEquals(100.0, a.annualrevenue);
                a.accountNumber = 'yyy';
            }
    
    // If the trigger is not a before trigger, it must be an after trigger. 
        
    } else {
        if (Trigger.isInsert) {
            List<Contact> contacts = new List<Contact>();
            for (Account a : Trigger.new) {        
                if(a.Name == 'makeContact') {
                    contacts.add(new Contact (LastName = a.Name,
                                              AccountId = a.Id));
                }
            } 
          insert contacts;
        }
      }                                                                      }}}  
    
           Now in the above trigger you will notice that a) before insert b) before delete and c) after insert are being handled . So what does it imply in order to get the code executed or visited on the above trigger one needs to create and delete accounts. So our unit test method will look like this :-              
    public class myClass  {   static testMethod void myTest()      {      String brno='678900';      Account a = new Account();      a.Name='Test Account';      //a.Branch_Number__c = brno;      insert a;      delete a;    }  }
  2.                               
  3.  Now let me take an example of writing a separate class for Unit Test Methods and here I will take the example of a VF Page and its controller and how to provide coverage to the controller class.              Say my Visual Force page is called "MyController" and is associated with a custom controller by the name-"MyController"                                                                                                                            Code VF Page is as follows:-
    <apex:page controller="MyController" tabStyle="Account">
    <apex:form >
    <apex:pageBlock title="Hellooo{!$User.FirstName}">
    Your Account Name:
    <apex:inputField value="{!acc1.name}"/>
    <apex:commandButton action="{!save}" value="save"/>
    </apex:pageBlock>
    </apex:form> 
    </apex:page>         
                                                                                                                          Code of the controller is as follows:-                                                                                                    public class MyControllerAcc
     {
        public String save { get; set; }

     public Account[] acc1;
     public Contact SelectedCon;
     public Contact[] Arrcon ;
     public string SelectedConName;
     String[] SelectedAccName= new String[]{}; 
     public String Conid { get; set; }
     public String ConName { get; set; }
     public Boolean MasterBtnVis { get; set; }

    public MyControllerAcc() 
    {
    //Id aid = ApexPages.currentPage().getParameters().get('id');    
    acc1 = [select name,id from Account];
    MasterBtnVis   =false;
    }

    public Contact[] getcontacts()
    {
    if(SelectedAccName.size()>0)
    {
    Arrcon = [select firstname,id from Contact where accountid=:SelectedAccName];
    }
    else
    {
    //Arrcon = [select firstname,id,account.name from Contact];

    }
    return Arrcon;   
    }


    public List<SelectOption> getAcc1() 
    {    
    List<SelectOption> options = new List<SelectOption>();
    Integer i=0;
     for(Account acc: acc1)
       {
           options.add(new SelectOption(acc.id,acc.name));
       }
      return options;
     
    }

           public String[] getSelectedAccName() 
            {
                return SelectedAccName;
            }
                
            public void setSelectedAccName(String[] SelectedAccName) 
            {
                this.SelectedAccName= SelectedAccName;
            }

            public PageReference test() 
            {
                  MasterBtnVis=true;
                  return null;
            }
            
            public PageReference save() 
            {
             
                //if(ApexPages.currentPage().getParameters().get('cid')!= null)
                //{
                   SelectedCon = [select id, firstname from Contact where id =:conid];
                   SelectedCon.firstname=conname;
                  update SelectedCon ;
                  //}
                  
                  String Contactid = Conid;
                  return new PageReference('/' + Contactid ) ;
                  //return null;
            }
            public String getSelectedConName() 
            {
                return SelectedConName;
            }
            public boolean getMasterBtnVis() 
            {
                return MasterBtnVis;
            }
     
            public void setSelectedConName() 
            {
                SelectedConName = ApexPages.currentPage().getParameters().get('cid'); 
                //SelConName; 
                //return SelectedConName;
            }
            public Pagereference SetContactValues()
            {
                  Conid = Apexpages.currentPage().getParameters().get('cid');
                  ConName = Apexpages.currentPage().getParameters().get('cname');
                  return null;
            }
            public PageReference iWantMyJSValues() {
            conid= Apexpages.currentPage().getParameters().get('one');
            conname = Apexpages.currentPage().getParameters().get('two');
            return null;
        }
    } Code of my Unit Test Method for the above controller and page is as follows:- @isTest
    public class MyControllerTests
    {
     public static testMethod void testMyController()
     {
             //create instance or variable of your VF Page PageReference pageRef = Page.MyController;
            Test.setCurrentPage(pageRef);
            Account acc= new Account(name='Acme');
            insert acc;
            // Add parameters to page URL
            ApexPages.currentPage().getParameters().put('id', acc.id); //create instance or variable of your controller class         MyController controller = new MyController(); //set the values of public property controller.MasterBtnVis =false; controller.ConName ='TestName'; //invoke public methods of the controller class Account Acctmp=controller.getAcc1();
            System.assertEquals('Acme', Acctmp.Name);
            controller.Acc1.name='Changed';
             //invoke public methods of the controller class controller.save();
            Account[] accs = [select id, name from account where id =: acc.id];
            System.assertEquals('Changed', accs[0].name);
       
             }

    } So in a controller and a VF page one has to write code which emulates the invoking of the UI by a user. So how does one do that. Create an instance of the VF page as done in the above code and then set the parameters if the page needs parameters for being invoked. Secondly you can instantiate a variable of your controller class , set various public properties, invoke the public methods as highlighted in the sample test Method class above.
Hope this clears the confusion around test classes and in case you still face challenges feel free to post your queries.


Thursday, May 10, 2012

HP Public Beta Cloud Launched today!




HP Cloud is All Set to Enter the Public Beta. Though analysts say it has a long way to go before perfecting its cloud avatar. One of the things which caught my imagination was that in HP cloud one could migrate LAMP based application onto HP Cloud Compute Service!!!! It has primarily the constituents viz. :-
1. HP Cloud Compute
2. HP Cloud Object Storage
3. HP Cloud Content Delivery Network (CDN)
Enclosed is the brief overview by JANAKIRAM MSV . It also contains a video of the HP cloud. We can have head-sup in knowing the pos of SFDC over HP Cloud. Salesforce pros time to dive into the nuances of this new cloud offering - do a gap analysis vis-a-vis edge SFDC holds over HP or things which need to be factored onto the Salesforce cloud platform... 



HP Cloud is All Set to Enter the Public Beta

HP Cloud Video