A flow to clone a hierarchy of any depth

A user on the hub wanted to clone campaign hierarchies (just the campaigns, not the members). I thought that it just might be possible using visual workflow, but had no idea what i was in for…

I managed to pull it off, and stay reasonably within governor limits by using some well-placed screen elements. Screen elements, after all, start a new transaction, which resets the limits.

I learned a lot working through this challenge, and will try to lay out the key findings in this post.

The basic idea was to approach it one ‘level’ at a time. So start with a parent campaign (A) and clone it (A1) then query all of the campaigns (B) where B.parentID = A.id, and make copies of those under A1. And then go through each child campaign (B) and find campaigns © where c.parentId = b.id, and so on…

I used a subflow to do most of the lifting. The subflow takes two IDs as inputs: the existing campaign, and the cloned campaign. It queries all the chlidren of the existing campaign and makes copies of them under the cloned campaign. And the it outputs an sObject collection of the new campaigns that were created.

Inputs: Campign ID 1, Campaign ID 2
Outputs: Sobject Collection X

I needed a way to store the relationship between the new campaign and the old campaign, in order to pull the correct child campaigns. So when I cloned a campaign, I wrote the ID of the ‘original’ campaign to the description field.

So lets set this up w/ a scenario of an annual giving campaign with a few child campaigns

Master parent campaign (A): 2015 annual outreach
Child 1: Individual donors
Child 1a: high donors
Child 1b: regular donors
Child 2: Corporations
Child 3: Foundations
Child 3a: Environmental foundations
Child 3b: Education foundations

And we want to clone this structure for 2016.

The flow would be launched from a button on the parent campaign (A). This button passes the campaign ID to the flow, and the flow clones A and then calls the subflow, passing in the new parent ID and the old parent ID (A). The sublow clones each of the child campaigns, and returns a sObject collection w the campaigns {!socNewChildCampaign}

Now is where it gets interesting. I run {!socNewChildCampaign} through a loop. I run the subflow in the loop, passing in the newCampaignId, and the oldCampaignId (which is stored in the description field on the new campaign). So the subflow can do something like this

  1. query all campaigns that are children (1 level down) of the old campaign
  2. make copies of those under the new campaign (writing the old campaign ID to the description field)
  3. return a sObject collection of all the new campaigns that were created

rinse and repeat…more or less.

Where it got tricky:

knowing when you had completed a level in order to pop a screen to reset limits
you need a field on the original campaign to store the cloned campaign, as you cant do lookups filtering on a set of IDs

Adding campaign member status should be fairly easy, but will eat up an extra query, so will i believe limit you to 50-75 campaigns per ‘level’. If you need more than that, find yourself a developer!

UPDATE - Link to unmanaged package for testing only


Now read this

Manipulating text in flows

i occasionally need to iterate over a list of records in a sObject collection, and display values from the records in a screen. back in the day i got some crucial help from salesforce yoda / mark ross on this developerforce post, which... Continue →