Ab und an kommt es vor, dass gewünscht wird entsprechende Dokumente aus einer Dokumentenbibliothek zu löschen. Oder gleich den kompletten Bibliotheksinhalt zu löschen. Die Library selber sollte aber bestehen bleiben.
Ebenfalls nicht ausser Acht gelassen, sollten hierbei die aktuellen SharePoint Limits. Dies ist mit ein paar wenigen Items sicherlich ohne Probleme möglich. Bei einer Bibliotheksgrösse von mehr als ~ 2‘200‘000 Elementen und bei einer Contentdatenbak von ~200 GB, sieht dies schon anders aus . Hier kann nicht mehr so schnell, schnell die einzelnen Elemente löschen.

________________________________________

Problemstellung / Ausgangslage:

Als Beispiel gehen wir von einer Dokumentenbibliothek von einer Grösse von mehr als 2‘200‘000 Elementen aus. Zum Löschen der einzelnen Elemente kann man einer der folgenden Methoden einsetzen:

________________________________________

Lösung:

  1. Variante: „PowerShell Script to delete items from SharePoint List“

    Folgend ein TechNet Script, welches Elemente aus der SharePoint-Liste, mit CAML Query löscht. Das Skript löscht alle Elemente die 7 Tage vorher erstellt wurden:

    [System.reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

    $web = Get-SPWeb "YOUR SHAREPOINT SITE"

    $list = $web.Lists["YOUR LIST NAME"]

    $DeleteBeforeDate = [Microsoft.SharePoint.Utilities.SPUtility]::CreateISO8601DateTimeFromSystemDateTime([DateTime]::Now.AddDays(-7))

    $caml='<Where> <Lt> <FieldRef Name="Created" /><Value Type="DateTime">{0}</Value> </Lt> </Where> ' -f $DeleteBeforeDate

    $query=new-object Microsoft.SharePoint.SPQuery

    $query.Query=$caml

    $col=$list.GetItems($query)

    Write-Host $col.Count

    $col | % {$list.GetItemById($_.Id).Delete()}

    $web.Dispose()

    Hier ist die offizielle Seite und das Script kann hier runter geladen werden:

    https://social.technet.microsoft.com/wiki/contents/articles/17895.powershell-script-to-delete-items-from-sharepoint-list.aspx

  2. Variante: Verbindung via Microsoft Access:

    Durch die Verbindung der Liste mit Microsoft Access, können alle Elemente ausgewählt und gelöscht werden. Mit dieser Variante lassen Sich auch je nach Grösse der Liste gut Anpassungen vornehmen:

    Die folgenden Schritte müssen hierzu durchgeführt werden:

    • Öffnen Sie Access und erstellen Sie eine leere Datenbank
    • Im Ribbon, gehen Sie  zu “External Data” und klicken Sie auf das Dropdown-Menü Mehr ... im Bereich Import & Link.
    • Wählen Sie die SharePoint-Liste aus
    • Geben Sie die URL der SharePoint-Website an, in welcher die Liste aufgeführt ist
    • Vergewissern Sie sich, dass die Standardoptionsschaltfläche ausgewählt ist, um eine Verbindung zu Access und der SharePoint-Liste herzustellen
    • Klicken Sie auf Weiter und wählen Sie die Liste aus, mit der Sie arbeiten möchten
    • Klick OK

    Für den Zugriff wird eine neue Tabelle eingerichtet, welche mit der SharePoint Liste verknüpft wird. Diese Liste können Sie wie jede andere Tabelle in Access öffnen.
    Öffnen Sie die Tabelle - ab nun haben Sie die Möglichkeit, die gewünschten Elemente auszuwählen, die Sie bearbeiten oder löschen möchten.

    Hierbei ist zu beachten, dass in der Central Administration allenfalls der „List View Threshold“ angepasst werden muss. Andernfalls werden die gewünschten Elemente der Liste nicht angezeigt und können nicht editiert werden.

  3. Variante: mit Tool z.B. Metalogix Content Matrix

    Hier besteht die Möglichkeit die komplette Konfiguration der gewünschten Bibliothek als XML zu exportieren und anschliessend die "neue" Leere Bibliothek wieder in einer neuen Datenbank bzw. WebApplication einzuspielen. So hat man relativ schnell eine leere Identische Bibliothek im System.

  4. Client-side SharePoint PowerShell

    Eine weitere mögliche Variante ist es über “Client-side SharePoint PowerShell” Files zu löschen. Dies habe ich selber noch nicht getestet, ist aber allenfalls auch eine Möglichkeit welche in Betracht gezogen werden kann. Hier gibt es eine Funktion namens „Clear-ListContent“, die die Arbeit übernimmt. Schaut es Euch doch selber mal an, die Bibliothek von Ryan Yeats scheint mir allenfalls auch noch eine Option zu sein: http://sharepointpowershell.codeplex.com/

  5. Variante: Explorer View

    Hier kann die gewünschte Bibliothek in der “Explorer View” geöffnet werden und anschliessend die einzelnen Elemente gelöscht werden. Bitte beachtet hierzu allfällige Clientseitige Limitationen welche ich im nachfolgenden Blog bereits beschrieben habe:

    http://blog.trivadis.com/b/collaboration/archive/2016/11/14/es-ist-nicht-m-246-glich-gro-223-e-dokumentbibliothek-in-der-explorer-ansicht-zu-durchsuchen.aspx


    Auch hier spielt selbstverständlich die Grösse bzw. die Anzahl der Elemente eine nicht zu vernachlässigende Rolle bei der Umsetzung.

  6. Variante: Weiteres Script zum Löschen via PowerShell (inkl. Papierkorb und verschieben in neue leere Datenbank)

    Das nachfolgende Script löscht nicht nur die gewünschten Files, es löscht auch gleich noch den Papierkorb und verschiebt die leeren Bibliotheken in eine neue Datenbank:

    param
    (
        [Parameter(Mandatory=$true,Position=0)][string]$SPWebUrl = $(throw '- Need parameter SPWebUrl'),
        [Parameter(Mandatory=$false,Position=1)][array]$SPListNames = @("Documents1","Documents2")
    )
    Add-PSSnapin Microsoft.SharePoint.Powershell -EA 0
    function ProcessDelete ($spweburl, $spListname, $folders){
        $web = get-spweb $spweburl
        $list = $web.lists[$SPListName]
        # $web = get-spweb "http://abcd.next"
        # $list = $web.lists["Documents1"]
        $rowlimit = 100;
        if ($folder -eq $true){
            $global:ResumingItems = $list.Folders.Count
        }
        else{
            $global:ResumingItems = $list.Items.Count
        }
        [System.Text.StringBuilder] $deleteBldr = New-Object "System.Text.StringBuilder";
        $deleteBldr.Append("<?xml version=""1.0"" encoding=""UTF-8""?><Batch>");
        $i=0
        $spQuery = New-Object Microsoft.SharePoint.SPQuery;
        if ($folder -eq $true){
        $spQuery.ViewAttributes = "";
        }
        else{
        $spQuery.ViewAttributes = "Scope='Recursive'";
        }
        $spQuery.RowLimit = $rowlimit;
        $spQuery.Query = '';
        $items = $list.GetItems($spQuery);
        $count = $items.Count
        while ($i -le ($count-1))
        {
            $item = $items[$i]
            write-host $item.File.ServerRelativeUrl
            write-host $item.Folder.ServerRelativeUrl
            if($folder -ne $true -and $($item.File).CheckOutStatus -ne "None" )
            {
                write-host "Automatic CheckIn for file $($($item.File).ServerRelativeUrl) by Administrator" -foregroundcolor green
                try{
                    $($item.File).CheckIn("Automatic CheckIn. (Administrator)")
                }
                catch{
                }
            }
            elseif ($($item.Folder) -ne $NULL){
                write-host "Delete Folder $($item.Folder.ServerRelativeUrl)";
                $list.Folders.DeleteItemById($item.Folder.Item.ID)
            }
            # write-host $item.id

            $deleteBldr.Append("<Method><SetList Scope=""Request"">" + $list.ID + "</SetList><SetVar Name=""ID"">" + $item.Id + "</SetVar><SetVar Name=""owsfileref"">$($item.File.ServerRelativeUrl)</SetVar><SetVar Name=""Cmd"">Delete</SetVar></Method>") -eq $NULL;
            $global:ResumingItems = $global:ResumingItems-1
            $host.ui.RawUI.WindowTitle = "Total $global:ResumingItems items in this list ( $SPListName )remaining.. "
            $i++
        }
        try{
            $deleteBldr.Append("</Batch>")
            if ($($web.ProcessBatchData($deleteBldr.ToString()) -notlike "*ErrorText*") -eq $true){
            }
            else{
                $items | %{$list.Items.DeleteItemById($_.Id)}
            }
        }
        catch{
        }
        write-host "Emptying Recycle Bin..."
        $web.RecycleBin.DeleteAll()
        $host.ui.RawUI.WindowTitle = "Total $global:ResumingItems items in this list ( $SPListName )remaining.. "
        if ($global:ResumingItems -ne 0){
            $global:ResumingItems
            ProcessDelete $SPWebUrl $SPListName
        }
        else{
        $Global:TotalCount = $Global:TotalCount+$Count
        }
    }
    $watch = [System.Diagnostics.Stopwatch]::StartNew()
    try
    {
        #Files
        foreach ($SPListName in $SPListNames){
        ProcessDelete $SPWebUrl $SPListName
        }
        #Folders
        foreach ($SPListName in $SPListNames){
        ProcessDelete $SPWebUrl $SPListName -folders:$true
        }
        $web = get-spweb $spweburl
        $web.site.RecycleBin.DeleteAll()
        #write-host "Moving Site in separate Site Collection..."
        Move-SPSite -Identity $($web.Site.WebApplication.Url) -DestinationDatabase "SPContent_ABC_0" -confirm:$false -verbose
        $web.dispose()
    }
    catch{
        Write-Host -ForegroundColor Red $_.Exception.ToString()
    }
    finally{
    write-host -ForegroundColor Green "done."
    #stats
    $minutes = ($watch.ElapsedMilliseconds/1000/60);
    write-host -ForegroundColor Green "Done! deleted $Global:TotalCount items in $minutes minutes."
    }


  7.  Variante: weiteres Script zum löschen via PowerShell

    Zum Schluss nochmals ein weiteres Script zum Löschen der Inhalte. Dieses Script ist aber eher für kleinere Libraries einzusetzen und ist ebenfalls auch etwas langsamer bei der Umsetzung, bzw. beim Einsatz in sehr grossen Dokumentenbibliotheken:

    [System.Reflection.Assembly]::Load("Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")
    # "Enter the site URL here"
    $SITEURL = "http://URL_ABCD"

    $site = new-object Microsoft.SharePoint.SPSite ( $SITEURL )
    $web = $site.OpenWeb()
    "Web is : " + $web.Title
     
    # Enter name of the List below
    $oList = $web.Lists["Documents1"];

    "List is :" + $oList.Title + " with item count " + $oList.ItemCount
    $collListItems = $oList.Items;
    $count = $collListItems.Count - 1
    # -----------
    for($intIndex = $count; $intIndex -gt -1; $intIndex--)
    {
            "Deleting : " + $intIndex
            $collListItems.Delete($intIndex);

    }

*Disclaimer: Verwendung der Codezeilen / Anpassung der Windows-Registrierung auf eigene Gefahr.
Wir übernehmen keinerlei Verantwortung für Probleme, die durch das Ausführen der Codezeilen oder Anpassungen in der Windows-Registrierung entstehen.