Friday, November 22, 2013

Hide quick launch in SharePoint 2013

To hide the quick launch, add a Script Editor web part to your page, and then paste in the following code:

<style type="text/css">
 #sideNavBox {display: none}
 #contentBox {margin-left: 5px}
</style>


Tuesday, November 19, 2013

Move List Items to Subfolders Via PowerShell

The following script was written to organize list items into yearly folders, e.g. 2012, 2013 etc. based on a list item's created date and status (using a CAML query). The script also captures an item's modified by date and modified by user and resets these values once the item is moved.

Background


Though we typically avoid using folders and rely on metadata, we had to use folders to deal with the 5,000 item list items threshold. At first, we tried creating views that were filtered by indexed columns, and though this helped when viewing data, we still ran into the list threshold issue when attempting to further filter items using the view column filters. Also, we did not want to override the list threshold in Central Admin given potential performance implications (and it's not recommended!). Using folders solved this issue for us.

Script


# Script to move list items to Year sub folders, e.g. 2012, 2013.

# Add SharePoint PowerShell Snap-in if missing
if((Get-PSSnapin | Where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}) -eq $null) {
     Add-PSSnapin Microsoft.SharePoint.PowerShell;
}

Start-SPAssignment -Global

# Get Site
$Site = Get-SPSite -Identity "<Site Collection URL>";

## Get Web
$Web = $Site.OpenWeb("<Web Name>");

## Get List
$List = $Web.Lists["<List Name>"];

## Initialize Counts
$Count = 0;
$ErrorCount = 0;

## Set Query
$Query = New-Object Microsoft.SharePoint.SPQuery;
$Query.Folder = $List.RootFolder;
$camlQuery = "<CAML Query>";
$Query.Query = $camlQuery;
$Query.RowLimit = 10;

# Get all list items that match the query and where the item content type is not a folder
$List.GetItems($Query)  | Where {$_.ContentType.Name -ne "Folder"}  |  foreach-object {

  # Get the data we need to work with and update
  $ItemID = $_["ID"];
  $ItemTitle = $_["Title"];
  $Year = ([System.DateTime] $_["Created"]).Year;
  $ModifiedDate = [System.DateTime] $_["Modified"];
  $ModifiedBy = New-Object Microsoft.SharePoint.SPFieldUserValue($Web, [string]$_["Modified By"]);

  $ListPath = $Web.ServerRelativeUrl + "/" + $List.RootFolder.Url + "/";
  $FolderPath = $ListPath + $Year;
  $Folder = $Web.GetFolder($FolderPath);

  # Create the Year folder if it does not already exist
  if (-not $Folder.Exists)
  {
    $Folder = $List.Folders.Add("", [Microsoft.SharePoint.SPFileSystemObjectType]::Folder, $Year);
    $Folder.Update();
  }
 
  Write-Host ("Moving: " + $ItemTitle);

  # Try moving the file to the subfolder setting the modified and modified date fields
  Try
  {
      $Web.GetFile($_.Url).MoveTo([System.String]::format("{0}/{1}", $Folder, $ItemID.ToString()+"_.000"));
      $Count = $Count + 1;
   
      $ListItem = $List.GetItemByID($ItemID);
      $ListItem["Editor"] = $ModifiedBy;
      $ListItem["Modified"] = $ModifiedDate;
      $ListItem.Update();
  }
  Catch [system.exception]
  {
      $ErrorCount = $ErrorCount + 1;
      Write-Error ("Error moving file: " + $ItemTitle);
  }

};

Write-Host ("`n" + $Count.ToString() + " items moved.");

if ($ErrorCount -gt 0)
{
    Write-Host ("`n" + $ErrorCount.ToString() + " errors.");
}

Stop-SPAssignment -Global

References

Referred to the following links:

Move documents into folders in the same library using PowerShell

Move listitems programatically to sub folder in sharepoint 2010

Move SharePoint List Item (SPListItem) To Sub Folder

Saturday, July 30, 2011

PowerShell to help with Branding Deployment

Whilst working on a project to deploy a new branding solution, there was a requirement to disable existing brand features on all webs and site collections across all web applications, and then deploy a new branding solution to all root webs on all site collections. To do this manually would have been very tedious and time consuming, so using some simple PowerShell scripts made this process very easy and fast. Here are the scripts used:

DisableFeatures

$webApp = "http://WebAppUrl/"
$StapleFeature = Get-SPFeature | where {$_.DisplayName -eq "Name"}
$BrandingFeature = Get-SPFeature | where {$_.DisplayName -eq "Name"}
$WebPartsFeature = Get-SPFeature | where {$_.DisplayName -eq "Name"}

