libreoffice-writer について
libreoffice-writerは、UNO経由でLibreOffice Writer文書を操作するモジュール群です。文書を扱うエージェント向けに、構造化編集、書式設定、パッチ操作、メタデータ変更、エクスポート、レイアウト確認用のページ撮影を提供します。
主な機能
- 01Writer文書の作成と編集
- 02テキスト、表、画像、リストの指定
- 03順序付きパッチ操作の適用
- 04文書メタデータと書式の設定
- 05文書のエクスポートとページ撮影
活用シーン
- 01既存レポートの構造化編集
- 02文書変更の一括適用
- 03書式設定や編集後のページレイアウト確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ dfk1352/ libreoffice-skills --skill libreoffice-writerインストール後、Claude Code で/libreoffice-writerを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/troubleshooting.mdscripts/colors.pyconstants.pyexceptions.pypatch_base.pysession.pyuno_bridge.pyscripts/writer/__init__.pycore.pyexceptions.pypatch.pysession.pysnapshot.pytargets.py詳細
LibreOffice Writer
UNO 対応の Writer ドキュメントを操作するには、同梱の writer モジュールを使用します。
すべてのパスは絶対パスである必要があります。同梱モジュールは、この
スキルディレクトリ内の scripts/ にあります。そのため、PYTHONPATH=<skill_base_dir>/scripts を設定してください。
セットアップまたは実行時に問題が発生した場合は、references/troubleshooting.md を確認してください。
API サーフェス
# Non-session utilities
create_document(path, source=None) # source: path to .md file to import
export_document(path, output_path, export_format) # formats: "pdf", "docx", "md"
snapshot_page(doc_path, output_path, page=1, dpi=150)
# Session (primary editing API)
WriterSession(path) -> context manager
WriterSession methods:
read_text(target: WriterTarget | None = None) -> str
insert_text(text, target: WriterTarget | None = None)
replace_text(target: WriterTarget, new_text)
delete_text(target: WriterTarget)
format_text(target: WriterTarget, formatting: TextFormatting)
insert_table(rows, cols, data=None, name=None, target: WriterTarget | None = None)
update_table(target: WriterTarget, data)
delete_table(target: WriterTarget)
insert_image(image_path, width=None, height=None, name=None, target: WriterTarget | None = None)
update_image(target: WriterTarget, image_path=None, width=None, height=None)
delete_image(target: WriterTarget)
insert_list(items: list[ListItem], ordered: bool, target: WriterTarget | None = None)
replace_list(target: WriterTarget, items: list[ListItem], ordered: bool | None = None)
delete_list(target: WriterTarget)
set_metadata(values: dict[str, str])
get_metadata() -> dict[str, str]
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
構造化ターゲット:WriterTarget
from writer import WriterTarget
WriterTarget(
kind="text" | "insertion" | "table" | "image" | "list",
text=None,
after=None,
before=None,
occurrence=None,
name=None,
index=None,
)
ターゲットの種類
| 種類 | サポートされるフィールド | 用途 |
|---|---|---|
text | text、after、before、occurrence | 一致したテキストの読み取り、置換、削除、書式設定 |
insertion | text、after、before、occurrence | 解決された境界、または一致した範囲の後に挿入 |
table | name または index | 表の更新/削除 |
image | name または index | 画像の更新/削除 |
list | text、after、before、occurrence | 論理的なリストブロックの置換/削除 |
解決ルール
targetを省略すると、ドキュメント全体を読み取るか、挿入したコンテンツを末尾に追加します。afterとbeforeを使って、検索範囲を絞り込みます。- 同じテキストが複数回出現する場合は
occurrenceを指定します。それ以外の場合、一致する箇所は一意である必要があります。 text、after、beforeのアンカーには、文章全体や段落単位の特徴的なフレーズを使用してください。単語だけのアンカーは、実際の文章を編集する際に不安定になりやすいためです。- 表/画像のターゲットでは
nameを優先し、順序が変わらない場合に限りindexを使用してください。 - インラインテキストの後に挿入すると、Writer は一致した範囲の直後の境界に挿入します。段落区切りは、挿入するテキストまたはセッションヘルパーで指定する必要があります。
書式設定ペイロード
from writer import TextFormatting
TextFormatting(
bold=None,
italic=None,
underline=None,
font_name=None,
font_size=None,
color=None, # named color or integer
align=None, # "left" | "center" | "right" | "justify" | "start" | "end"
line_spacing=None,
spacing_before=None,
spacing_after=None,
)
注:
- 文字書式と段落書式は、1 回の呼び出しで組み合わせられます。
alignなどの段落プロパティは、一致した範囲だけでなく、その範囲を含む段落全体に適用されます。- 書式フィールドを少なくとも 1 つ設定する必要があります。
リスト項目
from writer import ListItem
ListItem(text="Confirm scope", level=0)
levelは、0 から始まるネストレベルです。- レベルを飛ばしたネストはできません。
ordered=Trueは番号付きスタイルを、ordered=Falseは箇条書きを使用します。
メタデータ
set_metadata()は、キーと値のペアを格納した辞書を受け取ります。- サポートされているキーは
title、author、subject、keywords、descriptionです。 keywordsはカンマ区切りの文字列を指定できます。get_metadata()はキーワードを 1 つのカンマ区切り文字列として返します。
パッチ DSL
順序付きの操作を適用するには、patch() または session.patch() を使用します。
[operation]
type = format_text
target.kind = text
target.text = Quarterly revenue grew 18%.
target.after = Financial Summary
target.before = Action Items
format.bold = true
format.align = center
[operation]
type = insert_list
target.kind = insertion
target.after = Action Items
list.ordered = false
items <<JSON
[
{"text": "Confirm scope", "level": 0},
{"text": "Review output", "level": 0},
{"text": "Update packaging", "level": 1}
]
JSON
サポートされている操作の種類
insert_textreplace_textdelete_textformat_textinsert_tableupdate_tabledelete_tableinsert_imageupdate_imagedelete_imageinsert_listreplace_listdelete_list
パッチ値のルール
- ターゲットの定義には
target.*フィールドを使用します。 - ドキュメントの末尾に追加するには、すべての
target.*フィールドを省略します。アンカーなしでtarget.kind = insertionだけを指定しないでください。 - 書式設定ペイロードには
format.*フィールドを使用します。 - リスト操作には
list.orderedと JSON のitemsを使用します。 itemsとdataは有効な JSON である必要があります。- 複数行のテキストまたは JSON には、
<<TAG ... TAGの形式でヒアドキュメントブロックを使用できます。
モード
atomicは最初の失敗時に停止し、セッションをリセットして、何も保存しません。best_effortは、先行する操作のうち成功したものを保持し、失敗を記録します。
PatchApplyResult のフィールド:
modeoverall_status="ok" | "partial" | "failed"operations=PatchOperationResultのリストdocument_persisted
単独の patch(path, ...) では、document_persisted は変更がディスクに保存されたことを示します。session.patch(...) では、現在開いているセッションの状態でパッチによる変更が成功したことを示します。
例:セッション内でレポートを編集する
from pathlib import Path
from writer import ListItem, TextFormatting, WriterSession, WriterTarget
from writer.core import create_document
output = str(Path("test-output/report.odt").resolve())
create_document(output)
with WriterSession(output) as session:
session.insert_text(
"Executive Summary\n\n"
"Financial Summary\n\n"
"Quarterly revenue grew 18%.\n\n"
"Action Items"
)
session.format_text(
WriterTarget(
kind="text",
text="Quarterly revenue grew 18%.",
after="Financial Summary",
before="Action Items",
),
TextFormatting(bold=True, align="center"),
)
session.insert_list(
[
ListItem(text="Confirm scope", level=0),
ListItem(text="Review output", level=0),
ListItem(text="Update packaging", level=1),
],
ordered=False,
target=WriterTarget(kind="insertion", after="Action Items"),
)
例:既存のドキュメントにパッチを適用する
from writer import patch
result = patch(
"/abs/path/report.odt",
"""
[operation]
type = replace_text
target.kind = text
target.text = Draft
new_text = Final
[operation]
type = update_table
target.kind = table
target.name = Summary
data = [["Metric", "Value"], ["Revenue", "$2M"]]
[operation]
type = replace_list
target.kind = list
target.text = Confirm scope
items = [{"text": "Approve release", "level": 0}, {"text": "Notify team", "level": 1}]
list.ordered = true
""",
mode="best_effort",
)
print(result.overall_status)
スナップショット
from pathlib import Path
from writer import snapshot_page
result = snapshot_page(doc_path, "/tmp/page1.png", page=1, dpi=150)
print(result.file_path, result.width, result.height)
Path(result.file_path).unlink(missing_ok=True) # clean up used snapshots
フォーマット後、リストの編集後、画像の配置後、または表の変更後に、スナップショットを使ってレイアウトを確認します。
- ドキュメントがすでに
WriterSessionで開かれている場合は、session.export()を優先して使用します。 - セッションを開いたままにせず既存のファイルをエクスポートする場合は、スタンドアロンの
export_document()を使用します。 get_metadata()はkeywordsをカンマとスペースで区切った1つの文字列に正規化します。
よくある間違い
- 相対パスを渡すこと。UNOに対応するWriter APIでは、絶対ファイルパスが必要です。
- 繰り返し出現するテキストに
occurrenceを指定せず、曖昧さのエラーが発生すること。 - アンカーが短すぎたり、一般的すぎたりすること。可能な場合は、文全体または段落単位のアンカーテキストに加えて、
after/beforeの境界を指定してください。 alignがフレーズだけに適用されると考えること。Writerでは、段落の配置はそのフレーズを含む段落全体に適用されます。itemsまたはdataのパッチフィールドに不正なJSONを指定すること。- 確認後に、取得したスナップショットを削除し忘れること。
session.close()の後に、session.export()やその他のメソッドを呼び出すこと。- Markdownのインポート/エクスポート用フィルターを使用するには、LibreOffice 26.2以降が必要です。
- 段落配置の
"start"および"end"オプションを使用するには、LibreOffice 26.2以降が必要です。
コメント
Markdown 対応