Power Automate

Power AutomateでCSVテーブルをJSON配列に変換したい

icteacher

経緯

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 ブックに変換する
CSV ファイルを Excel ブックに変換する
Power Automate で使用するために Excel テーブル データを JSON として出力する
Power Automate で使用するために Excel テーブル データを JSON として出力する

CSVファイルをExcelブックに変換できて、ExcelテーブルデータをJSONとして出力できるわけなんですから、CSVテーブルをJSON配列に変換することもできるはず!

解決方法

ということで、前置きが長くなってしまいごめんなさい。
CSVテーブルをJSON配列に変換するOfficeスクリプトはこちらです。

/**
* Convert incoming CSV data into JSON and return it as a string for Power Automate.
*/
function main(workbook: ExcelScript.Workbook, csv: string): string {
return JSON.stringify(convertCSVToJSON(csv));
}
/**
* Parses CSV data and converts it into a JSON array.
*/
function convertCSVToJSON(csv: string): object[] {
// Remove any Windows \r characters.
csv = csv.replace(/\r/g, “”);
// Split each line into a row.
const rows = csv.split(“\n”).filter(row => row.trim() !== “”);
if (rows.length < 2) return [];
// Extract headers from the first row.
const headers = splitCSVLine(rows[0]);
// Build JSON objects from rows.
const jsonData: object[] = rows.slice(1).map(row => {
const values = splitCSVLine(row);
let obj: { [key: string]: string } = {};
headers.forEach((header, index) => {
obj[header] = values[index] || “”;
});
return obj;
});
return jsonData;
}
/**
* Splits a CSV line into an array while handling quoted values.
*/
function splitCSVLine(line: string): string[] {
const regex = /(?:^|,)(?:”([^”]*(?:””[^”]*)*)”|([^,]*))/g;
let values: string[] = [];
let match: RegExpExecArray | null;
while ((match = regex.exec(line)) !== null) {
let value = match[1] !== undefined ? match[1].replace(/””/g, “\””) : match[2] || “”;
values.push(value);
}
return values;
}

解説

このコードは、CSVデータをJSON配列に変換し、その結果をPower Automate用の文字列として返すものです。それぞれの関数を詳しく解説します。


1. main 関数

function main(workbook: ExcelScript.Workbook, csv: string): string {
return JSON.stringify(convertCSVToJSON(csv));
}

main はエントリーポイントとなる関数です。

workbookExcelScript.Workbook 型)は使用していませんが、存在しないとエラーが発生するので、仕方なく記載しています。
csv はCSV形式の文字列データです。
convertCSVToJSON(csv) を呼び出してCSVデータをJSONオブジェクトの配列に変換します。

JSON.stringify でJSON配列を文字列化し、最終的な結果を文字列として返します。


2. convertCSVToJSON 関数

function convertCSVToJSON(csv: string): object[] {
// Remove any Windows \r characters.
csv = csv.replace(/\r/g, “”);
// Split each line into a row.
const rows = csv.split(“\n”).filter(row => row.trim() !== “”);
if (rows.length < 2) return [];
// Extract headers from the first row.
const headers = splitCSVLine(rows[0]);
// Build JSON objects from rows.
const jsonData: object[] = rows.slice(1).map(row => {
const values = splitCSVLine(row);
let obj: { [key: string]: string } = {};
headers.forEach((header, index) => {
obj[header] = values[index] || “”;
});
return obj;
});
return jsonData;
}

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 関数

function splitCSVLine(line: string): string[] {
const regex = /(?:^|,)(?:”([^”]*(?:””[^”]*)*)”|([^,]*))/g;
let values: string[] = [];
let match: RegExpExecArray | null;
while ((match = regex.exec(line)) !== null) {
let value = match[1] !== undefined ? match[1].replace(/””/g, “\””) : match[2] || “”;
values.push(value);
}
return values;
}

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行を配列として返す。


全体の流れ

  1. main 関数が convertCSVToJSON を呼び出す。
  2. convertCSVToJSON が CSV データを適切にパースし、JSON オブジェクトの配列を作成。
  3. splitCSVLine が、カンマ区切りやクオートの処理を適切に行い、1行のデータを正しく分割。
  4. 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()関数で配列にすることをお忘れなく。

ABOUT ME
みっきー♪
みっきー♪
ICTエバンジェリスト
元小学校教員が、Power Platformでの市民開発を中心に、自力でできる業務効率化の可能性を伝えていきます。
記事URLをコピーしました