const fs = require('fs'); const path = require('path'); const { parse } = require('csv-parse/sync'); const { stringify } = require('csv-stringify/sync'); const csvDir = './csv'; const dataDir = './data'; function appendWithNewlineIfNeeded(filePath, text) { if (!text) return; const stat = fs.statSync(filePath); let prefix = ''; if (stat.size > 0) { const fd = fs.openSync(filePath, 'r'); try { const buffer = Buffer.alloc(1); fs.readSync(fd, buffer, 0, 1, stat.size - 1); const lastChar = buffer.toString('utf-8'); if (lastChar !== '\n') { prefix = '\n'; } } finally { fs.closeSync(fd); } } fs.appendFileSync(filePath, prefix + text, 'utf-8'); } function writeOrAppendCsv(filePath, rows) { if (!rows || rows.length === 0) return; const hasContent = fs.existsSync(filePath) && fs.statSync(filePath).size > 0; const columns = Object.keys(rows[0]); if (!hasContent) { const csvText = stringify(rows, { header: true, columns }); fs.writeFileSync(filePath, csvText, 'utf-8'); return; } // 既存ファイルがある場合は「データ行のみ」を末尾に追加 // stringify は末尾改行を付けないケースがあるため、追記前に改行を補う const dataOnlyText = stringify(rows, { header: false, columns }); appendWithNewlineIfNeeded(filePath, dataOnlyText); } // dataフォルダが存在しなければ作成 if (!fs.existsSync(dataDir)) { fs.mkdirSync(dataDir, { recursive: true }); } // csvフォルダのファイルを読み込み const files = fs.readdirSync(csvDir).filter(file => file.endsWith('.csv')); files.forEach(file => { const filePath = path.join(csvDir, file); const content = fs.readFileSync(filePath, 'utf-8'); // CSV解析 const records = parse(content, { columns: true, skip_empty_lines: true }); // 1項目目をグループ化 const grouped = {}; records.forEach(record => { const firstValue = Object.values(record)[0]; if (!grouped[firstValue]) { grouped[firstValue] = []; } grouped[firstValue].push(record); }); // グループごとにファイル出力 Object.entries(grouped).forEach(([name, rows]) => { const outputFile = path.join(dataDir, `${name}_スケジュール.csv`); writeOrAppendCsv(outputFile, rows); }); }); console.log('処理完了');