> ## Documentation Index
> Fetch the complete documentation index at: https://docs.profy.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# Excel 表格

> profy-xlsx — 创建、编辑、分析 .xlsx：公式而非硬编码值、零公式错误、财务模型配色规范

# Excel 表格（profy-xlsx）

创建、编辑、分析电子表格。与「让模型算好数再填进去」的做法相反，这个能力的核心约束是**产出必须是活的表格**：公式留在单元格里，源数据一改结果就跟着变。

## 激活方式

`profy-xlsx` 是 `user_selectable: false`——**自动可用，不需要勾选**。插件面板里看不到它，因为它没有需要你决策的东西。

```json theme={null}
{ "id": "profy-xlsx", "activation": { "user_selectable": false } }
```

它的 `contracts` 只声明 `skills: ["skills/"]`，**没有 tools**。这意味着专家不是调用某个"生成 Excel 的工具"，而是在沙箱里用 `bash` 跑 Python（openpyxl / pandas），技能文档规定它该怎么跑。

触发条件是**表格文件是主要输入或输出**：`.xlsx` / `.xlsm` / `.csv` / `.tsv`。如果最终交付物是 Word、HTML 报告或独立脚本，就算中间处理了表格数据也不走这条路径。

## 快速开始

```
把这份销售数据按月汇总，加一列同比增长率，生成趋势图
```

```
这个 Excel 里的公式报了一堆 #REF!，帮我修
```

```
建一个三年期财务模型，假设放在单独的假设区
```

## 第一原则：用公式，不要硬编码

这是整份技能里被反复强调的一条，值得单独说清楚为什么。

<CodeGroup>
  ```python 错误做法 theme={null}
  # 在 Python 里算完，把结果写死
  total = sum(revenues)
  sheet['D20'] = total              # 死数字

  growth = (rev_2025 - rev_2024) / rev_2024
  sheet['E5'] = growth              # 死数字
  ```

  ```python 正确做法 theme={null}
  # 让 Excel 自己算
  sheet['D20'] = '=SUM(D2:D19)'
  sheet['E5']  = '=(D5-C5)/C5'
  sheet['D21'] = '=AVERAGE(D2:D19)'
  ```
</CodeGroup>

差别不在于哪种写起来快，而在于**交付物的性质**。硬编码出来的是一张数字快照——你改一个输入，其余全是错的，而且没有任何提示。留公式出来的是一个模型——它能被使用、被审计、被复用。

这条规则适用于**所有**计算：合计、百分比、比率、差额，无一例外。

## 必做步骤：重算与校验

写完公式的文件里，单元格存的是公式**文本**，缓存值是空的。直接交付会让对方打开时看到一片空白或旧值。所以有一步强制动作：

```bash theme={null}
python scripts/recalc.py output.xlsx
```

脚本靠 LibreOffice 重算（sandbox 里 Unix socket 受限的情况由 `scripts/office/soffice.py` 自动处理），返回 JSON：

| 返回                     | 含义    | 下一步                         |
| ---------------------- | ----- | --------------------------- |
| `status` 正常            | 无公式错误 | 可以交付                        |
| `status: errors_found` | 有公式错误 | 读 `error_summary` 定位后修复，再重算 |

### 必须清零的五类错误

| 错误        | 含义     | 常见原因                |
| --------- | ------ | ------------------- |
| `#REF!`   | 引用无效   | 删行删列后引用悬空           |
| `#DIV/0!` | 除以零    | 分母单元格为空或为 0         |
| `#VALUE!` | 类型不对   | 文本参与了数值运算           |
| `#NAME?`  | 函数名不认识 | 拼写错误，或用了当前版本没有的函数   |
| `#N/A`    | 查找不到   | VLOOKUP / MATCH 未命中 |

**交付标准是零公式错误**，不是"大部分能算"。

## 财务模型规范

做财务模型时，技能会套用行业通行的约定，让任何看过财务模型的人拿到就能读。

### 颜色编码

| 颜色  | RGB       | 含义                |
| --- | --------- | ----------------- |
| 蓝色字 | 0,0,255   | 硬编码输入值，用户会改来做情景分析 |
| 黑色字 | 0,0,0     | 所有公式与计算           |
| 绿色字 | 0,128,0   | 引用同一工作簿其他工作表      |
| 红色字 | 255,0,0   | 引用外部文件            |
| 黄色底 | 255,255,0 | 关键假设，需要注意或待更新     |

