xiaodao-spreader 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ZH.md +46 -5
- package/README.md +47 -6
- package/dist/style.css +1 -1
- package/dist/types/components/spreader/components/dropdown.vue.d.ts +3 -0
- package/dist/types/components/spreader/components/pickers/calcPicker.vue.d.ts +1 -1
- package/dist/types/components/spreader/components/pickers/numberFormatDialog.vue.d.ts +23 -0
- package/dist/types/components/spreader/components/toolbar.vue.d.ts +11 -4
- package/dist/types/components/spreader/composables/borders-merge.d.ts +2 -0
- package/dist/types/components/spreader/composables/core-state.d.ts +11 -1
- package/dist/types/components/spreader/composables/interactions.d.ts +4 -0
- package/dist/types/components/spreader/composables/sheets-ops.d.ts +1 -1
- package/dist/types/components/spreader/composables/undo-styles.d.ts +8 -0
- package/dist/types/components/spreader/core/formula.d.ts +13 -4
- package/dist/types/components/spreader/core/number-format.d.ts +100 -0
- package/dist/xiaodao-spreader.es.js +4657 -3025
- package/dist/xiaodao-spreader.umd.js +9 -9
- package/package.json +1 -1
package/README.ZH.md
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
- [架构设计](#架构设计)
|
|
25
25
|
- [键盘快捷键](#键盘快捷键)
|
|
26
26
|
- [公式引擎](#公式引擎)
|
|
27
|
+
- [数字格式](#数字格式)
|
|
27
28
|
- [主题与国际化](#主题与国际化)
|
|
28
29
|
- [开发指南](#开发指南)
|
|
29
30
|
- [构建发布](#构建发布)
|
|
@@ -40,12 +41,13 @@
|
|
|
40
41
|
|
|
41
42
|
- **Canvas 2D 渲染** — 高 DPI 自适应(DPR 缩放),虚拟视口渲染,支持 200 行 × 26 列
|
|
42
43
|
- **多 Sheet 工作簿** — 标签栏支持新建、重命名、复制、删除、拖拽排序
|
|
43
|
-
- **公式引擎** — 支持 `=SUM()`、`=AVERAGE()
|
|
44
|
+
- **公式引擎** — 支持 `=SUM()`、`=AVERAGE()`、`=COUNT()`、`=IF()`、`=VLOOKUP()`、`=CONCATENATE()`,支持依赖追踪与循环引用检测;工具栏与右键菜单提供一键求和/平均值/计数
|
|
44
45
|
- **合并单元格** — 合并居中、跨列合并、取消合并,边框自动同步
|
|
45
46
|
- **丰富单元格格式** — 字体、字号(5–72)、加粗、斜体、下划线、删除线、文字颜色、填充颜色、水平/垂直对齐、自动换行
|
|
46
47
|
- **边框** — 上/下/左/右/全部/无,5 种预设样式及自定义颜色
|
|
47
48
|
- **撤销 / 重做** — 单元格、列宽、行高的完整状态快照(50 步)
|
|
48
49
|
- **格式刷** — 复制并应用单元格格式到任意区域
|
|
50
|
+
- **数字格式** — Excel 风格数字格式(常规 / 文本 / 数值 / 货币 / 会计 / 百分比 / 科学计数 / 日期 / 时间 / 日期时间 / 持续时间),提供自定义格式对话框;仅影响显示,绝不修改底层单元格值
|
|
49
51
|
|
|
50
52
|
### 交互体验
|
|
51
53
|
|
|
@@ -216,7 +218,8 @@ src/
|
|
|
216
218
|
│ └── pickers/
|
|
217
219
|
│ ├── colorPicker.vue
|
|
218
220
|
│ ├── borderPicker.vue
|
|
219
|
-
│
|
|
221
|
+
│ ├── mergePicker.vue
|
|
222
|
+
│ └── numberFormatDialog.vue
|
|
220
223
|
├── composables/
|
|
221
224
|
│ ├── core-state.ts # Props、cells/merges/selection、字体度量、导航
|
|
222
225
|
│ ├── undo-styles.ts # 撤销重做、格式刷、字体/对齐/颜色
|
|
@@ -227,6 +230,7 @@ src/
|
|
|
227
230
|
├── constants.ts # 布局常量、国际化、主题调色板
|
|
228
231
|
├── types.ts # 全部类型定义
|
|
229
232
|
├── formula.ts # 公式引擎(解析、计算、依赖、缓存)
|
|
233
|
+
├── number-format.ts # 数字格式引擎(Excel 风格显示格式化)
|
|
230
234
|
├── theme.ts # 主题 CSS 变量构建
|
|
231
235
|
└── utils.ts # 纯工具函数(列标签、命中测试、尺寸解析)
|
|
232
236
|
```
|
|
@@ -292,6 +296,10 @@ src/
|
|
|
292
296
|
|------|------|------|
|
|
293
297
|
| `SUM` | `=SUM(A1:B5)` | 区间求和 |
|
|
294
298
|
| `AVERAGE` | `=AVERAGE(A1:B5)` | 区间平均值 |
|
|
299
|
+
| `COUNT` | `=COUNT(A1:B5)` | 统计区域内数值单元格数 |
|
|
300
|
+
| `IF` | `=IF(A1>5, A1*2, 0)` | 条件分支;支持比较运算符(`> < >= <= = <>`)与四则运算 |
|
|
301
|
+
| `VLOOKUP` | `=VLOOKUP(value, A1:C5, 2, FALSE)` | 垂直查找;默认精确匹配,`TRUE` 为近似匹配 |
|
|
302
|
+
| `CONCATENATE` | `=CONCATENATE(A1, " ", B1)` | 将多个值拼接为字符串 |
|
|
295
303
|
| 绝对引用 | `$A$1` | 锁定列与行 |
|
|
296
304
|
| 混合引用 | `$A1`、`A$1` | 仅锁定列或行 |
|
|
297
305
|
|
|
@@ -302,7 +310,7 @@ src/
|
|
|
302
310
|
- **正向**:`formulaKey` → `[depKey, ...]` — 公式引用了哪些单元格
|
|
303
311
|
- **反向**:`depKey` → `Set<formulaKey>` — 哪些公式依赖此单元格
|
|
304
312
|
|
|
305
|
-
|
|
313
|
+
单元格变更时,脏标记通过反向图传播。循环引用通过独立的 `inProgress` 集合检测,返回 `#ERROR`。
|
|
306
314
|
|
|
307
315
|
### 粘贴时的引用偏移
|
|
308
316
|
|
|
@@ -310,6 +318,39 @@ src/
|
|
|
310
318
|
|
|
311
319
|
---
|
|
312
320
|
|
|
321
|
+
## 数字格式
|
|
322
|
+
|
|
323
|
+
一套 Excel 风格的数字格式引擎(`spreader/core/number-format.ts`),控制**单元格值的显示方式**——绝不修改存储的 `value`(始终保持原始字符串)。
|
|
324
|
+
|
|
325
|
+
### 分类
|
|
326
|
+
|
|
327
|
+
| 分类 | 示例显示 | 格式代码 |
|
|
328
|
+
|------|----------|----------|
|
|
329
|
+
| 常规 General | 自动(数值;极大/极小用科学计数法) | ``(空串) |
|
|
330
|
+
| 文本 Text | 原样显示 | `@` |
|
|
331
|
+
| 数值 Number | `1,234.56` | `#,##0.00` |
|
|
332
|
+
| 百分比 Percent | `12.34%` | `0.00%` |
|
|
333
|
+
| 科学计数 Scientific | `1.23E+03` | `0.00E+00` |
|
|
334
|
+
| 货币 Currency | `¥1,234.56` / `$1,234.56` | `¥#,##0.00` |
|
|
335
|
+
| 货币(取整)Currency (rounded) | `¥1,235` | `¥#,##0` |
|
|
336
|
+
| 会计 Accounting | 负数 `(¥1,234.56)` | `¥#,##0.00;(¥#,##0.00);¥"-"` |
|
|
337
|
+
| 财务 Financial | 负数 `[Red](#,##0.00)` | `#,##0.00;[Red](#,##0.00)` |
|
|
338
|
+
| 日期 Date | `2026年8月24日` / `8/24/2026` | `yyyy"年"m"月"d"日"` |
|
|
339
|
+
| 时间 Time | `13:45:30` | `h:mm:ss` |
|
|
340
|
+
| 日期时间 Date & Time | `2026年8月24日 13:45:30` | `yyyy"年"m"月"d"日" h:mm:ss` |
|
|
341
|
+
| 持续时间 Duration | `26:30:00` | `[h]:mm:ss` |
|
|
342
|
+
| 自定义 Custom | 用户自定义 Excel 风格代码 | — |
|
|
343
|
+
|
|
344
|
+
### 工作原理
|
|
345
|
+
|
|
346
|
+
- **存储**:格式代码按单元格存入 `cell.style.numberFormat`(字符串)。省略该属性(或空串)即常规格式。
|
|
347
|
+
- **界面**:工具栏数字格式下拉框将预设应用到当前选区;**「格式…」** 项打开 `numberFormatDialog.vue`,可自定义格式代码、小数位数与千位分隔符。
|
|
348
|
+
- **显示**:`formatNumber(value, format, locale)` 解析代码(带缓存),应用千位分隔 / 小数位 / 百分比缩放 / 日期序列号转换,返回显示字符串。非法的日期/持续时间序列号渲染为 `###`。
|
|
349
|
+
- **对齐**:数值类格式默认右对齐;文本及常规下的非数值保持左对齐——与 Excel 语义一致。
|
|
350
|
+
- **国际化**:货币符号(`¥` / `$`)、月份与星期名称随 `locale` 属性变化。
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
313
354
|
## 主题与国际化
|
|
314
355
|
|
|
315
356
|
### 内置主题
|
|
@@ -400,9 +441,9 @@ pnpm build:demo
|
|
|
400
441
|
|
|
401
442
|
### 近期
|
|
402
443
|
|
|
403
|
-
- [
|
|
444
|
+
- [x] 更多公式:`COUNT`、`IF`、`VLOOKUP`、`CONCATENATE`
|
|
404
445
|
- [ ] 单元格背景颜色选择器
|
|
405
|
-
- [ ]
|
|
446
|
+
- [x] 数字格式(货币、百分比、日期、小数位数)—— *见 [数字格式](#数字格式)*
|
|
406
447
|
- [ ] 条件格式规则
|
|
407
448
|
- [ ] 自动填充拖拽手柄
|
|
408
449
|
- [ ] 查找与替换
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Xiaodao Spreader
|
|
2
2
|
|
|
3
|
-
中文
|
|
3
|
+
[中文](./README.ZH.md) | English
|
|
4
4
|
|
|
5
5
|
A high-performance, canvas-based spreadsheet component for Vue 3 — bringing an Excel-like editing experience to the web.
|
|
6
6
|
|
|
@@ -24,6 +24,7 @@ A high-performance, canvas-based spreadsheet component for Vue 3 — bringing an
|
|
|
24
24
|
- [Architecture](#architecture)
|
|
25
25
|
- [Keyboard Shortcuts](#keyboard-shortcuts)
|
|
26
26
|
- [Formula Engine](#formula-engine)
|
|
27
|
+
- [Number Format](#number-format)
|
|
27
28
|
- [Theming](#theming)
|
|
28
29
|
- [Development](#development)
|
|
29
30
|
- [Building](#building)
|
|
@@ -39,12 +40,13 @@ A high-performance, canvas-based spreadsheet component for Vue 3 — bringing an
|
|
|
39
40
|
### Core Spreadsheet
|
|
40
41
|
- **Canvas 2D Rendering** — High-DPI aware with DPR scaling, virtual viewport rendering for 200 × 26 sheets
|
|
41
42
|
- **Multi-Sheet Workbook** — Tab bar with add, rename, duplicate, delete, reorder
|
|
42
|
-
- **Formula Engine** — `=SUM()`, `=AVERAGE()
|
|
43
|
+
- **Formula Engine** — `=SUM()`, `=AVERAGE()`, `=COUNT()`, `=IF()`, `=VLOOKUP()`, `=CONCATENATE()` with dependency tracking and circular-reference detection; toolbar and context menu provide one-click sum/average/count
|
|
43
44
|
- **Merge Cells** — Merge & Center, Merge Across, Unmerge with border synchronization
|
|
44
45
|
- **Rich Cell Formatting** — Font family, font size (5–72), bold, italic, underline, strikethrough, text color, fill color, horizontal & vertical alignment, wrap text
|
|
45
46
|
- **Borders** — Top / bottom / left / right / all / none with 5 predefined styles and custom color
|
|
46
47
|
- **Undo / Redo** — Full state snapshots for cells, column widths, and row heights (50 steps)
|
|
47
48
|
- **Format Painter** — Copy & apply cell formatting across ranges
|
|
49
|
+
- **Number Format** — Excel-style number formatting (General / Text / Number / Currency / Accounting / Percent / Scientific / Date / Time / DateTime / Duration) with a custom format dialog; display-only, never mutates the stored cell value
|
|
48
50
|
|
|
49
51
|
### Interaction
|
|
50
52
|
- **Smart Selection** — Click, drag, Shift+Click, row/column header select, corner-cell select-all
|
|
@@ -213,7 +215,8 @@ src/
|
|
|
213
215
|
│ └── pickers/
|
|
214
216
|
│ ├── colorPicker.vue
|
|
215
217
|
│ ├── borderPicker.vue
|
|
216
|
-
│
|
|
218
|
+
│ ├── mergePicker.vue
|
|
219
|
+
│ └── numberFormatDialog.vue
|
|
217
220
|
├── composables/
|
|
218
221
|
│ ├── core-state.ts # Props, cells/merges/selection, font metrics, navigation
|
|
219
222
|
│ ├── undo-styles.ts # Undo/redo, format painter, font/alignment/color
|
|
@@ -224,6 +227,7 @@ src/
|
|
|
224
227
|
├── constants.ts # Layout constants, i18n, theme palettes
|
|
225
228
|
├── types.ts # All type definitions
|
|
226
229
|
├── formula.ts # Formula engine (parse, evaluate, deps, cache)
|
|
230
|
+
├── number-format.ts # Number format engine (Excel-style display formatting)
|
|
227
231
|
├── theme.ts # Theme CSS variable construction
|
|
228
232
|
└── utils.ts # Pure utilities (col label, hit test, resolve size)
|
|
229
233
|
```
|
|
@@ -289,6 +293,10 @@ src/
|
|
|
289
293
|
|---------|--------|-------------|
|
|
290
294
|
| `SUM` | `=SUM(A1:B5)` | Range summation |
|
|
291
295
|
| `AVERAGE` | `=AVERAGE(A1:B5)` | Range average |
|
|
296
|
+
| `COUNT` | `=COUNT(A1:B5)` | Count numeric cells in range |
|
|
297
|
+
| `IF` | `=IF(A1>5, A1*2, 0)` | Conditional branching; supports comparison operators (`> < >= <= = <>`) and arithmetic |
|
|
298
|
+
| `VLOOKUP` | `=VLOOKUP(value, A1:C5, 2, FALSE)` | Vertical lookup; exact match by default, `TRUE` for approximate match |
|
|
299
|
+
| `CONCATENATE` | `=CONCATENATE(A1, " ", B1)` | Concatenate multiple values into a string |
|
|
292
300
|
| Absolute ref | `$A$1` | Lock column and row |
|
|
293
301
|
| Mixed ref | `$A1`, `A$1` | Lock column or row only |
|
|
294
302
|
|
|
@@ -299,7 +307,7 @@ The `FormulaDeps` class maintains a bidirectional dependency graph:
|
|
|
299
307
|
- **Forward**: `formulaKey` → `[depKey, ...]` — which cells a formula references
|
|
300
308
|
- **Reverse**: `depKey` → `Set<formulaKey>` — which formulas depend on a cell
|
|
301
309
|
|
|
302
|
-
When a cell changes, dirty flags propagate through the reverse graph. Circular references
|
|
310
|
+
When a cell changes, dirty flags propagate through the reverse graph. Circular references are detected via a separate `inProgress` set and return `#ERROR`.
|
|
303
311
|
|
|
304
312
|
### Reference Offsetting During Paste
|
|
305
313
|
|
|
@@ -307,6 +315,39 @@ When a cell changes, dirty flags propagate through the reverse graph. Circular r
|
|
|
307
315
|
|
|
308
316
|
---
|
|
309
317
|
|
|
318
|
+
## Number Format
|
|
319
|
+
|
|
320
|
+
An Excel-style number formatting engine (`spreader/core/number-format.ts`) that controls **how a cell value is displayed** — it never mutates the stored `value` (which always remains a raw string).
|
|
321
|
+
|
|
322
|
+
### Categories
|
|
323
|
+
|
|
324
|
+
| Category | Example display | Format code |
|
|
325
|
+
|----------|-----------------|-------------|
|
|
326
|
+
| General | Auto (numbers, sci-notation for very large/small) | `` (empty) |
|
|
327
|
+
| Text | Verbatim | `@` |
|
|
328
|
+
| Number | `1,234.56` | `#,##0.00` |
|
|
329
|
+
| Percent | `12.34%` | `0.00%` |
|
|
330
|
+
| Scientific | `1.23E+03` | `0.00E+00` |
|
|
331
|
+
| Currency | `¥1,234.56` / `$1,234.56` | `¥#,##0.00` |
|
|
332
|
+
| Currency (rounded) | `¥1,235` | `¥#,##0` |
|
|
333
|
+
| Accounting | `(¥1,234.56)` for negatives | `¥#,##0.00;(¥#,##0.00);¥"-"` |
|
|
334
|
+
| Financial | `[Red](#,##0.00)` for negatives | `#,##0.00;[Red](#,##0.00)` |
|
|
335
|
+
| Date | `2026年8月24日` / `8/24/2026` | `yyyy"年"m"月"d"日"` |
|
|
336
|
+
| Time | `13:45:30` | `h:mm:ss` |
|
|
337
|
+
| Date & Time | `2026年8月24日 13:45:30` | `yyyy"年"m"月"d"日" h:mm:ss` |
|
|
338
|
+
| Duration | `26:30:00` | `[h]:mm:ss` |
|
|
339
|
+
| Custom | User-defined Excel-style code | — |
|
|
340
|
+
|
|
341
|
+
### How it works
|
|
342
|
+
|
|
343
|
+
- **Storage**: the format code is stored per-cell in `cell.style.numberFormat` (a string). Omitting the property (or empty string) means General.
|
|
344
|
+
- **UI**: the toolbar number-format dropdown applies presets to the current selection; the **「Format…」(格式…)** item opens `numberFormatDialog.vue` for a custom code, decimals, and thousands separator.
|
|
345
|
+
- **Display**: `formatNumber(value, format, locale)` parses the code (cached), applies thousands separators / decimals / percent scaling / date-serial conversion, and returns the display string. Invalid date/duration serials render as `###`.
|
|
346
|
+
- **Alignment**: numeric formats default to right-aligned; Text and General-with-non-numeric keep left alignment — matching Excel semantics.
|
|
347
|
+
- **i18n**: currency symbol (`¥` / `$`), month and weekday names follow the `locale` prop.
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
310
351
|
## Theming
|
|
311
352
|
|
|
312
353
|
### Built-in Themes
|
|
@@ -397,9 +438,9 @@ The project includes a GitHub Actions workflow (`.github/workflows/publish.yml`)
|
|
|
397
438
|
|
|
398
439
|
### Near-term
|
|
399
440
|
|
|
400
|
-
- [
|
|
441
|
+
- [x] More formulas: `COUNT`, `IF`, `VLOOKUP`, `CONCATENATE`
|
|
401
442
|
- [ ] Cell background color picker
|
|
402
|
-
- [
|
|
443
|
+
- [x] Number format (currency, percentage, date, number of decimals) — *see [Number Format](#number-format)*
|
|
403
444
|
- [ ] Conditional formatting rules
|
|
404
445
|
- [ ] Auto-fill drag handle
|
|
405
446
|
- [ ] Find & Replace
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.sp-dropdown[data-v-67defaed]{position:relative;display:inline-flex;min-width:0}.sp-dropdown__trigger[data-v-67defaed]{display:flex;align-items:center;justify-content:space-between;gap:4px;width:100%;height:26px;border:1px solid transparent;border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color, #444);font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;cursor:pointer;padding:0 5px;box-sizing:border-box}.sp-dropdown__trigger[data-v-67defaed]:hover{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6)}.sp-dropdown__trigger--open[data-v-67defaed]{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6);border-color:var(--sp-toolbar-border, #d8d8d8)}.sp-dropdown__value[data-v-67defaed]{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}.sp-dropdown__caret[data-v-67defaed]{width:10px;height:10px;min-width:10px;opacity:.7}.sp-dropdown__menu[data-v-67defaed]{position:fixed;z-index:20000;display:flex;flex-direction:column;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;padding:4px;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;transform-origin:top center}.sp-dropdown__menu--up[data-v-67defaed]{transform-origin:bottom center}.menu-pop-enter-active[data-v-67defaed],.menu-pop-leave-active[data-v-67defaed]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-67defaed],.menu-pop-leave-to[data-v-67defaed]{opacity:0;transform:scaleY(.85)}.sp-dropdown__nav[data-v-67defaed]{display:flex;align-items:center;justify-content:center;height:15px;min-height:15px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #666);cursor:pointer;padding:0;border-radius:3px}.sp-dropdown__nav[data-v-67defaed]:hover:not(:disabled){background:#eef3f9}.sp-dropdown__nav[data-v-67defaed]:disabled{color:#ccc;cursor:default}.sp-dropdown__nav svg[data-v-67defaed]{width:10px;height:10px}.sp-dropdown__list[data-v-67defaed]{display:flex;flex-direction:column;overflow:hidden;touch-action:none}.sp-dropdown__icon[data-v-67defaed]{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.sp-dropdown__icon[data-v-67defaed] svg{width:18px;height:18px;display:block}.sp-dropdown__item-icon[data-v-67defaed]{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.sp-dropdown__item-icon[data-v-67defaed] svg{width:16px;height:16px;display:block}.sp-dropdown__item-label[data-v-67defaed]{white-space:nowrap}.sp-dropdown__item[data-v-67defaed]{display:flex;align-items:center;gap:6px;width:100%;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);font-size:12px;cursor:pointer;padding:4px 8px;box-sizing:border-box;border-radius:3px}.sp-dropdown__item[data-v-67defaed]:hover{background:#eef3f9}.sp-dropdown__item--active[data-v-67defaed]{background:#e5f1fb;color:#0078d7}.color-picker[data-v-f8fac424]{position:relative;display:inline-flex;height:26px}.color-picker__menu[data-v-f8fac424]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;padding:6px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;transform-origin:top right}.menu-pop-enter-active[data-v-f8fac424],.menu-pop-leave-active[data-v-f8fac424]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-f8fac424],.menu-pop-leave-to[data-v-f8fac424]{opacity:0;transform:scale(.9)}.color-picker__row[data-v-f8fac424]{display:flex;gap:4px;margin-bottom:4px}.color-picker__row[data-v-f8fac424]:last-child{margin-bottom:0}.color-picker__swatch[data-v-f8fac424]{width:20px;height:20px;padding:0;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:transform .08s,box-shadow .08s;position:relative}.color-picker__swatch[data-v-f8fac424]:hover{transform:scale(1.18);box-shadow:0 0 0 1px #0003;z-index:1}.color-picker__swatch--selected[data-v-f8fac424]{box-shadow:0 0 0 2px #0078d7}.border-picker[data-v-f362abdb]{position:relative;display:inline-flex;height:26px}.border-picker__menu[data-v-f362abdb]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.border-picker__item[data-v-f362abdb]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.border-picker__item[data-v-f362abdb]:hover{background:#eef3f9}.border-picker__icon[data-v-f362abdb]{width:18px;height:18px;flex-shrink:0}.border-picker__label[data-v-f362abdb]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-f362abdb],.menu-pop-leave-active[data-v-f362abdb]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-f362abdb],.menu-pop-leave-to[data-v-f362abdb]{opacity:0;transform:scale(.9)}.merge-picker[data-v-67c0f9e3]{position:relative;display:inline-flex;height:26px}.merge-picker__menu[data-v-67c0f9e3]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.merge-picker__item[data-v-67c0f9e3]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.merge-picker__item[data-v-67c0f9e3]:hover{background:#eef3f9}.merge-picker__icon[data-v-67c0f9e3]{width:18px;height:18px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.merge-picker__icon[data-v-67c0f9e3] svg{width:18px;height:18px}.merge-picker__label[data-v-67c0f9e3]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-67c0f9e3],.menu-pop-leave-active[data-v-67c0f9e3]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-67c0f9e3],.menu-pop-leave-to[data-v-67c0f9e3]{opacity:0;transform:scale(.9)}.calc-picker[data-v-08615aee]{position:relative;display:inline-flex;height:26px}.calc-picker__menu[data-v-08615aee]{position:fixed;z-index:9999;min-width:120px;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.calc-picker__item[data-v-08615aee]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.calc-picker__item[data-v-08615aee]:hover:not(.calc-picker__item--disabled){background:#eef3f9}.calc-picker__item--disabled[data-v-08615aee]{color:var(--sp-toolbar-btn-disabled-color, #bbb);cursor:default}.calc-picker__label[data-v-08615aee]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-08615aee],.menu-pop-leave-active[data-v-08615aee]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-08615aee],.menu-pop-leave-to[data-v-08615aee]{opacity:0;transform:scale(.9)}.toolbar[data-v-dc556a27]{position:relative;display:flex;align-items:center;height:32px;min-height:32px;gap:2px;padding:0 6px;background:var(--sp-toolbar-bg);border-bottom:1px solid var(--sp-toolbar-border);-webkit-user-select:none;user-select:none}.tb-item[data-v-dc556a27]{display:flex;align-items:center;flex:0 0 auto}.toolbar-sep[data-v-dc556a27]{width:1px;height:18px;margin:0 4px;background:var(--sp-toolbar-border)}.toolbar-font[data-v-dc556a27],.toolbar-align[data-v-dc556a27]{flex:0 0 auto}.toolbar-font-size[data-v-dc556a27]{display:inline-flex;align-items:center;gap:0;height:26px;position:relative}.toolbar-font-size__input[data-v-dc556a27]{width:36px;height:26px;border:1px solid transparent;border-right:none;border-radius:3px 0 0 3px;background:transparent;color:var(--sp-toolbar-btn-color);font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;text-align:left;padding:0 5px;outline:none;box-sizing:border-box;-webkit-appearance:none;appearance:none;-moz-appearance:textfield}.toolbar-font-size__input[data-v-dc556a27]::-webkit-outer-spin-button,.toolbar-font-size__input[data-v-dc556a27]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.toolbar-font-size__input[data-v-dc556a27]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-font-size__input[data-v-dc556a27]:focus{border-color:var(--sp-toolbar-border);background:#fff}.toolbar-font-size__btn[data-v-dc556a27]{display:flex;align-items:center;justify-content:center;width:16px;height:26px;border:1px solid transparent;border-left:none;border-radius:0 3px 3px 0;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0}.toolbar-font-size__btn[data-v-dc556a27]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-font-size__btn svg[data-v-dc556a27]{width:10px;height:10px}.toolbar-font-size__dropdown[data-v-dc556a27]{position:absolute;width:56px;height:26px;pointer-events:none}.toolbar-btn[data-v-dc556a27]{display:flex;align-items:center;justify-content:center;width:30px;height:26px;border:none;border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0}.toolbar-btn[data-v-dc556a27]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.toolbar-btn[data-v-dc556a27]:active:not(:disabled){opacity:.7}.toolbar-btn--active[data-v-dc556a27]{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.toolbar-btn--step[data-v-dc556a27]{width:26px;height:26px}.toolbar-btn--step svg[data-v-dc556a27]{width:16px;height:16px}.toolbar-btn[data-v-dc556a27]:disabled{color:var(--sp-toolbar-btn-disabled-color);cursor:default}.toolbar-btn__icon[data-v-dc556a27]{width:18px;height:18px}.toolbar-btn svg[data-v-dc556a27]:not(.toolbar-btn__icon){width:18px;height:18px}.toolbar-split[data-v-dc556a27]{display:inline-flex;align-items:center;position:relative;height:26px}.toolbar-split__main[data-v-dc556a27]{border:1px solid transparent;border-right:none;border-radius:3px 0 0 3px}.toolbar-split__arrow[data-v-dc556a27]{display:flex;align-items:center;justify-content:center;width:16px;height:26px;border:1px solid transparent;border-radius:0 3px 3px 0;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0}.toolbar-split__arrow[data-v-dc556a27]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.toolbar-split__arrow svg[data-v-dc556a27]{width:10px!important;height:10px!important}.toolbar-more[data-v-dc556a27]{display:flex;align-items:center;justify-content:center;width:30px;height:26px;border:none;border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0;flex:0 0 auto;margin-left:auto}.toolbar-more[data-v-dc556a27]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-more--active[data-v-dc556a27]{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.toolbar-more svg[data-v-dc556a27]{width:18px;height:18px}.overflow-menu[data-v-dc556a27]{min-width:180px;max-width:260px;max-height:calc(100vh - 40px);overflow-y:auto;background:var(--sp-toolbar-bg, #fff);border:1px solid var(--sp-toolbar-border);border-radius:4px;box-shadow:0 4px 12px #0000001f;padding:4px 6px;display:flex;flex-direction:column;gap:2px;z-index:1000;transform-origin:top right}.overflow-menu.no-anim[data-v-dc556a27]{transition:none!important}.overflow-menu .tb-item[data-v-dc556a27]{width:100%}.overflow-menu .toolbar-sep[data-v-dc556a27]{width:100%;height:1px;margin:2px 0}.overflow-menu .toolbar-split[data-v-dc556a27]{width:100%}.overflow-menu .toolbar-split__main[data-v-dc556a27]{flex:1 1 auto;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-font-size[data-v-dc556a27]{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font[data-v-dc556a27],.overflow-menu .toolbar-align[data-v-dc556a27]{width:100%}.overflow-menu .toolbar-btn[data-v-dc556a27]:not(.toolbar-btn--step):not(.toolbar-split__arrow){width:100%;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-color[data-v-dc556a27]{width:100%}.overflow-menu .toolbar-wrap[data-v-dc556a27]{width:100%;justify-content:flex-start}.menu-pop-enter-active[data-v-dc556a27],.menu-pop-leave-active[data-v-dc556a27]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-dc556a27],.menu-pop-leave-to[data-v-dc556a27]{opacity:0;transform:scale(.9)}.overflow-menu .tb-item{width:100%}.overflow-menu .toolbar-sep{width:100%;height:1px;margin:2px 0}.overflow-menu .toolbar-split{width:100%}.overflow-menu .toolbar-split__main{flex:1 1 auto;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-font-size{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font,.overflow-menu .toolbar-align{width:100%}.overflow-menu .toolbar-btn:not(.toolbar-btn--step):not(.toolbar-split__arrow){width:100%;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-color{width:100%}.overflow-menu .toolbar-wrap{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font-size__input{flex:1 1 auto;width:auto;min-width:40px}.overflow-menu .toolbar-btn:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-btn:active:not(:disabled){opacity:.7}.overflow-menu .toolbar-btn--active{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.overflow-menu .toolbar-btn:disabled{color:var(--sp-toolbar-btn-disabled-color);cursor:default}.overflow-menu .toolbar-split__main:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-split__arrow:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-font-size__input:hover{background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-font-size__input:focus{border-color:var(--sp-toolbar-border);background:#fff}.overflow-menu .toolbar-font-size__btn:hover,.overflow-menu .toolbar-more:hover{background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-more--active{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.tab-bar[data-v-454e1a12]{display:flex;align-items:stretch;height:30px;min-height:30px;background:var(--sp-tab-bar-bg);border-top:1px solid var(--sp-tab-bar-border);-webkit-user-select:none;user-select:none;margin-top:4px}.tab-list[data-v-454e1a12]{display:flex;align-items:flex-start;flex:1;overflow:hidden;gap:1px;padding:0 1px}.tab-item[data-v-454e1a12]{display:flex;align-items:center;height:28px;min-width:0;max-width:120px;padding:0 10px;cursor:pointer;border:1px solid var(--sp-tab-inactive-border);background:var(--sp-tab-inactive-bg);color:var(--sp-tab-inactive-color);font-size:14px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap;transition:background .1s}.tab-item[data-v-454e1a12]:hover{background:var(--sp-tab-hover-bg)}.tab-item--active[data-v-454e1a12]{height:28px;background:var(--sp-tab-active-bg);color:var(--sp-tab-active-color);border-color:var(--sp-tab-active-bg) var(--sp-tab-bar-border) var(--sp-tab-bar-border);border-top:2px solid var(--sp-tab-active-border);font-size:16px}.tab-item--active[data-v-454e1a12]:hover{background:var(--sp-tab-active-bg)}.tab-item__name[data-v-454e1a12]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-rename-input[data-v-454e1a12]{width:100%;height:18px;border:none;border-radius:0;outline:none;padding:0;font-size:16px;font-family:inherit;background:var(--sp-tab-active-bg);color:var(--sp-tab-active-color);box-sizing:border-box}.tab-bar__add-btn[data-v-454e1a12]{width:24px;min-width:24px;height:24px;margin:0 4px 3px 3px;border:none;background:transparent;color:var(--sp-tab-add-btn-color);font-size:16px;line-height:22px;text-align:center;cursor:pointer;padding:0}.tab-bar__add-btn[data-v-454e1a12]:hover{background:var(--sp-tab-add-btn-hover-bg)}.spreadsheet-outer[data-v-562e145a]{flex:1;display:flex;flex-direction:column;overflow:hidden;height:100%;min-height:400px;width:100%}.formula-bar[data-v-562e145a]{display:flex;align-items:start;height:36px;min-height:36px;padding:0;gap:0}.formula-bar__cell-label[data-v-562e145a]{width:48px;min-width:48px;height:28px;line-height:28px;margin-top:4px;text-align:center;font-size:12px;font-weight:600;color:var(--sp-formula-bar-label-color);background:var(--sp-formula-bar-label-bg);border:1px solid var(--sp-formula-bar-label-border);border-radius:2px;-webkit-user-select:none;user-select:none}.formula-bar__input[data-v-562e145a]{flex:1;height:28px;margin-top:4px;border:1px solid var(--sp-formula-bar-input-border);border-radius:2px;outline:none;padding:0 6px;margin-left:4px;font-size:13px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:var(--sp-formula-bar-input-color);background:var(--sp-formula-bar-input-bg)}.formula-bar__input[data-v-562e145a]:focus{border-color:var(--sp-formula-bar-input-focus-border);box-shadow:0 0 0 1px var(--sp-formula-bar-input-focus-shadow)}.spreadsheet-wrapper[data-v-562e145a]{flex:1;position:relative;overflow:hidden;background:var(--sp-wrapper-bg)}.grid-canvas[data-v-562e145a]{position:absolute;top:0;left:0;display:block;outline:none;cursor:cell}.grid-canvas[data-v-562e145a]:focus{outline:none}.v-scrollbar[data-v-562e145a]{position:absolute;right:0;top:0;width:11px;height:calc(100% - 11px);display:flex;flex-direction:column;background:var(--sp-wrapper-bg)}.h-scrollbar[data-v-562e145a]{position:absolute;left:0;bottom:0;height:11px;width:calc(100% - 11px);display:flex;background:var(--sp-wrapper-bg)}.sb-corner[data-v-562e145a]{position:absolute;right:0;bottom:0;width:11px;height:11px;background:var(--sp-wrapper-bg)}.sb-btn[data-v-562e145a]{width:11px;height:11px;min-width:11px;min-height:11px;border:none;background:var(--sp-scroll-btn-bg, #e8e8e8);display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;-webkit-user-select:none;user-select:none}.sb-btn[data-v-562e145a]:hover{background:var(--sp-scroll-btn-hover-bg, #d0d0d0)}.sb-btn[data-v-562e145a]:active{background:var(--sp-scroll-btn-active-bg, #c0c0c0)}.sb-arrow[data-v-562e145a]{display:block;width:0;height:0}.sb-arrow--up[data-v-562e145a]{border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:4px solid var(--sp-scroll-btn-color, #666)}.sb-arrow--down[data-v-562e145a]{border-left:3px solid transparent;border-right:3px solid transparent;border-top:4px solid var(--sp-scroll-btn-color, #666)}.sb-arrow--left[data-v-562e145a]{border-top:3px solid transparent;border-bottom:3px solid transparent;border-right:4px solid var(--sp-scroll-btn-color, #666)}.sb-arrow--right[data-v-562e145a]{border-top:3px solid transparent;border-bottom:3px solid transparent;border-left:4px solid var(--sp-scroll-btn-color, #666)}.sb-track[data-v-562e145a]{flex:1;position:relative;background:var(--sp-scroll-track-bg, rgba(0,0,0,.06))}.sb-track--v[data-v-562e145a]{width:11px}.sb-track--h[data-v-562e145a]{height:11px}.sb-thumb[data-v-562e145a]{position:absolute;border-radius:3px;background:var(--sp-scroll-thumb);cursor:default}.sb-thumb[data-v-562e145a]:hover{background:var(--sp-scroll-thumb-hover)}.sb-thumb--v[data-v-562e145a]{left:1px;right:1px;min-height:16px}.sb-thumb--h[data-v-562e145a]{top:1px;bottom:1px;min-width:16px}.cell-editor[data-v-562e145a]{position:absolute;border:2px solid var(--sp-cell-editor-border);outline:none;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;font-size:13px;color:var(--sp-cell-editor-color);background:var(--sp-cell-editor-bg);box-shadow:0 0 0 1px var(--sp-cell-editor-shadow);z-index:10;box-sizing:border-box;min-width:0;overflow:hidden;padding:0;margin:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;resize:none;white-space:pre-wrap;word-break:break-all}.context-menu{position:fixed;z-index:10000;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:4px 0;min-width:120px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;font-size:13px;transform-origin:top left}.context-menu__item{padding:6px 20px;cursor:pointer;color:#333;white-space:nowrap;position:relative;display:flex;align-items:center;justify-content:space-between}.context-menu__item:hover{background:#e8f0fe}.context-menu__item--disabled{color:#bbb;cursor:default}.context-menu__item--disabled:hover{background:transparent}.context-menu__arrow{margin-left:16px;margin-right:-5px;width:0;height:0;border-top:3px solid transparent;border-bottom:3px solid transparent;border-left:4px solid #888}.context-submenu{display:none;position:absolute;left:100%;top:-4px;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:4px 0;min-width:100px;z-index:10001}.context-submenu--left{left:auto;right:100%}.context-menu__item:hover>.context-submenu{display:block}.context-submenu .context-menu__item{justify-content:flex-start}.menu-pop-enter-active,.menu-pop-leave-active{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from,.menu-pop-leave-to{opacity:0;transform:scale(.9)}.dim-panel{position:fixed;z-index:10002;width:220px;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:10px 12px;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;-webkit-user-select:none;user-select:none;transform-origin:top left}.dim-panel__title{font-size:13px;font-weight:600;color:#333;margin-bottom:8px}.dim-panel__body{display:flex;align-items:center;gap:6px}.dim-panel__input{flex:1;height:26px;border:1px solid #c0c0c0;border-radius:3px;outline:none;padding:0 6px;font-size:13px;color:#1a1a1a;background:#fff;box-sizing:border-box}.dim-panel__input:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.dim-panel__input--error{border-color:#d93025;box-shadow:0 0 0 1px #d930254d}.dim-panel__unit{font-size:12px;color:#888}.dim-panel__error{margin-top:6px;font-size:12px;color:#d93025;line-height:1.4}.dim-panel__footer{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}.dim-panel__btn{height:26px;padding:0 14px;border:1px solid #ccc;border-radius:3px;background:#fff;color:#333;font-size:13px;cursor:pointer}.dim-panel__btn:hover{background:#f0f0f0}.dim-panel__btn--primary{border-color:#0078d7;background:#0078d7;color:#fff}.dim-panel__btn--primary:hover{background:#0069c0}
|
|
1
|
+
.sp-dropdown[data-v-77df3baf]{position:relative;display:inline-flex;min-width:0}.sp-dropdown__trigger[data-v-77df3baf]{display:flex;align-items:center;justify-content:space-between;gap:4px;width:100%;height:26px;border:1px solid transparent;border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color, #444);font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;cursor:pointer;padding:0 5px;box-sizing:border-box}.sp-dropdown__trigger[data-v-77df3baf]:hover{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6)}.sp-dropdown__trigger--open[data-v-77df3baf]{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6);border-color:var(--sp-toolbar-border, #d8d8d8)}.sp-dropdown__value[data-v-77df3baf]{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}.sp-dropdown__caret[data-v-77df3baf]{width:10px;height:10px;min-width:10px;opacity:.7}.sp-dropdown__menu[data-v-77df3baf]{position:fixed;z-index:20000;display:flex;flex-direction:column;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;padding:4px;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;transform-origin:top center}.sp-dropdown__menu--up[data-v-77df3baf]{transform-origin:bottom center}.menu-pop-enter-active[data-v-77df3baf],.menu-pop-leave-active[data-v-77df3baf]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-77df3baf],.menu-pop-leave-to[data-v-77df3baf]{opacity:0;transform:scaleY(.85)}.sp-dropdown__nav[data-v-77df3baf]{display:flex;align-items:center;justify-content:center;height:15px;min-height:15px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #666);cursor:pointer;padding:0;border-radius:3px}.sp-dropdown__nav[data-v-77df3baf]:hover:not(:disabled){background:#eef3f9}.sp-dropdown__nav[data-v-77df3baf]:disabled{color:#ccc;cursor:default}.sp-dropdown__nav svg[data-v-77df3baf]{width:10px;height:10px}.sp-dropdown__list[data-v-77df3baf]{display:flex;flex-direction:column;overflow:hidden;touch-action:none}.sp-dropdown__icon[data-v-77df3baf]{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.sp-dropdown__icon[data-v-77df3baf] svg{width:18px;height:18px;display:block}.sp-dropdown__item-icon[data-v-77df3baf]{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.sp-dropdown__item-icon[data-v-77df3baf] svg{width:16px;height:16px;display:block}.sp-dropdown__item-label[data-v-77df3baf]{white-space:nowrap}.sp-dropdown__item[data-v-77df3baf]{display:flex;align-items:center;gap:6px;width:100%;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);font-size:12px;cursor:pointer;padding:4px 8px;box-sizing:border-box;border-radius:3px}.sp-dropdown__item[data-v-77df3baf]:hover{background:#eef3f9}.sp-dropdown__item--active[data-v-77df3baf]{background:#e5f1fb;color:#0078d7}.color-picker[data-v-f8fac424]{position:relative;display:inline-flex;height:26px}.color-picker__menu[data-v-f8fac424]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;padding:6px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;transform-origin:top right}.menu-pop-enter-active[data-v-f8fac424],.menu-pop-leave-active[data-v-f8fac424]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-f8fac424],.menu-pop-leave-to[data-v-f8fac424]{opacity:0;transform:scale(.9)}.color-picker__row[data-v-f8fac424]{display:flex;gap:4px;margin-bottom:4px}.color-picker__row[data-v-f8fac424]:last-child{margin-bottom:0}.color-picker__swatch[data-v-f8fac424]{width:20px;height:20px;padding:0;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:transform .08s,box-shadow .08s;position:relative}.color-picker__swatch[data-v-f8fac424]:hover{transform:scale(1.18);box-shadow:0 0 0 1px #0003;z-index:1}.color-picker__swatch--selected[data-v-f8fac424]{box-shadow:0 0 0 2px #0078d7}.border-picker[data-v-f362abdb]{position:relative;display:inline-flex;height:26px}.border-picker__menu[data-v-f362abdb]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.border-picker__item[data-v-f362abdb]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.border-picker__item[data-v-f362abdb]:hover{background:#eef3f9}.border-picker__icon[data-v-f362abdb]{width:18px;height:18px;flex-shrink:0}.border-picker__label[data-v-f362abdb]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-f362abdb],.menu-pop-leave-active[data-v-f362abdb]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-f362abdb],.menu-pop-leave-to[data-v-f362abdb]{opacity:0;transform:scale(.9)}.merge-picker[data-v-67c0f9e3]{position:relative;display:inline-flex;height:26px}.merge-picker__menu[data-v-67c0f9e3]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.merge-picker__item[data-v-67c0f9e3]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.merge-picker__item[data-v-67c0f9e3]:hover{background:#eef3f9}.merge-picker__icon[data-v-67c0f9e3]{width:18px;height:18px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.merge-picker__icon[data-v-67c0f9e3] svg{width:18px;height:18px}.merge-picker__label[data-v-67c0f9e3]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-67c0f9e3],.menu-pop-leave-active[data-v-67c0f9e3]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-67c0f9e3],.menu-pop-leave-to[data-v-67c0f9e3]{opacity:0;transform:scale(.9)}.calc-picker[data-v-9029e58c]{position:relative;display:inline-flex;height:26px}.calc-picker__menu[data-v-9029e58c]{position:fixed;z-index:9999;min-width:120px;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.calc-picker__item[data-v-9029e58c]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.calc-picker__item[data-v-9029e58c]:hover:not(.calc-picker__item--disabled){background:#eef3f9}.calc-picker__item--disabled[data-v-9029e58c]{color:var(--sp-toolbar-btn-disabled-color, #bbb);cursor:default}.calc-picker__label[data-v-9029e58c]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-9029e58c],.menu-pop-leave-active[data-v-9029e58c]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-9029e58c],.menu-pop-leave-to[data-v-9029e58c]{opacity:0;transform:scale(.9)}.toolbar[data-v-7328a54c]{position:relative;display:flex;align-items:center;height:32px;min-height:32px;gap:2px;padding:0 6px;background:var(--sp-toolbar-bg);border-bottom:1px solid var(--sp-toolbar-border);-webkit-user-select:none;user-select:none}.tb-item[data-v-7328a54c]{display:flex;align-items:center;flex:0 0 auto}.toolbar-sep[data-v-7328a54c]{width:1px;height:18px;margin:0 4px;background:var(--sp-toolbar-border)}.toolbar-font[data-v-7328a54c],.toolbar-number-format[data-v-7328a54c],.toolbar-align[data-v-7328a54c]{flex:0 0 auto}.toolbar-font-size[data-v-7328a54c]{display:inline-flex;align-items:center;gap:0;height:26px;position:relative}.toolbar-font-size__input[data-v-7328a54c]{width:36px;height:26px;border:1px solid transparent;border-right:none;border-radius:3px 0 0 3px;background:transparent;color:var(--sp-toolbar-btn-color);font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;text-align:left;padding:0 5px;outline:none;box-sizing:border-box;-webkit-appearance:none;appearance:none;-moz-appearance:textfield}.toolbar-font-size__input[data-v-7328a54c]::-webkit-outer-spin-button,.toolbar-font-size__input[data-v-7328a54c]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.toolbar-font-size__input[data-v-7328a54c]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-font-size__input[data-v-7328a54c]:focus{border-color:var(--sp-toolbar-border);background:#fff}.toolbar-font-size__btn[data-v-7328a54c]{display:flex;align-items:center;justify-content:center;width:16px;height:26px;border:1px solid transparent;border-left:none;border-radius:0 3px 3px 0;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0}.toolbar-font-size__btn[data-v-7328a54c]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-font-size__btn svg[data-v-7328a54c]{width:10px;height:10px}.toolbar-font-size__dropdown[data-v-7328a54c]{position:absolute;width:56px;height:26px;pointer-events:none}.toolbar-btn[data-v-7328a54c]{display:flex;align-items:center;justify-content:center;width:30px;height:26px;border:none;border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0}.toolbar-btn[data-v-7328a54c]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.toolbar-btn[data-v-7328a54c]:active:not(:disabled){opacity:.7}.toolbar-btn--active[data-v-7328a54c]{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.toolbar-btn--step[data-v-7328a54c]{width:26px;height:26px}.toolbar-btn--step svg[data-v-7328a54c]{width:16px;height:16px}.toolbar-btn[data-v-7328a54c]:disabled{color:var(--sp-toolbar-btn-disabled-color);cursor:default}.toolbar-btn__icon[data-v-7328a54c]{width:18px;height:18px}.toolbar-btn svg[data-v-7328a54c]:not(.toolbar-btn__icon){width:18px;height:18px}.toolbar-split[data-v-7328a54c]{display:inline-flex;align-items:center;position:relative;height:26px}.toolbar-split__main[data-v-7328a54c]{border:1px solid transparent;border-right:none;border-radius:3px 0 0 3px}.toolbar-split__arrow[data-v-7328a54c]{display:flex;align-items:center;justify-content:center;width:16px;height:26px;border:1px solid transparent;border-radius:0 3px 3px 0;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0}.toolbar-split__arrow[data-v-7328a54c]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.toolbar-split__arrow svg[data-v-7328a54c]{width:10px!important;height:10px!important}.toolbar-more[data-v-7328a54c]{display:flex;align-items:center;justify-content:center;width:30px;height:26px;border:none;border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0;flex:0 0 auto;margin-left:auto}.toolbar-more[data-v-7328a54c]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-more--active[data-v-7328a54c]{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.toolbar-more svg[data-v-7328a54c]{width:18px;height:18px}.overflow-menu[data-v-7328a54c]{min-width:180px;max-width:260px;max-height:calc(100vh - 40px);overflow-y:auto;background:var(--sp-toolbar-bg, #fff);border:1px solid var(--sp-toolbar-border);border-radius:4px;box-shadow:0 4px 12px #0000001f;padding:4px 6px;display:flex;flex-direction:column;gap:2px;z-index:1000;transform-origin:top right}.overflow-menu.no-anim[data-v-7328a54c]{transition:none!important}.overflow-menu .tb-item[data-v-7328a54c]{width:100%}.overflow-menu .toolbar-sep[data-v-7328a54c]{width:100%;height:1px;margin:2px 0}.overflow-menu .toolbar-split[data-v-7328a54c]{width:100%}.overflow-menu .toolbar-split__main[data-v-7328a54c]{flex:1 1 auto;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-font-size[data-v-7328a54c]{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font[data-v-7328a54c],.overflow-menu .toolbar-number-format[data-v-7328a54c],.overflow-menu .toolbar-align[data-v-7328a54c]{width:100%}.overflow-menu .toolbar-btn[data-v-7328a54c]:not(.toolbar-btn--step):not(.toolbar-split__arrow){width:100%;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-color[data-v-7328a54c]{width:100%}.overflow-menu .toolbar-wrap[data-v-7328a54c]{width:100%;justify-content:flex-start}.menu-pop-enter-active[data-v-7328a54c],.menu-pop-leave-active[data-v-7328a54c]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-7328a54c],.menu-pop-leave-to[data-v-7328a54c]{opacity:0;transform:scale(.9)}.overflow-menu .tb-item{width:100%}.overflow-menu .toolbar-sep{width:100%;height:1px;margin:2px 0}.overflow-menu .toolbar-split{width:100%}.overflow-menu .toolbar-split__main{flex:1 1 auto;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-font-size{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font,.overflow-menu .toolbar-number-format,.overflow-menu .toolbar-align{width:100%}.overflow-menu .toolbar-btn:not(.toolbar-btn--step):not(.toolbar-split__arrow){width:100%;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-color{width:100%}.overflow-menu .toolbar-wrap{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font-size__input{flex:1 1 auto;width:auto;min-width:40px}.overflow-menu .toolbar-btn:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-btn:active:not(:disabled){opacity:.7}.overflow-menu .toolbar-btn--active{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.overflow-menu .toolbar-btn:disabled{color:var(--sp-toolbar-btn-disabled-color);cursor:default}.overflow-menu .toolbar-split__main:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-split__arrow:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-font-size__input:hover{background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-font-size__input:focus{border-color:var(--sp-toolbar-border);background:#fff}.overflow-menu .toolbar-font-size__btn:hover,.overflow-menu .toolbar-more:hover{background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-more--active{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.tab-bar[data-v-454e1a12]{display:flex;align-items:stretch;height:30px;min-height:30px;background:var(--sp-tab-bar-bg);border-top:1px solid var(--sp-tab-bar-border);-webkit-user-select:none;user-select:none;margin-top:4px}.tab-list[data-v-454e1a12]{display:flex;align-items:flex-start;flex:1;overflow:hidden;gap:1px;padding:0 1px}.tab-item[data-v-454e1a12]{display:flex;align-items:center;height:28px;min-width:0;max-width:120px;padding:0 10px;cursor:pointer;border:1px solid var(--sp-tab-inactive-border);background:var(--sp-tab-inactive-bg);color:var(--sp-tab-inactive-color);font-size:14px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap;transition:background .1s}.tab-item[data-v-454e1a12]:hover{background:var(--sp-tab-hover-bg)}.tab-item--active[data-v-454e1a12]{height:28px;background:var(--sp-tab-active-bg);color:var(--sp-tab-active-color);border-color:var(--sp-tab-active-bg) var(--sp-tab-bar-border) var(--sp-tab-bar-border);border-top:2px solid var(--sp-tab-active-border);font-size:16px}.tab-item--active[data-v-454e1a12]:hover{background:var(--sp-tab-active-bg)}.tab-item__name[data-v-454e1a12]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-rename-input[data-v-454e1a12]{width:100%;height:18px;border:none;border-radius:0;outline:none;padding:0;font-size:16px;font-family:inherit;background:var(--sp-tab-active-bg);color:var(--sp-tab-active-color);box-sizing:border-box}.tab-bar__add-btn[data-v-454e1a12]{width:24px;min-width:24px;height:24px;margin:0 4px 3px 3px;border:none;background:transparent;color:var(--sp-tab-add-btn-color);font-size:16px;line-height:22px;text-align:center;cursor:pointer;padding:0}.tab-bar__add-btn[data-v-454e1a12]:hover{background:var(--sp-tab-add-btn-hover-bg)}.nf-dialog__mask[data-v-69cb36b7]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:30000;background:rgba(0,0,0,.25);display:flex;align-items:center;justify-content:center}.nf-dialog[data-v-69cb36b7]{width:380px;max-width:calc(100vw - 32px);max-height:calc(100vh - 48px);overflow-y:auto;background:#fff;border:1px solid #d0d0d0;border-radius:6px;box-shadow:0 8px 24px #0000002e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:#1a1a1a;-webkit-user-select:none;user-select:none}.nf-dialog__header[data-v-69cb36b7]{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid #ececec}.nf-dialog__title[data-v-69cb36b7]{font-size:13px;font-weight:600}.nf-dialog__close[data-v-69cb36b7]{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:transparent;color:#888;cursor:pointer;border-radius:3px;padding:0}.nf-dialog__close[data-v-69cb36b7]:hover{background:#f0f0f0;color:#444}.nf-dialog__close svg[data-v-69cb36b7]{width:14px;height:14px}.nf-dialog__body[data-v-69cb36b7]{padding:12px 14px;display:flex;flex-direction:column;gap:10px}.nf-field[data-v-69cb36b7]{display:flex;align-items:center;gap:8px}.nf-field--inline[data-v-69cb36b7]{min-height:26px}.nf-field__label[data-v-69cb36b7]{width:88px;min-width:88px;font-size:12px;color:#555}.nf-field__select[data-v-69cb36b7],.nf-field__input[data-v-69cb36b7]{flex:1;height:26px;border:1px solid #c0c0c0;border-radius:3px;background:#fff;font-size:12px;color:#1a1a1a;padding:0 6px;outline:none;box-sizing:border-box;font-family:inherit}.nf-field__select[data-v-69cb36b7]:focus,.nf-field__input[data-v-69cb36b7]:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.nf-field__textarea[data-v-69cb36b7]{flex:1;min-height:44px;border:1px solid #c0c0c0;border-radius:3px;background:#fff;font-size:12px;color:#1a1a1a;padding:4px 6px;outline:none;box-sizing:border-box;resize:none;font-family:Consolas,Courier New,monospace}.nf-field__textarea[data-v-69cb36b7]:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.nf-checkbox[data-v-69cb36b7]{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:#333;cursor:pointer}.nf-checkbox input[data-v-69cb36b7]{margin:0;cursor:pointer}.nf-dialog__footer[data-v-69cb36b7]{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 14px;border-top:1px solid #ececec}.nf-preview[data-v-69cb36b7]{display:flex;flex-direction:column;gap:2px;min-width:0}.nf-preview__label[data-v-69cb36b7]{font-size:11px;color:#888}.nf-preview__value[data-v-69cb36b7]{font-size:13px;color:#1a1a1a;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}.nf-dialog__actions[data-v-69cb36b7]{display:flex;gap:8px}.nf-btn[data-v-69cb36b7]{height:28px;padding:0 16px;border:1px solid #ccc;border-radius:3px;background:#fff;color:#333;font-size:12px;cursor:pointer;font-family:inherit}.nf-btn[data-v-69cb36b7]:hover{background:#f0f0f0}.nf-btn--primary[data-v-69cb36b7]{border-color:#0078d7;background:#0078d7;color:#fff}.nf-btn--primary[data-v-69cb36b7]:hover{background:#0069c0}.nf-dialog-enter-active[data-v-69cb36b7],.nf-dialog-leave-active[data-v-69cb36b7]{transition:opacity .14s ease-out}.nf-dialog-enter-from[data-v-69cb36b7],.nf-dialog-leave-to[data-v-69cb36b7]{opacity:0}.nf-dialog-enter-active .nf-dialog[data-v-69cb36b7],.nf-dialog-leave-active .nf-dialog[data-v-69cb36b7]{transition:transform .14s ease-out}.nf-dialog-enter-from .nf-dialog[data-v-69cb36b7],.nf-dialog-leave-to .nf-dialog[data-v-69cb36b7]{transform:scale(.96)}.spreadsheet-outer[data-v-a54563ff]{flex:1;display:flex;flex-direction:column;overflow:hidden;height:100%;min-height:400px;width:100%}.formula-bar[data-v-a54563ff]{display:flex;align-items:flex-start;min-height:36px;padding:0;gap:0}.formula-bar--expanded[data-v-a54563ff]{min-height:72px}.formula-bar__cell-label[data-v-a54563ff]{width:48px;min-width:48px;height:28px;line-height:28px;margin-top:4px;text-align:center;font-size:12px;font-weight:600;color:var(--sp-formula-bar-label-color);background:var(--sp-formula-bar-label-bg);border:1px solid var(--sp-formula-bar-label-border);border-radius:2px;-webkit-user-select:none;user-select:none}.formula-bar__buttons[data-v-a54563ff]{display:inline-flex;align-items:stretch;margin-top:4px;margin-left:6px;height:28px;border:1px solid var(--sp-formula-bar-input-border);border-radius:2px;overflow:hidden;background:var(--sp-formula-bar-input-bg)}.formula-bar__btn[data-v-a54563ff]{width:22px;height:28px;border:none;border-radius:0;background:transparent;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;-webkit-user-select:none;user-select:none;color:inherit}.formula-bar__btn+.formula-bar__btn[data-v-a54563ff]{border-left:1px solid var(--sp-formula-bar-input-border)}.formula-bar__btn[data-v-a54563ff]:hover{background:var(--sp-scroll-btn-hover-bg, #f0f0f0)}.formula-bar__btn--cancel[data-v-a54563ff]:hover{color:#e53935;background:#fdecea}.formula-bar__btn--accept[data-v-a54563ff]:hover{color:#2e7d32;background:#e8f5e9}.formula-bar__input[data-v-a54563ff]{flex:1;min-height:28px;height:28px;line-height:20px;margin-top:4px;border:1px solid var(--sp-formula-bar-input-border);border-radius:2px;outline:none;padding:3px 6px;margin-left:4px;font-size:13px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:var(--sp-formula-bar-input-color);background:var(--sp-formula-bar-input-bg);resize:none;overflow:hidden;box-sizing:border-box}.formula-bar__input--expanded[data-v-a54563ff]{height:68px;overflow:auto}.formula-bar__input[data-v-a54563ff]:focus{border-color:var(--sp-formula-bar-input-focus-border);box-shadow:0 0 0 1px var(--sp-formula-bar-input-focus-shadow)}.formula-bar__toggle[data-v-a54563ff]{width:22px;min-width:22px;height:28px;margin-top:4px;margin-left:2px;margin-right:2px;border:1px solid var(--sp-formula-bar-input-border);border-radius:2px;background:var(--sp-formula-bar-input-bg);color:var(--sp-formula-bar-input-color);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;-webkit-user-select:none;user-select:none}.formula-bar__toggle[data-v-a54563ff]:hover{background:var(--sp-scroll-btn-hover-bg, #e8e8e8)}.spreadsheet-wrapper[data-v-a54563ff]{flex:1;position:relative;overflow:hidden;background:var(--sp-wrapper-bg)}.grid-canvas[data-v-a54563ff]{position:absolute;top:0;left:0;display:block;outline:none;cursor:cell}.grid-canvas[data-v-a54563ff]:focus{outline:none}.v-scrollbar[data-v-a54563ff]{position:absolute;right:0;top:0;width:11px;height:calc(100% - 11px);display:flex;flex-direction:column;background:var(--sp-wrapper-bg)}.h-scrollbar[data-v-a54563ff]{position:absolute;left:0;bottom:0;height:11px;width:calc(100% - 11px);display:flex;background:var(--sp-wrapper-bg)}.sb-corner[data-v-a54563ff]{position:absolute;right:0;bottom:0;width:11px;height:11px;background:var(--sp-wrapper-bg)}.sb-btn[data-v-a54563ff]{width:11px;height:11px;min-width:11px;min-height:11px;border:none;background:var(--sp-scroll-btn-bg, #e8e8e8);display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;-webkit-user-select:none;user-select:none}.sb-btn[data-v-a54563ff]:hover{background:var(--sp-scroll-btn-hover-bg, #d0d0d0)}.sb-btn[data-v-a54563ff]:active{background:var(--sp-scroll-btn-active-bg, #c0c0c0)}.sb-arrow[data-v-a54563ff]{display:block;width:0;height:0}.sb-arrow--up[data-v-a54563ff]{border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:4px solid var(--sp-scroll-btn-color, #666)}.sb-arrow--down[data-v-a54563ff]{border-left:3px solid transparent;border-right:3px solid transparent;border-top:4px solid var(--sp-scroll-btn-color, #666)}.sb-arrow--left[data-v-a54563ff]{border-top:3px solid transparent;border-bottom:3px solid transparent;border-right:4px solid var(--sp-scroll-btn-color, #666)}.sb-arrow--right[data-v-a54563ff]{border-top:3px solid transparent;border-bottom:3px solid transparent;border-left:4px solid var(--sp-scroll-btn-color, #666)}.sb-track[data-v-a54563ff]{flex:1;position:relative;background:var(--sp-scroll-track-bg, rgba(0,0,0,.06))}.sb-track--v[data-v-a54563ff]{width:11px}.sb-track--h[data-v-a54563ff]{height:11px}.sb-thumb[data-v-a54563ff]{position:absolute;border-radius:3px;background:var(--sp-scroll-thumb);cursor:default}.sb-thumb[data-v-a54563ff]:hover{background:var(--sp-scroll-thumb-hover)}.sb-thumb--v[data-v-a54563ff]{left:1px;right:1px;min-height:16px}.sb-thumb--h[data-v-a54563ff]{top:1px;bottom:1px;min-width:16px}.cell-editor[data-v-a54563ff]{position:absolute;border:2px solid var(--sp-cell-editor-border);outline:none;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;font-size:13px;color:var(--sp-cell-editor-color);background:var(--sp-cell-editor-bg);box-shadow:0 0 0 1px var(--sp-cell-editor-shadow);z-index:10;box-sizing:border-box;min-width:0;overflow:hidden;padding:0;margin:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;resize:none;white-space:pre-wrap;word-break:break-all}.context-menu{position:fixed;z-index:10000;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:4px 0;min-width:120px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;font-size:13px;transform-origin:top left}.context-menu__item{padding:6px 20px;cursor:pointer;color:#333;white-space:nowrap;position:relative;display:flex;align-items:center;justify-content:space-between}.context-menu__item:hover{background:#e8f0fe}.context-menu__item--disabled{color:#bbb;cursor:default}.context-menu__item--disabled:hover{background:transparent}.context-menu__arrow{margin-left:16px;margin-right:-5px;width:0;height:0;border-top:3px solid transparent;border-bottom:3px solid transparent;border-left:4px solid #888}.context-submenu{display:none;position:absolute;left:100%;top:-4px;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:4px 0;min-width:100px;z-index:10001}.context-submenu--left{left:auto;right:100%}.context-menu__item:hover>.context-submenu{display:block}.context-submenu .context-menu__item{justify-content:flex-start}.menu-pop-enter-active,.menu-pop-leave-active{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from,.menu-pop-leave-to{opacity:0;transform:scale(.9)}.dim-panel{position:fixed;z-index:10002;width:220px;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:10px 12px;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;-webkit-user-select:none;user-select:none;transform-origin:top left}.dim-panel__title{font-size:13px;font-weight:600;color:#333;margin-bottom:8px}.dim-panel__body{display:flex;align-items:center;gap:6px}.dim-panel__input{flex:1;height:26px;border:1px solid #c0c0c0;border-radius:3px;outline:none;padding:0 6px;font-size:13px;color:#1a1a1a;background:#fff;box-sizing:border-box}.dim-panel__input:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.dim-panel__input--error{border-color:#d93025;box-shadow:0 0 0 1px #d930254d}.dim-panel__unit{font-size:12px;color:#888}.dim-panel__error{margin-top:6px;font-size:12px;color:#d93025;line-height:1.4}.dim-panel__footer{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}.dim-panel__btn{height:26px;padding:0 14px;border:1px solid #ccc;border-radius:3px;background:#fff;color:#333;font-size:13px;cursor:pointer}.dim-panel__btn:hover{background:#f0f0f0}.dim-panel__btn--primary{border-color:#0078d7;background:#0078d7;color:#fff}.dim-panel__btn--primary:hover{background:#0069c0}
|
|
@@ -10,6 +10,8 @@ type __VLS_Props = {
|
|
|
10
10
|
hideTrigger?: boolean;
|
|
11
11
|
align?: 'left' | 'right';
|
|
12
12
|
triggerEl?: HTMLElement | null;
|
|
13
|
+
/** 当前值未命中任何选项时触发器显示的占位文本(如选区格式不一致时的「混合」) */
|
|
14
|
+
fallbackLabel?: string;
|
|
13
15
|
};
|
|
14
16
|
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
15
17
|
"update:modelValue": (v: string | number) => void;
|
|
@@ -28,6 +30,7 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
28
30
|
hideTrigger: boolean;
|
|
29
31
|
align: "left" | "right";
|
|
30
32
|
triggerEl: HTMLElement | null;
|
|
33
|
+
fallbackLabel: string;
|
|
31
34
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {
|
|
32
35
|
rootRef: HTMLDivElement;
|
|
33
36
|
menuRef: HTMLDivElement;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
modelOpen?: boolean;
|
|
3
|
+
locale?: string;
|
|
4
|
+
/** 当前选区格式(混合时由父组件传入空串,从常规开始) */
|
|
5
|
+
currentFormat?: string;
|
|
6
|
+
/** 预览样例值(默认 1234.5) */
|
|
7
|
+
sampleValue?: string;
|
|
8
|
+
};
|
|
9
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
10
|
+
"update:modelOpen": (v: boolean) => any;
|
|
11
|
+
apply: (formatCode: string) => any;
|
|
12
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
13
|
+
"onUpdate:modelOpen"?: ((v: boolean) => any) | undefined;
|
|
14
|
+
onApply?: ((formatCode: string) => any) | undefined;
|
|
15
|
+
}>, {
|
|
16
|
+
modelOpen: boolean;
|
|
17
|
+
locale: string;
|
|
18
|
+
currentFormat: string;
|
|
19
|
+
sampleValue: string;
|
|
20
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {
|
|
21
|
+
customCodeRef: HTMLTextAreaElement;
|
|
22
|
+
}, any>;
|
|
23
|
+
export default _default;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FontOption, MergeType } from '../core/constants';
|
|
2
|
+
import { type NFOption } from '../core/number-format';
|
|
2
3
|
import { type BorderType } from './pickers/borderPicker.vue';
|
|
3
4
|
type __VLS_Props = {
|
|
4
5
|
locale: string;
|
|
@@ -33,6 +34,8 @@ type __VLS_Props = {
|
|
|
33
34
|
calcMenuOpen: boolean;
|
|
34
35
|
isSingleCell: boolean;
|
|
35
36
|
themeVars?: Record<string, string>;
|
|
37
|
+
selNumberFormat: string;
|
|
38
|
+
nfOptions: NFOption[];
|
|
36
39
|
};
|
|
37
40
|
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
38
41
|
undo: () => void;
|
|
@@ -52,6 +55,9 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
52
55
|
"apply-border": () => void;
|
|
53
56
|
"wrap-toggle": () => void;
|
|
54
57
|
"apply-merge": () => void;
|
|
58
|
+
"calc-sum": () => void;
|
|
59
|
+
"calc-avg": () => void;
|
|
60
|
+
"calc-count": () => void;
|
|
55
61
|
"font-family-change": (v: string | number) => void;
|
|
56
62
|
"font-size-change": (v: string | number) => void;
|
|
57
63
|
"h-align-change": (v: string | number) => void;
|
|
@@ -59,6 +65,7 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
59
65
|
"font-size-input": (v: string) => void;
|
|
60
66
|
"text-color-change": (v: string) => void;
|
|
61
67
|
"fill-color-change": (v: string) => void;
|
|
68
|
+
"number-format-change": (v: string) => void;
|
|
62
69
|
"font-size-keydown": (ev: KeyboardEvent) => void;
|
|
63
70
|
"update:font-size-menu-open": (v: boolean) => void;
|
|
64
71
|
"update:text-color-menu-open": (v: boolean) => void;
|
|
@@ -68,8 +75,6 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
68
75
|
"update:calc-menu-open": (v: boolean) => void;
|
|
69
76
|
"border-change": (v: BorderType) => void;
|
|
70
77
|
"merge-change": (v: MergeType) => void;
|
|
71
|
-
"calc-sum": () => void;
|
|
72
|
-
"calc-avg": () => void;
|
|
73
78
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
74
79
|
onUndo?: (() => any) | undefined;
|
|
75
80
|
onRedo?: (() => any) | undefined;
|
|
@@ -88,6 +93,9 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
88
93
|
"onApply-border"?: (() => any) | undefined;
|
|
89
94
|
"onWrap-toggle"?: (() => any) | undefined;
|
|
90
95
|
"onApply-merge"?: (() => any) | undefined;
|
|
96
|
+
"onCalc-sum"?: (() => any) | undefined;
|
|
97
|
+
"onCalc-avg"?: (() => any) | undefined;
|
|
98
|
+
"onCalc-count"?: (() => any) | undefined;
|
|
91
99
|
"onFont-family-change"?: ((v: string | number) => any) | undefined;
|
|
92
100
|
"onFont-size-change"?: ((v: string | number) => any) | undefined;
|
|
93
101
|
"onH-align-change"?: ((v: string | number) => any) | undefined;
|
|
@@ -95,6 +103,7 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
95
103
|
"onFont-size-input"?: ((v: string) => any) | undefined;
|
|
96
104
|
"onText-color-change"?: ((v: string) => any) | undefined;
|
|
97
105
|
"onFill-color-change"?: ((v: string) => any) | undefined;
|
|
106
|
+
"onNumber-format-change"?: ((v: string) => any) | undefined;
|
|
98
107
|
"onFont-size-keydown"?: ((ev: KeyboardEvent) => any) | undefined;
|
|
99
108
|
"onUpdate:font-size-menu-open"?: ((v: boolean) => any) | undefined;
|
|
100
109
|
"onUpdate:text-color-menu-open"?: ((v: boolean) => any) | undefined;
|
|
@@ -104,8 +113,6 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
104
113
|
"onUpdate:calc-menu-open"?: ((v: boolean) => any) | undefined;
|
|
105
114
|
"onBorder-change"?: ((v: BorderType) => any) | undefined;
|
|
106
115
|
"onMerge-change"?: ((v: MergeType) => any) | undefined;
|
|
107
|
-
"onCalc-sum"?: (() => any) | undefined;
|
|
108
|
-
"onCalc-avg"?: (() => any) | undefined;
|
|
109
116
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {
|
|
110
117
|
rootEl: HTMLDivElement;
|
|
111
118
|
fontSizeArrowRef: HTMLButtonElement;
|
|
@@ -45,9 +45,11 @@ export interface BordersMergeState {
|
|
|
45
45
|
clearSelected: () => void;
|
|
46
46
|
sumSelected: () => void;
|
|
47
47
|
avgSelected: () => void;
|
|
48
|
+
countSelected: () => void;
|
|
48
49
|
calcMenuOpen: Ref<boolean>;
|
|
49
50
|
onCalcMenuToggle: (v: boolean) => void;
|
|
50
51
|
onCalcSum: () => void;
|
|
51
52
|
onCalcAvg: () => void;
|
|
53
|
+
onCalcCount: () => void;
|
|
52
54
|
}
|
|
53
55
|
export declare function createBordersMerge(s: CoreState, us: UndoStylesState): BordersMergeState;
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { type ComputedRef, type Ref } from 'vue';
|
|
2
2
|
import { FormulaDeps } from '../core/formula';
|
|
3
3
|
import type { CellCoord, CellData, SelectionRange } from '../core/types';
|
|
4
|
+
/** 选区触发方式,影响「合并单元格是否扩大选区」。
|
|
5
|
+
* - 'cell':单元格点击/拖动(默认)→ 保持现有 expandSelectionForMerges 行为
|
|
6
|
+
* - 'row' :行头点击/拖动 → Excel 风格「穿透」合并,选区矩形保持用户点击的行范围
|
|
7
|
+
* - 'col' :列头点击/拖动 → 同上,选区矩形保持用户点击的列范围
|
|
8
|
+
* - 'all' :左上角全选按钮 → expandSelectionForMerges 行为
|
|
9
|
+
*/
|
|
10
|
+
export type SelectionMode = 'cell' | 'row' | 'col' | 'all';
|
|
4
11
|
export interface CoreState {
|
|
5
12
|
props: {
|
|
6
13
|
rowCount: number;
|
|
@@ -47,9 +54,12 @@ export interface CoreState {
|
|
|
47
54
|
totalWidth: ComputedRef<number>;
|
|
48
55
|
totalHeight: ComputedRef<number>;
|
|
49
56
|
selectCell: (c: number, r: number) => void;
|
|
50
|
-
selectRange: (sC: number, sR: number, eC: number, eR: number) => void;
|
|
57
|
+
selectRange: (sC: number, sR: number, eC: number, eR: number, mode?: SelectionMode) => void;
|
|
51
58
|
selectAll: () => void;
|
|
52
59
|
isSelected: (c: number, r: number) => boolean;
|
|
60
|
+
/** 渲染高亮专用:整行/整列选择模式下「穿透」合并单元格,仅判断 (c,r) 自身是否在选区矩形内 */
|
|
61
|
+
isCellSelected: (c: number, r: number) => boolean;
|
|
62
|
+
selectionMode: Ref<SelectionMode>;
|
|
53
63
|
cellKey: (c: number, r: number) => string;
|
|
54
64
|
delCell: (k: string) => void;
|
|
55
65
|
findMerge: (c: number, r: number) => {
|
|
@@ -9,10 +9,14 @@ export interface InteractionsState {
|
|
|
9
9
|
render: () => void;
|
|
10
10
|
activeCellLabel: ComputedRef<string>;
|
|
11
11
|
formulaBarDisplay: ComputedRef<string>;
|
|
12
|
+
formulaBarDraft: Ref<string>;
|
|
13
|
+
formulaBarExpanded: Ref<boolean>;
|
|
12
14
|
onFormulaBarFocus: () => void;
|
|
13
15
|
onFormulaBarInput: (e: Event) => void;
|
|
14
16
|
onFormulaBarKeydown: (e: KeyboardEvent) => void;
|
|
15
17
|
onFormulaBarBlur: () => void;
|
|
18
|
+
acceptFormulaBarEdit: () => void;
|
|
19
|
+
cancelFormulaBarEdit: () => void;
|
|
16
20
|
renTab: Ref<number | null>;
|
|
17
21
|
renTabVal: Ref<string>;
|
|
18
22
|
onTabClick: (i: number) => void;
|
|
@@ -27,7 +27,7 @@ export interface SheetsOpsState {
|
|
|
27
27
|
wrapperRef: Ref<HTMLDivElement | null>;
|
|
28
28
|
canvasRef: Ref<HTMLCanvasElement | null>;
|
|
29
29
|
editInputRef: Ref<HTMLTextAreaElement | null>;
|
|
30
|
-
formulaBarRef: Ref<
|
|
30
|
+
formulaBarRef: Ref<HTMLTextAreaElement | null>;
|
|
31
31
|
viewSize: {
|
|
32
32
|
w: number;
|
|
33
33
|
h: number;
|
|
@@ -2,6 +2,7 @@ import { type ComputedRef, type Ref } from 'vue';
|
|
|
2
2
|
import type { FontOption } from '../core/constants';
|
|
3
3
|
import type { CoreState } from './core-state';
|
|
4
4
|
import type { CellData, SheetState } from '../core/types';
|
|
5
|
+
import { type NFOption } from '../core/number-format';
|
|
5
6
|
export interface UndoStylesState {
|
|
6
7
|
undoStack: Ref<UndoSnap[]>;
|
|
7
8
|
redoStack: Ref<UndoSnap[]>;
|
|
@@ -67,6 +68,13 @@ export interface UndoStylesState {
|
|
|
67
68
|
selFillColor: ComputedRef<string>;
|
|
68
69
|
borderMenuOpen?: Ref<boolean>;
|
|
69
70
|
mergeMenuOpen?: Ref<boolean>;
|
|
71
|
+
nfOptions: ComputedRef<NFOption[]>;
|
|
72
|
+
selNumberFormat: ComputedRef<string>;
|
|
73
|
+
NF_NUMBER_FORMAT_MIXED: string;
|
|
74
|
+
nfDialogOpen: Ref<boolean>;
|
|
75
|
+
onNumberFormatChange: (v: string) => void;
|
|
76
|
+
openNumberFormatDialog: () => void;
|
|
77
|
+
applyNumberFormatCode: (code: string) => void;
|
|
70
78
|
}
|
|
71
79
|
interface UndoSnap {
|
|
72
80
|
sheets: SheetState[];
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import type { CellData } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* 公式求值结果:
|
|
4
|
+
* - number:SUM / AVERAGE / COUNT 等数值类公式
|
|
5
|
+
* - string:IF / VLOOKUP 文本返回 / CONCATENATE 等文本类公式
|
|
6
|
+
* - null:求值时出现错误(循环引用、参数非法、未找到等),渲染为 #ERROR
|
|
7
|
+
*/
|
|
8
|
+
export type FormulaValue = string | number | null;
|
|
2
9
|
/** 解析区域引用(如 "A1:B5" → {sc, sr, ec, er}) */
|
|
3
10
|
export declare function parseRangeRef(rangeRef: string, colCount: number, rowCount: number): {
|
|
4
11
|
sc: number;
|
|
@@ -6,12 +13,14 @@ export declare function parseRangeRef(rangeRef: string, colCount: number, rowCou
|
|
|
6
13
|
ec: number;
|
|
7
14
|
er: number;
|
|
8
15
|
} | null;
|
|
9
|
-
/**
|
|
16
|
+
/** 获取单元格标量值(用于公式参数求值)。公式单元格会递归求值,空单元格返回 '' */
|
|
17
|
+
export declare function getCellScalar(col: number, row: number, cells: Record<string, CellData>, colCount: number, rowCount: number): FormulaValue;
|
|
18
|
+
/** 获取单元格数值(用于 SUM/AVERAGE/COUNT 等数值上下文),非数值按 0 处理 */
|
|
10
19
|
export declare function getNumericValue(col: number, row: number, cells: Record<string, CellData>, colCount: number, rowCount: number): number;
|
|
11
20
|
export declare function clearEvalCache(): void;
|
|
12
|
-
export declare function getEvalCache(): Map<string,
|
|
13
|
-
/**
|
|
14
|
-
export declare function evalFormula(key: string, cells: Record<string, CellData>, colCount: number, rowCount: number):
|
|
21
|
+
export declare function getEvalCache(): Map<string, FormulaValue>;
|
|
22
|
+
/** 对指定单元格公式求值,返回标量结果;普通值则解析为标量(数字或字符串) */
|
|
23
|
+
export declare function evalFormula(key: string, cells: Record<string, CellData>, colCount: number, rowCount: number): FormulaValue;
|
|
15
24
|
/** 解析公式中引用的单元格列表(用于依赖追踪) */
|
|
16
25
|
export declare function parseFormulaRefs(formula: string, colCount: number, rowCount: number): string[];
|
|
17
26
|
/** 计算单元格显示值(公式则求值,否则返回原值) */
|