From 25428ccce23b28fe20c292fc3b4d1260fcfb892c Mon Sep 17 00:00:00 2001 From: Torsten Date: Wed, 15 Apr 2026 15:13:49 +0200 Subject: [PATCH] adding List / Library Mapping via Manifest File --- README.md | 57 ++++++++- Start-SPMigration.ps1 | 290 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 307 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index a4272e7..42e1d0a 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Das Skript kann: - normale SharePoint-Listen und deren Eintraege exportieren - exportierte Inhalte wieder in ein Ziel-Web importieren - Feldwerte ueber eine Mapping-CSV von Quell- auf Ziel-InternalNames abbilden +- Listen- und Bibliotheksnamen ueber `manifest.csv` auf Zielnamen abbilden ## Voraussetzungen @@ -49,6 +50,7 @@ OutputPath - 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 @@ -86,6 +88,33 @@ Bedeutung: - `SourceInternalName`: interner Feldname aus dem Export - `TargetInternalName`: interner Feldname im Zielsystem +## manifest.csv fuer Listen- und Bibliotheksmapping + +Beim Export wird fuer jede Liste und jede Dokumentbibliothek eine Container-Zeile in `manifest.csv` geschrieben. + +Wichtige Spalten: + +- `RecordType` +- `ObjectType` +- `SourceTitle` +- `TargetTitle` +- `BaseTemplate` + +Fuer das Mapping ist insbesondere `TargetTitle` gedacht: + +- leer: das Skript sucht im Ziel mit dem Quellnamen +- gesetzt: das Skript sucht im Ziel mit dem Wert aus `TargetTitle` + +Beispiel: + +```csv +RecordType;ObjectType;SourceWebUrl;SourceTitle;TargetTitle;BaseType;BaseTemplate;RootFolderUrl;SourceServerRelativeUrl;FileName;FileUniqueId;FileLength;LocalFilePath;LocalMetadataPath;ExportedAtUtc +Container;DocumentLibrary;http://clshp001/;Documents;Dokumente;DocumentLibrary;101;/Documents;/Documents;;;;;; +Container;List;http://clshp001/;TestListe;ZielTestListe;GenericList;100;/Lists/TestListe;/Lists/TestListe;;;;;; +``` + +Wenn eine Ziel-Liste oder Ziel-Bibliothek nicht existiert, gibt das Skript eine Warnung aus, dass dieser Container manuell angelegt werden soll. + ## Parameter ### Pflichtparameter @@ -98,6 +127,7 @@ Bedeutung: - `IncludeHiddenLibraries`: exportiert auch versteckte Bibliotheken - `IncludeHiddenLists`: exportiert auch versteckte Listen - `ExportOnly`: fuehrt nur den Export aus +- `ImportOnly`: fuehrt nur den Import aus einem vorhandenen Exportordner aus ### Importparameter @@ -111,6 +141,7 @@ Hinweis: - Wenn weder `ImportFiles` noch `ImportLists` gesetzt sind, werden beim Import beide Bereiche verarbeitet. - Wenn `ExportOnly` gesetzt ist, wird kein Import gestartet. +- Wenn `ImportOnly` gesetzt ist, wird kein neuer Export gestartet. ## Beispiele @@ -133,6 +164,27 @@ Hinweis: -MappingCsvPath ".\FieldMapping.sample.csv" ``` +### Export, manifest.csv anpassen, dann nur Import + +```powershell +.\Start-SPMigration.ps1 ` + -WebUrl "http://sharepoint/sites/Quelle" ` + -OutputPath "C:\Temp\SP-Export" ` + -ExportOnly +``` + +Danach `manifest.csv` bearbeiten und `TargetTitle` fuer Listen oder Bibliotheken setzen. + +Anschliessend: + +```powershell +.\Start-SPMigration.ps1 ` + -OutputPath "C:\Temp\SP-Export" ` + -TargetWebUrl "http://sharepoint/sites/Ziel" ` + -MappingCsvPath ".\FieldMapping.sample.csv" ` + -ImportOnly +``` + ### Nur Dateien importrelevant ausfuehren ```powershell @@ -160,7 +212,7 @@ Hinweis: ### Dokumentbibliotheken -- Dateien werden in die gleichnamige Zielbibliothek importiert. +- Dateien werden in die per `manifest.csv` aufgeloeste Zielbibliothek importiert. - Unterordner werden bei Bedarf angelegt. - Metadaten werden anschliessend ueber das CSV-Mapping gesetzt. @@ -171,9 +223,10 @@ Hinweis: ## Bekannte Einschraenkungen -- Zielbibliotheken und Ziellisten werden aktuell ueber den Titel aufgeloest. +- Die Zielaufloesung kann ueber `manifest.csv` 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. diff --git a/Start-SPMigration.ps1 b/Start-SPMigration.ps1 index 182ac2e..a0fa95c 100644 --- a/Start-SPMigration.ps1 +++ b/Start-SPMigration.ps1 @@ -1,6 +1,5 @@ [CmdletBinding()] param( - [Parameter(Mandatory = $true)] [string]$WebUrl, [Parameter(Mandatory = $true)] @@ -20,7 +19,9 @@ param( [switch]$OverwriteFiles, - [switch]$ExportOnly + [switch]$ExportOnly, + + [switch]$ImportOnly ) Set-StrictMode -Version Latest @@ -62,7 +63,9 @@ function Invoke-MigrationImport { $resolvedInputPath = [System.IO.Path]::GetFullPath($InputPath) $filesRootPath = [System.IO.Path]::Combine($resolvedInputPath, "Files") $listsRootPath = [System.IO.Path]::Combine($resolvedInputPath, "Lists") + $manifestPath = [System.IO.Path]::Combine($resolvedInputPath, "manifest.csv") $fieldMapping = Get-FieldMapping -Path $MappingCsvPath + $containerManifestMap = Get-ContainerManifestMap -ManifestRows (Read-ManifestRows -ManifestPath $manifestPath) if ($fieldMapping.Count -eq 0) { throw "Die Mapping-CSV enthaelt keine gueltigen Zuordnungen." @@ -82,11 +85,11 @@ function Invoke-MigrationImport { $targetWeb = Get-SPWeb -Identity $TargetWebUrl -ErrorAction Stop if ($shouldImportFiles) { - Import-SPDocumentLibraries -Web $targetWeb -FilesRootPath $filesRootPath -FieldMapping $fieldMapping -OverwriteFiles:$OverwriteFiles + Import-SPDocumentLibraries -Web $targetWeb -FilesRootPath $filesRootPath -FieldMapping $fieldMapping -ContainerManifestMap $containerManifestMap -OverwriteFiles:$OverwriteFiles } if ($shouldImportLists) { - Import-SPLists -Web $targetWeb -ListsRootPath $listsRootPath -FieldMapping $fieldMapping + Import-SPLists -Web $targetWeb -ListsRootPath $listsRootPath -FieldMapping $fieldMapping -ContainerManifestMap $containerManifestMap } Write-Host ("Import abgeschlossen. Quelle: {0}" -f $resolvedInputPath) @@ -515,6 +518,73 @@ function Write-ManifestRow { $Row | Export-Csv -Path $ManifestPath -NoTypeInformation -Delimiter ";" -Encoding UTF8 -Append:$append } +function New-ManifestRow { + param( + [string]$RecordType = "", + [string]$ObjectType = "", + [string]$SourceWebUrl = "", + [string]$SourceTitle = "", + [string]$TargetTitle = "", + [string]$BaseType = "", + [string]$BaseTemplate = "", + [string]$RootFolderUrl = "", + [string]$SourceServerRelativeUrl = "", + [string]$FileName = "", + [string]$FileUniqueId = "", + [string]$FileLength = "", + [string]$LocalFilePath = "", + [string]$LocalMetadataPath = "", + [string]$ExportedAtUtc = "" + ) + + return [PSCustomObject]@{ + RecordType = $RecordType + ObjectType = $ObjectType + SourceWebUrl = $SourceWebUrl + SourceTitle = $SourceTitle + TargetTitle = $TargetTitle + BaseType = $BaseType + BaseTemplate = $BaseTemplate + RootFolderUrl = $RootFolderUrl + SourceServerRelativeUrl = $SourceServerRelativeUrl + FileName = $FileName + FileUniqueId = $FileUniqueId + FileLength = $FileLength + LocalFilePath = $LocalFilePath + LocalMetadataPath = $LocalMetadataPath + ExportedAtUtc = $ExportedAtUtc + } +} + +function Write-ContainerManifestRow { + param( + [Parameter(Mandatory = $true)] + [Microsoft.SharePoint.SPWeb]$Web, + + [Parameter(Mandatory = $true)] + [Microsoft.SharePoint.SPList]$List, + + [Parameter(Mandatory = $true)] + [string]$ManifestPath + ) + + $objectType = if ($List.BaseType -eq [Microsoft.SharePoint.SPBaseType]::DocumentLibrary) { "DocumentLibrary" } else { "List" } + + $manifestRow = New-ManifestRow ` + -RecordType "Container" ` + -ObjectType $objectType ` + -SourceWebUrl $Web.Url ` + -SourceTitle $List.Title ` + -TargetTitle "" ` + -BaseType $List.BaseType.ToString() ` + -BaseTemplate ([string][int]$List.BaseTemplate) ` + -RootFolderUrl $List.RootFolder.ServerRelativeUrl ` + -SourceServerRelativeUrl $List.RootFolder.ServerRelativeUrl ` + -ExportedAtUtc ([System.DateTime]::UtcNow.ToString("o")) + + Write-ManifestRow -Row $manifestRow -ManifestPath $ManifestPath +} + function Get-RelativeFilePathSegments { param( [Parameter(Mandatory = $true)] @@ -590,17 +660,22 @@ function Export-SPFile { $metadata = Get-FileMetadataObject -Web $Web -List $List -File $File Write-MetadataJson -MetadataObject $metadata -Path $metadataPath - $manifestRow = [PSCustomObject]@{ - WebUrl = $Web.Url - LibraryTitle = $List.Title - FileName = $File.Name - FileServerRelativeUrl = $File.ServerRelativeUrl - FileUniqueId = $File.UniqueId.ToString() - FileLength = $File.Length - LocalFilePath = $localFilePath - LocalMetadataPath = $metadataPath - ExportedAtUtc = [System.DateTime]::UtcNow.ToString("o") - } + $manifestRow = New-ManifestRow ` + -RecordType "File" ` + -ObjectType "DocumentLibrary" ` + -SourceWebUrl $Web.Url ` + -SourceTitle $List.Title ` + -TargetTitle "" ` + -BaseType $List.BaseType.ToString() ` + -BaseTemplate ([string][int]$List.BaseTemplate) ` + -RootFolderUrl $List.RootFolder.ServerRelativeUrl ` + -SourceServerRelativeUrl $File.ServerRelativeUrl ` + -FileName $File.Name ` + -FileUniqueId $File.UniqueId.ToString() ` + -FileLength ([string]$File.Length) ` + -LocalFilePath $localFilePath ` + -LocalMetadataPath $metadataPath ` + -ExportedAtUtc ([System.DateTime]::UtcNow.ToString("o")) Write-ManifestRow -Row $manifestRow -ManifestPath $ManifestPath } @@ -655,6 +730,7 @@ function Export-SPDocumentLibrary { ) Write-Host ("Exportiere Bibliothek: {0}" -f $List.Title) + Write-ContainerManifestRow -Web $Web -List $List -ManifestPath $ManifestPath $fileCount = 0 Export-SPFolder -Web $Web -List $List -Folder $List.RootFolder -FilesRootPath $FilesRootPath -ManifestPath $ManifestPath -FileCount ([ref]$fileCount) @@ -671,10 +747,14 @@ function Export-SPList { [Microsoft.SharePoint.SPList]$List, [Parameter(Mandatory = $true)] - [string]$ListsRootPath + [string]$ListsRootPath, + + [Parameter(Mandatory = $true)] + [string]$ManifestPath ) Write-Host ("Exportiere Liste: {0}" -f $List.Title) + Write-ContainerManifestRow -Web $Web -List $List -ManifestPath $ManifestPath $safeListName = Get-SafePathSegment $List.Title $listPath = [System.IO.Path]::Combine($ListsRootPath, "$safeListName.json") @@ -732,6 +812,105 @@ function Get-ObjectPropertyValue { return $property.Value } +function Read-ManifestRows { + param( + [Parameter(Mandatory = $true)] + [string]$ManifestPath + ) + + if (-not [System.IO.File]::Exists($ManifestPath)) { + return @() + } + + return @(Import-Csv -Path $ManifestPath -Delimiter ";") +} + +function Get-ContainerManifestEntryKey { + param( + [Parameter(Mandatory = $true)] + [string]$ObjectType, + + [Parameter(Mandatory = $true)] + [string]$SourceTitle + ) + + return ("{0}|{1}" -f $ObjectType.Trim(), $SourceTitle.Trim()).ToLowerInvariant() +} + +function Get-ContainerManifestMap { + param( + [Parameter(Mandatory = $true)] + [object[]]$ManifestRows + ) + + $containerMap = @{} + + foreach ($row in $ManifestRows) { + $recordType = [string](Get-ObjectPropertyValue -Object $row -PropertyName "RecordType") + $sourceTitle = [string](Get-ObjectPropertyValue -Object $row -PropertyName "SourceTitle") + $objectType = [string](Get-ObjectPropertyValue -Object $row -PropertyName "ObjectType") + + if ($recordType -ne "Container" -or [string]::IsNullOrWhiteSpace($sourceTitle) -or [string]::IsNullOrWhiteSpace($objectType)) { + continue + } + + $key = Get-ContainerManifestEntryKey -ObjectType $objectType -SourceTitle $sourceTitle + $containerMap[$key] = $row + } + + return $containerMap +} + +function Get-TargetContainerTitle { + param( + [Parameter(Mandatory = $true)] + [hashtable]$ContainerManifestMap, + + [Parameter(Mandatory = $true)] + [string]$ObjectType, + + [Parameter(Mandatory = $true)] + [string]$SourceTitle + ) + + $key = Get-ContainerManifestEntryKey -ObjectType $ObjectType -SourceTitle $SourceTitle + $manifestEntry = $ContainerManifestMap[$key] + + if ($null -eq $manifestEntry) { + return $SourceTitle + } + + $targetTitle = [string](Get-ObjectPropertyValue -Object $manifestEntry -PropertyName "TargetTitle") + if ([string]::IsNullOrWhiteSpace($targetTitle)) { + return $SourceTitle + } + + return $targetTitle.Trim() +} + +function Test-ContainerHasExplicitTargetMapping { + param( + [Parameter(Mandatory = $true)] + [hashtable]$ContainerManifestMap, + + [Parameter(Mandatory = $true)] + [string]$ObjectType, + + [Parameter(Mandatory = $true)] + [string]$SourceTitle + ) + + $key = Get-ContainerManifestEntryKey -ObjectType $ObjectType -SourceTitle $SourceTitle + $manifestEntry = $ContainerManifestMap[$key] + + if ($null -eq $manifestEntry) { + return $false + } + + $targetTitle = [string](Get-ObjectPropertyValue -Object $manifestEntry -PropertyName "TargetTitle") + return -not [string]::IsNullOrWhiteSpace($targetTitle) +} + function Test-ObjectHasProperty { param( $Object, @@ -1211,6 +1390,9 @@ function Import-SPDocumentLibraries { [Parameter(Mandatory = $true)] [System.Collections.IDictionary]$FieldMapping, + [Parameter(Mandatory = $true)] + [hashtable]$ContainerManifestMap, + [switch]$OverwriteFiles ) @@ -1232,21 +1414,27 @@ function Import-SPDocumentLibraries { $metadata = Read-JsonFile -Path $metadataFile.FullName $libraryMetadata = Get-ObjectPropertyValue -Object $metadata -PropertyName "Library" $itemMetadata = Get-ObjectPropertyValue -Object $metadata -PropertyName "Item" - $libraryTitle = [string](Get-ObjectPropertyValue -Object $libraryMetadata -PropertyName "Title") + $sourceLibraryTitle = [string](Get-ObjectPropertyValue -Object $libraryMetadata -PropertyName "Title") - if ([string]::IsNullOrWhiteSpace($libraryTitle)) { + if ([string]::IsNullOrWhiteSpace($sourceLibraryTitle)) { Write-Warning ("Bibliothekstitel fehlt in: {0}" -f $metadataFile.FullName) continue } - $targetLibrary = $Web.Lists.TryGetList($libraryTitle) + $targetLibraryTitle = Get-TargetContainerTitle -ContainerManifestMap $ContainerManifestMap -ObjectType "DocumentLibrary" -SourceTitle $sourceLibraryTitle + $targetLibrary = $Web.Lists.TryGetList($targetLibraryTitle) if ($null -eq $targetLibrary) { - Write-Warning ("Zielbibliothek nicht gefunden: {0}" -f $libraryTitle) + if (Test-ContainerHasExplicitTargetMapping -ContainerManifestMap $ContainerManifestMap -ObjectType "DocumentLibrary" -SourceTitle $sourceLibraryTitle) { + Write-Warning ("Zielbibliothek '{0}' fuer Quellbibliothek '{1}' nicht gefunden. Bitte diese Bibliothek im Ziel manuell anlegen." -f $targetLibraryTitle, $sourceLibraryTitle) + } + else { + Write-Warning ("Zielbibliothek '{0}' nicht gefunden und kein TargetTitle im manifest.csv gepflegt. Bitte Bibliothek manuell anlegen oder TargetTitle im Manifest setzen." -f $sourceLibraryTitle) + } continue } if ($targetLibrary.BaseType -ne [Microsoft.SharePoint.SPBaseType]::DocumentLibrary) { - Write-Warning ("Zielliste ist keine Dokumentbibliothek: {0}" -f $libraryTitle) + Write-Warning ("Zielliste ist keine Dokumentbibliothek: {0}" -f $targetLibraryTitle) continue } @@ -1286,7 +1474,10 @@ function Import-SPLists { [string]$ListsRootPath, [Parameter(Mandatory = $true)] - [System.Collections.IDictionary]$FieldMapping + [System.Collections.IDictionary]$FieldMapping, + + [Parameter(Mandatory = $true)] + [hashtable]$ContainerManifestMap ) if (-not [System.IO.Directory]::Exists($ListsRootPath)) { @@ -1301,35 +1492,41 @@ function Import-SPLists { $listExport = Read-JsonFile -Path $listFile.FullName $listMetadata = Get-ObjectPropertyValue -Object $listExport -PropertyName "List" $items = @(Get-ObjectPropertyValue -Object $listExport -PropertyName "Items" -DefaultValue @()) - $listTitle = [string](Get-ObjectPropertyValue -Object $listMetadata -PropertyName "Title") + $sourceListTitle = [string](Get-ObjectPropertyValue -Object $listMetadata -PropertyName "Title") - if ([string]::IsNullOrWhiteSpace($listTitle)) { + if ([string]::IsNullOrWhiteSpace($sourceListTitle)) { Write-Warning ("Listentitel fehlt in: {0}" -f $listFile.FullName) continue } - $targetList = $Web.Lists.TryGetList($listTitle) + $targetListTitle = Get-TargetContainerTitle -ContainerManifestMap $ContainerManifestMap -ObjectType "List" -SourceTitle $sourceListTitle + $targetList = $Web.Lists.TryGetList($targetListTitle) if ($null -eq $targetList) { - Write-Warning ("Zielliste nicht gefunden: {0}" -f $listTitle) + if (Test-ContainerHasExplicitTargetMapping -ContainerManifestMap $ContainerManifestMap -ObjectType "List" -SourceTitle $sourceListTitle) { + Write-Warning ("Zielliste '{0}' fuer Quellliste '{1}' nicht gefunden. Bitte diese Liste im Ziel manuell anlegen." -f $targetListTitle, $sourceListTitle) + } + else { + Write-Warning ("Zielliste '{0}' nicht gefunden und kein TargetTitle im manifest.csv gepflegt. Bitte Liste manuell anlegen oder TargetTitle im Manifest setzen." -f $sourceListTitle) + } continue } if ($targetList.BaseType -eq [Microsoft.SharePoint.SPBaseType]::DocumentLibrary) { - Write-Warning ("Liste ist eine Dokumentbibliothek und wird im Listenimport uebersprungen: {0}" -f $listTitle) + Write-Warning ("Liste ist eine Dokumentbibliothek und wird im Listenimport uebersprungen: {0}" -f $targetListTitle) continue } - Write-Host ("Importiere Liste: {0}" -f $listTitle) + Write-Host ("Importiere Liste: {0}" -f $targetListTitle) foreach ($sourceItem in $items) { $fileSystemObjectType = [string](Get-ObjectPropertyValue -Object $sourceItem -PropertyName "FileSystemObjectType") if ($fileSystemObjectType -eq "Folder") { - Write-Warning ("Ordner in normalen Listen werden in dieser Version uebersprungen: {0}" -f $listTitle) + Write-Warning ("Ordner in normalen Listen werden in dieser Version uebersprungen: {0}" -f $targetListTitle) continue } if ((Get-ObjectPropertyValue -Object $sourceItem -PropertyName "HasAttachments" -DefaultValue $false)) { - Write-Warning ("Listenanlagen wurden im Export nicht physisch gesichert und werden uebersprungen. Liste: {0}, ItemId: {1}" -f $listTitle, (Get-ObjectPropertyValue -Object $sourceItem -PropertyName "Id")) + Write-Warning ("Listenanlagen wurden im Export nicht physisch gesichert und werden uebersprungen. Liste: {0}, ItemId: {1}" -f $targetListTitle, (Get-ObjectPropertyValue -Object $sourceItem -PropertyName "Id")) } $targetItem = $targetList.Items.Add() @@ -1346,6 +1543,30 @@ $filesRootPath = [System.IO.Path]::Combine($resolvedOutputPath, "Files") $listsRootPath = [System.IO.Path]::Combine($resolvedOutputPath, "Lists") $manifestPath = [System.IO.Path]::Combine($resolvedOutputPath, "manifest.csv") +$importConfigurationProvided = + (-not [string]::IsNullOrWhiteSpace($TargetWebUrl)) -or + (-not [string]::IsNullOrWhiteSpace($MappingCsvPath)) -or + $ImportFiles -or + $ImportLists -or + $OverwriteFiles + +if ($ExportOnly -and $ImportOnly) { + throw "ExportOnly und ImportOnly koennen nicht gleichzeitig gesetzt werden." +} + +if ($ImportOnly) { + if ([string]::IsNullOrWhiteSpace($TargetWebUrl) -or [string]::IsNullOrWhiteSpace($MappingCsvPath)) { + throw "Fuer ImportOnly muessen TargetWebUrl und MappingCsvPath angegeben werden." + } + + Invoke-MigrationImport -InputPath $resolvedOutputPath -TargetWebUrl $TargetWebUrl -MappingCsvPath $MappingCsvPath -ImportFiles:$ImportFiles -ImportLists:$ImportLists -OverwriteFiles:$OverwriteFiles + return +} + +if ([string]::IsNullOrWhiteSpace($WebUrl)) { + throw "Fuer den Export muss WebUrl angegeben werden." +} + Ensure-Directory -Path $resolvedOutputPath Ensure-Directory -Path $filesRootPath Ensure-Directory -Path $listsRootPath @@ -1383,7 +1604,7 @@ try { } foreach ($list in $lists) { - Export-SPList -Web $web -List $list -ListsRootPath $listsRootPath + Export-SPList -Web $web -List $list -ListsRootPath $listsRootPath -ManifestPath $manifestPath } if ($documentLibraries.Length -eq 0 -and $lists.Length -eq 0) { @@ -1393,13 +1614,6 @@ try { Write-Host ("Export abgeschlossen. Ausgabe: {0}" -f $resolvedOutputPath) - $importConfigurationProvided = - (-not [string]::IsNullOrWhiteSpace($TargetWebUrl)) -or - (-not [string]::IsNullOrWhiteSpace($MappingCsvPath)) -or - $ImportFiles -or - $ImportLists -or - $OverwriteFiles - if ($ExportOnly) { Write-Host "ExportOnly ist gesetzt. Import wird uebersprungen." return