odfdo - Python library for OpenDocument Format

raw JSON →
3.22.6 verified Mon Apr 27 auth: no python

A Python library to create, read, and manipulate OpenDocument Format (ODF) files (ODT, ODS, ODP). Version 3.22.6 supports Python >=3.10, <4. Active development, frequent releases.

pip install odfdo
error ModuleNotFoundError: No module named 'odfdo'
cause Library not installed or installed for wrong Python environment.
fix
Run pip install odfdo in the correct environment (e.g., virtualenv).
error ImportError: cannot import name 'Style' from 'odfdo'
cause In v3.x, Style was moved to `odfdo.style`.
fix
Use from odfdo.style import ParagraphStyle or from odfdo.style import Style.
error AttributeError: 'Document' object has no attribute 'save'
cause Misspelled method `save`; correct is `save` (lowercase).
fix
Use doc.save('filename.odt').
error ValueError: Unknown document type 'Text'
cause Document type must be lowercase: 'text', 'spreadsheet', or 'presentation'.
fix
Use Document('text') instead of Document('Text').
error TypeError: 'odfdo.element.Element' object is not callable
cause Trying to call an Element instance as a function, likely misusing `body()` instead of `body.append()`.
fix
Use body.append(...) not body(...).
breaking In version 3.x, many import paths changed from flat to nested (e.g., `from odfdo import Document` works, but `from odfdo.style import ParagraphStyle` is now required instead of `from odfdo import Style`).
fix Use nested imports: `from odfdo.element import Element`, `from odfdo.style import ParagraphStyle`, etc.
deprecated The `from odfdo import Element` top-level import is deprecated as of v3.6. Prefer `from odfdo.element import Element`.
fix Use `from odfdo.element import Element`.
gotcha When creating a document, specifying the type as a string (e.g., 'text', 'spreadsheet', 'presentation') is required; omitting it or using wrong case raises `ValueError`.
fix Use lowercase strings: 'text', 'spreadsheet', 'presentation'.
gotcha The `body` property returns a generic `Element`. To append content, use `body.append()` but ensure the appended element is a valid ODF element (e.g., Paragraph, Table).
fix Always import and instantiate specific elements like `from odfdo import Paragraph`.

Creates a simple ODT file with a paragraph.

from odfdo import Document, Paragraph
from odfdo.style import ParagraphStyle

# Create a new text document
doc = Document('text')
body = doc.body

# Add content
body.append(Paragraph('Hello, ODF!'))

# Save
doc.save('hello.odt')
print('Document created.')