Update Choice Field values using CSOM in PowerShell

I wanted a CSOM script in PowerShell to add a new value to a choice field in SharePoint. Most of the examples I found were in CSOM Managed Code (C#) but could not find anything in PowerShell.

I came up with the embedded code.

The client assemblies are referenced

  •  SharePoint Assemblies\Microsoft.SharePoint.Client.dll
  • SharePoint Assemblies\Microsoft.SharePoint.Client.Runtime.dll

I have created the function Add-ChoiceValueToField to contain the logic to add a value to a choice field.

The Field object has to be cast into FieldChoice to expose the Choices property. In PowerShell the CastTo method can be accessed using the MakeGenericMethod.

[Microsoft.SharePoint.Client.ClientContext].GetMethod("CastTo").MakeGenericMethod([Microsoft.SharePoint.Client.FieldChoice]).Invoke($ctx,$field)

I have used the  Load-CSOMProperties function from script Load-CSOMProperties.ps1  to load the existing property “Choices” which an immutable collection.  Load-CSOMProperties.ps1  is available from blog post Loading Specific Values Using Lambda Expressions and the SharePoint CSOM API with Windows PowerShell to help with querying object properties like Lambda expressions in C#.

Load-CSOMProperties -object $fieldChoice -propertyNames @("Choices") ;

I have saved the collection in an array object $FieldChoiceValues to which the existing choice values have been added. If the value to be added does not exist, then it is added to the array object  $FieldChoiceValues.

Finally the Field Choices property is updated with the array object $FieldChoiceValues

$fieldChoice.Choices = $FieldChoiceValues;
$fieldChoice.Update()

The function can be called as follows

Add-ChoiceValueToField -ctx $ctx -ListTitle "ListTestManually" -FieldName "TypeNum" -ChoiceValue "7"

 


Param(
[Parameter(Mandatory=$true, position=0, ValueFromPipeLineByPropertyName=$true, HelpMessage="Specifies the Web. The type must be a valid URL or GUID")]
[String]$WebUrl
)
Set-Location $PSScriptRoot
Add-Type -Path ( ".\SharePoint Assemblies\Microsoft.SharePoint.Client.dll")
Add-Type -Path ( ".\SharePoint Assemblies\Microsoft.SharePoint.Client.Runtime.dll")
# help to use lamda expressions to query object properties
. .\Load-CSOMProperties.ps1
function Add-ChoiceValueToField {
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true,Position=0)]
[Microsoft.SharePoint.Client.ClientContext]$ctx,
[Parameter(Mandatory=$false, position=1, ValueFromPipeLine=$true, ValueFromPipeLineByPropertyName=$true, HelpMessage="TODO")]
[Alias("ListName")]
[string]$ListTitle,
[Parameter(Mandatory=$false, position=2,ValueFromPipeLineByPropertyName=$true, HelpMessage="TODO")]
[string]$FieldName,
[Parameter(Mandatory=$false, position=3,ValueFromPipeLineByPropertyName=$true, HelpMessage="TODO")]
[Alias("Field")]
[string]$ChoiceValue
)
#Retrieve List
$List = $ctx.Web.Lists.GetByTitle($ListTitle)
$ctx.Load($List)
$ctx.ExecuteQuery()
#Retrieve field
$field = $List.Fields.GetByInternalNameOrTitle($FieldName);
$fieldChoice = [Microsoft.SharePoint.Client.ClientContext].GetMethod("CastTo").MakeGenericMethod([Microsoft.SharePoint.Client.FieldChoice]).Invoke($ctx,$field)
Load-CSOMProperties -object $fieldChoice -propertyNames @("Choices") ;
$ctx.Load( $fieldChoice);
$ctx.ExecuteQuery() ;
#if not exists then add
$bExists = $false
$FieldChoiceValues=@();
foreach ($choice in $fieldChoice.Choices)
{
$FieldChoiceValues +=$choice
if($choice -eq $ChoiceValue)
{
$bExists = $true
}
}
#add choices to dropdown list
if($bExists -eq $false)
{
$FieldChoiceValues += $ChoiceValue
$fieldChoice.Choices = $FieldChoiceValues;
$fieldChoice.Update()
$ctx.ExecuteQuery() ;
}
}
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($WebUrl)
# $ctx.Credentials = System.Net.CredentialCache.DefaultCredentials;
$web = $ctx.Web
$ctx.Load($web)
$ctx.ExecuteQuery()
Add-ChoiceValueToField -ctx $ctx -ListTitle "ListTestManually" -FieldName "TypeNum" -ChoiceValue "7"

