Tuesday, December 26, 2023

Export all Custom Metadata Records in CSV file using Apex

Using apex, we can export all custom metadata records in CSV files. This is sometime needed if we want to review all custom metadata records after sandbox refresh or to check the dependency of any field or attribute in all custom metadata records.


Below is apex class which can be used for this and once you execute its method from developer console, you will receive email with csv that contain all custom metadata records.

Open developer console and open execute anonymous window. Execute below script:

SK_CustomMetadataUtility.exportAllCMRecordsInCSV();


Below is snapshot of csv file:


Note:

  • This script will specify the custom metadata field api name and its value seperated by "&SK&" delimiter.
  • All fields and its values are seperated by comma.
  • You can modify this method to fetch all custom metadata related to installed packages by specifying a parameter for namespace.


Hope this will help!!

 

Sunday, August 20, 2023

Open Standard Email composer from LWC Component - Global Email Quick Action

As we all know that we can create Email Actions in Salesforce but capability to invoke Email Action from LWC components was not present. After Winter' 23, Salesforce allowed to invoke global email action from custom components (from Aura and LWC both).

In this blog, I am going to explain how to invoke email action from LWC component. You can launch email composer from custom button. 

We have to use the lightning-navigation and lightning-page-reference-utils components to create a QuickAction (Global) Send Email action, which opens an email draft with pre-populated field values.

We will create simple LWC component which will have button. Once we click on this button, email composer will open. Below is sample code for reference:


Note:

  • You can default email properties like subject, body, ccAddress, toAddress and fromEmailAddress.
  • You always need to provide record. Whenever you click on send button after composing email, system will create an emailmessage record with relatedToId as specified recordId.
  • encodeDefaultFieldValues is being provide to specify all default values.

Snapshots for reference:




Hope this will help!!






Thursday, August 3, 2023

Automatically Remove Special Characters from Filename while Uploading Files in Salesforce

 As we all know that we can perform URL hack to download all files related to parent record from salesforce. We have observed that sometime downloaded file name is changed to contentversion recordId by salesforce instead of actual file name. 

It is my observation that if file name contains special characters, then when we perform download All, file name is changed to "068xxxxxxxxxxxxxx.pdf".

I have added 2 files to account record for reference:



Now I can generate download URL if I have contentversionId of these 2 files. In my case the download URL will be:

https://xxxx/sfc/servlet.shepherd/version/download/0680K00000kLSdbQAG/0680K00000kLSfwQAG

where xxxx is you org domain URL.

You can use below script to generate download all files URL if you know the parent record Id.


If I open this URL, I will zip file which will contain both files and when I will extract it, it will appear as shown below:


As my observation, if any special character is present in file name then salesforce changes the file name. If "-" character is present, then salesforce won't change file name.

For this kind of scenarios, I recommend to have script in place which will remove all special characters from file name whenever file is being uploaded. You can write trigger on contentVersion object to remove special characters from file name. Below is code snippet which can help:



Hope this will help!!!!



Wednesday, July 5, 2023

FieldDefinition - How to get list of all fields present in any Object using Tooling API in Salesforce

We can utilize Tooling API to get information of all fields present in a object. You can put different filters like to get all fields or specific fields like auto number fields, ExternalID fields etc.

Below is apex class which contains method to get all fields. Remember that callout uses Named Credential in order to do handshake with SFDC org.

This method contains 3 parameters:

  • selOrgNCName : Name of Named Credential created to connect to SFDC org
  • objAPIName : Specify the object API name in order to get list of all fields
  • namespacePrefix : Specify namespacePrefix if you want to retrieve fields related to any installed packages. If you want to get list of fields created in SFDC org, then specify blank or NULL.
Note:
  • I have added filter not to return auto number fields. If you want to get those fields details then remove it from query string.
  • If you want to query only External Id fields then specify filter as DataType+Like+\'%25(External+ID)%25\'';


Hope this will help!!



Tuesday, July 4, 2023

EntityDefinition - How to get list of all objects present in any SFDC org using tooling API

Salesforce provide Metadata API through which we can metadata information present in any SFDC org. Metadata API is SOAP based which involves consuming WSDL and then calling methods provided in WSDL.

Salesforce has introduced Tooling API which is REST based and can be used to get metadata information from any salesforce org. Tooling API is very easy to implement.

EntityDefinition provides information about standard and custom metadata. Before invoking any Tooling API endpoint, we need to do handshake with SFDC org. You can utilise Oauth 2.0 (username-password flow) or create "Named Credential" for SFDC org from which you want to fetch information.


Below is Apex class which contains method through which we can get all object details:

"findAllObjects" Method contains 3 parameters: 

  • selOrgNCName : Name of Named Credential created to connect to SFDC org
  • namespacePrefix : Specify namespacePrefix if you want to retrieve objects related to any installed packages. If you want to get list of objects created in SFDC org, then specify blank or NULL.
  • objName : specify search string if you want to get list of specific objects that contain that string. Pass blank or NULL if you want to retrieve all objects.


Hope this will help!!

Monday, June 26, 2023

Composite Batch- Way to call multiple REST API in single request (sending multiple request to Salesforce)

