【初心者向け】Power Automateで注意したいこと

今回の記事では、一応プログラミング言語を触った経験がある私がPower Automateの変数やループを使っていて「できないんか～い」と思ったことなどをまとめます。
またPower Automateの変数には日付型が存在しないため、こちらについても少しまとめていきます。

# ➊変数について
## ⑴変数に値を代入するとき値の自己参照ができない
Power Automateのアクション「変数を設定」で宣言済の変数に値を代入するとき、x = x + 1といったような値の自己参照ができません。
ループ制御のためにカウンタ変数をカウントアップしたい…などといった、単純な加算・減算などを行いたい場合は「変数の値を増やす/減らす」アクションも使えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/504e18f7-a2a6-5717-16f2-3936df9e9d40.png)
ただし、「変数の値を増やす」のアクションの「値」パラメータで「-1」としても1カウントアップされるだけなので「変数の値を増やしたいのか？減らしたいのか？」注意しましょう。

**こんな工夫が必要かも**
ロジックによっては「変数の値を増やす/減らす」アクションでは対応しきれない場合があります。このような場合は<b>退避用の変数</b>を宣言しましょう。
イメージとしては以下のような感じです。
x = x + 1 を行うとき…
① x = 1 があったとする。
② 退避用変数x'を宣言し、x'= x でxの値を代入する。この結果、 x' = 1
③ x = x' + 1を実行する。
④③の結果、x = x + 1と同じ実行結果になる。

## ⑵変数の宣言(アクション「変数の初期化」)の位置に注意！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/b2e2f2e9-c3aa-b657-95ea-78b38beaa6c1.png)
Do~Untilや条件分岐などといった**スコープの中で変数を宣言することができません。**（値の代入(アクション「変数の設定」の使用)は可）

## ⑶「変数を設定する」アクションで文字列変数を空にできない！
ループ処理中に文字列変数を初期化したい場合は値に半角空白を入れて代用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/0c4bdb28-ede9-9085-3bf4-dbaff27d1dfe.png)

【結果】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/8b11f72e-d494-28d4-8f3d-ad114b6e6380.png)

::: note warn
厳密には空にはできていません。
:::


# ➋Do~Untilのループを抜ける条件
ループ処理から抜ける条件に複数の条件を設定したい場合があると思います。「条件Aがtrueまたは条件Bがfalseのとき」…みたいな感じです。
基本モードでは一つの変数の値しか設定できないように一見なっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/ef8e3963-4a1f-95f7-4a97-248c2bdaa1ac.png)
**こんな工夫が必要**
複数の条件に従わせる場合、<b>or(and)関数とequals関数を使用して一つの条件式になるように設定する必要があります。</b>
【例】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/f9cd4e3a-dc5b-d8e8-457d-47d360243c2f.png)
…動的なコンテンツの追加をクリックし、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/c41ba8d2-2135-20ec-4f5f-ed0c23916c52.png)
式を以下のように変更します。
`@equals(or(equals(条件A, true), equals(条件B, false)), true)`
※条件Aや条件Bもtrue/falseで結果が返ってくるようになっています。
先頭で使用している関数equalsは、期待する結果がtrueの場合以下のように省略することもできます。
`or(equals(条件A, true), equals(条件B, false))`

**参考**

https://qiita.com/kojisaiki/items/b5302d7e1adad19780f2

https://blog-tips.sekenkodqx.jp/2020/07/16/power-automate-bool-variable/

>論理関数に組み込む
論理関数にブール変数を含めることも可能です。
これによる複雑は判断を最小限の条件コントロールで実現可能です。


# ❸日時について
## ⑴「現在の時刻」取得アクションで取得した時刻は日本の現在時刻ではない
見出しの通りです。「現在の時刻」取得アクションで取得した時刻は協定世界時間になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/1cdca6ba-dc61-4171-9fdf-458915c3e1f8.png)

