feat(est-test): 엑셀형 수량산출서 읽기 전용 표시

- 원본 엑셀형 산출서 본문(OLE2 .xls BIFF8) 셀 값을 읽는 xls-read.cjs
- 가져올 때 시트를 붙이고 수량산출 화면에 읽기 전용 격자로 표시

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-11 19:49:49 +09:00
co-authored by Claude Opus 5.5
parent 5b2ebeb676
commit 6f32263ea3
7 changed files with 335 additions and 8 deletions
+31 -1
View File
@@ -137,5 +137,35 @@ const EstQuantitySheets = (() => {
return true;
}
return { copy, move, mark, free, handle };
// 엑셀형 수량산출서(원본 TFRMMULEXCEL) — 가져온 셀 값을 읽기 전용 격자로 보인다. 수식 셀은 저장된 계산값(굵게).
function excelView(sheet) {
if (!sheet?.excel?.length) return "";
const { esc, number } = EstApp;
const letter = (n) => {
let s = "";
for (n += 1; n > 0; n = Math.floor((n - 1) / 26))
s = String.fromCharCode(65 + ((n - 1) % 26)) + s;
return s;
};
return sheet.excel
.map(({ name, cells }) => {
const keys = Object.keys(cells).map((k) => k.split(",").map(Number));
if (!keys.length) return "";
const rows = Math.max(...keys.map(([r]) => r)) + 1,
cols = Math.min(40, Math.max(...keys.map(([, c]) => c)) + 1);
const body = Array.from({ length: rows }, (_, r) => {
const cellsHtml = Array.from({ length: cols }, (_, c) => {
const cell = cells[`${r},${c}`];
if (!cell) return "<td></td>";
const value = typeof cell.value === "number" ? number(cell.value) : esc(cell.value);
return `<td${cell.formula ? ' style="font-weight:bold" title="수식(저장된 계산값)"' : ""}>${value}</td>`;
}).join("");
return `<tr><th>${r + 1}</th>${cellsHtml}</tr>`;
}).join("");
return `<h4>엑셀형 산출서 · ${esc(name)} (읽기 전용)</h4><div style="overflow:auto;max-height:420px"><table class="sheet" style="font-size:11px"><thead><tr><th></th>${Array.from({ length: cols }, (_, c) => `<th>${letter(c)}</th>`).join("")}</tr></thead><tbody>${body}</tbody></table></div>`;
})
.join("");
}
return { copy, move, mark, free, excelView, handle };
})();