Tuesday, December 26, 2017

VisualForce Charting in Salesforce

As salesforce has given us the functionality of report and dashboard to create chart then what is the use of visualforce charting?.
In some situations existing functionality of salesforce can not meet our requirement properly . Suppose there is a requirement to compose custom pages that combine charts and data tables in ways that are more useful to our organization.In that case visual force charting is useful.There are also other way to meet this requirement. We can use Google chart Api for this.In my previous post I have explained.
Visualforce charting gives you an easy way to create customized business charts, based on data sets you create directly from SOQL queries, or by building the data set in your own Apexcode. By combining and configuring individual data series, you can compose charts that display your data in ways meaningful to your organization.
Visualforce charts are rendered client-side using JavaScript. This allows charts to be animated and visually exciting, and chart data can load and reload asynchronously, which can make the page feel more responsive.
This is the my page and controller. 
<apex:page controller="OppsControllernew" tabStyle="Account">
    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockSection title="Chart With Table">
                <apex:outputPanel style="float:left;">
                    <apex:chart data="{!Opportunities}" width="500" height="250">
                        <apex:axis type="Numeric" position="left" fields="Amount" title="Amount"/>
                        <apex:axis type="Category" position="bottom" fields="Name" title="Name"/>
                            
                        <apex:barSeries orientation="horizontal" axis="left" xField="Amount" yField="Name"/>
                        <!--<apex:pieSeries dataField="amount" labelField="name"/>-->
                        <apex:legend position="right"/>
                    </apex:chart>
                
                    <apex:chart data="{!Opportunities}" width="500" height="250">
                        <apex:axis type="Category" position="bottom" fields="Name" title="Name" />
                        <apex:axis type="Numeric" position="left" fields="Amount" title="Amount" grid="true"/>
                        <apex:lineSeries axis="left" fill="true"  xField="Name" yField="Amount"  markerType="cross" markerSize="4" markerFill="#FF0000"/>
                  </apex:chart>
                </apex:outputPanel>
              
               <apex:outputPanel style="float:right;margin-right:4cm;height:600px;width:400px;" >
                 <p><b> Opportunity Table</b></p><br/>
                 <apex:pageBlockTable value="{!Opportunities}" var="opp">
                    <apex:column headerValue="Opportunity" value="{!opp.Name}"/>
                    <apex:column headerValue="Amount" value="{!opp.amount}"/>
                    <apex:column headerValue="Created Date" value="{!opp.createddate}" style="width:80px"/>
                </apex:pageBlockTable>
            </apex:outputPanel>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>
My controller is 

public class OppsControllernew {

    
    // Get a set of Opportunities 
    
    public ApexPages.StandardSetController setCon {
        get {
            if(setCon == null) {
                setCon = new ApexPages.StandardSetController(Database.getQueryLocator(
                      [SELECT Name, Type,createddate, Amount, Closedate FROM Opportunity]));
                setCon.setPageSize(5);
            }
            return setCon;
        }
        set;
    }
    
    public List<Opportunity> getOpportunities() {
         return (List<Opportunity>) setCon.getRecords();
    }

}

Visualforce chart binds to the source of its data through the data attribute on the <apex:chart> component.

Here data source is sObjects that is Opportunity.
Data can be 

  • Name of java script function
  •  Non-Salesforce data sources by building a JavaScript array
  • Apex wrapper objects
The object field names used as data attributes are case-sensitive in JavaScript while field names in Apex and Visualforce are case-insensitive. Be careful to use the precise field name in the fields, xField, and yField attributes of axes and data series components, or your chart will silently fail.Make sure all the name perfectly equal between fields , xFields and yFields.
Limitations Of Visualforce Charting 
  • Visualforce charts only render in browsers which support scalable vector graphics (SVG).
  • Visualforce charts won’t display in pages rendered as PDFs
  • Dynamic (Apex-generated) charting components are not supported at this time
Now the final out put will be like this 

Creating charst in Visualforce page by using JavaScript Remoting & Google Charts API.

