$npx -y skills add XiaoMaColtAI/math-modeling-skill --skill xlsx读取、创建、修改和验证 XLSX,支持模板保留、公式重算和错误检查。
| 1 | # Excel 工具 |
| 2 | |
| 3 | ## 原则 |
| 4 | |
| 5 | - 输入表格只读,输出写入 `PROJECT_ROOT`。 |
| 6 | - 普通结果汇总优先 CSV。 |
| 7 | - 题目指定 XLSX、需保留公式、多工作表或模板结构时才使用 XLSX。 |
| 8 | - 不覆盖题目原始附件和 Skill 文件。 |
| 9 | |
| 10 | ## 读取与写入 |
| 11 | |
| 12 | ```python |
| 13 | import pandas as pd |
| 14 | |
| 15 | # 第一行就是数据时必须显式使用 header=None。 |
| 16 | data = pd.read_excel("data/input.xlsx", sheet_name=0, header=None) |
| 17 | assert len(data) == 7470, f"行数异常: {len(data)}" |
| 18 | result = pd.DataFrame({"方案": names, "目标值": values}) |
| 19 | result.to_excel("results/结果.xlsx", index=False) |
| 20 | ``` |
| 21 | |
| 22 | 禁止依赖 `pandas.read_excel()` 默认的 `header=0` 猜测表头,否则第一行数据会被当成列名。未知表头结构或必须精确保留行时使用无隐式推断的读取工具: |
| 23 | |
| 24 | ```python |
| 25 | from scripts.read_rows import read_excel_rows |
| 26 | |
| 27 | rows = read_excel_rows( |
| 28 | "data/input.xlsx", |
| 29 | header=False, |
| 30 | expected_rows=7470, |
| 31 | ) |
| 32 | assert rows[0][0] == 399.6747 |
| 33 | ``` |
| 34 | |
| 35 | 读取后必须核对首行、末行、原始工作表有效行数和题目声明的记录数;行数不符时立即报错,不得静默继续建模。 |
| 36 | |
| 37 | 使用模板时用 `openpyxl.load_workbook()` 打开,写入指定单元格后另存新文件。不要删除未知工作表、命名区域、公式或验证规则。 |
| 38 | |
| 39 | ## 公式重算 |
| 40 | |
| 41 | `openpyxl` 不计算公式。修改含公式的工作簿后使用 LibreOffice 隔离重算: |
| 42 | |
| 43 | ```powershell |
| 44 | python scripts/recalc.py "<PROJECT_ROOT>/results/结果.xlsx" 60 |
| 45 | ``` |
| 46 | |
| 47 | 工具会: |
| 48 | |
| 49 | 1. 使用唯一临时 LibreOffice 配置; |
| 50 | 2. 把重算结果写入临时目录; |
| 51 | 3. 检查常见 Excel 错误; |
| 52 | 4. 仅在成功后原子替换目标文件; |
| 53 | 5. 超时、失败或未生成输出时保留原文件。 |
| 54 | |
| 55 | DOCX 与 XLSX 共用的 OOXML/LibreOffice 基础代码位于 `../docx/scripts/office/`,本工具不再维护重复副本。 |
| 56 | |
| 57 | ## 检查 |
| 58 | |
| 59 | - 公式引用和范围正确。 |
| 60 | - 工作表名、列名、数据类型和单位正确。 |
| 61 | - 已显式声明是否有表头,首行、末行和预期数据行数均已核对。 |
| 62 | - 无 `#VALUE!`、`#DIV/0!`、`#REF!`、`#NAME?`、`#NULL!`、`#NUM!`、`#N/A`。 |
| 63 | - 结果与代码终端输出和论文表格一致。 |