+ Start a Discussion

Cloning a Campaign and CampaignMemberStatus

Hello, I am trying to clone a Campaign along with CampaignMemberStatus.


In the following code segment, there are two approaches (one commented out) both of which fail with the error: Required fields are missing: [Label]: [Label]


Any help appreciated.  Thanks


    public PageReference Duplicate() {
        if (selection == '0') {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Please select a template to use before clicking New.'));
            return null;
        Campaign template = [SELECT Name FROM Campaign WHERE id = :selection];
        Campaign clone = template.clone(false);    // Create a clone without the id.
        clone.Template__c = false;
        clone.IsActive = true;
        clone.Name = 'New Campaign';
        insert clone;
        // Now that the Campaign has been inserted, we need to insert the CampaignMemberStatus list
        // BOTH OF THE FOLLOWING Approaches to insert the cloned list cause the following error:
        // Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Label]: [Label]
        List<CampaignMemberStatus> statuslist = [SELECT Id from CampaignMemberStatus WHERE CampaignId = :selection];
        List<CampaignMemberStatus> clonelist = statuslist.deepClone(false);
        for (CampaignMemberStatus status : clonelist) {
            status.CampaignId = clone.Id;
        // List<CampaignMemberStatus> clonelist = new List<CampaignMemberStatus>();
        // for (CampaignMemberStatus status : statuslist) {
        //     CampaignMemberStatus sclone = status.clone(false);
        //     sclone.CampaignId = clone.Id;    // Point this CampaignMemberStatus to the inserted Campaign
        //     clonelist.add(sclone);
        // }
        insert clonelist;
        PageReference editPage = new ApexPages.StandardController(clone).edit();
        editPage.setRedirect(true); // ???  Do I need to do this?
        return editPage;


Here's the doc's on CampaignMemberStatus




I believe you need to pull in more info from your query of status:


        List<CampaignMemberStatus> statuslist = [SELECT Id, CampaignId, HasResponded, Label, IsDefault from CampaignMemberStatus WHERE CampaignId = :selection];


Then you can change the Campaign ID & then insert the new statuses after the campaign.


2nd note - I'm not sure that you can directly grab the ID of clone without querying the database after insert.  You may need to create another line to grab it:


Campaign c = [ SELECT ID FROM Campaign WHERE  ID=clone.ID];


sclone.CampaignId = c.Id;


Thanks for the response.


It looks like your solution will work.  Since I only wanted to set a few fields after cloning, I was able to eliminate the Apex code handling the vf page button click and replace the click action with a URLFOR as follows:


            <apex:commandButton value="New Campaign"    action="{!URLFOR($Action.Campaign.Clone,selection,[cpn1='New Campaign&cpn16=1&00NT0000000zjpi=0'])}" rendered="{!NOT(error)}"/>      


In this case, selection is the id of the Campaign I cloned, cpn1 is the DOM id for the Campaign Name, apn16 is the DOM id for the Active checkbox, and the hard coded sf id is the DOM id for a custom checkbox field that I have on the Campaign.  The standard sf clone action for Campaign clones the CampaignMemberStatus as well and works just how I wanted.


It would be nice if salesforce could provide a way to access the input fields without having to hard code the DOM ids.

Note, that when the page gets deployed to production, the hardcoded sf id will need to be looked up by viewing the page source.


Hopefully, someone will be able to use the URLFOR example, as they are also not simple to figure out.


Thanks again,



Hello... Could you explain how you determined cpn1 was the campaign Name and cpn16 was the Active flag. I see where Custom fields would use the ID as shown in the URL but not sure I understand the standard SFDC DOM Id's.




<apex:commandButton value="New Campaign"    action="{!URLFOR($Action.Campaign.Clone,selection,[cpn1='New Campaign&cpn16=1&00NT0000000zjpi=0'])}" rendered="{!NOT(error)}"/>


I initially was using a simpler URLfor to jump to the New Campaign page.  Once you're there, you can view the page source from your browser and search for the input fields in the html.  The DOM ids  for both the standard (cpn1 is the Name field and cpn16 was a checkbox I wanted to turn on) and custom fields (00NT0000000zjpi - a custom checkbox turned off) show up in the HTML.


I know that this is probably not a good practice, but it works.  Realize that when you migrate from sandbox to production the id for the custom field changes.


Thank you. Yes, I did see this post earlier. I was able to default the oppty name by using:


{!URLFOR($Action.Opportunity.Clone,Opportunity.Id, [cloneli=1, opp3 = Opportunity.Name &' New Oppty Clone' ],true) }





And you need SortOrder.