关于 libreoffice-calc
libreoffice-calc 是通过 UNO 驱动 LibreOffice Calc 电子表格操作的技能,面向需要用 Python 处理表格的用户。它提供会话式编辑、结构化目标和可批量应用的操作补丁。
主要功能
- 01读取和写入单元格及区域
- 02格式化并设置数据验证
- 03创建、更新和删除图表
- 04管理工作表与命名区域
- 05通过补丁批量应用操作
- 06导出文件并生成区域快照
适用场景
- 01编辑并格式化现有电子表格
- 02为表格数据创建图表
- 03批量更新工作簿内容
- 04导出表格或检查布局快照
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dfk1352/ libreoffice-skills --skill libreoffice-calc安装后在 Claude Code 中输入/libreoffice-calc确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/troubleshooting.mdscripts/colors.pyconstants.pyexceptions.pypatch_base.pysession.pyuno_bridge.pyscripts/calc/__init__.pycore.pyexceptions.pypatch.pysession.pysnapshot.pytargets.py详细介绍
LibreOffice Calc
使用捆绑的 calc 模块处理由 UNO 支持的 Calc 电子表格。
所有路径都必须是绝对路径。捆绑模块位于此技能目录下的 scripts/ 中,因此请设置 PYTHONPATH=<skill_base_dir>/scripts。
如果出现设置或运行时问题,请查阅 references/troubleshooting.md。
API 接口
# Non-session utilities
create_spreadsheet(path, source=None) # source: path to .json or .xml file to import
export_spreadsheet(path, output_path, export_format) # formats: "pdf", "xlsx", "csv"
snapshot_area(doc_path, output_path, sheet="Sheet1", row=0, col=0, width=None, height=None, dpi=150)
# Session (primary editing API)
CalcSession(path) -> context manager
CalcSession methods:
read_cell(target: CalcTarget) -> dict[str, object]
write_cell(target: CalcTarget, value, value_type="auto")
read_range(target: CalcTarget) -> list[list[dict[str, object]]]
write_range(target: CalcTarget, data)
format_range(target: CalcTarget, formatting: CellFormatting)
list_sheets() -> list[dict[str, object]]
add_sheet(name, index=None)
rename_sheet(target: CalcTarget, new_name)
delete_sheet(target: CalcTarget)
define_named_range(name, target: CalcTarget)
get_named_range(target: CalcTarget) -> dict[str, object]
delete_named_range(target: CalcTarget)
set_validation(target: CalcTarget, rule: ValidationRule)
clear_validation(target: CalcTarget)
create_chart(target: CalcTarget, spec: ChartSpec)
update_chart(target: CalcTarget, spec: ChartSpec)
delete_chart(target: CalcTarget)
recalculate()
patch(patch_text, mode="atomic") -> PatchApplyResult
export(output_path, export_format)
reset()
close(save=True)
# Standalone patch utility
patch(path, patch_text, mode="atomic") -> PatchApplyResult
结构化目标:CalcTarget
from calc import CalcTarget
CalcTarget(
kind="cell" | "range" | "sheet" | "named_range" | "chart",
sheet=None,
sheet_index=None,
row=None,
col=None,
end_row=None,
end_col=None,
name=None,
index=None,
)
目标类型
| 类型 | 支持的字段 | 用途 |
|---|---|---|
cell | sheet 或 sheet_index、row、col | 读取或写入一个单元格 |
range | sheet 或 sheet_index、row、col、end_row、end_col | 读取、写入、设置格式、验证或为矩形区域创建图表 |
sheet | sheet 或 sheet_index | 重命名或删除一个工作表 |
named_range | name | 检查或删除一个命名区域 |
chart | sheet 或 sheet_index,以及 name 或 index | 更新或删除一个图表 |
解析规则
- 坐标从 0 开始,且必须为非负数。
sheet和sheet_index不能同时使用。name和index不能同时使用。- 区域目标必须满足
end_row >= row且end_col >= col。 - 图表目标必须指定一个工作表和一个图表选择器。
- Calc 不会自动将单单元格区域转换为单元格目标;请明确保留这两种类型。
单元格读取结果
read_cell() 和 read_range() 返回形状相同的单元格字典:
{
"value": 100.0,
"formula": None,
"error": None,
"type": "number",
"raw": 100.0,
}
空单元格返回 type="empty",且 value=None:
{"value": None, "formula": None, "error": None, "type": "empty", "raw": None}
公式单元格使用 type="formula";当 Calc 报告公式错误时,会填充 error,并将 value 设为 None。
布尔值(True/False)以数值 1.0/0.0 存储。读取用 Python 布尔值写入的单元格时,返回的是 type="number",且 value=1.0 或 value=0.0,而不是文本字符串。
格式设置载荷:CellFormatting
from calc import CellFormatting
CellFormatting(
bold=None,
italic=None,
font_name=None,
font_size=None,
color=None, # named color or integer
number_format=None, # "currency" | "percentage" | "date" | "time"
)
说明:
- 必须至少设置一个格式字段。
color接受命名颜色或0xRRGGBB整数。format_range()既适用于cell目标,也适用于矩形range目标。
验证载荷:ValidationRule
from calc import ValidationRule
ValidationRule(
type="whole",
condition="between",
value1=1,
value2=10,
show_error=True,
error_message="Enter a value from 1 to 10.",
show_input=True,
input_title="Allowed values",
input_message="Only integers from 1 to 10 are valid.",
ignore_blank=True,
error_style=0,
)
支持的 type 值:
anywholedecimaldatetimetext_lengthlist
支持的 condition 值:
betweennot_betweenequalnot_equalgreater_thanless_thangreater_or_equalless_or_equal
图表载荷:ChartSpec
from calc import CalcTarget, ChartSpec
ChartSpec(
chart_type="line",
data_range=CalcTarget(
kind="range",
sheet="Data",
row=0,
col=0,
end_row=5,
end_col=1,
),
anchor_row=7,
anchor_col=0,
width=10000,
height=7000,
title="Revenue Trend",
)
说明:
chart_type必须为bar、line、pie或scatter之一。width和height使用 Calc 图表矩形单位(与打包 API 已接受的单位相同)。- 创建图表时以工作表为目标;更新或删除图表时以图表为目标。
补丁 DSL
使用 patch() 或 session.patch() 按顺序应用电子表格操作。
[operation]
type = write_range
target.kind = range
target.sheet = Revenue Data
target.row = 0
target.col = 0
target.end_row = 2
target.end_col = 1
data <<JSON
[["Label", "Value"], ["Revenue", 100], ["Cost", 80]]
JSON
[operation]
type = format_range
target.kind = range
target.sheet = Revenue Data
target.row = 1
target.col = 1
target.end_row = 2
target.end_col = 1
format.number_format = currency
format.bold = true
[operation]
type = create_chart
target.kind = sheet
target.sheet = Revenue Data
chart.chart_type = line
chart.data_range.kind = range
chart.data_range.sheet = Revenue Data
chart.data_range.row = 0
chart.data_range.col = 0
chart.data_range.end_row = 2
chart.data_range.end_col = 1
chart.anchor_row = 5
chart.anchor_col = 0
chart.width = 9000
chart.height = 6000
chart.title = Revenue Trend
支持的操作类型
write_cellwrite_rangeformat_rangeadd_sheetrename_sheetdelete_sheetdefine_named_rangedelete_named_rangeset_validationclear_validationcreate_chartupdate_chartdelete_chartrecalculate
补丁值规则
- 主目标使用
target.*字段。 CellFormatting使用format.*字段。ValidationRule使用rule.*字段。ChartSpec使用chart.*字段;图表源区域使用chart.data_range.*。data必须是有效的 JSON。- 支持使用
<<TAG ... TAGheredoc 块来提供多行 JSON 或文本。
模式
atomic遇到首个失败时停止、重置会话,且不持久化任何内容。best_effort保留此前成功的操作,并记录失败。
PatchApplyResult 字段:
modeoverall_status="ok" | "partial" | "failed"operations=PatchOperationResult列表document_persisted
对于独立的 patch(path, ...),document_persisted 表示更改已保存到磁盘。对于 session.patch(...),它表示补丁在当前打开的会话状态中成功产生了变更。
示例:在会话中构建电子表格
from pathlib import Path
from calc import (
CalcSession,
CalcTarget,
CellFormatting,
ChartSpec,
ValidationRule,
)
from calc.core import create_spreadsheet
output = str(Path("test-output/revenue-report.ods").resolve())
create_spreadsheet(output)
with CalcSession(output) as session:
session.rename_sheet(CalcTarget(kind="sheet", sheet="Sheet1"), "Revenue Data")
session.add_sheet("Summary")
session.write_range(
CalcTarget(kind="range", sheet="Revenue Data", row=0, col=0, end_row=2, end_col=1),
[["Label", "Value"], ["Revenue", 100], ["Cost", 80]],
)
session.format_range(
CalcTarget(kind="range", sheet="Revenue Data", row=1, col=1, end_row=2, end_col=1),
CellFormatting(number_format="currency", bold=True),
)
session.define_named_range(
"RevenueValues",
CalcTarget(kind="range", sheet="Revenue Data", row=1, col=1, end_row=2, end_col=1),
)
session.set_validation(
CalcTarget(kind="range", sheet="Revenue Data", row=1, col=1, end_row=2, end_col=1),
ValidationRule(type="whole", condition="greater_than", value1=0),
)
session.create_chart(
CalcTarget(kind="sheet", sheet="Revenue Data"),
ChartSpec(
chart_type="line",
data_range=CalcTarget(
kind="range",
sheet="Revenue Data",
row=0,
col=0,
end_row=2,
end_col=1,
),
anchor_row=5,
anchor_col=0,
width=9000,
height=6000,
title="Revenue Trend",
),
)
session.recalculate()
示例:修补现有电子表格
from calc import patch
result = patch(
"/abs/path/revenue-report.ods",
"""
[operation]
type = write_cell
target.kind = cell
target.sheet = Summary
target.row = 1
target.col = 1
value = Ready
value_type = text
[operation]
type = format_range
target.kind = cell
target.sheet = Summary
target.row = 1
target.col = 1
format.bold = true
[operation]
type = recalculate
""",
mode="best_effort",
)
print(result.overall_status)
快照
from pathlib import Path
from calc import snapshot_area
result = snapshot_area(doc_path, "/tmp/revenue.png", sheet="Revenue Data", row=0, col=0, dpi=150)
print(result.file_path, result.width, result.height)
Path(result.file_path).unlink(missing_ok=True) # clean up used snapshots
交付前,使用快照验证图表位置、格式和工作表布局。
snapshot_area()输出的尺寸可能与请求尺寸略有差异;少量像素差异属于正常情况。
常见错误
- 传入相对路径;面向 UNO 的 Calc API 要求使用绝对文件路径。
- 混淆
cell和range目标;即使是单单元格选区,Calc 也会将两者区分开。 - 使用从 1 开始的坐标;行和列的索引都从 0 开始。
- 以为
create_chart()会随机选择另一个目标名称;设置title后,后续使用相同名称定位图表是最稳妥的做法。 - 打包的 API 未提供图表列表或验证检查辅助工具;在高级工作流中,深入验证可能需要直接检查 UNO。
- 修改图表操作时,忘记设置
chart.data_range.*字段。 - 期望
snapshot_area()导出的 PNG 尺寸与请求完全一致;Calc 导出结果可能会有少量差异。 - 检查完成后忘记清理捕获的快照。
- 在调用
session.close()后继续调用会话方法。 - 导入 JSON / XML 需要 LibreOffice 26.2+。