0

I am trying to migrate notes from another CRM into Salesforce. Based on the salesforce documentation (link below) it seems to imply I need to have my notes in text file format to import them into the ContentNote object.

[https://help.salesforce.com/articleView?id=000339316&type=1&mode=1][1]

I want to use the ContentNote object as I need to relate Notes to Opportunities. My notes are not in file format though and it's not really feasbile to manually do this work as I have hundreds of notes to import across multiple objects.

I have the content of each note in a column in my csv. Is there a way to import into the ContentNotes object without using actual files?

Maybe the API or other if it's not possible using the Data Loader?

2 Answers 2

1

Similar to Rick's answer, I once wrote a trigger to do exactly this.

First, create an object (I named it Note_Creation_Trigger), with the following fields

  1. Content__c (Long Text Area), representing the contents of the note
  2. Title__c (Text), representing the title of the note
  3. Owner_Id__c (Text or User Lookup), representing the Id of the user owner
  4. Related_Record_Id__c (Text), representing the record that note should reside in
  5. Share_Type__c (Text), can be I, V or C. See https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_contentdocumentlink.htm (search ShareType)

Then add the following Trigger

trigger NoteCreationTrigger on Note_Creation_Trigger__c (before insert, before update, after insert, after update) {

    if (Trigger.isInsert && Trigger.isAfter) {

        List<ContentNote> notes = new List<ContentNote>();
        List<ContentDocumentLink> links = new List<ContentDocumentLink>();
        Map<Id, ContentNote> notesById = new Map<Id, ContentNote>();

        for(Note_Creation_Trigger__c triggerNote : Trigger.new){
            ContentNote note = new ContentNote();
            note.Content = Blob.valueof(triggerNote.Content__c);
            note.Title = triggerNote.Title__c;
            note.OwnerId = triggerNote.Owner_Id__c;

            notes.add(note);
            notesById.put(triggerNote.Id, note);
        }

        if(notes.size()>0){
            insert notes;
        }

        for(Note_Creation_Trigger__c triggerNote : Trigger.new){
            ContentDocumentLink documentLink = new ContentDocumentLink();
            documentLink.LinkedEntityId = triggerNote.Related_Record_Id__c;
            documentLink.ContentDocumentId = notesById.get(triggerNote.Id).Id;
            documentLink.ShareType = triggerNote.Share_Type__c != null ?  triggerNote.Share_Type__c : 'I';

            links.add(documentLink);
        }

        if(links.size()>0){
            insert links;
        }
    }
}

Import the notes into this object and all should be good.

EDIT: @user1669296 requested that I post the unit test. See code below. It is just to pass code coverage (provides 100% coverage).

@IsTest
private class NoteCreationTest {
    static testMethod void coverageTest() {

        Account a = new Account(Name = 'Test Account');
        insert a;

        insert new Note_Creation_Trigger__c(
                Content__c = 'Content',
                Title__c = 'Title',
                Related_Record_Id__c = a.Id,
                Owner_Id__c = UserInfo.getUserId()
        );
    }
}
4
  • N.B. the if (notes.size()>0) and if(links.size()>0) can be dispensed with; DML on empty collections does not burn DML statements; less-is-more.
    – cropredy
    Mar 12, 2021 at 5:16
  • good catch. I wrote this code a while back, I've since stopped doing empty list checks Mar 12, 2021 at 13:11
  • Are you able to add the test code for this trigger @MenachemShanowitz to make the solution deployment-ready? ;) Mar 25, 2021 at 0:44
  • @user1669296 Done. Mar 26, 2021 at 14:24
0

You could accomplish this by importing your file into another object and creating a flow or trigger to create the ContentNote and ContentDocument.

I elected to build a record based flow based on the Task object and copied Task.Subject to ContentNote.Title and Task.Description to ContentNote.Content.

Don't forget to create the ContentDocument to link the note to the parent. Insert this object in the same flow after the note is in.

Cleanup all the Tasks or whichever object afterwards.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .