Copy Files from SharePoint Library Folder to Another SharePoint Library Folder

$varSourceWebUrl="http://team/sites/teamsite1"
$varTargetWebUrl="http://team/sites/teamsite2"
$varSourceLibraryName = "Shared Documents"
$varTargetLibraryName = "Shared Documents"
$varSourceFolderUrl = "http://team/sites/teamsite1/Shared Documents/Subfolder/"
$varTargetParentFolderUrl = "http://team/sites/teamsite2/Shared Documents"

 $varSourceWeb = Get-SPWeb $varSourceWebUrl
 $varTargetWeb = Get-SPWeb $varTargetWebUrl 
 $varSourceLibrary = $varSourceWeb.Lists[$varSourceLibraryName]
 $varTargetLibrary = $varTargetWeb.Lists[$varTargetLibraryName]
 $varSourceFolder = $varSourceWeb.GetFolder($varSourceFolderUrl) 
 $varTargetFolder = $varTargetWeb.GetFolder($varTargetFolderUrl)
 $varTargetFolderParent = $varTargetWeb.GetFolder($varTargetParentFolderUrl)
 $varTargetFolderName =$varTargetFolder.Name
 if(!$varTargetFolder.Exists)
 {
 $varTargetFolder = $varTargetLibrary.AddItem($varTargetFolderParent,[Microsoft.SharePoint.SPFileSystemObjectType]::Folder,$varTargetFolderName)
 $varTargetFolder.Update()
 }
 $varSourceFolder = $varSourceWeb.GetFolder($varSourceFolderUrl)
 $varTargetFolder = $varTargetWeb.GetFolder($varTargetFolderUrl)
 $colSourceFiles = $varSourceFolder.Files
 foreach ($varSourceFile in $colSourceFiles) 
 {
 $varTargetFileUrl = $varTargetFolder.ServerRelativeUrl + "/" + $varSourceFile.Name
 $varTargetFile=$varTargetWeb.GetFile($varTargetFileUrl)
 if(!$varTargetFile.Exists)
 {
 $varBuffer = $varSourceFile.OpenBinary();
 $varNewTargetFile = $varTargetFolder.Files.Add($varTargetFile,$varBuffer,$true)
 }
 }
 
$varSourceWeb.Dispose();
$varTargetWeb.Dispose();
Posted in PowerShell, SharePoint 2010, SharePoint Library | Leave a comment

SharePoint Content Database Report using Powershell

#Enter a URL in the function at the bottom of this script Example: Report-SharePointDatabase -ReportURL "http://team/sites/reports"
#The first time you run the script, the script will create a custom list with the report fields in a datasheet view
#Each subsequent time you run the script, it will add to the existing list, but with a new report date

function Report-SharePointDatabase{
param(
[string]$ReportURL
)
$varReportDate = get-date
$varReportWeb = get-spweb $ReportURL
$varReportList = $varReportWeb.lists["SharePoint Database Report"]
if(!$varReportList)
{
$varListTemplate = $varReportWeb.listtemplates["Custom List"]
$varReportList = $varReportWeb.lists.add("SharePoint Database Report",
"SharePoint Database Report",$varListTemplate)
$varReportList = $varReportWeb.lists["SharePoint Database Report"]
$varAddField = $varReportList.fields.add("Server", "Text", $null)
$varAddField = $varReportList.fields.add("Status", "Text", $null)
$varAddField = $varReportList.fields.add("Warning Site Count", "Number", $null)
$varAddField = $varReportList.fields.add("Current Site Count", "Number", $null)
$varAddField = $varReportList.fields.add("Maximum Site Count", "Number", $null)
$varAddField = $varReportList.fields.add("Web Application","Text",$null)
$varAddField = $varReportList.fields.add("Attached to Farm","Text",$null)
$varAddField = $varReportList.fields.add("Storage Size GB","Number",$null)
$varAddField = $varReportList.fields.add("Storage Size TB","Number",$null)
$varAddField = $varReportList.fields.add("Needs Upgrade","Text",$null)
$varAddField = $varReportList.fields.add("Database Type","Text",$null)
$varAddField = $varReportList.fields.add("Report Date","DateTime",$null)

$varFields = new-object system.collections.specialized.stringcollection
$varViewField = $varFields.add("Title")
$varViewField = $varFields.add("Server")
$varViewField = $varFields.add("Current Site Count")
$varViewField = $varFields.add("Web Application")
$varViewField = $varFields.add("Storage Size GB")
$varViewField = $varFields.add("Storage Size TB")
$varViewField = $varFields.add("Needs Upgrade")
$varViewField = $varFields.add("Database Type")
$varViewField = $varFields.add("Report Date")
$varView = $varReportList.views.add("AllData", $varFields, $null, 50, $true, $true, "GRID", $false)
$varView.update()
$varView = $varReportList.views["AllData"]
$varView.aggregations = "
"
$varView.aggregationsstatus="On"
$varView.query = '
'
$varView.update()
}

$colContentDatabases = get-spdatabase
foreach($varContentDatabase in $colContentDatabases)
{
$varNewItem = $varReportList.items.add()
$varNewItem["Title"] = $varContentDatabase.name
$varNewItem["Server"] = $varContentDatabase.server
$varNewItem["Status"] = $varContentDatabase.status
$varNewItem["Warning Site Count"] = $varContentDatabase.warningsitecount
$varNewItem["Web Application"] = $varContentDatabase.webapplication.name
$varNewItem["Current Site Count"] = $varContentDatabase.currentsitecount
$varNewItem["Storage Size GB"] = [Math]::round(($varContentDatabase.disksizerequired/1GB),4)
$varNewItem["Storage Size TB"] = [Math]::round(($varContentDatabase.disksizerequired/1TB),4)
$varNewItem["Attached to Farm"] = $varContentDatabase.isattachedtofarm
$varNewItem["Needs Upgrade"] = $varContentDatabase.needsupgrade
$varNewItem["Maximum Site Count"] = $varContentDatabase.maximumsitecount
$varNewItem["Database Type"] = $varContentDatabase.type
$varNewItem["Report Date"] = $varReportDate
$varNewItem.update()
}
write-host "==Script complete=="
$varReportWeb.dispose()
}