SharePoint JSOM to update Document ID Settings

The Document ID Service feature is useful to tag unique Id to documents across site collection to make it easier to retrieve. A prefix can be specified to use when the unique Id is generated.

The document id settings is stored in the web property bag “docid_settings_ui” after the feature the activated.

The web property bag can be updated using JSOM to assign a prefix with XML snippet like below.

var docIdValue = ‘<?xml version=”1.0″ encoding=”utf-16″?><DocIdUiSettings xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221; xmlns:xsd=”http://www.w3.org/2001/XMLSchema”&gt; <Prefix>’ + docIDPrefix + ‘</Prefix> <AssignmentEnabled>true</AssignmentEnabled></DocIdUiSettings>’

webProperties.set_item(“docid_settings_ui”, docIdValue);

The full script can be copied from below and tested in a content editor web part.


<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript">
//declare namespace
var ConfigureSiteSettings = ConfigureSiteSettings || {};
// use sp utility to Get field values, need to find out how it will work with Nintex forms
//var myRichTextValue = getFieldValue('SiteCollectionURL');
//alert(myRichTextValue);
ConfigureSiteSettings.UpdateDocIdSettings = (function()
{
var siteUrl = document.getElementById("SiteUrl").value
var docIDPrefix = document.getElementById("docIDPrefix").value
if(!!siteUrl && !!docIDPrefix )
{
var clientContext = new SP.ClientContext(siteUrl);
oWebsite = clientContext.get_web();
clientContext.load(oWebsite);
clientContext.executeQueryAsync(
Function.createDelegate(this, onQuerySucceeded),
Function.createDelegate(this, onQueryFailed)
);
function onQuerySucceeded(sender, args) {
alert('Title: ' + oWebsite.get_title() +
' Description: ' + oWebsite.get_description());
var webProperties = oWebsite.get_allProperties();
clientContext.load(webProperties);
var docIdValue = '<?xml version="1.0" encoding="utf-16"?><DocIdUiSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt; <Prefix>' + docIDPrefix + '</Prefix> <AssignmentEnabled>true</AssignmentEnabled></DocIdUiSettings>'
webProperties.set_item("docid_settings_ui", docIdValue);
oWebsite.update();
clientContext.executeQueryAsync(TaggedSuccess, TaggedFail);
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
function TaggedSuccess(sender, args) {
alert("Tagged your site.");
}
function TaggedFail(sender, args) {
alert("Tagging failed" + args.get_message());
}
}
else
{
alert("Enter Site Url and doc prefix");
}
});
</script>
<div>
<p>
<b>Configure Document Id Settings</b>
<br />
<label>Site Collection URL<label><input type="text" value="" id="SiteUrl" />
<label>Doc ID Prefix<label><input type="text" value="" id="docIDPrefix" />
<button id="configureSiteDocIdSettings" onclick="ConfigureSiteSettings.UpdateDocIdSettings()">Configure Doc Id Settings</button>
</p>
</div>


<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript">
//declare namespace
var ConfigureSiteSettings = ConfigureSiteSettings || {};
// use sp utility to Get field values, need to find out how it will work with Nintex forms
//var myRichTextValue = getFieldValue('SiteCollectionURL');
//alert(myRichTextValue);
ConfigureSiteSettings.UpdateDocIdSettings = (function()
{
var siteUrl = document.getElementById("SiteUrl").value
var docIDPrefix = document.getElementById("docIDPrefix").value
if(!!siteUrl && !!docIDPrefix )
{
var clientContext = new SP.ClientContext(siteUrl);
oWebsite = clientContext.get_web();
clientContext.load(oWebsite);
clientContext.executeQueryAsync(
Function.createDelegate(this, onQuerySucceeded),
Function.createDelegate(this, onQueryFailed)
);
function onQuerySucceeded(sender, args) {
alert('Title: ' + oWebsite.get_title() +
' Description: ' + oWebsite.get_description());
var webProperties = oWebsite.get_allProperties();
clientContext.load(webProperties);
var docIdValue = '<?xml version="1.0" encoding="utf-16"?><DocIdUiSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt; <Prefix>' + docIDPrefix + '</Prefix> <AssignmentEnabled>true</AssignmentEnabled></DocIdUiSettings>'
webProperties.set_item("docid_settings_ui", docIdValue);
oWebsite.update();
clientContext.executeQueryAsync(TaggedSuccess, TaggedFail);
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
function TaggedSuccess(sender, args) {
alert("Tagged your site.");
}
function TaggedFail(sender, args) {
alert("Tagging failed" + args.get_message());
}
}
else
{
alert("Enter Site Url and doc prefix");
}
});
</script>
<div>
<p>
<b>Configure Document Id Settings</b>
<br />
<label>Site Collection URL<label><input type="text" value="" id="SiteUrl" />
<label>Doc ID Prefix<label><input type="text" value="" id="docIDPrefix" />
<button id="configureSiteDocIdSettings" onclick="ConfigureSiteSettings.UpdateDocIdSettings()">Configure Doc Id Settings</button>
</p>
</div>

After the script is loaded on a content editor webpart, the [Site Collection URL] and [Doc ID Prefix] needs to be filled before clicking on “Configure Doc ID Settings”.

ConfigureDocIdSettings_UI

If successful, the message will appear.

TagYourSite

Navigate to site settings> Document ID Settings to verify the prefix

DocIdSettingsPrefix

 

SharePoint Get list items and Effective Permissions on a list via REST API from SharePoint Add-in

The requirement was to build a SharePoint hosted Add-in to allow logged user to create/edit list item from any site from the site collection. The permissions of the user to be able to create/edit an item against the list needed to be checked.

The following script gets list items with effective permissions against the list using jQuery promises from the SharePoint hosted Add-in


function getListItemsAndPermissions(webUrl, listTitle)
{
var appWebUrl = decodeURIComponent(getQueryStringParameter("SPAppWebUrl"));
var deferredPermissions = $.Deferred();
var endpointUrl = appWebUrl + "/_api/SP.AppContextSite(@target)/web/lists/getByTitle('" + listTitle + "')?$select=EffectiveBasePermissions,items/Title&$expand=items&@target='" + webUrl+ "'";
var executor = new SP.RequestExecutor(appWebUrl);
executor.executeAsync(
{
url: endpointUrl,
method: "GET",
dataType: "json",

headers: {
Accept: "application/json;odata=verbose"
},
success: function (data, textStatus, xhr) {
var roles = parseBasePermissions(data);
deferredPermissions.resolve(roles,data);
},
error: function (xhr, textStatus, errorThrown) {
deferredPermissions.reject(JSON.stringify(xhr));
}
});
return deferredPermissions;
}

function parseBasePermissions(value) {
var permissions = new SP.BasePermissions();
permissions.initPropertiesFromJson(JSON.parse(value.body).d.EffectiveBasePermissions);

var permLevels = [];
//more interested in add/edit permissions of the user to the list "Audit"
if (permissions.has(SP.PermissionKind.viewListItems)) {
permLevels.push("viewListItems");
}
if (permissions.has(SP.PermissionKind.editListItem)) {
permLevels.push("editListItem");
}
if (permissions.has(SP.PermissionKind.addListItems)) {
permLevels.push("addListItems");
}
//console.log(permLevels);
return permLevels;
}

function getQueryStringParameter(urlParameterKey, uriString) {
if (!uriString) {
uriString = document.URL;
}
else {
uriString = uriString;
}
if (uriString.indexOf('?') != -1) {
uriString = uriString.split('?')[1];
}
var params = uriString.split('&');
var strParams = '';
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split('=');
if (singleParam[0].toLowerCase() == urlParameterKey.toLowerCase())
return singleParam[1];
}
};