// Excel定義書の展開データとサイトの実Columnsデータを突き合わせ、差分を出力する。 // 読み取り専用の調査用スクリプト(ファイルへの書き込みは行わない)。 const fs = require("fs"); const [, , excelJsonPath, siteJsonPath, outPath] = process.argv; const excelRecords = JSON.parse(fs.readFileSync(excelJsonPath, "utf8")); const siteRecords = JSON.parse(fs.readFileSync(siteJsonPath, "utf8")); const excelByCol = new Map(); for (const r of excelRecords) { if (!excelByCol.has(r.ColumnName)) excelByCol.set(r.ColumnName, r); } const siteByCol = new Map(siteRecords.map((r) => [r.ColumnName, r])); const excelOnly = []; const siteOnly = []; const mismatches = []; for (const [col, ex] of excelByCol) { if (["状況", "タイトル", "コメント"].includes(col)) continue; // 固定列(Status/Title/Comments)は別名管理のためスキップ const isBlankTemplateRow = !ex.label; // ラベル未記入=未使用項目のテンプレート行(tab/other等に列名メモが残っている場合がある) if (isBlankTemplateRow) continue; const s = siteByCol.get(col); if (!s) { excelOnly.push({ ColumnName: col, label: ex.label, note: ex.note }); continue; } const diffs = []; const exShow = ex.show || ""; const wantHide = exShow.includes("非表示"); if (wantHide !== s.Hide) diffs.push(`表示有無: Excel="${exShow}" / サイトHide=${s.Hide}`); const exReq = !!(ex.req || "").trim(); const siteReq = s.ValidateRequired || s.ProcessRequired; if (exReq !== siteReq) diffs.push(`入力必須: Excel="${ex.req}" / サイトValidateRequired=${s.ValidateRequired} ProcessRequired=${s.ProcessRequired}`); const exRo = !!(ex.readOnly || "").trim(); const siteRo = !!s.ExtendedFieldCss; if (exRo !== siteRo) diffs.push(`読み取り専用: Excel="${ex.readOnly}" / サイトExtendedFieldCss="${s.ExtendedFieldCss}"`); const exLock = !!(ex.lock || "").trim(); if (exLock !== s.StatusLocked) diffs.push(`編集不可(ロック): Excel="${ex.lock}" / サイトStatusLocked=${s.StatusLocked}`); if (ex.label && ex.label !== s.LabelText && ex.label !== s.GridLabelText) { diffs.push(`ラベル: Excel="${ex.label}" / サイトLabelText="${s.LabelText}" GridLabelText="${s.GridLabelText}"`); } const exStyle = (ex.style || "").trim(); const siteStyleWide = s.FieldCss === "field-wide"; if (exStyle === "ワイド" && !siteStyleWide) diffs.push(`スタイル: Excel="ワイド" / サイトFieldCss="${s.FieldCss}"`); if (exStyle === "ノーマル" && siteStyleWide) diffs.push(`スタイル: Excel="ノーマル" / サイトFieldCss="${s.FieldCss}"`); if (diffs.length) mismatches.push({ ColumnName: col, diffs }); } for (const [col, s] of siteByCol) { if (!excelByCol.has(col)) { siteOnly.push({ ColumnName: col, LabelText: s.LabelText, GridLabelText: s.GridLabelText, Hide: s.Hide, Tab: s.Tab }); } } const result = { excelOnly, siteOnly, mismatches }; fs.writeFileSync(outPath, JSON.stringify(result, null, 2), "utf8"); console.log("Excelのみ(サイト側に無い→削除候補):", excelOnly.length); console.log("サイトのみ(Excel未記載→追加候補):", siteOnly.length); console.log("属性不一致:", mismatches.length); console.log("詳細:", outPath);