Report-SharePointDatabase -ReportURL "http://team/sites/reports"

Posted in PowerShell, SharePoint 2010 | Tagged , , | Leave a comment

SharePoint – PowerShell – Export List Data from a view to CSV and Save in a SharePoint Library

I really like this script.  You create a view in the SharePoint UI with the fields you want, filters, etc., (Script does not include sorting) and it will export that data to a CSV file and save it on your SharePoint site in a Library.  You could also create a PowerShell scheduled task on your server to run a nightly local backup. Let me know if this helps anyone.


$url="http://teamsite"
$lists =
"Customers",
"Customer Calls"
$viewname = "Backup View"
#Make the view name the same for all lists
$libraryname="Backups"
#Location of the backups - create this SharePoint Library in advance
$web = get-spweb $url
foreach($listname in $lists)
{
$list = $web.lists[$listname]
$date = get-date -format yyyy-MM-dd
$webfolder = $web.getfolder($libraryname)
$view = $list.views[$viewname]
$view.rowlimit = 100000
#This will temporarily update the view row limit - it gets set back to 30 at the end of the script
$view.update()
$vfields=$view.viewfields
$lfields=$list.fields
$efields=@()
foreach($vf in $vfields)
{
foreach($lf in $lfields)
{
if($lf.internalname -eq $vf)
{
$efields += $lf.title
}
}
}
$items = $list.getitems($view)
if($items.count -gt 0)
{
$exportlist = $null
$exportlist = @()
$items | foreach {
$hash = $null
$hash = @{}
foreach($ef in $efields)
{
$hash.add($ef, $_[$ef])
}
$obj = New-Object PSObject -Property $hash
$exportlist += $obj
}
$sel=@()
foreach($efield in $efields)
{
$sel+=$efield
}
$expath = "E:\ListDataBackups\"+[string]$date+'-'+$listname+'.csv'
$exportlist |select $sel | Export-Csv -path $expath -notypeinformation
$file = get-item -path $expath
$fileStream = ([System.IO.FileInfo] (Get-Item $file.FullName)).OpenRead()
$spFile = $webfolder.Files.Add($webfolder.Url + "/" + $file.Name, [System.IO.Stream]$fileStream, $true)
$fileStream.Close();
$view.rowlimit = 30
$view.update()
}
}
$web.dispose()

Posted in PowerShell, SharePoint 2010 | Tagged , , , , | 2 Comments

PowerShell – Copy Current Navigation from SharePoint Site to another SharePoint Site

Very Handy! Use this in a content migration scenario, or updating many sites with the same navigation.

