Power AutomateでCSVテーブルをJSON配列に変換したい
経緯
Power AutomateでJSON配列をCSVテーブルに変換するのは簡単です。
アクション「CSVテーブルの作成」を使用すればいいんですから。
でも、CSVテーブルをJSON配列に変換したいときは?
ないんですよね、これが。逆のアクションがないんです。2025年3月現在でも。
いや、必要でしょ!依然としてシステムの多くはCSVファイルでデータをエクスポートしてくるんだから!そのデータを扱いたいでしょうが!市民開発なら尚のことです。なぜ反対向きのアクションの提供してくれないの!?
なんて、文句を言ってても仕方ありません。
「よーし、ないなら作ってやろうじゃないの!」
ということで、Google検索!CSVテーブルをJSON配列に変換している猛者のブログを参考にフローを組んでみたのですが、
アクションが多すぎるよ、、、
何が困るって、1行ごとにApply to Eachで処理するので、アクションが行数倍実行されるんです。
わずか2アクションで処理しても5000行あったら10000万アクションです。フローごとの 24 時間あたりのアクション要求数を使い切ってしまいますし、処理に時間もかかります。
やりたいことはただの変換なんです。1アクションであっという間に処理してしまいたい。
というわけで、悩んだ挙句、別のアプローチをとりました。
Office スクリプトの利用です。
本来はExcelブックでの作業を再現して自動化するためのもの(ExcelVBAのオンライン版みたいなもの)なんですが、Power Automateから実行して、結果をPower Automateに返すこともできます。
公式に以下のシナリオが公開されています。


CSVファイルをExcelブックに変換できて、ExcelテーブルデータをJSONとして出力できるわけなんですから、CSVテーブルをJSON配列に変換することもできるはず!
解決方法
ということで、前置きが長くなってしまいごめんなさい。
CSVテーブルをJSON配列に変換するOfficeスクリプトはこちらです。
解説
このコードは、CSVデータをJSON配列に変換し、その結果をPower Automate用の文字列として返すものです。それぞれの関数を詳しく解説します。
1. main
関数
main
はエントリーポイントとなる関数です。
workbook
(ExcelScript.Workbook
型)は使用していませんが、存在しないとエラーが発生するので、仕方なく記載しています。csv
はCSV形式の文字列データです。convertCSVToJSON(csv)
を呼び出してCSVデータをJSONオブジェクトの配列に変換します。
JSON.stringify
でJSON配列を文字列化し、最終的な結果を文字列として返します。
2. convertCSVToJSON
関数
csv.replace(/\r/g, "");
Windowsの改行コード(\r\n
)をUnix形式(\n
)に統一するため、\r
(キャリッジリターン)を削除します。
const rows = csv.split("\n").filter(row => row.trim() !== "");
CSVデータを改行(\n
)で分割して配列にし、空行を除外します。
if (rows.length < 2) return [];
最低でも1行目にヘッダー、2行目以降にデータが必要なため、行数が2未満の場合は空の配列を返します。
const headers = splitCSVLine(rows[0]);
最初の行(ヘッダー行)をsplitCSVLine
関数で分割し、カラム名(キー)を取得します。
const jsonData: object[] = rows.slice(1).map(row => { ... });
2行目以降のデータをループ処理してJSONオブジェクトの配列を作成します。
const values = splitCSVLine(row);
データ行をカンマ区切りで分割し、values
配列を作成します。
let obj: { [key: string]: string } = {};
で空のオブジェクトを作成します。
headers.forEach((header, index) => { obj[header] = values[index] || ""; });
header
(カラム名)と対応するデータ値をセットし、オブジェクトを作成します。
値がない場合は空文字(""
)をセットします。
return jsonData;
最終的に、JSON形式のオブジェクト配列を返します。
3. splitCSVLine
関数
const regex = /(?:^|,)(?:"([^"]*(?:""[^"]*)*)"|([^,]*))/g;
CSVの各フィールドを適切に分割するための正規表現。"..."
で囲まれた値はそのまま取り出し、ダブルクオート(""
)はエスケープとして解釈。,
(カンマ)で区切られた非クオート値も正しく取得。
let values: string[] = [];
抽出した値を格納する配列。
let match: RegExpExecArray | null;
while ((match = regex.exec(line)) !== null) { ... }
regex.exec(line)
を使って line
の中で次にマッチするフィールドを取得する。RegExpExecArray
とは:exec()
の戻り値で、マッチした詳細情報を含む配列オブジェクト。
マッチしない場合は null
を返すため、match: RegExpExecArray | null
として型を宣言。
let value = match[1] !== undefined ? match[1].replace(/""/g, "\"") : match[2] || "";
match[1]
に値がある場合(クオートされたフィールド)、match[1].replace(/""/g, "\"")
""
(エスケープされたダブルクオート)を "
に変換
それ以外(通常の値)の場合、match[2] || ""
match[2]
に値があればそのまま使う。match[2]
が undefined
の場合は ""
(空文字)を代入。
values.push(value);
取得した値を配列に追加。
return values;
CSVの1行を配列として返す。
全体の流れ
main
関数がconvertCSVToJSON
を呼び出す。convertCSVToJSON
が CSV データを適切にパースし、JSON オブジェクトの配列を作成。splitCSVLine
が、カンマ区切りやクオートの処理を適切に行い、1行のデータを正しく分割。- JSON配列を
JSON.stringify
で文字列化し、Power Automate で扱いやすい形にして返す。
結果として何をしているのか
このコードは CSVデータをJSON形式の文字列に変換する処理 を行っています。
CSVのデータが "name,age\nAlice,30\nBob,25"
だった場合、以下のようなJSONが生成されます:
[
{ "name": "Alice", "age": "30" },
{ "name": "Bob", "age": "25" }
]
そして main
関数によって、これが文字列として返されます:
"[{\"name\":\"Alice\",\"age\":\"30\"},{\"name\":\"Bob\",\"age\":\"25\"}]"
この結果はPower Automateなどのツールで処理しやすい形になっています。
感想
めちゃくちゃ疲れました。1行ずつよく読めば分かるし興味深いけど、やっぱりOfficeスクリプトは苦手です。ローコードツールを使うために、コーディングするのも受け入れがたい。そんなに英語も得意じゃないし、そもそも最終目的はJSON配列に変換することじゃないんですよね。JSON配列を利用して何かがしたいわけです。
だから、上記のOfficeスクリプトが書かれている.ostsファイルも置いておきます。
変換方法は分からなくていいから、とりあえず変換がしたいという方はそのままOneDriveかSharePointにアップロードして、Power Automateから呼び出してみてください。返ってくる文字列をJSON()関数で配列にすることをお忘れなく。