A wrapper library to read, manipulate and write data in ods format
npx @tessl/cli install tessl/pypi-pyexcel-ods@0.6.00
# pyexcel-ods
1
2
A 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.
3
4
## Package Information
5
6
- **Package Name**: pyexcel-ods
7
- **Language**: Python
8
- **Installation**: `pip install pyexcel-ods`
9
10
## Core Imports
11
12
```python
13
from pyexcel_ods import get_data, save_data
14
```
15
16
Alternative import for backward compatibility:
17
18
```python
19
from pyexcel_ods import read_data, write_data
20
```
21
22
Check if object is a stream:
23
24
```python
25
from pyexcel_ods import isstream
26
```
27
28
## Basic Usage
29
30
```python
31
from pyexcel_ods import get_data, save_data
32
from collections import OrderedDict
33
34
# Reading an ODS file
35
data = get_data("input.ods")
36
print(data) # {'Sheet1': [[1, 2, 3], [4, 5, 6]], 'Sheet2': [['a', 'b', 'c']]}
37
38
# Writing to an ODS file
39
output_data = OrderedDict()
40
output_data.update({"Sheet 1": [[1, 2, 3], [4, 5, 6]]})
41
output_data.update({"Sheet 2": [["row 1", "row 2", "row 3"]]})
42
save_data("output.ods", output_data)
43
44
# Working with memory streams
45
from io import BytesIO
46
47
# Write to memory
48
io_stream = BytesIO()
49
save_data(io_stream, output_data)
50
51
# Read from memory
52
io_stream.seek(0) # Reset stream position
53
data_from_memory = get_data(io_stream)
54
```
55
56
## Capabilities
57
58
### Data Reading
59
60
Read data from ODS files into Python data structures.
61
62
```python { .api }
63
def get_data(afile, file_type=None, **keywords):
64
"""
65
Standalone module function for reading module supported file type.
66
67
Args:
68
afile: File path (str) or file-like object to read from
69
file_type (str, optional): File type specification. Defaults to 'ods'
70
when afile is a stream
71
**keywords: Additional keyword arguments:
72
- start_row (int): Starting row index for pagination
73
- row_limit (int): Maximum number of rows to read
74
- start_column (int): Starting column index for pagination
75
- column_limit (int): Maximum number of columns to read
76
- auto_detect_int (bool): Auto-detect integers from floats (default: True)
77
78
Returns:
79
dict: Dictionary with sheet names as keys and data as lists of lists
80
81
Example:
82
data = get_data("file.ods")
83
# Returns: {"Sheet1": [[1, 2], [3, 4]], "Sheet2": [["a", "b"]]}
84
85
# With pagination
86
partial = get_data("file.ods", start_row=1, row_limit=5)
87
"""
88
```
89
90
### Data Writing
91
92
Write Python data structures to ODS files.
93
94
```python { .api }
95
def save_data(afile, data, file_type=None, **keywords):
96
"""
97
Standalone module function for writing module supported file type.
98
99
Args:
100
afile: File path (str) or file-like object to write to
101
data (dict): Dictionary with sheet names as keys and data as lists of lists
102
file_type (str, optional): File type specification. Defaults to 'ods'
103
when afile is a stream
104
**keywords: Additional keyword arguments passed to writer
105
106
Returns:
107
None
108
109
Example:
110
from collections import OrderedDict
111
data = OrderedDict()
112
data["Sheet1"] = [[1, 2, 3], [4, 5, 6]]
113
data["Sheet2"] = [["a", "b", "c"]]
114
save_data("output.ods", data)
115
"""
116
```
117
118
### Compatibility Functions
119
120
Alternative function names for backward compatibility with older pyexcel-ods versions.
121
122
```python { .api }
123
def read_data(afile, file_type=None, **keywords):
124
"""
125
Alias for get_data(). Identical functionality.
126
127
Args:
128
afile: File path or file-like object
129
file_type (str, optional): File type specification
130
**keywords: Same as get_data()
131
132
Returns:
133
dict: Same as get_data()
134
"""
135
136
def write_data(afile, data, file_type=None, **keywords):
137
"""
138
Alias for save_data(). Identical functionality.
139
140
Args:
141
afile: File path or file-like object
142
data (dict): Data to write
143
file_type (str, optional): File type specification
144
**keywords: Same as save_data()
145
146
Returns:
147
None
148
"""
149
```
150
151
### Stream Utilities
152
153
Utility functions for working with file-like objects.
154
155
```python { .api }
156
def isstream(afile):
157
"""
158
Check if the given object is a stream-like object.
159
160
Args:
161
afile: Object to check
162
163
Returns:
164
bool: True if object is stream-like, False otherwise
165
"""
166
```
167
168
## Data Types and Formats
169
170
### Supported Data Types
171
172
**Reading Support:**
173
- **Strings**: Text content, including multi-line strings with embedded newlines
174
- **Numbers**: Integers and floating-point numbers with automatic type detection
175
- **Booleans**: True/False values
176
- **Dates**: Date objects (converted to Python datetime.date)
177
- **Times**: Time objects (converted to Python datetime.time or timedelta)
178
- **Currency**: Formatted as "value currency" strings (e.g., "1 GBP", "-10000 USD")
179
- **Percentages**: Numeric percentage values
180
- **Empty cells**: Represented as empty strings or appropriate null values
181
182
**Writing Support:**
183
- **Basic Python types**: str, int, float, bool
184
- **Multi-line strings**: Strings containing newline characters
185
- **Automatic type conversion**: Python types are automatically converted to appropriate ODS cell types
186
187
### Data Structure Format
188
189
Data is organized as nested dictionaries and lists:
190
191
```python
192
{
193
"Sheet Name 1": [
194
["cell_a1", "cell_b1", "cell_c1"], # Row 1
195
["cell_a2", "cell_b2", "cell_c2"], # Row 2
196
["cell_a3", "cell_b3", "cell_c3"] # Row 3
197
],
198
"Sheet Name 2": [
199
[1, 2, 3, 4],
200
[5, 6, 7, 8]
201
]
202
}
203
```
204
205
### Pagination Options
206
207
For large files, you can read partial data using pagination parameters:
208
209
- **`start_row`**: Starting row index (0-based)
210
- **`row_limit`**: Maximum number of rows to read
211
- **`start_column`**: Starting column index (0-based)
212
- **`column_limit`**: Maximum number of columns to read
213
214
```python
215
# Read rows 2-4, columns 1-3
216
partial_data = get_data("large_file.ods",
217
start_row=2, row_limit=3,
218
start_column=1, column_limit=3)
219
```
220
221
## File and Stream Handling
222
223
### File Path Usage
224
225
```python
226
# Read from file path
227
data = get_data("/path/to/file.ods")
228
229
# Write to file path
230
save_data("/path/to/output.ods", data)
231
```
232
233
### Memory Stream Usage
234
235
```python
236
from io import BytesIO
237
238
# Writing to memory stream
239
memory_stream = BytesIO()
240
save_data(memory_stream, data)
241
242
# Reading from memory stream
243
memory_stream.seek(0) # Reset position to beginning
244
data = get_data(memory_stream, file_type="ods")
245
246
# Or get bytes for HTTP response, file upload, etc.
247
ods_bytes = memory_stream.getvalue()
248
```
249
250
### Integration with Web Frameworks
251
252
```python
253
# Flask example - file upload
254
from flask import Flask, request
255
app = Flask(__name__)
256
257
@app.route('/upload', methods=['POST'])
258
def upload_file():
259
file = request.files['ods_file']
260
data = get_data(file, file_type="ods")
261
# Process data...
262
return "File processed"
263
264
# Django example - file download
265
from django.http import HttpResponse
266
267
def download_ods(request):
268
data = {"Sheet1": [[1, 2, 3], [4, 5, 6]]}
269
270
response = HttpResponse(content_type='application/vnd.oasis.opendocument.spreadsheet')
271
response['Content-Disposition'] = 'attachment; filename="data.ods"'
272
273
save_data(response, data)
274
return response
275
```
276
277
## Integration with pyexcel Ecosystem
278
279
pyexcel-ods automatically integrates with the broader pyexcel library when both are installed:
280
281
```python
282
import pyexcel as pe
283
284
# pyexcel automatically uses pyexcel-ods for .ods files
285
book = pe.get_book(file_name="data.ods")
286
sheet = pe.get_sheet(file_name="data.ods")
287
288
# Save pyexcel objects as ODS
289
sheet.save_as("output.ods")
290
```
291
292
## Error Handling
293
294
Common error scenarios and handling:
295
296
```python
297
# File not found
298
try:
299
data = get_data("nonexistent.ods")
300
except FileNotFoundError:
301
print("File not found")
302
303
# Invalid ODS file
304
try:
305
data = get_data("corrupted.ods")
306
except Exception as e:
307
print(f"Error reading ODS file: {e}")
308
309
# Write permissions
310
try:
311
save_data("/readonly/path/file.ods", data)
312
except PermissionError:
313
print("No write permission")
314
```
315
316
## Limitations
317
318
- **Formatting not supported**: Fonts, colors, charts, and visual formatting are not preserved
319
- **Data focus**: Designed for data extraction and generation, not document formatting
320
- **Read-only for complex features**: Advanced ODS features like formulas, macros, and embedded objects are not supported
321
- **Memory considerations**: Large files are read entirely into memory; use pagination for very large datasets
322
323
## Constants
324
325
```python { .api }
326
__FILE_TYPE__ = "ods" # File type identifier used internally
327
```