テーマの整理:「配列ユーティリティ × CSV 変換」とは何か
ここで扱うのは、「JavaScript の配列(オブジェクト配列)を、業務でそのまま使える CSV 文字列に変換するユーティリティ」です。 CSV は、Excel・スプレッドシート・BI ツール・他システム連携など、実務でめちゃくちゃよく使われます。
だからこそ、
配列 → CSV CSV → ダウンロード CSV → 別システムへ送信
この流れを、毎回手書きではなく「ユーティリティ」として持っておくと、仕事がかなり楽になります。
基本コンセプト:オブジェクト配列を「ヘッダー+行」に落とし込む
どんな配列を CSV にするのか
業務でよくある形は、こんな配列です。
const rows = [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" },
{ id: 3, name: "Carol", email: "carol@example.com" },
];
JavaScriptこれを CSV にすると、こういうイメージになります。
id,name,email
1,Alice,alice@example.com
2,Bob,bob@example.com
3,Carol,carol@example.com
つまり、
1 行目が「ヘッダー(列名)」 2 行目以降が「データ行」
という構造です。
ヘッダーをどう決めるか
一番シンプルなのは、「最初のオブジェクトのキーをヘッダーにする」方法です。
const header = Object.keys(rows[0]); // ["id", "name", "email"]
JavaScript業務では「列順を指定したい」「表示名を変えたい」ことも多いので、 後で「ヘッダーを明示的に渡す」形にも拡張できるようにしておくとよいです。
実装:配列 → CSV 文字列の基本ユーティリティ
コア関数:toCsv
まずは、初心者でも読めるレベルで、ちゃんと業務で使える CSV 変換関数を書きます。
function escapeCsvValue(value) {
if (value === null || value === undefined) {
return "";
}
const str = String(value);
const needsQuote =
str.includes(",") ||
str.includes('"') ||
str.includes("\n") ||
str.includes("\r");
if (!needsQuote) {
return str;
}
const escaped = str.replace(/"/g, '""');
return `"${escaped}"`;
}
function toCsv(rows, headerKeys) {
if (!Array.isArray(rows) || rows.length === 0) {
return "";
}
const keys =
Array.isArray(headerKeys) && headerKeys.length > 0
? headerKeys
: Object.keys(rows[0]);
const headerLine = keys.join(",");
const dataLines = rows.map((row) => {
return keys
.map((key) => escapeCsvValue(row[key]))
.join(",");
});
return [headerLine, ...dataLines].join("\n");
}
JavaScript重要ポイントをかみ砕いて説明
escapeCsvValue が「1 つのセルの値を CSV 用に安全にする」役割です。 カンマ・ダブルクォート・改行が含まれる場合は、ダブルクォートで囲み、内部の " は "" にエスケープします。 null や undefined は空文字にしておくと、Excel などで扱いやすいです。
toCsv は「配列全体を CSV 文字列にする」関数です。 headerKeys が渡されていればそれを列順として使い、なければ最初の行のキーを使います。 各行は「キー順に値を取り出して、カンマで結合」して作ります。 最後に、ヘッダー行+データ行を \n で結合して 1 つの文字列にします。
この時点で、かなり実務でそのまま使えるレベルになっています。
例題 1:ユーザー一覧を CSV にしてコンソールに出す
コード
const users = [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" },
{ id: 3, name: "Carol", email: "carol@example.com" },
];
const csv = toCsv(users);
console.log(csv);
JavaScript出力イメージはこうなります。
id,name,email
1,Alice,alice@example.com
2,Bob,bob@example.com
3,Carol,carol@example.com
ここでのポイントは、
配列のキー順がそのまま列順になっている。 特別な文字がないので、エスケープもシンプル。
というところです。
例題 2:日本語やカンマ・改行を含む値を CSV にする
シナリオ
業務では、名前や備考に日本語・カンマ・改行が普通に入ります。 これを正しく CSV にしないと、Excel で開いたときに列がズレます。
コード
const items = [
{ id: 1, name: "りんご", note: "赤い, おいしい" },
{ id: 2, name: "バナナ", note: "黄色\n南国フルーツ" },
{ id: 3, name: "ぶどう", note: "「高級」フルーツ" },
];
const csv = toCsv(items);
console.log(csv);
JavaScript出力イメージ(概念的):
id,name,note
1,りんご,"赤い, おいしい"
2,バナナ,"黄色
南国フルーツ"
3,ぶどう,"""高級""フルーツ"
ここでの重要ポイントは、
カンマを含む note は "..." で囲まれている。 改行を含む note も "..." で囲まれていて、1 セルとして扱われる。 ダブルクォートを含む note は "" にエスケープされている。
このエスケープができていないと、CSV は「見た目はそれっぽいけど壊れている」状態になります。 業務で CSV を扱うなら、ここは絶対に押さえておきたいところです。
例題 3:列順・列名を指定して CSV を作る
シナリオ
業務では、「出力する列の順番」「列名」を仕様で決められていることが多いです。 内部のキー名と CSV のヘッダー名を変えたいこともあります。
列順だけ指定する場合
const users = [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" },
];
const csv = toCsv(users, ["name", "email", "id"]);
console.log(csv);
JavaScript出力イメージ:
name,email,id
Alice,alice@example.com,1
Bob,bob@example.com,2
列名も変えたい場合(ラッパーを作る)
function toCsvWithHeaderMap(rows, headerMap) {
const keys = Object.keys(headerMap); // ["id", "name", "email"]
const headerLine = keys.map((k) => headerMap[k]).join(",");
const dataLines = rows.map((row) => {
return keys
.map((key) => escapeCsvValue(row[key]))
.join(",");
});
return [headerLine, ...dataLines].join("\n");
}
const users = [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" },
];
const headerMap = {
id: "ユーザーID",
name: "氏名",
email: "メールアドレス",
};
const csv = toCsvWithHeaderMap(users, headerMap);
console.log(csv);
JavaScript出力イメージ:
ユーザーID,氏名,メールアドレス
1,Alice,alice@example.com
2,Bob,bob@example.com
ここでのポイントは、
内部のキー(id, name, email)と、CSV のヘッダー名(日本語)が分離されている。 仕様変更でヘッダー名が変わっても、headerMap だけ直せばよい。
というところです。
CSV 変換ユーティリティで意識してほしい重要ポイント
「壊れた CSV」を絶対に出さない
CSV は「ただのテキスト」なので、壊れていても一見それっぽく見えます。 でも、Excel や他システムに読み込ませたときに列がズレたり、行が分割されたりして地獄になります。
だからこそ、
カンマ・ダブルクォート・改行を含む値は必ずエスケープする。 null / undefined はどう扱うかを決めておく(空文字にするのが無難)。 ヘッダー行とデータ行の列数が必ず一致するようにする。
このあたりは「CSV ユーティリティの品質」として、かなり重要です。
「文字コード」と「改行コード」を意識する(軽く触れておく)
ブラウザでダウンロードする CSV は、だいたい UTF-8+\n で問題ありません。 Windows の古い環境や一部ツールでは、Shift_JIS や \r\n が求められることもあります。
初心者のうちは、
まずは UTF-8+\n で作る。 もし「文字化けする」「改行がおかしい」と言われたら、そこから調べる。
くらいのスタンスで十分です。
手を動かして「配列 → CSV」の感覚をつかむ
次のコードを実行して、 「シンプルな配列」「日本語・カンマ・改行を含む配列」「列順指定」の CSV 出力を体感してみてください。
function escapeCsvValue(value) {
if (value === null || value === undefined) {
return "";
}
const str = String(value);
const needsQuote =
str.includes(",") ||
str.includes('"') ||
str.includes("\n") ||
str.includes("\r");
if (!needsQuote) {
return str;
}
const escaped = str.replace(/"/g, '""');
return `"${escaped}"`;
}
function toCsv(rows, headerKeys) {
if (!Array.isArray(rows) || rows.length === 0) {
return "";
}
const keys =
Array.isArray(headerKeys) && headerKeys.length > 0
? headerKeys
: Object.keys(rows[0]);
const headerLine = keys.join(",");
const dataLines = rows.map((row) => {
return keys
.map((key) => escapeCsvValue(row[key]))
.join(",");
});
return [headerLine, ...dataLines].join("\n");
}
function demo() {
const users = [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" },
];
console.log("=== basic ===");
console.log(toCsv(users));
const items = [
{ id: 1, name: "りんご", note: "赤い, おいしい" },
{ id: 2, name: "バナナ", note: "黄色\n南国フルーツ" },
{ id: 3, name: "ぶどう", note: "「高級」フルーツ" },
];
console.log("=== with japanese & special chars ===");
console.log(toCsv(items));
console.log("=== custom column order ===");
console.log(toCsv(users, ["name", "email", "id"]));
}
demo();
JavaScriptまとめ:CSV 変換ユーティリティで「配列をそのまま業務連携の材料にする」
配列 → CSV は、 「コードの世界の配列を、Excel や他システムが理解できる形に変える橋渡し」です。
プロジェクトに例えば次のような形で置いておくイメージです。
export function toCsv(rows, headerKeys) { ... }
export function escapeCsvValue(value) { ... }
JavaScriptそして、
一覧データのエクスポート、 レポート出力、 他システムへの連携ファイル生成
といったところでは、必ずこのユーティリティを通す。
こう決めておくと、「毎回 CSV を手書きする」「壊れた CSV を量産する」といった事故が減り、 配列データがそのまま“業務の材料”として使えるようになっていきます。
CSV は地味だけど、仕事では主役級です。 そこにちゃんとしたユーティリティを用意しておくのは、かなり“仕事ができるエンジニア”の動き方です。
