Let’s say, you have a SharePoint folder with the list of opportunities as sub folders. Consider, the sub folders names are the names of your opportunities in Salesforce Org. To retrieve files based on the opportunity name from SharePoint, follow these steps.
Search for “Collaboration” and Drag the component COLLABORATION Butler (O365 Edition) anywhere on to the page, according to your requirement.
Set the fields as below
• Site Library URL
Set the full URL to your site Library. In this example, this is nothing but the complete URL of the SharePoint folder where your opportunities sub folders are residing. This can be dynamic. You can create a field on opportunity object and enter the URL values in this field for every opportunity record and refer it in the URL.
Example:
https://…….com/sites/C……o/Shared Documents
• Path to Directory
This is the path to the directory where your opportunity related files are being stored. Append the mergefield [[!Name!]] to this path, so that collaboration butler will only retrieve the files based on the opportunity name. If you want to use any custom field instead of standard field “Name”, you can refer that custom field as well.Example:/C….st/C……s/[[!Name!]]
You can set below options according to your requirements
You might have already setup and configured the Collaboration Butler. You can login to the SharePoint from any opportunity and the files will be retrieved automatically.
If you would like to merge SharePoint PDF Documents, we have implemented a custom solution for this.
Custom Solution involves creation of following components:
Apex classes to fetch files from SharePoint and merge the selected files
public class CheckboxChoice {
@AuraEnabled
//@InvocableVariable(label='Choice Value')
public String value;
@AuraEnabled
//@InvocableVariable(label='Choice Label')
public String label;
public CheckboxChoice(String value, String label) {
this.value = value;
this.label = label;
}
}
public class getFilesFromSharePoint {
@InvocableMethod(label='Get Files From SharePoint' description='Get Files From SharePoint')
public static List<FlowOutput> getFiles(List<flowinputs> flowinputs) {
Opportunity opp =[Select Id, Name from Opportunity where Id=:flowinputs[0].recordId];
cadmus_una.MSGraphClient cli=new cadmus_una.MSGraphClient();
cli.prepareRefreshToken(UserInfo.getUserId());
cadmus_una.CollabMSGraphClient.GetDriveResponse gdr = cli.getSiteDrive(UserInfo.getUserId(),flowinputs[0].libraryUrl);
cadmus_una.CollabMSGraphClient.GetDriveContentResponse response = cadmus_una.CollabMSGraphClient.getDriveItemsByPath(UserInfo.getUserId(), gdr.data.id, flowinputs[0].path+'/'+opp.Name);
List<FlowOutput> outputs = new List<FlowOutput>();
FlowOutput output = new FlowOutput();
List<List<CheckboxChoice>> allChoices = new List<List<CheckboxChoice>>();
List<CheckboxChoice> choices = new List<CheckboxChoice>();
for (cadmus_una.MsGraphContentResponse.Value value : response.data.value) {
choices.add(new CheckboxChoice(value.name, value.name));
}
output.filechoices = choices;
outputs.add(output);
return outputs;
}
public class flowinputs {
@InvocableVariable(label='libraryUrl')
public String libraryUrl;
@InvocableVariable(label='recordId')
public String recordId;
@InvocableVariable(label='Path')
public String path;
}
public class FlowOutput {
@InvocableVariable(label='filechoices')
public List<CheckboxChoice> filechoices;
}
}
public class mergeselectedFileFromSharePoint{
@InvocableMethod(label='Merge Selected Files From SharePoint' description='Merge Selected Files From SharePoint')
public static void mergeFiles(List<flowinputs> flowinputs) {
Opportunity opp =[Select Id, Name from Opportunity where Id=:flowinputs[0].recordId];
system.debug(flowinputs[0].selectedFiles);
List<String> selectedFiles = new List<String>();
selectedFiles = flowinputs[0].selectedFiles.split(';');
List<Blob> docs = new List<Blob>();
List<filedata> filedataList = new List<filedata>();
cadmus_una.MSGraphClient cli=new cadmus_una.MSGraphClient();
cli.prepareRefreshToken(UserInfo.getUserId());
cadmus_una.CollabMSGraphClient.GetDriveResponse gdr = cli.getSiteDrive(UserInfo.getUserId(),flowinputs[0].libraryUrl);
Map<String,blob> mapOfFileNameAndBlob = new Map<String,blob>();
for(String str : selectedFiles){
cadmus_una.CollabMSGraphClient.GetFileResponse resp = cli.getFile(UserInfo.getUserId(),
flowinputs[0].libraryUrl,
true, flowinputs[0].path+'/'+opp.Name+'/'+str);
if(resp.isError()) {
System.debug(LoggingLevel.ERROR, resp.error + ': ' + resp.error);
} else {
mapOfFileNameAndBlob.put(str,resp.data);
}
}
for(String str1: selectedFiles){
cadmus_una.CollabMSGraphClient.GetDriveResponse di=cadmus_una.CollabMSGraphClient.getDriveItemByPath(UserInfo.getUserId(),
gdr.data.id, flowinputs[0].path+'/'+opp.Name+'/'+str1);
if(di.isError()) {
System.debug(LoggingLevel.ERROR, di.error);
} else {
filedata fd = new filedata();
fd.fileName=str1;
fd.fileURL = di.data.downloadUrl;
fd.fileBlob = mapOfFileNameAndBlob.get(str1);
filedataList.add(fd);
}
}
cadmus_core.UtilClasses.PdfMergeInput pdfMergeInput = new cadmus_core.UtilClasses.PdfMergeInput();
pdfMergeInput.documents = new List<cadmus_core.UtilClasses.PdfMergeDocument>();
for(filedata fl : filedataList){
cadmus_core.UtilClasses.PdfMergeDocument tempdoc = new cadmus_core.UtilClasses.PdfMergeDocument();
tempdoc.filename = fl.fileName;
tempdoc.base64 = EncodingUtil.base64Encode(fl.fileBlob);
tempdoc.downloadUrl = fl.fileURL;
pdfMergeInput.documents.add(tempdoc);
}
cadmus_core.UtilClasses.PdfMergeResult result = cadmus_core.ConvertController.mergePdfs(pdfMergeInput);
System.debug(result.base64);
System.debug(result.sharepointUrl);
Blob fileContent = EncodingUtil.base64Decode(result.base64); //this can be the VersionData of a ContentVersion
cadmus_una.CollabMSGraphClient.SaveFileResponse response = cadmus_una.CollabMSGraphClient.saveFile(UserInfo.getUserId(), flowinputs[0].libraryUrl, true, flowinputs[0].path+'/'+opp.Name+'/'+flowinputs[0].mergedFileName+'.pdf', fileContent);
}
public class flowinputs {
@InvocableVariable(label='libraryUrl')
public String libraryUrl;
@InvocableVariable(label='recordId')
public String recordId;
@InvocableVariable(label='Path')
public String path;
@InvocableVariable(label='Selected Files')
public String selectedFiles;
@InvocableVariable(label='Merged File Name')
public String mergedFileName;
}
public class FlowOutput {
@InvocableVariable
public String fileName;
}
public class filedata {
public String fileName;
public String fileURL;
public Blob fileBlob;
}
}
2. Create Screen Flow as shown below
Create below resources in screen flow
Drag screen element and add below input text boxes to screen element
Add Apex action and choose “’Get Files From SharePoint”. Set all input values to the apex action as below
Drag screen element to show success message
Drag screen element to your fault path top show error message
3. Quick action on the object to refer the above flow(In our example, opportunity)
Open any opportunity and edit the page. Add the above quick action in the page and save it.
Click on the quick action and below screen will be displayed. Enter your library URL and path in the fields and click on Get Files. This will fetch all the documents from the SharePoint which are related to this opportunity(Apex class will fetch files if the opportunity name is same as the folder name in you SharePoint)
Select files and click on Merge Merged document will be in Collaboration Butler section and will be uploaded to SharePoint folder as shown below.
Select the merged file from Collaboration Butler section and click on Send email to send out merged files according to your requirements
Example: Let’s say, you have a Contact field “Primary Contact” on opportunity and you need to send the merged document to that content.
To do this follow below steps:
Create Data source which will fetch the primary contact details
Create a pack record and choose any dummy doc config as we are not using doc config here. However that field is mandatory on page layout.
Create a lightning template or email template for the email body and refer this in Actionable record.Create an Actionable record to the pack record as shown below.
Open any opportunity and edit the page, go to the collaboration butler component, copy the PDF butler pack Id which was created in step 2 and paste it in the component. Save the page.
Select the Merged file and click on pack action “Send Email”
The template bodywhich was created in step 3and the document will automatically populate, add recipients and emailcan be sent.
Change the CheckboxChoice apex class code to below
public class CheckboxChoice implements Comparable{
@AuraEnabled
//@InvocableVariable(label='Choice Value')
public String value;
@AuraEnabled
//@InvocableVariable(label='Choice Label')
public String label;
public CheckboxChoice(String value, String label) {
this.value = value;
this.label = label;
}
public Integer compareTo(Object obj) {
CheckboxChoice other = (CheckboxChoice) obj;
// Null safety
if (label == null && other.label == null) return 0;
if (label == null) return -1;
if (other.label == null) return 1;
// CASE-SENSITIVE sort
return label.compareTo(other.label);
}
}
Add Sort() method
public class getFilesFromSharePoint {
@InvocableMethod(label='Get Files From SharePoint' description='Get Files From SharePoint')
public static List<FlowOutput> getFiles(List<flowinputs> flowinputs) {
Opportunity opp =[Select Id, Name from Opportunity where Id=:flowinputs[0].recordId];
cadmus_una.MSGraphClient cli=new cadmus_una.MSGraphClient();
cli.prepareRefreshToken(UserInfo.getUserId());
cadmus_una.CollabMSGraphClient.GetDriveResponse gdr = cli.getSiteDrive(UserInfo.getUserId(),flowinputs[0].libraryUrl);
cadmus_una.CollabMSGraphClient.GetDriveContentResponse response = cadmus_una.CollabMSGraphClient.getDriveItemsByPath(UserInfo.getUserId(), gdr.data.id, flowinputs[0].path+'/'+opp.Name);
List<FlowOutput> outputs = new List<FlowOutput>();
FlowOutput output = new FlowOutput();
List<List<CheckboxChoice>> allChoices = new List<List<CheckboxChoice>>();
List<CheckboxChoice> choices = new List<CheckboxChoice>();
for (cadmus_una.MsGraphContentResponse.Value value : response.data.value) {
choices.add(new CheckboxChoice(value.name, value.name));
}
Choices.sort(); - Added here
output.filechoices = choices;
outputs.add(output);
return outputs;
}
public class flowinputs {
@InvocableVariable(label='libraryUrl')
public String libraryUrl;
@InvocableVariable(label='recordId')
public String recordId;
@InvocableVariable(label='Path')
public String path;
}
public class FlowOutput {
@InvocableVariable(label='filechoices')
public List<CheckboxChoice> filechoices;
}
}