# Start-SPMigration PowerShell-Skript fuer die Migration von SharePoint On-Premise Inhalten ueber das serverseitige Objektmodell. Das Skript kann: - Dokumentbibliotheken exportieren - Dateien inklusive Metadaten exportieren - normale SharePoint-Listen und deren Eintraege exportieren - exportierte Inhalte wieder in ein Ziel-Web importieren - beim Export automatisch eine JSON-`MappingTable` fuer Feld-, Listen- und Bibliotheks-Mappings erzeugen - beim Import dieselbe `MappingTable` fuer Container- und Metadaten-Mappings verwenden ## Voraussetzungen - SharePoint On-Premise Server - Ausfuehrung auf einem Server mit installiertem SharePoint PowerShell-Modul - Berechtigungen auf Quell- und Ziel-Web - PowerShell mit Zugriff auf `SharePointServer` Das Skript laedt intern: ```powershell Import-Module SharePointServer ``` ## Dateien im Projekt - `Start-SPMigration.ps1`: Hauptskript fuer Export und optionalen Import - `FieldMapping.sample.csv`: altes CSV-Beispiel fuer Feldmapping, weiterhin als Fallback lesbar ## Exportierte Struktur Beim Export entsteht unter `-OutputPath` folgende Struktur: ```text OutputPath |-- Files | |-- | | |-- Unterordner | | | |-- Dokument.pdf | | | |-- Dokument.pdf.properties.json |-- Lists | |-- ListeA.json |-- MappingTable.json |-- manifest.csv ``` ### Dateien - Die Originaldatei wird in `Files\\...` gespeichert. - Die Metadaten liegen direkt daneben als Sidecar-Datei: `Dateiname.ext.properties.json` - `manifest.csv` enthaelt ausserdem Container-Eintraege fuer Listen und Dokumentbibliotheken ### Listen - Pro Liste wird genau eine JSON-Datei unter `Lists\` erzeugt. - Die Eintraege enthalten insbesondere: - `ContentTypeId` - `FieldValues` - `FieldTextValues` - `Fields` ## Wichtige Metadaten Fuer den Import sind vor allem diese Informationen relevant: - `FieldValues` - `FieldTextValues` - `ContentTypeId` - interne Feldnamen (`InternalName`) Der Name des Inhaltstyps wird bewusst nicht als fuehrende Importinformation verwendet, da er sich im Zielsystem unterscheiden kann. ## MappingTable.json Beim Export wird automatisch eine `MappingTable.json` erzeugt. Diese Datei enthaelt: - `LibraryMappings`: Mapping von Quellbibliothek auf Zielbibliothek - `ListMappings`: Mapping von Quellliste auf Zielliste - `MetadataColumnMappings.SystemColumns`: erkannte Systemspalten - `MetadataColumnMappings.CustomColumns`: erkannte eigene Fachspalten Beispiel: ```json { "SchemaVersion": 1, "GeneratedAtUtc": "2026-04-15T08:00:00.0000000Z", "SourceWebUrl": "http://sharepoint/sites/Quelle", "LibraryMappings": [ { "ObjectType": "DocumentLibrary", "SourceTitle": "Documents", "TargetTitle": "Dokumente", "BaseType": "DocumentLibrary", "BaseTemplate": 101, "RootFolderUrl": "/Documents", "Hidden": false } ], "ListMappings": [ { "ObjectType": "List", "SourceTitle": "TestListe", "TargetTitle": "ZielTestListe", "BaseType": "GenericList", "BaseTemplate": 100, "RootFolderUrl": "/Lists/TestListe", "Hidden": false } ], "MetadataColumnMappings": { "SystemColumns": [ { "ObjectType": "List", "ContainerSourceTitle": "Kalender", "SourceInternalName": "EventDate", "SourceCanonicalInternalName": "EventDate", "SourceSupportingInternalNames": [], "TargetInternalName": "EventDate", "DisplayName": "Beginnt", "TypeAsString": "DateTime", "Hidden": false, "ReadOnly": false, "Sealed": true, "IsSystemColumn": true, "ImportSupported": true } ], "CustomColumns": [ { "ObjectType": "DocumentLibrary", "ContainerSourceTitle": "Documents", "SourceInternalName": "SecurityClearance", "SourceCanonicalInternalName": "SecurityClearance", "SourceSupportingInternalNames": [ "SecurityClearance_0" ], "TargetInternalName": "GMNSecurityClearance", "DisplayName": "Security Clearance", "TypeAsString": "TaxonomyFieldType", "Hidden": false, "ReadOnly": false, "Sealed": false, "IsSystemColumn": false, "ImportSupported": true } ] } } ``` Fuer das Mapping ist vor allem relevant: - `TargetTitle`: Zielname von Liste oder Bibliothek - `TargetInternalName`: Zielfeld fuer die exportierte Metadatenspalte - `SystemColumns`: SharePoint-Standardfelder wie `EventDate`, `EndDate`, `Title` oder `Created` - `CustomColumns`: eigene Fachspalten, die im Ziel oft umbenannt oder anders aufgebaut sind - `SourceSupportingInternalNames`: technische Begleitspalten wie `_0` werden nur noch informativ aufgefuehrt und nicht separat gemappt - `ImportSupported`: steuert, ob eine Spalte beim Import ueberhaupt beruecksichtigt wird - Taxonomy-Felder werden beim Import ueber den exportierten `TermGuid` gesetzt; dabei wird angenommen, dass derselbe Term im Ziel bereits mit identischer GUID existiert Wenn eine Ziel-Liste oder Ziel-Bibliothek nicht existiert, gibt das Skript eine Warnung aus, dass dieser Container manuell angelegt werden soll. ## Parameter ### Pflichtparameter - `SourceUrl`: Quell-Web fuer den Export - `TargetUrl`: Ziel-Web fuer den Import `OutputPath` ist optional. Standard ist `.\SPMigrationOutput` im aktuellen Verzeichnis. ### Exportparameter - `Export`: fuehrt den Export aus - `IncludeHiddenLibraries`: exportiert auch versteckte Bibliotheken - `IncludeHiddenLists`: exportiert auch versteckte Listen ### Importparameter - `Import`: fuehrt den Import aus einem vorhandenen Exportordner aus - `MappingTable`: JSON-Datei mit Listen-, Bibliotheks- und Spalten-Mappings - `ImportFiles`: importiert nur Dateien/Bibliotheken - `ImportLists`: importiert nur Listen - `Overwrite`: ueberschreibt vorhandene Dateien beim Import Hinweis: - Wenn weder `ImportFiles` noch `ImportLists` gesetzt sind, werden beim Import beide Bereiche verarbeitet. - Wird `MappingTable` nicht angegeben, verwendet das Skript standardmaessig `OutputPath\MappingTable.json`. - Die alte CSV-Variante wird fuer reines Feldmapping weiterhin als Fallback gelesen. - Werden keine Schalter gesetzt, leitet das Skript den Modus weiterhin aus `SourceUrl` und `TargetUrl` ab. - Wenn `Overwrite` nicht gesetzt ist und eine Datei bereits existiert, wird bei aktiver Versionierung eine neue Version geschrieben; ohne Versionierung wird die Datei uebersprungen. - Nicht importierbare Systemfelder wie `Attachments`, `Created`, `Modified`, `Author` oder `Editor` werden automatisch aus der MappingTable herausgehalten bzw. beim Import uebersprungen. - Vor dem Speichern prueft das Skript fehlende Pflichtfelder. Wenn ein einzelnes Listen- oder Datei-Metadatenobjekt trotzdem nicht gespeichert werden kann, wird es mit Kontext-Warnung uebersprungen und der Import laeuft weiter. ## Beispiele ### Nur Export ```powershell .\Start-SPMigration.ps1 ` -SourceUrl "http://sharepoint/sites/Quelle" ` -Export ` -IncludeHiddenLists ` -IncludeHiddenLibraries ``` ### Nur Import ```powershell .\Start-SPMigration.ps1 ` -TargetUrl "http://sharepoint/sites/Ziel" ` -Import ` -MappingTable "C:\Temp\SP-Export\MappingTable.json" ``` ### Export, MappingTable anpassen, dann Import ```powershell .\Start-SPMigration.ps1 ` -SourceUrl "http://sharepoint/sites/Quelle" ` -OutputPath "C:\Temp\SP-Export" ` -Export ``` Danach `MappingTable.json` bearbeiten und dort `TargetTitle` sowie `TargetInternalName` anpassen. Anschliessend: ```powershell .\Start-SPMigration.ps1 ` -OutputPath "C:\Temp\SP-Export" ` -TargetUrl "http://sharepoint/sites/Ziel" ` -Import ` -MappingTable "C:\Temp\SP-Export\MappingTable.json" ``` ### Nur Dateien importrelevant ausfuehren ```powershell .\Start-SPMigration.ps1 ` -TargetUrl "http://sharepoint/sites/Ziel" ` -Import ` -MappingTable "C:\Temp\SP-Export\MappingTable.json" ` -ImportFiles ` -Overwrite ``` ### Nur Listen importrelevant ausfuehren ```powershell .\Start-SPMigration.ps1 ` -TargetUrl "http://sharepoint/sites/Ziel" ` -Import ` -MappingTable "C:\Temp\SP-Export\MappingTable.json" ` -ImportLists ``` ## Aktuelles Verhalten beim Import ### Dokumentbibliotheken - Dateien werden in die per `MappingTable.json` aufgeloeste Zielbibliothek importiert. - Unterordner werden bei Bedarf angelegt. - Metadaten werden anschliessend ueber die `MetadataColumnMappings` gesetzt. ### Listen - Listeneintraege werden neu angelegt. - Feldwerte werden ueber `FieldValues`, `FieldTextValues` und `MetadataColumnMappings` gemappt. ## Bekannte Einschraenkungen - Die Zielaufloesung kann ueber `MappingTable.json` mit `TargetTitle` ueberschrieben werden. - Listenanhaenge werden derzeit noch nicht physisch mit importiert. - Ordner in normalen Listen werden beim Import derzeit uebersprungen. - Fehlende Ziellisten oder Zielbibliotheken werden derzeit nicht automatisch angelegt; das Skript gibt stattdessen eine Warnung zur manuellen Anlage aus. - Sehr spezielle Feldtypen koennen je nach Farm-Konfiguration zusaetzliche Anpassungen benoetigen. - Das Skript ist fuer SharePoint On-Premise mit serverseitigem Objektmodell gedacht, nicht fuer SharePoint Online. ## Empfehlung Zuerst immer mit `-Export` testen und die exportierten `*.properties.json`, Listen-JSONs und die `MappingTable.json` pruefen. Danach die Zielnamen und Feldmappings vervollstaendigen und erst dann den Import gegen das Zielsystem laufen lassen.