からめもぶろぐ。

俺たちは雰囲気で 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()

削除されました!