Nanairo

I want to run a way in front of me.

Sharepoint OnlineとPowershellでリストを大量作成した話①

Microsoft 365ではSharepoint Onlineが使えますが、Sharepoint上に大量のリストを作るということがあったので、今後の参考にまとめておきたいと思います。
Sharepoint関係のPowershell情報は日本語ではあまりなく、英語情報ばかりな気がします。
(やりたいこと)
・会社の各部署に共通のリストフォームを使って、社内に情報を公開したい。
・1部署に対して、サイトページ1個を割り当てて、その中に2個のリストを表示させる。

(前提条件)
Sharepointサイトへのアクセス許可において、メンバーに閲覧権限があること。編集権限では駄目。
・サイトの管理者にフルコントロールをつけておくこと。

1.PnPモジュールのインストール

まずはPowershellでPnPモジュールをインストールします。Powershellは管理者権限で動かします。

Install-Module SharePointPnPPowerShellOnline

2.Sharepoint Online上のサイトへアクセス

次にSharrpoint上のリストを作成したいサイトにアクセスします。

Connect-PnPOnline -Url https://contoso.onmicrosoft.com/example -Credentials (Get-Credential)

これを実行すると管理者の資格情報が求められるので、資格情報を入力してやります。MFA適用環境下ではどのように動くのかは分かりません。
処理のフローですが、リスト→ページの順に作成し、作成したページに2種類のリストを貼り付けるということをします。

3.リストの作成

リストを作成する際のコマンドは次のとおりです。
引数 -titleに渡す値はリストの名前、-Urlに渡す値はリストの保管パスになります。リストの保管パスはLists/○○○○という形で、Listsの中に保管するように指定することが基本のようです。

New-PnPList -Title "title" `
            -Url "Lists/ListFilename" `
            -Template 100

引数 templateに入っている100という値ですが、今回は白地のリストにSet-PnPFieldで列やデータ型を定義する(=白地のリストをカスタマイズする)ので、GenericListというテンプレートを使います。
GenericTemplateの値は100であるため、100を指定します。その他のテンプレはここに記載があります。
docs.microsoft.com

作成されたリストは添付ファイルの添付が既定で可能になっていますが、今回はファイルを添付させたくないので、Set-PnPListで添付ファイルを添付できないようにします。
引数EnableAttachmentsに対してFalseを指定します。
また、作成したリストは社内の誰でもアクセスできるが、編集はその部署の人しかできないようにしたいので、ここで権限の継承を解除します。継承を解除するにはBreakRoleInheritanceに対してTrueを入れます。

Set-PnPList -Identity "Lists/Filename" `
            -EnableAttachments:$false
            -BreakRoleInheritance:$True

リストのアクセス制御はSet-PnPListPermissionで行います。
Sharepointグループを指定するか、ユーザーあるいはMicrosoft 365グループを指定するかで引数が異なるので注意してください。前者の場合はgroup、後者の場合はuserです。

Set-PnPListPermission `
     -Identity "Lists/Filename" `
     -User "division@contoso.onmicrosoft.com" `
     -Addrole "編集"

余談ですが、Azureと一緒に使っている場合は、Sharepointサイトを作成された際に自動的にMicrosoft 365グループが出来ると思いますが、そこに動的メンバーシップを設定しておくと便利かもしれません。
あるいは権限の継承を止めているので、Set-PnPListPermissionを使って、閲覧と編集を個別に設定してやるという方法もあると思います。

4.デフォルトの列の定義

次に作ったリストの列の定義をします。
作成されたリストには既に列が1個用意されており、この列をクリックすると詳細が表示されます。この列を考慮しておかないと、意味の分からない列が1個出来るので、まずはこの列を変更します。
リストは表示上は日本語名の列をつけることが出来ますが、PoiwershellではInternalNameという値をもって管理します。InternalNameは基本的に英語で設定するようですが、この列のInternalNameはTitleになっています。
New-PnPListで作ったリストをブラウザ上で見ると、その列名は「タイトル」になっています。このタイトル列をまずは適当なものに変更します(必要がなければこの作業は不要です)。

まずは、この列名「タイトル」のGuidを取得します。取得したGuidは変数「RootId」に格納しています。

$RootId = (Get-PnPField -List "Lists/Filename" | Where-Object {($_.InternalName) -eq "Title"}).Id

※よくよく考えたら、こんなことしなくてもInternalNameでTitleを指定してやれば良かったですね。なんでGuIdで指定しようとしたのだろうか。。。

