Tag Archives: SharePoint 2016

Export-SPAllSitesForMigration


Function Name

Export-SPAllSitesForMigration


Download Source Code

Export-SPAllSitesForMigration.zip


Description

The code in this module will gather all site collections in your farm and write the details to a CSV file. The CSV file will be formatted to support a migration effort.


Parameters

Parameter Name$CsvFilename
Data Type[System.String]
RequiredYes
DescriptionUse this parameter to specify the output CSV filename.
Parameter Name
$OutGrid
Data Type[Switch]
RequiredNo
DescriptionUse to indicate if you’d like an output grid before returning. Using this during the initial build of your migration to see that all site information is included as expected.

Return Value

This function returns an array of custom PS objects. Each object contains the following properties:

[System.String]Migrate
[System.String]SourceSiteName
[System.String]SourceSiteUrl
[System.String]SourceDatabaseName
[System.String]SourceWebApplicationName
[System.String]SourceSiteTemplate
[System.String]DestinationWebApplicationUrl
[System.String]DestinationSiteUrl
[System.String]DestinationSiteTemplate

Code

<#
# Export-SPAllSitesForMigration
#
# .Synopsis
#    The code in this module will gather all site collections in your farm and write the details
#    to a CSV file.
#
# .Description
#    The code in this module will gather all site collections in your farm and write the details
#    to a CSV file. The CSV file will be formatted to support a migration effort.
#
# .Notes
#    This script must be run on one of the source farm servers. I usually run this on a secondary
#    application server; in most cases where I build the farm, this will be SPAPP02 server.
#
# .Author
#    Written by Bob Mixon
#>
cls

