86 lines
2.5 KiB
JavaScript
86 lines
2.5 KiB
JavaScript
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('処理完了'); |