Wednesday, December 11, 2013

Assign/Remove Permission set to multiple users on single click

Currently in Salesforce if you want to assign Permission Set to multiple users, you have to go to each user and you have to assign. Using this page you can Assign/Remove Permission Set to multiple users on single click, which will save your time.

Permission Set assignment depends on the user License and Permission set License. If both are same, then only you can assign Permission Set to User. So, this page will list out only those users who have same license as permission set.

If you assign a permission set with no associated user license, all of its enabled settings and permissions must be allowed by the user’s license, or the assignment will fail.

In this page I am generating user table using JQuery and JSON. Because it will solve the problem of Salesforce Government limit of 1000 records in a list. User table can list out more records.


Page : AssignPermissionSet


<apex:page controller="AssignPermissionSetController" tabStyle="Account">
    <apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery)}" />
    <style>
        #ProcessDiv{
            display: none;
            position: fixed;
            top: 0%;
            left: 0%;
            width: 100%;
            height: 100%;
            background-color: #ffffff;
            z-index:1;
            opacity:0.5;
            text-align: center;
            vertical-align:50%;
            ProcessDiv: alpha(opacity=50);
        }
        
        
        .datagrid table {
            border-collapse: collapse;
            text-align: left;
            width: 600px;
        }
        
        .datagrid {
            font: normal 12px/150% Verdana, Arial, Helvetica, sans-serif;
            background: #fff;
            overflow: hidden;
            border: 1px solid #8C8C8C;
            width: 600px;
        }
        .header{
            background-color:#8C8C8C;
            color:#FFFFFF;
            font-size: 12px;
            padding: 1px 12px;
            font-weight: bold;
            border-left: 1px solid #A3A3A3;
            width: 300px;
        }
        .cell{
            color: #7D7D7D;
            border-left: 1px solid #DBDBDB;
            font-size: 12px;
            font-weight: normal;
            padding: 1px 12px;
            width: 300px;
        }
        
        .selected{
            background-color:#E3F3FF;
            cursor:pointer;
        }
    </style>
    <script>
        var jsonString;
        var removedTbl;
        var addedTbl;
        var row;
        var tr = [];
        var headerAPI = [];
        var td;
        var rowCnt;
        var jsonObj;
        function showJSONData(jsonString1,jsonString2){
            generateTbl();
            jsonObj = jQuery.parseJSON(jsonString1);
            rowCnt = new Number(jsonObj.total);
            for (var i = 0; i < rowCnt; i++) {
                row = $('<tr></tr>').attr('id',jsonObj.rows[i].Id).appendTo(removedTbl);
                row.bind( "click", function() {
                    $(this).toggleClass('selected');
                });
                td = $('<td></td>').addClass('cell').text(jsonObj.rows[i].Name).appendTo(row);
                td = $('<td></td>').addClass('cell').text(jsonObj.rows[i].Profile).appendTo(row);    
            } 
            
            jsonObj = jQuery.parseJSON(jsonString2);
            rowCnt = new Number(jsonObj.total);
            tr = [];
            headerAPI = [];
            for (var i = 0; i < rowCnt; i++) {
                row = $('<tr></tr>').attr('id',jsonObj.rows[i].Id).appendTo(addedTbl);
                row.bind( "click", function() {
                    $(this).toggleClass('selected');
                });
                td = $('<td></td>').addClass('cell').text(jsonObj.rows[i].Name).appendTo(row);
                td = $('<td></td>').addClass('cell').text(jsonObj.rows[i].Profile).appendTo(row);
            }           
            console.log("TTTTT:"+$('#assignedUserRds').html());
        }
        
        function generateTbl(){
            $('#RemovedUserRds').empty();
            $('#AssignedUserRds').empty();
            //Removed user Data Table
            removedTbl = $('<table></table>').attr('id',"removedTbl");
            row = $('<tr></tr>').appendTo(removedTbl);
            td = $('<th></th>').addClass('header').text('Name').appendTo(row);
            td = $('<th></th>').addClass('header').text('Profile').appendTo(row);
            removedTbl.appendTo($('#RemovedUserRds'));
            
            //Added user Data Table
            addedTbl = $('<table></table>').attr('id',"addedTbl");
            row = $('<tr></tr>').appendTo(addedTbl);
            td = $('<th></th>').addClass('header').text('Name').appendTo(row);
            td = $('<th></th>').addClass('header').text('Profile').appendTo(row);
            addedTbl.appendTo($('#AssignedUserRds'));
        }
        
        $(document).ready(function() {
            generateTbl();
        });
        
        function startProcess(){
            document.getElementById('ProcessDiv').style.display = 'block'; 
        }
        function endProcess(){
            document.getElementById('ProcessDiv').style.display = 'none'; 
        }
        
        function moveRow(tblId){
            if(tblId == 'AssignedUserRds'){
                tr = $('#RemovedUserRds table tr[class="selected"]').appendTo($('#' + tblId + ' table'));
            }else{
                tr = $('#AssignedUserRds table tr[class="selected"]').appendTo($('#' + tblId + ' table'));
            }
        }
        function getUserIds(){
            var addUserIds = '';
            $('#AssignedUserRds table tr').each(function() {
                if($(this).attr('id') != ''){
                    addUserIds = addUserIds + ',' + $(this).attr('id');
                }
            });            
            Save(addUserIds);         
        }
    </script>
    <apex:form >
        <div id="ProcessDiv"><b>Saving records.........</b></div>
        <apex:messages id="errorMsgId"/>
        <apex:actionFunction name="fetchUserRds" action="{!fetchUserRds}" oncomplete="showJSONData('{!removedUserRds}','{!assignedUserRds}');endProcess();" />
        <apex:actionFunction name="Save" action="{!Save}" oncomplete="showJSONData('{!removedUserRds}','{!assignedUserRds}');endProcess();" reRender="errorMsgId">
            <apex:param assignTo="{!addUserIds}" value="{!addUserIds}" name="addUserIds"/>
        </apex:actionFunction>
        <apex:pageBlock >
            <apex:pageBlockSection columns="1" title="Permission Set Assignment">
                <apex:selectList value="{!permissionSetId}" label="Select Permission Set" onchange="startProcess();fetchUserRds();" multiselect="false" size="1">
                    <apex:selectOptions value="{!options}"/>
                </apex:selectList>
            </apex:pageBlockSection>
            <apex:pageBlockSection columns="1" id="pgSectionBlock">
                <apex:outputPanel >
                <table width="700px" height="400px;">
                    <tr>
                        <td style="width:300px;">
                            <apex:outputText value="Available Users" style="font-weight:bold; font-size:16px;"/>
                            <div id="RemovedUserRds" class="datagrid" style="height:400px;overflow:auto;background-color:white;">
                            </div>
                        </td>
                        <td style="width:100px;text-align:center;vertical-align:middle">
                            <div onClick="moveRow('AssignedUserRds');" style="cursor:pointer;border:1px">
                                <b>&gt;&gt;</b>
                            </div>
                            <br/>
                            <div onClick="moveRow('RemovedUserRds');" style="cursor:pointer;border:1px">
                                <b>&lt;&lt;</b>
                            </div>
                        </td>
                        <td style="width:300px;">
                            <apex:outputText value="Selected Users" style="font-weight:bold; font-size:16px;"/>
                            <div id="AssignedUserRds" class="datagrid" style="height:400px; overflow:auto; background-color:white;">
                            </div>
                        </td>
                    </tr>
                </table>
                </apex:outputPanel>
            </apex:pageBlockSection>
            <apex:pageBlockButtons location="bottom">
                <apex:commandButton onClick="startProcess();getUserIds();" reRender="errorMsgId" value="Save"/>
                <apex:commandButton onClick="window.open('/005','_self');" reRender="errorMsgId" value="Cancel"/>
            </apex:pageBlockButtons>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Class : AssignPermissionSetController


