data-export について
Node.js と Python のアプリケーションで、データのエクスポートや CSV 解析を実装するための実用スキルです。大規模データのストリーミング、表計算ファイルの生成、ダウンロードヘッダー、運用時の確認事項を扱います。
主な機能
- 01Node.js での CSV ストリーミング出力
- 02ExcelJS による Excel ワークブック生成
- 03大規模 Excel 出力のストリーミング
- 04Papa Parse によるアップロード CSV の解析
- 05openpyxl による Python での Excel ファイル作成
- 06エクスポートの安全性と運用チェック
活用シーン
- 01データベースのレコードをダウンロード可能な CSV として出力
- 02アプリケーションデータから Excel レポートを生成
- 03フロントエンドでアップロードされた CSV を解析
- 04全データをメモリに読み込まずに大規模出力を処理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill data-exportインストール後、Claude Code で/data-exportを入力して読み込まれたか確認します。
詳細
データのエクスポート
CSV エクスポート(Node.js)
import { stringify } from 'csv-stringify';
import { pipeline } from 'stream/promises';
// Streaming CSV (handles large datasets)
app.get('/api/export/users.csv', async (req, res) => {
res.setHeader('Content-Type', 'text/csv');
res.setHeader('Content-Disposition', 'attachment; filename="users.csv"');
const cursor = db.collection('users').find().cursor();
const csvStringifier = stringify({
header: true,
columns: ['name', 'email', 'createdAt'],
});
await pipeline(cursor, csvStringifier, res);
});
// Simple in-memory CSV
import { stringify } from 'csv-stringify/sync';
const csv = stringify(rows, { header: true, columns: ['name', 'email', 'amount'] });
Excel エクスポート(ExcelJS — 推奨)
import ExcelJS from 'exceljs';
app.get('/api/export/report.xlsx', async (req, res) => {
const workbook = new ExcelJS.Workbook();
const sheet = workbook.addWorksheet('Report');
// Headers with styling
sheet.columns = [
{ header: 'Name', key: 'name', width: 25 },
{ header: 'Email', key: 'email', width: 30 },
{ header: 'Amount', key: 'amount', width: 15 },
];
sheet.getRow(1).font = { bold: true };
// Data
const users = await getUsers();
users.forEach((u) => sheet.addRow(u));
// Number formatting
sheet.getColumn('amount').numFmt = '$#,##0.00';
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader('Content-Disposition', 'attachment; filename="report.xlsx"');
await workbook.xlsx.write(res);
});
大規模データセット向け Excel のストリーミング
const workbook = new ExcelJS.stream.xlsx.WorkbookWriter({ stream: res });
const sheet = workbook.addWorksheet('Data');
sheet.columns = [{ header: 'Name', key: 'name' }, { header: 'Value', key: 'value' }];
for await (const row of cursor) {
sheet.addRow(row).commit(); // Flushes row to stream
}
await workbook.commit();
フロントエンドでの CSV パース(Papa Parse)
import Papa from 'papaparse';
// Parse uploaded CSV
const result = Papa.parse<UserRow>(file, {
header: true,
skipEmptyLines: true,
dynamicTyping: true,
complete: (results) => {
console.log(results.data); // Parsed rows
console.log(results.errors); // Parse errors
},
});
// Generate CSV in browser
const csv = Papa.unparse(data);
const blob = new Blob([csv], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
Python(openpyxl)
from openpyxl import Workbook
from io import BytesIO
def export_excel(data: list[dict]) -> bytes:
wb = Workbook()
ws = wb.active
ws.title = "Report"
headers = list(data[0].keys())
ws.append(headers)
for row in data:
ws.append([row[h] for h in headers])
buffer = BytesIO()
wb.save(buffer)
return buffer.getvalue()
アンチパターン
| アンチパターン | 対策 |
|---|---|
| すべてのデータをメモリに読み込む | 大規模なエクスポートでは、DB カーソルからストリーミングします |
| Content-Disposition ヘッダーがない | ブラウザーからダウンロードする場合は必ず設定します |
| リクエストハンドラーでエクスポートを生成する | 10K 行を超える場合はバックグラウンドジョブを使用します |
| 進行状況を表示しない | 大規模なエクスポートの進行状況には WebSocket/SSE を使用します |
| CSV 値をエスケープしない | ライブラリ(csv-stringify、Papa Parse)を使用します |
本番環境チェックリスト
- 10K 行を超えるデータセットにはストリーミングを使用する
- 大規模なエクスポートにはバックグラウンドジョブキューを使用する
- Content-Type および Content-Disposition ヘッダーを適切に設定する
- メモリ制限を監視する
- エクスポートエンドポイントにレート制限を設定する
- ディスクに書き込む場合、一時ファイルを削除する
コメント
Markdown 対応