https://mokudai.jp/knowledge-base/power-automate/automate-convert-time-utc2japantime/#:~:text=Power%20Automate%20%E3%81%A7%E6%89%B1%E3%81%86%E6%97%A5%E6%99%82%E3%81%AFUTC%EF%BC%88%E4%B8%96%E7%95%8C%E6%A8%99%E6%BA%96%E6%99%82%EF%BC%89%E3%81%A7%E3%81%99%E3%80%82.%20%E3%81%A7%E3%82%82%E6%88%91%E3%80%85%E3%81%8C%E6%89%B1%E3%81%84%E3%81%9F%E3%81%84%E3%81%AE%E3%81%AF%E6%97%A5%E6%9C%AC%E6%A8%99%E6%BA%96%E6%99%82,%28UTC%2B9%29%E3%81%A7%E3%81%99%E3%80%82.%20%E3%81%AA%E3%81%AE%E3%81%A7UTC%E3%82%92UTC%2B9%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%82%92%E7%B4%B9%E4%BB%8B%E3%81%97%E3%81%BE%E3%81%99%E3%80%82.%20%E3%81%A1%E3%81%AA%E3%81%BF%E3%81%AB%E3%80%81Office%20365%20%E3%81%AE%E3%83%86%E3%83%8A%E3%83%B3%E3%83%88%E8%A8%AD%E5%AE%9A%E3%81%A8%E3%81%8B%E3%81%9D%E3%81%86%E3%81%84%E3%81%A3%E3%81%9F%E5%85%A8%E4%BD%93%E7%9A%84%E3%81%AA%E8%A8%AD%E5%AE%9A%E3%81%A7%E6%97%A5%E6%9C%AC%E6%A8%99%E6%BA%96%E6%99%82%E3%81%AB%E5%9B%BA%E5%AE%9A%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%81%AF%E7%8F%BE%E5%9C%A8%E3%81%AE%E3%81%A8%E3%81%93%E3%82%8D%E3%81%AA%E3%81%84%E3%82%88%E3%81%86%E3%81%A7%E3%81%99%E3%80%82

**こんな工夫が必要**
日本の時間を取得するには「現在の時刻」取得アクションに「タイムゾーンの変換」アクションを組み合わせる必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/a039c55e-4f28-61a5-d97e-6576ce0d84eb.png)
【実行結果】
実行結果を見ると世界協定時間に9時間追加されて日本のタイムゾーンで時刻が取得されたことが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/c87f0707-647e-2cdc-6a63-37cc6b0b416c.png)

【2022/03/07 追記】
また、**スケジュールフローを実行する場合もタイムゾーンの指定に注意**を払う必要があります。

https://qiita.com/fsgwmhr/items/b86b7618edbdc40d6a01

### 式で現在の日時を取得する場合
使用するアクションの数を減らしたい場合、utcnow()関数とconvertFromUtc関数を組み合わせた式を利用することができます。
```convertFromUtc(utcNow(),'Tokyo Standard Time','yyyy-MM-dd')```

https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#convertfromutc

convertFromUtc関数の第2引数はタイムゾーンを指定します。利用できる値は[Microsoft公式「既定のタイムゾーン」記事](https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones?view=windows-11)から調べることができます。

::: note warn
なお、上記の「既定のタイムゾーン」の記事には日本語のページが存在しますが、日本語ページの日本語訳されてしまったタイムゾーンを式に入れても失敗するので必ず英語サイトで調べて利用してください。
:::

## ⑵変数を宣言するとき、日付型が無く文字列を日付型に変換することもできない
小見出しの通りです。
ただし、日付と時刻を操作する関数を使用することは可能です。次のMicorosoftのページを参考にしてください。

https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#date-and-time-functions


**こんな工夫が必要かも**
日付の加算・減算などには以下のいずれかの方法で行います。

➊日付の減算には日付に関するアクションを使用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/cf11e3c0-241b-3df5-14fb-faa1aaf6c931.png)
【使用例】1日加算してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/5dd5831d-cf94-c209-5265-e0781b227fa2.png)
【実行結果】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/b9ad4f1e-e747-a19a-73c8-89ebf0138cc3.png)