public class AssignPermissionSetController{
    public String removeUserIds { get; set; }
    public String addUserIds { get; set; }
    public List<SelectOption> options{get;set;}
    public Id permissionSetId{get;set;}
  
    // Global JSON generator
    public static JSONGenerator gen{get; set;}
    public String assignedUserRds{get; set;}
    public String removedUserRds{get; set;}
  
    List<PermissionSetAssignment> insertList;
    List<PermissionSetAssignment> removeList;
    Map<Id,PermissionSetAssignment> userPermissionSetAssignmentMap;
  
    public AssignPermissionSetController(){
        options = new List<SelectOption>();
        options.add(new SelectOption('','--None--'));
        for(PermissionSet temp : [Select Id,Label,UserLicenseId from PermissionSet where  ProfileId = null]){
            options.add(new SelectOption(temp.Id,temp.Label));
        }
    }
  
    public void fetchUserRds(){
        addUserIds = '';
        removeUserIds = '';
        assignedUserRds = '';
        removedUserRds = '';
        userPermissionSetAssignmentMap = new Map<Id,PermissionSetAssignment>();
        if(permissionSetId != null){
            set<Id> userId = new set<Id>();
            for(PermissionSetAssignment Obj : [select Id,AssigneeId from PermissionSetAssignment where PermissionSetId =: permissionSetId]){
                userId.add(Obj.AssigneeId);
                userPermissionSetAssignmentMap.put(Obj.AssigneeId,Obj);
            }
          
            Integer cnt = 0;
            gen = JSON.createGenerator(true);  
            gen.writeStartObject();
            gen.writeFieldName('rows');
            gen.writeStartArray();
          
            PermissionSet tempObj = [Select UserLicenseId from PermissionSet where Id =: permissionSetId];
            List<Profile> tempProfilelList = new List<Profile>();
            if(tempObj.UserLicenseId != null){
                tempProfilelList = [select Id,(Select Id,Name,Profile.Name from users where Id not in : userId) from Profile where UserLicenseId =: tempObj.UserLicenseId];
            }else{
                tempProfilelList = [select Id,(Select Id,Name,Profile.Name from users where Id not in : userId) from Profile];
            }
            for(Profile profileObj : tempProfilelList){
                for(User ur : profileObj.users){
                    gen.writeStartObject();
                    gen.writeStringField('Id', ur.Id);
                    gen.writeStringField('Name', ur.Name);
                    gen.writeStringField('Profile', ur.Profile.Name);
                    gen.writeEndObject();
                    cnt++;
                }
            }
            gen.writeEndArray();
            gen.writeStringField('total',cnt + '');
            gen.writeEndObject();
            removedUserRds = gen.getAsString();

            cnt = 0;
            gen = JSON.createGenerator(true);  
            gen.writeStartObject();
            gen.writeFieldName('rows');
            gen.writeStartArray();
          
            for(User ur : [Select Id, Name,Profile.Name from User where Id in : userId]){
                gen.writeStartObject();
                gen.writeStringField('Id', ur.Id);
                gen.writeStringField('Name', ur.Name);
                gen.writeStringField('Profile', ur.Profile.Name);
                gen.writeEndObject();
                cnt++;
            }
            gen.writeEndArray();
            gen.writeStringField('total',cnt + '');
            gen.writeEndObject();
            assignedUserRds = gen.getAsString();
        }
    }