# Load PowerShell cmdlet's for SharePoint
if((Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null)
{
    Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
}

<#
# Export-SPAllSitesForMigration
#
# .Synopsis
#    The code in this function will gather all site collections in your farm and write the details
#    to a CSV file.
#
# .Description
#    The code in this function will gather all site collections in your farm and write the details
#    to a CSV file. The CSV file will be formatted to support a migration effort.
#
# .Notes
#    This script must be run on one of the source farm servers. I usually run this on a secondary
#    application server; in most cases where I build the farm, this will be SPAPP02 server.
#
# .Parameter $CsvFilename
#    Required - Use this parameter to specify the output CSV filename.
#
# .Parameter $OutGrid
#    Optional - Use to indicate if you'd like an output grid before returning. Using this during
#               the initial build of your migration to see that all site information is included
#               as expected.
#
# .Returns
#    This function returns an array of custom PS objects. Each object contains the following
#    properties:
#
#    String    Migrate
#    String    SourceSiteName
#    String    SourceSiteUrl
#    String    SourceDatabaseName
#    String    SourceWebApplicationName
#    String    SourceSiteTemplate
#    String    DestinationWebApplicationUrl
#    String    DestinationSiteUrl
#    String    DestinationSiteTemplate
#
# .Example
#    Export-SPAllSitesForMigration -CsvFilename "c:\spreports\allsites.csv" -OutGrid
#
# .Author
#    Written by Bob Mixon
#>
function Export-SPAllSitesForMigration
{
    Param(
        [Parameter(Mandatory=$true)]
            [string]$CsvFilename,
        [Parameter(Mandatory=$false)]
            [switch]$OutGrid = $false
    )

    # Retrieve all site collections.
    Write-Host "RETRIEVING ALL SITE COLLECTIONS TO BE MIGRATED" -ForegroundColor Yellow

    # $oSites results in an array of SPSite objects.
    $oSites = Get-SPSite -Limit ALL
    Write-Host "Completed the retrieval of all site collections."

    Write-Host "Building an array of all site collections to be exported and returned: " -NoNewline
    # Array to contain all sites to migrate objects.
    $aSitesToMigrate = @()

    $oSites | ForEach-Object {
        $sSourceSiteTemplateName = ([Microsoft.SharePoint.SPSite]$_).RootWeb.WebTemplate.ToString()
        $sSourceSiteTemplateId = ([Microsoft.SharePoint.SPSite]$_).RootWeb.WebTemplateId.ToString()
        $sSourceSiteTemplate = [String]::Format("{0}#{1}", $sSourceSiteTemplateName, $sSourceSiteTemplateId)
        $oSiteToMigrate = New-Object -TypeName PSObject -Property @{
            Migrate                      = "NO"
            SourceSiteName               = $_.RootWeb.Title
            SourceSiteUrl                = ([Microsoft.SharePoint.SPSite]$_).Url
            SourceDatabaseName           = ([Microsoft.SharePoint.SPSite]$_).ContentDatabase.Name
            SourceWebApplicationName     = ([Microsoft.SharePoint.SPSite]$_).WebApplication.Name
            SourceSiteTemplate           = $sSourceSiteTemplate
            DestinationWebApplicationUrl = ""
            DestinationSiteUrl           = ""
            DestinationSiteTemplate      = $sSourceSiteTemplate 
        }
        $aSitesToMigrate += $oSiteToMigrate
    }
    Write-Host "Success!" -ForegroundColor Green
    
    if($OutGrid)
    {
        $aSitesToMigrate | Select-Object Migrate, SourceSiteName, SourceSiteUrl, SourceDatabaseName, `
            SourceWebApplicationName, SourceSiteTemplate, DestinationWebApplicationUrl, DestinationSiteUrl, `
            DestinationSiteTemplate | Out-Gridview
    }

    Write-Host ([string]::Format("Exporting site collection report to [{0}]: ", $CsvFilename)) -NoNewline
    $aSitesToMigrate | Sort-Object SourceSiteUrl | Select-Object Migrate, SourceSiteName, SourceSiteUrl, SourceDatabaseName, `
        SourceWebApplicationName, SourceSiteTemplate, DestinationWebApplicationUrl, DestinationSiteUrl, `
        DestinationSiteTemplate | Export-CSV $CsvFilename -NoTypeInformation -Encoding UTF8
    Write-Host "Success!" -ForegroundColor Green
    return($aSitesToMigrate)
}

###################################################################################################
# Module Members to be Exported
###################################################################################################
#region Module Members to be Exported

if([System.IO.Path]::GetExtension($MyInvocation.ScriptName) -like ".psm1")
{
	Export-ModuleMember -Function Export-SPAllSitesForMigration -ErrorAction SilentlyContinue
}

#endregion

SharePoint 2016 Site Templates and ID’s

I’m constantly needing a list of all the site templates available in SharePoint 2016. I decided to start maintaining this list on my blog so I don’t have to search for it anymore.

Note – I did not come up with this list in a vacuum. I’m making updates here but the original list came from Microsoft and a few other blogs.

 

Below is a list of all the SharePoint 2016 site templates, including their ID’s which are used in development; .NET, PowerShell, etc.

You can use one of these template ID’s to create a new site, in PowerShell.

The following example will create a new site using the Team Site template STS#0.

New-SPSite "https://NewSharePointSiteURLs" -OwnerAlias "domain\bob" -Language 1033 -Template "STS#0"
Template ID Title Description
ACCSRV#0 Access Services Site Microsoft Access Server
ACCSVC#0 Access Services Site Internal Microsoft Access Server Internal
ACCSVC#1 Access Services Site Microsoft Access Server
APP#0 App Template A base template for app development. It provides the minimal set of features needed for an app.
APPCATALOG#0 App Catalog Site A site for sharing apps for SharePoint and Office
BDR#0 Document Center A site to centrally manage documents in your enterprise
BICenterSite#0 Business Intelligence Center A site for presenting Business Intelligence content in SharePoint.
BLANKINTERNET#0 Publishing Site This template creates a site for publishing Web pages on a schedule, with workflow features enabled. By default, only Publishing subsites can be created under this site. A Document and Picture Library are included for storing Web publishing assets.
BLANKINTERNET#1 Press Releases Site This template creates the Press Releases subsite for an Internet-facing corporate presence website.
BLANKINTERNET#2 Publishing Site with Workflow A site for publishing Web pages on a schedule by using approval workflows. It includes document and image libraries for storing Web publishing assets. By default, only sites with this template can be created under this site.
BLANKINTERNETCONTAINER#0 Publishing Portal A starter site hierarchy for an Internet-facing site or a large intranet portal. This site can be customized easily with distinctive branding. It includes a home page, a sample press releases subsite, a Search Center, and a login page. Typically, this site has many more readers than contributors, and it is used to publish Web pages with approval workflows.
BLOG#0 Blog A site for a person or team to post ideas, observations, and expertise that site visitors can comment on.
CENTRALADMIN#0 Central Admin Site A site for central administration. It provides Web pages and links for application and operations management.
CMSPUBLISHING#0 Publishing Site A blank site for expanding your Web site and quickly publishing Web pages. Contributors can work on draft versions of pages and publish them to make them visible to readers. The site includes document and image libraries for storing Web publishing assets.
COMMUNITY#0 Community Site A place where community members discuss topics of common interest. Members can browse and discover relevant content by exploring categories, sorting discussions by popularity or by viewing only posts that have a best reply. Members gain reputation points by participating in the community, such as starting discussions and replying to them, liking posts and specifying best replies.
COMMUNITYPORTAL#0 Community Portal A site for discovering communities.
DEV#0 Developer Site A site for developers to build, test and publish apps for Office
EDISC#0 eDiscovery Center A site to manage the preservation, search, and export of content for legal matters and investigations.
EDISC#1 eDiscovery Case This template creates an eDiscovery case. Users create locations where they can preserve or export data.
ENTERWIKI#0 Enterprise Wiki A site for publishing knowledge that you capture and want to share across the enterprise. It provides an easy content editing experience in a single location for co-authoring content, discussions, and project management.
GLOBAL#0 Global template This template is used for initializing a new site.
GROUP#0 Group A site template used to create a Group.
MPS#0 Basic Meeting Workspace A site to plan, organize, and capture the results of a meeting. It provides lists for managing the agenda, meeting attendees, and documents.
MPS#1 Blank Meeting Workspace A blank meeting site for you to customize based on your requirements.
MPS#2 Decision Meeting Workspace A site for meetings that track status or make decisions. It provides lists for creating tasks, storing documents, and recording decisions.
MPS#3 Social Meeting Workspace A site to plan social occasions. It provides lists for tracking attendees, providing directions, and storing pictures of the event.
MPS#4 Multipage Meeting Workspace A site to plan, organize, and capture the results of a meeting. It provides lists for managing the agenda and meeting attendees in addition to two blank pages for you to customize based on your requirements.
OFFILE#0 (obsolete) Records Center (obsolete) This template creates a site designed for records management. Records managers can configure the routing table to direct incoming files to specific locations. The site also lets you manage whether records can be deleted or modified after they are added to the repository.
OFFILE#1 Records Center This template creates a site designed for records management. Records managers can configure the routing table to direct incoming files to specific locations. The site also lets you manage whether records can be deleted or modified after they are added to the repository.
OSRV#0 Shared Services Administration Site This template creates a site for administering shared services
POINTPUBLISHINGHUB#0 PointPublishing Hub A site template used to create a PointPublishing hub site.
POINTPUBLISHINGPERSONAL#0 PointPublishing Personal A site template used to create a PointPublishing personal site.
POINTPUBLISHINGTOPIC#0 PointPublishing Topic A site template used to create a PointPublishing topic site.
POLICYCTR#0 Compliance Policy Center
PPSMASite#0 PerformancePoint
PRODUCTCATALOG#0 Product Catalog A site for managing product catalog data which can be published to an internet-facing site through search. The product catalog can be configured to support product variants and multilingual product properties. The site includes admin pages for managing faceted navigation for products.
PROFILES#0 Profiles This template creates a profile site that includes page layout with zones
PROJECTSITE#0 Project Site A site for managing and collaborating on a project. This site template brings all status, communication, and artifacts relevant to the project into one place.
PWA#0 Project Web App Site Microsoft Project Web App
PWS#0 Microsoft Project Site A site that supports team collaboration on projects. This site includes documents, issues, risks, and deliverables which may be linked to tasks in Project Web App.
SGS#0 Group Work Site This template provides a groupware solution that enables teams to create, organize, and share information quickly and easily. It includes Group Calendar, Circulation, Phone-Call Memo, the Document Library and the other basic lists.
SPS#0 SharePoint Portal Server Site This template is obsolete.
SPSCOMMU#0 Community area template This template is obsolete.
SPSMSITE#0 Personalization Site A site used for hosting personal sites (My Sites) and the public People Profile page. This template needs to be provisioned only once per User Profile Service Application, please consult the documentation for details.
SPSMSITEHOST#0 My Site Host A site used for hosting personal sites (My Sites) and the public People Profile page. This template needs to be provisioned only once per User Profile Service Application, please consult the documentation for details.
SPSNEWS#0 News Site This template is obsolete.
SPSNHOME#0 News Site A site for publishing news articles and links to news articles. It includes a sample news page and an archive for storing older news items.
SPSPERS#0 SharePoint Portal Server Personal Space This web template defines a Personal Space for an individual participating on a SharePoint Portal.
SPSPERS#10 Storage And Social SharePoint Portal Server Personal Space This web template defines a minimal Personal Space with Storage, on-demand Social and Multilingual User Interface with document parser disabled at web level features for an individual participating on a SharePoint Portal.
SPSPERS#2 Storage And Social SharePoint Portal Server Personal Space This web template defines a minimal Personal Space with both Social and Storage features for an individual participating on a SharePoint Portal.
SPSPERS#3 Storage Only SharePoint Portal Server Personal Space This web template defines a minimal Personal Space with Storage features for an individual participating on a SharePoint Portal.
SPSPERS#4 Social Only SharePoint Portal Server Personal Space This web template defines a minimal Personal Space with Social features for an individual participating on a SharePoint Portal.
SPSPERS#5 Empty SharePoint Portal Server Personal Space This web template defines a empty Personal Space.
SPSPERS#6 Storage And Social SharePoint Portal Server Personal Space This web template defines a minimal Personal Space with Storage and on-demand Social features for an individual participating on a SharePoint Portal.
SPSPERS#7 Storage And Social SharePoint Portal Server Personal Space This web template defines a minimal Personal Space with Storage, Social and Multilingual User Interface features for an individual participating on a SharePoint Portal.
SPSPERS#8 Storage And Social SharePoint Portal Server Personal Space This web template defines a minimal Personal Space with Storage, on-demand Social and Multilingual User Interface features for an individual participating on a SharePoint Portal.
SPSPERS#9 Storage And Social SharePoint Portal Server Personal Space This web template defines a minimal Personal Space with Storage, on-demand Social with document parser disabled at web level features for an individual participating on a SharePoint Portal.
SPSPORTAL#0 Collaboration Portal A starter site hierarchy for an intranet divisional portal. It includes a home page, a News site, a Site Directory, a Document Center, and a Search Center with Tabs. Typically, this site has nearly as many contributors as readers and is used to host team sites.
SPSREPORTCENTER#0 Report Center A site for creating, managing, and delivering Web pages, dashboards, and key performance indicators that communicate metrics, goals, and business intelligence information.
SPSSITES#0 Site Directory A site for listing and categorizing important sites in your organization. It includes different views for categorized sites, top sites, and a site map.
SPSTOC#0 Contents area Template This template is obsolete.
SPSTOPIC#0 Topic area template This template is obsolete.
SRCHCEN#0 Enterprise Search Center A site focused on delivering an enterprise-wide search experience. Includes a welcome page with a search box that connects users to four search results page experiences: one for general searches, one for people searches, one for conversation searches, and one for video searches. You can add and customize new results pages to focus on other types of search queries.
SRCHCENTERLITE#0 Basic Search Center A site focused on delivering a basic search experience. Includes a welcome page with a search box that connects users to a search results page, and an advanced search page. This Search Center will not appear in navigation.
SRCHCENTERLITE#1 Basic Search Center The Search Center template creates pages dedicated to search. The main welcome page features a simple search box in the center of the page. The template includes a search results and an advanced search page. This Search Center will not appear in navigation.
STS#0 Team Site A place to work together with a group of people.
STS#1 Blank Site A blank site for you to customize based on your requirements.
STS#2 Document Workspace A site for colleagues to work together on a document. It provides a document library for storing the primary document and supporting files, a tasks list for assigning to-do items, and a links list for resources related to the document.
TBH#0 In-Place Hold Policy Center A site to manage policies to preserve content for a fixed period of time.
TENANTADMIN#0 Tenant Admin Site A site for tenant administration. It provides Web pages and links for self-serve administration.
visprus#0 Visio Process Repository A site for viewing, sharing, and storing Visio process diagrams. It includes a versioned document library and templates for Basic Flowcharts, Cross-functional Flowcharts, and BPMN diagrams.
WIKI#0 Wiki Site A site for a community to brainstorm and share ideas. It provides Web pages that can be quickly edited to record information and then linked together through keywords

SharePoint Sites versus Webs

SharePoint Sites versus Webs

This is a post I wrote long ago for my previous blog. I’ve been asked what the difference is between Site and Web; here I’m going to tackle that question head on!

First and foremost, Microsoft didn’t make the differentiation of these two easy to follow as they use the terms interchangeably. In this article I’ll be describing the technical naming conventions and how to simplify this for non-technical business users.

For reference, I’m using the term Site (SPSite) to indicate a Site Collection and Web (SPWeb) to reference an actual web site. These are the technical internal terms used.

The first thing to remember about a SharePoint Site, for both on-premise and Office 365, is it’s just a site. Same for a Web, it is just a website. What makes each of these unique are the features enabled for that specific template and the content types to display pages on those Webs.

Site Collection

A Site Collection is a container of Webs. Every Site Collection has a single top-level Web. The top-level Web can have zero to many sub-webs.

From a development perspective, a Site Collection can be created or accessed via the SPSite class.

Web

A Web is the actual web site.

From a development perspective, a Web can be created or accessed via the SPWeb class.

Below is an image that describes the Site Collection and Web relationships.

Working with End Users

When working with non-technical end users, you may just wish to use the terms Site Collection and Site. There’s no need to confuse them with the internal class/object names.

Conclusion

In SharePoint, a site is just a site and a web is just a web; they are all fundamentally the same with different features enabled. For example, a Publishing site is just a site collection with the Publishing feature enabled.

Don’t hesitate to ask questions if you need additional information!

SharePoint on!

PowerShell and SharePoint Modules

There are a lot of posts about creating modules, for SharePoint, in PowerShell. I decided to write this post so everything I’ve learned is in one place. I’m hoping you learn something from this (as I did).

I have tested the code in this article in SharePoint On-premise  2010, 2013 and 2016.

Modules do have the advantage of, once created and loaded, the functions in your module will be available in every PowerShell session.

Loading the Microsoft.SharePoint.Powershell Snapin

Making sure the Microsoft.SharePoint.PowerShell snapin is always loaded first. This way you are always certain the snapin is available and its not necessary to add it to every script file you create.

Note: this only has to be done once and will be available for all future PowerShell sessions.

Open the PowerShell ISE and run the following, at the command line.  This will create a new profile script (profile.ps1) or open if it already exists.

PS C:> if (!(test-path $profile.AllUsersAllHosts)) {new-item -type file -path $profile.AllUsersAllHosts –force}
powershell_ise $profile.AllUsersAllHosts

Now that the profile.ps1 file is open in the PowerShell ISE, add the following code.  If there is already code in the profile.ps1 file, make sure the following doesn’t already exist and, if not, add it.

$ver = $host | select version
if ($ver.Version.Major -gt 1) {$host.Runspace.ThreadOptions = "ReuseThread"} 
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) 
{
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}

