resolveCondFmtStyle 결과를 칸 서식 위에 덮어씀(채움·글자색·굵게) · 글자색은 조건부 서식이
숫자 형식([Red] 등)보다 이김(엑셀과 같음). 오류 칸은 기존 title 풍선에 더해 왼 위 초록
세모(엑셀 오류 검사 표시)도 그림. 필터로 걸러진 행 숨김은 이전 커밋(ebdee04f)에서 이미
buildRowGeometry 에 같이 넣어 둠(걸러짐 · 숨김 · 묶음 접힘 모두 처리).
ORCA 시험 틀 — 조건 맞는 칸 배경·글자색·굵기 수치로 확인 · 오류 칸 title·세모 확인.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVM3xZ1aUPcUTuW2WZSnwg
191 lines
5.6 KiB
TypeScript
191 lines
5.6 KiB
TypeScript
/* =============================================================================
|
|
* spreadsheet_grid_test.ts
|
|
* C(격자) 화면 시험 틀 — 병합 · 틀고정 · 숨김 · 폭 · hair 선 · 균등 분할 · 선택 영역 가운데 ·
|
|
* [Red] 음수 서식 · 1만 행 스크롤 때 DOM 칸 수를 ORCA 로 확인. D · 엔진이 없으니 이 파일이
|
|
* `SpreadsheetContext` 를 최소로 흉내 낸다(엔진 값은 안 씀 — 식 칸이 없음).
|
|
* ========================================================================== */
|
|
|
|
import { createGrid } from "../../../A00_Common/spreadsheet/spreadsheet_grid";
|
|
import type {
|
|
CalcEngine,
|
|
Command,
|
|
History,
|
|
Sheet,
|
|
Workbook,
|
|
} from "../../../A00_Common/spreadsheet/spreadsheet_types";
|
|
import { colIndex } from "../../../A00_Common/spreadsheet/spreadsheet_address";
|
|
import type {
|
|
GridHandle,
|
|
SpreadsheetContext,
|
|
} from "../../../A00_Common/spreadsheet/spreadsheet_view_types";
|
|
|
|
const sheet: Sheet = {
|
|
id: "s1",
|
|
이름: "시험",
|
|
칸: {
|
|
A1: { 값: "□격자 시험 — 병합 · 틀고정 · 숨김 · hair 선", 서식: 1 },
|
|
A3: { 값: "공종", 서식: 2 },
|
|
B3: { 값: "규격", 서식: 2 },
|
|
C3: { 값: "산출 내역", 서식: 2 },
|
|
G3: { 값: "단위", 서식: 2 },
|
|
H3: { 값: "수량", 서식: 2 },
|
|
A4: { 값: "터파기", 서식: 3 },
|
|
C4: { 값: "균등 분할 정렬 보기 글", 서식: 4 },
|
|
H4: { 값: -12.5, 서식: 6 },
|
|
A6: { 값: "선택 영역 가운데(centerContinuous) 보기", 서식: 5 },
|
|
A8: { 값: "hair 테두리 칸", 서식: 3 },
|
|
B8: { 값: 3.14159, 서식: 7 },
|
|
G9: { 식: "1/0" },
|
|
J10000: { 값: "맨 끝 칸(1만 행 스크롤 확인용)" },
|
|
},
|
|
comments: { H4: "메모 — ROUNDDOWN 끝수 확인" },
|
|
조건부서식: [
|
|
{
|
|
id: "cf1",
|
|
범위: [{ r0: 3, c0: 7, r1: 3, c1: 7 }],
|
|
조건: { 종류: "비교", 연산: "보다작음", 값: 0 },
|
|
스타일: { 채움: "#ffe0e0", 글자색: "#c00000", 굵게: true },
|
|
},
|
|
],
|
|
병합: ["A1:H1", "B8:C9"],
|
|
열: {
|
|
A: { 폭: 14 },
|
|
D: { 숨김: true },
|
|
E: { 묶음: { 층: 1 } },
|
|
F: { 묶음: { 층: 1 } },
|
|
},
|
|
행: {
|
|
"1": { 높이: 22 },
|
|
"5": { 숨김: true },
|
|
"11": { 묶음: { 층: 1 } },
|
|
"12": { 묶음: { 층: 1 } },
|
|
},
|
|
틀고정: { 행: 3, 열: 1 },
|
|
보기: { 눈금선: true },
|
|
};
|
|
|
|
const book: Workbook = {
|
|
종류: "통합문서",
|
|
판: 1,
|
|
열: "test",
|
|
기본: { 글꼴: "굴림", 크기: 10, 열폭: 8.43, 행높이: 15 },
|
|
서식: [
|
|
{},
|
|
{ 크기: 14, 굵게: true },
|
|
{
|
|
가로: "center",
|
|
세로: "center",
|
|
채움: "#F2F2F2",
|
|
테두리: {
|
|
위: { 선: "thin" },
|
|
아래: { 선: "thin" },
|
|
왼: { 선: "thin" },
|
|
오른: { 선: "thin" },
|
|
},
|
|
},
|
|
{ 세로: "center", 테두리: { 위: { 선: "hair" }, 아래: { 선: "hair" } } },
|
|
{ 가로: "distributed", 세로: "center" },
|
|
{ 가로: "centerContinuous", 세로: "center" },
|
|
{ 형식: "0.00;[Red]-0.00" },
|
|
{
|
|
형식: "0.0000",
|
|
테두리: {
|
|
위: { 선: "hair" },
|
|
아래: { 선: "hair" },
|
|
왼: { 선: "hair" },
|
|
오른: { 선: "hair" },
|
|
},
|
|
},
|
|
],
|
|
시트: [sheet],
|
|
활성: "s1",
|
|
};
|
|
|
|
function noopEngine(): CalcEngine {
|
|
return {
|
|
update: () => [],
|
|
rebuild: () => {},
|
|
value: (_sheet, r, c) =>
|
|
r === 8 && c === 6 ? { error: "#DIV/0!", why: "0 으로 나눔(시험 칸 G9)" } : null,
|
|
precedents: () => [],
|
|
snapshot: () => ({}),
|
|
};
|
|
}
|
|
|
|
function noopHistory(): History {
|
|
return {
|
|
push: () => {},
|
|
undo: () => null,
|
|
redo: () => null,
|
|
canUndo: () => false,
|
|
canRedo: () => false,
|
|
clear: () => {},
|
|
};
|
|
}
|
|
|
|
let grid!: GridHandle;
|
|
|
|
const ctx: SpreadsheetContext = {
|
|
root: document.getElementById("app")!,
|
|
book,
|
|
readOnly: false,
|
|
engine: noopEngine(),
|
|
history: noopHistory(),
|
|
selection: {
|
|
시트: "s1",
|
|
범위: [{ r0: 2, c0: 2, r1: 2, c1: 2 }],
|
|
활성: { r: 2, c: 2 },
|
|
기준: { r: 2, c: 2 },
|
|
},
|
|
sheet: () => sheet,
|
|
dispatch: (command: Command) => {
|
|
if (command.종류 === "열폭") {
|
|
const c0 = command.열[0];
|
|
const key = c0 >= 0 ? String.fromCharCode(65 + c0) : "A"; // 시험 데이터가 A~J 안쪽이라 단순 변환으로 충분
|
|
sheet.열 = { ...sheet.열, [key]: { ...sheet.열?.[key], 폭: command.폭 ?? undefined } };
|
|
} else if (command.종류 === "행높이") {
|
|
const r0 = command.행[0];
|
|
sheet.행 = {
|
|
...sheet.행,
|
|
[String(r0 + 1)]: { ...sheet.행?.[String(r0 + 1)], 높이: command.높이 ?? undefined },
|
|
};
|
|
} else if (command.종류 === "묶음설정") {
|
|
const table = command.축 === "열" ? "열" : "행";
|
|
const next = { ...sheet[table] } as Record<string, { 묶음?: unknown }>;
|
|
for (const i of command.번호) {
|
|
const key = command.축 === "열" ? String.fromCharCode(65 + i) : String(i + 1);
|
|
next[key] = { ...next[key], 묶음: command.묶음 ?? undefined };
|
|
}
|
|
(sheet as unknown as Record<string, unknown>)[table] = next;
|
|
}
|
|
grid.render();
|
|
},
|
|
undo: () => {},
|
|
redo: () => {},
|
|
select: () => grid.renderSelection(),
|
|
showSheet: () => {},
|
|
get grid() {
|
|
return grid;
|
|
},
|
|
editor: {
|
|
editing: () => false,
|
|
begin: () => {},
|
|
commit: () => {},
|
|
cancel: () => {},
|
|
sync: () => {},
|
|
},
|
|
} as SpreadsheetContext;
|
|
|
|
grid = createGrid(ctx);
|
|
ctx.root.append(grid.root);
|
|
|
|
// ORCA 수치 확인용 — 눈에 안 보이는 전역에 걸어 둠(콘솔 · eval 로 셈).
|
|
(window as unknown as { __gridTest: unknown }).__gridTest = {
|
|
grid,
|
|
sheet,
|
|
book,
|
|
ctx,
|
|
colIndex,
|
|
countCells: () => grid.root.querySelectorAll(".aislo-cell").length,
|
|
};
|