I believe the key here is using Dictionaries (which are only available in SPD2013 workflows). The value of a multi-person field is treated by the workflow engine as a JSON object containing an array of user ID's, like this:
"Attendees": {
"__metadata": {
"type": "Collection(Edm.Int32)"
},
"results": [
92,
479,
21,
55
]
}
In a SPD2013 workflow you can set a dictionary variable to a multi-value field like this and then iterate through the contents like an array. The process requires a lot of tedious steps but it works basically like a for loop in any programming language.
So, if you already know the ID of the person who needs to be removed from the field, the procedure would go like this:
Set up an index variable. This will be incremented during each iteration of the loop block.
Create a new dictionary variable called "results" and use the get an item from a dictionary activity to get the results array from the field value JSON object. This contains the user id's as plain numbers.
Count the number of items in the dictionary and save to a variable
Create a Number variable called lastIndex
and set it to the count of items in results
minus 1
Create a String variable output
but do not set a value yet (we are going to build a JSON object with this to set as the new value of the field)
Add a Loop block to the workflow and set it to run the number of times as there are items in the array.
For each item in the array, get the value at the index variable by using the get item from dictionary activity. Enclose the index variable in parentheses
Here, compare the current
value to the user ID that we want to remove. If that value equals current
then we simply do not add it to the output string. We also must compare index
to lastIndex
in order to format the output string correctly. If we are handling the last item in the results
array then we do not want to add it to the output string with a trailing comma.*
In the below screenshot, the IF statement is this:
if( index !== lastindex && current !== BadUserId ){
output = output + current + ","
} else {
output = output + current
}
As the final action inside the loop, increment the index variable
After the loop, set the output variable to itself in brackets so that it has correct notation for an array
Create a new dictionary called type
that contains this Name / Value pair: {type
: Collection(Edm.Int32)
}
Create a new dictionary called ValueCollection
and give it two Name/Value pairs:
{ results
: results
, __metadata
: type
}
Finally, set the multi-value person field to the ValueCollection
field.
*There is a potential flaw here, which is that if the bad user id occurs at the end of the array then you may still end up having a trailing comma. It may be more effective to use Regular Expression Matching but I have not tried that.