Here is what the above looks like in my PowerShell session.

profile.ps1 – click on the image to open, full size, in another browser tab.

Make sure to close this PowerShell instance and load a new instance. Test that the Microsoft.SharePoint.PowerShell module has been loaded into your new PowerShell instance, type
Get-SPFarm at the command line and it should now execute without any issues.

Now that we have the Microsoft.SharePoint.PowerShell module loading with every instance of PowerShell, lets move on to creating our first module.

Creating a Script/Module Template

A PowerShell module is fundamentally the same as any other script file with the addition of a few elements.  Let’s start by showing you the fundamental header, body and footer that is in every one of my script files.  In fact, I have this as a template file and use it each time I wish to create a new module.

<#
	.SYNOPSIS
	.DESCRIPTION
	.NOTES
#>
function Verb-YourFunctionName
{
    <#
    .SYNOPSIS

    .DESCRIPTION

    .PARAMETER Web

    .PARAMETER LeadingSpaceCount
        Used to control verbose output. If -1 (default) no verbose output will be rendered. Any value of zero or greater, will generate verbose output to the host. The value of this parameter is used to indent the verbose output. For example, a value of 2 will put two spaces before the output.

    .EXAMPLE
    .EXAMPLE
    #>
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)][Microsoft.SharePoint.PowerShell.SPWebPipeBind]$Web,
        [Parameter(Mandatory=$false)]
            [System.Int32]$LeadingSpaceCount=-1
    )

    # Setup the leading space for verbose output.
    # If -1 (default) no verbose output will be rendered.  Any value of zero or greater, will generate verbose output to the host.
    # The value of this parameter is used to indent the verbose output.  For example, a value of 2 will put two spaces before the output.
    $ls = ""
    if($LeadingSpaceCount -ge 0){$ls = "".PadRight($LeadingSpaceCount," "); $LeadingSpaceCount++}
    if($LeadingSpaceCount -ge 0)
    {
        Write-Host "$ls- WHAT THIS FUNCTION DOES" -ForegroundColor Yellow
        $ls = "".PadRight($LeadingSpaceCount," ")
        $LeadingSpaceCount++
    }
    try
    {
        [Microsoft.SharePoint.SPWeb]$oWeb = Get-SPWeb $Web
    }
    catch
    {
        Write-Host ([System.String]::Format("$ls- EXCEPTION: [{0}] [{1}]", $sScriptName, $_.Exception.Message)) -ForegroundColor Red
        Write-Host
        throw $_.Exception
    }
    finally
    {
        if($oWeb -ne $null){$oWeb.Dispose()}
    }
    return($SomeReturnVar)
    }

