モダン リストとモダン ライブラリを最大限に利用する

この記事では、SharePoint でモダン ユーザー インターフェイス使用時に、リストとライブラリの最大数を取得する方法について説明します。

以下の理由のため、まだすべてのリストとライブラリをモダン エクスペリエンスに変換できるわけではありません。

  • リストやライブラリの中には、モダン ユーザー インターフェイスに表示するのに必要な SharePoint チームによるビルドが現時点では完了していないものが存在します。例としては、タスク リストやイベント リストなどです。 このようなリストやライブラリに関しては、SharePoint チームがモダン バージョンを実装するのをお待ちになるか、他の同じような方法に切り替えてください。 他の方法には、従来のタスク リストではなく Microsoft Planner を使用する方法や、従来の SharePoint イベント リスト カレンダーではなく Microsoft 365 グループのカレンダーを使用する方法があります。

  • リストやライブラリの中には、モダン ユーザー インターフェイスで表示できるのに、互換性のない構成やカスタマイズが原因でブロックされるものも存在するため、ここで対策を講じることができます。

重要

モダン化ツールと他のすべての PnP コンポーネントは、それらをサポートしてくれるアクティブなコミュニティによって支援されているオープン ソース ツールです。 公式の Microsoft サポート チャネルのオープン ソース ツール用の SLA ではありません。

モダン ユーザー インターフェイスで使用可能なリスト テンプレート

次に示すテンプレートの種類は、現時点で SharePoint がモダン ユーザー インターフェイスに表示できる最も使用頻度の高いリスト テンプレートの種類です (2018 年 10 月現在)。

  • リスト (100)
  • ドキュメント ライブラリ (101)
  • リンク リスト (103)
  • お知らせリスト (104)
  • 連絡先リスト (105)
  • 画像ライブラリ (109)
  • フォーム ライブラリ (115)
  • サイト ページ ライブラリ (119)
  • カスタム グリッド (120)
  • 注目リンク リスト (170)
  • 発行ページ ライブラリ (850)
  • アセット ライブラリ (851)
  • 問題点の追跡リスト (1100)

このセクションでは、モダン リストとして表示されないリストの種類を識別する方法と、その理由について説明します。また、そうしたリストの種類の修正方法についても説明します (可能な場合)。 その説明の前に、理解しておくべき重要な事項があります。ほとんどのテナントでは、多くのリストが一切の警告なしにモダン形式で読み込まれるということです。 モダン形式で読み込まれないリストは、予定表やタスク リストのようにクラシック形式のまま表示するか、そうしたリストの修正によってブロックを解除します。このシリーズ記事では、その解除方法について説明しています。 モダン リストとして読み込まれないリストは、使用上の問題はなく、完全にサポートされます。また、テナントでリストとライブラリのモダン エクスペリエンスを有効化してもかまいません。

重要

SharePoint では自動的に最新のリストとライブラリが既定として設定されますが、必要に応じて自動的にフォールバックもします。 これにより、モダン形式が使用可能なすべてのリストはモダン リストとして表示されるようになります。モダン形式が使用できないリストについては、そのリストの使用時に、単にクラシック形式に切り替えます。

モダン ユーザー インターフェイスで使用できないリストとライブラリを検出する

モダン ユーザー インターフェイスで使用できないリストやライブラリを検出するには、SharePoint モダン化スキャナーを実行するアプローチをお勧めします。 このツールは、テナントに含まれるすべてのリストとライブラリを詳細に分析し、モダン ユーザー インターフェイスで表示されないリストやライブラリと、さらに重要な点として、その理由についても詳細な情報を提供するレポートを作成します。 スキャナーの出力を基に、リストとライブラリを修正するとブロックを解除することができます。これについては、次の章で説明します。

リストとライブラリのブロックを解除する

リストは、1 つ以上の理由によりブロックされる場合があります。それらの理由がすべて、スキャナーの出力に表示されます。以下に、一般的な理由とその修復方法を説明します。

互換性のないカスタマイズ

リストがモダン ユーザー インターフェイスに表示されない原因として最も多く指摘されるのは互換性のないカスタマイズです。通常、次のいずれかが該当します。

  • JSLink の使用
  • JavaScript を埋め込むユーザー カスタム アクションの使用

