diff --git a/resources/tester/spreadsheet/harness_links.html b/resources/tester/spreadsheet/harness_links.html new file mode 100644 index 00000000..04d11161 --- /dev/null +++ b/resources/tester/spreadsheet/harness_links.html @@ -0,0 +1,22 @@ + + + + + 알약 막대 시험 틀 + + + +
+ + + diff --git a/resources/tester/spreadsheet/harness_links.ts b/resources/tester/spreadsheet/harness_links.ts new file mode 100644 index 00000000..9b36313a --- /dev/null +++ b/resources/tester/spreadsheet/harness_links.ts @@ -0,0 +1,57 @@ +/* 알약 막대 시험 틀 — 진짜 부품(createSpreadsheet)에 `links` 선택 · 가짜 입력값 · 가짜 자재 목록. + * Vite 개발 서버가 바로 풂: /resources/tester/spreadsheet/harness_links.html?mode=입력|자재 + * window.ss = 부품 손잡이(getDoc · getLinkedValues) · window.ssFind = 자재찾기 부른 글 목록 */ +import "../../../ui_template/ui_template_theme.css"; // 앱 색 · 간격 토큰 +import { createSpreadsheet } from "../../../A00_Common/spreadsheet/spreadsheet"; +import type { LinkMaterial, Workbook } from "../../../A00_Common/spreadsheet/spreadsheet"; + +const w = window as unknown as Record; +const mode = new URLSearchParams(location.search).get("mode") === "자재" ? "자재" : "입력"; + +const book: Workbook = { + 종류: "통합문서", + 판: 1, + 열: "harness", + 서식: [{}], + 시트: [ + { + id: "s1", + 이름: "면적산출", + 칸: { + A1: { 값: "길이" }, + B1: { 값: 12.5 }, + A2: { 값: "높이" }, + B2: { 값: 3 }, + A3: { 값: "면적" }, + B3: { 식: "B1*B2" }, + }, + }, + ], + 활성: "s1", +}; + +const MATERIALS: LinkMaterial[] = [ + { 코드: "M001", 이름: "레미콘", 규격: "25-21-12", 단위: "m³" }, + { 코드: "M002", 이름: "철근", 규격: "SD400 D13", 단위: "ton" }, + { 코드: "M003", 이름: "거푸집", 규격: "합판 3회", 단위: "m²" }, +]; +const asked: string[] = []; +w.ssFind = asked; + +w.ss = createSpreadsheet(document.getElementById("host")!, book, { + tabs: false, + onChange: () => (w.ssChanges = ((w.ssChanges as number) ?? 0) + 1), + links: { + 모드: mode, + 항목: [ + { 키: "L", 이름: "길이", 단위: "m" }, + { 키: "H", 이름: "높이", 단위: "m" }, + { 키: "A", 이름: "면적", 단위: "m²" }, + ], + 자재찾기: async (글) => { + asked.push(글); + await new Promise((r) => setTimeout(r, 50)); + return MATERIALS.filter((m) => !글 || `${m.코드}${m.이름}${m.규격}`.includes(글)); + }, + }, +}); diff --git a/resources/tester/spreadsheet/helper_spreadsheet_d.cjs b/resources/tester/spreadsheet/helper_spreadsheet_d.cjs index 16b3be28..527b4e66 100644 --- a/resources/tester/spreadsheet/helper_spreadsheet_d.cjs +++ b/resources/tester/spreadsheet/helper_spreadsheet_d.cjs @@ -123,5 +123,28 @@ const out = { }; return addr.toA1(sel.move(s, sel.selectCell(s, 1, 11), 1, 0).활성.r, 11); })(), + // 알약 연결 — 행 넣기 · 열 지우기(연결 칸 지움 → 빠짐) · 되돌리기 두 번 + links: (() => { + const lk = load(path.join(SS, "spreadsheet_links.ts")); + const book = JSON.parse(JSON.stringify(sample)); + const id = book.시트[0].id; + book.시트[0].연결 = [ + { 키: "L", 이름: "길이", 칸: "B5" }, + { 키: "W", 이름: "폭", 칸: "D3" }, + ]; + const read = () => (book.시트[0].연결 ?? []).map((l) => `${l.키}:${l.칸}`).join(","); + const out = []; + const ins = lk.applyLinked(book, { 종류: "행넣기", 시트: id, at: 2, 수: 2 }); + out.push(read()); + const del = lk.applyLinked(book, { 종류: "열지우기", 시트: id, at: 3, 수: 1 }); + out.push(read()); + lk.applyLinked(book, del.undo); + out.push(read()); + lk.applyLinked(book, ins.undo); + out.push(read()); + const one = [{ 키: "a", 칸: "C1" }]; + out.push(lk.shiftLinks(one, { 종류: "열넣기", 시트: id, at: 0, 수: 1 })[0].칸); + return out; + })(), }; console.log(JSON.stringify(out)); diff --git a/resources/tester/spreadsheet/test_spreadsheet_d_input.py b/resources/tester/spreadsheet/test_spreadsheet_d_input.py index 3a1d008f..ad128f05 100644 --- a/resources/tester/spreadsheet/test_spreadsheet_d_input.py +++ b/resources/tester/spreadsheet/test_spreadsheet_d_input.py @@ -106,3 +106,8 @@ def test_abs_cycle_and_fold(r): None, ] assert r["foldSkip"] == "L5" + + +def test_links_follow_rows_cols(r): + # 행 넣기 → 밀림 · 연결 칸 열 지움 → 빠짐 · 되돌리기 → 제자리 + assert r["links"] == ["L:B7,W:D5", "L:B7", "L:B7,W:D5", "L:B5,W:D3", "D1"]