SharePoint Online リスト アイテムの新規作成フォーム、編集フォーム、表示フォームを復旧する

こんにちは SharePoint サポートの森 健吾 (kenmori) です。

今回の投稿では、SharePoint Online のブログ サイトで、リストの新規作成フォーム、編集フォーム、表示フォームを再作成する方法をご紹介します。

画面からリスト フォームの Web パーツを削除してしまった場合、画面上で Web パーツが消失するだけでなく、リストのフォーム定自体が消失します。
その結果、 特に予定表リストなど内部処理でフォームの定義 (SPList.Forms プロパティ) が参照されるような処理が実行されたた場合、エラーが発生する場合があります。

オンプレミス版の対処策は下記ページでも公開されており、このページに記載されているSharePoint Designer による対処策は SharePoint Online でも使用できます。

タイトル : SharePoint 2013 リスト アイテムの新規作成フォーム、編集フォーム、表示フォームを作成する
アドレス: https://blogs.technet.com/b/sharepoint_support/archive/2015/06/22/sharepoint-2013-create-a-new-form-for-a-list-item.aspx

しかしながら、SharePoint Designer での対処策ではフォームの機能を有する別のユーザー定義フォームの Web パーツを貼り付ける形式ですので見た目での対処には至りますが、リストのフォーム定義は消失したままとなりますため、完全な対処策にならない場合があります。
結果的に、PowerShell による完全対策を希望される場合が多いためSharePoint Online 向けの修正方法も記載します。

実行手順

1. テキスト エディタを開き、下記の内容を FixListView.ps1 として保存します。

 param(

  $siteUrl,
  $listName,
  $username,
  $password,
  $formtype = "ALL",
  $force = $false
)

$ErrorActionPreference = "Stop"

[void][System.Reflection.Assembly]::Load("Microsoft.SharePoint.Client, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")
[void][System.Reflection.Assembly]::Load("Microsoft.SharePoint.Client.Runtime, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")

$context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
$secpass = ConvertTo-SecureString $password -AsPlainText -Force
$context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $secpass)

$web = $context.Web
$list = $web.Lists.GetByTitle($listName)
$context.Load($list)
$context.ExecuteQuery()

$parentFolder = $list.RootFolder
$context.Load($parentFolder)
$context.ExecuteQuery()

if ($list.BaseType -eq [Microsoft.SharePoint.Client.BaseType]::DocumentLibrary)
{
  $formsurl = $parentFolder.ServerRelativeUrl + "/Forms"
  $parentFolder = $web.GetFolderByServerRelativeUrl($formsurl)
  $context.Load($parentFolder)
  $context.ExecuteQuery()
}