# Site collection scoped features
# Get all sites in the web app and if the feature exists, disable it
Get-SPSite -WebApp $webApp | foreach {
if($_.Features[$StapleFeature.ID]) {
Disable-SPFeature $StapleFeature -url $_.URL -Force -Confirm:$false
Disable-SPFeature $WebPartsFeature -url $_.URL -Force -Confirm:$false
}
}

# Web scoped features
# Get all webs in all sites in the web app and if the feature exists, disable it
Get-SPSite -WebApp $webApp | Get-SPWeb -limit all | foreach {
if($_.Features[$BrandingFeature.ID]) {
Disable-SPFeature $BrandingFeature -url $_.URL -Force -Confirm:$false
}
}

Enable Features

$webApp = "http://WebAppUrl/"
$StapleFeature = Get-SPFeature | where {$_.DisplayName -eq "Name"}
$BrandingFeature = Get-SPFeature | where {$_.DisplayName -eq "Name"}
$WebPartsFeature = Get-SPFeature | where {$_.DisplayName -eq "Name"}

# Site collection scoped features
# Enable features in all sites in the web app
Get-SPSite -WebApp $webApp | foreach {
Enable-SPFeature $StapleFeature -url $_.Url -Force
Enable-SPFeature $BrandingFeature -url $_.Url -Force
Enable-SPFeature $WebPartsFeature -url $_.Url -Force
}

I only had a couple of web apps, so just replaced the web app URL $webApp for each one and ran the scripts. You could just put another foreach and loop through all the webs if needed.

Monday, June 6, 2011

FileNotFoundException with new SPSite

When debugging a SharePoint console application in Visual Studio 2010, I ran into the error FileNotFoundException during the line:

using (SPSite site = new SPSite("http://dev.company.com/mysite/"))

The fix that worked for me was to make sure the Platform target: on the Build tab under the Project's properties page, was set to Any CPU from x86 which makes sense since SharePoint binaries are targeted to the x64 CPU.
The FileNotFoundException error is a little misleading, so if you run into, please check your Platform target.

Friday, June 3, 2011

AD Security Groups Not Showing in Web Part Audience Picker

When attempting to set audiences on a web part using AD Security groups, you click the Target Audiences Browse icon (under Advanced in the Web Part properties), and this displays the Select Audiences dialog box. Then you select Distribution/Security Groups from the Find drop down list, type a search key word and then click Search. Then a list of all the AD Security Groups should be displayed. However, in my case I was getting the message:

No security groups or distribution lists were found based on your search request. Refine the search text, and then rerun the search request.

So I checked the synchronization connection under Configure Synchronization Connections on the Manage Profile Service page in Central Administration, to see if I was omitting an AD container. (You can get to this page by going to Manage Service Applications on the Application Management menu, selecting your User Profile Service Application and selecting Manage in the ribbon). This looked fine as all the AD OUs with the security groups were already being included.

Then I did a full profile synchronization but the AD Security Groups were still missing from the Web Part Audience Picker. I then tried setting permissions on a site and list item, and the AD Security Groups were showing up, but just not in the Audience Picker.

So being unable to find a solution, I decided to delete and re-create the User Profile Service application. I would delete the sync database, but keep the existing user profile and social databases. Steps I followed:
  • Went to Manage Service Applications in Central Administration, deleted the User Profile Service Application (without deleting its data - clear the Delete data associated with the Service Application check box).
  • Deleted the Sync database from SQL Server
  • Created a new User Profile Service Application using the existing user profile and social databases
  • Added the Farm account to the local server admin group (can be removed after the next step runs)
  • Started the User Profile Synchronization service under Manage services on server link on the System Settings page. Wait for a little while for the status to go from Starting to Started
  • Removed the Farm account from the local server admin group (if added it above)
  • Re-created the synchronization connection under Configure Synchronization Connections on the Manage Profile Service page in Central Administration.
  • Started a full profile synchronization
Went back to the Audience Picker and now the AD Security Groups were showing up. Seems like way over-kill, and perhaps there is a much more simple and elegant solution, but this worked for me.

Wednesday, October 6, 2010

Error Occurred in Deployment Step - Access Denied

When deploying a site workflow solution from Visual Studio 2010 to a site, I ran into the error:

Error occurred in deployment step 'Recycle IIS Application Pool':
0x80070005Access denied.


Checking permissions, I found that the user account that was deploying the site workflow (under which Visual Studio was running) did not have site collection administrator permissions. After adding the user as a site collection administrator, I was able to deploy the solution successfully.