GEN（生産管理システム）に足りない機能をM365ライセンスの範囲で補完してみた

## 序：ベンダーとしての Power Platform 開発
「Power Platform は内製化のためのツールであって、そのためのご支援はできても、作ってあげたり直してあげたりするくらいなら Power Platform 以外のソリューションを検討してもらった方がいい」という主張をよく耳にします。

　筆者も、基本的にはその立場にあります。言うまでもなく、ローコード・ノーコードツールは、決して「安価かつ高速で導入できる製品」ではありません。あくまでも「内製化を促進するためのプラットフォーム」であると考えています。その導入目的は様々ですが、主に、企業や組織が自らのビジネスプロセスや業務フローを理解し、自分たちで管理・運用できるようにしていくことを目指していくという点に異論を呈する人は恐らくいないはずです。

　ローコード・ノーコードツールを利用することによって、他開発言語の知識がなくても、業務担当者が迅速にアプリケーションを開発・運用できます。しかし、それには一定の学習や慣れが必要であり、最初からすべてを他者に任せてしまうと、本来の内製化の意図から外れてしまいます。

　したがって、Power Platform を最大限に活用するためには、企業内で必要なスキルを育成することが不可欠です。その過程において外部の支援を受けることは重要ですが、あくまでも内製化のプロセスをサポートするものであるべきです。この視点を欠いて、単に「安価で速い解決策」を求めるのであれば、他のソリューションを検討する方が適切である場合もあるでしょう。

 　しかし、筆者は、全ての企業がこれを満たせるとは考えていません。経歴でいえば3年目を迎えた現在までに、Power Platform 導入による内製化を成功させるために必要なリソースやスキルを全ての企業が持ち合わせているわけではないと感じた場面に多く出会いました。

　特に、人員が限られている中小企業やITスキルが十分に備わっていない組織にとっては、内製化の負担は大き過ぎるように思います。業務改善をしたところで増えるのはお金や時間ではなく仕事ですし、特に、今回の記事を書くきっかけとなった企業さま（製造業）においては、決めつけているわけではありませんが、極寒・酷暑の中での体力仕事の後、ITスキルの習得などを考えられる人はほぼいないと見受けられます。結果として外部の専門家に依存することが多くなり、内製化の本来の目的が達成されにくくなります。

　また、組織の規模やビジネスの複雑さによっては、対応しきれない高度な要件や統合が必要になることもあります。そのような場合、無理に内製化にこだわるよりも、適切な外部ソリューションを検討し、専門家の助けを借りて効率的かつ効果的に問題を解決する方が、結果としてビジネスにとって良い選択となるような気がします。

　程度にもよるのですが、最近は、内製化が必ずしもすべての企業にとって最適な道ではないことを理解しながら、あえて Power Platform を選択肢として挙げることもアリなのではないか、という思想に寄りつつあります。

 　今回の記事は、既存の基幹システムからデータをエクスポートし、そのマスターデータを Power Automate で Power Apps 内に取り込んでアプリ開発を行った…という事例共有となっています（※公開の許可は取っています）

  基幹システムからエクスポートしたCSVファイルを Power Platform に取り込む、この一連の流れは（とても狭い範囲だとは思いますが）需要があると思っていますので、参考にしていただけますと幸いです。少し複雑な仕様なので筆者がベンダーとして入っていますが、上級の市民開発者であれば難なくクリアできる内容となっているはずです。

### 基幹システムとローコードツールを連携することについて
【2025年1月追記】こちら、kintone さんの見解ですが、Power Platform 界隈の方々にも一読をオススメいたします。
https://topics.cybozu.co.jp/news/img/2cf53a44ac8a43ed4a64e1124a8a7bef3df610e9.pdf

### GEN って何？
一纏めに "GEN" といっても様々ですが、今回は主に「生産管理システム」と同義で記事を執筆しています。この GEN は、生産工程の計画、実行、監視、最適化を支援するためのツールです。主に製造業において使用され、生産効率の向上、コスト削減、品質管理を行うためのものです。

https://kb.gen-cloud.jp/knowledgebase/gn040201

画面イメージはこちらの動画をご視聴ください。とても使いやすいUIです。

### 問題点
基幹システムなら Power Platform の出番はないと思いましたが、GEN の場合、登録してある既存データを元にした製造指示登録はできる一方で、柔軟な品目の追加・削除をした上での製造指示登録ができない仕様となっています。例えば、カレーを作るために必要なジャガイモ、ニンジン、牛肉、といった材料をマスターデータとして登録していれば、カレーという品目で製造指示を出すことができます。

　しかし、このカレーに「ジャガイモが不要」だったり「エリンギを追加したい」であったり、カレーAを元にして、スパイスの配合を変えたカレーBを作りたいといった場合の入出庫管理が難しい現実に直面しました。

　そういった背景から、GEN に登録されているマスターデータを元に、柔軟な入出庫データの登録が行えるアプリを別のツール（Power Apps）を用いて作れないものか、というご相談をいただく格好となりました。

### M365ライセンスの範囲内でできないか
ここでさらなる問題点が浮き彫りになりました。GEN には、Power Platform に繋ぐためのAPIがありません。そもそも、外部データとのAPI連携は有償ライセンスの範疇となることが多く「「「本当に」」」運用コストをかけられない企業にとっては頭を抱える問題がありました。