このようなブロックが行われないように修正するには、そのカスタマイズを削除する (ビジネスで不要になっている場合) か、別のソリューションを作成します。 リストとライブラリのモダン エクスペリエンスと互換性があるカスタマイズの構築の詳細については、「カスタマイズのモダン化」の記事を参照してください。 Web パーツ レベルの JSLink があると、ページでリストとライブラリのモダン エクスペリエンスが使用できなくなるため、この構成を削除する必要があります。 この作業を手動で実行する場合は、ページの URL に ?ToolPaneView=2&pagemode=edit を追加することでページを編集モードにして、Web パーツのプロパティを更新します。 プログラムで実行する場合は、LimitedWebPartManager クラスで Web パーツを取得して、次のスニペットで示すように、それぞれのプロパティを更新します。 このスニペットを、このページの後半で示すより完成されたコードと組み合わせると、完全なソリューションが得られます。

webPart.Properties["JSLink"] = "";
webPart.SaveWebPartChanges();
cc.ExecuteQuery();

特定の型のフィールドの存在

特定の型のフィールド (BCS 外部データ、位置情報、編集モードの OutcomeChoice、画像、Html、SummaryLinks) は、モダン ユーザー インターフェイスで機能するのに必要なビルドが現時点では完了していません。これらを修正するには、次のアプローチを適用できます。

  • フィールドをビューから削除します。このフィールドはまだ存在するため、従来の編集体験ができますが、少なくともビューはモダンです。
  • フィールド データをモダン ユーザー インターフェイスと互換性のある新しいフィールドに移行します。
  • そのフィールドが使用されていない場合は、フィールドを完全に削除します。

サイト レベルまたは Web レベルでブロックする、モダンおよびライブラリ ユーザー インターフェイス

モダン リストとライブラリのユーザー インターフェイスは、完全なサイト コレクション (サイト レベル) または 1 つ以上のサイト (Web レベル) について、ブロックされる可能性があります。 これを修復するには、以下の PnP PowerShell スニペットに示すように、それぞれ、サイト範囲または Web 範囲の機能を無効にして行うことができます。

$minimumVersion = New-Object System.Version("2.24.1803.0")
if (-not (Get-InstalledModule -Name SharePointPnPPowerShellOnline -MinimumVersion $minimumVersion -ErrorAction Ignore))
{
    Install-Module SharePointPnPPowerShellOnline -MinimumVersion $minimumVersion -Scope CurrentUser
}
Import-Module SharePointPnPPowerShellOnline -DisableNameChecking -MinimumVersion $minimumVersion

Connect-PnPOnline -Url "<your site url>"

# Disable the modern list site level blocking feature
Disable-PnPFeature -Identity "E3540C7D-6BEA-403C-A224-1A12EAFEE4C4" -Scope Site
# Disable the modern list web level blocking feature
Disable-PnPFeature -Identity "52E14B6F-B1BB-4969-B89B-C4FAA56745EF" -Scope Web

注意

PnP PowerShell はオープン ソース ソリューションであり、アクティブなコミュニティでサポートが提供されています。 Microsoft からのオープン ソース ツールのサポート SLA はありません。

リスト レベルでブロックするモダンおよびライブラリ ユーザー インターフェイス

リストは、常にクラシック エクスペリエンスを実行するようにリスト レベルで定義されていることがあります (ListExperienceOptions が ClassicExperience に設定されている)。 この状態は、次のコード スニペットで元に戻すことができます。

// Load the list you want to update
var list = context.Web.Lists.GetByTitle(title);
context.Load(list);
context.ExecuteQuery();

// Possible options are Auto (= defaults to modern), NewExperience (= "modern") and ClassicExperience
list.ListExperienceOptions = ListExperience.Auto;

// Persist the changes
list.Update();
context.ExecuteQuery();

BaseTemplate = 0 で表示されるリスト

それぞれのリストには基本テンプレートがありますが、スキャナーの出力では基本テンプレートの値が 0 になっているリストが見つかることがあります。 該当するリストに既定としてマークされたビューが存在していないことが原因の場合もありますが、そもそもビューが存在していないこともあります。 こうしたリストを修正する場合は、リストの設定ページ (_layouts/15/listedit.aspx?List=%7B<list id>%7D) に移動して、リストにビューを設定します。

XSLTListViewWebPart リスト以外のものも含むカスタマイズされたリスト ビュー ページ

従来のリスト ビューと編集ページはユーザーが編集できるため、たとえば、リスト ビュー ページに新しい Web パーツを追加することもできます。 追加した場合は、リストはもうモダン ユーザー インターフェイスに表示されなくなります。 修正する唯一の方法は、追加した Web パーツをそのリスト ページから削除することです。 このようなケースを手動で確認する場合は、リストに移動してリストの URL に ?ToolPaneView=2&pagemode=edit を追加します。 これにより、ページが編集モードになり、余分な Web パーツが表示され、それらを削除できるようになります。 この作業をプログラムで実行する場合は、出発点として次のコードスニペットを使用できます。 このスニペットは、PnP サイトのコア ライブラリに依存します。このライブラリは、SharePointPnPCoreOnline NuGet パッケージから Visual Studio プロジェクトにインストールできます。

