Power Automate からリストやライブラリにアイテムを保存するアクションは用意されていますが、ページを作成したりニュースを投稿したりするアクションがありません。

SharePoint Online のモダンサイトを利用するには、やはりニュースを上手く利用するのが要だと思っています。そこで、やっぱり Power Automate からもニュースが投稿できると便利だろうと言うわけで、いろいろ勉強しながらその手法を探してみました。

なかなか苦労したのでメモしておきます。

「SharePoint に HTTP 要求を送信します」アクションを利用する

SharePoint のコネクタには、強力な「SharePoint に HTTP 要求を送信します」アクションがあるため、HTTP で利用できる API さえ分かってしまえば、多くのことを Power Automate から実行できます。今回のニュース記事を投稿する処理も API を探りあて、このアクションを利用することにしました。

そんなわけなので、内容はちょっと複雑です。

ニュース記事を作成する

いよいよ作成していきましょう。まずは、いつも通り SharePoint からニュースを作成するときと同様に、Power Automate からもニュースのページを作成します。次のように設定します。

設定項目設定値
サイトのアドレスニュースを投稿するサイトの URL
方法POST
URI_api/sitepages/pages
ヘッダーcontent-type: application/json;odata=verbose
ボディ以下の通り
{
  "__metadata": {
    "type": "SP.Publishing.SitePage"
  },
  "PromotedState": 1,
  "PageLayoutType": "Article"
}

実行結果は JSON で返ってきます。この中にある新しく作成されたページの「Id」を利用したいので、「JSON の解析」で値を取れるようにしておきましょう。次のようなスキーマーで解析できます。