    public void save(){
        try{
            if(permissionSetId != null){
                insertList = new List<PermissionSetAssignment>();
                removeList = new List<PermissionSetAssignment>();
                PermissionSetAssignment temp;
                if(addUserIds != ''){
                    addUserIds = addUserIds.substring(1);
                    for(String str : addUserIds.split(',')){
                        if(!userPermissionSetAssignmentMap.containsKey((Id)str)){
                            temp = new PermissionSetAssignment();
                            temp.PermissionSetId = permissionSetId;
                            temp.AssigneeId = str;
                            insertList.add(temp);
                        }
                    }
                }
                for(String str : userPermissionSetAssignmentMap.keySet()){
                    if(!addUserIds.contains(str)){
                        removeList.add(userPermissionSetAssignmentMap.get(str));
                    }
                }
                if(insertList.size() > 0){
                    insert insertList;
                }
                if(removeList.size() > 0){
                    delete removeList;
                }
                fetchUserRds();
            }
        }catch(Exception ex){
            Apexpages.addMessage(new Apexpages.Message(Apexpages.Severity.INFO, 'Permission Set assignment failed.'));
        }
    }  
}

Thursday, December 5, 2013

Generate formatted Excel sheet in Salesforce

Sample:

Using Microsoft Office XML formats we can generate formatted excel sheet. For more detail refer below sites. Using schema provided by office, we can create formatted word document also.

http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats
http://msdn.microsoft.com/en-us/library/aa140066(office.10).aspx

Page : FormattedExcel


<apex:page controller="ExcelXMLController" contentType="application/vnd.ms-excel#XYZ.xls">
    {!ExcelData}
    <c:excelgenerator></c:excelgenerator>
    {!EOF}
</apex:page>


Class : ExcelXMLController 





public class ExcelXMLController {

    public String getExcelData() {
        return '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?>';
    }
    public String getEOF() {
        return '</Workbook>';
    }

}


Component : ExcelGenerator


