SharePoint Online で選択肢列と参照列を PowerShell で付け替える(1/3)

[ブログからの転載](http://1bed.allright.life/?p=2592)

選択肢列を参照列に入れ替える時にはどうするのか？
それは我々に永遠の課題である（嘘

当初は選択肢列で作っていたが、運用していくとマスタ化したくなり、参照列に変更したいということがあるのではないでしょうか。
但し、参照列にするとアイテムを残し続けないといけないカルマを背負うため、上手く先を見越さないと「xxxxx (使用禁止)」とか「xxxx (yyyy.mm.dd まで使用)」とかいう超絶ダサいマスタになっていき、未来永劫、裏でコソコソ言われるので気をつけましょう（言い過ぎ
　＃参照列にフィルタリングする方法があれば教えてください... orz

さて、選択肢列を参照列に置き換える時は、恐らく次の手順な感じになると思う

1. 選択肢列の値を使い、参照列元のリストを作成する
2. 手順 1 で作成したリストを使い、参照列を作成する
3. 選択肢列の値を参照列に移行
4. 選択肢列の削除  
   ＃実際は非表示列にして、動作確認後に削除するというのが良いかと思う

上記手順の 1 ～ 3 を PowerShell でやってみようと思う

今回は「1. 選択肢列の値を使い、参照列元のリストを作成する」を行う

## 環境

SharePoint Online に次のリスト準備

* リスト名: 選択肢列と参照列を付け替える

| 列名 | 内部列名 | 種類 | 値 |
| --- | --- | --- | --- |
| 目的地 | Title | 1 行テキスト | |
| 乗り物 | vehicle | 選択肢 | 車 , バイク , 自転車 , 船 , 飛行機 |
| おやつ | snack | 選択肢(複数選択可能) | ポテトチップス , アポロ , じゃがりこ , チップスター , ハイレモン , かっぱえびせん | 

* 選択肢列から作成される参照元リスト(マスタリスト)

| 列名 | 生成されるリスト名 | リストのタイトル |
| --- | --- | --- |
| 乗り物 | 乗り物マスタ | vehicleMst |
| おやつ | おやつマスタ | snackMst |

## 1. 選択肢列の値を使い、参照列元のリストを作成する

```powershell

[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")

# SharePoint Online の URL
$SiteURL = 'https://<tenant>.sharepoint.com/sites/example'
# ユーザー名
$user = 'miyamiya@example.com';
# パスワード
$secure = Read-Host -Prompt "Enter the password for ${user}(Office365)" -AsSecureString;
# SharePoint Online 認証情報
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($user, $secure);
# SharePoint Client Context インスタンスを生成
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$ctx.Credentials = $credentials

## ここまではいつものおまじない的なコード。
## ログインして SharePoint Client Context のインスタンスを作成しています。

# 選択肢列を参照列に置き換えるリストのリスト名
$ListName         = "選択肢列と参照列を付け替える"
# 参照列化する列名
$fieldName        = "乗り物"
# マスタリストのタイトル
$convertListTitle = "vehicleMst"
# マスタリストの名前
$convertListName  = "乗り物マスタ"

# リストの取得
$list = $ctx.Web.Lists.GetByTitle($ListName)
# フィールドの取得
$field = $list.Fields.GetByInternalNameOrTitle($fieldName)
# 値のロード
$ctx.Load($field)
$ctx.ExecuteQuery()

# 選択肢列でない時は処理を終了する
if ($field.TypeAsString.ToUpper() -ne 'CHOICE' -and $field.TypeAsString.ToUpper() -ne 'MULTICHOICE') {
    exit
}

# マスタリストの作成
$listInfo = New-Object Microsoft.SharePoint.Client.ListCreationInformation
$listInfo.TemplateType = 100
$listInfo.Title = $convertListTitle
$listInfo.Url = "Lists/$convertListTitle"

$mstlist = $ctx.Web.Lists.Add($listInfo)
$mstlist.Title = $convertListName
$mstlist.Update()
$ctx.ExecuteQuery()

# マスタデータの作成
foreach($value in $field.TypedObject.Choices) {
    $itemCreateInfo = New-Object Microsoft.SharePoint.Client.ListItemCreationInformation
    $item = $mstlist.AddItem($itemCreateInfo)
    $item['Title'] = $value
    $item.Update()
}
$ctx.ExecuteQuery()

# コンテキストの破棄
$ctx.Dispose()
```

マスタリストの作成は以前に詳しく紹介しているのでそちらを参考にしてください。

* [Qiita: SharePoint Online にリストを作成する手順(PowerShell)](https://qiita.com/miyamiya/items/f2a57d20e34a33f4c26d) 

マスタデータの作成では、リストの列情報にある選択肢列の値の分データを作成、更新予約を行い、最後に一気に ExecuteQuery で更新しています。

あとは、もう一つの選択肢列「おやつ」を使って「おやつマスタ」リストを作成するために、上記のコードの 21 ～ 26 行目を変更してもう一度実行します。

実際に使うコードの時は、外部ファイルから次のようなオブジェクトを作成できるようにして、繰り返し処理を加えても良いとは思う。

```powershell
$target = @()
$target += @{
    fieldName        = "乗り物";
    convertListTitle = "vehicleMst";
    convertListName  = "乗り物マスタ";
}
$target += @{
    fieldName        = "おやつ";
    convertListTitle = "snackMst";
    convertListName  = "おやつマスタ";
}
```