// サイト定義書xlsxの1シートを、ブロック(文字列/数値/日付/説明/チェックボックス/添付ファイル)ごとに // 縦展開したレコード配列へ変換する。読み取り専用の調査用スクリプト(ファイルへの書き込みは行わない)。 const fs = require("fs"); const XLSX = require("xlsx"); const [, , xlsxPath, sheetName, outPath] = process.argv; const wb = XLSX.readFile(xlsxPath); const ws = wb.Sheets[sheetName]; if (!ws) { console.error("シートが見つかりません:", sheetName, "候補:", wb.SheetNames); process.exit(1); } const rows = XLSX.utils.sheet_to_json(ws, { header: 1, defval: "" }); // ヘッダー行(2行目、0-indexed row1)の3列目が「タブ」かどうかでブロック幅を自動判定する。 // シートによって「タブ」列の有無が異なるため(site-335411は有り、site-335410は無し)。 // また「サンプル項目有無」列は先頭の文字列ブロックのみに存在し、それ以外のブロックには無い(不均等な列幅)。 const hasTabColumn = String((rows[1] && rows[1][2]) || "").trim() === "タブ"; const firstBlockOff = hasTabColumn ? { col: 0, tab: 1, label: 2, show: 3, req: 4, ro: 5, lock: 6, style: 7, sample: 8, ver: 9, note: 10, other: 11 } : { col: 0, tab: -1, label: 1, show: 2, req: 3, ro: 4, lock: 5, style: 6, sample: 7, ver: 8, note: 9, other: 10 }; const restBlockOff = hasTabColumn ? { col: 0, tab: 1, label: 2, show: 3, req: 4, ro: 5, lock: 6, style: 7, sample: -1, ver: 8, note: 9, other: 10 } : { col: 0, tab: -1, label: 1, show: 2, req: 3, ro: 4, lock: 5, style: 6, sample: -1, ver: 7, note: 8, other: 9 }; const firstBlockWidth = Math.max(...Object.values(firstBlockOff)) + 1; const restBlockWidth = Math.max(...Object.values(restBlockOff)) + 1; const kinds = ["文字列", "数値", "日付", "説明", "チェックボックス", "添付ファイル"]; const blocks = kinds.map((kind, i) => { const start = i === 0 ? 1 : 1 + firstBlockWidth + restBlockWidth * (i - 1); const off = i === 0 ? firstBlockOff : restBlockOff; const abs = {}; for (const [k, v] of Object.entries(off)) abs[k] = v === -1 ? -1 : start + v; return { kind, ...abs }; }); const records = []; for (let r = 2; r < rows.length; r++) { const row = rows[r]; for (const b of blocks) { const colName = String(row[b.col] || "").trim(); if (!colName) continue; records.push({ rowIndex: r + 1, // 1-indexed excel row kind: b.kind, ColumnName: colName, tab: row[b.tab] || "", label: row[b.label] || "", show: row[b.show] || "", req: row[b.req] || "", readOnly: row[b.ro] || "", lock: row[b.lock] || "", style: row[b.style] || "", sample: b.sample >= 0 ? row[b.sample] || "" : "", ver: row[b.ver] || "", note: row[b.note] || "", other: row[b.other] || "", }); } } fs.writeFileSync(outPath, JSON.stringify(records, null, 2), "utf8"); console.log("件数:", records.length, "→", outPath);