この後に$RootIdを実行して、Guidが格納されているか確認をします。
次にSet-PnPFieldで列の変更をします。以下の構文では「タイトル」を「名前」に変更しています。
リストに新しいアイテムを入れる際、ユーザーに何を入力してほしいのか表示させたいので、引数descriptionに説明文を入れます。MaxLengthの値は格納する文字列の最大長です。以下では64文字です。

Set-PnPField  `
   -List "Lists/Filename" `
   -Identity $RootId `
   -Values @{`
      "MaxLength" = 64; `
      "Description" = "ここに名前を入れてください。";
      "Indexed" = $false; `
      "Title" = "名前"; `
    }| Out-String

5.列の追加・追加した列の定義

次に列を追加しています。
リストに列を追加するだけだったら、New-PnPFieldだけでいいのですが、列に文字列の長さであったり、データ型を定義する場合はSet-PnPFieldも実行しなければなりません。
InternalNameにはSharepointの内部で管理する列名を入力します。ブラウザでリストを表示させたときに表示される列名とは異なります。ここでは表示名を「年齢」として、InternalName(Powershllなどで変更を行うときに使う識別名)を「age」にします。データ型はI年齢ですのでnteger(整数)で指定します。
typeに設定できる型は以下が参考になります。
docs.microsoft.com

また、作成した列をデフォルトで表示させておきたいので、AddtoDefauleViewも入れておきます。これを入れておかないと、リスト上に作った列は表示されません。

Add-PnPField  `
    -List "Lists/Listname" `
    -DisplayName "年齢" `
    -InternalName "age" `
    -Type Integer `
    -AddToDefaultView

作成した列に説明や文字列の最大長、必須項目か否かを設定します。リストにアイテムを作成するに当たって、その列を入力必須項目にしたい場合は、RequiredをTrueにします。

 Set-PnPField  `
      -List "Lists/Filename"  `
      -Identity "age" `
      -Values @{`
          "MaxLength" = 3; `
          "Description" = "年齢を入力してください。"; `
          "Indexed" = $False; `
          "Required" = $True; `
       }

この作業ですが、Add-PnPFieldとSet-PnPFieldは1セットで実行する方がいいような気がしたので、私は関数化しました。
が、物によっては引き渡す値がそもそも不要ということもあり、複数回実行するとエラーで止まってしまいました。関数を実行すると見えない場所で結果のテーブルを作っているようなのですが、このテーブルのフォーマットが一致しないため、エラーが出てしまう模様です。なので、エラーが出ないように関数に「Out-String」をつけます。

function MakeListField {
        param (
            $ListPath,
            $DisplayName,
            $InternalName,
            $TypeOfData,
            $MaxLength,
            $Description,
            $Indexed,
            $Required,
            $Title
        )
        
        Add-PnPField `  
              -List $ListPath `
              -DisplayName $DisplayName `
              -InternalName $InternalName `
              -Type $TypeOfData `
              -AddToDefaultView
    
        Set-PnPField ` 
              -List $ListPath `
              -Identity $InternalName `
              -Values @{`
                 "MaxLength" = $MaxLength; `
                 "Description" = $Description; `
                 "Indexed" = $Indexed; `
                 "Required" = $Required; `
                 "Title" = $Title; `
               }
}

6.リストにビューを設定する。

リストにビューを設定する必要がある場合は、Add-ViewとSet-Viewでビューを作ります。
例えば名簿などで序列を作ったりする場合は、こういった処理を入れておくことが良いかと思います。以下は年齢順という名前のビューを作るコマンドです。
Fieldでこのビューでの表示列を指定します。また、SetAsDefaultを入れることで、このビューがデフォルトで適用されるようにします。

Add-PnPView `
         -List "Lists/Filename" `
         -Title "年齢順" `
         -Field "Title","age" `
         -SetAsDefault | Out-String

Out-Stringは本来いらないのですが、関数を入れてリストを作っている場合はエラーが出ることがあるので、おまじないとして入れています。
実行すると年齢順というビューが作成されます。
年を取っている順(年齢の値が大きい順)に並べ替えるために、Set-PnPViewで並べ替えの指定をします。ここでは降順に並べ替えるのでAscendingをFalseにします。若者順にする場合はAscendingはTrueにします。

Set-PnPView  `
   -List "Lists/Filename" `
   -Identity "年齢順" `
   -Values @{ViewQuery = "<Query><OrderBy><FieldRef Name='age' Ascending='FALSE' /></OrderBy></Query>"} | Out-String

ただ、こいつはうまく動きませんでした。何でかは分かりません。
なので、ページを作る際に少し強引に設定を行いたいと思います。

ここまでリストは完成したので、次回はサイトを作成し、そこに作ったリストを貼り付けます。

(次回へ続く。)