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 {