{"id":1532,"date":"2013-11-12T06:39:37","date_gmt":"2013-11-12T06:39:37","guid":{"rendered":"https:\/\/poiseddevelopers.com\/reality-tech\/?p=1532"},"modified":"2024-05-06T12:21:54","modified_gmt":"2024-05-06T12:21:54","slug":"programmatically-targeting-audiences-for-audience-enabled-libraries-in-sharepoint","status":"publish","type":"post","link":"https:\/\/poiseddevelopers.com\/reality-tech\/programmatically-targetting-audiences-for-audience-enabled-libraries-in-sharepoint\/","title":{"rendered":"Programmatically Targeting Audiences for Audience Enabled Libraries in SharePoint"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_65 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title \" >Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 eztoc-toggle-hide-by-default' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/poiseddevelopers.com\/reality-tech\/programmatically-targetting-audiences-for-audience-enabled-libraries-in-sharepoint\/#Overview\" title=\"Overview\">Overview<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/poiseddevelopers.com\/reality-tech\/programmatically-targetting-audiences-for-audience-enabled-libraries-in-sharepoint\/#Reporting\" title=\"Reporting\">Reporting<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/poiseddevelopers.com\/reality-tech\/programmatically-targetting-audiences-for-audience-enabled-libraries-in-sharepoint\/#Audience_Shuffling\" title=\"Audience Shuffling\">Audience Shuffling<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"Overview\"><\/span>Overview<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Targeting an audience for a given document is a great capability within SharePoint. There\u2019s a simple Document Library setting to enable Audience Targeting.<\/p>\n<p>This enables a dedicated Audience Targeting field to be configured per document. I customized a Content Query Web Part (CQWP) that honors audience targeting, while displaying the fields in a grid view, enabling a targeted and custom portal home page. While the CQWP is harder to work with than a Data View Web Part, CQWP is the primary way to leverage Audience targeting.<\/p>\n<div style=\"background-color: white; box-shadow: 0px 0px 10px 10px whitesmoke; padding: 20px;\">\n<h4 style=\"color: black;\">Additional Read<\/h4>\n<p><a style=\"color: #1f6799;\" href=\"https:\/\/poiseddevelopers.com\/reality-tech\/set-an-email-alert-for-document-library-or-list-for-sharepoint-2013\/\" target=\"_blank\" rel=\"noopener\">Set an Email alert for Document library or List for SharePoint 2013<\/a><\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Reporting\"><\/span>Reporting<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>I prefer to first output a CSV of all documents, with one column for Audience. Note I also output the absolute URL. Here\u2019s a function to do it. Note the proper use of memory management:<\/p>\n<pre lang=\"php\">$LineHeader= 'Site,Lib,URL,ID,Versions,Name,Title,Created,Modified By,Modified,Audiences'\r\n$LineHeader | Out-file -Filepath $ReportFile\r\n \r\nfunction generate-VerReport ($WebUrl, $ListName)\r\n{\r\n    $ac=Start-SPAssignment\r\n    $web = $ac | Get-SPWeb $WebUrl\r\n    $list = $web.Lists[$ListName]\r\n    $VerOut=$null;\r\n \r\n    Write-Host \"+\" -NoNewline #each plus is a full look through all Docs in a library\r\n    $xSit=$WebUrl;\r\n    $xLis=$ListName;\r\n \r\n        #Go through each item in the list\r\n        $Items = $list.Items\r\n        $ItemCount = $Items.count;\r\n        for ($i=0; $i -lt $ItemCount; $i++)\r\n        {\r\n            #Check if the item content type currently equals the old content type specified\r\n            $item=$items[$i];\r\n \r\n            $sep='\",\"';\r\n            $xURL = $Item[\"EncodedAbsUrl\"]\r\n            $RawAud = $item[\"Target Audiences\"];\r\n            $xNam=$item['Name']\r\n            $xTit=$item['Title']\r\n            $xCre=$item['Created']\r\n            $xEdi=$item[\"Editor\"]\r\n            $xMod=$item[\"Modified\"]\r\n            $xID= $item.ID\r\n            $xVer= $item.Versions.count;\r\n            $Line1='\"'+$xSit+$sep+$xLib+$sep+$xURL+$sep+$xID+$sep+$xVer+$sep+$xNam+$sep+$xTit+$sep+$xCre+$sep+$xEdi+$sep+$xMod+$sep+$rawAud,'\"';\r\n            $Line1 | Out-file -Filepath $ReportFile -Append\r\n            #$LineHeader+= '`r`n'\r\n            #$VerOut+=$Line1;\r\n \r\n        }\r\n \r\n$LineHeader+= '`r`n'\r\n$LineHeader | Out-file -Filepath $ReportFile -Append\r\n \r\n  $web.Dispose()\r\n \r\n   $ac | Stop-SPAssignment\r\n}\r\n<\/pre>\n<p>Here\u2019s the function call:<\/p>\n<pre lang=\"php\">generate-VerReport -weburl $web.url -listname $JPlib\r\n<\/pre>\n<p>The output enables an end user to modify the CSV to specify the audience per document.<\/p>\n<div style=\"background-color: white; box-shadow: 0px 0px 10px 10px whitesmoke; padding: 20px;\">\n<h4 style=\"color: black;\">Additional Read<\/h4>\n<p><a style=\"color: #1f6799;\" href=\"https:\/\/poiseddevelopers.com\/reality-tech\/mirroring-sharepoint-document-library-contents-to-multiple-sites\/\" target=\"_blank\" rel=\"noopener\">Mirroring SharePoint Document Library Contents to Multiple Sites<\/a><\/p>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"Audience_Shuffling\"><\/span>Audience Shuffling<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>I created a script to apply the Audiences specified per document in the control spreadsheet. The Audiences are expected to be in semi-colon separated format (multiple values possible). There is no error checking on spelling of Audiences. It turns out Document Audiences in SharePoint are weakly-typed. That is to say, it is simply a string. The string has four semi-colons. In this script, we only apply SharePoint Groups, and they appear as comma separated after four semi-colons. If multiple values appear, these are comma separated. If an AD group is used, then that appears nestled between two pairs of semi-colons, as in this example:<br role=\"presentation\" data-uw-rm-sr=\"\" \/>;;CN=GroupName Membership,OU=Security Groups,OU=Information Technology,DC=MyDomain,DC=com;;<br role=\"presentation\" data-uw-rm-sr=\"\" \/>Under the covers, SharePoint will accept not just AD groups and SharePoint groups, but also UPS (User Profile Service) Audiences, specified as GUIDs. So two semi-colons are used as delimiters (beats me, but this is the first time I\u2019ve seen this convention). Here\u2019s how it is structured:<br role=\"presentation\" data-uw-rm-sr=\"\" \/>[Guids, comma separated];;[AD group LDAP paths separated by line breaks];;[SharePoint security group names, comma separated]<\/p>\n<p>Here\u2019s the script to apply the Audiences. It assumes all are SharePoint Groups, but is easily extensible to support AD groups if desired. Note it does not do checking for validity of SharePoint groups. Note the \u201cAction\u201d column to determine whether to \u201cD\u201delete or \u201cA\u201dssign audiences:<\/p>\n<pre lang=\"php\">Add-PSSnapin \"Microsoft.SharePoint.PowerShell\" -ErrorAction SilentlyContinue\r\nStart-SPAssignment \u2013Global\r\n$ShuffleSource = \"C:UsersplautjDocumentsPowerShellAudienceShuffle.txt\"\r\n$siteUrl = \"ht tp:\/\/SharePoint\"\r\n \r\nWrite-Host \"script starting $(get-date)\"\r\n$myheader = \"STARTING: $(get-date)\"\r\n \r\n$ShuffArr = Import-Csv -Path $ShuffleSource -Delimiter \"`t\"\r\n \r\n$ShuffCount = $ShuffArr.count;\r\n \r\nfor ($i=0; $i -lt $ShuffCount; $i++)\r\n{\r\n        $Row = $ShuffArr[$i]\r\n \r\n        if (($Row.action -ne $null) -and ($Row.action.length -ne 0))\r\n        {\r\n        $docurl = $row.url;\r\n        $site = New-Object Microsoft.SharePoint.SPSite($docurl)\r\n        $web = $site.OpenWeb()\r\n        $item = $web.GetListItem($docurl)\r\n        $list = $item.ParentList\r\n \r\n        if ($Row.action -eq \"D\")\r\n        {\r\n            $item[\"Target Audiences\"] = $null;\r\n            $item.SystemUpdate();\r\n        }\r\n        elseif ($Row.action -eq \"A\")\r\n        {\r\n \r\n            if ($Row.Audiences -gt 0) #ignore if empty\r\n            #actual Target Audience property has four semicolons, followed by comma delimited SharePoint groups\r\n            #for AD group is how semicolons work ;;CN=ADW Membership,OU=Security Groups,OU=Information Technology,DC=DOMAIN,DC=com;;\r\n \r\n            {\r\n                $AudBuilder = \";;;;\"\r\n                $AudArr = $Row.Audiences.Split(\";\");\r\n                for ($ai=0; $ai-lt $AudArr.Count; $ai++)\r\n                {\r\n                    if ($ai-gt 0)\r\n                    {\r\n                        $AudBuilder = $AudBuilder + \",\"\r\n                    }\r\n                    $AudBuilder = $AudBuilder + $AudArr[$ai]\r\n                }\r\n                $item[\"Target Audiences\"] = $AudBuilder;\r\n                $item.SystemUpdate();\r\n \r\n            } #IF Audiences is not null\r\n \r\n        } #Add action\r\n \r\n        } #action exists\r\n} #loop of rows\r\n \r\nWrite-Host \"script finishing $(get-date)\"\r\n \r\nStop-SPAssignment \u2013Global\r\n###########################\r\n<\/pre>\n<div style=\"background-color: white; box-shadow: 0 0 10px whitesmoke; padding: 20px; border-radius: 5px; display: flex; justify-content: space-around; width: 950px;\">\n<div class=\"content\">\n<h4 role=\"heading\" data-uw-rm-heading=\"level\" aria-level=\"3\"><b>Are you in need of assistance? We can help!<\/b><\/h4>\n<p style=\"width: 70%;\">Book a live 1-on-1 call with the experts of Reality Tech to find out how we will help you to achieve your goal.<\/p>\n<\/div>\n<div style=\"display: flex; align-items: center;\">\n<div class=\"content-btn\" style=\"padding: 8px; border: 1px solid #009a00; width: 89px; height: fit-content; cursor: pointer;\"><a style=\"color: #009a00;\" href=\"https:\/\/poiseddevelopers.com\/reality-tech\/contact-us\/\" target=\"_blank\" rel=\"noopener\">Let\u2019s Talk<\/a><\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Overview Targeting an audience for a given document is a great capability within SharePoint. There\u2019s a simple Document Library setting to enable Audience Targeting. This enables a dedicated Audience Targeting field to be configured per document. I customized a Content Query Web Part (CQWP) that honors audience targeting, while displaying the fields in a grid [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":1533,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[26],"tags":[],"class_list":["post-1532","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell"],"acf":[],"_links":{"self":[{"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/posts\/1532","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/comments?post=1532"}],"version-history":[{"count":18,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/posts\/1532\/revisions"}],"predecessor-version":[{"id":2989,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/posts\/1532\/revisions\/2989"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/media\/1533"}],"wp:attachment":[{"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/media?parent=1532"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/categories?post=1532"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/tags?post=1532"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}