SOLVED

Set-PnPListItem - Multiple Managed Metadata Field

Copper Contributor

I need to update a Multivalued Managed Metadata field in a document library (sometimes resetting value as well), I'd like to use Set-PnPListItem to do this.
Assuming $LibraryName and $Id are respectively the document library name and an Id of an existing document, assuming $mm1 and $mm2 are two identifiers of terms in the right scope - here is code sample to illustrate the issue -

 

$lib = "BI"; $id = 45934;
$mm1 = "f5d4baae-6d12-42bf-b3f1-76f06ef0f037"; $mm2 = "bca7c6ab-a948-4cd1-b1b6-38d9001b47bc"
Set-PnPListItem -List $lib -Identity $Id -Values @{"Tags" = $null}
Set-PnPListItem -List $lib -Identity $Id -Values @{"Tags" = ($mm1, $mm2)}

 

works just fine and so is the following code too:

 

$mml1 = @($mm1, $mm2) # $mml1 = ("...", "...") or  $mml1 = "...", "..." work too
Set-PnPListItem -List $lib -Identity $Id -Values @{"Tags" = $mml1}

However, obviously, the list of terms' GUID (an array of strings) is not that simple and is build somewhere else and, to illustrate the issue I am facing - the following code does not work for me:

# Basically, this academical code is aimed to create $mml2, a [String[]] object
# equivalent to $mml1 but build in a way neither the strings nor their number are
# known in advance
$mml2 = $mml1 | Foreach-Object -Process {$_} # i.e. a String Array build by code
Set-PnPListItem -List $lib -Identity $Id -Values @{"Tags" = $mml2} # <= FAILS!

 

I get the following error and couldn't figure out how to avoid it

 

Set-PnPListItem : Value cannot be null.
Parameter name: path
At line:1 char:1
+ Set-PnPListItem -List $lib -Identity $Id -Values @{"Tags" = $mml3} #  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (:) [Set-PnPListItem], ArgumentNullException
    + FullyQualifiedErrorId : EXCEPTION,PnP.PowerShell.Commands.Lists.SetListItem

 

In the above examples,

  • Both $mml1 and $mml2 happen to be all Object[], base type: System.Array
  • Both have 2 individual elements
  • Individual elements are of type String, base type: System.Object
  • Their respective individual elements all match

What did I miss?
How should I build my array of terms' GUID so that update of the field works with Set-PnPListItem?

4 Replies
best response confirmed by PHubaut (Copper Contributor)
Solution

@PHubaut did not try it, nor am I a super-efficient PowerShell developer, but could you try to:

-create a main array that will contain all your items

-for each object, add to the array. Not sure of you need to create an array with @(yourVal) inside the foreach for the object and append to the main array like: $mainArray  = $mainArray + $itemArray? 

 

Sorry of this does not help

 

@Joel Rodrigues 

Thanks Joel - I reshaped my tests based on your idea -
I am not a super-efficient PowerShell developer either and this may be the issue.
This works

 

# WORKS
$mainarray1 = @()
$mainarray1 = $mainarray1 + $mm1
$mainarray1 = $mainarray1 + $mm2
Set-PnPListItem -List $lib -Identity $Id -Values @{"Tags" = $mainarray1} # WORKS
# WORKS TOO
$mainarray2 = @()
foreach ($term in $mainarray1) {
    $mainarray2 = $mainarray2 + $term
}
Set-PnPListItem -List $lib -Identity $Id -Values @{"Tags" = $mainarray2} # WORKS

 

But this does not

 

$mainarray3 = @()
$mainarray1 | Foreach-Object -Process {$mainarray3 = $mainarray3 + $_}
Set-PnPListItem -List $lib -Identity $Id -Values @{"Tags" = $mainarray3} # FAILS

 

So the error is related to the "For Each"-way to add items to the array (statement or cmdlet).
Just for the record, after running above code, doing a $mainarray2.GetType(), $mainarray2[0].GetType(), $mainarray2[1].GetType() and same for $mainarray3 reveals exact same data types. Furthermore, $mainarray2[0].equals($mainarray3[0]) and $mainarray2[1].equals($mainarray3[1]) both returns True. I don't see the difference.

Thanks for the idea as I have a workaround !
...yet remaining with my doubts about what is going wrong.

@PHubaut I just had the exact same thing as you - but I managed to get the "inline" method (with the Foreach-Object) working when I called .ToString() on my term.

 

 $properties = @{}
  foreach ($propertyName in $metadataFields) {
    $value = $targetFileItem[$propertyName]
    if ($value.GetType().Name -eq "TaxonomyFieldValue") {
      $value = $value.TermGuid
    }

    if ($value.GetType().Name -eq "TaxonomyFieldValueCollection") {
      $termArray = @()
      $value | Select-Object -ExpandProperty TermGuid | ForEach-Object { $termArray = $termArray + $_.ToString()}
      $value = $termArray
    }

    $properties.Add($propertyName, $value)
  }

Hi @James Love, thanks for the trick. I do not have the environment required to test this but trust it is indeed a good solution. Thanks for the update as this scenario could happen to me (and to others too) in the future.

1 best response

Accepted Solutions
best response confirmed by PHubaut (Copper Contributor)
Solution

@PHubaut did not try it, nor am I a super-efficient PowerShell developer, but could you try to:

-create a main array that will contain all your items

-for each object, add to the array. Not sure of you need to create an array with @(yourVal) inside the foreach for the object and append to the main array like: $mainArray  = $mainArray + $itemArray? 

 

Sorry of this does not help

 

View solution in original post