这套配色的作用是**一眼分辨哪些数能改、哪些数是算出来的**。改了黑色字的单元格就破坏了模型，颜色是最省事的护栏。

### 数字格式

| 类型  | 格式                  | 说明                        |
| --- | ------------------- | ------------------------- |
| 年份  | 文本字符串               | `"2024"` 而非 `2,024`       |
| 货币  | `$#,##0`            | 表头必须标单位，如 `Revenue ($mm)` |
| 零值  | `$#,##0;($#,##0);-` | 零显示为 `-`，百分比同理            |
| 百分比 | `0.0%`              | 默认一位小数                    |
| 倍数  | `0.0x`              | 估值倍数如 EV/EBITDA、P/E       |
| 负数  | `(123)`             | 用括号，不用负号                  |

### 公式构造

* **假设集中放**：增长率、利润率、倍数等全部放独立假设单元格
* **引用而非写死**：用 `=B5*(1+$B$6)`，不要用 `=B5*1.05`
* **投影期公式一致**：每一期的公式结构必须相同，否则中间某年会悄悄算错
* **硬编码必须注明出处**：格式为 `Source: [系统/文档], [日期], [具体位置], [URL]`，例如 `Source: Company 10-K, FY2024, Page 45, Revenue Note`

最后一条容易被忽略，但它决定了这份模型半年后还能不能被信任——一个没有出处的硬编码数字，等于一个无法验证的断言。

## 改已有文件时：模板优先

<Warning>
  **已有模板的约定永远覆盖上面所有规范。** 修改别人的文件时，先研究它现有的格式、样式与惯例并**精确匹配**，不要把标准化格式强加上去。
</Warning>

理由很直接：你不知道那套格式背后有什么下游依赖。一份被下游脚本按列位置解析的表，你"顺手规范化"一下列顺序，下游就全断了。

## 工具选型

| 场景         | 用什么      |
| ---------- | -------- |
| 数据分析、清洗、转换 | pandas   |
| 公式、格式、图表   | openpyxl |

标准流程是：选工具 → 创建/加载 → 修改 → 保存 → **重算** → 校验并修错。

## 边界与失败态

* **重算依赖 LibreOffice**。沙箱里已预装；本地 Desktop 环境若没有，`recalc.py` 会失败，此时公式不会有缓存值。
* **`.xlsm` 的宏不会被执行**。可以读写文件结构，但宏逻辑不参与计算。
* **图表由 openpyxl 生成，样式能力有限**。复杂的可视化需求更适合交给可视化能力做成网页图表。
* **超大表有内存上限**。几十万行以上建议先用 pandas 聚合，再把结果写成 xlsx，而不是把原始数据整个装进 openpyxl。

### 排错

| 症状                          | 原因               | 处理                              |
| --------------------------- | ---------------- | ------------------------------- |
| 打开文件所有公式单元格是空白              | 写完没跑 `recalc.py` | 跑重算脚本                           |
| `status: errors_found` 反复出现 | 修了表面错误但引用结构仍有问题  | 按 `error_summary` 的定位逐个查，别只看第一个 |
| 数字显示成 `2,024`               | 年份被当成数值          | 年份按文本格式写                        |
| 改了源数据结果不变                   | 结果是硬编码的          | 把死数字换成公式后重算                     |
| 模板文件改完样式全乱                  | 强加了标准格式          | 回滚，改为精确匹配原有约定                   |

## 验证你的产出

1. 打开文件，随便改一个输入单元格——**下游数字应该跟着变**。不变就说明有硬编码。
2. 全表搜索 `#`，五类公式错误应该一个都搜不到。
3. 财务模型再看一眼颜色：蓝色应该只出现在输入区，黑色应该覆盖所有计算区。

## 相关页面

<CardGroup cols={2}>
  <Card title="办公文档总览" href="/zh/documentation/capabilities/office-documents">
    四类文档能力的定位与选型
  </Card>

  <Card title="数据可视化" href="/zh/documentation/plugins/3d-development">
    需要交互式图表时的另一条路径
  </Card>
</CardGroup>

<Note>
  核对日期 2026-08-11。来源：`services/agent-runtime/src/plugins/builtin/xlsx/plugin.json`、`skills/SKILL.md`、`skills/scripts/recalc.py`、`skills/scripts/office/soffice.py`。
</Note>
