numbers-parser 4.17.0.post1__tar.gz → 4.18.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {numbers_parser-4.17.0.post1/src/numbers_parser.egg-info → numbers_parser-4.18.1}/PKG-INFO +35 -121
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/README.md +34 -120
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/pyproject.toml +2 -2
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/_cat_numbers.py +15 -4
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/cell.py +3 -15
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/constants.py +5 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/document.py +85 -40
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/exceptions.py +1 -1
- numbers_parser-4.18.1/src/numbers_parser/experimental.py +30 -0
- numbers_parser-4.18.1/src/numbers_parser/formula.py +278 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/model.py +159 -149
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/xrefs.py +0 -2
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1/src/numbers_parser.egg-info}/PKG-INFO +35 -121
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser.egg-info/SOURCES.txt +0 -1
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_cat_numbers.py +9 -6
- numbers_parser-4.18.1/tests/test_categories.py +391 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_coverage.py +12 -7
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_formatting.py +2 -2
- numbers_parser-4.18.1/tests/test_formulas.py +114 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_issues.py +1 -1
- numbers_parser-4.17.0.post1/src/numbers_parser/experimental.py +0 -16
- numbers_parser-4.17.0.post1/src/numbers_parser/formula.py +0 -689
- numbers_parser-4.17.0.post1/src/numbers_parser/tokenizer.py +0 -548
- numbers_parser-4.17.0.post1/tests/test_categories.py +0 -687
- numbers_parser-4.17.0.post1/tests/test_formulas.py +0 -404
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/LICENSE.rst +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/setup.cfg +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/__init__.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/_csv2numbers.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/_unpack_numbers.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/bullets.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/containers.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/currencies.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/data/empty.numbers +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TNArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TNArchives_sos_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TNCommandArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TNCommandArchives_sos_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSAArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSAArchives_sos_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSACommandArchives_sos_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSCEArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSCH3DArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSCHArchives_Common_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSCHArchives_GEN_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSCHArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSCHArchives_sos_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSCHCommandArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSCHPreUFFArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSCKArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSCKArchives_sos_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSDArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSDArchives_sos_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSDCommandArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSKArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSPArchiveMessages_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSPDatabaseMessages_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSPMessages_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSSArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSSArchives_sos_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSTArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSTArchives_sos_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSTCommandArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSTStylePropertyArchiving_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSWPArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSWPArchives_sos_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/TSWPCommandArchives_pb2.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/__init__.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/fontmap.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/functionmap.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/generated/mapping.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/iwafile.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/iwork.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/numbers_cache.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/numbers_uuid.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser/roman.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser.egg-info/dependency_links.txt +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser.egg-info/entry_points.txt +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser.egg-info/requires.txt +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/src/numbers_parser.egg-info/top_level.txt +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_all_formulas.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_api_change.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_borders.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_bullets.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_create_cells.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_csv2numbers.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_currency.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_folder.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_large.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_memory_leaks.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_merges.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_package.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_properties.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_roman.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_save.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_slices.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_styles.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_table_size.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_tables.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_unpack_numbers.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_unsupported.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_uuids.py +0 -0
- {numbers_parser-4.17.0.post1 → numbers_parser-4.18.1}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: numbers-parser
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.18.1
|
|
4
4
|
Summary: Read and write Apple Numbers spreadsheets
|
|
5
5
|
Author-email: Jon Connell <python@figsandfudge.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,20 +26,15 @@ Dynamic: license-file
|
|
|
26
26
|
|
|
27
27
|
[](https://github.com/masaccio/numbers-parser/actions/workflows/run-all-tests.yml)[](https://github.com/masaccio/numbers-parser/actions/workflows/codeql.yml)[](https://codecov.io/gh/masaccio/numbers-parser)[](https://badge.fury.io/py/numbers-parser)
|
|
28
28
|
|
|
29
|
-
`numbers-parser` is a Python module for
|
|
30
|
-
generated by Numbers version 10.3, and up with the latest tested version being 14.1
|
|
31
|
-
(current as of June 2024).
|
|
29
|
+
`numbers-parser` is a Python module for reading and editing [Apple Numbers](https://www.apple.com/numbers/)`.numbers` files. It supports Numbers files generated by Numbers versions 3.x and later. It is tested against Numbers documents from 10.0 through to 14.4 (the last version of Numbers) and Numbers Creator Studio up to version 15.1, which the most current as of February 2026.
|
|
32
30
|
|
|
33
|
-
It supports and is tested against Python versions from 3.10 onwards. It is not compatible
|
|
34
|
-
with earlier versions of Python.
|
|
31
|
+
It supports and is tested against Python versions from 3.10 onwards. It is not compatible with earlier versions of Python.
|
|
35
32
|
|
|
36
33
|
## Installation
|
|
37
34
|
|
|
38
35
|
A pre-requisite for this package is [python-snappy](https://pypi.org/project/python-snappy/) which will be installed by Python automatically, but python-snappy also requires binary libraries for snappy compression.
|
|
39
36
|
|
|
40
|
-
The most straightforward way to install the binary dependencies is to use
|
|
41
|
-
[Homebrew](https://brew.sh) and source Python from Homebrew rather than from macOS as described
|
|
42
|
-
in the [python-snappy github](https://github.com/andrix/python-snappy). Using [pipx](https://pipx.pypa.io/stable/installation/) for package management is also strongly recommended:
|
|
37
|
+
The most straightforward way to install the binary dependencies is to use [Homebrew](https://brew.sh) and source Python from Homebrew rather than from macOS as described in the [python-snappy github](https://github.com/andrix/python-snappy). Using [pipx](https://pipx.pypa.io/stable/installation/) for package management is also strongly recommended:
|
|
43
38
|
|
|
44
39
|
```bash
|
|
45
40
|
brew install snappy python3 pipx
|
|
@@ -52,9 +47,7 @@ For Linux (your package manager may be different):
|
|
|
52
47
|
sudo apt-get -y install libsnappy-dev
|
|
53
48
|
```
|
|
54
49
|
|
|
55
|
-
On Windows, you will need to either arrange for snappy to be found for VSC++ or you can install python
|
|
56
|
-
[pre-compiled binary libraries](https://github.com/cgohlke/win_arm64-wheels/) which are only available
|
|
57
|
-
for Windows on Arm. There appear to be no x86 pre-compiled packages for Windows.
|
|
50
|
+
On Windows, you will need to either arrange for snappy to be found for VSC++ or you can install python [pre-compiled binary libraries](https://github.com/cgohlke/win_arm64-wheels/) which are only available for Windows on Arm. There appear to be no x86 pre-compiled packages for Windows.
|
|
58
51
|
|
|
59
52
|
```text
|
|
60
53
|
pip install python_snappy-0.6.1-cp312-cp312-win_arm64.whl
|
|
@@ -118,12 +111,7 @@ python datatype. Available cell types are:
|
|
|
118
111
|
| ErrorCell | `None` | |
|
|
119
112
|
| MergedCell | `None` | See [Merged cells](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.MergedCell) |
|
|
120
113
|
|
|
121
|
-
Cell references can be either zero-offset row/column integers or an
|
|
122
|
-
Excel/Numbers A1 notation. Where cell values are not `None` the
|
|
123
|
-
property `formatted_value` returns the cell value as a `str` as
|
|
124
|
-
displayed in Numbers. Cells that have no values in a table are
|
|
125
|
-
represented as `EmptyCell` and cells containing evaluation errors of
|
|
126
|
-
any kind `ErrorCell`.
|
|
114
|
+
Cell references can be either zero-offset row/column integers or an Excel/Numbers A1 notation. Where cell values are not `None` the property `formatted_value` returns the cell value as a `str` as displayed in Numbers. Cells that have no values in a table are represented as `EmptyCell` and cells containing evaluation errors of any kind `ErrorCell`.
|
|
127
115
|
|
|
128
116
|
```python
|
|
129
117
|
>>> table.cell(1,0)
|
|
@@ -140,10 +128,7 @@ any kind `ErrorCell`.
|
|
|
140
128
|
|
|
141
129
|
### Pandas Support
|
|
142
130
|
|
|
143
|
-
Since the return value of `rows()` is a list of lists, you can pass
|
|
144
|
-
this directly to pandas. Assuming you have a Numbers table with a single
|
|
145
|
-
header which contains the names of the pandas series you want to create
|
|
146
|
-
you can construct a pandas dataframe using:
|
|
131
|
+
Since the return value of `rows()` is a list of lists, you can pass this directly to pandas. Assuming you have a Numbers table with a single header which contains the names of the pandas series you want to create you can construct a pandas dataframe using:
|
|
147
132
|
|
|
148
133
|
```python
|
|
149
134
|
import pandas as pd
|
|
@@ -157,14 +142,9 @@ df = pd.DataFrame(data[1:], columns=data[0])
|
|
|
157
142
|
|
|
158
143
|
### Writing Numbers Documents
|
|
159
144
|
|
|
160
|
-
Whilst support for writing numbers files has been stable since version
|
|
161
|
-
3.4.0, you are highly recommended not to overwrite working Numbers files
|
|
162
|
-
and instead save data to a new file.
|
|
145
|
+
Whilst support for writing numbers files has been stable since version 3.4.0, you are highly recommended not to overwrite working Numbers files and instead save data to a new file.
|
|
163
146
|
|
|
164
|
-
Cell values are written using
|
|
165
|
-
[Table.write()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.write) and
|
|
166
|
-
`numbers-parser` will automatically create empty rows and columns
|
|
167
|
-
for any cell references that are out of range of the current table.
|
|
147
|
+
Cell values are written using [Table.write()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.write) and `numbers-parser` will automatically create empty rows and columns for any cell references that are out of range of the current table.
|
|
168
148
|
|
|
169
149
|
```python
|
|
170
150
|
doc = Document("write.numbers")
|
|
@@ -176,9 +156,7 @@ table.write("B7", datetime(2020, 12, 25))
|
|
|
176
156
|
doc.save("new-sheet.numbers")
|
|
177
157
|
```
|
|
178
158
|
|
|
179
|
-
Additional tables and worksheets can be added to a `Document` before saving using
|
|
180
|
-
[Document.add_sheet()](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_sheet) and
|
|
181
|
-
[Sheet.add_table()](https://masaccio.github.io/numbers-parser/api/sheet.html#numbers_parser.Sheet.add_table) respectively:
|
|
159
|
+
Additional tables and worksheets can be added to a `Document` before saving using [Document.add_sheet()](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_sheet) and [Sheet.add_table()](https://masaccio.github.io/numbers-parser/api/sheet.html#numbers_parser.Sheet.add_table) respectively:
|
|
182
160
|
|
|
183
161
|
```python
|
|
184
162
|
doc = Document()
|
|
@@ -204,19 +182,11 @@ styles. The following styles are supported:
|
|
|
204
182
|
- cell background images
|
|
205
183
|
- cell indents (first line, left, right, and text inset)
|
|
206
184
|
|
|
207
|
-
Numbers conflates style attributes that can be stored in paragraph
|
|
208
|
-
styles (the style menu in the text panel) with the settings that are
|
|
209
|
-
available on the Style tab of the Text panel. Some attributes in Numbers
|
|
210
|
-
are not applied to new cells when a style is applied.
|
|
185
|
+
Numbers conflates style attributes that can be stored in paragraph styles (the style menu in the text panel) with the settings that are available on the Style tab of the Text panel. Some attributes in Numbers are not applied to new cells when a style is applied.
|
|
211
186
|
|
|
212
|
-
To keep the API simple, `numbers-parser` packs all styling into a single
|
|
213
|
-
[Style](https://masaccio.github.io/numbers-parser/api/style.html) object. When a document is saved, the attributes
|
|
214
|
-
not stored in a paragraph style are applied to each cell that includes it.
|
|
187
|
+
To keep the API simple, `numbers-parser` packs all styling into a single [Style](https://masaccio.github.io/numbers-parser/api/style.html) object. When a document is saved, the attributes not stored in a paragraph style are applied to each cell that includes it.
|
|
215
188
|
|
|
216
|
-
Styles are read from cells using the
|
|
217
|
-
[Cell.style](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.Cell.style) property and you can
|
|
218
|
-
add new styles with
|
|
219
|
-
[Document.add_style](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_style).
|
|
189
|
+
Styles are read from cells using the [Cell.style](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.Cell.style) property and you can add new styles with [Document.add_style](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_style).
|
|
220
190
|
|
|
221
191
|
```python
|
|
222
192
|
red_text = doc.add_style(
|
|
@@ -234,18 +204,11 @@ table.set_cell_style("C2", red_text)
|
|
|
234
204
|
|
|
235
205
|
### Cell Data Formatting
|
|
236
206
|
|
|
237
|
-
Numbers has two different cell formatting types: data formats and custom
|
|
238
|
-
formats.
|
|
207
|
+
Numbers has two different cell formatting types: data formats and custom formats.
|
|
239
208
|
|
|
240
|
-
Data formats are presented in Numbers in the Cell tab of the Format pane
|
|
241
|
-
and are applied to individual cells. Like Numbers, `numbers-parsers`
|
|
242
|
-
caches formatting information that is identical across multiple cells.
|
|
243
|
-
You do not need to take any action for this to happen; this is handled
|
|
244
|
-
internally by the package. Changing a data format for cell has no impact
|
|
245
|
-
on any other cells.
|
|
209
|
+
Data formats are presented in Numbers in the Cell tab of the Format pane and are applied to individual cells. Like Numbers, `numbers-parsers` caches formatting information that is identical across multiple cells. You do not need to take any action for this to happen; this is handled internally by the package. Changing a data format for cell has no impact on any other cells.
|
|
246
210
|
|
|
247
|
-
Cell formats are changed using
|
|
248
|
-
[Table.set_cell_formatting()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_formatting):
|
|
211
|
+
Cell formats are changed using [Table.set_cell_formatting()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_formatting):
|
|
249
212
|
|
|
250
213
|
```python
|
|
251
214
|
table.set_cell_formatting(
|
|
@@ -262,13 +225,7 @@ table.set_cell_formatting(
|
|
|
262
225
|
)
|
|
263
226
|
```
|
|
264
227
|
|
|
265
|
-
Custom formats are shared across a Document and can be applied to
|
|
266
|
-
multiple cells in multiple tables. Editing a custom format changes the
|
|
267
|
-
appearance of data in all cells that share that format. You must first
|
|
268
|
-
add a custom format to the document using
|
|
269
|
-
[Document.add_custom_format()](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_custom_format)
|
|
270
|
-
before assigning it to cells using
|
|
271
|
-
[Table.set_cell_formatting()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_formatting):
|
|
228
|
+
Custom formats are shared across a Document and can be applied to multiple cells in multiple tables. Editing a custom format changes the appearance of data in all cells that share that format. You must first add a custom format to the document using [Document.add_custom_format()](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_custom_format) before assigning it to cells using [Table.set_cell_formatting()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_formatting):
|
|
272
229
|
|
|
273
230
|
```python
|
|
274
231
|
long_date = doc.add_custom_format(
|
|
@@ -279,33 +236,17 @@ long_date = doc.add_custom_format(
|
|
|
279
236
|
table.set_cell_formatting("C1", "custom", format=long_date)
|
|
280
237
|
```
|
|
281
238
|
|
|
282
|
-
A limited number of currencies are formatted using symbolic notation
|
|
283
|
-
rather than an ISO code. These are defined in
|
|
284
|
-
`numbers_parser.currencies` and match the ones chosen by Numbers. For
|
|
285
|
-
example, US dollars are referred to as `US$` whereas Euros and British
|
|
286
|
-
Pounds are referred to using their symbols of `€` and `£`
|
|
287
|
-
respectively.
|
|
239
|
+
A limited number of currencies are formatted using symbolic notation rather than an ISO code. These are defined in `numbers_parser.currencies` and match the ones chosen by Numbers. For example, US dollars are referred to as `US$` whereas Euros and British Pounds are referred to using their symbols of `€` and `£` respectively.
|
|
288
240
|
|
|
289
241
|
### Borders
|
|
290
242
|
|
|
291
|
-
`numbers-parser` supports reading and writing cell borders, though the
|
|
292
|
-
interface for each differs. Individual cells can have each of their four
|
|
293
|
-
borders tested, but when drawing new borders, these are set for the
|
|
294
|
-
table to allow for drawing borders across multiple cells. Setting the
|
|
295
|
-
border of merged cells is not possible unless the edge of the cells is
|
|
296
|
-
at the end of the merged region.
|
|
243
|
+
`numbers-parser` supports reading and writing cell borders, though the interface for each differs. Individual cells can have each of their four borders tested, but when drawing new borders, these are set for the table to allow for drawing borders across multiple cells. Setting the border of merged cells is not possible unless the edge of the cells is at the end of the merged region.
|
|
297
244
|
|
|
298
|
-
Borders are represented using the [Border](https://masaccio.github.io/numbers-parser/api/border.html) class
|
|
299
|
-
that can be initialized with line width, color and line style. The
|
|
300
|
-
current state of a cell border is read using the
|
|
301
|
-
[Cell.border](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.Cell.border) property
|
|
302
|
-
and [Table.set_cell_border()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_border)
|
|
303
|
-
sets the border for a cell edge or a range of cells.
|
|
245
|
+
Borders are represented using the [Border](https://masaccio.github.io/numbers-parser/api/border.html) class that can be initialized with line width, color and line style. The current state of a cell border is read using the [Cell.border](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.Cell.border) property and [Table.set_cell_border()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_border) sets the border for a cell edge or a range of cells.
|
|
304
246
|
|
|
305
247
|
## API
|
|
306
248
|
|
|
307
|
-
For more examples and details of all available classes and methods,
|
|
308
|
-
see the [full API docs](https://masaccio.github.io/numbers-parser/).
|
|
249
|
+
For more examples and details of all available classes and methods, see the [full API docs](https://masaccio.github.io/numbers-parser/).
|
|
309
250
|
|
|
310
251
|
## Command-line scripts
|
|
311
252
|
|
|
@@ -318,9 +259,7 @@ a number of command-line scripts are installed:
|
|
|
318
259
|
|
|
319
260
|
### cat-numbers
|
|
320
261
|
|
|
321
|
-
This script dumps Numbers spreadsheets into Excel-compatible CSV
|
|
322
|
-
format, iterating through all the spreadsheets passed on the
|
|
323
|
-
command-line.
|
|
262
|
+
This script dumps Numbers spreadsheets into Excel-compatible CSV format, iterating through all the spreadsheets passed on the command-line.
|
|
324
263
|
|
|
325
264
|
```text
|
|
326
265
|
usage: cat-numbers [-h] [-T | -S | -b] [-V] [--formulas] [--formatting]
|
|
@@ -349,25 +288,17 @@ options:
|
|
|
349
288
|
--debug Enable debug logging
|
|
350
289
|
```
|
|
351
290
|
|
|
352
|
-
Note: `--formatting` will return different capitalization for 12-hour
|
|
353
|
-
times due to differences between Numbers’ representation of these dates
|
|
354
|
-
and `datetime.strftime`. Numbers in English locales displays 12-hour
|
|
355
|
-
times with ‘am’ and ‘pm’, but `datetime.strftime` on macOS at least
|
|
356
|
-
cannot return lower-case versions of AM/PM.
|
|
291
|
+
Note: `--formatting` will return different capitalization for 12-hour times due to differences between Numbers’ representation of these dates and `datetime.strftime`. Numbers in English locales displays 12-hour times with ‘am’ and ‘pm’, but `datetime.strftime` on macOS at least cannot return lower-case versions of AM/PM.
|
|
357
292
|
|
|
358
293
|
### csv2numbers
|
|
359
294
|
|
|
360
|
-
This script converts Excel-compatible CSV files into Numbers documents. Output files
|
|
361
|
-
can optionally be provided, but is none are provided, the output is created by replacing
|
|
362
|
-
the input’s files suffix with .numbers. For example:
|
|
295
|
+
This script converts Excel-compatible CSV files into Numbers documents. Output files can optionally be provided, but is none are provided, the output is created by replacing the input’s files suffix with .numbers. For example:
|
|
363
296
|
|
|
364
297
|
```text
|
|
365
298
|
csv2numbers file1.csv file2.csv -o file1.numbers file2.numbers
|
|
366
299
|
```
|
|
367
300
|
|
|
368
|
-
Columns of data can have a number of transformations applied to them. The primary use-
|
|
369
|
-
case intended for `csv2numbers` is converting banking exports to well-formatted
|
|
370
|
-
spreadsheets.
|
|
301
|
+
Columns of data can have a number of transformations applied to them. The primary use- case intended for `csv2numbers` is converting banking exports to well-formatted spreadsheets.
|
|
371
302
|
|
|
372
303
|
```text
|
|
373
304
|
usage: csv2numbers [-h] [-V] [--whitespace] [--reverse] [--no-header]
|
|
@@ -455,39 +386,22 @@ csv2numbers --transform='Category=LOOKUP:Transaction;mapping.numbers' file1.csv
|
|
|
455
386
|
|
|
456
387
|
Current known limitations of `numbers-parser` which may be implemented in the future are:
|
|
457
388
|
|
|
458
|
-
- Table styles that allow new tables to adopt a style across the whole
|
|
459
|
-
table are not suppported
|
|
389
|
+
- Table styles that allow new tables to adopt a style across the whole table are not supported
|
|
460
390
|
- Creating cells of type `BulletedTextCell` is not supported
|
|
461
|
-
- New tables are inserted with a fixed offset below the last table in a
|
|
462
|
-
|
|
463
|
-
- Captions can be created and edited as of numbers-parser version 4.12, but cannot
|
|
464
|
-
be styled. New captions adopt the first caption style available in the current
|
|
465
|
-
document
|
|
391
|
+
- New tables are inserted with a fixed offset below the last table in a worksheet which does not take into account title or caption size
|
|
392
|
+
- Captions can be created and edited as of numbers-parser version 4.12, but cannot be styled. New captions adopt the first caption style available in the current document
|
|
466
393
|
- Formulas cannot be written to a document
|
|
467
|
-
- Pivot tables are unsupported and saving a document with a pivot table issues
|
|
468
|
-
|
|
394
|
+
- Pivot tables are unsupported and saving a document with a pivot table issues a UnsupportedWarning (see [issue 73](https://github.com/masaccio/numbers-parser/issues/73) for details).
|
|
395
|
+
- Tables which have been saved grouped cannot be safely edited as references to written cells refer to the ungrouped cell rows rather than the row number in the groups.
|
|
469
396
|
|
|
470
397
|
The following limitations are expected to always remain:
|
|
471
398
|
|
|
472
|
-
- New sheets insert tables with formats copied from the first table in
|
|
473
|
-
|
|
474
|
-
-
|
|
475
|
-
|
|
476
|
-
versions older than 3.11 do not support image filenames with UTF-8 characters
|
|
477
|
-
[Cell.add_style.bg_image()](https://masaccio.github.io/numbers-parser/api/sheet.html#numbers_parser.Style) returns
|
|
478
|
-
`None` for such files and issues a `RuntimeWarning`
|
|
479
|
-
(see [issue 69](https://github.com/masaccio/numbers-parser/issues/69) for details).
|
|
480
|
-
- Password-encrypted documents cannot be opened. You must first re-save without
|
|
481
|
-
a password to read (see [issue 88](https://github.com/masaccio/numbers-parser/issues/88) for details).
|
|
482
|
-
A UnsupportedError exception is raised when such documents are opened.
|
|
483
|
-
- Due to changes in the format of Numbers documents, decoding of category groups
|
|
484
|
-
(introduced in `numbers-parser` version 4.16) is supported only for documents
|
|
485
|
-
created by Numbers 12.0 and later. No warnings are issued for earlier
|
|
399
|
+
- New sheets insert tables with formats copied from the first table in the previous sheet rather than default table formats
|
|
400
|
+
- Due to a limitation in Python’s [ZipFile](https://docs.python.org/3/library/zipfile.html), Python versions older than 3.11 do not support image filenames with UTF-8 characters [Cell.add_style.bg_image()](https://masaccio.github.io/numbers-parser/api/sheet.html#numbers_parser.Style) returns `None` for such files and issues a `RuntimeWarning` (see [issue 69](https://github.com/masaccio/numbers-parser/issues/69) for details).
|
|
401
|
+
- Password-encrypted documents cannot be opened. You must first re-save without a password to read (see [issue 88](https://github.com/masaccio/numbers-parser/issues/88) for details). A UnsupportedError exception is raised when such documents are opened.
|
|
402
|
+
- Due to changes in the format of Numbers documents, decoding of category groups (introduced in `numbers-parser` version 4.16) is supported only for documents created by Numbers 12.0 and later. No warnings are issued for earlier
|
|
486
403
|
Numbers documents.
|
|
487
|
-
- Only standard macOS fonts are not supported. If a document includes a non-standard
|
|
488
|
-
font, numbers-parser will issue a UnsupportedWarning and default styles to
|
|
489
|
-
Helvetica Neue. Reading font names from the system would add additional system-specific
|
|
490
|
-
dependencies to the package and so this is not planned to changed.
|
|
404
|
+
- Only standard macOS fonts are not supported. If a document includes a non-standard font, numbers-parser will issue a UnsupportedWarning and default styles to Helvetica Neue. Reading font names from the system would add additional system-specific dependencies to the package and so this is not planned to changed.
|
|
491
405
|
|
|
492
406
|
## License
|
|
493
407
|
|
|
@@ -2,20 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/masaccio/numbers-parser/actions/workflows/run-all-tests.yml)[](https://github.com/masaccio/numbers-parser/actions/workflows/codeql.yml)[](https://codecov.io/gh/masaccio/numbers-parser)[](https://badge.fury.io/py/numbers-parser)
|
|
4
4
|
|
|
5
|
-
`numbers-parser` is a Python module for
|
|
6
|
-
generated by Numbers version 10.3, and up with the latest tested version being 14.1
|
|
7
|
-
(current as of June 2024).
|
|
5
|
+
`numbers-parser` is a Python module for reading and editing [Apple Numbers](https://www.apple.com/numbers/)`.numbers` files. It supports Numbers files generated by Numbers versions 3.x and later. It is tested against Numbers documents from 10.0 through to 14.4 (the last version of Numbers) and Numbers Creator Studio up to version 15.1, which the most current as of February 2026.
|
|
8
6
|
|
|
9
|
-
It supports and is tested against Python versions from 3.10 onwards. It is not compatible
|
|
10
|
-
with earlier versions of Python.
|
|
7
|
+
It supports and is tested against Python versions from 3.10 onwards. It is not compatible with earlier versions of Python.
|
|
11
8
|
|
|
12
9
|
## Installation
|
|
13
10
|
|
|
14
11
|
A pre-requisite for this package is [python-snappy](https://pypi.org/project/python-snappy/) which will be installed by Python automatically, but python-snappy also requires binary libraries for snappy compression.
|
|
15
12
|
|
|
16
|
-
The most straightforward way to install the binary dependencies is to use
|
|
17
|
-
[Homebrew](https://brew.sh) and source Python from Homebrew rather than from macOS as described
|
|
18
|
-
in the [python-snappy github](https://github.com/andrix/python-snappy). Using [pipx](https://pipx.pypa.io/stable/installation/) for package management is also strongly recommended:
|
|
13
|
+
The most straightforward way to install the binary dependencies is to use [Homebrew](https://brew.sh) and source Python from Homebrew rather than from macOS as described in the [python-snappy github](https://github.com/andrix/python-snappy). Using [pipx](https://pipx.pypa.io/stable/installation/) for package management is also strongly recommended:
|
|
19
14
|
|
|
20
15
|
```bash
|
|
21
16
|
brew install snappy python3 pipx
|
|
@@ -28,9 +23,7 @@ For Linux (your package manager may be different):
|
|
|
28
23
|
sudo apt-get -y install libsnappy-dev
|
|
29
24
|
```
|
|
30
25
|
|
|
31
|
-
On Windows, you will need to either arrange for snappy to be found for VSC++ or you can install python
|
|
32
|
-
[pre-compiled binary libraries](https://github.com/cgohlke/win_arm64-wheels/) which are only available
|
|
33
|
-
for Windows on Arm. There appear to be no x86 pre-compiled packages for Windows.
|
|
26
|
+
On Windows, you will need to either arrange for snappy to be found for VSC++ or you can install python [pre-compiled binary libraries](https://github.com/cgohlke/win_arm64-wheels/) which are only available for Windows on Arm. There appear to be no x86 pre-compiled packages for Windows.
|
|
34
27
|
|
|
35
28
|
```text
|
|
36
29
|
pip install python_snappy-0.6.1-cp312-cp312-win_arm64.whl
|
|
@@ -94,12 +87,7 @@ python datatype. Available cell types are:
|
|
|
94
87
|
| ErrorCell | `None` | |
|
|
95
88
|
| MergedCell | `None` | See [Merged cells](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.MergedCell) |
|
|
96
89
|
|
|
97
|
-
Cell references can be either zero-offset row/column integers or an
|
|
98
|
-
Excel/Numbers A1 notation. Where cell values are not `None` the
|
|
99
|
-
property `formatted_value` returns the cell value as a `str` as
|
|
100
|
-
displayed in Numbers. Cells that have no values in a table are
|
|
101
|
-
represented as `EmptyCell` and cells containing evaluation errors of
|
|
102
|
-
any kind `ErrorCell`.
|
|
90
|
+
Cell references can be either zero-offset row/column integers or an Excel/Numbers A1 notation. Where cell values are not `None` the property `formatted_value` returns the cell value as a `str` as displayed in Numbers. Cells that have no values in a table are represented as `EmptyCell` and cells containing evaluation errors of any kind `ErrorCell`.
|
|
103
91
|
|
|
104
92
|
```python
|
|
105
93
|
>>> table.cell(1,0)
|
|
@@ -116,10 +104,7 @@ any kind `ErrorCell`.
|
|
|
116
104
|
|
|
117
105
|
### Pandas Support
|
|
118
106
|
|
|
119
|
-
Since the return value of `rows()` is a list of lists, you can pass
|
|
120
|
-
this directly to pandas. Assuming you have a Numbers table with a single
|
|
121
|
-
header which contains the names of the pandas series you want to create
|
|
122
|
-
you can construct a pandas dataframe using:
|
|
107
|
+
Since the return value of `rows()` is a list of lists, you can pass this directly to pandas. Assuming you have a Numbers table with a single header which contains the names of the pandas series you want to create you can construct a pandas dataframe using:
|
|
123
108
|
|
|
124
109
|
```python
|
|
125
110
|
import pandas as pd
|
|
@@ -133,14 +118,9 @@ df = pd.DataFrame(data[1:], columns=data[0])
|
|
|
133
118
|
|
|
134
119
|
### Writing Numbers Documents
|
|
135
120
|
|
|
136
|
-
Whilst support for writing numbers files has been stable since version
|
|
137
|
-
3.4.0, you are highly recommended not to overwrite working Numbers files
|
|
138
|
-
and instead save data to a new file.
|
|
121
|
+
Whilst support for writing numbers files has been stable since version 3.4.0, you are highly recommended not to overwrite working Numbers files and instead save data to a new file.
|
|
139
122
|
|
|
140
|
-
Cell values are written using
|
|
141
|
-
[Table.write()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.write) and
|
|
142
|
-
`numbers-parser` will automatically create empty rows and columns
|
|
143
|
-
for any cell references that are out of range of the current table.
|
|
123
|
+
Cell values are written using [Table.write()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.write) and `numbers-parser` will automatically create empty rows and columns for any cell references that are out of range of the current table.
|
|
144
124
|
|
|
145
125
|
```python
|
|
146
126
|
doc = Document("write.numbers")
|
|
@@ -152,9 +132,7 @@ table.write("B7", datetime(2020, 12, 25))
|
|
|
152
132
|
doc.save("new-sheet.numbers")
|
|
153
133
|
```
|
|
154
134
|
|
|
155
|
-
Additional tables and worksheets can be added to a `Document` before saving using
|
|
156
|
-
[Document.add_sheet()](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_sheet) and
|
|
157
|
-
[Sheet.add_table()](https://masaccio.github.io/numbers-parser/api/sheet.html#numbers_parser.Sheet.add_table) respectively:
|
|
135
|
+
Additional tables and worksheets can be added to a `Document` before saving using [Document.add_sheet()](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_sheet) and [Sheet.add_table()](https://masaccio.github.io/numbers-parser/api/sheet.html#numbers_parser.Sheet.add_table) respectively:
|
|
158
136
|
|
|
159
137
|
```python
|
|
160
138
|
doc = Document()
|
|
@@ -180,19 +158,11 @@ styles. The following styles are supported:
|
|
|
180
158
|
- cell background images
|
|
181
159
|
- cell indents (first line, left, right, and text inset)
|
|
182
160
|
|
|
183
|
-
Numbers conflates style attributes that can be stored in paragraph
|
|
184
|
-
styles (the style menu in the text panel) with the settings that are
|
|
185
|
-
available on the Style tab of the Text panel. Some attributes in Numbers
|
|
186
|
-
are not applied to new cells when a style is applied.
|
|
161
|
+
Numbers conflates style attributes that can be stored in paragraph styles (the style menu in the text panel) with the settings that are available on the Style tab of the Text panel. Some attributes in Numbers are not applied to new cells when a style is applied.
|
|
187
162
|
|
|
188
|
-
To keep the API simple, `numbers-parser` packs all styling into a single
|
|
189
|
-
[Style](https://masaccio.github.io/numbers-parser/api/style.html) object. When a document is saved, the attributes
|
|
190
|
-
not stored in a paragraph style are applied to each cell that includes it.
|
|
163
|
+
To keep the API simple, `numbers-parser` packs all styling into a single [Style](https://masaccio.github.io/numbers-parser/api/style.html) object. When a document is saved, the attributes not stored in a paragraph style are applied to each cell that includes it.
|
|
191
164
|
|
|
192
|
-
Styles are read from cells using the
|
|
193
|
-
[Cell.style](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.Cell.style) property and you can
|
|
194
|
-
add new styles with
|
|
195
|
-
[Document.add_style](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_style).
|
|
165
|
+
Styles are read from cells using the [Cell.style](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.Cell.style) property and you can add new styles with [Document.add_style](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_style).
|
|
196
166
|
|
|
197
167
|
```python
|
|
198
168
|
red_text = doc.add_style(
|
|
@@ -210,18 +180,11 @@ table.set_cell_style("C2", red_text)
|
|
|
210
180
|
|
|
211
181
|
### Cell Data Formatting
|
|
212
182
|
|
|
213
|
-
Numbers has two different cell formatting types: data formats and custom
|
|
214
|
-
formats.
|
|
183
|
+
Numbers has two different cell formatting types: data formats and custom formats.
|
|
215
184
|
|
|
216
|
-
Data formats are presented in Numbers in the Cell tab of the Format pane
|
|
217
|
-
and are applied to individual cells. Like Numbers, `numbers-parsers`
|
|
218
|
-
caches formatting information that is identical across multiple cells.
|
|
219
|
-
You do not need to take any action for this to happen; this is handled
|
|
220
|
-
internally by the package. Changing a data format for cell has no impact
|
|
221
|
-
on any other cells.
|
|
185
|
+
Data formats are presented in Numbers in the Cell tab of the Format pane and are applied to individual cells. Like Numbers, `numbers-parsers` caches formatting information that is identical across multiple cells. You do not need to take any action for this to happen; this is handled internally by the package. Changing a data format for cell has no impact on any other cells.
|
|
222
186
|
|
|
223
|
-
Cell formats are changed using
|
|
224
|
-
[Table.set_cell_formatting()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_formatting):
|
|
187
|
+
Cell formats are changed using [Table.set_cell_formatting()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_formatting):
|
|
225
188
|
|
|
226
189
|
```python
|
|
227
190
|
table.set_cell_formatting(
|
|
@@ -238,13 +201,7 @@ table.set_cell_formatting(
|
|
|
238
201
|
)
|
|
239
202
|
```
|
|
240
203
|
|
|
241
|
-
Custom formats are shared across a Document and can be applied to
|
|
242
|
-
multiple cells in multiple tables. Editing a custom format changes the
|
|
243
|
-
appearance of data in all cells that share that format. You must first
|
|
244
|
-
add a custom format to the document using
|
|
245
|
-
[Document.add_custom_format()](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_custom_format)
|
|
246
|
-
before assigning it to cells using
|
|
247
|
-
[Table.set_cell_formatting()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_formatting):
|
|
204
|
+
Custom formats are shared across a Document and can be applied to multiple cells in multiple tables. Editing a custom format changes the appearance of data in all cells that share that format. You must first add a custom format to the document using [Document.add_custom_format()](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_custom_format) before assigning it to cells using [Table.set_cell_formatting()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_formatting):
|
|
248
205
|
|
|
249
206
|
```python
|
|
250
207
|
long_date = doc.add_custom_format(
|
|
@@ -255,33 +212,17 @@ long_date = doc.add_custom_format(
|
|
|
255
212
|
table.set_cell_formatting("C1", "custom", format=long_date)
|
|
256
213
|
```
|
|
257
214
|
|
|
258
|
-
A limited number of currencies are formatted using symbolic notation
|
|
259
|
-
rather than an ISO code. These are defined in
|
|
260
|
-
`numbers_parser.currencies` and match the ones chosen by Numbers. For
|
|
261
|
-
example, US dollars are referred to as `US$` whereas Euros and British
|
|
262
|
-
Pounds are referred to using their symbols of `€` and `£`
|
|
263
|
-
respectively.
|
|
215
|
+
A limited number of currencies are formatted using symbolic notation rather than an ISO code. These are defined in `numbers_parser.currencies` and match the ones chosen by Numbers. For example, US dollars are referred to as `US$` whereas Euros and British Pounds are referred to using their symbols of `€` and `£` respectively.
|
|
264
216
|
|
|
265
217
|
### Borders
|
|
266
218
|
|
|
267
|
-
`numbers-parser` supports reading and writing cell borders, though the
|
|
268
|
-
interface for each differs. Individual cells can have each of their four
|
|
269
|
-
borders tested, but when drawing new borders, these are set for the
|
|
270
|
-
table to allow for drawing borders across multiple cells. Setting the
|
|
271
|
-
border of merged cells is not possible unless the edge of the cells is
|
|
272
|
-
at the end of the merged region.
|
|
219
|
+
`numbers-parser` supports reading and writing cell borders, though the interface for each differs. Individual cells can have each of their four borders tested, but when drawing new borders, these are set for the table to allow for drawing borders across multiple cells. Setting the border of merged cells is not possible unless the edge of the cells is at the end of the merged region.
|
|
273
220
|
|
|
274
|
-
Borders are represented using the [Border](https://masaccio.github.io/numbers-parser/api/border.html) class
|
|
275
|
-
that can be initialized with line width, color and line style. The
|
|
276
|
-
current state of a cell border is read using the
|
|
277
|
-
[Cell.border](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.Cell.border) property
|
|
278
|
-
and [Table.set_cell_border()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_border)
|
|
279
|
-
sets the border for a cell edge or a range of cells.
|
|
221
|
+
Borders are represented using the [Border](https://masaccio.github.io/numbers-parser/api/border.html) class that can be initialized with line width, color and line style. The current state of a cell border is read using the [Cell.border](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.Cell.border) property and [Table.set_cell_border()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_border) sets the border for a cell edge or a range of cells.
|
|
280
222
|
|
|
281
223
|
## API
|
|
282
224
|
|
|
283
|
-
For more examples and details of all available classes and methods,
|
|
284
|
-
see the [full API docs](https://masaccio.github.io/numbers-parser/).
|
|
225
|
+
For more examples and details of all available classes and methods, see the [full API docs](https://masaccio.github.io/numbers-parser/).
|
|
285
226
|
|
|
286
227
|
## Command-line scripts
|
|
287
228
|
|
|
@@ -294,9 +235,7 @@ a number of command-line scripts are installed:
|
|
|
294
235
|
|
|
295
236
|
### cat-numbers
|
|
296
237
|
|
|
297
|
-
This script dumps Numbers spreadsheets into Excel-compatible CSV
|
|
298
|
-
format, iterating through all the spreadsheets passed on the
|
|
299
|
-
command-line.
|
|
238
|
+
This script dumps Numbers spreadsheets into Excel-compatible CSV format, iterating through all the spreadsheets passed on the command-line.
|
|
300
239
|
|
|
301
240
|
```text
|
|
302
241
|
usage: cat-numbers [-h] [-T | -S | -b] [-V] [--formulas] [--formatting]
|
|
@@ -325,25 +264,17 @@ options:
|
|
|
325
264
|
--debug Enable debug logging
|
|
326
265
|
```
|
|
327
266
|
|
|
328
|
-
Note: `--formatting` will return different capitalization for 12-hour
|
|
329
|
-
times due to differences between Numbers’ representation of these dates
|
|
330
|
-
and `datetime.strftime`. Numbers in English locales displays 12-hour
|
|
331
|
-
times with ‘am’ and ‘pm’, but `datetime.strftime` on macOS at least
|
|
332
|
-
cannot return lower-case versions of AM/PM.
|
|
267
|
+
Note: `--formatting` will return different capitalization for 12-hour times due to differences between Numbers’ representation of these dates and `datetime.strftime`. Numbers in English locales displays 12-hour times with ‘am’ and ‘pm’, but `datetime.strftime` on macOS at least cannot return lower-case versions of AM/PM.
|
|
333
268
|
|
|
334
269
|
### csv2numbers
|
|
335
270
|
|
|
336
|
-
This script converts Excel-compatible CSV files into Numbers documents. Output files
|
|
337
|
-
can optionally be provided, but is none are provided, the output is created by replacing
|
|
338
|
-
the input’s files suffix with .numbers. For example:
|
|
271
|
+
This script converts Excel-compatible CSV files into Numbers documents. Output files can optionally be provided, but is none are provided, the output is created by replacing the input’s files suffix with .numbers. For example:
|
|
339
272
|
|
|
340
273
|
```text
|
|
341
274
|
csv2numbers file1.csv file2.csv -o file1.numbers file2.numbers
|
|
342
275
|
```
|
|
343
276
|
|
|
344
|
-
Columns of data can have a number of transformations applied to them. The primary use-
|
|
345
|
-
case intended for `csv2numbers` is converting banking exports to well-formatted
|
|
346
|
-
spreadsheets.
|
|
277
|
+
Columns of data can have a number of transformations applied to them. The primary use- case intended for `csv2numbers` is converting banking exports to well-formatted spreadsheets.
|
|
347
278
|
|
|
348
279
|
```text
|
|
349
280
|
usage: csv2numbers [-h] [-V] [--whitespace] [--reverse] [--no-header]
|
|
@@ -431,39 +362,22 @@ csv2numbers --transform='Category=LOOKUP:Transaction;mapping.numbers' file1.csv
|
|
|
431
362
|
|
|
432
363
|
Current known limitations of `numbers-parser` which may be implemented in the future are:
|
|
433
364
|
|
|
434
|
-
- Table styles that allow new tables to adopt a style across the whole
|
|
435
|
-
table are not suppported
|
|
365
|
+
- Table styles that allow new tables to adopt a style across the whole table are not supported
|
|
436
366
|
- Creating cells of type `BulletedTextCell` is not supported
|
|
437
|
-
- New tables are inserted with a fixed offset below the last table in a
|
|
438
|
-
|
|
439
|
-
- Captions can be created and edited as of numbers-parser version 4.12, but cannot
|
|
440
|
-
be styled. New captions adopt the first caption style available in the current
|
|
441
|
-
document
|
|
367
|
+
- New tables are inserted with a fixed offset below the last table in a worksheet which does not take into account title or caption size
|
|
368
|
+
- Captions can be created and edited as of numbers-parser version 4.12, but cannot be styled. New captions adopt the first caption style available in the current document
|
|
442
369
|
- Formulas cannot be written to a document
|
|
443
|
-
- Pivot tables are unsupported and saving a document with a pivot table issues
|
|
444
|
-
|
|
370
|
+
- Pivot tables are unsupported and saving a document with a pivot table issues a UnsupportedWarning (see [issue 73](https://github.com/masaccio/numbers-parser/issues/73) for details).
|
|
371
|
+
- Tables which have been saved grouped cannot be safely edited as references to written cells refer to the ungrouped cell rows rather than the row number in the groups.
|
|
445
372
|
|
|
446
373
|
The following limitations are expected to always remain:
|
|
447
374
|
|
|
448
|
-
- New sheets insert tables with formats copied from the first table in
|
|
449
|
-
|
|
450
|
-
-
|
|
451
|
-
|
|
452
|
-
versions older than 3.11 do not support image filenames with UTF-8 characters
|
|
453
|
-
[Cell.add_style.bg_image()](https://masaccio.github.io/numbers-parser/api/sheet.html#numbers_parser.Style) returns
|
|
454
|
-
`None` for such files and issues a `RuntimeWarning`
|
|
455
|
-
(see [issue 69](https://github.com/masaccio/numbers-parser/issues/69) for details).
|
|
456
|
-
- Password-encrypted documents cannot be opened. You must first re-save without
|
|
457
|
-
a password to read (see [issue 88](https://github.com/masaccio/numbers-parser/issues/88) for details).
|
|
458
|
-
A UnsupportedError exception is raised when such documents are opened.
|
|
459
|
-
- Due to changes in the format of Numbers documents, decoding of category groups
|
|
460
|
-
(introduced in `numbers-parser` version 4.16) is supported only for documents
|
|
461
|
-
created by Numbers 12.0 and later. No warnings are issued for earlier
|
|
375
|
+
- New sheets insert tables with formats copied from the first table in the previous sheet rather than default table formats
|
|
376
|
+
- Due to a limitation in Python’s [ZipFile](https://docs.python.org/3/library/zipfile.html), Python versions older than 3.11 do not support image filenames with UTF-8 characters [Cell.add_style.bg_image()](https://masaccio.github.io/numbers-parser/api/sheet.html#numbers_parser.Style) returns `None` for such files and issues a `RuntimeWarning` (see [issue 69](https://github.com/masaccio/numbers-parser/issues/69) for details).
|
|
377
|
+
- Password-encrypted documents cannot be opened. You must first re-save without a password to read (see [issue 88](https://github.com/masaccio/numbers-parser/issues/88) for details). A UnsupportedError exception is raised when such documents are opened.
|
|
378
|
+
- Due to changes in the format of Numbers documents, decoding of category groups (introduced in `numbers-parser` version 4.16) is supported only for documents created by Numbers 12.0 and later. No warnings are issued for earlier
|
|
462
379
|
Numbers documents.
|
|
463
|
-
- Only standard macOS fonts are not supported. If a document includes a non-standard
|
|
464
|
-
font, numbers-parser will issue a UnsupportedWarning and default styles to
|
|
465
|
-
Helvetica Neue. Reading font names from the system would add additional system-specific
|
|
466
|
-
dependencies to the package and so this is not planned to changed.
|
|
380
|
+
- Only standard macOS fonts are not supported. If a document includes a non-standard font, numbers-parser will issue a UnsupportedWarning and default styles to Helvetica Neue. Reading font names from the system would add additional system-specific dependencies to the package and so this is not planned to changed.
|
|
467
381
|
|
|
468
382
|
## License
|
|
469
383
|
|
|
@@ -22,7 +22,7 @@ classifiers = [
|
|
|
22
22
|
description = "Read and write Apple Numbers spreadsheets"
|
|
23
23
|
name = "numbers-parser"
|
|
24
24
|
readme = "README.md"
|
|
25
|
-
version = "4.
|
|
25
|
+
version = "4.18.1"
|
|
26
26
|
|
|
27
27
|
[project.urls]
|
|
28
28
|
repository = "https://github.com/masaccio/numbers-parser"
|
|
@@ -197,5 +197,5 @@ ban-relative-imports = "all"
|
|
|
197
197
|
"src/build/**" = ["PLR2004", "INP001", "PTH"]
|
|
198
198
|
"src/build/protodump.py" = ["PLR2004", "INP001", "PTH", "S110", "N806"]
|
|
199
199
|
"src/debug/**" = ["INP001"]
|
|
200
|
-
"tests/**" = ["PLR2004", "S101", "D103", "ANN201", "ANN001"]
|
|
200
|
+
"tests/**" = ["PLR2004", "S101", "D103", "ANN201", "ANN001", "DTZ001"]
|
|
201
201
|
|
|
@@ -16,11 +16,19 @@ from numbers_parser import (
|
|
|
16
16
|
)
|
|
17
17
|
from numbers_parser import __name__ as numbers_parser_name
|
|
18
18
|
from numbers_parser.constants import MAX_SIGNIFICANT_DIGITS
|
|
19
|
-
from numbers_parser.experimental import
|
|
19
|
+
from numbers_parser.experimental import ExperimentalFeatures, enable_experimental_feature
|
|
20
20
|
|
|
21
21
|
logger = logging.getLogger(numbers_parser_name)
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
def experimental_feature_choice(s: str) -> ExperimentalFeatures:
|
|
25
|
+
try:
|
|
26
|
+
return ExperimentalFeatures[s]
|
|
27
|
+
except KeyError:
|
|
28
|
+
msg = f"invalid experimental feature: {s}"
|
|
29
|
+
raise argparse.ArgumentTypeError(msg) # noqa: B904
|
|
30
|
+
|
|
31
|
+
|
|
24
32
|
def command_line_parser():
|
|
25
33
|
parser = argparse.ArgumentParser(
|
|
26
34
|
description="Export data from Apple Numbers spreadsheet tables",
|
|
@@ -70,10 +78,13 @@ def command_line_parser():
|
|
|
70
78
|
)
|
|
71
79
|
parser.add_argument("document", nargs="*", help="Document(s) to export")
|
|
72
80
|
parser.add_argument("--debug", default=False, action="store_true", help="Enable debug logging")
|
|
81
|
+
experimental_choices = [
|
|
82
|
+
f.name for f in ExperimentalFeatures if f is not ExperimentalFeatures.NONE
|
|
83
|
+
]
|
|
73
84
|
parser.add_argument(
|
|
74
85
|
"--experimental",
|
|
75
|
-
|
|
76
|
-
|
|
86
|
+
type=experimental_feature_choice,
|
|
87
|
+
choices=[ExperimentalFeatures[name] for name in experimental_choices],
|
|
77
88
|
help=argparse.SUPPRESS,
|
|
78
89
|
)
|
|
79
90
|
return parser
|
|
@@ -136,7 +147,7 @@ def main() -> None:
|
|
|
136
147
|
else:
|
|
137
148
|
logger.setLevel("ERROR")
|
|
138
149
|
if args.experimental:
|
|
139
|
-
|
|
150
|
+
enable_experimental_feature(args.experimental)
|
|
140
151
|
for filename in args.document:
|
|
141
152
|
try:
|
|
142
153
|
if args.list_sheets:
|