Showing posts with label Tips & Trick. Show all posts
Showing posts with label Tips & Trick. Show all posts

Wednesday, October 12, 2022

How to get list of all accounts present in account hierarchy in Salesforce

 As a developer, we always get requirement to display records in their hierarchy (Account Hierarchy, Case Hierarchy etc). Using SOQL queries, its really tough to get all accounts in hierarchy as we have to fire multiple SOQL queries to get ultimate parent record id if we are on a record which is 3 or 4 level down in hierarchy. 

Instead of achieving everything using SOQL, we can create formula field "Ultimate Account Id" in account object which will store ultimate account record id on all account records present in account hierarchy. As formula field allows you to refer upto 10 parent, we can easily get list of all account in account hierarchy upto 10 levels.


Below is formula for Ultimate Account Id.


Now if you know account record id, just get Ultimate Account Id field value and then query all accounts which have this ultimate account Id.

Below is static method which can be used to get list of all account present in account hierarchy.

public static list<Account> findAllHierarchyAccounts(string recordId){
list<Account> allAccountList=new List<Account>();
string ultimateAccountId;
for(Account acc:[select Ultimate_Account_Id__c from Account where Id=:recordId]){
ultimateAccountId=acc.Ultimate_Account_Id__c;
}
if(string.isNotBlank(ultimateAccountId)){
for(Account acc:[select id,Name,ParentId
from Account where Ultimate_Account_Id__c=:ultimateAccountId]){
allAccountList.add(acc);
}
}
system.debug('***allAccountList size:'+allAccountList);
return allAccountList;
}

Hope this will help!!


Sunday, July 26, 2020

Compare CRUD (Object Level Access) Permission for a Profile from 2 different Org

Through this blog, I am going to share a script through which you can compare object level permission for a profile in 2 different SFDC orgs. This script is very helpful when you want to compare CRUD level permission for a profile in 2 different sandbox or permission in sandbox and production.

When you run below script, you will receive email with csv file with CRUD permission comparison.
You need to specify the target org domain url and sessionid or access_token of target org and need to run below script in source org in execute anonymous window in developer console.

Below is script:

Below is snapshot of csv file:



Note:

This is just a prototype and it may work for small organization. You need to consider heap size and apex CPU time limit exceeded errors. You can refractor this code for your use based on number of objects that you have in your org.

Hope this will help!!



Thursday, January 9, 2020

How to Delete all Files from Library using Apex

If you have to delete any library, then first you have to delete all the files present in that library. For this purpose you can run below mentioned simple apex script to delete all files from library.

string LibraryName='Demo Library';
ContentWorkspace ws = [SELECT Id, RootContentFolderId FROM ContentWorkspace WHERE Name = :LibraryName LIMIT 1];
List<ContentDocument> contentDocumentIds = new List<ContentDocument>();
for(ContentDocumentLink con:[select id,LinkedEntityId,ContentDocumentId   from ContentDocumentLink  where LinkedEntityId=:ws.Id]){
    contentDocumentIds.add(new ContentDocument(id=con.ContentDocumentId));
}
system.debug('********contentDocumentIds:'+contentDocumentIds);
system.debug('********contentDocumentIds.size:'+contentDocumentIds.size());
database.delete(contentDocumentIds,false);


Hope this will help!!

Wednesday, January 8, 2020

Download Multiple Files from Libraries

Consider a scenario in which we are suppose to download all files from libraries. Below are different approach which can be utilized:

Approach 1: Salesforce UI Download Button

If the file size is around 60 or less in library then you can use Salesforce UI to download all files at one time.

Open any library, click on show all button, then click on display options and select "Show 60 results per page". By doing this, you will be able to see 60 files at once in library. Now you can click on select all checkbox and click download button. This will help you to download files at once.
If you have more than 60 files, then click on next page and then again download all files. This process will become hectic if you have more than 1000 files in library.

Approch 2:URL hack