<apex:component controller="AccountData">
    <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
     xmlns:o="urn:schemas-microsoft-com:office:office"
     xmlns:x="urn:schemas-microsoft-com:office:excel"
     xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
     xmlns:html="http://www.w3.org/TR/REC-html40">
     <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
      <Author>Ankurkumar Amratlal Patel</Author>
      <LastAuthor>Ankurkumar Amratlal Patel</LastAuthor>
      <Created>2013-12-06T05:12:53Z</Created>
      <Company>HP</Company>
      <Version>14.00</Version>
     </DocumentProperties>
     <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
      <WindowHeight>10035</WindowHeight>
      <WindowWidth>22995</WindowWidth>
      <WindowTopX>480</WindowTopX>
      <WindowTopY>120</WindowTopY>
      <ProtectStructure>False</ProtectStructure>
      <ProtectWindows>False</ProtectWindows>
     </ExcelWorkbook>
     <Styles>
      <Style ss:ID="Default" ss:Name="Normal">
       <Alignment ss:Vertical="Bottom"/>
       <Borders/>
       <Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"/>
       <Interior/>
       <NumberFormat/>
       <Protection/>
      </Style>
      <Style ss:ID="s70">
       <Alignment ss:Horizontal="Center" ss:WrapText="1" ss:Vertical="Bottom"/>
       <Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#FF0000"
        ss:Bold="1"/>
      </Style>
     </Styles>
     <Worksheet ss:Name="Sheet1">
      <Names>
       <NamedRange ss:Name="_FilterDatabase" ss:RefersTo="=Sheet1!R1C1:R1C3"
        ss:Hidden="1"/>
      </Names>
      <Table ss:ExpandedColumnCount="3" ss:ExpandedRowCount="{!excelRowCnt}" x:FullColumns="1"
       x:FullRows="1" ss:DefaultRowHeight="15">
       <Column ss:Index="2" ss:Width="102"/>
       <Row>
        <Cell ss:StyleID="s70"><Data ss:Type="String">Account Name</Data><NamedCell ss:Name="_FilterDatabase"/></Cell>
        <Cell ss:StyleID="s70"><Data ss:Type="String">Type</Data><NamedCell ss:Name="_FilterDatabase"/></Cell>
        <Cell ss:StyleID="s70"><Data ss:Type="String">SLA</Data><NamedCell
          ss:Name="_FilterDatabase"/></Cell>
       </Row>
       <apex:repeat value="{!accList}" var="acc">
           <Row>
            <Cell><Data ss:Type="String">{!acc.Name}</Data></Cell>
            <Cell><Data ss:Type="String">{!acc.Type}</Data></Cell>
            <Cell><Data ss:Type="String">{!acc.SLA__c}</Data></Cell>
           </Row>
       </apex:repeat>
      </Table>
      <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
       <PageSetup>
        <Header x:Margin="0.3"/>
        <Footer x:Margin="0.3"/>
        <PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
       </PageSetup>
       <Print>
        <ValidPrinterInfo/>
        <HorizontalResolution>600</HorizontalResolution>
        <VerticalResolution>600</VerticalResolution>
       </Print>
       <Selected/>
       <Panes>
        <Pane>
         <Number>3</Number>
         <ActiveRow>7</ActiveRow>
         <ActiveCol>9</ActiveCol>
        </Pane>
       </Panes>
       <ProtectObjects>False</ProtectObjects>
       <ProtectScenarios>False</ProtectScenarios>
      </WorksheetOptions>
      <AutoFilter x:Range="R1C1:R1C3" xmlns="urn:schemas-microsoft-com:office:excel">
      </AutoFilter>
     </Worksheet>
    </Workbook>
</apex:component>


Class : AccountData



public class AccountData{
    public List<Account> accList{get;set;}
    public Integer excelRowCnt {get;set;}
    public AccountData(){
        accList = [Select Name,Type,SLA__c from Account];
        excelRowCnt = 4 + accList.size();
    }
}

Wednesday, December 4, 2013

Apex code to Freeze Cloumns and Header of table

Sample :


  • Download latest JQuery package from below link and upload it into static resource in SFDC.
  • Create page and controller.
Page : FreezeTable


