From a927ae64bceaa051283a22bb6ae9e0d301df55c0 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 28 Sep 2026 14:24:04 +0900 Subject: [PATCH] =?UTF-8?q?feat(spreadsheet):=20=EC=97=91=EC=85=80=20?= =?UTF-8?q?=EC=88=98=EC=8B=9D=20=EB=B3=B5=EC=82=AC=20=EC=95=88=EB=82=B4=20?= =?UTF-8?q?=C2=B7=20=EA=B0=92=EB=A7=8C=20=EC=98=A8=20=EB=B6=99=EC=97=AC?= =?UTF-8?q?=EB=84=A3=EA=B8=B0=20=EC=84=B8=EC=85=98=20=EC=95=8C=EB=A6=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 도구 모음 오른쪽 끝에 흐린 글씨 안내 추가 — 「엑셀 수식까지: 엑셀에서 Ctrl+` → 복사 → 여기 Ctrl+V · 끝나면 엑셀 Ctrl+` 다시」 · 누르면 왜 그런지 두세 줄 설명(엑셀 Ctrl+` = 「수식 표시」 켜기 · 그 상태로 복사해야 수식이 실림 · 그냥 복사하면 값만 옴 · 붙인 뒤 엑셀에서 Ctrl+` 다시 눌러 원래대로) - 도구 모음은 readOnly 면 안 붙는 기존 길을 그대로 써 보기 전용 카드에서는 자동으로 숨음(새 분기 없음) - 엑셀 HTML 붙여넣기(출처: "excel")인데 뭉치 전체에 식이 하나도 없으면 세션에 한 번만 토스트 — 「값만 들어왔음 — 수식까지는 엑셀 Ctrl+` 뒤 복사」 (sessionStorage 로 한 번 표시 기억 · 못 쓰면 매번 뜰 수 있으나 치명적이지 않음) - ORCA 로 확인 — 안내 글 그대로 보임 · 눌러 설명 펼침/접힘 · 식 없는 엑셀 붙여넣기 첫 번은 토스트 뜨고 세션 안 지운 채 두 번째는 안 뜸 · 식이 있으면 (「=A1+B1」) 애초에 안 뜸 · 기존 클립보드 회귀 시험(TSV) 통과 Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01AeeQRLknEpP4SFjVkjDWDs --- .../spreadsheet/spreadsheet_clipboard.ts | 20 +++++++++++ A00_Common/spreadsheet/spreadsheet_text.ts | 17 ++++++++++ .../spreadsheet/spreadsheet_toolbar.css | 34 +++++++++++++++++++ A00_Common/spreadsheet/spreadsheet_toolbar.ts | 21 ++++++++++++ 4 files changed, 92 insertions(+) diff --git a/A00_Common/spreadsheet/spreadsheet_clipboard.ts b/A00_Common/spreadsheet/spreadsheet_clipboard.ts index 45c514d4..93b3f1bc 100644 --- a/A00_Common/spreadsheet/spreadsheet_clipboard.ts +++ b/A00_Common/spreadsheet/spreadsheet_clipboard.ts @@ -405,6 +405,25 @@ export function parseClipboard(html: string, text: string, at: CellAddress): Cli return null; } +const NO_FORMULA_NOTIFIED_KEY = "aislo-ss-notified-no-formula"; + +/** 붙인 뭉치 어디에도 수식(`식`)이 없음 — 엑셀 HTML 클립보드는 「수식 표시」(Ctrl+`) 없이 복사하면 + * 계산값만 실림(수식 자체는 절대 안 실림). */ +function hasNoFormula(block: ClipBlock): boolean { + return !Object.values(block.칸).some((cell) => cell.식 !== undefined); +} + +/** 세션에 한 번만 — 엑셀에서 값만 온 붙여넣기마다 매번 뜨면 성가심. */ +function notifyNoFormulaOnce(): void { + try { + if (sessionStorage.getItem(NO_FORMULA_NOTIFIED_KEY)) return; + sessionStorage.setItem(NO_FORMULA_NOTIFIED_KEY, "1"); + } catch { + // 세션 저장 안 되면 매번 뜰 수 있으나 치명적이지 않음. + } + showToast(st("ClipboardExcelNoFormula")); +} + /* ── 화면 붙임 — copy · cut · paste 사건 ────────────────────────────────── */ function activeRange(ctx: SpreadsheetContext): CellRange { @@ -525,6 +544,7 @@ export function attachClipboard(ctx: SpreadsheetContext): PartHandle { return; } ev.preventDefault(); + if (block.출처 === "excel" && hasNoFormula(block)) notifyNoFormulaOnce(); pasteBlock(ctx, block, at); } diff --git a/A00_Common/spreadsheet/spreadsheet_text.ts b/A00_Common/spreadsheet/spreadsheet_text.ts index 1928550f..a4230d36 100644 --- a/A00_Common/spreadsheet/spreadsheet_text.ts +++ b/A00_Common/spreadsheet/spreadsheet_text.ts @@ -103,6 +103,23 @@ const TEXT = { UnitGroup_op: ["연산·비교", "Operators"], UnitRecent: ["최근 씀", "Recently used"], UnitAsFormat: ["숫자 형식으로 붙이기", "Attach as number format"], + FormulaHint_label: [ + "엑셀 수식까지: 엑셀에서 Ctrl+` → 복사 → 여기 Ctrl+V · 끝나면 엑셀 Ctrl+` 다시", + "Formulas too: in Excel Ctrl+` → copy → paste here (Ctrl+V) · then Ctrl+` again in Excel", + ], + FormulaHint_title: ["엑셀 수식까지 옮기는 법", "How to bring formulas along"], + FormulaHint_detail: [ + "엑셀 Ctrl+` = 「수식 표시」 켜기 · 칸에 계산값 대신 「=...」 글이 그대로 보임. 그 상태로 복사해 " + + "여기 붙이면 수식까지 옮겨짐(그냥 복사하면 값만 옴 · 수식 없음). 붙인 뒤 엑셀에서 Ctrl+` 다시 " + + "눌러 원래대로.", + 'Excel Ctrl+` turns on "Show Formulas" — cells show "=..." text instead of the computed ' + + "value. Copy in that state and paste here to bring the formulas along (a normal copy only " + + "brings values). Press Ctrl+` again in Excel afterward to switch back.", + ], + ClipboardExcelNoFormula: [ + "값만 들어왔음 — 수식까지는 엑셀 Ctrl+` 뒤 복사", + "Only values came in — for formulas too, copy after Ctrl+` in Excel", + ], } as const; export function st(key: keyof typeof TEXT): string { diff --git a/A00_Common/spreadsheet/spreadsheet_toolbar.css b/A00_Common/spreadsheet/spreadsheet_toolbar.css index 214b2f33..89c2410e 100644 --- a/A00_Common/spreadsheet/spreadsheet_toolbar.css +++ b/A00_Common/spreadsheet/spreadsheet_toolbar.css @@ -145,6 +145,40 @@ padding: 4px 2px; } +.ss-toolbar__hint { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 2px; + margin-left: auto; + max-width: 320px; +} + +.ss-toolbar__formula-hint { + border: 0; + padding: 0; + background: none; + color: var(--color-text-muted); + font-size: 0.72rem; + text-align: right; + opacity: 0.6; + cursor: pointer; +} + +.ss-toolbar__formula-hint:hover { + opacity: 1; +} + +.ss-toolbar__formula-hint-detail { + color: var(--color-text-muted); + font-size: 0.68rem; + text-align: right; +} + +.ss-toolbar__formula-hint-detail[hidden] { + display: none; +} + /* ── 시트 탭 ─────────────────────────────────────────────────────────────── */ .ss-tabs { diff --git a/A00_Common/spreadsheet/spreadsheet_toolbar.ts b/A00_Common/spreadsheet/spreadsheet_toolbar.ts index 90577706..3518e51e 100644 --- a/A00_Common/spreadsheet/spreadsheet_toolbar.ts +++ b/A00_Common/spreadsheet/spreadsheet_toolbar.ts @@ -452,6 +452,26 @@ export function mountToolbar(ctx: SpreadsheetContext): PartHandle { }; document.addEventListener("click", closeUnitPop); + // ── 엑셀 수식 복사 안내(오른쪽 위 흐린 글씨 · 누르면 두세 줄 설명) ───────── + const formulaHintBtn = el("button", { + className: "ss-toolbar__formula-hint", + attrs: { type: "button", title: st("FormulaHint_title") }, + text: st("FormulaHint_label"), + }); + const formulaHintDetail = el("div", { + className: "ss-toolbar__formula-hint-detail", + attrs: { hidden: "true" }, + text: st("FormulaHint_detail"), + }); + formulaHintBtn.addEventListener("click", (ev) => { + ev.stopPropagation(); + formulaHintDetail.hidden = !formulaHintDetail.hidden; + }); + const formulaHint = el("div", { + className: "ss-toolbar__hint", + children: [formulaHintBtn, formulaHintDetail], + }); + root.append( group(undoBtn, redoBtn), group(fontInput, sizeInput), @@ -462,6 +482,7 @@ export function mountToolbar(ctx: SpreadsheetContext): PartHandle { group(borderBtn, borderPop), group(numfmtInput), group(unitBtn, unitPop), + formulaHint, ); function refresh(): void {