からめもぶろぐ。

俺たちは雰囲気で OAuth をやっている

Microsoft Graph を使って Excel のサーバーサイド オートメーションを実現する

みんな大好き Excel ということで、Excel のサーバーサイド オートメーションは、昔から様々な手法によって実現されてきました。サポートされない (意味深) *1 方法であったり、サードパーティの製品に頼らなければいけなかったのですが、現在では Microsoft Graph を使うことで、サーバーサイドで Excel を作成することができるようになりました。

やりたいことをざっくりとまとめると以下のような感じになります。

  • Excel のテンプレートを SharePoint サイトの任意の場所に置く
  • Excel のテンプレートをコピーする
  • コピーしたファイルに値を書き込む
  • 書き込んだファイルをダウンロードする (Azure Blob Storage などに保存する)

手順

具体的に API を見ながら実装方法を確認します。

Excel のテンプレートを SharePoint サイトの任意の場所に置く

これは自動化する必要はないので手動でやればいいですね。もしテンプレートの自動更新のようなことを行いたい場合はファイルのアップロードができます。

docs.microsoft.com
docs.microsoft.com

Excel のテンプレートをコピーする

ファイルのコピーは copy メソッドを使います。コピーは driveId を指定できるので、SharePoint サイト間や SharePoint から OneDrive for Bussiness へのコピーも行うことができます。

docs.microsoft.com

コピーしたファイルに値を書き込む

セルに値を書き込むには range に対して PATCH 要求を実行します。値を設定できるほか、数式や書式を設定することもできます。値は二次元配列で指定するのがミソです。

docs.microsoft.com

また、大量の値を書き込む場合は、パフォーマンスを向上させるためにセッションを使うのがいいでしょう。

docs.microsoft.com

書き込んだファイルをダウンロードする

作成したファイルは content プロパティでダウンロードできます。GET 要求を投げるとダウンロードのための一時的な URL にリダイレクトされ、そこからファイルをダウンロードできるようになります。

docs.microsoft.com

まとめ

今回はファイル操作と Excel 操作だけでしたが、例えば申請書の宛先に上司の名前を自動的に設定するために manager を使ったり、作ったファイルをダウンロードせずに URL をメールで送ったり、いろいろなバリエーションが考えられると思います。ぜひ Microsoft Graph を使って自由なプログラミングを体感していただければと思います。

第25回 Office 365 勉強会で LT をしました

第25回 Office 365 勉強会で LT をしました。

jpo365ug.connpass.com

スライドはこちら。

うまくいくか不安だったのですが本当にちょうどいいタイミングでメールが送られてきたのが嬉しかったです。あと話ができなかった労働時間トラッキング ソリューション開発テンプレートについては中身自体は本当に面白いのでぜひ動かせるようであれば動かしてみてください。結構コードが泥臭いところがいろいろ興味深かったりします。

blogs.windows.com

削除できなくなった SharePoint 2013 ワークフローを強制的に削除する

SharePoint Designer で SharePoint 2013 ワークフローを開発しているとまれに作成したワークフローを削除できなくなることがあります。具体的には、再利用可能なワークフローを作成し、テンプレートとして保存し、保存したテンプレートから展開した場合に、ワークフローが削除できなくなることが確認できています。この場合、SharePoint Designer で削除できないだけでなく、CSOM から WorkflowDeploymentService.DeleteDefinition メソッドを呼び出しても削除できません。
削除できないと最悪サイトの作り直しになってしまいますので、頑張って無理やり削除してみたいと思います。

まず、SharePoint 2013 ワークフローの情報はどこに格納されているかというと「wfsvc」という隠しドキュメントライブラリにあります。「wfsvc」は GUI からも SharePoint Designer からも見えませんが、CSOM からであれば確認することができます。

試しに SharePoint Designer で SharePoint 2013 ワークフローを作成してみます。

CSOM でワークフローが存在することを確認します。

Add-Type -LiteralPath "$PSScriptRoot\Microsoft.SharePoint.Client.dll"
Add-Type -LiteralPath "$PSScriptRoot\Microsoft.SharePoint.Client.Runtime.dll"

$siteurl = "{{siteurl}}"
$username = "{{username}}"
$password = "{{password}}"

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

$web = $context.Web
$context.Load($web)
$context.ExecuteQuery()

$list = $web.GetList($web.ServerRelativeUrl.TrimEnd('/') + '/wfsvc')
$query = New-Object Microsoft.SharePoint.Client.CamlQuery
$query.ViewXml = '<View Scope="RecursiveAll"></View>'
$items = $list.GetItems($query)
$context.Load($items)
$context.ExecuteQuery()

foreach ($item in $items) {
    Write-Output ([pscustomobject]@{ Path = $item['FileRef']; Name =  $item['WSDisplayName'] })
}

実行すると以下のような結果が返ってきます。

Path                                                  Name
----                                                  ----
/wfsvc/a1ef7b8ae5554ee18af83707d4bdef88
/wfsvc/a1ef7b8ae5554ee18af83707d4bdef88/workflow.xaml Test Workflow 1

workflow.xaml がワークフローの本体です。よってこれをフォルダーごと削除してしまいます。

$folder = $web.GetFolderByServerRelativeUrl('/wfsvc/a1ef7b8ae5554ee18af83707d4bdef88')
$folder.DeleteObject()
$context.ExecuteQuery()

削除されました!

PowerApps の所有者を PowerShell で変更する

なんか煽られた気がするので書いてみます。

PowerApps で、アプリの作成者が退職したなどの理由でアカウントがなくなってしまった場合、アプリ自体は残り続けます。共有されている場合はまだいいのですが、自分だけで使っていたなどの場合は、誰もアプリを編集できない状態になってしまいます。それを回避するためにアプリの所有者を変更するという手段が提供されています。今回は PowerShell でアプリの所有者を変更してみたいと思います。

まず、組織のアプリの一覧は管理センターから見ることができます。今回は「野良アプリ」の所有者を変更してみます。

PowerApps の管理モジュールは PowerShell Gallery から入手することができます。

www.powershellgallery.com

モジュールをインポートしてログインします。

PS C:\> Import-Module Microsoft.PowerApps.Administration.PowerShell
PS C:\> Add-PowerAppsAccount

アプリの一覧を取得するのは「Get-AdminPowerApp」コマンドを使用します。

PS C:\> Get-AdminPowerApp

AppName                  : 4e3bd861-3ae1-4e15-a5e3-93e8585cbfdd
DisplayName              : パスワード マネージャー
CreatedTime              : 2018-08-24T01:33:36.3124145Z
...

AppName                  : 60ebc075-e5a3-49d3-8163-c216ecc688b0
DisplayName              : 野良アプリ
CreatedTime              : 2019-08-29T06:02:42.8999503Z
...

アプリの所有者を変更するのは「Set-AdminPowerAppOwner」を使用します。パラメーターは (Name とかいう名前になっていますが) すべて GUID で指定します。

PS C:\> Set-AdminPowerAppOwner -AppName 60ebc075-e5a3-49d3-8163-c216ecc688b0 -EnvironmentName Default-92dbed3f-d37a-4f19-a392-f6970505cc6a -AppOwner 4b34f1e2-0c77-4fbd-a8cf-94a4606021ee

Code        :
Description :
Error       :
Errors      :
Internal    : @{name=60ebc075-e5a3-49d3-8163-c216ecc688b0; id=/providers/Microsoft.PowerApps/apps/60ebc075-e5a3-49d3-81
              63-c216ecc688b0; type=Microsoft.PowerApps/apps; tags=; properties=}

変更されました!