#region Module Members to be Exported
if([System.IO.Path]::GetExtension($MyInvocation.ScriptName) -like ".psm1")
{
    Export-ModuleMember -Function Verb-YourFunctionName -ErrorAction SilentlyContinue
}
#endregion

The header section of the module is simply a set of comments describing the functionality contained within the script/module file.  I tend to breakup my functions into separate files so maintenance is simplified.

The body section of the module is the function or code we are writing.  In the case of my template, the function is named Verb-YourFunctionName.  When being used, the function name will be modified to match the need.

The footer section is where we tell the Add-PSModule code (in the next section) what functions are to be included in our module.

#region Module Members to be Exported
if([System.IO.Path]::GetExtension($MyInvocation.ScriptName) -like ".psm1")
{
    Export-ModuleMember -Function Verb-YourFunctionName -ErrorAction SilentlyContinue
}
#endregion

You will change the Verb-YourFunctionName to the actual name of your function in this module.

Using Add-PSModule to Add Your Module

The last step in this process is to use the Add-PSModule to add the module to your PowerShell session.

Personally I so this in a PowerShell function; one for each different module I wish to create.  For example, I have BMCommon, BMActiveDirectory, BMSharePoint2013, etc. modules.  In most of my client environments, I install these modules so all of my extended functions and variables are available to all instances of PowerShell.

