日本の伝統的な通達文書をPower Appsで作成する

# はじめに 

歴史の長い企業では、人事異動を中心に通達という香ばしいものを`メール`や*PDF*で配信する企業が多いのではないでしょうか。
伝統的な業務です。なかなか変えがたくなるハードルも生まれるでしょう。

大した手間も発生しないということから、業務課題に感じず、そのまま運用しているケースもあるのではないでしょうか？
「テンプレートの文章を編集し、一部の情報を置き換えるだけだから」といってそのままにしておくことも、あまり褒められたものではないでしょう。チリツモで負担は溜まっていきます。こういった細かな業務こそ、効率化はじめの一歩に適しているのでは？と思います。

今回は、*Power Apps*で**通達文書を作成するアプリ**を考えてみました。

:::note info
 - そもそもそのような運用やめようという観点はなしでお願いします
:::

<iframe width="560" height="315" src="https://www.youtube.com/embed/qCeX_0YNJL0?si=8JyCAFofN8KQYlhE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

# 通達のイメージ

今回の通達文書は、人事異動をテーマにしたものです。具体的には、以下のような文章をイメージしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/f839f4a7-f062-7b8c-4849-a71e0cfe3b1f.png)

伝統的な企業ではよく見られる形式だと思います。
- 右上に発行日付
- お決まりの左から始まる従業員各位
- また右端に戻って会社名、部長名
- 書類の名前
- メールのような挨拶文
- 表形式で旧部署と新部署が並ぶ

私の想像です。あくまで私の想像です。
~~こういった文書を一太郎で作成するまでがテンプレートだと思っています~~

# *Power Apps*でのアプローチ

この通達文書を作成するために、*Power Apps*では以下のような機能で対応を考えてみました。

- DraftScreen
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/05dd369c-0029-11c5-1581-1309fd96b51d.png)

- PreviewScreen
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/ce17c2c6-a9a0-0a2a-3a19-f5cc62c4ad82.png)

- DraftScreen(入力画面)
    - ScreenContainer1 - 垂直コンテナー
        - HeaderContainer1 - 水平コンテナー
            - Header1 - ヘッダー コントロール
        - BottomContainer1 - 水平コンテナー
            - SidebarContainer1 - 垂直コンテナー
                - galUser - 垂直ギャラリー
                    - Container1 - デザイン用のコンテナ
                        - imgUser 社員の画像
                        - lblName - 社員の名前
                        - lblDept - 社員の部署
                        - newDept - 移動先の入力
                - BadgeCanvas1 - バッジコントロールで映えを狙う
                    Control: Badge
            - MainContainer1 - HTMLテキストの格納する垂直コンテナー
                - txtHTML - HTML テキスト コントロール
                - btnSubmit - 画面遷移用のボタン
- PreviewScreen:
    Variant: printableLayout_A4Portrait_ver2.0
    - PDFContainer - HTMLテキストを挿入するコネクタ、PDFのソース
        - PreviewHTML:
            Control: HTML テキスト コントロール
    - PrintContainer - 水平コンテナー
        - PDFTitle - 画面のタイトル
        - btnPDF - PDF保存用のボタン
        - LinkCanvas1 - 保存されたPDFを表示するリンク

## 機能の詳細
- *Office 365 Users*コネクタによって、社員情報を`ギャラリー コントロール`で一覧にし、異動先部署を入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/75d2d4c3-016c-3389-d082-29846ab680c1.png)

`ギャラリー コントロール`の`Items`プロパティには、[Office 365 Usersコネクタでユーザー情報を表示しています。](https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/connections/connection-office365-users
)

関数は下記のようになります。

```plaintext:items
Office365ユーザー.SearchUserV2({isSearchTermRequired:false}).value
```

:::note info
`isSearchTermRequired`は`true`が既定です。
`false`を設定しない場合、検索文字列がない限り表示されません。
:::

ユーザーの写真は丸みを帯びたデザインにし、`テキスト ラベル`を並べるだけです。移動先の部署を入力するために`テキスト インプット`を配置します。

# ギャラリー コントロールの値に応じた動的なHTML テキストの作成
肝になるのは`メイン コンテナー`の`HTML テキスト コントロール`です。`HTML テキスト コントロール`は関数芸です。