I performed some search on google and found out that there is another way to download all files as zip by specifying the contentversion Ids of file in URL. I can call it as URL hack and everyone mentioned that it is not recommended way. Below is URL format that you need to use:

https://xxxxxx.salesforce.com/sfc/servlet.shepherd/version/download/068xxxxxxxxxxxxxxx/068yyyyyyyyyyyyyyy/068wwwwwwwwwwwwwww/068zzzzzzzzzzzzz?

Just paste this URL and files will be downloaded as zip file.

If you have more than 1000 files in library, then you have to build different URL by specifying 10 or 15 record id in one URL. I was able to download zip file with size around 400Mb using one URL.

Approach 3: Using Apex Script & Tab Save Chrome Extension

One of my friend told me about Tab Save  chrome extension. You just need to paste all files download url and click on download.



This will download all files in your downloads folder or folder that you have specified in chrome download settings.

Now we wrote simple apex script which will send email with all URLs(file download URL) in csv file. Suppose you want to get download URLs for all files present in library "Demo Download Library", then refer below script:

Run above script in developer console by specifying your library name. You will receive email with all file download URLs. Now you just copy and paste these URLs in Tab Save edit window and click on download.

I have used Tab Save extension to download around 1500 files and it was working fine.

Now you have all 3 approaches and you can decide what to chose based on your requirements.

Hope this will help!!



Tuesday, September 3, 2019

Custom Label : Fetch all Custom Label Information using Tooling API

Considering the organization which have huge metdadata, its very difficult to fetch custom label information using Metadata API. When I tried using Metadata API in org which has more than 15000 custom label, then I was getting "IO Exception: Exceeded max size limit of 6000000" error.

CustomLabel is available in Tooling API and can be used to get all CustomLabel Information. With single callout, REST API return 2000 records and then provide "nextRecordsUrl" attribute which contain URI for next set of custom label.

I have created below code snippet which can be used to fetch all custom labels in csv file. User will receive email with attachment which contains Custom Label Id, Name and Value.

After saving this apex class, run below script in developer console and you will receive email with csv file with all custom label information.

SK_CustomlabelUtility.fetchAllCustomLabels();

Below is snapshot of csv file:



This utility can be helpful to take backup of custom labels in sandbox or production or find dependency or reference of any metadata component like fields in custom label.

Hope this will help!!

Looking forward for everyone comments and feedback.

Sunday, August 11, 2019

Accessing Child Records from sObjects using getSobjects method

Dynamic queries plays very important role when we need to run different SOQL based on different inputs. By using dynamic apex, we can store the output of queries in sObjects list and then can even check if parent record contains any child records. Even if you want to fetch child record information then you can use "getSobjects('relationshipname') method to get child information.

Below is code snippet to get all opportunities and contacts information related to Account:

Hope this will help!!!

Saturday, June 1, 2019

How to Get List of All Child Records for Given Parent Records in .csv File using Apex

If we have lot of child object for a parent object, then it becomes very difficult to find out list of all related records for a given parent. For example, Account and Contact is reference by many standard and custom objects.

Consider a scenario in which Account is parent for more than 50 objects. In this case if we have to check if account record is being reference in any of these child objects, then how we are going to do that.  Its very difficult to add all related list on account page layout or to write SOQL queries to get this information.

If we use nested queries as mentioned below, then we have limit to use only 20 nested queries.

select id, (Select id from Cases),(Select id from Contacts) from Account where Id='0010000xxxxxxx'

In order to overcome these issues, I have written a script which you can run in developer console and you will receive email with .csv file containing all child records for a given parent record.

In below mentioned script, specify the object API name and 15 or 18 digit record id.

After running this script, you will receive .csv file in email as shown below:


If you are getting below mentioned error, while running the script, the make note of below points:


  • This exception can not be handled by try and catch
  • SOQL is not performing well may be because the large volume of data or due to indexing issues on table.
  • Instead of running this script developer console, use batch apex to run this logic. You can create a custom object and first run a script to store all child objects details like relationship name, child object name. Then you can execute the logic in batch class to first fetch all these records from custom object and then fire nested queries by using relation names and store output in variable. Make sure your batch size is not greater than 20 as we have limit of 20 nested queries in SOQL. In finish method write send email code to get .csv file. If you are still getting this error, then keep on reducing the batch size.
Hope this will help!!

Looking forward for your comments and suggestions.



Thursday, May 30, 2019

How to get all Child Objects List along with Relationship Names related to Parent Object using Apex

Sometimes it is required to get the list of all child relationship names in order to identify all related child objects to a parent object.

Dynamic apex helps to find out all related child object. Suppose you want to find all related object for Account then use below code snippet:



You can specify any object API name and run this code snippet in developer console.

You can also use workbench to find out list of child objects. Navigate to Info tab and select Standard & Custom Objects.


Hope this will help!!

Friday, April 19, 2019

Way to export Code Coverage of Individual ApexClass or Trigger in .csv format

Salesforce provide Tooling API (REST API) through which we can find org metadata information.  Tooling API provide object called "ApexCodeCoverage" which can be used to find code coverage information about individual class or trigger or Org complete code coverage information.

I have created a apex script which can be run in developer console in "Execute Anonymous Window". After running this script, you will receive an email with .csv file which will contain information about code coverage for each apex class or trigger.

Below is snapshot of .csv file which you will recieve:


By using Tooling API you can find overall code coverage of your organization. Below is script which you can use in "Execute Anonymous Window".

Important things to consider in order to get have reliable coverage details:

  • Go to setup --> apex test execution ---> click on Options ---> deselect the Store only aggregate code coverage option.
  • Go to Setup --> Apex test execution ----> Clear all test history.
  • Go to Setup --> Apex classes ---> Compile all classes.
  • Go to Setup ---> Apex test execution ---> Run all test.
Once Run All Test is completed, then above scripts to get actual code coverage details of all classes or trigger or to get overall Org code coverage percentage.

You can also run the queries on "apexCodeCoverage" and "ApexOrgWideCoverage" object in developer console query editor by selecting tooloing api checkbox.

To get Org Overall Code coverage use below Query:

"SELECT PercentCovered FROM ApexOrgWideCoverage "



To get code coverage of specific apex class or trigger use below query:

SELECT Coverage FROM ApexCodeCoverage WHERE ApexClassOrTriggerId = 'xxxxxxxxx'
where xxxxxxxxx = 15 or 18 digit apex class or apex trigger id.



Hope this will help!!

Looking forward for everyone comments and suggestions...


Tuesday, February 12, 2019

Way to avoid Callouts during maintenance or site switching activity (during read only mode)

Salesforce maintain each instance in 2 different geographical locations and perform site switching after every 6 months. One location act as "active site" with all transaction and replicate all transaction in second location called as "ready site" in near real time.

Site switching helps Salesforce to perform maintenance activity and to plan for disaster recovery. Ideally this activity takes 1 hour and Salesforce instance will be available in read only mode.

If you have callout to external system and based on response you are trying to update anything inside salesforce then during read only mode Salesforce execute all callout but update on salesforce will be blocked. This may create some inconsistency in your program flow.

To avoid this scenario, first check if system is in read only mode or not then perform write operation in salesforce.

Salesforce provide below method through which you can identify if instance is read only mode or in default mode.

System.getApplicationReadWriteMode(); 

If this method return "ApplicationReadWriteMode.READ_ONLY" enum value, then the org is in read-only mode. If it return "ApplicationReadWriteMode.DEFAULT" then org is available in read/write mode.

Below is sample code which you can use in your apex logic

// check read only status for org
ApplicationReadWriteMode currentMode = System.getApplicationReadWriteMode();
String returnValue = '';

if (currentMode == ApplicationReadWriteMode.READ_ONLY) {
// avoid callout

} else if (currentMode == ApplicationReadWriteMode.DEFAULT) {
//perform callout
// write back in salesforce based on callout response

}