This post is all about how to draw a chart in Visual force page by using JavaScript Remoting & Google Charts API.
I had faced some requirement to draw a different types of chart in a visualforce page and also to display number of  distinct record for further reference. I had done some work around and finally I had reached to the final destination. Here I have created one object ChartObject__c and two field Name and Amount.
Here I am sharing some code snippet for your reference. 

Page:

<apex:page controller="GoogleChartsController" sidebar="false">

    <!-- Google API inclusion -->
    <apex:includeScript id="a" value="https://www.google.com/jsapi" />
    <apex:sectionHeader title="Google Charts + Javascript Remoting" subtitle="Demoing - Opportunities by Exepected Revenue"/> 
    
    <!-- Google Charts will be drawn in this DIV -->
    <div id="chartBlock"/>
    <div id="chartBlockpie"/>
    <div id="chartBlockline"/>
    <div id="chartBlockbar" />
    <div id="chartBlockgauge" />
     
    <script type="text/javascript">
     
  // Load the Visualization API and the piechart package.
  google.load('visualization', '1.0', {'packages':['corechart']});

   // Set a callback to run when the Google Visualization API is loaded.
  google.setOnLoadCallback(initCharts);

  function initCharts() {   
  
   // Following the usual Remoting syntax
   // [<namespace>.]<controller>.<method>([params...,] 
   //<callbackFunction>(result, event) {...}
   // namespace : 
   // controller : GoogleChartsController
  // method : loadOpps
   
  GoogleChartsController.loadOpps(
    function(result, event){ 
    
     // load Column chart
     var visualization = new google.visualization.ColumnChart(document.getElementById('chartBlock'));
    
     // Prepare table model for chart with columns
     var data = new google.visualization.DataTable();
     data.addColumn('string', 'Name');
     data.addColumn('number', 'Amount');  
      
     // add rows from the remoting results
     for(var i =0; i<result.length;i++){
      var r = result[i];
      data.addRow([r.Name, r.Amount]);
     }
     var chart = new google.visualization.PieChart(document.getElementById('chartBlockpie'));
     chart.draw(data, result);
      
     var chart = new google.visualization.LineChart(document.getElementById('chartBlockline'));
     chart.draw(data, result);
    
     var chart = new google.visualization.BarChart(document.getElementById('chartBlockbar'));
     chart.draw(data, result);
     
     /*var chart = new google.visualization.ScatterChart(document.getElementById('chartBlockscater'));
     chart.draw(data, result);*/
     
     var chart = new google.visualization.GaugeChart(document.getElementById('chartBlockgauge'));
     chart.draw(data, result);
      
     // all done, lets draw the chart with some options to make it look nice.
     visualization.draw(data, {legend : {position: 'top', textStyle: {color: 'blue', fontSize: 10}}, width:window.innerWidth,vAxis:
             {textStyle:{fontSize: 10}},hAxis:{textStyle:{fontSize: 10},showTextEvery:1,slantedText:false}});
         },{escape:true});
      }
       </script>
    <p>Total Different Kind Of Production:<apex:outputText value="{!totalvalue}"/></p>
</apex:page>

Controller:

global with sharing class GoogleChartsController {
    public Integer totalvalue{get;set;}
    public GoogleChartsController() {        
        // Integer totalvalue;
        list<AggregateResult>  Namecount=new List<AggregateResult>();
        Namecount= [select  COUNT_DISTINCT(Amount) ctr from Opportunity];
        for(AggregateResult sobj:Namecount){
            
            totalvalue=Integer.valueOf(sobj.get('ctr'));
        }
        System.debug('################asish####################'+totalvalue);
    } 
    
    /**
Loads most recent 10 Opportunities
*/
    @RemoteAction   
    global static Opportunity[] loadOpps() {        
        return  [select Id, Name, Amount from Opportunity  order by CreatedDate DESC limit 10];        
    }  
}

Here I am sharing some image regarding chart.

Generating pdf Using Conga Composer

Conga Composer lets you to create documents from a button or link placed on a Salesforce.com page layout. It merges Salesforce.com data with Word, Excel, PowerPoint, email, or PDF templates to create finished documents.

