xlsx 用于处理 .xlsx 工作簿。该格式是 OOXML SpreadsheetML——一个由 XML 部件组成的 zip 容器。应将每个单元格视为带类型的值:数字、字符串、日期时间或公式。混用这四种类型会导致 Excel 标记工作簿或计算出错误的总计。
先决定路径
根据你拥有的内容与目标选择路径:
- 已有 .xlsx,目标是读取工作表和单元格:路径 A,检查。
- 已有 .xlsx,目标是修改特定单元格:路径 B,原地编辑。
- 没有文件或只有简要说明,目标是构建新工作簿:路径 C,从零创建。
如果用户提供了要更新的工作簿,默认走路径 B,并将输入作为格式基线。仅当用户说“从零开始”时才选择路径 C。
执行与交付
在可用时,使用 execute_code 搭配下方的 Python 示例。将所有输入和输出文件保留在活动工作区中,然后调用 publish_artifact(path="out.xlsx") 交付完成的工作簿。在受限通道中,直接使用 openpyxl;下方的 shell 命令是可选快捷方式,适用于暴露 exec_command 的会话。不要使用 Python subprocess 绕过不可用的 shell 工具,也不要在沙箱失败时请求宿主执行。如果执行或所需库不可用,请报告该限制并保持会话为只读。
路径 A:检查
使用 execute_code:
from openpyxl import load_workbook wb = load_workbook("book.xlsx", data_only=False) for ws in wb.worksheets: print(ws.title, list(ws.values)) wb.close()
或运行:
python {baseDir}/scripts/inspect_xlsx.py /path/to/book.xlsx
输出示例:
{ "sheets": [ { "name": "Q3", "max_row": 10, "max_col": 5, "rows": [ [ {"value": "Metric", "type": "s"}, {"value": "Value", "type": "s"} ], [ {"value": "Revenue", "type": "s"}, {"value": 2100000, "type": "n"} ] ] } ] }
type 遵循 openpyxl 约定:n(数字)、s(字符串)、d(日期时间)、f(公式)、b(布尔)、e(错误)、inlineStr(内联字符串)。辅助脚本以 data_only=False 读取,因此公式表达式会按字面返回;传入 --data-only 则改为获取缓存的计算结果。
路径 B:原地编辑
使用 execute_code:
from openpyxl import load_workbook wb = load_workbook("book.xlsx") wb["Q3"]["B2"] = "=SUM(B3:B10)" wb.save("edited.xlsx") wb.close()
或运行:
python {baseDir}/scripts/edit_xlsx.py book.xlsx ops.json --out edited.xlsx
ops.json:
[ {"op": "set_cell", "sheet": "Q3", "row": 2, "col": 2, "value": "=SUM(B3:B10)"}, {"op": "set_cell", "sheet": "Q3", "row": 5, "col": 1, "value": "Net margin"}, {"op": "rename_sheet", "old": "Sheet1", "new": "Summary"} ]
规则:
- 行和列从 1 开始(Excel 约定)。
- 以 = 开头的字符串会写为公式(cell.value = "=..."),与 openpyxl 行为一致。要写入字面量 =hello,请使用 '=hello(Excel 的前导撇号转义)或传入显式的 as_text: true。
- 日期时间以 ISO 8601 字符串形式传入("2026-05-06T09:00:00");辅助脚本会将其解析回 datetime 对象,使 Excel 以日期格式呈现该单元格。
- 编辑单元格不会重新计算依赖的公式。Excel 和 LibreOffice 会在打开时重新计算。如需立即获得缓存值,请使用计算引擎(超出本文范围)。
路径 C:从零创建
运行:
python {baseDir}/scripts/create_xlsx.py spec.json --out out.xlsx
规格:
{ "sheets": [ { "name": "Sales", "rows": [ ["Region", "Revenue", "Growth"], ["NA", 1200000, "=B2/SUM($B$2:$B$4)"], ["EU", 850000, "=B3/SUM($B$2:$B$4)"] ], "merged": [{"range": "A1:C1"}], "freeze": "A2" } ] }
用于编程:
from openpyxl import Workbook wb = Workbook() ws = wb.active ws.title = "Sales" ws.append(["Region", "Revenue"]) ws.append(["NA", 1_200_000]) ws["C2"] = "=B2*1.05" # formula ws.merge_cells("A1:B1") ws.freeze_panes = "A2" wb.save("out.xlsx")
关于样式、条件格式、图表和公式引用,请参见 references/openpyxl.md。
常见陷阱
- 症状:单元格显示 =SUM(...) 为文本而非结果。原因:以 as_text: true 写入了字符串,或工作簿缺少缓存值。修复:在 Excel 中打开并保存一次;或使用计算引擎。
- 症状:日期显示为序列号(45000)。原因:写入了 int 而非 datetime。修复:传入 ISO 字符串让辅助脚本解析;或设置 cell.number_format。
- 症状:合并区域丢失边框。原因:合并后边框仅应用于左上角单元格。修复:合并后对左上角单元格应用边框。
- 症状:编辑后工作簿破坏 Excel。原因:删除了定义的名称但未更新依赖公式。修复:删除前审计 defined_names。
- 症状:透视表消失。原因:openpyxl 在保存时丢弃透视缓存。修复:在 Excel 中编辑透视表;不支持程序化编辑。
边界
- 此技能处理 .xlsx(OOXML SpreadsheetML)。它不处理 .xls(旧版二进制)、.xlsm(启用宏)或 Google Sheets。请先通过 Excel 或 LibreOffice 导出转换。
- 此处的透视表、切片器和透视缓存为只读。
- 对于大于约 10 万行或 50MB 的数据集,建议使用 pandas + to_excel 搭配 xlsxwriter 引擎;openpyxl 会将整个工作簿加载到内存中。