A wrapper library to read, manipulate and write data in ods format
npx @tessl/cli install tessl/pypi-pyexcel-ods@0.6.0A Python wrapper library for reading, manipulating, and writing data in OpenDocument Spreadsheet (ODS) format. Built on top of the odfpy library, pyexcel-ods provides simple, intuitive functions for working with ODS files without complex formatting concerns. Integrates seamlessly with the broader pyexcel ecosystem for comprehensive data processing workflows.
pip install pyexcel-odsfrom pyexcel_ods import get_data, save_dataAlternative import for backward compatibility:
from pyexcel_ods import read_data, write_dataCheck if object is a stream:
from pyexcel_ods import isstreamfrom pyexcel_ods import get_data, save_data
from collections import OrderedDict
# Reading an ODS file
data = get_data("input.ods")
print(data) # {'Sheet1': [[1, 2, 3], [4, 5, 6]], 'Sheet2': [['a', 'b', 'c']]}
# Writing to an ODS file
output_data = OrderedDict()
output_data.update({"Sheet 1": [[1, 2, 3], [4, 5, 6]]})
output_data.update({"Sheet 2": [["row 1", "row 2", "row 3"]]})
save_data("output.ods", output_data)
# Working with memory streams
from io import BytesIO
# Write to memory
io_stream = BytesIO()
save_data(io_stream, output_data)
# Read from memory
io_stream.seek(0) # Reset stream position
data_from_memory = get_data(io_stream)Read data from ODS files into Python data structures.
def get_data(afile, file_type=None, **keywords):
"""
Standalone module function for reading module supported file type.
Args:
afile: File path (str) or file-like object to read from
file_type (str, optional): File type specification. Defaults to 'ods'
when afile is a stream
**keywords: Additional keyword arguments:
- start_row (int): Starting row index for pagination
- row_limit (int): Maximum number of rows to read
- start_column (int): Starting column index for pagination
- column_limit (int): Maximum number of columns to read
- auto_detect_int (bool): Auto-detect integers from floats (default: True)
Returns:
dict: Dictionary with sheet names as keys and data as lists of lists
Example:
data = get_data("file.ods")
# Returns: {"Sheet1": [[1, 2], [3, 4]], "Sheet2": [["a", "b"]]}
# With pagination
partial = get_data("file.ods", start_row=1, row_limit=5)
"""Write Python data structures to ODS files.
def save_data(afile, data, file_type=None, **keywords):
"""
Standalone module function for writing module supported file type.
Args:
afile: File path (str) or file-like object to write to
data (dict): Dictionary with sheet names as keys and data as lists of lists
file_type (str, optional): File type specification. Defaults to 'ods'
when afile is a stream
**keywords: Additional keyword arguments passed to writer
Returns:
None
Example:
from collections import OrderedDict
data = OrderedDict()
data["Sheet1"] = [[1, 2, 3], [4, 5, 6]]
data["Sheet2"] = [["a", "b", "c"]]
save_data("output.ods", data)
"""Alternative function names for backward compatibility with older pyexcel-ods versions.
def read_data(afile, file_type=None, **keywords):
"""
Alias for get_data(). Identical functionality.
Args:
afile: File path or file-like object
file_type (str, optional): File type specification
**keywords: Same as get_data()
Returns:
dict: Same as get_data()
"""
def write_data(afile, data, file_type=None, **keywords):
"""
Alias for save_data(). Identical functionality.
Args:
afile: File path or file-like object
data (dict): Data to write
file_type (str, optional): File type specification
**keywords: Same as save_data()
Returns:
None
"""Utility functions for working with file-like objects.
def isstream(afile):
"""
Check if the given object is a stream-like object.
Args:
afile: Object to check
Returns:
bool: True if object is stream-like, False otherwise
"""Reading Support:
Writing Support:
Data is organized as nested dictionaries and lists:
{
"Sheet Name 1": [
["cell_a1", "cell_b1", "cell_c1"], # Row 1
["cell_a2", "cell_b2", "cell_c2"], # Row 2
["cell_a3", "cell_b3", "cell_c3"] # Row 3
],
"Sheet Name 2": [
[1, 2, 3, 4],
[5, 6, 7, 8]
]
}For large files, you can read partial data using pagination parameters:
start_row: Starting row index (0-based)row_limit: Maximum number of rows to readstart_column: Starting column index (0-based)column_limit: Maximum number of columns to read# Read rows 2-4, columns 1-3
partial_data = get_data("large_file.ods",
start_row=2, row_limit=3,
start_column=1, column_limit=3)# Read from file path
data = get_data("/path/to/file.ods")
# Write to file path
save_data("/path/to/output.ods", data)from io import BytesIO
# Writing to memory stream
memory_stream = BytesIO()
save_data(memory_stream, data)
# Reading from memory stream
memory_stream.seek(0) # Reset position to beginning
data = get_data(memory_stream, file_type="ods")
# Or get bytes for HTTP response, file upload, etc.
ods_bytes = memory_stream.getvalue()# Flask example - file upload
from flask import Flask, request
app = Flask(__name__)
@app.route('/upload', methods=['POST'])
def upload_file():
file = request.files['ods_file']
data = get_data(file, file_type="ods")
# Process data...
return "File processed"
# Django example - file download
from django.http import HttpResponse
def download_ods(request):
data = {"Sheet1": [[1, 2, 3], [4, 5, 6]]}
response = HttpResponse(content_type='application/vnd.oasis.opendocument.spreadsheet')
response['Content-Disposition'] = 'attachment; filename="data.ods"'
save_data(response, data)
return responsepyexcel-ods automatically integrates with the broader pyexcel library when both are installed:
import pyexcel as pe
# pyexcel automatically uses pyexcel-ods for .ods files
book = pe.get_book(file_name="data.ods")
sheet = pe.get_sheet(file_name="data.ods")
# Save pyexcel objects as ODS
sheet.save_as("output.ods")Common error scenarios and handling:
# File not found
try:
data = get_data("nonexistent.ods")
except FileNotFoundError:
print("File not found")
# Invalid ODS file
try:
data = get_data("corrupted.ods")
except Exception as e:
print(f"Error reading ODS file: {e}")
# Write permissions
try:
save_data("/readonly/path/file.ods", data)
except PermissionError:
print("No write permission")__FILE_TYPE__ = "ods" # File type identifier used internally