Benefit Of Conga Composer

  • Easily create and deliver customized documents, 
  • Presentations and reports using Word, PowerPoint, Excel, HTML email and PDF forms from standard & custom objects. 
  • Generate quotes, proposals, account plans, invoices, contracts, letters & more.
In order to use Conga Composer, we need to install two things.
  •     Conga Composer 
  •     Conga Query Manager.

If we need to use some related object's record then Conga Query Manager is necessary otherwise Conga Composer is enough.

How to Install Conga Composer


Go through this link for installation .

http://knowledge.appextremes.com/appextremes/ext/kb110-how-to-install-conga-composer

How to Install Conga Query Manager


Go through this link for installation .

http://knowledge.appextremes.com/appextremes/ext/kb611-how-to-install-conga-query-manager

We already have some sample design in our local drive which signifies how the information will be presented , If we don't have then we will make one using word or anything else.

Now we will create  Conga Template and Conga Query.



Creating Conga Template

Click New button on Conga Template to create one template
After template creation ,click on AttachFile button to attach some sample template from your local drive.






Creating Conga Query

If we have to display some related object record then we have to create conga query to pull data from salesforce, here we can define as many query as want.
There is field called SOQL Select Statement where we have to write query.
For example query will be like this 

SELECT invoiceit_s__Accounting_Code__c, invoiceit_s__Charge_Date__c, invoiceit_s__Service_End_Date__c, invoiceit_s__Service_Start_Date__c, CreatedById   FROM invoiceit_s__Invoice_Lines__c WHERE invoiceit_s__Invoice__c = '{pv0}

Here we are querying data from invoice lines that means button must be in invoice page.

There are two different approach for generating document.

  • By Clicking a Button
  • Some Automation process by using Work flow  

By Clicking a Button
  • Create a custom button on master object 
  • Choose content source as URL
  • paste this code 

https://www.appextremes.com/apps/Conga/PointMerge.aspx?SessionId={!API.Session_ID}
   &ServerUrl={!API.Partner_Server_URL_80}
   &Id={!Credit_Note__c.Id} //object id where button is present
   &DefaultPDF=1
   &PartnerCode=0015000000Yd8nM // optionals 
  &EmailReplyToId{!User.Id}
  &EmailToId={!Credit_Note__c.Billing_ContactId__c}//to whom emil is going
  &EmailRelatedToId={!Credit_Note__c.Id}//object id where button is present
  &TemplateId=a0mb0000000KYO0 // conga templae id which you have created
  &QueryID=[CreditLines]a0nb0000000zgUE //conga query id, you can give many query id by using comma

How to use Conga Composer 

Go through this pdf 

Automation Process
  • Create one formula field and one checkbox field on mater object.
  • When that check box is true then workflow will be fired.
  • Create a email template through which email will be going to the customer.
  • In the formula field paste this code 

 "&Id="+Id 
   +"&TemplateId=a0pW000000335Xt" //conga template id
   +"&EmailTemplateId=00XW0000000M8Hp" //the emailtemplate id which you have created
   +"&QMode=3" 
   +"&DefaultPDF=1" 
   + "&EmailToId=" + invoiceit_s__Billing_Contact__c 
   +"&QueryID=a11W0000000ov1y,a11W0000000ov1t" //conga query id
   +"&EmailRelatedToId="+Id

  • Create work flow and an outbound message.
  • Give End point Url as https://workflow.appextremes.com/apps/Conga/PMWorkflow.aspx.
  • Select that formula field Account fields to send to selected fields.
  • Click on Save
Now work flow and outbound message is ready, when that checkbox will be ready a mail with attachment will reach to the contact's email.
For more information about salesforce conga work flow , please go through this pdf

LIKE Operator In Salesforce

The LIKE operator in SOQL and SOSL is quite similar to the LIKE operator in SQL; it provides a mechanism for matching partial text strings and includes support for wildcards.

Suppose we need to delete some test records of Account object, all test records are created having account name is test. Account name may "testasish" or "accounttest", how can we get those record by Soql query ?
For this propose LIKE operator is useful.

