Thursday 14 August 2014

Archive Sharepoint 2007/2010 List

There was a requirement where I work to automate archiving of Sharepoint 2007 lists. Thought someone might find my powershell implementation useful.

If running SharePoint on Windows 2003, one just needs to install Powershell components.

Thanks go out to http://www.astaticstate.com/2007/10/copy-version-history-with_5.html. My implementation adapted from their code.


### CHANGE ME ###########################

# Expiration date #
$expireDate = (Get-Date).AddDays(-365) 
# Base site URL #
$spSiteUrl="http://path/to/sharepoint/site"
# Source and destination list URLS
$srcListUrl=$spSiteUrl+"/Lists/Request"
$dstListUrl=$spSiteUrl+"/Lists/Archive Request"

#########################################

[System.Reflection.Assembly]::Load(Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c) 
[System.Reflection.Assembly]::Load(Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c) 

# Connect to sharepoint site
$spSite=[Microsoft.SharePoint.SPSite]($spSiteUrl)
$spWeb=$spSite.OpenWeb();

# Get lists
$srcList=$spWeb.GetList($srcListUrl)
$dstList=$spWeb.GetList($dstListUrl)

# Get list items
$srcListItems = [Microsoft.Sharepoint.SPListItemCollection]($srcList.Items)
$dstListItems = [Microsoft.Sharepoint.SPListItemCollection]($dstList.Items)

$toArchive = 0
$toKeep = 0

$purgeIds = @()

# Preflight
Write "Calculating damage..."

foreach ($srcItem in $srcListItems){
    # Must not be younger than the expiration date or opened
    if($srcItem["Modified"] -gt $expireDate -or $srcItem["Request Status"] -ne "Closed"){
        $toKeep++
        continue
    }
    $purgeIds += $srcItem["ID"]
    $toArchive++
    
}

Write-Host To Keep: $toKeep
Write-Host To Archive: $toArchive

Write-Host "Here we go..."


# Loop through candidates
for ($s = 0; $s -lt $purgeIds.Count; $s++){

    $srcItem = $srcListItems.GetItemById($purgeIds[$s])

    # Must not be younger that the expiration date or opened
    if($srcItem["Modified"] -gt $expireDate -or $srcItem["Request Status"] -ne "Closed"){
        continue
    }
    # Dump the item name for later cleaning
    Write-Host Archiving '{' $srcItem["ID"] - $srcItem["Name"] - $srcItem["Title"] '}'

    # Add destination list item
    $newItem = $dstListItems.Add()
    
    # We must loop through each item version and create at destination
    for ($i=$srcItem.Versions.Count - 1; $i -ge 0; $i--) {

        # Loop through each field
        foreach ($srcField in $srcItem.Fields) {
            $version = $srcItem.Versions[$i]
         
            if ($srcField.ReadOnlyField -ne $True -and  $srcField.InternalName -ne "Attachments") {
                $newItem[$srcField.Title] = $version[$srcField.Title]
            }
            elseif ($srcField.Title -eq "Created" -or
                    $srcField.Title -eq "Created By" -or
                    $srcField.Title -eq "Modified" -or
                    $srcField.Title -eq "Modified By") {
                    
                    $newItem[$srcField.Title] = $version[$srcField.Title]
            }
        }
        # Update item for next version
        $newItem.Update()
    }
 
    # Whack the attachments to the list item
    foreach($baseName in $srcItem.Attachments){
        $file = $srcList.ParentWeb.GetFile($srcItem.Attachments.UrlPrefix + $baseName)
        $newItem.Attachments.Add($baseName, $file.OpenBinary())
    }

    # And another update
    $newItem.Update()
    
    # Purge the source
    $srcItem.Delete()

} # Move onto next candidate