How to test read only mode in sandbox

Contact salesforce to enable read only test mode option for sandbox. Once enabled, you can toggle read only mode test functionality in sandbox.

Hope this will help!!!

Monday, October 29, 2018

Way to get complete RecordType Information (like DeveloperName) using describe

In summer'18 release, new methods have been introduced through which we can retrieve all recordtype info using describe information. Below are 2 methods introduced in summer'18:

  • Schema.DescribeSObjectResult.getRecordTypeInfosByDeveloperName()
  • Schema.RecordTypeInfo.getDeveloperName()

Suppose you want to retrieve all recordtype information for account object then use below code:

Below is console output

Hope this help!!

Monday, April 2, 2018

Sorting Wrapper List in ASC or DESC order based on Wrapper Property

We get these kind of scenarios in which we have List of wrapper available and want to sort it either in ASC or DESC order based on any member variable wrapper class.

Suppose we have wrapper class as mentioned below:

public class SK_sortUtilityTestWrapper {
public string category{get;set;}
        public decimal count{get;set;}
    public SK_sortUtilityTestWrapper(string ss,decimal sk){
             this.category=ss;
             this.count=sk;
    }
}

Now imagine if we have list<SK_sortUtilityTestWrapper>  and want to sort list based on count value then we can do that by using below code.
I have added a static method which can be called from developer console to see the output for reference.



From developer console execute below script:

SK_WrapperSortUtility.testWrapperListSorting();

You will see below output in debug logs:


 Hope this will help!!!!


Monday, March 26, 2018

Skinny Tables- When/Why to use?