For example 
List<Account> listOfAccounts;
listOfAccounts = [SELECT id, Name
                           FROM Account
                           WHERE Name  LIKE '%test%'];
This query matches both testasish,accounttest, and test.

Use Cases Of LIKE Operator

  • The % and _ wildcards are supported for the LIKE operator.
  • The % wildcard matches zero or more characters.
  • The _ wildcard matches exactly one character.
  • The text string in the specified value must be enclosed in single quotes.
  • The LIKE operator is supported for string fields only.
  • The LIKE operator performs a case-insensitive match, unlike the case-sensitive matching in SQL.
  • The LIKE operator in SOQL and SOSL supports escaping of special characters % or _.
  • Do not use the backslash character in a search except to escape a special character.

EmailService In Salesforce

Email services are automated processes that use Apex classes to process the contents, headers, and attachments of inbound email.
An email service is a system in Salesforce.com that gives you an email address to which you can send emails that you want to be handled by Salesforce.com in some way. The "handling" of the email is through custom APEX code that gets executed when an email is received at that address.
At first we need to create an apex class which will process the incomming email. From incomming email all the information entered are processed here.From that information salesforce automatically creates record.The object in which salesforce will create record will be defined in this class.This class must implements Messaging.InboundEmailHandler interface .So this class will look like in this way

global class myHandler implements Messaging.InboundEmailHandler {
       global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope) {
             Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();
            return result;
       }
}

For every email the Apex email service domain receives, Salesforce creates a separate InboundEmail object that contains the contents and attachments of that email. You can use Apex classes that implement the Messaging.InboundEmailHandler interface to handle an inbound email message. Using the handleInboundEmail method in that class, you can access an InboundEmail object to retrieve the contents, headers, and attachments of inbound email messages, as well as perform many functions.
The InboundEnvelope object stores the envelope information associated with the inbound email, and has toAddress and fromAddress field.The InboundEmailResult object is used to return the result of the email service. If this object is null, the result is assumed to be successful. The InboundEmailResult object has success and message field.

Then we need to create an email service which is present at Develop-->Email Service and also we need to choose that apex class at time of creation, After creating we will also have to create an new Email address under that email service. An email service may have multiple email address which will be automatically created by salesforce. We can also restrict email service to recieve email from specified domain.
Now just copy the email address which is generated by salesforce and send a mail to this id from your personal email id.After that check in your account some record will be definitey created.

Hiding header and Sidebar in Salesforce

some times we need to hide header and sidebar of a visualforce page or standard layout.
we can do it by writing showheader = "false"  and sidebar = "false" in the visualforce page.

for example 
<apex:page controller = "TestController"  showheader = "false" sidebar = "false">
   // your information 
</apex:page>

How can we hide in header and sidebar standard layout ?
ans- Salesforce is user friendly language, There is also a feature available so called "Enable Collapsible Section", By using this we can only hide sidebar
you can go in this way Name-->set up-->customize--> user interface--> checked the check box "
Enable Collapsible Section", after that you can show or hide sidebar.

If someone wants to hide both sidebar and header of standard layout, then how will we do it? 
Ans- It is very simple, just append "isdtp = vw" at end of link in the URL, you will see the magic.

Also you can write this in apex code.for example

PageReference samepage= new PageReference('/apex/pagename?recordid&isdtp=vw);
For testing you can write "isdtp = vw" in the any standard layout, It will automatically hide header and sidebar, Try It.

Wednesday, September 20, 2017

Updating Salesforce Records Using JavaScript

Create a Opportunity Custom Button and select Behavior as Execute javascript and paste the below code,

{!REQUIRESCRIPT("/soap/ajax/35.0/connection.js")}

var opp = new sforce.SObject("Opportunity");
opp.Id = "{!Opportunity.Id}";
opp.StageName = "Closed Won";

//update the opp
result = sforce.connection.update([opp]);

if (result[0].getBoolean("success")) {
    log("opp.with id " + result[0].id + " updated");
} else {
    log("failed to update opp." + result[0]);
}

When user clicks that button it will make that opportunity as Won.