function CreateView($fileName, $ControlMode, $FormType)
{
  $url = $parentFolder.ServerRelativeUrl + "/" + $fileName
  $fileType = [Microsoft.SharePoint.Client.TemplateFileType]::FormPage

  $checkfile = $web.GetFileByServerRelativeUrl($url)
  $context.Load($checkfile)

  try
  {
    $context.ExecuteQuery()
    $fileExists = $checkfile.Exists
  }
  catch{}

   if ($force)
  {
    if ($fileExists)
    {
      $checkfile.DeleteObject()
      $context.ExecuteQuery()
    }

    $file = $parentFolder.Files.AddTemplateFile($url, $fileType)
    $context.Load($file)
    $context.ExecuteQuery()
  }
  else
  {
    Write-Host $url "already exists. You may have duplicate list forms now."
    $file = $checkfile
  }

  $wpm = $file.GetLimitedWebPartManager([Microsoft.SharePoint.Client.WebParts.PersonalizationScope]::Shared)
  $webPartXml = '<?xml version="1.0" encoding="utf-8"?>'
  $webPartXml += '<WebPart xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://schemas.microsoft.com/WebPart/v2">'
  $webPartXml += '<Title>' + $list.Title + '</Title>'
  $webPartXml += '<FrameType>Default</FrameType>'
  $webPartXml += '<Description/>'
  $webPartXml += '<IsIncluded>true</IsIncluded>'
  $webPartXml += '<PartOrder>2</PartOrder>'
  $webPartXml += '<FrameState>Normal</FrameState>'
  $webPartXml += '<Height/>'
  $webPartXml += '<Width/>'
  $webPartXml += '<AllowRemove>true</AllowRemove>'
  $webPartXml += '<AllowZoneChange>true</AllowZoneChange>'
  $webPartXml += '<AllowMinimize>true</AllowMinimize>'
  $webPartXml += '<AllowConnect>true</AllowConnect>'
  $webPartXml += '<AllowEdit>true</AllowEdit>'
  $webPartXml += '<AllowHide>true</AllowHide>'
  $webPartXml += '<IsVisible>true</IsVisible>'
  $webPartXml += '<DetailLink/>'
  $webPartXml += '<HelpLink/>'
  $webPartXml += '<HelpMode>Modeless</HelpMode>'
  $webPartXml += '<Dir>Default</Dir>'
  $webPartXml += '<PartImageSmall />'
  $webPartXml += '<MissingAssembly>Cannot import this Web Part.</MissingAssembly>'
  $webPartXml += '<PartImageLarge/>'
  $webPartXml += '<IsIncludedFilter/>'
  $webPartXml += '<Assembly>Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>'
  $webPartXml += '<TypeName>Microsoft.SharePoint.WebPartPages.ListFormWebPart</TypeName>'
  $webPartXml += '<ListName xmlns="https://schemas.microsoft.com/WebPart/v2/ListForm">{' + $list.ID.ToString() + '}</ListName>'
  $webPartXml += '<ListId xmlns="https://schemas.microsoft.com/WebPart/v2/ListForm">' + $list.ID.ToString() + '</ListId>'
  $webPartXml += '<ControlMode xmlns="https://schemas.microsoft.com/WebPart/v2/ListForm">' + $ControlMode + '</ControlMode>'
  $webPartXml += '<TemplateName xmlns="https://schemas.microsoft.com/WebPart/v2/ListForm">ListForm</TemplateName>'
  $webPartXml += '<FormType xmlns="https://schemas.microsoft.com/WebPart/v2/ListForm">' + $FormType + '</FormType>'
  $webPartXml += '<ViewFlag xmlns="https://schemas.microsoft.com/WebPart/v2/ListForm">1048576</ViewFlag>'
  $webPartXml += '</WebPart>'

  $webPartDefinition = $wpm.ImportWebPart($webPartXml)
  $webPart = $webPartDefinition.WebPart

  [void]$wpm.AddWebPart($webPart, "Main", 1)
  $context.Load($webPart)
  $context.ExecuteQuery()
}

$formtype = $formtype.ToUpper()
if (($formtype -eq "ALL") -or ($formtype -eq "DISPLAY"))
{
  CreateView -fileName "DispForm.aspx" -ControlMode "Display" -FormType "4"
}
if (($formtype -eq "ALL") -or ($formtype -eq "EDIT"))
{
  CreateView -fileName "EditForm.aspx" -ControlMode "Edit" -FormType "6"
}
if (($formtype -eq "ALL") -or ($formtype -eq "NEW"))
{
  CreateView -fileName "NewForm.aspx" -ControlMode "New" -FormType "8"
}

 

2. 下記のように実行します。

.\fixlistview.ps1 -siteurl https://tenant.sharepoint.com -listName "リスト名" -username user@tenant.onmicrosoft.com -password password -formtype DISPLAY -force $true

パラメータの説明

-siteurl ・・・ サイトの URL
-listname ・・・ リストのタイトル
-username ・・・ 実行ユーザーのログイン名
-password ・・・ 上記ユーザーのパスワード
-formtype ・・・ 修復するフォーム タイプ DISPLAY, NEW, EDIT, ALL (省略した場合は ALL)
-force ・・・ 既存のページにフォームを配置する場合は -force $false, ページを再作成してフォームを再配置する場合 -force $true (省略した場合は $false)

 

※ 注意
SharePoint オンプレミス版と異なり、IListWebPart など公開されたクラスが存在しているわけではありません。XML を自身で作成して配置した方法ですので、今後のアップデートによっては正常動作しなくなる可能性があります。
ご使用前にテスト用のリストを用意し、事前に動作を確認した上で、有効と判断される場合はご使用いただくことをお勧めします。

今回の投稿は以上になります。