【Power Automate Desktop】特定のフォルダとそのサブフォルダ(任意の複数階層)をコピーする
- 1.やりたいこと
- 2.実践① フロー作成 ~ 新しいフォルダの作成
- 3.実践② Switch条件の設定 ~ 各階層サブフォルダの作成ループ処理
- 4.実践③ コピー階層の選択2と1の場合(それぞれサブフローを設定)
- 5.フローの実行/確認
1.やりたいこと
みなさん、自身のPCのフォルダはどのように管理しているでしょうか。
私は下図のように会計年度毎に各項目に分けてフォルダ管理することが多いのですが、これまでは当年度が終わる前に翌年度用のフォルダをまた一から作り直していました。よくよく考えたらこれはすごく無駄な作業だと思います。かといって、当年度のフォルダをまるまるコピーするとその中のすべてのドキュメントもコピーされてしまい、時間をかけてコピーした後にファイルを削除するというかなりの手間が掛かってしまいます。はじめから数年分の空フォルダを作っておいても1年の間でフォルダ体系は変わってしまいます。
そこで、今回PADを使って同じ体系のままフォルダのみをコピーする仕組みを考えてみました。
長くなりますので、全体の流れとポイントを要約したものを下図にまとめました。
2.実践① フロー作成 ~ 新しいフォルダの作成
トップ画面から、新しいフローをクリックします。
任意の名前を付けて作成ボタンをクリックします。
画面左のアクション一覧からフォルダ→特別なフォルダーを取得 をダブルクリック(又は真ん中のフロー詳細へドラッグ&ドロップ)します。このアクションは以降のファイル選択等の際に「初期フォルダ」を設定するために変数化しておくものです。
ここでは、特別なフォルダ―の名前: デスクトップ を選択します。特別なフォルダーのパス:は自身のデスクトップのパスが自動設定されます。生成された変数はデフォルトの SpecialFolderPath のままとし、保存します。
【コピー対象フォルダを選択をするためのダイアログ設定】
アクション一覧 → メッセージボックス → ファイルの選択ダイアログを表示 をダブルクリックします。
下図の通り入力し保存します。
ダイアログの説明: コピー対象のフォルダを選択(任意のテキスト)
初期フォルダ:%SpecialFolderPath% (右端の{X}をクリックし、変数名を選択)
フォルダ―選択ダイアログを常に手前に表示する:オン
生成された変数:デフォルトの SelectedFolder を CopyFolder に変更します。変数名は後続の処理を考慮して極力わかりやすい名前にしておいた方がよいです。変数ButtonPressedは今回特に使用しませんのでデフォルトのままとします。
【コピー対象フォルダのサブフォルダ(1階層目)のフォルダを取得】
アクション一覧 → フォルダ― → フォルダ―内のサブフォルダーを取得 をダブルクリックします。
下図の通り入力し保存します。
フォルダ―:%CopyFolder% (右端の{X}をクリックし、変数名を選択)
フォルダ―フィルター:*(デフォルトのまま)
サブフォルダーを含める:オフ
※ここをオンにしてしまうと、1階層目に2階層目以降のフォルダが含まれてしまうため、必ずオフにする必要があります。
生成された変数:SubFolders に変更します。
【コピー階層選択用のリストを設定】
アクション一覧 → 変数 → {x}変数の設定 をダブルクリックします。
下図の通り入力し保存します。
設定: SelectList (任意の変数名)
宛先: %[3,2,1]% と入力。
変数をリストにする場合は、値を [] で括り , で区切る必要があります。リストの順は%[1,2,3]%でもよいのですが、使用頻度を考慮して今回は降順にしています。
【コピー階層選択用のリストダイアログを設定】
アクション一覧 → メッセージボックス → リストから選択ダイアログを表示 をダブルクリックします。
下図の通り入力し保存します。
ダイアログのタイトル:コピー対象フォルダの階層数選択(任意)
ダイアログメッセージ:コピー対象フォルダに含まれるサブフォルダのうち、何階層目までをコピーするか選択してください。(1~3) (任意)
選択元のリスト: %SelectList% (右端の{X}をクリックし、変数名を選択)
選択ダイアログを常に手前に表示する:オン
リストに制限:オン
空の選択を許可:オフ
複数の選択を許可:オフ
生成された変数: SelectedItem(デフォルトのまま)、SelectedIndex と ButtonPressed3は今回使用しないためこちらもデフォルトのままで結構です。
【新規コピー先のフォルダ名の入力ダイアログ設定】
アクション一覧 → メッセージボックス → 入力ダイアログを表示 をダブルクリックします。
下図の通り入力し保存します。
入力ダイアログのタイトル:コピー先のフォルダ名を入力(任意)
入力ダイアログメッセージ:ブランク(必要に応じて任意入力)
規定値:ブランク
入力の種類: 1行(デフォルトのまま)
入力ダイアログを常に手前に表示する:オン
生成された変数 NewFolderName に変更します。ButtonPressed2は今回使用しない為デフォルトのままで結構です。
【新規コピー先のフォルダの作成】
アクション一覧 → フォルダー → フォルダ―の作成 をダブルクリックします。
下図の通り入力し保存します。
新しいフォルダーを次の場所に作成:%CopyFolder.Parent% と入力。
※プロパティ「.Parent」を使用します。これにより、CopyFolder の親フォルダ、つまり、コピー元フォルダと同じ場所に新しいフォルダーが作成されることになります。
新しいフォルダー名: %NewFolderName %(右端の{X}をクリックし、変数名を選択)
ここまでで作成したフローは下図の通りとなります。
3.実践② Switch条件の設定 ~ 各階層サブフォルダの作成ループ処理
ここから各階層ごとにフォルダのコピーを行う設定をしていきます。
【コピー階層の選択結果に応じた条件の設定】
恐らく If条件でも設定できると思いますが、折角なのでSwitch条件を使ってみました。ExcelのSwitch関数と同じ考え方だと思います。
アクション一覧 → 条件 → Switch をダブルクリックします。
下図の通り入力し保存します。
チェックする値:%SelectedItem%(右端の{X}をクリックし選択)
【コピー階層選択が3(階層)の場合を設定】
アクション一覧 → 条件 → Case をダブルクリックします。
下図の通り入力し保存します。
演算子: と等しい(=) を選択
比較する値: 3 を入力
【フォルダ作成(1階層目)のループ処理】
アクション一覧 → ループ → For each をダブルクリックします。
変数SubFoldersを変数CurrentItemに入れ、CurrentItemの数分フォルダのコピーを繰り返します。
下図の通り入力し保存します。
反復処理を行う値: %SubFolders% (右端の{X}をクリックし選択)
生成された変数: CurrentItem (デフォルトのまま)
【1階層目処理を示すコメントを設定】
任意ですが、後続の処理でわかりやすいようにコメントを入れておきます。
アクション一覧 → フリーコントロール → コメント をダブルクリックします。
コメント:任意のコメントを入力し保存します。
【新規フォルダにサブフォルダ(1階層目)をコピーするためのフォルダ名取得】
アクション一覧 → テキスト → テキストを置換する をダブルクリックします。
下図の通り入力し保存します。
解析するテキスト:%CurrentItem% (右端の{X}をクリックし選択)
検索するテキスト:%CopyFolder% (右端の{X}をクリックし選択)
検索と置換に正規表現を使う:オフ
大文字と小文字を区別しない:オフ
置き換え先のテキスト: %''% を入力
※ブランクに置き換えたいのですが、ここをブランクにするとエラーとなるので、このように%’’%(シングルクオーテーション2つ)を入力します。
生成された変数: NewSubFolderName に変更します。
以下、実際に最初に変数に入る値を例として補足します。
① 解析するテキスト:CurrentItem → C:\Desktop\2020年度\00_日時関係
② 検索するテキスト:CopyFolder → C:\Desktop\2020年度
③ ①の中の②をブランクにする。 → \00_日時関係
となります。ただ、このままだと頭に余計な \ が残ってしまうので次のアクションで取り除きます。
再び、アクション一覧 → テキスト → テキストを置換する をダブルクリックします。
下図の通り入力し保存します。
解析するテキスト:%NewSubFolderName% (右端の{X}をクリックし選択)
検索するテキスト: \
検索と置換に正規表現を使う:オフ
大文字と小文字を区別しない:オフ
置き換え先のテキスト: %''% を入力
生成された変数: NewSubFolderName として変数を上書きします。
【 新規フォルダにサブフォルダ(1階層目)を作成】
アクション一覧 → フォルダー → フォルダ―の作成 をダブルクリックします。
下図の通り入力し保存します。
新しいフォルダを次の場所に作成:%Newfolder% (右端の{X}をクリックし選択)
新しいフォルダ名: %NewSubFolderName% (右端の{X}をクリックし選択)
生成された変数: NewSubfolder に変更します。
【2階層目処理を示すコメントを設定】
任意ですが、後続の処理でわかりやすいようにコメントを入れておきます。
アクション一覧 → フリーコントロール → コメント をダブルクリックします。
コメント:任意のコメントを入力し保存します。
【1階層目のサブフォルダ(2階層目)を取得】
アクション一覧 → フォルダ― → フォルダ―内のサブフォルダーを取得 をダブルクリックします。
下図の通り入力し保存します。
フォルダ―: %CurrentItem% (右端の{X}をクリックし選択)
フォルダ―フィルター:*(デフォルトのまま)
サブフォルダーを含める:オフ
生成された変数: SubFolders2 に変更します。
前述の例だとこのCurrentItemは C:\Desktop\2020年度\00_日時関係
となります。つまり、00_日時関係 のサブフォルダ(2階層目)が取得されることになります。
【フォルダ作成(2階層目)のループ処理】
アクション一覧 → ループ → For each をダブルクリックします。
変数SubFolders2を変数CurrentItem2に入れ、CurrentItem2の数分フォルダのコピーを繰り返します。
下図の通り入力し保存します。
反復処理を行う値: %SubFolders2% (右端の{X}をクリックし選択)
生成された変数: CurrentItem2 (デフォルトのまま)
【新規フォルダのサブフォルダ(1階層目)にサブフォルダ(2階層目)をコピーするためのフォルダ名取得】
アクション一覧 → テキスト → テキストを置換する をダブルクリックします。
下図の通り入力し保存します。
解析するテキスト:%CurrentItem2% (右端の{X}をクリックし選択)
検索するテキスト:%CurrentItem% (右端の{X}をクリックし選択)
検索と置換に正規表現を使う:オフ
大文字と小文字を区別しない:オフ
置き換え先のテキスト: %''% を入力
生成された変数: NewSubFolderName2 に変更します。
以下、前述と同様に実際に最初に変数に入る値を例として補足します。
①解析するテキスト:CurrentItem2→C:\Desktop\2020年度\00_日時関係\00_未処理事項
②検索するテキスト:CurrentItem → C:\Desktop\2020年度\00_日時関係
③ ①の中の②をブランクにする。 → \00_未処理事項
となります。ただ、このままだと頭に余計な \ が残ってしまうので次のアクションで取り除きます。
再び、アクション一覧 → テキスト → テキストを置換する をダブルクリックします。
下図の通り入力し保存します。
解析するテキスト:%NewSubFolderName2% (右端の{X}をクリックし選択)
検索するテキスト: \
検索と置換に正規表現を使う:オフ
大文字と小文字を区別しない:オフ
置き換え先のテキスト: %''% を入力
生成された変数: NewSubFolderName2 として変数を上書きします。
1階層目の時はこの置換まででうまくいったのですが、2階層目以降はこの置換までで実行するとなぜか余計な空白が含まれた状態となってしまい実行時エラーとなります。そのため、次のトリミング処理を追加します。
アクション一覧 → テキスト → テキストのトリミング をダブルクリックします。
下図の通り入力し保存します。
トリミングするテキスト: %NewSubFolderName2% (右端の{X}をクリックし選択)
トリミング対象: 先頭と末尾の空白文字 を選択します。
【 新規フォルダにサブフォルダ(2階層目)を作成】
アクション一覧 → フォルダー → フォルダ―の作成 をダブルクリックします。
下図の通り入力し保存します。
新しいフォルダを次の場所に作成:%NewSubfolder% (右端の{X}をクリックし選択)
新しいフォルダ名: %NewSubFolderName2% (右端の{X}をクリックし選択)
生成された変数: NewSubfolder2 に変更します。
ここからは3階層目の設定になりますが、2階層目の設定と同じ内容となりますので画面のみの貼り付けとし、説明は省略します。
ここまでで3階層目のフォルダコピー処理が完了です。ここで設定したフローは以下の通りです。
4.実践③ コピー階層の選択2と1の場合(それぞれサブフローを設定)
次に最初のコピー階層の選択で2、1を選択した場合の分岐処理を設定していきます。単純にそれぞれのケース毎に先ほどのアクションを減らしたものを追加してもよいのですがフロー全体がかなり長くなってきたこともありますので、それぞれのケース毎にサブフローを設定することにします。
【コピー階層選択が2(階層)の場合を設定】
アクション一覧 → 条件 → Case をダブルクリックします。
下図の通り入力し保存します。
演算子: と等しい(=) を選択。
比較する値: 2 を入力。
次に画面上の サブフロー をクリックします。
+ 新しいサブフローをクリックします。
任意のサブフロー名を入力し保存します。
今回は、Subflow_1_Case_2 とします。
Mainフロータブの隣に新しいサブフロータブが作成されました。
次に一旦Mainフローに戻り、下図の通りCase3の次の For eachアクションからCase2の前のEndまでを選択し、Ctrl+C(又は右クリックでコピーを選択)でコピーします。
サブフロータブをクリックし、Ctrl+V(又は右クリック→貼り付け)で貼り付けます。
コメント(3階層目)から次のEndまでは不要となりますので下図の通り選択し削除します。
Subflow_1_Case_2 はこれで完了です。下図の通りのフローとなります。
再び、Mainフローに戻ります。Case2の下に作成したサブフローの実行を設定します。
アクション一覧 → フリーコントロール → サブフローの実行 をダブルクリックします。
Subflow_1_Case_2 を選択し保存します。
Case2の下にサブフローの実行が設定されました。
【コピー階層選択が1(階層)の場合を設定】
アクション一覧 → 条件 → Case をダブルクリックします。
下図の通り入力し保存します。
演算子: と等しい(=) を選択。
比較する値: 1 を入力。
この後のサブフローの設定は先ほどほぼ同じで、最後に削除する部分が増えるだけですので説明は省略します。
Subflow_1_Case_1 のフローは下図の通りとなります。
Mainフローの末尾は次の通りとなります。
これですべてのフローの設定は完了となります。設定したMainフロー全体は下図の通りです。
5.フローの実行/確認
【フローの実行】
詳細設定画面から実行するとデバッグモードで実行され時間が掛かる為、作成したフローを一旦保存後に閉じて、トップ画面から実行します。
コピー対象フォルダ選択ダイアログが表示されるので対象フォルダを選択し、OKをクリックします。
次にコピー対象フォルダの階層数選択ダイアログが表示されます。今回は3を選択し、OKをクリックします。
続いて、コピー先のフォルダ名入力ダイアログが表示されるので、任意の名称を入力しOKをクリックします。今回は 2021年度 とします。
その後、コピー処理が実行されます。わずか2秒で完了しました。
【結果の確認】
コピー元のフォルダ 「2020年度」と同じ場所に「2021年度」が作成されました。
ドリルダウンしてみると、1階層目のフォルダが作成されています。
更に1階層目の「00_日時処理」をドリルダウンします。
2階層目のフォルダも作成されています。
更に2階層目の「00_未処理事項」をドリルダウンします。
3階層目のフォルダまできちんと作成されたことが確認できました。
以上となります。
【Power Automate Desktop】置換リストからテキストを一括置換処理
今回の変換リストからテキストを一括置換処理する方法となりますが、これは実は、鷹尾祥さんの著書「Excelパワークエリ データ収集・整形を自由自在にする本」の第4章7『文字列変換リストを使った一括文字列置換』と同じことをPowerAutomateDesktopを使ってやってみようという試みになります。
- 1.やりたいこと
- 2.事前準備「置換リスト」の作成
- 3.実践① フロー作成 ~ 置換リストの変数設定
- 4.実践② 2つのループ処理を設定
- 5.実践③ エクセルを閉じる(置換後の変換対象ファイルは名前を付けて保存)
- 6.フローの実行
- 7.最後に
1.やりたいこと
下図の通り、事前に「置換リスト」の各組合せをエクセルファイルに設定しておき、選択した「変換対象ファイル」(エクセル)の任意の列の文字列を置換リストの数分、置換処理するものです。
説明が長くなりそうなので全体の流れを要約したものを以下記載しました。
2.事前準備「置換リスト」の作成
下図は今回使用する「置換リスト」の最初と最後のページを横並びにしたものです。これで簡単に説明します。まず、最低限必要なのは「検索Text(A列)」と「置換Text(B列)」となります。下図2行目で例えると、仮に対象テキストが「渋谷109」(0のみ全角)であれば、検索Text 0(全角)を置換Text 0(半角)に置換し、「渋谷109」にすることになります。C、D列の分類と備考はA,B列の説明となりますので無くてもPADフローの動作に影響はありません。分類で分けた通り、置換の分類としては大きく次の通りに分けられます。
00 文字種 ・・ 全角⇔半角、平仮名⇔カタカナ、大文字⇔小文字 の置換等
01 固有テキスト・・その通り固有のテキスト⇔固有テキストの置換
02 削除 ・・ 固有テキストを削除するもの
03 スペース削除・・テキストに含まれる余分な空白を削除するもの
この置換リストでポイントとなるのは上記分類の並び順です。どうゆうことかというと、今回の変換対象ファイルに「WORD WORLD(株)」というテキストがあります。これを下図の置換リストで置換をかけると、リスト順に次の順番で置換されていきます。
WORD WORLD(株) ・・置換前
WORD WORLD(株) ・・D → D (文字種置換)
WORD WORLD(株) ・・ L → L (文字種置換)
WORD WORLD(株) ・・ O → O (文字種置換)
WORD WORLD(株) ・・ R → R (文字種置換)
WORD WORLD(株) ・・ W → W (文字種置換)
WORD WORLD株式会社 ・・ (株) → 株式会社 (固有テキスト置換)
ワード WORLD株式会社 ・・ WORD → ワード (固有テキスト置換)
ワード■WORLD株式会社 ・・ ” ”(半角) → ” "(全角) (スペース置換)
ワード WORLD株式会社 ・・置換後
仮に、92行目の検索Text「WORD」置換Text「ワード」が2行目にあったとしたら、これは置換されず(全角のWORDである為)に最終結果は、「WORD WORLD株式会社」となってしまいます。よって、正しく置換を反映するには固有テキストの前に文字種をセットしたり、半角スペースを一旦、全角スペースに置換してから、その後に全角スペースの調整がなされるようセットする等、工夫が必要です。
その他、94行目のような削除の場合の置換Textは完全なブランクで問題ありません。(パワークエリの場合は「’」とする必要あり)
また、各検索Text、置換Textをエクセルシートに設定するにあたっては、文字列や数値以外の関数(CHAR関数等)の結果であってもフロー実行の置換ではテキストとして扱われます。
3.実践① フロー作成 ~ 置換リストの変数設定
任意の名前を付けて作成ボタンをクリックします。
画面左のアクション一覧からフォルダ→特別なフォルダーを取得 をダブルクリック(又は真ん中のフロー詳細へドラッグ&ドロップ)します。このアクションは以降のファイル選択等の際に「初期フォルダ」を設定するために変数化しておくものです。
ここでは、特別なフォルダ―の名前: デスクトップ を選択します。特別なフォルダーのパス:は自身のデスクトップのパスが自動設定されます。生成された変数はデフォルトの SpecialFolderPath のままとし、保存します。
【置換リストを選択をするためのダイアログ設定】
アクション一覧 → メッセージボックス → ファイルの選択ダイアログを表示 をダブルクリックします。
下図の通り入力し保存します。
ダイアログのタイトル: 置換リストの選択(任意のテキスト)
初期フォルダ:%SpecialFolderPath% (右端の{X}をクリックし、変数名を選択)
ファイルフィルター: *.XLSX* (今回はエクセルファイルに限定するため)
ファイル選択ダイアログ:オン
複数の選択を許可:オフ
ファイルが存在するかどうかを確認:オフ
生成された変数:デフォルトの SelectedFile を ReplaceList_File に変更します。変数名と変更方法は下図(補足)を参照してください。変数ButtonPressedは今回特に使用しませんのでデフォルトのままとします。
今回のフローでは、置換リストと変更対象ファイルを別ファイルとしており、それぞれに対してフローを設定していきますので、
置換リスト関係 = ReplaceList
変更対象ファイル関係 = ConversionSheet
をそれぞれの各変数名に使用して管理することとしますので、頭に入れておいてください。
(補足)
【変更対象ファイルを選択をするためのダイアログ設定】
再び、アクション一覧 → メッセージボックス → ファイルの選択ダイアログを表示 をダブルクリックします。
下図の通り入力し保存します。
ダイアログのタイトル: 変更対象のエクセルファイルを選択(任意のテキスト)
初期フォルダ:%SpecialFolderPath% (右端の{X}をクリックし、変数名を選択)
ファイルフィルター: *.XLSX* (今回はエクセルファイルに限定するため)
ファイル選択ダイアログ:オン
複数の選択を許可:オフ
ファイルが存在するかどうかを確認:オフ
生成された変数:デフォルトの SelectedFile を ConversionSheet_File に変更します。変数ButtonPressed2は今回特に使用しませんのでデフォルトのままとします。
【置換リスト:エクセルの起動】
アクション一覧 → Excel → Excelの起動 をダブルクリックします。
下図の通り入力し保存します。
Excelの起動:次のドキュメントを開く を選択します。
ドキュメントパス:右端の{X}をクリックし、変数ReplaceList_File を選択します。
インスタンスを表示する:オフとします。(起動したエクセル画面を表示するかどうかの設定ですが、置換リストを表示する必要はない為オフ)
読み取り専用として開く:オンにします。
生成された変数名は、ExcelInstanse_ReplaceList に変更します。
【置換リスト:最初の空の列・行(リストの範囲)を取得】
アクション一覧 → Excel → Excelワークシートから最初の空の列や行を取得 をダブルクリックします。
下図の通り入力し保存します。
Excelインスタンス:右端をクリックし、変数ExcelInstanse_ReplaceListを選択します
生成された変数は、FirstFreeColmn_ReplaceList 、FirstFreeRow_ReplaceList に変更します。(ただし、以降のフローで使用するのはFirstFreeRow_ReplaceListのみです)
【変更対象ファイル:エクセルの起動】
アクション一覧 → Excel → Excelの起動 をダブルクリックします。
下図の通り入力し保存します。
Excelの起動:次のドキュメントを開く を選択します。
ドキュメントパス:右端の{X}をクリックし、変数ConversionSheet_File を選択します。
インスタンスを表示する:オンとします。(変更対象ファイルを表示するのは、後の工程で対象の列番号等を目視で確認し入力する想定であること、また実際の置換の動きを画面で確認するためです)
読み取り専用として開く:オフにします。
生成された変数名は、ExcelInstanse_ConversionSheet に変更します。
【変更対象ファイル:最初の空の列・行(リストの範囲)を取得】
アクション一覧 → Excel → Excelワークシートから最初の空の列や行を取得 をダブルクリックします。
下図の通り入力し保存します。
Excelインスタンス:右端をクリックし、変数ExcelInstanse_ConversionSheetを選択します。
生成された変数は、FirstFreeColmn_ConversionSheet 、FirstFreeRow_ConversionSheet に変更します。(ただし、以降のフローで使用するのはFirstFreeRow_ConversionSheetのみです)
【変更対象ファイル:変換対象の列番号をダイアログで入力】
アクション一覧 → メッセージボックス → 入力ダイアログを表示 をダブルクリックします。
下図の通り入力し保存します。
入力ダイアログのタイトル:変更対象ファイルの対象列選択(任意)
入力ダイアログメッセージ:変換対象エクセルファイルの変換対象の列番号を入力してください。(任意)
規定値: ブランク
入力の種類:1行 を選択
入力ダイアログを常に手前に表示する:オン
生成された変数 は、Conversion_Colmn に変更します。ButtonPressed3は使用しない為、デフォルトのままで構いません。
【変更対象ファイル:変換対象列の先頭行番号をダイアログで入力】
再び、アクション一覧 → メッセージボックス → 入力ダイアログを表示 をダブルクリックします。
下図の通り入力し保存します。
入力ダイアログのタイトル:変更対象ファイルの先頭行を選択(任意)
入力ダイアログメッセージ:変換対象エクセルファイルの変換対象列の先頭行番号を入力してください。(任意)
規定値: 2 (先ほどはブランクでしたが、ここは基本的に変更対象ファイルの先頭行は見出しであることを想定し、デフォルト値を 2行目としています。フロー実行時に変更可能です。)
入力の種類:1行 を選択
入力ダイアログを常に手前に表示する:オン
生成された変数 は、Conversion_StartRow に変更します。ButtonPressed4は使用しない為、デフォルトのままで構いません。
【置換リスト:ループ処理用変数の設定】
アクション一覧 → {X}変数の設定 をダブルクリックします。
下図の通り入力し保存します。
設定: ReplaceList_Var とします。(当変数の名前です)
宛先: 2 とします。(この変数は、ループ処理の際に置換リストから読み取る行の初期値となります。置換リストの1行目は見出し(固定)となりますので、初期値が2行目からとなるようにします)
ここまでで、設定したフローは下図の通りとなります。
4.実践② 2つのループ処理を設定
ここで置換をループ処理するためのフローを設定していきます。置換リストの値を読み取るループの中に、変換対象ファイルのテキストを置換するループを入れ子にして、一連の置換ループ処理を作っていきます。(フローの順番に説明していきますので少しわかりずらいところがあるかもしれません)
【置換リストの値を読み取るループ】
アクション一覧 → ループ → ループ条件 をダブルクリックします。
下図の通り入力し保存します。
最初のオペランド: 右端の{X}をクリックし、ReplaceList_Var を選択します。
演算子: と等しくない(<>) を選択します。
2番目のオペランド: 右端の{X}をクリックし、FirstFreeRow_ReplaceList を選択します。
この設定の意味は、ReplaceList_Var (初期値 2)が FirstFreeRow_ReplaceList(置換リスト最終行の次の行) と等しくない限りループ処理を続ける。つまり、置換リストの最初の行から最後の行までループ処理を続けるということです。
【変換対象ファイル:ループ処理用変数の設定】
アクション一覧 → {X}変数の設定 をダブルクリックします。
下図の通り入力し保存します。
設定: ConversionSheet_Var とします。
宛先: 右端の{X}をクリックし、Conversion_StartRow を選択します。
ここで前項の入力ダイアログで取得した変数 Conversion_StartRow を新たな変数としてConversionSheet_Var に設定する理由は、Conversion_StartRowはテキスト型として認識されているためループ処理を回し、この後の変数を大きくするステップで+1をしたときにエラーとなってしまうためです。ここで新たな変数に入れることで数値型となります。
【置換リスト:エクセルから検索Textを読み取る】
アクション一覧 → Excel → Excelワークシートから読み取りをダブルクリックします。
下図の通り入力し保存します。
Excelインスタンス:変数ExcelInstanse_ReplaceList を選択します。
取得: 単一のセルの値 を選択します。
先頭列: 1 を入力します。
先頭行: 右端の{X}をクリックし、ReplaceList_Var を選択します。
生成された変数は、SearchData に変更します。
【置換リスト:エクセルから置換Textを読み取る】
再び、アクション一覧 → Excel → Excelワークシートから読み取りをダブルクリックします。
下図の通り入力し保存します。
Excelインスタンス:変数ExcelInstanse_ReplaceList を選択します。
取得: 単一のセルの値 を選択します。
先頭列: 2 を入力します。
先頭行: 右端の{X}をクリックし、ReplaceList_Var を選択します。
生成された変数は、ReplaceData に変更します。
【変換対象ファイルのテキストを置換するループ】
まだ、最初のループの途中ですがここで置換処理のループを入れます。
アクション一覧 → ループ → ループ条件 をダブルクリックします。
下図の通り入力し保存します。
最初のオペランド: 右端の{X}をクリックし、ConversionSheet_Var を選択します。
演算子: と等しくない(<>) を選択します。
2番目のオペランド: 右端の{X}をクリックし、FirstFreeRow_ConversionSheet を選択します。
この設定の意味は、ConversionSheet_Var (初期値 2)が FirstFreeRow_ConversionSheet(変換対象ファイル最終行の次の行) と等しくない限りループ処理を続ける。つまり、変換対象ファイルの最初の行から最後の行までループ処理を続けるということです。
【変換対象ファイルの対象テキストを読み取る】
アクション一覧 → Excel → Excelワークシートから読み取りをダブルクリックします。
下図の通り入力し保存します。
Excelインスタンス:変数ExcelInstanse_ConversionSheet を選択します。
取得: 単一のセルの値 を選択します。
先頭列:右端の{X}をクリックし、Conversion_Colmn を選択します。
先頭行: 右端の{X}をクリックし、ConversionSheet_Var を選択します。
生成された変数は、TargetData に変更します。
【対象テキストを置換する】
アクション一覧 → テキスト → テキストを置換する をダブルクリックします。
下図の通り入力し保存します。
解析するテキスト: 右端の{X}をクリックし、TargetData を選択します。
検索するテキスト: 右端の{X}をクリックし、SearchData を選択します。
検索と置換に正規表現を使う:オフ
大文字と小文字を区別しない:オフ
置き換え先のテキスト:右端の{X}をクリックし、ReplaceData を選択します。
エスケープシーケンスをアクティブ化:オフ
生成された変数は、デフォルトのReplaced のままとします。
【置換後のテキストに対しトリミングする】
前項の置換だけでは先頭と末尾に余分な空白文字があった場合そのまま残ってしまうため、ここで更にトリミング処理を追加します。
アクション一覧 → テキスト → テキストのトリミング をダブルクリックします。
下図の通り入力し保存します。
トリミングするテキスト:右端の{X}をクリックし、Replaced を選択します。
トリミング対象:先頭と末尾の空白文字 を選択します。
生成された変数は、さきほどの置換時に作成した Replaced とします。
つまり、既にある変数 Replaced を上書きする形となります。
【置換・トリミング後のテキストを変換対象ファイルの元セルへ書き込む】
アクション一覧 → Excel → Excelワークシートに書き込み をダブルクリックします。
下図の通り入力し保存します。
Excelインスタンス:ExcelInstanse_ConversionSheet を選択します。
書き込み値:右端の{X}をクリックし、Replaced を選択します。
書き込みモード:指定したセル上(デフォルトのまま)
列:右端の{X}をクリックし、Conversion_Colmn を選択します。
行:右端の{X}をクリックし、ConversionSheet_Var を選択します。
【次のループ処理の為、変換対象ファイル変数をインクリメントする】
アクション一覧 → 変数 → 変数を大きくする をダブルクリックします。
下図の通り入力し保存します。
変数名:右端の{X}をクリックし、ConversionSheet_Var を選択します。
大きくする数値:1 を入力します。
ここまでで、2つ目のループ処理(置換と書き込み)のフロー設定は完了となります。この2つ目のループ処理のフローを抜き出したのが下図となります。ループ条件とEndの間に設定したアクションが入った状態です。この後、1つ目のループ処理の続きを設定します。
【置換リスト読み取り変数をインクリメントする】
アクション一覧 → 変数 →変数を大きくする をダブルクリックします。
下図の通り入力し保存します。
変数名:右端の{X}をクリックし、ReplaceList_Var を選択します。
大きくする数値: 1 を入力します。
これでループ処理のアクション設定は完了です。2つのループ処理のフロー一覧が下図となります。
最初のループで置換リストの最初の検索Textと置換Textを読み取り →
2つ目のループで変換対象列の行数分の置換処理を実施 →
その後、最初のループ変数をインクリメント →
最初のループの頭に戻って置換リストの2つ目の検索Textと置換Textを読み取り →
これを置換リストの行数分繰り返し処理します。
5.実践③ エクセルを閉じる(置換後の変換対象ファイルは名前を付けて保存)
【置換リスト:エクセルを閉じる】
アクション一覧 → Excel → Excelを閉じる をダブルクリックします。
下図の通り入力し保存します。
Excelインスタンス:ExcelInstanse_ReplaceList を選択します。
Excelを閉じる前:ドキュメントを保存しない を選択します。
【置換後の変換対象ファイルを保存する際の新規ファイル名を作成】
保存するファイル名は元のファイル名の末尾に(Replaced)を追記したファイル名としますので次のアクションでファイル名を作成します。
アクション一覧 → テキスト → テキストを置換する をダブルクリックします。
下図の通り入力し保存します。
解析するテキスト:右端の{X}をクリックし、ConversionSheet_File を選択します。
検索するテキスト:.xlsx と入力します。
検索と置換に正規表現を使う:オフ
大文字と小文字を区別しない:オン(ファイル名の拡張子はどちらもあり得る為)
置き換え先のテキスト: %'(Replaced.xlsx’% と入力します。
エスケープシーケンスをアクティブ化:オフ
生成された変数は、Replaced_FileName とします。
解析するテキストの変数 ConversionSheet_File は元のファイル保存先のパスがすべて含まれていますので、この置換によって変数 Replaced_FileName は元のファイル保存先パスでファイル名の末尾に(Replaced)が追加されたものとなります。
【変換対象ファイル:名前を付けて保存しエクセルを閉じる】
アクション一覧 → Excel → Excelを閉じる をダブルクリックします。
下図の通り入力し保存します。
Excelインスタンス:ExcelInstanse_ConversionSheet を選択します。
Excelを閉じる前:名前を付けてドキュメントを保存 を選択します。
ドキュメント形式:規定(拡張機能から) 【デフォルトのまま】
ドキュメントパス: 右端の{X}をクリックし、Replaced_FileName を選択します。
以上でフローの作成は完了です。作成したフロー全体は次の通りです。
6.フローの実行
詳細設定画面から実行するとデバッグモードで実行され時間が掛かる為、作成したフローを一旦保存後に閉じて、トップ画面から実行します。
置換リスト選択のダイアログが表示されるのでエクセルファイルを選択し、開くをクリックします。
続いて、変換対象のエクセルファイル選択ダイアログが表示されるのでファイルを選択し、開くをクリックします。
変換対象のエクセルファイルが開き、変換対象ファイルの対象列選択ダイアログが表示されるので、対象列を入力してOKをクリックします。
続いて、変換対象ファイルの先頭行を選択ダイアログが表示されます。初期値に設定した 2 が予め入力されていますので、正しければそのままOKをクリックします。その後、置換処理が実行されます。
下図は置換途中の状態です。
置換が完了すると、エクセルが閉じます。元の変換対象ファイル(取引マスタ_202106.xlsx)があった場所を確認すると、「取引マスタ_202106(Replaced).xlsx」という名前のファイルが新たに保存されました。
このファイルを開いてみると、想定通りに置換されたことが確認できました。
7.最後に
想定した通りのフローを作成することができましたが、ひとつ大きな課題が残ってしまいました。それは置換処理にかなりの時間が掛かることです。今回例で実行した置換リスト 98パターン × 取引先マスタ 10件 = 980回の置換処理で掛かった時間が48秒でした。試しに置換リスト 98パターン × 取引先マスタ 100件 = 9800回の置換処理で実行したところ、約10倍以上の9分50秒(590秒)という結果でした。
実務で数千数万件を処理するのにこれでは厳しいです。まずは置換リストのパターンを限定した上で実行すべきかなと思います。また、もっと効率的なフローの書き方があるかも知れませんので今後の課題にしたいと思います。
かなり長くなってしまいましたが、最後まで読んでいただきありがとうございました。
【Power Automate Desktop】エクセルワークシートの値リストからフォルダを作成
- 1.やりたいこと
- 2.事前準備
- 3.実践(1)Excelの起動 ~ Excelワークシートdataの読み取り
- 4.補足 ~3.(1)実行動作確認~
- 5.実践(2)ループ処理 For each でフォルダ作成
- 6.フロー実行
1.やりたいこと
下図の通り、エクセルのワークシート A列に入力された値のリスト分のフォルダを作成する処理をPowerAutomateDesktopでフローを作成し実行します。単純な処理ですがPADの練習としてはよいのではないかと思います。
2.事前準備
今回は、作成したフローを継続的に使用することを想定して以下条件としました。
事前にPCのデスクトップに「TEST_Folder」という名前のフォルダを準備し、フローで作成したフォルダはこの中に入るようにします。
また、読み込み元のエクセルファイルを「TEST_File.xlsx」の名前で同フォルダに保管しておきます。
※上記フォルダ、エクセルファイルの名称はなんでも構いません。
エクセルファイルの中身は次の通り。A列に入力されて値をフォルダ作成対象としますので、A1セル以下に入力しておきます。今回は、連番+_+47都道府県名としました。
※下図は、A列を2つに分けて表示しています。
3.実践(1)Excelの起動 ~ Excelワークシートdataの読み取り
PowerAutomateDesktop(プレビュー)から 新しいフローをクリックします。
任意のフロー名を入力して作成をクリックします。
まず、エクセルファイルからデータを読込むためのフローを作っていきます。
画面左のアクションから、Excel → Excelの起動をダブルクリック(又は右へドラッグ)します。
Excelの起動:次のドキュメントを開く を選択します。
ドキュメント パス: 右のファイルの選択ボタンをクリックし、TEST_Folderの中のTEST_File.xlsx を選択します。(又は直接パスを入力。)
インスタンスを表示する: エクセルを表示する必要はないのでオフにします。
読み取り専用として開く:どちらでも構いませんが、オープンエラーとならないようオンとしています。
詳細はデフォルトのままでよいので、これで保存をクリックします。
これにより、変数 ExcelInstance が生成されます。
Excel → Excelワークシートから最初の空の列や行を取得 をダブルクリックします。
これはワークシートからデータの範囲(最終行)を取得するためのアクションです。
Excelインスタンス:デフォルトで%ExcelInstance%が入るのでそのまま保存します。
変数 FirstFreeColumn と FirstFreeRow が生成されます。今回使うのは後者のみです。
Excel → Excelワークシートから読み取り をダブルクリックします。
Excelインスタンス: %ExcelInstance%(デフォルト値)
取得: セル範囲の値 を選択
先頭列: 1 (A列)
先頭行: 1 (1行目)
最終列: 1 (A列)
最終行: %FirstFreeRow -1%
※{X}をクリックし、FirstFreeRow を選択し、末尾に -1 と入力します。
FirstFreeRowは最初の空白行であり、データの最終行はその1行前と
なるためです。
保存をクリックします。
変数 ExcelData で生成されます。
Excel → Excelを閉じる をダブルクリックします。
Excelインスタンス:%ExcelInstance%(デフォルト値)
Excelを閉じる前:ドキュメントを保存しない を選択します。
保存をクリックします。
4.補足 ~3.(1)実行動作確認~
ここは補足となりますので飛ばしても構いません。
下図は前項までに作成したフローです。全体としては途中段階ですが、ここまでで一度フローを実行してみます。
左上の実行ボタン▷ をクリックします。
インスタンスの表示をオフにしているので見た目のエクセルの動きはありませんが、フロー実行が完了すると、画面右の変数のフロー変数に中身が入ったことがわかります。試しに、前項最後に生成した変数 ExcelData をダブルクリックしてみます。
すると、エクセルから読み取ったDatatalbeが表示されます。下図は途中で見切れていますが、47都道府県分が変数としてきちんと取り込めたことがわかりました。
5.実践(2)ループ処理 For each でフォルダ作成
さて、フロー作成に戻ります。アクションから
ループ → For each をダブルクリックします。
パラメーターの選択
反復処理を行う値: 右の{X}をクリックし、ExcelData を選択します。
保存をクリックします。
変数 CurrentItem が生成されます。
フォルダー → フォルダーの作成 をダブルクリックします。
新しいフォルダーを次の場所に作成:
右端のフォルダーの選択ボタンをクリックし、TEST_Folder を選択しOKをクリックします。(又は直接パスを入力)
新しいフォルダー名: 右端の{X}をクリックし、CurrentItem をクリックします。
保存をクリックします。ここまででフローの作成は完了です。
6.フロー実行
下図が作成したフロー全体です。左上の実行ボタン▷をクリックし実行してみます。
For each のところで47フォルダ分の処理が繰り返され、下図の通り47都道府県分のフォルダがTEST_Folderの中に作成されました。この数で実行時間は20秒でしたが、フローを保存し閉じた状態で実行した場合は5秒ほどで完了しました。
以上となります。
【パワークエリ】一定期間の予算データから月割計上用データを作成する
1.やりたいこと
下図に記載の通りです。今回は一般的に年2回支給される賞与とそれに伴う社会保険料の個人別予算を支給前の期間で月割り計上する前提で例を作成しています。
2.実践(1)基dataの取込み ~ 「分割月数」「基準年月日」の設定
前画像BEFOREの3つのテーブルをエディターに取り込んだところから始めます。各クエリはデータ型を変更して、適用したステップが「変更された型」となっている状態です。この段階で、「分割月数」「基準年月日」は接続の作成のみ、「予算data」はテーブルとしてワークシートへ読み込んでいます。(説明省略)
下図は参考までに完成後の各クエリの状態を表したものです。
今回は同じエクセルのワークシートのテーブルから取り込んでいますが、ファイルからの取込みとしても構いません。
まず、「分割月数」クエリを選択します。
この「分割月数」はワークシートで入力した月数を単一の数値として以降で参照するものとしますので次の操作を行います。数値入った箇所で右クリックし、「ドリルダウン」をクリックします。
変換タブに数値ツールと表示され、適用したステップに「分割月数1」が追加されました。これでテーブルから数値に変換されました。
次に「基準年月日」を選択します。
まず、先ほどと同様にドリルダウンします。
変換タブに日付時刻ツールと表示され、適用したステップに「基準年月日1」が追加されました。これでテーブルから日付に変換されました。
次が今回のポイントです。
ホームタブ → 詳細エディター をクリックします。
下図が、前述のステップまでのコードです。ここに直接関数を書き込みます。
今回使うM関数は、List.Accumulate です。詳細は以下リンク公式の通り。
繰り返しの処理をする関数で、今回の処理を非常に簡潔に言うと、基準年月日2021/4/1 の月末日(2021/4/30) から6ヶ月分の日付(各月末日)をリスト化するもの となります。
もとの基準年月日1のコードの末尾に「 , 」を入力後、以下数式を入力します。各行の//以降の緑文字は説明書きです。inの後は 分割対象年月 に変更し完了します。
List.Accumulate( {1..分割月数-1}, // リスト:1~ 分割月数-1 の連続した数値
{Date.EndOfMonth(基準年月日1)}, // 初項(seed) : 基準年月日1の日付の月の最終日
(x,y)=> x & {Date.EndOfMonth(Date.AddMonths(基準年月日1,y))} //最初の状態x とリストの各項目xを処理した結果のリスト出力
)
詳細を下図で説明します。
6ヶ月分のリストが作られました。基準年月日の操作はここまでとなります。
3.実践(2)予算dataから月割計上dataを作成
「予算data」クエリを選択し、列の追加タブ → カスタム列 をクリックします。
下図の通り、入力してOKをクリックします。カスタム列の式の 基準年月日 は先ほどList.Accumulate関数で作成したリストです。
計上年月日 列が追加されました。各行は基準年月日リストが入れ子となった状態です。
計上年月日列見出し右側の矢印ボタン → 新しい行に展開する をクリックします。
もとのデータが計上年月日の数分に展開されました。
更に列の追加タブ → カスタム列 をクリックします。
賞与の月割計上列を追加するため、以下数式を入力します。
Number.Round([賞与予算]/ 分割月数,0,RoundingMode.AwayFromZero)*-1 *(List.Count(基準年月日)-1)
else
Number.Round([賞与予算]/ 分割月数,0,RoundingMode.AwayFromZero))
if式で、内容を要約(ラウンドは省略)すると
計上年月日 が基準年月日リストの最期の項目(今回は2021/9/30)であった場合は、
(賞与予算を分割月数(6)で除した金額 ×-1 )× (基準年月日リストの項目数 -1)
それ以外は、
(賞与予算を分割月数(6)で除した金額 )
となります。
賞与_月割 列が追加されました。4-8月は予算の1/6 、最終月の9月は4-8月の合計額をマイナスした金額となっています。
更にカスタム列を追加し、社保予算についても同様の数式を入力します。
社保_月割 列が追加されました。予算列は不要となるので(残しておいても問題なし)削除します。
これで完成です。
今回はわかりやすいように賞与と社保の列を分けていますが、その後の集計用データとして使う場合はこの後にピボット解除したり、部門でグループ化したりすればよいと思います。
4.動作確認等
下図は完成後にエクセルワークシートに取り込んだものです。集計行(合計)を追加すると各列の合計は当然0となっています。
試しに基テーブルの分割月数を 6 → 12 に変更してみます。
月割dataシートに戻り、テーブル上で右クリックし、更新 をクリックします。
データが12ヶ月に変更されました。
以上となります。
【Power Automate Desktop(無償版)】Outlookで受信したメールの添付ファイルを定期的にPCの特定フォルダに保存する。
- 1.やりたいこと
- 2.実践① フロー作成~Outlookメール取得・添付ファイル保存
- 3.実践② 保存先フォルダの重複ファイル削除
- 4.実践③ ループの次回実行時間設定〜現在時刻の取得、トリガー設定
- 5.フローの実行
- 6.さいごに
1.やりたいこと
全体としてやりたいことは下図の通りとなりますが、今回説明するのは下図真ん中の黄色部分で、これをPowerAutomateDesktopでフローを作成して実行します。
前提条件としてOutlookで受信する添付エクセルファイルは固定のフォーマットですが、ファイル名は異なるものとします。
(例:Testファイル_A部門.xlsx / Testファイル_B部門.xlsx ・・等)
2.実践① フロー作成~Outlookメール取得・添付ファイル保存
まず、PowerAutomateDesktopを起動し、新しいフローをクリックして任意のフロー名を入力し、 作成 をクリックします。
(画面左の)アクション → ループ → ループ条件 をクリックします。
今回は、一度実行したら手動でフローを停止しない限りずっとループさせたいので、全体のループ条件は下図の通り1=1とします。
アクション → 日時 → 現在の日時(アクション開始時の日時とする)を取得します をクリックします。
取得:タイムゾーン:はデフォルトのままとします。生成された変数はデフォルトでCurrentDateTime が入りますが、これをクリックして%RunDateTime%に変更します。この名称はなんでもよいのですが、デフォルトのCurrentDateTime は後ほど別のアクションで使いますので変更しておいてください。
アクション → Outlook → Outlookを起動します をクリックします。
生成された変数はデフォルトの %OutlookInstance% のままとします。
アクション → Outlook → Outlookからメール メッセージを取得します をクリックします。
前々画面で生成した変数(変数を入力するときは変数名を%で囲います)
アカウント:
自身のメールアカウント
メールフォルダ:
取得する対象のフォルダ
今回は、Inboxフォルダの中のTestという名前のフォルダから取得します。
取得: 〜 本文に次が含まれてます:
ここは必要に応じて設定/変更して下さい。これらの項目でメールボックス
内の大量のメールから対象のメールを絞り込むことが出来ますが、今回
はOutlook側のメールルールで予めメールボックス(Test)に対象を集約して
います。
添付ファイル:
「添付ファイルを保存します」 を選択します。
添付ファイルを次に保存します:
保存先のパスを入力します。(※補足参照)
※補足)
前述の保存先パスについては下図のように対象のフォルダ(又はファイル)を選択した状態でShiftキーを押しながら右クリックすると、「パスのコピー」が出ます。これをクリックするとパスがクリップボードにコピーされるので便利です。但し、そのまま貼り付けた場合、頭と末尾に ” が付加されますのでこれは削除するようにしてください。
3.実践② 保存先フォルダの重複ファイル削除
前述までのフローをループさせた場合、つまり特定のフォルダにファイルを保存後、再度同じフォルダに同じ名称のファイルを保存するフローを実行した場合、元のファイル名の末尾に(2)が付いたファイルが新たに保存されてしまいます。これを回避するために次のアクションを入れます。
アクション → フォルダ → フォルダ内のファイルを取得 をクリックする。
フォルダ:
対象フォルダのパスを入力。ファイル保存先のフォルダとなる。
ファイルフィルター:
*(2)*
生成された変数
デフォルトのFiles のままとする。これにより変数Filesにこのフォルダ内
で(2)を名称に含むファイルが取得される。
アクション → ファイル → ファイルの削除 をクリックする。
削除するファイル: 先ほどの変数%Files%を入力
4.実践③ ループの次回実行時間設定〜現在時刻の取得、トリガー設定
アクション → 日時 → 加算する日時 をクリックする。
日時: 加算するもととなる日時を設定します。最初のアクション開始時に設定した
変数 %RunDateTime% を入力します。
加算: 上記日時に加算する時間を設定します。今回は最初のアクション開始時から
60秒後に次のアクションを実行する設定とします。
生成された変数
デフォルトでResultedDateが入ります、このままでも構いません が、ここで
は %ReactionDateTime% に変更します。
次に次回のアクションを実行するためのトリガーを設定します。
アクション → ループ → ループ条件 をクリックします。
最初のオペランド: 先ほどの%ReactionDateTime% とします。
演算子: 「より大きい(>)」 を選択します。
2番目のオペランド: %CurrentDateTime% を入力します。
上記ループ条件を保存すると、下図のようなエラーが発生します。この時点ではCurrentDateTimeという変数は存在していないためです。一旦放置して次に進みます。
アクション → 日時 → 現在の日時を取得します をクリックします。
取得:タイムゾーンはデフォルトのままとします。ここで変数CurrentDateTimeがデフォルトで出てきますのでそのまま保存します。これで先ほどのエラーは消えたはずです。
先ほど設定したループ条件の内容を訳すと、
ReactionDateTime(アクションの最初の時間から60秒後の時間)が
CurrentDateTime(現在の時間)を超えた時点で
次のアクション(=一番最初のアクションの再実行)を実行する
ということになります。
このループを短時間で回し続けることによるPCへの負担を軽減するために次のアクションで一定の待ち時間を設定します。
アクション → 遅延 → Wait をクリックします。
今回は10秒(単位は秒です)で設定します。
ここまででフローの設定は完了です。
完成した全体のフローは下図の通りとなります。
5.フローの実行
出来上がったフローを実行してみようと思いますが、その前にOutlookのメールボックスとPCの保存先フォルダの状態を確認しておきます。
Inboxフォルダの中のTestフォルダに3件の未読メールがあり、それぞれのメールに以下の通り添付ファイルが付されている状態です。
件名:Test 1 添付ファイル名: Testファイル_A.xlsx
件名:Test 2 添付ファイル名: Testファイル_B.xlsx
件名:Test 3 添付ファイル名: Testファイル_C.xlsx
<PC保存先フォルダ>
Test保存フォルダ は空の状態です。
この状態で左上の実行ボタンをクリックし、フローを実行してみます。
フローが一巡すると、以下の通りTest保存フォルダに3つの添付ファイルが保存されました。60秒経過後に二巡目以降が実行されてもこの状態のままとなっています。新規メールを受信後にフロー が回った段階でファイルが追加されることになります。
6.さいごに
この仕組みを使えば、パワークエリを利用してPCフォルダ内のファイルからデータを集計・整形することが可能です。複数の相手先から収集するエクセルデータをいちいち開き、シート移動して串刺しにする必要もありません。また、途中段階での集計状況の確認も可能となります。
今回は以下の記事を参考にさせていただきました。ありがとうございました。
【パワークエリ】部門費実績配賦を都度変動する配賦基準で実行する。
1.やりたいこと
下図BEFOREのような基データがあります。部門A、B、C で発生した部門費は共通費用となるため、売上高(実発生額)を配賦基準として部門D~Gへ配賦したいというケースです。月単位でこの処理を行うという前提ですので、配賦基準(売上高)は月次の都度変動するものとなります。これをパワークエリ上で実施し、最終的にAFTERのような状態(配賦後の部門費が部門A~Cは0となり、部門D~Gに賦課)にします。また、配賦額と賦課額の合計に計算上の端数差異が発生した場合は配賦先の特定部門で端数調整を行い配賦額列の合計は0になるようにします。
2.エクセルワークシートで関数等により計算する場合(参考)
パワークエリでの処理を説明する前に同じことをエクセルで実行する場合について、参考までに書いておきます。これを見てからの方が理解が早いと思います。
下図G~J列は基のデータとなりますので、K、J列に数式を入れて作成します。K3~K9セルに入力する数式を下図右側に記載しています。J列の数式は省略していますが単純に部門費_配賦前と配賦額を足すだけとなります。
K列(配賦額)のK3~K5セルについては配賦元となりますのでI3~I5セル(部門費_配賦前)に -1 を乗じるだけです。K6~K9セルは部門A~Cの部門費合計額(300+281+422=1,003)を売上高_配賦基準の割合で案分配賦する数式です。ROUND関数で小数点以下端数は四捨五入するようにしています。ただし、この計算でK6~K9を計算した結果の合計は 1,004 となり 1 の端数が生じてしまうため、部門Gの配賦額(K9セル)で、-1 の調整をしています。
(補足)これを実務でやる場合は都度端数を+-するのではなく、K9セルの数式は、
=SUM(I3:I5)-SUM(K6:K8) とするのが無難だと思います。
さて、これをパワークエリでやるのですが、実は基本的にはやることは前述のエクセルと変わりませんのでここの考え方は覚えておいてください。
3.実践
まず、パワークエリエディタを起動します。基データを取り込んで型を変更した状態(操作省略)です。クエリの設定ペインの適用したステップは「変更された型」となっています。
列の追加タブ → カスタム列 をクリックします。
配賦元と配賦先ははじめは列を分けて作成していきます。
下図のように、新しい列名を 配賦元 とし、カスタム列の式は以下を入力してOKをクリックします。
= if [配賦対象] ="○" then [部門費_配賦前]*-1 else 0)
IF文となります。配賦対象列が ○ であれば 部門費_配賦前 に -1 を乗じた金額
それ以外は 0 とする といった内容です。
※もし基データに配賦対象を示す列がない場合は if 文の分岐を配賦対象の部門毎に記入します。
配賦元列が追加されました。適用したステップは「追加されたカスタム」となります。
※適用したステップの名称は説明上はデフォルトのままとしますが、後でわかりやすい名称に変更するのがベターです。
再度、列の追加タブ → カスタム列 をクリックします。
新しい列名を 配賦元 とし、カスタム列の式は以下を入力してOKをクリックします。
=if [配賦対象]=null then
Number.Round(
List.Sum(追加されたカスタム[配賦元]) * [売上高_配賦基準]
/ List.Sum(追加されたカスタム[売上高_配賦基準])
,0,RoundingMode.AwayFromZero ) * -1
else 0)
配賦対象列がnull(空白)であれば、
配賦元の合計に売上高_配賦基準を乗じた額を
売上高_配賦基準の合計で除した金額 →これを円未満四捨五入した金額に
-1を乗じた金額とする。
それ以外は 0 とする。
といった内容です。
配賦先列が追加されました。適用したステップは「追加されたカスタム1」となります。更に、列の追加タブ → カスタム列 をクリックします。
新しい列名を 配賦元 とし、カスタム列の式は以下を入力してOKをクリックします。
ここで配賦元合計と配賦先合計に端数が生じた場合、その端数は部門Gで調整する記述をするのがポイントとなります。
=if [部門] = "G" then
[配賦元] + [配賦先]
- List.Sum(追加されたカスタム1[配賦元])
- List.Sum(追加されたカスタム1[配賦先])
else
[配賦元] + [配賦先]
部門がGの場合は、
配賦元と配賦先の金額を加算した金額から
配賦元列の合計を減算し 更に (→端数調整)
配賦先列の合計を減算する。 (→端数調整)
それ以外は
配賦元と配賦先の金額を加算した金額とする。
といった内容です。
配賦額列が追加されました。部門Gの配賦先額 294 に対し、配賦額 が 293 となっており端数調整がされた結果になっていることがわかります。適用したステップは「追加されたカスタム2」となります。
配賦額列ができれば、先に作った配賦元列と配賦先列は不要となりますので列を選択した状態で右クリックし、列の削除をクリックします。
適用したステップに「削除された列」が追加されました。
最後に配賦後の部門費列を作りますので、部門費_配賦前列と配賦額列を選択した状態で、列の追加タブ → 標準 → 加算 をクリックします。
適用したステップに「挿入された加算」ができ、列が追加されますが、この操作の場合新しい列名はデフォルトで「加算」となります。この後、「加算」列の見出しをクリックして名前を変更してもよいのですが、その場合、適用したステップに「名前が変更された列」という余計なステップが追加されてしまいますので、今回は数式バーの列名”加算”となっているところを直接 ”部門費_配賦後”に書き換えることとします。
列名が変更されました。これで完成です。
4.おまけ
最後に完成したものをエディターからワークシートに読み込み数値の確認を行います。
下図が読み込んだままの状態です。これにテーブルの機能で合計行を追加します。
テーブルデータ上で右クリックし、テーブル>集計行 をクリックします。
集計行ができますので1列ずつプルダウンから合計を選択します。(これを複数列一括で選択する方法が知りたい。)
すると配賦額の合計は0となっており、賦課後の合計金額も賦課前の合計金額と合致した結果になっていることが確認できました。
以上となります。
【パワークエリ】データに小計・合計行を追加し、更に列のピボット、合計列を追加する。
以前、「データに小計・合計行を追加する。」記事を書きましたが、今回はそれの続編で更に列にピボット展開し、列の合計までをパワークエリで作る方法について書いてみます。ただ、やることはさほど難しくはないのですが、ワークシート上でピボットテーブルで集計するほうが数十倍速いです。あくまでこうゆうこともできるよという紹介となりますのでご承知おきください。
1.やりたいこと
下図の通りBEFOREのようなデータから、AFTERのように部門小計・合計行を追加、更に日付を列に展開し、部門・商品毎の合計列を追加した集計表をパワークエリで作成します。
2.実践(1)基データ取込み~クエリの複製(下準備)
まず、基となるデータをエディタに取込みます。
日付列の左端をクリックし、型を日付に変更しておきます。
この状態のクエリ(名前を集計表としています)をベースに以下でパーツとなる小計・合計行/列を作成していきます。クエリの設定ペインの適用したステップは変更された型までの状態です。
左側の集計表クエリ名上で右クリックし、複製をクリックします。
集計表(2)が作成されます。同じ作業をあと3回繰り返し、下図左のような状態にします。その後、集計表(2)〜集計表(5)の名前を下図右の名前に変更します。名前は後でわかるようにしておけば何でも構いません。今作成したクエリの中身をこの後作っていきます。
次のステップの前に、この後に中身を作るクエリ(テーブル)と最終形の集計表との関係を下図にまとめておきます。すべて表現できていませんがおおよそ下図の通りです。
3.実践(2)各小計・合計行/列クエリの編集(パーツ作成)
各クエリの中身を作っていきます。まず、合計列クエリを選択します。この時点では先ほどの集計表クエリと同じ状態です。
列の追加タブ→カスタム列 をクリックします。
下図の通り式を入力し、OKをクリックします。
日付列の上で右クリックし、削除をクリックします。
カスタム列の名前を「日付」に変更します。
このクエリはここまでです。このクエリは合計列自体ではなく、最後に集計表クエリでピボットする前の合計列のもととなるデータを作成したものとなります。
続いて部門合計列クエリを選択します。ホームタブ→グループ化 をクリックします。
下図の通り、選択/入力し、OKをクリックします。
部門毎に売上がグループ化されました。
列の追加タブ→カスタム列 をクリックします。
下図の通り、列名と式を入力し、OKをクリックします。
日付列が挿入されました。部門合計列クエリはここまでです。
続いて、部門小計行&部門合計クエリを選択します。ホームタブ→グループ化 をクリックします。
詳細設定のラジオボタンを選択し、日付、部門列を選択します。新しい列名等は先程同様に入力/選択し、OKをクリックします。
数式バーの左のfxボタン(ステップの追加)をクリックします。
適用したステップにカスタム1が追加され、数式バーは前ステップのグループ化された行を参照した状態になります。
この数式バーを直接次の数式に書き換えます。
変更前:
= グループ化された行
変更後:
= Table.Combine( {グループ化された行,部門合計列})
この関数は複数テーブルをひとつに結合するものです。つまり、前ステップのグループ化された行 と 先程作成した部門合計列 が下図の通りひとつになります。
続いて日付列を選択した状態から、変換タブ→列のピボット をクリックします。
値列は売上を選択し、OKをクリックします。
行が部門小計で日付が列に並び最後が合計列のピボットされた表になりました。
列の追加タブ→カスタム列 をクリックします。
カスタム列の式を下図の通り入力し、OKをクリックします。もとの部門列に (半角スペース+)小計を追加した列にします。
部門列を削除します。
先ほど作成したカスタム列の名前を 部門 に変更します。これでこのクエリは終わりです。
次に最後の日付合計行クエリを選択します。ホームタブ→グループ化 をクリックします。
グループ化のキーを日付とし、その他下図の通り選択/入力し、OKをクリックします。
グループ化されたらfxボタンをクリックし、適用されたステップ カスタム1が挿入された状態にします。
数式バーを直接以下の数式に書き換えます。
変更前:
=グループ化された行
変更後:
= Table.InsertRows( グループ化された行,Table.RowCount(グループ化された行),{[日付="合計", 売上 =List.Sum(グループ化された行[売上]) ]})
数式の詳細について次の画像で説明します。
合計行が追加されました。この合計値 90,230 が行列の合計値となります。
変換タブ → 入れ替え をクリックします。
前ステップの行と列が入れ替わった状態になります。この時点での列名はColumn1~5が自動的に割り当てられます。左上のワークシートマークのよいなボタンをクリックします。
1行目をヘッダーとして使用 をクリックします。
1行目がヘッダー(列名)となりました。列の追加タブ → カスタム列をクリックします。
新しい列名を 部門 とし、カスタム列の式を下図の通り入力してOKをクリックします。
これで日付合計行クエリの作成は完了です。
4.実践(3)集計表の作成(組み立て)
集計表クエリ を選択します。
fxボタン をクリックし、適用されたステップ:カスタム1 が挿入された状態にします。
数式バーを次の数式に直接書き換えます。
変更前:
= 変更された型
変更後:
= Table.Combine( {変更された型,合計列})
前述と同じ関数で、前ステップ:変更された型 と 合計列クエリ(テーブル)がひとつに結合されます。
続いて、日付列を選択した状態で ホームタブ → 昇順で並べ替えボタンをクリックします。これはこの後に列のピボットを実行する際に列を日付順に並べる為の操作です。(基データが日付順に入力されているとは限らないという前提)
日付列を選択した状態で、変換タブ → 列のピボット をクリックします。
値列を 売上 とし、OKをクリックします。
ピボットされました。これに小計・合計行を加えていきます。
fxボタン をクリックし、適用されたステップ:カスタム2 が挿入された状態にします。
数式バーを次の数式に直接書き換えます。
変更前:
=ピボットされた列
変更後:
= Table.Combine({ピボットされた列,#"部門小計行&部門合計",日付合計行})
前述と同じ関数ですが、今回は3つのテーブル(前ステップ:ピボットされた列、部門小計行&部門合計、日付合計行)を結合します。
続いて、部門列を選択した状態で ホームタブ → 昇順で並べ替えボタンをクリックします。
更に、商品列を選択した状態で同様に 昇順で並べ替えをします。
最後の仕上げに、数値がnull(空白)のものを 0 に置き換えたいのですが、ここは少し工夫が必要です。まず、置換したい日付列を選択した状態で、ホームタブ → 値の置換 をクリックします。
下図の通り、検索する値を null 、置換後を 0 とし、OKをクリックします。
各日付列のnull が 0 に置換されました。しかし、自動生成された数式をよく見ると各列名に対して値の置換処理が実行されています。このままだと、新たな日付がデータに追加された場合に置換がされなくなってしまいます。
これを回避するため、数式の一部を以下に書き換えます。
変更前:
= Table.ReplaceValue(並べ替えられた行,null,0,Replacer.ReplaceValue,{"2021/04/01", "2021/04/02", "2021/04/03", "2021/04/05"})
変更後:
= Table.ReplaceValue(並べ替えられた行,null,0,Replacer.ReplaceValue,Table.ColumnNames(並べ替えられた行) )
※ステップの追加から直接上記変更後の数式を入力する方法でも構いません。
下図は上記変更後の数式の補足となります。
テーブルのすべての null が 0 へ置換されましたが、今度は商品列の各小計・合計行のnullまで 0 が入ってしまいました。ここは個別に逆の操作をします。
商品列を選択した状態で、ホームタブ → 値の置換 をクリックします。
先ほどと逆に、検索された値 0、置換後 null としOKをクリックします。
これで完成となります。
5.動作確認検証
下図はワークシート上の基データです。ちなみに作成した集計表は別ワークシートに取込み、その他のクエリは接続のみとしています。
試しに基データに2行追加してみます。
取込み済の集計表シートを選択し、テーブル上で右クリックし、更新をクリックします。
追加したデータがきちんと集計表に反映されました。以上となります。
長くなってしまいましたが、最後まで読んでいただきありがとうございました。