<apex:page controller="FreezeTableController">
    <apex:stylesheet value="{!URLFOR($Resource.FreezeTable, '/jquery-easyui-1.3.4/themes/default/easyui.css')}"/>
    <apex:stylesheet value="{!URLFOR($Resource.FreezeTable, '/jquery-easyui-1.3.4/themes/icon.css')}"/>
    <apex:includeScript value="{!URLFOR($Resource.FreezeTable, '/jquery-easyui-1.3.4/jquery.min.js')}"/>
    <apex:includeScript value="{!URLFOR($Resource.FreezeTable, '/jquery-easyui-1.3.4/jquery.easyui.min.js')}"/>
    <table class="easyui-datagrid" title="Frozen Columns in DataGrid" style="width:700px;height:250px"
            data-options="rownumbers:true,singleSelect:true">
        <thead data-options="frozen:true">
            <tr>
                <th data-options="field:'itemid',width:100">Item ID</th>
                <th data-options="field:'productid',width:120">Product</th>
            </tr>
        </thead>
        <thead>
            <tr>
                <th data-options="field:'listprice',width:90,align:'right'">List Price</th>
                <th data-options="field:'unitcost',width:90,align:'right'">Unit Cost</th>
                <th data-options="field:'attr1',width:250">Attribute</th>
                <th data-options="field:'status',width:60,align:'center'">Status</th>
            </tr>
        </thead>
        <tbody>
            <apex:repeat value="{!accList}" var="acc">
                <tr>
                    <td>{!acc.Name}</td>
                    <td>{!acc.Name}</td>
                    <td>{!acc.Name}</td>
                    <td>{!acc.Name}</td>
                    <td>{!acc.Name}</td>
                    <td>{!acc.Name}</td>
                </tr>
            </apex:repeat>
        </tbody>
    </table>
</apex:page>


Controller : FreezeTableController


public class FreezeTableController{
    public list<Account> accList{get;set;}
    // Global JSON generator
    public JSONGenerator gen {get; set;}
    public String JsonData {get; set;}
    public FreezeTableController(){
        gen = JSON.createGenerator(true);    
        gen.writeStartObject();
        accList = [select Id, Name from Account];
        gen.writeStringField('total',accList.size() + '');
        gen.writeFieldName('rows');
        gen.writeStartArray(); 
        for(Account acc : accList){
          gen.writeStartObject();
            gen.writeStringField('productid', acc.Id);
            gen.writeStringField('productname', acc.Name);
            gen.writeStringField('unitcost', acc.Id);
            gen.writeStringField('status', acc.Id);
            gen.writeStringField('listprice', acc.Id);
            gen.writeStringField('attr1', acc.Id);
            gen.writeStringField('itemid', acc.Id);
            gen.writeEndObject();
        }
        gen.writeEndArray();
        gen.writeEndObject();
        JsonData = gen.getAsString(); 
    }
}

JSON sample : 


"total" : "31",
  "rows" : [ {
    "productid" : "0019000000SEf0aAAD",
    "productname" : "Diwali",
    "unitcost" : "0019000000SEf0aAAD",
    "status" : "0019000000SEf0aAAD",
    "listprice" : "0019000000SEf0aAAD",
    "attr1" : "0019000000SEf0aAAD",
    "itemid" : "0019000000SEf0aAAD"
  }, {
    "productid" : "0019000000SEf6WAAT",
    "productname" : "test",
    "unitcost" : "0019000000SEf6WAAT",
    "status" : "0019000000SEf6WAAT",
    "listprice" : "0019000000SEf6WAAT",
    "attr1" : "0019000000SEf6WAAT",
    "itemid" : "0019000000SEf6WAAT"
  }]
}

Assign default value to any field in Edit mode

Create Home page component with type 'HTML Area'.


Add below line of code in 'Show HTML'.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">  
var j$ = jQuery.noConflict();      
j$(document).ready(function(){      
    j$('#00N90000003CEbd').val('Medium'); //To set Custom field value
    j$('#acc23').val('Test');  // To set Standard Field value
});
</script>

Custom Field :
Here, '00N90000003CEbd' is the SFDC id of the custom field.

 

Standard Field:
To set standard field default value, 1st get id of that field using firebug and after that use that id in code and assign value.(refer below snap)




Here, 'acc23' is the id of the Account Site.

Result:


Consideration:
  • Make sure that sidebar is enabled for user.
  • Custom component is added in sidebar and it is visible in all pages.

Skip validation rule in Salesforce


  • Create checkbox field on object.

  • Add NOT( ISCHANGED(Skip_Validation__c) in validation rule, which you want to skip when you are updating record from any VF page or Web service.

  • In your code just flip the value of Skip_Validation__c field. Refer below code.


Bypass Triggers in Salesforce

  • Create custom setting as shown below.
  • Fields
    • Name – Text field to store Trigger name.
    • User List – Text field to store Users Name like ankur.iteng21@gmail.com.
    • Block Trigger - Checkbox to control specified trigger execution.
      • True - It won’t execute trigger for specified Block User.
      • False - It will execute trigger for specified Block User
  • Create records as shown below.

  • Modify your trigger code. Add condition in the begining of the trigger.