Composite batch allows to send up to 25 separate API request in a single call to salesforce. Best thing about this is that all sub-request are considered as separate call. Suppose you want to move multiple records to next salesforce org or want to create multiple records in salesforce from external system then this will help you.


By using composite batch API, I am going to create a new Account record, Update existing Account record (by using external Id field -Account_Unique_Id__c) and query account record in same API call.

Below are details you need:

REST API service URI-   /services/data/v56.0/composite/batch/

Request Body Sample-

{

"batchRequests": [{

"method": "POST",

"url": "v56.0/sobjects/Account",

"richInput": {

"Name": "New Account using Composite Batch"

}

},

{

"method": "PATCH",

"url": "v56.0/sobjects/account/Account_Unique_Id__c/ACC-000033",

"richInput": {

"NumberOfEmployees": "2000",

"Type": "Customer"

}

}, {

"method": "GET",

"url": "v56.0/query/?q=SELECT+name+from+Account+where+Account_Unique_Id__c='ACC-000033'"

}

]

}


Response Body:

{

"hasErrors": false,

"results": [{

"statusCode": 201,

"result": {

"id": "0010K00002mziKJQAY",

"success": true,

"errors": []

}

}, {

"statusCode": 200,

"result": {

"id": "0010K00002PBQTyQAP",

"success": true,

"errors": [],

"created": false

}

}, {

"statusCode": 200,

"result": {

"totalSize": 1,

"done": true,

"records": [{

"attributes": {

"type": "Account",

"url": "/services/data/v56.0/sobjects/Account/0010K00002PBQTyQAP"

},

"Name": "Sunil Test Account"

}]

}

}]

}


Important points to consider while using this:

  • The response bodies and HTTP statuses of the subrequests in the batch are returned in a single response body.
  • Each sub request counts against rate limits.
  • Each API request are considered as separate and you can not pass information between them.
  • If one API request get successfully completed from batch request, then it gets committed. If any subsequent request fails then previous request is not rollbacked automatically.
  • Batch request should complete in 10 minutes. If batch times out then the remaining sub requests aren’t executed

Hope this will help!!



Sunday, March 26, 2023

Custom Events in Lightning Web Components : Pass data from child component to parent component

In order to communicate from child component to parent component in LWC, we use custom events. Custom events helps in passing data from child components to parent component in containment hierarchy.

If you want to refer on how same thing can be achieved in Aura Components then refer below article:

Component Events: Way to Communicate Between Components in Containment Hierarchy


Lightning component can create and dispatch events in a component’s JavaScript class. To create an event, use the CustomEvent() constructor. To dispatch an event, call the EventTarget.dispatchEvent() method.

The CustomEvent() constructor needs one required parameter, which is a string indicating what event has been performed. You can define ant string as event name. While defining event name, follw below recommendation based on DOM event standard.

  • No uppercase letters
  • No spaces
  • Use underscores to separate words

Steps involved in implementing custom events

1. Create custom event in child component and dispatch that event.

    const newEvent = new CustomEvent("search");
    this.dispatchEvent(newEvent);

2. Handle the event in parent component.

When you declare the child component in parent component, then use "on" event handler to execute logic whenever the event is fired. Suppose you event name which is dispateched from child component is "search", event handler name will be "onsearch".

<c-sk-child-cmp onsearch={capturedEvent}></c-sk-child-cmp>
capturedEvent(event) {
    console.log("**recieved event-->" + event);
}

Custom events to inform what action is performed in child component

If you want to inform parent component about what has been clicked or operation performed in child component, then you can simply define custom event as mentioned below:

<template>
    <lightning-button label="Edit" onclick={editAction}></lightning-button>
    <lightning-button label="New" onclick={deleteAction}></lightning-button>
</template>

    editAction() {
const newEvent = new CustomEvent("edit");
        this.dispatchEvent(newEvent);
    }

    deleteAction() {
const newEvent = new CustomEvent("delete");
        this.dispatchEvent(newEvent);
    }


Custom events to pass data to parent component

If you want to pass data to parent component, then set a detail property in the CustomEvent constructor. 

You can pass any record id  or any data from child component in detail property.

@track selectedRecordId;

handleResponse(event) {
const answerEvent = new CustomEvent("search", { detail: this.selectedRecordId});
this.dispatchEvent(answerEvent);
}

Parent component can access detail property in order to read data passed from child component

 capturedEvent(event) {
    console.log("**recieved event detail-->" + event.detail);
 }


Note: There is no restriction on data type of detail property but is is recommended to pass only primitive data. JavaScript passes all data types by reference except for primitives. If a component includes an object in its detail property, any listener can mutate that object without the component’s knowledge. This is a bad thing! It’s a best practice either to send only primitives, or to copy data to a new object before adding it to the detail property. Copying the data to a new object ensures that you’re sending only the data you want, and that the receiver can’t mutate your data.

Lets try to understand custom events through simple example:

We will create a child component "skChildCmp" which will contain few buttons. Once user will click on one of the button, child component will pass resource URL based on button click to parent component and parent component will display that URL.

Below is snapshot for parent component:


Now when user clicks on SFDCSTUFF BLOGS button, URL for that button will be appearing on parent component.


If user clicks on TRAILHEAD button, then parent will display URL for that.


Below is complete code snippet:



Hope this will help!!