using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.WebParts;
using OfficeDevPnP.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;

namespace MultipleWebPartFixer
{
    class Program
    {
        static void Main(string[] args)
        {
            string siteUrl = "https://contoso.sharepoint.com/sites/demo";
            string userName = "joe@contoso.onmicrosoft.com";
            AuthenticationManager am = new AuthenticationManager();
            using (var cc = am.GetSharePointOnlineAuthenticatedContextTenant(siteUrl, userName, GetSecureString("Password")))
            {
                // Grab the list
                var list = cc.Web.Lists.GetByTitle("listtofix");
                list.EnsureProperties(l => l.RootFolder, l => l.Id);

                bool isNoScriptSite = cc.Web.IsNoScriptSite();

                if (isNoScriptSite)
                {
                    throw new Exception("You don't have the needed permissions to apply this fix!");
                }

                // get the current (allitems) form
                var files = list.RootFolder.FindFiles("allitems.aspx");
                var allItemsForm = files.FirstOrDefault();
                if (allItemsForm != null)
                {
                    // Load web part manager and web parts
                    var limitedWPManager = allItemsForm.GetLimitedWebPartManager(PersonalizationScope.Shared);
                    cc.Load(limitedWPManager);

                    // Load the web parts on the page
                    IEnumerable<WebPartDefinition> webParts = cc.LoadQuery(limitedWPManager.WebParts.IncludeWithDefaultProperties(wp => wp.Id, wp => wp.ZoneId, wp => wp.WebPart.ExportMode, wp => wp.WebPart.Title, wp => wp.WebPart.ZoneIndex, wp => wp.WebPart.IsClosed, wp => wp.WebPart.Hidden, wp => wp.WebPart.Properties));
                    cc.ExecuteQueryRetry();

                    List<WebPartDefinition> webPartsToDelete = new List<WebPartDefinition>();
                    if (webParts.Count() > 1)
                    {
                        // List all except the XsltListView web part(s)
                        foreach (var webPart in webParts)
                        {
                            if (GetTypeFromProperties(webPart.WebPart.Properties) != "XsltListView")
                            {
                                webPartsToDelete.Add(webPart);
                            }
                        }

                        if (webPartsToDelete.Count == webParts.Count() - 1)
                        {
                            foreach(var webPart in webPartsToDelete)
                            {
                                webPart.DeleteWebPart();
                            }
                            cc.ExecuteQueryRetry();
                            Console.WriteLine("List fixed!");
                        }
                        else
                        {
                            // Special case...investigation needed. Go to list and append ?ToolPaneView=2&pagemode=edit to the list url to check the page
                            Console.WriteLine("Go to list and append ?ToolPaneView=2&pagemode=edit to the list url to check this page");
                        }
                    }
                }
            }

            Console.WriteLine("Press enter to continue...");
            Console.ReadLine();
        }

        public static string GetTypeFromProperties(PropertyValues properties)
        {
            // Check for XSLTListView web part
            string[] xsltWebPart = new string[] { "ListUrl", "ListId", "Xsl", "JSLink", "ShowTimelineIfAvailable" };
            if (CheckWebPartProperties(xsltWebPart, properties))
            {
                return "XsltListView";
            }

            return "";
        }
        private static bool CheckWebPartProperties(string[] propertiesToCheck, PropertyValues properties)
        {
            bool isWebPart = true;
            foreach (var wpProp in propertiesToCheck)
            {
                if (!properties.FieldValues.ContainsKey(wpProp))
                {
                    isWebPart = false;
                    break;
                }
            }

            return isWebPart;
        }

        private static SecureString GetSecureString(string label)
        {
            SecureString sStrPwd = new SecureString();
            try
            {
                Console.Write(String.Format("{0}: ", label));

                for (ConsoleKeyInfo keyInfo = Console.ReadKey(true); keyInfo.Key != ConsoleKey.Enter; keyInfo = Console.ReadKey(true))
                {
                    if (keyInfo.Key == ConsoleKey.Backspace)
                    {
                        if (sStrPwd.Length > 0)
                        {
                            sStrPwd.RemoveAt(sStrPwd.Length - 1);
                            Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
                            Console.Write(" ");
                            Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
                        }
                    }
                    else if (keyInfo.Key != ConsoleKey.Enter)
                    {
                        Console.Write("*");
                        sStrPwd.AppendChar(keyInfo.KeyChar);
                    }

                }
                Console.WriteLine("");
            }
            catch (Exception e)
            {
                sStrPwd = null;
                Console.WriteLine(e.Message);
            }

            return sStrPwd;
        }
    }
}

関連項目