　そこで、GEN からエクスポートした CSV 形式のマスターデータファイルを SharePoint ドキュメントライブラリに保存し、そこからコレクションとして Power Apps に取り込めないかと考えました。

　マスターデータを元に入出庫管理を行うアプリを作成し、そのトランザクションデータを SharePoint リストに登録すれば、苦労はしますが、M365のライセンス範囲内で実現できそうです。
 
　マスターデータに変更があった場合に都度ファイルの更新作業が発生しますが、これによって、追加費用をかけずに要件を満たせます（※ただし、既にM365を導入して業務を行っている組織に限ります）

### Power Automate でのフロー作成
フローの概観は次のとおりです。Power Apps のコレクションとして取得するので、トリガーは Power Apps で特定の操作があった時としています。

![新規キャンバス1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/689e8289-e688-c60c-0558-b5f7831cb599.jpeg)

CSV形式のファイル操作で必要なのは、改行コード（や文字コード）を考慮しておくことです。今回の場合、２行目のアクション（変数を初期化する - 改行コード）に、次のような改行コードを定義しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/a1793e14-f359-631b-a89c-2553dbd087bb.png)
 ~~~
decodeUriComponent('%0A')
 ~~~

3行目の SharePoint アクションでCSVファイルを選択します。その後、4行目の変数アクションでは、そのCSVコンテンツを「文字列型」の変数としてセットしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/9a7877e9-fff5-d685-5b3e-6df6a6035ea7.png)

 ここまでできたら、あとはコレクションとして取り込むために配列化します。データ操作コネクタから作成アクションを追加し、次の数式を入力します。

 ~~~
split(substring(variables('CSVコンテンツ'),0,sub(length(variables('CSVコンテンツ')),1)),variables('改行コード'))
 ~~~

作成したこの元データを後続の作成アクションでヘッダー行とデータ行に分断します。

~~~
//作成 - ヘッダー行
first(outputs('作成_-_CSVコンテンツ'))
~~~

~~~
//作成 - データ行
skip(outputs('作成_-_CSVコンテンツ'),1)
~~~

あとは、選択アクションを使ってフィールドの数だけ「マップ」に数式を入力していきます。今回は8列あるテーブルなので、一列ずつ、JSONデータから値を取り出していきます。例として一行目の取り出し方のみ書いておきますので、必要な列数分の処理を行ってください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/44918130-c1d4-62ea-32f8-c35f9dff9466.png)

~~~
//開始
outputs('作成_-_データ行')
~~~
~~~
//マップ（左辺）
split(outputs('作成_-_ヘッダー行'),',')[0]

//マップ（右辺）
replace(split(item(),',')?[0],'"','')
~~~
最後に、作成したテーブルをPower Appsに戻して準備完了です。
アプリ作成に移りましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/d5b96842-565d-51b9-d45f-a3d890d3d843.png)

### Power Apps でアプリ作成
アプリ作成画面に移ったら、OnStartプロパティに先ほど作成したワークフローを発火させる数式を入力します。「ゑ？ アプリ重くならない？」と、読者の皆さまと同じく最初は自分も思ったのですが、CSVファイルはものすごく軽いことが判明したため、こちらで対応して問題ないレベルだと思います。

![新規キャンバス1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/8023bbc9-2e34-911a-e700-4d17ea5bad02.jpeg)

今回、設備マスタ、従業員マスタ、品目マスタ、構成表マスタを取得するワークフローを作成しているため、その4つを発火させます。例として１つ記しておきます。

~~~
// 品目マスタをコレクションに取込む
ClearCollect(colItemMaster,
    ForAll(
        Table(ParseJSON(GENDataImport_ItemMaster.Run().output)),
        {
            品目コード: ThisRecord.Value.品目コード,
            品目名: ThisRecord.Value.品目名,
            品目グループ1: ThisRecord.Value.品目グループ1,
            品目グループ2: ThisRecord.Value.品目グループ2,
            品目グループ3: ThisRecord.Value.品目グループ3,
            管理単位: ThisRecord.Value.管理単位,
            非表示: ThisRecord.Value.非表示,
            ラインコード: ThisRecord.Value.ラインコード
        }
    )
);
~~~
結果、正常に4つのマスターデータを取り込むことに成功しました。意外だったのは、2000件以上のデータをこの方法だと取り込めてしまった点です。今後どういう問題が生じるのかは時間をかけて観察してみますが今のところ問題は起きていません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/608cf0e1-bcee-0535-4e2c-8b65803f5f67.png)

うーん、有識者の意見を求ム…。

### 追記：有識者現る

https://x.com/youseibubu/status/1828786620713345387

ということでした。ParseJSON 関数の動きをきちんと理解できていませんでしたが、ガツオさんとヨウセイさんのおかげでモヤモヤが解消されました。この場をお借りして御礼を申し上げます（いつもありがとうございます）

## 結：所感
こちら、Lookup 関数を多用するアプリとなるため、できれば Dataverse を扱えるのが望ましいのですが「本当に頑張れば」なんとかできる範囲ではあるように思いました。本当に頑張れば、です。Power Apps と Power Automate が末恐ろしいツールだなあと改めて感じました。

　とてもニッチな内容となってしまいましたが、なかなか有償ライセンスを導入してもらえないという方々に、この記事が広く遠くに届くことを願っております。