- 원본 누계 표지(F·a)를 읽어 계산마다 소계로 다시 구함 - 산출 줄 커서 자리에 누계 넣기, 표지 반올림 방식·자리 반영 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
62 lines
3.1 KiB
JavaScript
62 lines
3.1 KiB
JavaScript
// 원본 수량산출 누계(TfrmMulWord ActionAdd Ctrl+U → 0x11155c4, 재계산 0x111c0b0 에서 F·a 표지 다시 계산).
|
|
// 누계 값 = 가장 가까운 위쪽 품명 줄(포함) 또는 앞 누계 줄(제외)부터 누계 줄 바로 위까지, 줄마다 첫 결과 수량의 합.
|
|
// 앞 누계는 더하지 않는 소계다. 반올림은 표지 이름 뒤 방식·자리(F000003 + 1 + 2), 없으면 산출서 설정.
|
|
// 웹은 누계를 \x16 쌍으로 적고 이름을 row.totals 에 둔다. 「누계」·「∴」 같은 글자는 넣지 않는다.
|
|
const EstQuantityTotal = (() => {
|
|
const first = (line) => {
|
|
const match = String(line ?? "").match(/\x12([-\d.,]+)\x12/);
|
|
return match ? Number(match[1].replaceAll(",", "")) || 0 : 0;
|
|
};
|
|
function format(value, digits) {
|
|
return value.toLocaleString("en-US", { maximumFractionDigits: digits, useGrouping: true });
|
|
}
|
|
function rounding(sheet, name) {
|
|
const match = String(name ?? "").match(/^[Fa]\d{6}([123])(\d)$/);
|
|
return {
|
|
method: match ? Number(match[1]) : (sheet.options?.roundMode ?? 2),
|
|
digits: match ? Number(match[2]) : (sheet.options?.digits ?? 2),
|
|
};
|
|
}
|
|
// rows: 계산이 끝난 줄(LineData 의 결과 값이 갱신된 것). 누계 줄의 \x16 값을 고쳐 쓴다.
|
|
function apply(sheet, rows) {
|
|
let start = 0;
|
|
rows.forEach((row, i) => {
|
|
const line = String(row.LineData ?? "");
|
|
if (line.includes("\x16")) {
|
|
let sum = 0;
|
|
for (let j = start; j < i; j++) sum += first(rows[j].LineData);
|
|
const names = sheet.rows[i]?.totals || [];
|
|
let part = 0;
|
|
row.LineData = line.replace(/\x16[^\x16]*\x16/g, () => {
|
|
const { method, digits } = rounding(sheet, names[part++]);
|
|
return `\x16${format(EstMath.fixed(sum, digits, method), digits)}\x16`;
|
|
});
|
|
start = i + 1;
|
|
} else if (line.includes("\x0e")) start = i;
|
|
});
|
|
return rows;
|
|
}
|
|
// 커서 자리에 새 누계를 넣는다. text 는 화면 표기(⟦누계⟧) 줄, caret 은 그 안의 위치.
|
|
function insert(sheet, rowIndex, caret, text) {
|
|
const row = sheet.rows[rowIndex];
|
|
if (!row) throw Error("누계를 넣을 산출 줄을 고르세요.");
|
|
const used = new Set(sheet.rows.flatMap((r) => (r.totals || []).map((n) => n.slice(1, 7))));
|
|
let n = 1;
|
|
while (used.has(String(n).padStart(6, "0"))) n++;
|
|
const { method, digits } = rounding(sheet, "");
|
|
const name = `F${String(n).padStart(6, "0")}${method}${digits}`,
|
|
shown = text ?? EstText.display(row.LineData),
|
|
at = Math.max(0, Math.min(caret, shown.length)),
|
|
position = shown.slice(0, at).split("⟦누계⟧").length - 1;
|
|
const before = shown.slice(0, at);
|
|
if (position % 2 || before.lastIndexOf("⟦") > before.lastIndexOf("⟧"))
|
|
throw Error("누계 표지 안에는 넣을 수 없습니다.");
|
|
row.LineData = EstText.encode(`${shown.slice(0, at)}⟦누계⟧0⟦누계⟧${shown.slice(at)}`);
|
|
row.totals = [...(row.totals || [])];
|
|
row.totals.splice(position / 2, 0, name);
|
|
sheet.markerEdited = true;
|
|
return name;
|
|
}
|
|
return { apply, insert, rounding };
|
|
})();
|