➋文字列型の変数で、式を使用する
「変数の設定」アクション、または「変数を初期化するアクション」を使用して値を以下のような式に設定します。 
`addDays(variables('2021/12/24'), -2)` 
暗黙の型変換を行っているみたいでなんだか気持ち悪いのですが、これで動きます。

:::note info 
**変換後の日時の形式について**
なお、上記の式では変換前の数値は"yyyy/MM/dd"形式で表記されていますが、<b>addDays関数を実行した後は日付の文字列</b>時刻もくっついてきます</b>。
【例】`2021-12-24T01:00:01.1141290Z`

不要な場合はfotmatDateTime関数で"yyyy/MM/dd"形式に直しましょう。
:::
【例】
`formatDateTime(addDays(variables('通知日'), -1), 'yyyy/MM/dd')`

※日時形式文字列について

https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/custom-date-and-time-format-strings

必要に応じて日時の形式を直す必要があるのは「1. 日付の減算には日付に関するアクションを使用する。」方法でも同様です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/648c2de4-3064-bc49-66dd-25f48df5d432.png)

## ⑶日付同士の減算を行うには
**方法**

1. 対象の日付を**ticks関数**で変換する
1. 上記手順で変換した日数同士をsub関数で減算し、その結果をdiv関数を使い**864000000000で**割る。

```
int(div(sub(ticks(variables('終了日')),ticks(variables('開始日'))),864000000000))
```
### 何故864000000000で割るのか
**そもそもticks関数とは何なのか**

https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#ticks

ticks関数は対処の日付のタイムスタンプを[ticksプロパティ](https://docs.microsoft.com/ja-jp/dotnet/api/system.datetime.ticks?view=net-6.0)に変換する関数です。そこでticksプロパティとは何なのかと公式の説明を見ると以下のように説明されています。
>1 ティックは、100 ナノ秒または 1,000 万分の 1 秒を表します。 ミリ秒単位には1万ティックがあります (「」を参照 TicksPerMillisecond )。2番目のタイマー刻みは1000万ティックです。

上記の説明から1日は何ティックなのかを換算すれば何故864000000000で割るのかが理解することができます。

|  | 1秒=10000000ティック | 1分=60秒 | 1時間=60分 |1日=24時間
|--|--|--|--|--|
|ティックで換算→|10000000|600000000|36000000000|**864000000000**|

**参考**

https://www.fixes.pub/program/169550.html#:~:text=PowerAutomate%E3%81%A72%E3%81%A4%E3%81%AE%E6%97%A5%E4%BB%98%E3%81%AE%E5%B7%AE%E3%82%92%E8%A8%88%E7%AE%97%E3%81%99%E3%82%8B%E7%B0%A1%E5%8D%98%E3%81%AA%E9%96%A2%E6%95%B0%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82%20%E4%BB%A3%E3%82%8F%E3%82%8A%E3%81%AB%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%93%E3%81%A8%E3%81%AF%20ticks%EF%BC%88%EF%BC%89%E9%96%A2%E6%95%B0%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%80%81%E9%96%8B%E5%A7%8B%E6%97%A5%E3%81%AEvarStartDateTicks%E3%81%A8%E3%81%84%E3%81%86%E6%95%B4%E6%95%B0%E5%9E%8B%E3%81%AE%E5%A4%89%E6%95%B0%E3%82%92%E4%BD%9C%E6%88%90%E3%81%97%E3%81%BE%E3%81%99%E3%80%82%20ticks,%28triggerBody%20%28%29%3F%20%5B%27StartDate%27%5D%29%20ticks%EF%BC%88%EF%BC%89%E9%96%A2%E6%95%B0%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%80%81%E7%B5%82%E4%BA%86%E6%97%A5%E3%81%AEvarEndDateTicks%E3%81%A8%E3%81%84%E3%81%86%E6%95%B4%E6%95%B0%E5%9E%8B%E3%81%AE%E5%A4%89%E6%95%B0%E3%82%92%E4%BD%9C%E6%88%90%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

# 終わりに
以上です。こちらの記事をご覧になった方の役に少しでも立っていれば幸いです。