{
    "type": "object",
    "properties": {
        "d": {
            "type": "object",
            "properties": {
                "__metadata": {
                    "type": "object",
                    "properties": {
                        "id": {
                            "type": "string"
                        },
                        "uri": {
                            "type": "string"
                        },
                        "type": {
                            "type": "string"
                        }
                    }
                },
                "CreatedBy": {
                    "type": "object",
                    "properties": {
                        "__deferred": {
                            "type": "object",
                            "properties": {
                                "uri": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                },
                "LastModifiedBy": {
                    "type": "object",
                    "properties": {
                        "__deferred": {
                            "type": "object",
                            "properties": {
                                "uri": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                },
                "Translations": {
                    "type": "object",
                    "properties": {
                        "__deferred": {
                            "type": "object",
                            "properties": {
                                "uri": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                },
                "AbsoluteUrl": {
                    "type": "string"
                },
                "AuthorByline": {},
                "BannerImageUrl": {},
                "BannerThumbnailUrl": {},
                "CallToAction": {
                    "type": "string"
                },
                "Categories": {},
                "ContentTypeId": {
                    "type": "string"
                },
                "Description": {},
                "DoesUserHaveEditPermission": {
                    "type": "boolean"
                },
                "FileName": {
                    "type": "string"
                },
                "FirstPublished": {
                    "type": "string"
                },
                "Id": {
                    "type": "integer"
                },
                "IsPageCheckedOutToCurrentUser": {
                    "type": "boolean"
                },
                "IsWebWelcomePage": {
                    "type": "boolean"
                },
                "Modified": {
                    "type": "string"
                },
                "PageLayoutType": {
                    "type": "string"
                },
                "Path": {
                    "type": "object",
                    "properties": {
                        "__metadata": {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "type": "string"
                                }
                            }
                        },
                        "DecodedUrl": {
                            "type": "string"
                        }
                    }
                },
                "PromotedState": {
                    "type": "integer"
                },
                "Title": {},
                "TopicHeader": {},
                "UniqueId": {
                    "type": "string"
                },
                "Url": {
                    "type": "string"
                },
                "Version": {
                    "type": "string"
                },
                "VersionInfo": {
                    "type": "object",
                    "properties": {
                        "__metadata": {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "type": "string"
                                }
                            }
                        },
                        "LastVersionCreated": {
                            "type": "string"
                        },
                        "LastVersionCreatedBy": {
                            "type": "string"
                        }
                    }
                },
                "AlternativeUrlMap": {
                    "type": "string"
                },
                "CanvasContent1": {
                    "type": "string"
                },
                "LayoutWebpartsContent": {},
                "SitePageFlags": {
                    "type": "string"
                }
            }
        }
    }
}

ここまでが実行されると、サイトのページ ライブラリには次のようなファイルが出来ています。

仮のファイル名でコンテンツも空白のファイルになっていますね。

コンテンツを入れて仮保存

つぎが一番ややこしくて一番大事な手順です。ページにコンテンツを流し込む処理ですね。

設定項目設定値
サイトのアドレスニュースを投稿するサイトの URL
方法POST
URI_api/sitepages/pages( <Id> )/SavePage
※ <Id> はページ作成処理の結果として出力されたもの
ヘッダーcontent-type: application/json;odata=verbose
ボディ以下の通り
{
    "__metadata": {
      "type": "SP.Publishing.SitePage"
    },
    "LayoutWebpartsContent": "[{\"id\":\"cbe7b0a9-3504-44dd-a3a3-0e5cacd07788\",\"instanceId\":\"cbe7b0a9-3504-44dd-a3a3-0e5cacd07788\",\"title\":\"\\n      タイトル領域\\n    \",\"description\":\"\\n      タイトル領域の説明\\n    \",\"audiences\":[],\"serverProcessedContent\":{\"htmlStrings\":{},\"searchablePlainTexts\":{},\"imageSources\":{\"imageSource\":\"https://cdn.hubblecontent.osi.office.net/m365content/publish/5642d96d-50b6-414f-95fe-ca1c62442700/84307093.jpg\"},\"links\":{},\"customMetadata\":{\"imageSource\":{\"imgWidth\":5256,\"imgHeight\":3508}}},\"dataVersion\":\"1.4\",\"properties\":{\"imageSourceType\":2,\"title\":\"タイトル\",\"textAlignment\":\"Left\",\"showPublishDate\":false,\"authors\":[],\"showTopicHeader\":true,\"authorByline\":[],\"layoutType\":\"CutInShape\",\"topicHeader\":\"トピックヘッダー\",\"enableGradientEffect\":true,\"hasTitleBeenCommitted\":true},\"reservedHeight\":307}]",
    "CanvasContent1": "[{\"controlType\":4,\"id\":\"1212fc8d-dd6b-408a-8d5d-9f1cc787efbb\",\"position\":{\"controlIndex\":2,\"sectionIndex\":1,\"sectionFactor\":12,\"zoneIndex\":1,\"layoutIndex\":1},\"addedFromPersistedData\":true,\"emphasis\":{},\"zoneGroupMetadata\":{\"type\":0},\"innerHTML\":\"<h2>Power Automate の可能性は五大陸を駆け巡る!</h2><p>このニュースは Power Automate から投稿されました。</p>\"},{\"controlType\":0,\"pageSettingsSlice\":{\"isDefaultDescription\":true,\"isDefaultThumbnail\":true}}]",
    "BannerImageUrl": "https://cdn.hubblecontent.osi.office.net/m365content/publish/5642d96d-50b6-414f-95fe-ca1c62442700/84307093.jpg",
    "AuthorByline": [],
    "TopicHeader": "Power Automate",
    "Title": "自動投稿ニュース"
}

ここまで処理が終わると、ファイル名も決まり、ページを開くとコンテンツも表示される状態になっています。

ところで、ボディの中身が複雑すぎますよね。これを一から作成するのは大変なので、SharePoint サイトで作成したページの内容をキャプチャしましょう。

コンテンツを SharePoint サイトからキャプチャする

まずは、Microsoft Edge を用いて SharePoint サイトでニュースを作成し、編集画面を開いておきましょう。そしてこのとき、開発者ツールを開き、[ネットワーク] タブを表示させておきます。

この状態のまま、SharePoint 側でページを [下書きとして保存] をクリックします。

キャプチャされたデータの中から「SavePageAsDraft」を探して開き、「Payload」タブを確認すると表示されるデータが、SharePoint ページ上のコンテンツを表現しているものになります。Visual Studio Code などにコピペしておきましょう。

主に修正するのは Title の値と、CanvasContent1 の値です。

まず、Title については、新しく作成したいページの名前に変更しましょう。

CanvasConent1 については、さらにその中に「innerHTML」があるので、ここを流し込みたいコンテンツに変更します。もっと調査を進めていけば、SharePoint の Web パーツなどを差し込めるかもしれませんが、ここから先は機会があれば調べてみたいと思います。

と、こんな形で作成していきます。かなり骨が折れる作業です。

ニュースの発行

あとは、作成されたニュースの記事を発行するだけです。

設定項目設定値
サイトのアドレスニュースを投稿するサイトの URL
方法POST
URI_api/sitepages/pages( <Id> )/publish
※ <Id> はページ作成処理の結果として出力されたもの
ヘッダーcontent-type: application/json;odata=verbose
ボディ以下の通り
{
  "__metadata": {
    "type": "SP.Publishing.SitePage"
  }
}

はい。これでサイトにニュースが投稿できました。

いやはや、なかなか大変でした。

作成したページの情報を取得

(2021/21/22 追記)ちなみに、作成したページの情報を API で取得するときには次のようにします。

設定項目設定値
サイトのアドレスニュースを投稿するサイトの URL
方法GET
URI_api/sitepages/pages( <Id> )
※ <Id> はページ作成処理の結果として出力されたもの
ヘッダーなし
ボディなし

JSON が返ってくるので、例のごとく解析して情報を利用しましょう。

利用例

さて、何に利用しようかなと思案したのですが、まずは、先日投稿した Google ニュースの RSS をまとめた情報を利用し、定期的に SharePoint にニュースとして投稿してみるのも良いかと思いました。

Power Automate を使って月曜朝に先週のニュースをまとめ読みする
https://idea.tostring.jp/?p=6279

次のようなフローができました。

ちょっと見た目に関する部分も研究して、次のようなニュースを投稿できました。

なかなか良いのではないでしょうか?

さいごに

かなり大変なことは分かりましたが、なんとか Power Automate からニュースを投稿することができました。何かしらの情報を集めて、SharePoint にニュースとして掲載し、社内と共有する…、そんなシーンで活用できるかもしれません。

できるということを知れたというだけでも成果ですね。お疲れさまでした。