function Add-BMSharePoint2013PSModule
{
    Param(
        [Parameter(Mandatory=$false
            [string]$ModuleInstallPath = "C:\Windows\System32\WindowsPowerShell\v1.0\Modules",
        [Parameter(Mandatory=$false)]
            [int]$LeadingSpaceCount=-1
    )

    $ls = ""
    if($LeadingSpaceCount -ge 0){$ls0 `
        "".PadRight($LeadingSpaceCount," ");
        $LeadingSpaceCount++}

    $sScriptSourcePath = Split-Path -parent `
        $PSCommandPath
    $sModuleName = "BMSharePoint2013"
    $sManifestDescription = "Contains SharePoint 2013 management extended functions."

    $aScriptFiles = "Add-ADUserToSPGroup.ps1",
        "Add-SPAppTile.ps1",
        "Add-SPSitePermissionLevel.ps1"

    $bSuccess = Add-PSModule `
        -ScriptSourcePath $sScriptSourcePath `
        -ModuleName $sModuleName `
        -ScriptFiles $aScriptFiles `
        -ManifestAuthor "Bob Mixon" `
        -ManifestCompanyName "Bob Mixon" `
        -ManifestDescription $sManifestDescription `
        -ModuleInstallPath $ModuleInstallPath `
        -LeadingSpaceCount $LeadingSpaceCount

    return($bSuccess)
}

Add-BMSharePoint2013PSModule -LeadingSpaceCount 0

 

This is all you really need to do!  The high-level steps for accomplishing this are:

  1. Make sure the PowerShell snapin “Microsoft.SharePoint.PowerShell” has been loaded in the PowerShell profile.ps1 file.
  2. Create your new function script file/module; include the Export-ModuleMember at the bottom of the script file/module.
  3. Create and run your module to create and install the module.

Once these steps are complete, you can close your PowerShell instance, open another and your functions will be available.

 

Document Libraries and Folders

I am asked on a regular basis how I feel about the use of Document Library folders. To be honest, I always tell people “avoid them” unless you thoroughly understand the consequences of using folders or have a controlled means of promoting consistent use. This response always stirs up controversy so I thought I’d write this article to help you better understand my thinking.

Before I dive too deep in to this article, I need to first say; there is no right or wrong way of implementing your document management solution. There are simply better ways of surfacing information and improving the user experience. If you are concerned about findability and user adoption, then read-on! Another prerequisite to reading this article is to understand, this is not a black and white topic; meaning, it’s not an all or nothing issue. I believe document library folders have a place and can be used as long as the consequences are thoroughly understood.

Do I use them in my implementations? Absolutely… However, I do so in a very limited manner and very specific ways. With all that said, let’s move on…

First, let’s take a look at why you would use document library folders. The only reason that immediately comes to mind is; because that is what we are used to doing! I personally don’t think this is a great reason, but it does hold some truth. We have pushed users to using file share and local drives all of which have folder and nested folders.

Now lets take a look at why we shouldn’t use document library folders; or ways of improving the users experience.

Navigating document library folders is not the same as what users experienced when storing/managing files on file shares and other drives. The tree view, with +/- to expand/collapse branches, doesn’t exist in the out-of-box Document Library Web Part. Navigating down a folder branch requires the simple click of a link. However, navigating back up the branch requires the user to click the browser back button (1). This is a cumbersome user experience at best.

(1) UPDATE: The above has been improved in SharePoint 2016 and SharePoint Online. Now you can click a parent folder from the folder breadcrumb at the top of the list or library. However, if you are many levels deep into a folder structure, you will need to continue to click the parent folder to walk back up the folder tree!

Just so you are aware, there are options to help solve some of the navigation issues described above. You could write a custom Web Part, find publicly available code or purchase a 3rd party product. There is code and products available. However, I would first recommend you continue reading because these products won’t solve all of the problems you will have.

In addition to the navigation issues described above, folders hide the content contained within; especially when you use sub-folders. For example, when a user arrives at a site and they see a library named Shared Documents (which I also don’t recommend using), first off the name of that library doesn’t tell them anything about what it contains. Also, if the user clicks on the library, all they see is the first layer of folders. This may begin to indicate what files are contained within those folders but doesn’t suggest anything about what might be contained within sub-folders. Again, hiding content and detail from users; forcing them to traverse folders until they find what they are looking for. Not very efficient at all.

Remember, if it takes a long time for a user to find an important document, quite often they will make a local copy for future reference; so they don’t have to go through the pains of finding it again on your Intranet. Findability is extremely important!

I also have to make a comment about manually managing folder-level security; avoid it at all costs! The use of it can and will become confusing for your user-base. I have seen structures become so complex, contributors loose comfort knowing where to store and manage their content. And what happens when contributors loose comfort and security with the solutions we implement? They stop using them and go back to what they feel secure and comfortable with… Something else to remember, security is one of the most complex features to teach a non-technical user. If you are expecting your non-technical user-base to manage item and folder-level security, it will eventually be done so incorrectly; this brings up a whole different set of issues (good topic for another article). And, if you aren’t expecting the general non-technical user to manage their own security (which is good, I don’t recommend it) then you are placing the burden of that management on Site Collection Administrators, IT or whomever you have it assigned to.

Lastly, let’s talk about content duplication and single source of truth. Content duplication occurs in an organization in many different ways; so many that we don’t want to add to the problem. Folders hide content. As such, if it takes a long time for a user to find an important document, they are more likely to make a local copy of that document so they don’t have to find it again in the future. Another way duplication occurs by using folders, is by simply needing a document to be present in multiple folders. For example, let’s say you have a document that is related to 2 of 3 areas of Human Resources Benefits; related to Medical and Dental Benefits but not Vision Benefits. If you have benefit documents broken down in folders by benefit type (which is common), you may have to duplicate this common document in 2 places. Again, we have to avoid the duplication of content on our document management system at all costs. It’s called managing the single source of truth!

So… what can be done to solve these problems, improving the user experience and overall findability?

First and foremost, consider using metadata! Whether you choose to continue using a Document Library named Shared Documents or not, I would recommend you start applying Content Types and metadata to your documents. As a simplified example, move all of your documents in a library to the root folder and apply metadata that can be used to filter the view. Still not the greatest user experience; however, a user will at least be able to see all of the files contained within a library simply by clicking the library link. They can then filter the view down using the metadata column filtering abilities built in to SharePoint.

Using more Document Libraries is an even better approach to solving the overuse of folders issue. Let me demonstrate; a user arrives at a Human Resources site and is presented with a Document Library named Shared Documents, with folders and sub-folders. Well, you already know how I feel about this user experience. Now improve the experience for the user by creating multiple Document Libraries; one named Medical Benefit Documents, another named Dental Benefit Documents and another named Vision Benefit Documents. Using this approach alone will significantly improve the user experience from a findability perspective. The Medical Benefit Documents library has a Content Type associated with it named Medical Benefit Document; which forces the contributor to store and manage only documents of type Medical Benefit. This also helps with your overall IA too; but that’s a whole different article series! Just be certain to not have your Document Libraries so generic that you have to manage too many Content Types with it; this can also be confusing for contributors.

Another approach, and one I use all the time, is to build your hierarchy with sub-sites. Take Human Resources Benefits for example. You may be better suited having a Benefits sub-site then sub-sites below that, one for each specific type of benefit (Medical, Dental and Vision). There are many, many advantages to using sub-sites in this manner. Sub-sites, used in this manner are really nothing more than what is called “a point of aggregation and association”. Let me provide you with another example. On a Medical Benefits sub-site you can store and manage related announcements, policies, procedures, forms, FAQ’s, glossary terms, links to external references and so on. You are basically bringing the user to a new level of experience when you aggregate all information associated with Medical Benefits on a single sub-site.

Another advantage to using sub-sites as a point of aggregation and association, is realized when you begin to aggregate content to a higher level on your Intranet. For example, if you choose to aggregate all Policy Document (documents of type Policy) to an aggregate view using the Content Query Web Part, those policies can be grouped by site/sub-site. This is a very useful view and cannot be produced automatically using folders.

So how do you handle the folder-level security confusion issue described above Bob? Great question, and I’m glad you asked! Remember, my implementations utilize sub-sites and multiple document libraries. I simply place a Content Editor Web Part above the Document Library Web Part and use it to describe the libraries intended use and security. I target this Web Part to the contributor audience so it is only displayed for those who are contributors on that specific site or page.

The document management/Intranet solutions I have implemented, contain a wide rage of the techniques described above. The actual implementation techniques used all depends on the size of organization, amount of content, contributors, consumers, security and a myriad of other requirements. It is my hope that some of these techniques help with your next implementation or give you ideas of how to improve your current implementation.

Please leave questions and comments below as it tends to help me understand what other articles I need to write!

Until next time…