```plaintext:HtmlText
$"<div style='text-align: right; margin-bottom: 20px;'>
    <p>{Today()}</p>
</div>
<div style='text-align: left; margin-bottom: 20px;'>
    <p>従業員各位</p>
</div>
<div style='text-align: right; margin-bottom: 20px;'>
    <p>出戻りコーポレーションホールディングス株式会社<br>人事部長　荒賀　翼</p>
</div>
<div style='text-align: center; margin-bottom: 20px;'>
    <h1 style='margin: 0; font-size: 24px;'>人事異動社内通知書</h1>
</div>
<div style='margin-bottom: 20px;'>
    <p>{Today()}付で下記の人事異動が発令されましたので、お知らせします。</p>
</div>
<table border='1' cellpadding='5' cellspacing='0' style='width: 100%; border-collapse: collapse; margin-bottom: 20px;'>
    <thead>
        <tr>
            <th style='text-align: left; padding: 8px;'>氏名</th>
            <th style='text-align: left; padding: 8px;'>新部署</th>
            <th style='text-align: left; padding: 8px;'>旧部署</th>
        </tr>
    </thead>
    <tbody>
        {Concat(
    Filter(
        ForAll(
            galUser.AllItems,
            {
                氏名: DisplayName,
                旧部署: Department,
                新部署: ThisRecord.newDept.Value
            }
        ),
        !IsBlank(新部署)
    ),
    $"<tr><td style='padding: 8px;'>{氏名}</td><td style='padding: 8px;'>{新部署}</td><td style='padding: 8px;'>{旧部署}</td></tr>"
)}
    </tbody>
</table>"
```

データソースの評価は、下記の部分ですね。
```javascript
Filter(
    ForAll(
        galUser.AllItems,
        {
            氏名: DisplayName,
            旧部署: Department,
            新部署: ThisRecord.newDept.Value
        }
    ),
    !IsBlank(新部署)
)
```


[ForAll 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-forall)を使ってギャラリー`AllItems`プロパティから`HTML テキスト コントロール`の値を設定します。

これによって動的に`ギャラリー コントロール`の入力情報から文書が作成されるロジックです。

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-forall

こちらに[Filter 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-filter-lookup)を使って入力されている人だけ反映されるようにしています。

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-filter-lookup

テキスト インプットを使っているため、[IsBlank 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-isblank-isempty)による空白か否かの判定ロジックを設定していますが、チェックボックスのコントロールで判定する方法が個人的には好きです。

:::note info
[動的なHTMLテーブルの作成について過去に書いていますので、ぜひご覧ください。](https://qiita.com/DEmodoriGatsuO/items/a160994360cb34399fdc)
:::

https://qiita.com/DEmodoriGatsuO/items/a160994360cb34399fdc

# PDFの発行

次に[PDF 関数](https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/how-to/pdf-function)を使ってファイルのバイナリを取得し、*Power Automate*を使って*SharePoint*にアップロードします。

:::note warn
PDF関数は試験段階の機能です

Power Automateは下記のとおりです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/76d65204-7ffb-cb9f-3a55-25564216627f.png)

 - ファイルの作成
     - Power Appsからファイル名を設定 - `@{triggerBody()?['file']?['name']}`
     - PDF関数の戻り値を渡す - `@{triggerBody()?['file']?['contentBytes']}`
:::

アップロード先のリンクURLを*Power Apps*に戻し、印刷画面を用意することで便利に作成できます。

```plaintext:OnSelect
UpdateContext(
    {
        pdfLink: PowerAppsPDFCreate.Run(
            {
                name: Text(
                    Now(),
                    "yyyymmdd_hhmmss" // ファイル名を現在日時で設定
                ) & ".pdf",
                contentBytes: PDF(PDFContainer)
            }
        )
    }
);

```

実際に入力してみると、文字の動的な変更が確認できます。

### 固定的な文字を増やす
荒業ですが、固定的な文章も入力に応じて増やせます。
下記は入力された項目に応じて

```
【対象社員】{氏名}
【旧部署】{旧部署}
【新部署】{新部署}
```
のフォーマットで情報が表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/e764c5f7-1f9a-d6f6-0e39-870c15e988f4.png)

関数はコチラ！

```plaintext:Text
Concat(
    Filter(
        ForAll(
            galUser.AllItems,
            {
                氏名: DisplayName,
                旧部署: Department,
                新部署: ThisRecord.newDept.Value
            }
        ),
        !IsBlank(新部署)
    ),
    $"【対象社員】{氏名}
【旧部署】{旧部署}
【新部署】{新部署}

"
)
```

このように、伝統的な通達文書の作成も*Power Apps*を使うことで効率化できます。ぜひ試してみてください。

# おわりに
ちょこっとした改善?テクニックを載せてみました。
ご参考までに。