Skinny tables are helpful when you have Large Data Volumes (more than millions of records in object). These tables improves the ready only operations like reports, SOQL query performances. Below are pointers which explain everything about Skinny Tables:

  1. Skinny tables are custom tables (read only) created by Salesforce if enabled by customer support. These tables contains important fields information instead of storing all fields information which is present in actual object.
  2. Skinny tables can be created for Account, Contact, Opportunity, Lead, Case, and custom objects.
  3. The Force.com platform automatically synchronizes the rows between skinny table and the base object,so the data is always kept current. 
  4. Soft delete records ((i.e records in the Recycle Bin with isDeleted = true) are not present in Skinny tables which improves query output.
  5. Custom indexes are also copied if present in base table.
  6. Skinny tables support only few data types(Checkbox,Date,Date and time,Email,Number,Percent,Phone,Picklist (multi-select),Text,Text area,Text area (long),URL).
  7. The Force.com platform determines at query runtime when it would make sense to use skinny tables, so you don’t have to modify your reports or develop any Apex code or API calls
  8. You need to contact salesforce customer support in order to enable this.

Things which needs to be considered before implementing Skinny tables:

  1. Skinny tables can contain maximum of 100 fields. There are also limitation on data type as mentioned above.
  2. After creating Skinny table, if you decide to add one more field in Skinny table, then you have to contact customer support. They will delete existing skinny table and will recreate new one.
  3. If you change the data type of any field which is used in Skinny table, then Skinny table becomes invalid (unusable) and you need to contact customer support to again recreate it.
  4. Skinny tables can not refer fields from another object.
  5. Skinny tables get copied to full copy sandbox after refresh but not on other sandbox. in order copy it for other sandbox, contact customer support.
  6. Skinny tables can increase the query performance of SOQL queries not SOSL queries as SOSL search based on flat file search whereas SOQL is based on database search.

Monday, February 12, 2018

How to freeze datatable header using slds standard classes

There is common scenario to freeze the table header and providing scrollbar to table body. This can be achieved by using standard slds classes no need to add custom CSS for that.

You have to use below mentioned slds classes:
  • slds-table--header-fixed_container : add this class on div by specifying the height for div
  • slds-table--header-fixed :add this class to table
  • slds-cell-fixed: add this class to <th> tag.


I have created a sample to display account list in data table inside slds card. Please find below sample code:


Hope this will help!!!

Sunday, February 4, 2018

Important facts which needs to be considered while designing any solution which includes Large data volumes in Salesforce


  • Sharing calculation is even performed for records which are in recycle bin which may impact your performance. So if you don't need records then perform hard delete on records after archiving it.

  • Only Bulk API supports hard delete functionality.

  • Adding custom indexes on records may improve query performance but can degrade the performance of database insert and update. That is reason that Salesforce doesn't allow developers to add custom indexes by themselves. You have to raise support ticket and Salesforce will evaluate your use case before adding custom indexes. So always evaluate the pros and cons before adding any new custom indexes.

  • As a best practice, don't use formula fields in where clause in SOQL. It degrade the SOQL performance if it doesn't return deterministic values (formula returns pre-defined set of values which are repeatable).

  • Now Salesforce allow you to add custom index to formula fields only if it gives deterministic results

  • Use readonly attribute on VF page if you want to query more than 50 millions records and display the result on UI by processing those records.



Wednesday, January 24, 2018

How to use Lightning Icons (svg icons) in Visualforce Page

Salesforce provide different kind of Icons which can be used in Lightning component. As now we have an option to include slds in Visualforce pages, we can utilize predefined Icons in Visualforce page.

For complete list of icons please refer Lightning Icons

Icons have been divided in 5 different categories (Standart,Utility,Custom,Doctype and Action). In this blog we are going to explore how to utilize these icons in VF page.

First of all, you have to include SLDS in VF page by using <apex:slds/> tag as shown below:

<apex:page showHeader="false" standardStylesheets="false" sidebar="false" docType="html-5.0" >
<head>
  <apex:slds /> 
</head>

<body class="slds-scope">
<!--body content-->
</body>
</apex:page>

Now in order to refer any svg icon, use below code:

<span class="slds-icon_container slds-icon-custom-custom22 slds-icon-text-default" >
<svg aria-hidden="true" class="slds-icon ">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="/apexpages/slds/latest/assets/icons/custom-sprite/svg/symbols.svg#custom22">
</use>
</svg>
<span class="slds-assistive-text">Custom 22</span>
</span>

Now i will explain all css class options:
  • Icon background color(.slds-icon_container)  : This is used to provide background color to icon. By default, (.slds-icon_container) has a transparent background. In order to provide backgroud similar to specified in icons in SLDS, use .slds-icon-[cateory name]-[icon name] class. 
For example, for account icon, I need to provide background, then use .slds-icon-standard-account class.

<span class="slds-icon_container slds-icon-standard-account" >
<svg aria-hidden="true" class="slds-icon">
<use xmlns:xlink="http://www.w3.org/1999/xlink" 
xlink:href="/apexpages/slds/latest/assets/icons/standard-sprite/svg/symbols.svg#account">
</use>
</svg>
<span class="slds-assistive-text">Account</span>
</span>

  • Icon color(.slds-icon): By default, Icons color (.slds-icon) is white. Icon color can be changed by using below classes:
  1. .slds-icon-text-default: same as default text
  2. .slds-icon-text-warning: yellow
  3. .slds-icon-text-error: red
Note that doctype icons have specific colors that cannot be changed with the CSS property.
  • Icon size(.slds-icon): You can use below class to specify the icon size:
  1. Extra-small (.slds-icon--x-small): typically used for small alert icons, with no background color.
  2. Small (.slds-icon--small): 1.5rem×1.5rem (for icons with a background color).
  3. Medium (default - requires no additional class): 2rem×2rem.
  4. Large (.slds-icon--large): 3rem×3rem.
Below is sample VF page code which display different svg icons belonging to different categories.

VF Page snapshot:

Hope this will help!!

Monday, December 25, 2017

Custom Permissions : Way to control user access to different functionality in Salesforce

Problem Statement

There is a very common scenario in which admin has to configure different validation rules, workflow rules which fires based on User Id or Profile Id.

Consider below mentioned scenarios:
  • Position (Custom Object) records can be closed by user belonging to specific profile.
  • You have created a VF page where you display specific section to users based on profile. 

In both scenarios, you have to check for profile Id in validation rule as well as in VF (to rendered specific section).





Now after some time if you have to enable the above mentioned functionality to new profile or to specific user then, you have to modify the validation rule as well as your VF page code.

Solution

You can use custom permission for these kind of scenarios.

Custom permission is just a record which can be referenced in validation rule, workflow rules, VF, Apex etc. You can assign custom permission to profile or permission set (similar way in which we assign VF page and Apex class).

Now you can check custom permission in validation rules and VF by using global $Permission variable.

Steps to use custom permission and use as per above scenario:
  • Create custom permission (Navigate to Set Up--> Develop--> Custom Permissions).
  • Create new custom permission.

  • Add custom permission to profile or permission set(navigate to Enable custom permission section).

  • Modify the validation rule to and VF to refer custom permission instead of profile id.



So custom permission help us to control different functionality in salesforce to different users. If you have to enable functionality for single user then add custom permission to permission set and then add that permission set to user.

Alternate Approach

All admins/developers were using custom setting to control functionality for different users but after launch of custom permission, jobs of developer or admin will be easy.

Custom Permission in Apex

You can use below static method to find out list of user who have permission for custom permission:


public static List<User> findUsersWithCustomPermission(String customPermissionname)
{
    List<user> userList = new List<User>();
Set<Id> permissionSetIds = new Set<Id>();
    for (SetupEntityAccess access : [ SELECT ParentId FROM SetupEntityAccess 
WHERE SetupEntityId IN ( SELECT Id FROM CustomPermission 
            WHERE DeveloperName = :name)]) {
        permissionSetIds.add(access.ParentId);
    }
if(permissionSetIds.size()>0){
userList = [SELECT Username FROM User 
WHERE Id IN (SELECT AssigneeId FROM PermissionSetAssignment
WHERE PermissionSetId IN :permissionSetIds)];
}
    return userList;
}

Hope this will help!!!

Saturday, December 16, 2017

Insufficient Privileges : How to troubleshoot record access issue in Salesforce

"Insufficient Privileges" is common error which appears on user interface if user tries to access/edit a record. As we know that apart from OWD and profile, record can be shared by using sharing rules, role hierarchy, manual sharing or apex sharing.



If some user report this kind of issue, then instead of checking all sharing options, we can directly run below query to check what kind of access that user have for given record.

SELECT RecordId, HasReadAccess, HasTransferAccess, MaxAccessLevel, HasAllAccess, HasDeleteAccess, HasEditAccess FROM UserRecordAccess  WHERE UserId = “005xxxxxxxxx”AND RecordId = “001xxxxxxxx”

Where 005xxxxxxxxx is user id and  001xxxxxxxx is record Id.

HasAllAccess Indicates whether a user has all access–read, edit, delete, and transfer—to the record (true) or not (false).
HasReadAccess, HasEditAccess , HasDeleteAccess ,HasTransferAccess return Boolean value.
MaxAccessLevel return access level like None, read, Edit,Delete,Transfer and All.


This query will help to understand whether user has access to record or not. After that you can check different options (sharing rules, role, apex sharing etc.) to find out why that user is not having access to record.

Hope this will help!!!

Tuesday, December 12, 2017

Formatting and Localizing dates in javascript in Lightning

Date formatting in javascript

AuraLocalizationService JavaScript API provides methods for localizing dates and formatting.

Use the formatDate() to format date by providing format string as second argument.

formatDate (String | Number | Date date, String formatString)

Use $A.localizationService to use the methods in AuraLocalizationService.

Below are few examples of format string and their output:

var now = new Date();
var dateString = "2017-12-12";

// Returns date in the format "Dec 12, 2017"
console.log($A.localizationService.formatDate(dateString));

// Returns date in the format "2017 12 12"
console.log($A.localizationService.formatDate(dateString, "YYYY MM DD"));

// Returns date in the format "December 12 2017, 11:03:47 PM"
console.log($A.localizationService.formatDate(now, "MMMM DD YYYY, hh:mm:ss a"));

// Returns date in the format "Dec 12 2017, 11:03:57 PM"
console.log($A.localizationService.formatDate(now, "MMM DD YYYY, hh:mm:ss a"));

Refer below link for more details:
tokens supported in format string

Localization

Lightning framework provides client-side localization support on input/output elements. This helps in customize the date and time format.

For example, below code will display date in Europe/Berlin timezone (Dec 13, 2017 2:17:08 AM)

<aura:component>
    <ui:outputDateTime value="2017-12-13T02:17:08.997Z"  timezone="Europe/Berlin" />
</aura:component>

To customize date and time format use, lightning:formattedDateTime.

The attributes on lightning:formattedDateTime helps you to control formatting at a granular level. For example, you need to display the date using the MM/DD/YYYY format, then use below code:

<lightning:formattedDateTime value="{!v.datetimeValue}" timeZone="Europe/Berlin" year="numeric" month="numeric" day="numeric"/>


datetimeValue can be set in controller code either in doInit or any other function as mentioned below:

var date = new Date();
component.set("v.datetimeValue", date)

Locale Information on client side controller

  • $A.get("$Locale.timezone")  : This will return timezone like Europe/Paris, Europe/Berlin etc.
  • $A.get("$Locale.currency") : This will return org currency locale like "$", "¥" etc.

Hope this will help!!!!

Monday, November 6, 2017

Declarative Sharing Vs Apex Managed Sharing

Force.com platform provides declarative sharing option which are easy to configure and meets basic data sharing requirements.

Different declarative sharing options

  • Record Ownership
Record owner will have read, edit, delete, share and transfer access.
  • Teams
Account teams, sales team and case team allow group of users to have access to different account, opportunities and case records.
  • Role hierarchy
This allow users in higher role to have same level of access to data which users have in lower hierarchy.
  • Sharing rules
You can create owner based or criteria based sharing rules in system which will open up the record access to users. Records can be shared to public group, roles,roles and internal subordinates, roles internal and portal subordinates etc.

Sharing rules also allow to share data with external users. The default external access level must be more restrictive or equal to default internal access level.

For example, if external sharing default is set to Public Read-Only for custom object, then valid internal default settings will be Private and Public Read Only.
  • Manual Sharing
Manual Sharing is also known as User Managed Sharing. This option allow user to share record manually with another user or public group, portal roles, portal users, roles, roles and internal subordinates, roles internal and portal subordinates etc.

Remember if record owner share record manually with another user and later on record owner changes, then manual sharing record will be deleted.

Apex Managed Sharing

This allows developers to share records by using apex code. This is also known as "Programmatic Sharing". Object share records can be created for standard and custom object but custom sharing reason can be defined for custom object only.

For example, if we have to share a record with a user specified in lookup field, then you can use trigger to create record in share table to provide access. 
Valid access level for records are Edit/ Read.

If OWD for object is either Public Read only or Private, then share table will exist for that object. You can create record in that share table to provide access to any user. Below are 4 fields you need to specify in order to create record in share table:
  • ParentId : 15 digit or 18 digit id of record which you want to share.
  • UserOrGreoupId : User id or group Id
  • Access Level : Edit or Read. This field must be set to an access level that is higher than the organization’s default access level for the parent object.
  • RowCause : You can specify the reason for sharing record. First define sharing reason for custom object. For standard object, you can specify Manual.
 You can not update ParentId field.

You can share record with same user or group by using different sharing reasons.

Consideration while using Apex Managed Sharing
  • If record owner changes, then sharing created through apex managed sharing (if row cause is not manual and uses custom sharing reasons) are maintained but if user share record manually, then record sharing will be lost if owner changes.
  • User with "modify All Data" can only add, edit or delete records in share table.