{"id":1131,"date":"2013-04-16T21:40:27","date_gmt":"2013-04-16T21:40:27","guid":{"rendered":"http:\/\/turtlellc.com\/?p=1131"},"modified":"2017-09-22T20:00:58","modified_gmt":"2017-09-22T20:00:58","slug":"archive-a-sharepoint-list","status":"publish","type":"post","link":"https:\/\/www.turtle.works\/knowledge\/archive-a-sharepoint-list\/","title":{"rendered":"Archive a SharePoint List"},"content":{"rendered":"<p><a href=\"http:\/\/turtlellc.com\/wp-content\/uploads\/2013\/04\/raiders_of_the_lost_archive_450.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignright size-full wp-image-1254\" src=\"http:\/\/turtlellc.com\/wp-content\/uploads\/2013\/04\/raiders_of_the_lost_archive_450.jpg\" alt=\"archive a SharePoint list\" width=\"275\" height=\"183\" \/><\/a><\/p>\n<h2>Intro<\/h2>\n<p>A SharePoint list was filling up rapidly and had exceeded 5,000 items. Not wanting to use filtered views, the user instead wanted to archive the older items. This seemed like the perfect automation nut to to crack open with the PowerShell ISE editor. Keep reading to learn how to archive a SharePoint list.<!--more--><\/p>\n<p>The rate at which users were entering items\u00a0required\u00a0an archive done every quarter. From a high level this seemed straight forward:<\/p>\n<ol>\n<li><span style=\"font-size: 13px; line-height: 13px;\">Connect to the site<\/span><\/li>\n<li><span style=\"line-height: 13px; font-size: 13px;\">For each year, going back 10<\/span>\n<ol>\n<li><span style=\"line-height: 13px; font-size: 13px;\">And for each quarter<\/span>\n<ol>\n<li><span style=\"line-height: 13px; font-size: 13px;\">Query the list for items to archive<\/span><\/li>\n<li><span style=\"font-size: 13px;\">Create an archive list if necessary<\/span><\/li>\n<li><span style=\"font-size: 13px;\">Move the items to the archive list<\/span><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<h3>Connect to the site<\/h3>\n<p>Let&#8217;s begin by connecting to the site there are two ways to do this either by hard coded values or passing in the site collection and web site as parameters to the script. You&#8217;ll notice the very first line of the script deals with parameters. There are four parameters for this script:<\/p>\n<ol>\n<li><span style=\"font-size: 13px;\">$sitePath: which is the site collection for the list<\/span><\/li>\n<li><span style=\"font-size: 13px;\">$webPath: which is the relative path for any sites or sub-sites within the site collection<\/span><\/li>\n<li><span style=\"font-size: 13px;\">$sourceList: which is the list that needs to be archived<\/span><\/li>\n<li><span style=\"font-size: 13px;\">$destListPrefix: which is the list we write archived items to<\/span><\/li>\n<\/ol>\n<p>The first line of the script:<\/p>\n<p>[powershell]<br \/>\nparam(<br \/>\n[string]$sitePath = &#8220;http:\/\/sharepoint1&#8221;,<br \/>\n[string]$webPath = &#8220;&#8221;,<br \/>\n[string]$sourceList = &#8220;Supervisor Log&#8221;,<br \/>\n[string]$destListPrefix = &#8220;Supervisor Log&#8221;)<br \/>\n[\/powershell]<\/p>\n<p>And the actual connection:<\/p>\n<p>[powershell]<br \/>\n$site = new-object Microsoft.SharePoint.SPSite($sitePath)<br \/>\n$web = $site.AllWebs | where { $_.name -eq $webPath}<br \/>\n[\/powershell]<\/p>\n<h4>Set archive date variables<\/h4>\n<p>The main code path is wrapped in a try catch block near the end of the script. The code block gets the current year and month and then calls a function to determine what the archived date variables are. The setArchiveDateVars function has five parameters: current year, current month, archive year, archive month, and archive quarter. \u00a0The archive parameters are passed by reference. \u00a0Below is the source code for that function, you can see how it handles moving back to the previous month, previous quarter and previous year.<\/p>\n<p>[powershell]<\/p>\n<p>function SetArchiveDateVars([int]$curYr, [int]$curMonth,<br \/>\n[ref]$archYr, [ref]$archMonth, [ref]$archQtr)<br \/>\n{<br \/>\n#Set archive quarter, year and month<br \/>\nif ($curMonth -lt 4)<br \/>\n{<br \/>\n$archYr.Value = $curYr &#8211; 1<br \/>\n$archMonth.Value = 12<br \/>\n$archQtr.Value = 4<br \/>\n}<br \/>\nelseif (3 -lt $curMonth -and $curMonth -lt 7)<br \/>\n{<br \/>\n$archYr.Value = $curYr<br \/>\n$archMonth.Value = 3<br \/>\n$archQtr.Value = 1<br \/>\n}<br \/>\nelseif (6 -lt $curMonth -and $curMonth -lt 10)<br \/>\n{<br \/>\n$archYr.Value = $curYr<br \/>\n$archMonth.Value = 6<br \/>\n$archQtr.Value = 2<br \/>\n}<br \/>\nelseif (9 -lt $curMonth)<br \/>\n{<br \/>\n$archYr.Value = $curYr<br \/>\n$archMonth.Value = 9<br \/>\n$archQtr.Value = 3<br \/>\n}<br \/>\n}<br \/>\n[\/powershell]<\/p>\n<h3>For each year and quarter<\/h3>\n<p>After setting the archived date variables, the script sets the $site, $web and listA objects. $listA is the list to archive. \u00a0Once we have set those SharePoint objects in our script, we begin looping backward on the year and then quarter.<\/p>\n<p>[powershell]<br \/>\ntry<br \/>\n{<br \/>\n&#8230;<br \/>\n#Loop thru years<br \/>\nfor ($archYr = $archYr; ($curYr &#8211; $archYr) -lt 10; $archYr&#8211;)<br \/>\n{<br \/>\n#Loop thru quarters<br \/>\nfor ($qtrCnt = 1; $qtrCnt -lt 5; $qtrCnt++)<br \/>\n{<br \/>\n&#8230;<br \/>\n[\/powershell]<\/p>\n<h3>Query the list for items to archive<\/h3>\n<p>For each quarter we retrieve list items by using the GetItemsToMigrate function. This function uses <a title=\"SPQuery\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms466353.aspx\" target=\"_blank\" rel=\"noopener\">SPQuery<\/a> to filter list items.<\/p>\n<p>[powershell]<br \/>\n&lt;# Returns: SPList of items between $startDate and $endDate Globals Used: $listA #&gt;<br \/>\nfunction GetItemsToMigrate([string]$startDate, [string]$endDate)<br \/>\n{<br \/>\n$spQuery = new-object Microsoft.SharePoint.SPQuery<br \/>\n$camlQuery =<br \/>\n&#8216;&lt;Where&gt;<br \/>\n&lt;And&gt;<br \/>\n&lt;Leq&gt;<br \/>\n&lt;FieldRef Name=&#8221;MyCreated&#8221; \/&gt;<br \/>\n&lt;Value Type=&#8221;DateTime&#8221; IncludeTimeValue=&#8221;False&#8221;&gt;&#8217; + $endDate + &#8216;&lt;\/Value&gt;<br \/>\n&lt;\/Leq&gt;<br \/>\n&lt;Geq&gt;<br \/>\n&lt;FieldRef Name=&#8221;MyCreated&#8221; \/&gt;<br \/>\n&lt;Value Type=&#8221;DateTime&#8221; IncludeTimeValue=&#8221;False&#8221;&gt;&#8217; + $startDate + &#8216;&lt;\/Value&gt;<br \/>\n&lt;\/Geq&gt;<br \/>\n&lt;\/And&gt;<br \/>\n&lt;\/Where&gt;&#8217;<br \/>\n$spQuery.Query = $camlQuery<br \/>\n$localItems = $listA.GetItems($spQuery)<br \/>\n, $localItems<br \/>\n}<br \/>\n[\/powershell]<\/p>\n<p>The <strong>, <\/strong>at the front of the last line ensures only the list of $localItems is returned from the function.<\/p>\n<h3>Create an archive list if necessary<\/h3>\n<p>Now that we have a list of items to archive, we can create an archive list and move those items to that list. \u00a0We only create a list when it doesn&#8217;t already exist, we check this with the TryGetList function.<\/p>\n<p>We create the archive list by saving the source list has a template, then creating a new list from that template and finally adding fields to handle CreatedBy, ModifiedBy, Created and Modified.<\/p>\n<p>[powershell]<br \/>\nfunction CreateList([string]$destListName, [string]$destListDesc)<br \/>\n{<br \/>\n#Make Template<br \/>\n$sourceList = $web.Lists[$sourceListName]<br \/>\n$templateName = $sourceList.Title<br \/>\n$templateFileName = $sourceList.Title<br \/>\n$sourceList.SaveAsTemplate($templateFileName, $templateName, $sourceList.Description, 0)<\/p>\n<p>#Add List<br \/>\n$listTemplate = $site.GetCustomListTemplates($web)[$templateName]<br \/>\n$web.Lists.Add($destListName, $destListDescription, $listTemplate)<br \/>\n$web.Update()<\/p>\n<p>#Remove Template<br \/>\n$listTemplates = $site.RootWeb.Lists[&#8220;List Template Gallery&#8221;]<br \/>\n$listTemplateItems = $listTemplates.Items<br \/>\nforeach($listTemplateItem in $listTemplateItems)<br \/>\n{<br \/>\nif($listTemplate.Name.Equals($listTemplateItem[&#8220;Title&#8221;]))<br \/>\n{<br \/>\n$listTemplateItem.Delete()<br \/>\nbreak<br \/>\n}<br \/>\n}<br \/>\n#Add Columns to List<br \/>\n$listNew =$web.Lists[$destListName]<br \/>\n$listNew.Fields.Add(&#8220;Orig Created&#8221;, [Microsoft.SharePoint.SPFieldType]::DateTime, $False)<br \/>\n$listNew.Fields.Add(&#8220;Orig Created By&#8221;, [Microsoft.SharePoint.SPFieldType]::User, $False)<br \/>\n$listNew.Fields.Add(&#8220;Orig Modified&#8221;, [Microsoft.SharePoint.SPFieldType]::DateTime, $False)<br \/>\n$listNew.Fields.Add(&#8220;Orig Modified By&#8221;, [Microsoft.SharePoint.SPFieldType]::User, $False)<br \/>\n$listNew.Update()<br \/>\n}<br \/>\n[\/powershell]<\/p>\n<h3>Move the items to the archive list<\/h3>\n<p>The move is a two step process, copy the item to the archive list then delete the item from the source list. \u00a0I use the CopyItem function to:<\/p>\n<ol>\n<li>Copy each field<\/li>\n<li>Handle read only fields<\/li>\n<li>Handle the CreatedBy, ModifiedBy, Created dates and Modified dates<\/li>\n<li>Handle file attachments<\/li>\n<\/ol>\n<p>Files attached to an item are handled in the CopyItem function with this block of code:<\/p>\n<p>[powershell]<br \/>\n#Handle Attachments<br \/>\nforeach($leafName in $item.Value.Attachments)<br \/>\n{<br \/>\n$spFile = $web.GetFile($($item.Value.Attachments.UrlPrefix + $leafName));<br \/>\n$newItem.Attachments.Add($leafName, $spFile.OpenBinary());<br \/>\n}<br \/>\n[\/powershell]<\/p>\n<p>Then we decrement archive quarter, making adjustments for the previous year when necessary, and continue the looping.<\/p>\n<p>The Full script file link below contains the entire script needed to archive a SharePoint list. Enjoy the script and feel free to comment.<\/p>\n<h2>Resources<\/h2>\n<p><a title=\"Full script file\" href=\"http:\/\/turtlellc.com\/codeFiles\/archiveList\/ArchiveList.ps1\" target=\"_blank\" rel=\"noopener\">Full script file<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Intro A SharePoint list was filling up rapidly and had exceeded 5,000 items. Not wanting to use filtered views, the user instead wanted to archive the older items. This seemed like the perfect automation nut to to crack open with the PowerShell ISE editor. Keep reading to learn how to archive a SharePoint list.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[42,20],"tags":[],"class_list":["post-1131","post","type-post","status-publish","format-standard","hentry","category-powershell","category-sharepoint"],"_links":{"self":[{"href":"https:\/\/www.turtle.works\/knowledge\/wp-json\/wp\/v2\/posts\/1131","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.turtle.works\/knowledge\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.turtle.works\/knowledge\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.turtle.works\/knowledge\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.turtle.works\/knowledge\/wp-json\/wp\/v2\/comments?post=1131"}],"version-history":[{"count":1,"href":"https:\/\/www.turtle.works\/knowledge\/wp-json\/wp\/v2\/posts\/1131\/revisions"}],"predecessor-version":[{"id":1711,"href":"https:\/\/www.turtle.works\/knowledge\/wp-json\/wp\/v2\/posts\/1131\/revisions\/1711"}],"wp:attachment":[{"href":"https:\/\/www.turtle.works\/knowledge\/wp-json\/wp\/v2\/media?parent=1131"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.turtle.works\/knowledge\/wp-json\/wp\/v2\/categories?post=1131"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.turtle.works\/knowledge\/wp-json\/wp\/v2\/tags?post=1131"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}