$sourcewebURL = "http://teams/sites/teamsiteA"
$targetwebURL = "http://teams/sites/teamsiteB"
$find = "/teamsiteA/"
$replace = "/teamsiteB/"
$targetweb = get-spweb $targetwebURL
$sourceweb = get-spweb $sourcewebURL
$targetpub = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($targetweb)
$targetnav = $targetpub.navigation.currentnavigationnodes
$currentIds = @();
$targetpub.Navigation.currentnavigationnodes | ForEach-Object { $currentIds = $currentIds + $_.Id; }
$currentIds | ForEach-Object {
$currentNode = $targetweb.navigation.GetNodeById($_);
$targetnav.Delete($currentNode)}
$sourcepub = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($sourceweb)
$sourcenavs = $sourcepub.navigation.currentnavigationnodes
foreach($sourcenav in $sourcenavs)
{
$targetnavurl = $sourcenav.URL.replace($find,$replace)
$targetnavtitle = $sourcenav.Title.replace($find,$replace)
$newnavmethod = [Microsoft.SharePoint.Publishing.Navigation.SPNavigationSiteMapNode]::CreateSPNavigationNode
$heading = $newnavmethod.Invoke($targetnavtitle, $targetnavurl, [Microsoft.SharePoint.Publishing.NodeTypes]::Heading, $targetnav);
$sourcenavlinks = $sourcenav.children
$headingchildren = $heading.children;
foreach($sourcenavlink in $sourcenavlinks)
{
$targetnavlinkurl = $sourcenavlink.URL.replace($find,$replace)
$targetnavlinktitle = $sourcenavlink.Title.replace($find,$replace)
$targetnavlink = $newnavmethod.Invoke($targetnavlinktitle,$targetnavlinkurl, [Microsoft.SharePoint.Publishing.NodeTypes]::AuthoredLinkPlain, $headingchildren)
}
}

Posted in Uncategorized | 4 Comments

SharePoint and Large Lists – some tips!

SharePoint is a framework. As such, it’s generic. Many times you need a site to be stretched to fulfill a specific mission – and in many cases, this involves large lists with a high quantity of columns. You really have to keep an eye on the site, and the SQL server behind your farm.

Large lists are defined within a spectrum that includes record counts of higher than 2,000 items.  Although, a list with 2,000 items can have its own set of issues….

I have supported lists with over 2,000,000 items – clearly not recommended – but many times you inherit a farm that you need to re-architect while keeping the business running.

Here’s some very important tips:

  • Never use calculated columns – they will bring queries to their knees.  They also effectively kill the sustainability of InfoPath forms.  If you have a large list and need to make a change to an InfoPath form, calculated fields will cause the publishing process to time out.  You will be stuck with the form and won’t be able to make changes to it (I’ve observed this at about the 10,000+ list item level).
  • Lookup fields – at some point a large list will truly become too large and you will need to re-architect it.  If you have been using lookup fields, you will find it very difficult to “re-wire” the list.  It also can have very detrimental impacts to SQL server performance if you have instituted too many.
  • Strictly monitor and restrict who can create views.  I use a PowerShell script to frequently inventory the views on my lists – some lists have hundreds of views – it may only take one view to bring the whole list crashing down.
  • Multi-Line text fields configured to append – this provides an excellent business tool and always answers a business requirement – however, they become an administration nightmare.   It starts out providing great auditing, interaction, item history, etc., but when the list really becomes too large, or users want more transparency into that data – SharePoint doesn’t easily expose the versioned-appended fields.  The business users will also insist that you then cannot limit the number of versions as this will delete their appended text data.  Now you have multiplied the problem by having a large list with millions of versions as well (each list item, in effect, becomes a list!  Now you have lists inside of lists!).
  • Attachments – if you anticipate a list is going to grow – disable attachments.  Plenty of PowerShell scripts can help administer attachments, but from experience, it’s difficult to sustain.  Users may be expecting the kind of version control, metadata, and historical details from attachments that they expect from document libraries – but they will be disappointed.
  • When possible, even avoid using People fields – if views filtered by user, or assignments are required, you will probably need to use a People field.  In many instances, the outcome of a large list solution is to graduate the solution to a different application.  People fields can make it challenging to connect the data to other systems.  When sites become several years old, the users are no longer valid and become problematic when moving the lists around to different sites and different environments.
Posted in Uncategorized | Leave a comment

Thoughts…

Just needed to write – ever have moment when life just reaches out and spins you around? Complete disorientation! Old programs that were dormant, kick in and start running. Where did that code come from?

It’s a mix of panic, of motivation, of thought, of inspiration, of regret, of hope, of change, of reassessment, of context, of alignment, of meaning, of purpose.

Recently read a fascinating book “Proof of Heaven, A Neurosurgeon’s Journey into the Afterlife” – it unlocked some thoughts and ideas deep inside of me. We are definitely on a journey.

Posted in Uncategorized | Leave a comment

SharePoint – need more Date/Time Fields

Sometimes you have to break glass. You don’t want to, but you don’t have any other option. What to do when you need to add more field types (such as Date/Time) to a SharePoint list? When necessary, you can let SQL wrap rows and provide more columns to your list. However, the math adds up really fast – your removing a safety brake that taxes your SQL resource – so be cautious:

$wa = get-spwebapplication sharepointwebappname
$wa.MaxListItemRowStorage = 8
$wa.Update()

As the character Marcus Brody says in Indiana Jones, “You’re meddling with powers you can’t possibly comprehend!” (well, this might be extreme – I think we comprehend SharePoint a little..)

Posted in Uncategorized | Leave a comment