Erweitere README mit Informationen zu WssId und Taxonomie-Feldverarbeitung; füge Kontextmenü zum Löschen von Mapping-Zeilen in der GUI hinzu
This commit is contained in:
@@ -255,6 +255,28 @@ function Convert-SPFieldValue {
|
||||
return $Value.ToString("o")
|
||||
}
|
||||
|
||||
# Taxonomy values must be handled before the generic lookup/enumerable
|
||||
# branches. Their WssId is only local to the source site collection; the
|
||||
# portable part of the value is the label plus TermGuid.
|
||||
$typeName = $Value.GetType().FullName
|
||||
if ($typeName -like "*TaxonomyFieldValueCollection") {
|
||||
return @($Value | ForEach-Object {
|
||||
@{
|
||||
Label = $_.Label
|
||||
TermGuid = $_.TermGuid
|
||||
WssId = $_.WssId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if ($typeName -like "*TaxonomyFieldValue") {
|
||||
return @{
|
||||
Label = $Value.Label
|
||||
TermGuid = $Value.TermGuid
|
||||
WssId = $Value.WssId
|
||||
}
|
||||
}
|
||||
|
||||
if ($Value -is [Microsoft.SharePoint.SPFieldUserValue]) {
|
||||
return @{
|
||||
LookupId = $Value.LookupId
|
||||
@@ -294,25 +316,6 @@ function Convert-SPFieldValue {
|
||||
return @($Value | ForEach-Object { Convert-SPFieldValue $_ })
|
||||
}
|
||||
|
||||
$typeName = $Value.GetType().FullName
|
||||
if ($typeName -like "*TaxonomyFieldValue") {
|
||||
return @{
|
||||
Label = $Value.Label
|
||||
TermGuid = $Value.TermGuid
|
||||
WssId = $Value.WssId
|
||||
}
|
||||
}
|
||||
|
||||
if ($typeName -like "*TaxonomyFieldValueCollection") {
|
||||
return @($Value | ForEach-Object {
|
||||
@{
|
||||
Label = $_.Label
|
||||
TermGuid = $_.TermGuid
|
||||
WssId = $_.WssId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return $Value
|
||||
}
|
||||
|
||||
@@ -486,6 +489,7 @@ function Get-ListItemMetadataObject {
|
||||
UniqueId = $Item.UniqueId.ToString()
|
||||
Title = if ($Item.Fields.ContainsField("Title")) { $Item["Title"] } else { $null }
|
||||
ContentTypeId = $Item.ContentTypeId.ToString()
|
||||
ContentTypeName = if ($null -ne $Item.ContentType) { $Item.ContentType.Name } else { "" }
|
||||
FileSystemObjectType = $Item.FileSystemObjectType.ToString()
|
||||
DisplayName = $Item.DisplayName
|
||||
Name = if ($Item.Name) { $Item.Name } else { $null }
|
||||
@@ -976,6 +980,8 @@ function Test-SPFieldSupportedForImport {
|
||||
"SMTotalSize",
|
||||
"SortBehavior",
|
||||
"SyncClientId",
|
||||
"TaxCatchAll",
|
||||
"TaxCatchAllLabel",
|
||||
"TimeZone",
|
||||
"UID",
|
||||
"UniqueId",
|
||||
@@ -1530,6 +1536,8 @@ function Test-MetadataColumnMappingRowImportSupported {
|
||||
"SMTotalSize",
|
||||
"SortBehavior",
|
||||
"SyncClientId",
|
||||
"TaxCatchAll",
|
||||
"TaxCatchAllLabel",
|
||||
"TimeZone",
|
||||
"UID",
|
||||
"UniqueId",
|
||||
@@ -1737,6 +1745,86 @@ function Resolve-SPField {
|
||||
return $null
|
||||
}
|
||||
|
||||
function Resolve-SPAvailableContentTypeForImport {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPWeb]$Web,
|
||||
|
||||
[string]$SourceContentTypeId,
|
||||
|
||||
[string]$SourceContentTypeName
|
||||
)
|
||||
|
||||
$sourceId = $null
|
||||
if (-not [string]::IsNullOrWhiteSpace($SourceContentTypeId)) {
|
||||
try {
|
||||
$sourceId = New-Object Microsoft.SharePoint.SPContentTypeId($SourceContentTypeId)
|
||||
}
|
||||
catch {
|
||||
throw ("Ungueltige Source-ContentTypeId: {0}" -f $SourceContentTypeId)
|
||||
}
|
||||
}
|
||||
|
||||
$idMatches = @()
|
||||
if ($null -ne $sourceId) {
|
||||
foreach ($contentType in @($Web.AvailableContentTypes)) {
|
||||
if ($contentType.Id.Equals($sourceId) -or $contentType.Id.IsParentOf($sourceId)) {
|
||||
$idMatches += $contentType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($idMatches.Count -gt 0) {
|
||||
return @($idMatches | Sort-Object { $_.Id.ToString().Length } -Descending)[0]
|
||||
}
|
||||
|
||||
if (-not [string]::IsNullOrWhiteSpace($SourceContentTypeName)) {
|
||||
foreach ($contentType in @($Web.AvailableContentTypes)) {
|
||||
if ([string]$contentType.Name -eq $SourceContentTypeName) {
|
||||
return $contentType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Ensure-SPListContentTypeForImport {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPList]$List,
|
||||
|
||||
[string]$SourceContentTypeId,
|
||||
|
||||
[string]$SourceContentTypeName
|
||||
)
|
||||
|
||||
$siteContentType = Resolve-SPAvailableContentTypeForImport -Web $List.ParentWeb -SourceContentTypeId $SourceContentTypeId -SourceContentTypeName $SourceContentTypeName
|
||||
if ($null -eq $siteContentType) {
|
||||
throw ("Kein passender publizierter Site-Content-Type gefunden. SourceContentTypeId='{0}', SourceContentTypeName='{1}'" -f $SourceContentTypeId, $SourceContentTypeName)
|
||||
}
|
||||
|
||||
foreach ($listContentType in @($List.ContentTypes)) {
|
||||
if ($listContentType.Id.Equals($siteContentType.Id) -or $siteContentType.Id.IsParentOf($listContentType.Id)) {
|
||||
return $listContentType
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $List.ContentTypesEnabled) {
|
||||
$List.ContentTypesEnabled = $true
|
||||
$List.Update()
|
||||
}
|
||||
|
||||
if (-not $List.IsContentTypeAllowed($siteContentType)) {
|
||||
throw ("Content-Type '{0}' ({1}) ist fuer die Zielliste '{2}' nicht zulaessig." -f $siteContentType.Name, $siteContentType.Id, $List.Title)
|
||||
}
|
||||
|
||||
$listContentType = $List.ContentTypes.Add($siteContentType)
|
||||
$List.Update()
|
||||
Write-Host ("Content-Type zur Zielliste hinzugefuegt: Liste='{0}'; ContentType='{1}'; SiteContentTypeId='{2}'; ListContentTypeId='{3}'" -f $List.Title, $siteContentType.Name, $siteContentType.Id, $listContentType.Id)
|
||||
return $listContentType
|
||||
}
|
||||
|
||||
function Get-FieldMapping {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
@@ -1989,7 +2077,7 @@ function Convert-ToTaxonomyTermEntries {
|
||||
$label = $matches[1]
|
||||
$termGuid = $matches[2]
|
||||
}
|
||||
elseif ([guid]::TryParse($rawTermString, [ref]([guid]::Empty))) {
|
||||
elseif ($rawTermString -match "^[0-9a-fA-F-]{36}$") {
|
||||
$termGuid = $rawTermString
|
||||
}
|
||||
}
|
||||
@@ -1998,10 +2086,13 @@ function Convert-ToTaxonomyTermEntries {
|
||||
$label = $TextValue
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($termGuid)) {
|
||||
$parsedTermGuid = [Guid]::Empty
|
||||
if ([string]::IsNullOrWhiteSpace($termGuid) -or -not [Guid]::TryParse($termGuid, [ref]$parsedTermGuid)) {
|
||||
continue
|
||||
}
|
||||
|
||||
$termGuid = $parsedTermGuid.ToString()
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($label)) {
|
||||
$label = $termGuid
|
||||
}
|
||||
@@ -2070,6 +2161,10 @@ function New-TaxonomyFieldValueObject {
|
||||
|
||||
try {
|
||||
$taxonomyValue.PopulateFromLabelGuidPair($labelGuidPair)
|
||||
# WssIds belong to the site collection and must never be carried over
|
||||
# from the source TaxonomyHiddenList. -1 lets SharePoint resolve (and,
|
||||
# when necessary, create) the target-site entry from the TermGuid.
|
||||
$taxonomyValue.WssId = -1
|
||||
$isPopulated = $true
|
||||
}
|
||||
catch {
|
||||
@@ -2110,6 +2205,10 @@ function Set-SPTaxonomyFieldValue {
|
||||
$termEntries = @(Convert-ToTaxonomyTermEntries -RawValue $RawValue -TextValue $TextValue)
|
||||
|
||||
if ($termEntries.Count -eq 0) {
|
||||
if ((Test-SPValuePresent -Value $RawValue) -or -not [string]::IsNullOrWhiteSpace($TextValue)) {
|
||||
throw ("Taxonomy-Wert fuer Feld '{0}' enthaelt keine gueltige TermGuid. Der Wert kann nicht in die Ziel-SiteCollection aufgeloest werden." -f $Field.InternalName)
|
||||
}
|
||||
|
||||
$Item[$Field.InternalName] = $null
|
||||
return
|
||||
}
|
||||
@@ -2220,51 +2319,57 @@ function Set-SPItemFieldValue {
|
||||
|
||||
$field = Resolve-SPField -Fields $Item.Fields -InternalName $TargetInternalName
|
||||
if ($null -eq $field) {
|
||||
Write-SkippedImportFieldWarning -FieldInternalName $TargetInternalName -Message ("Zielfeld nicht gefunden: {0}" -f $TargetInternalName)
|
||||
return
|
||||
throw ("Zielfeld nicht gefunden: {0}" -f $TargetInternalName)
|
||||
}
|
||||
|
||||
if (-not (Test-SPFieldSupportedForImport -Field $field)) {
|
||||
Write-SkippedImportFieldWarning -FieldInternalName $TargetInternalName -Message ("Zielfeld wird nicht importiert und wird uebersprungen: {0}" -f $TargetInternalName)
|
||||
return
|
||||
throw ("Zielfeld wird nicht importiert und wird uebersprungen: {0}" -f $TargetInternalName)
|
||||
}
|
||||
|
||||
try {
|
||||
switch ($field.TypeAsString) {
|
||||
"Boolean" {
|
||||
$Item[$field.InternalName] = Convert-ToBoolean -RawValue $RawValue -TextValue $TextValue
|
||||
return
|
||||
return $true
|
||||
}
|
||||
"Integer" {
|
||||
$Item[$field.InternalName] = Convert-ToInt32 -RawValue $RawValue -TextValue $TextValue
|
||||
return
|
||||
return $true
|
||||
}
|
||||
"Counter" {
|
||||
return
|
||||
throw ("Counter-Feld kann nicht gesetzt werden: {0}" -f $TargetInternalName)
|
||||
}
|
||||
"Number" {
|
||||
$Item[$field.InternalName] = Convert-ToDouble -RawValue $RawValue -TextValue $TextValue
|
||||
return
|
||||
return $true
|
||||
}
|
||||
"Currency" {
|
||||
$Item[$field.InternalName] = Convert-ToDouble -RawValue $RawValue -TextValue $TextValue
|
||||
return
|
||||
return $true
|
||||
}
|
||||
"DateTime" {
|
||||
$Item[$field.InternalName] = Convert-ToDateTimeValue -RawValue $RawValue -TextValue $TextValue
|
||||
return
|
||||
return $true
|
||||
}
|
||||
"URL" {
|
||||
$Item[$field.InternalName] = Convert-ToUrlFieldValue -RawValue $RawValue -TextValue $TextValue
|
||||
return
|
||||
return $true
|
||||
}
|
||||
"User" {
|
||||
$Item[$field.InternalName] = Convert-ToUserFieldValue -Item $Item -RawValue $RawValue -TextValue $TextValue
|
||||
return
|
||||
return $true
|
||||
}
|
||||
"UserMulti" {
|
||||
$Item[$field.InternalName] = Convert-ToUserMultiFieldValue -Item $Item -RawValue $RawValue -TextValue $TextValue
|
||||
return
|
||||
return $true
|
||||
}
|
||||
"TaxonomyFieldType" {
|
||||
Set-SPTaxonomyFieldValue -Item $Item -Field $field -RawValue $RawValue -TextValue $TextValue
|
||||
return $true
|
||||
}
|
||||
"TaxonomyFieldTypeMulti" {
|
||||
Set-SPTaxonomyFieldValue -Item $Item -Field $field -RawValue $RawValue -TextValue $TextValue
|
||||
return $true
|
||||
}
|
||||
default {
|
||||
if ($null -eq $RawValue) {
|
||||
@@ -2274,22 +2379,28 @@ function Set-SPItemFieldValue {
|
||||
$Item[$field.InternalName] = $RawValue
|
||||
}
|
||||
|
||||
return
|
||||
return $true
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
$setErrorMessage = $_.Exception.Message
|
||||
|
||||
if ($field.TypeAsString -in @("TaxonomyFieldType", "TaxonomyFieldTypeMulti")) {
|
||||
throw ("Konnte Taxonomy-Feld '{0}' nicht ueber die TermGuid setzen. {1}" -f $TargetInternalName, $setErrorMessage)
|
||||
}
|
||||
|
||||
if (-not [string]::IsNullOrWhiteSpace($TextValue)) {
|
||||
try {
|
||||
$field.ParseAndSetValue($Item, $TextValue)
|
||||
return
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
throw ("Konnte Feld '{0}' weder direkt noch ueber ParseAndSetValue setzen. Direkt: {1}; ParseAndSetValue: {2}" -f $TargetInternalName, $setErrorMessage, $_.Exception.Message)
|
||||
}
|
||||
}
|
||||
|
||||
Write-SkippedImportFieldWarning -FieldInternalName $TargetInternalName -Message ("Konnte Feld '{0}' nicht setzen und ueberspringe es. {1}" -f $TargetInternalName, $_.Exception.Message)
|
||||
return
|
||||
throw ("Konnte Feld '{0}' nicht setzen. {1}" -f $TargetInternalName, $setErrorMessage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2303,7 +2414,9 @@ function Apply-FieldMappingToItem {
|
||||
|
||||
$SourceFieldValues,
|
||||
|
||||
$SourceFieldTextValues
|
||||
$SourceFieldTextValues,
|
||||
|
||||
[string]$Context = ""
|
||||
)
|
||||
|
||||
foreach ($sourceInternalName in $FieldMapping.Keys) {
|
||||
@@ -2340,7 +2453,15 @@ function Apply-FieldMappingToItem {
|
||||
$null
|
||||
}
|
||||
|
||||
Set-SPItemFieldValue -Item $Item -TargetInternalName $targetInternalName -RawValue $rawValue -TextValue $textValue
|
||||
try {
|
||||
$fieldWasSet = Set-SPItemFieldValue -Item $Item -TargetInternalName $targetInternalName -RawValue $rawValue -TextValue $textValue
|
||||
if ($fieldWasSet) {
|
||||
Write-Host ("Columnwert erfolgreich gesetzt: {0}; SourceColumn='{1}'; TargetColumn='{2}'" -f $Context, $sourceInternalName, $targetInternalName)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Warning ("Fehler beim Setzen eines Columnwerts: {0}; SourceColumn='{1}'; TargetColumn='{2}'; Fehler={3}" -f $Context, $sourceInternalName, $targetInternalName, $_.Exception.Message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2696,7 +2817,7 @@ function Import-SPDocumentLibraries {
|
||||
if ($null -ne $itemMetadata) {
|
||||
try {
|
||||
$fieldMapping = Get-FieldMappingForContainer -MigrationMappingTable $MigrationMappingTable -ObjectType "DocumentLibrary" -SourceTitle $sourceLibraryTitle
|
||||
Apply-FieldMappingToItem -Item $spItem -FieldMapping $fieldMapping -SourceFieldValues (Get-ObjectPropertyValue -Object $itemMetadata -PropertyName "FieldValues") -SourceFieldTextValues (Get-ObjectPropertyValue -Object $itemMetadata -PropertyName "FieldTextValues")
|
||||
Apply-FieldMappingToItem -Item $spItem -FieldMapping $fieldMapping -SourceFieldValues (Get-ObjectPropertyValue -Object $itemMetadata -PropertyName "FieldValues") -SourceFieldTextValues (Get-ObjectPropertyValue -Object $itemMetadata -PropertyName "FieldTextValues") -Context ("Bibliothek='{0}'; Datei='{1}'" -f $targetLibrary.Title, $fileName)
|
||||
Save-SPListItem -Item $spItem -Context ("Bibliothek '{0}', Datei '{1}'" -f $targetLibrary.Title, $fileName)
|
||||
}
|
||||
catch {
|
||||
@@ -2846,7 +2967,7 @@ function Import-SPLists {
|
||||
$targetItem = $targetList.Items.Add()
|
||||
}
|
||||
|
||||
Apply-FieldMappingToItem -Item $targetItem -FieldMapping $fieldMapping -SourceFieldValues (Get-ObjectPropertyValue -Object $sourceItem -PropertyName "FieldValues") -SourceFieldTextValues (Get-ObjectPropertyValue -Object $sourceItem -PropertyName "FieldTextValues")
|
||||
Apply-FieldMappingToItem -Item $targetItem -FieldMapping $fieldMapping -SourceFieldValues (Get-ObjectPropertyValue -Object $sourceItem -PropertyName "FieldValues") -SourceFieldTextValues (Get-ObjectPropertyValue -Object $sourceItem -PropertyName "FieldTextValues") -Context ("Liste='{0}'; SourceItemId='{1}'; Titel='{2}'" -f $targetListTitle, $sourceItemId, $sourceItemTitle)
|
||||
|
||||
if (-not [string]::IsNullOrWhiteSpace($sourceItemUniqueId)) {
|
||||
$targetItem[$trackingField.InternalName] = $sourceItemUniqueId
|
||||
|
||||
Reference in New Issue
Block a user