numbers-parser 4.14.1__py3-none-any.whl → 4.14.3__py3-none-any.whl
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/__init__.py +3 -3
- numbers_parser/_cat_numbers.py +10 -11
- numbers_parser/_csv2numbers.py +13 -14
- numbers_parser/_unpack_numbers.py +4 -4
- numbers_parser/cell.py +257 -229
- numbers_parser/constants.py +6 -3
- numbers_parser/containers.py +11 -10
- numbers_parser/document.py +199 -151
- numbers_parser/exceptions.py +1 -8
- numbers_parser/formula.py +28 -30
- numbers_parser/generated/TSKArchives_pb2.py +92 -92
- numbers_parser/generated/TSSArchives_pb2.py +36 -36
- numbers_parser/generated/TSWPCommandArchives_pb2.py +99 -99
- numbers_parser/generated/fontmap.py +16 -10
- numbers_parser/generated/mapping.py +0 -1
- numbers_parser/iwafile.py +16 -16
- numbers_parser/iwork.py +32 -17
- numbers_parser/model.py +224 -212
- numbers_parser/numbers_cache.py +6 -7
- numbers_parser/numbers_uuid.py +4 -1
- numbers_parser/roman.py +21 -7
- {numbers_parser-4.14.1.dist-info → numbers_parser-4.14.3.dist-info}/METADATA +16 -3
- {numbers_parser-4.14.1.dist-info → numbers_parser-4.14.3.dist-info}/RECORD +26 -26
- {numbers_parser-4.14.1.dist-info → numbers_parser-4.14.3.dist-info}/LICENSE.rst +0 -0
- {numbers_parser-4.14.1.dist-info → numbers_parser-4.14.3.dist-info}/WHEEL +0 -0
- {numbers_parser-4.14.1.dist-info → numbers_parser-4.14.3.dist-info}/entry_points.txt +0 -0
numbers_parser/document.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
2
3
|
from pathlib import Path
|
|
3
|
-
from typing import
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
4
5
|
from warnings import warn
|
|
5
6
|
|
|
6
7
|
from numbers_parser.cell import (
|
|
@@ -33,19 +34,24 @@ from numbers_parser.containers import ItemsList
|
|
|
33
34
|
from numbers_parser.model import _NumbersModel
|
|
34
35
|
from numbers_parser.numbers_cache import Cacheable
|
|
35
36
|
|
|
37
|
+
if TYPE_CHECKING: # pragma: nocover
|
|
38
|
+
from collections.abc import Iterator
|
|
39
|
+
from datetime import datetime, timedelta
|
|
40
|
+
|
|
36
41
|
__all__ = ["Document", "Sheet", "Table"]
|
|
37
42
|
|
|
38
43
|
|
|
39
|
-
class Sheet:
|
|
40
|
-
|
|
44
|
+
# class Sheet:
|
|
45
|
+
# pass
|
|
41
46
|
|
|
42
47
|
|
|
43
|
-
class Table:
|
|
44
|
-
|
|
48
|
+
# class Table:
|
|
49
|
+
# pass
|
|
45
50
|
|
|
46
51
|
|
|
47
52
|
class Document:
|
|
48
|
-
"""
|
|
53
|
+
"""
|
|
54
|
+
Create an instance of a new Numbers document.
|
|
49
55
|
|
|
50
56
|
If ``filename`` is ``None``, an empty document is created using the defaults
|
|
51
57
|
defined by the class constructor. You can optionionally override these
|
|
@@ -74,17 +80,20 @@ class Document:
|
|
|
74
80
|
If the sheet name already exists in the document.
|
|
75
81
|
IndexError:
|
|
76
82
|
If the table name already exists in the first sheet.
|
|
83
|
+
UnsupportedError:
|
|
84
|
+
If the document is encrypted.
|
|
85
|
+
|
|
77
86
|
"""
|
|
78
87
|
|
|
79
|
-
def __init__(
|
|
88
|
+
def __init__(
|
|
80
89
|
self,
|
|
81
|
-
filename:
|
|
82
|
-
sheet_name:
|
|
83
|
-
table_name:
|
|
84
|
-
num_header_rows:
|
|
85
|
-
num_header_cols:
|
|
86
|
-
num_rows:
|
|
87
|
-
num_cols:
|
|
90
|
+
filename: str | Path | None = None,
|
|
91
|
+
sheet_name: str | None = "Sheet 1",
|
|
92
|
+
table_name: str | None = "Table 1",
|
|
93
|
+
num_header_rows: int | None = 1,
|
|
94
|
+
num_header_cols: int | None = 1,
|
|
95
|
+
num_rows: int | None = DEFAULT_ROW_COUNT,
|
|
96
|
+
num_cols: int | None = DEFAULT_COLUMN_COUNT,
|
|
88
97
|
) -> None:
|
|
89
98
|
self._model = _NumbersModel(None if filename is None else Path(filename))
|
|
90
99
|
refs = self._model.sheet_ids()
|
|
@@ -102,7 +111,7 @@ class Document:
|
|
|
102
111
|
table.num_header_cols = num_header_cols
|
|
103
112
|
|
|
104
113
|
@property
|
|
105
|
-
def sheets(self) ->
|
|
114
|
+
def sheets(self) -> list[Sheet]:
|
|
106
115
|
"""List[:class:`Sheet`]: A list of sheets in the document."""
|
|
107
116
|
return self._sheets
|
|
108
117
|
|
|
@@ -112,19 +121,21 @@ class Document:
|
|
|
112
121
|
return self.sheets[0].tables[0]
|
|
113
122
|
|
|
114
123
|
@property
|
|
115
|
-
def styles(self) ->
|
|
124
|
+
def styles(self) -> dict[str, Style]:
|
|
116
125
|
"""Dict[str, :class:`Style`]: A dict mapping style names to to the corresponding style."""
|
|
117
126
|
return self._model.styles
|
|
118
127
|
|
|
119
128
|
@property
|
|
120
|
-
def custom_formats(self) ->
|
|
121
|
-
"""
|
|
129
|
+
def custom_formats(self) -> dict[str, CustomFormatting]:
|
|
130
|
+
"""
|
|
131
|
+
Dict[str, :class:`CustomFormatting`]: A dict mapping custom format names
|
|
122
132
|
to the corresponding custom format.
|
|
123
133
|
"""
|
|
124
134
|
return self._model.custom_formats
|
|
125
135
|
|
|
126
|
-
def save(self, filename:
|
|
127
|
-
"""
|
|
136
|
+
def save(self, filename: str | Path, package: bool = False) -> None:
|
|
137
|
+
"""
|
|
138
|
+
Save the document in the specified filename.
|
|
128
139
|
|
|
129
140
|
Parameters
|
|
130
141
|
----------
|
|
@@ -140,6 +151,7 @@ class Document:
|
|
|
140
151
|
FileFormatError:
|
|
141
152
|
If attempting to write a package into a folder that is not an
|
|
142
153
|
existing Numbers document.
|
|
154
|
+
|
|
143
155
|
"""
|
|
144
156
|
for sheet in self.sheets:
|
|
145
157
|
for table in sheet.tables:
|
|
@@ -156,12 +168,13 @@ class Document:
|
|
|
156
168
|
|
|
157
169
|
def add_sheet(
|
|
158
170
|
self,
|
|
159
|
-
sheet_name:
|
|
160
|
-
table_name:
|
|
161
|
-
num_rows:
|
|
162
|
-
num_cols:
|
|
171
|
+
sheet_name: str | None = None,
|
|
172
|
+
table_name: str | None = "Table 1",
|
|
173
|
+
num_rows: int | None = DEFAULT_ROW_COUNT,
|
|
174
|
+
num_cols: int | None = DEFAULT_COLUMN_COUNT,
|
|
163
175
|
) -> None:
|
|
164
|
-
"""
|
|
176
|
+
"""
|
|
177
|
+
Add a new sheet to the current document.
|
|
165
178
|
|
|
166
179
|
If no sheet name is provided, the next available numbered sheet
|
|
167
180
|
will be generated in the series ``Sheet 1``, ``Sheet 2``, etc.
|
|
@@ -180,6 +193,7 @@ class Document:
|
|
|
180
193
|
Raises
|
|
181
194
|
------
|
|
182
195
|
IndexError: If the sheet name already exists in the document.
|
|
196
|
+
|
|
183
197
|
"""
|
|
184
198
|
if sheet_name is not None:
|
|
185
199
|
if sheet_name in self._sheets:
|
|
@@ -211,7 +225,8 @@ class Document:
|
|
|
211
225
|
self._sheets.append(new_sheet)
|
|
212
226
|
|
|
213
227
|
def add_style(self, **kwargs) -> Style:
|
|
214
|
-
r"""
|
|
228
|
+
r"""
|
|
229
|
+
Add a new style to the current document.
|
|
215
230
|
|
|
216
231
|
If no style name is provided, the next available numbered style
|
|
217
232
|
will be generated in the series ``Custom Style 1``, ``Custom Style 2``, etc.
|
|
@@ -241,6 +256,7 @@ class Document:
|
|
|
241
256
|
If ``font_size`` is not a ``float``, ``font_name`` is not a ``str``,
|
|
242
257
|
``bg_image`` is not a :py:class:`~numbers_parser.BackgroundImage`,
|
|
243
258
|
or if any of the ``bool`` parameters are invalid.
|
|
259
|
+
|
|
244
260
|
"""
|
|
245
261
|
if "name" in kwargs and kwargs["name"] is not None and kwargs["name"] in self._model.styles:
|
|
246
262
|
msg = f"style '{kwargs['name']}' already exists"
|
|
@@ -260,13 +276,14 @@ class Document:
|
|
|
260
276
|
return style
|
|
261
277
|
|
|
262
278
|
def add_custom_format(self, **kwargs) -> CustomFormatting:
|
|
263
|
-
r"""
|
|
279
|
+
r"""
|
|
280
|
+
Add a new custom format to the current document.
|
|
264
281
|
|
|
265
282
|
.. code-block:: python
|
|
266
283
|
|
|
267
284
|
long_date = doc.add_custom_format(
|
|
268
285
|
name="Long Date",
|
|
269
|
-
type="
|
|
286
|
+
type="datetime",
|
|
270
287
|
date_time_format="EEEE, d MMMM yyyy"
|
|
271
288
|
)
|
|
272
289
|
table.set_cell_formatting("C1", "custom", format=long_date)
|
|
@@ -276,9 +293,9 @@ class Document:
|
|
|
276
293
|
depending upon the value of ``kwargs["type"]``.
|
|
277
294
|
|
|
278
295
|
:Common Args:
|
|
279
|
-
* **name** (``str``)
|
|
296
|
+
* **name** (``str``) - The name of the custom format. If no name is provided,
|
|
280
297
|
one is generated using the scheme ``Custom Format``, ``Custom Format 1``, ``Custom Format 2``, etc.
|
|
281
|
-
* **type** (``str``, *optional*, default: ``number``)
|
|
298
|
+
* **type** (``str``, *optional*, default: ``number``) - The type of format to
|
|
282
299
|
create:
|
|
283
300
|
|
|
284
301
|
* ``"datetime"``: A date and time value with custom formatting.
|
|
@@ -286,26 +303,26 @@ class Document:
|
|
|
286
303
|
* ``"text"``: A simple text string.
|
|
287
304
|
|
|
288
305
|
:``"number"``:
|
|
289
|
-
* **integer_format** (``PaddingType``, *optional*, default: ``PaddingType.NONE``)
|
|
306
|
+
* **integer_format** (``PaddingType``, *optional*, default: ``PaddingType.NONE``) - How
|
|
290
307
|
to pad integers.
|
|
291
|
-
* **decimal_format** (``PaddingType``, *optional*, default: ``PaddingType.NONE``)
|
|
308
|
+
* **decimal_format** (``PaddingType``, *optional*, default: ``PaddingType.NONE``) - How
|
|
292
309
|
to pad decimals.
|
|
293
|
-
* **num_integers** (``int``, *optional*, default: ``0``)
|
|
310
|
+
* **num_integers** (``int``, *optional*, default: ``0``) - Integer precision
|
|
294
311
|
when integers are padded.
|
|
295
|
-
* **num_decimals** (``int``, *optional*, default: ``0``)
|
|
312
|
+
* **num_decimals** (``int``, *optional*, default: ``0``) - Integer precision
|
|
296
313
|
when decimals are padded.
|
|
297
|
-
* **show_thousands_separator** (``bool``, *optional*, default: ``False``)
|
|
314
|
+
* **show_thousands_separator** (``bool``, *optional*, default: ``False``) - ``True``
|
|
298
315
|
if the number should include a thousands seperator.
|
|
299
316
|
|
|
300
317
|
:``"datetime"``:
|
|
301
|
-
* **format** (``str``, *optional*, default: ``"d MMM y"``)
|
|
318
|
+
* **format** (``str``, *optional*, default: ``"d MMM y"``) - A POSIX strftime-like
|
|
302
319
|
formatting string of `Numbers date/time directives <#datetime-formats>`_.
|
|
303
320
|
|
|
304
321
|
:``"text"``:
|
|
305
|
-
* **format** (``str``, *optional*, default: ``"%s"``)
|
|
322
|
+
* **format** (``str``, *optional*, default: ``"%s"``) - Text format.
|
|
306
323
|
The cell value is inserted in place of %s. Only one substitution is allowed by
|
|
307
324
|
Numbers, and multiple %s formatting references raise a TypeError exception
|
|
308
|
-
"""
|
|
325
|
+
"""
|
|
309
326
|
if (
|
|
310
327
|
"name" in kwargs
|
|
311
328
|
and kwargs["name"] is not None
|
|
@@ -342,7 +359,7 @@ class Sheet:
|
|
|
342
359
|
self._tables = ItemsList(self._model, refs, Table)
|
|
343
360
|
|
|
344
361
|
@property
|
|
345
|
-
def tables(self) ->
|
|
362
|
+
def tables(self) -> list[Table]:
|
|
346
363
|
"""List[:class:`Table`]: A list of tables in the sheet."""
|
|
347
364
|
return self._tables
|
|
348
365
|
|
|
@@ -352,18 +369,19 @@ class Sheet:
|
|
|
352
369
|
return self._model.sheet_name(self._sheet_id)
|
|
353
370
|
|
|
354
371
|
@name.setter
|
|
355
|
-
def name(self, value: str):
|
|
372
|
+
def name(self, value: str) -> None:
|
|
356
373
|
self._model.sheet_name(self._sheet_id, value)
|
|
357
374
|
|
|
358
|
-
def add_table(
|
|
375
|
+
def add_table(
|
|
359
376
|
self,
|
|
360
|
-
table_name:
|
|
361
|
-
x:
|
|
362
|
-
y:
|
|
363
|
-
num_rows:
|
|
364
|
-
num_cols:
|
|
377
|
+
table_name: str | None = None,
|
|
378
|
+
x: float | None = None,
|
|
379
|
+
y: float | None = None,
|
|
380
|
+
num_rows: int | None = DEFAULT_ROW_COUNT,
|
|
381
|
+
num_cols: int | None = DEFAULT_COLUMN_COUNT,
|
|
365
382
|
) -> Table:
|
|
366
|
-
"""
|
|
383
|
+
"""
|
|
384
|
+
Add a new table to the current sheet.
|
|
367
385
|
|
|
368
386
|
If no table name is provided, the next available numbered table
|
|
369
387
|
will be generated in the series ``Table 1``, ``Table 2``, etc.
|
|
@@ -402,11 +420,12 @@ class Sheet:
|
|
|
402
420
|
Raises
|
|
403
421
|
------
|
|
404
422
|
IndexError: If the table name already exists.
|
|
423
|
+
|
|
405
424
|
"""
|
|
406
425
|
from_table_id = self._tables[-1]._table_id
|
|
407
426
|
return self._add_table(table_name, from_table_id, x, y, num_rows, num_cols)
|
|
408
427
|
|
|
409
|
-
def _add_table(
|
|
428
|
+
def _add_table(
|
|
410
429
|
self,
|
|
411
430
|
table_name,
|
|
412
431
|
from_table_id,
|
|
@@ -470,7 +489,7 @@ class Table(Cacheable):
|
|
|
470
489
|
return self._model.table_name(self._table_id)
|
|
471
490
|
|
|
472
491
|
@name.setter
|
|
473
|
-
def name(self, value: str):
|
|
492
|
+
def name(self, value: str) -> None:
|
|
474
493
|
self._model.table_name(self._table_id, value)
|
|
475
494
|
|
|
476
495
|
@property
|
|
@@ -479,7 +498,7 @@ class Table(Cacheable):
|
|
|
479
498
|
return self._model.table_name_enabled(self._table_id)
|
|
480
499
|
|
|
481
500
|
@table_name_enabled.setter
|
|
482
|
-
def table_name_enabled(self, enabled: bool):
|
|
501
|
+
def table_name_enabled(self, enabled: bool) -> None:
|
|
483
502
|
self._model.table_name_enabled(self._table_id, enabled)
|
|
484
503
|
|
|
485
504
|
@property
|
|
@@ -502,7 +521,8 @@ class Table(Cacheable):
|
|
|
502
521
|
|
|
503
522
|
@property
|
|
504
523
|
def num_header_rows(self) -> int:
|
|
505
|
-
"""
|
|
524
|
+
"""
|
|
525
|
+
int: The number of header rows.
|
|
506
526
|
|
|
507
527
|
Example
|
|
508
528
|
-------
|
|
@@ -516,6 +536,7 @@ class Table(Cacheable):
|
|
|
516
536
|
ValueError:
|
|
517
537
|
If the number of headers is negative, exceeds the number of rows in the
|
|
518
538
|
table, or exceeds Numbers maxinum number of headers (``MAX_HEADER_COUNT``).
|
|
539
|
+
|
|
519
540
|
"""
|
|
520
541
|
return self._model.num_header_rows(self._table_id)
|
|
521
542
|
|
|
@@ -524,17 +545,18 @@ class Table(Cacheable):
|
|
|
524
545
|
if num_headers < 0:
|
|
525
546
|
msg = "Number of headers cannot be negative"
|
|
526
547
|
raise ValueError(msg)
|
|
527
|
-
|
|
548
|
+
if num_headers > self.num_rows:
|
|
528
549
|
msg = "Number of headers cannot exceed the number of rows"
|
|
529
550
|
raise ValueError(msg)
|
|
530
|
-
|
|
551
|
+
if num_headers > MAX_HEADER_COUNT:
|
|
531
552
|
msg = f"Number of headers cannot exceed {MAX_HEADER_COUNT} rows"
|
|
532
553
|
raise ValueError(msg)
|
|
533
554
|
return self._model.num_header_rows(self._table_id, num_headers)
|
|
534
555
|
|
|
535
556
|
@property
|
|
536
557
|
def num_header_cols(self) -> int:
|
|
537
|
-
"""
|
|
558
|
+
"""
|
|
559
|
+
int: The number of header columns.
|
|
538
560
|
|
|
539
561
|
Example
|
|
540
562
|
-------
|
|
@@ -548,6 +570,7 @@ class Table(Cacheable):
|
|
|
548
570
|
ValueError:
|
|
549
571
|
If the number of headers is negative, exceeds the number of rows in the
|
|
550
572
|
table, or exceeds Numbers maxinum number of headers (``MAX_HEADER_COUNT``).
|
|
573
|
+
|
|
551
574
|
"""
|
|
552
575
|
return self._model.num_header_cols(self._table_id)
|
|
553
576
|
|
|
@@ -556,10 +579,10 @@ class Table(Cacheable):
|
|
|
556
579
|
if num_headers < 0:
|
|
557
580
|
msg = "Number of headers cannot be negative"
|
|
558
581
|
raise ValueError(msg)
|
|
559
|
-
|
|
582
|
+
if num_headers > self.num_cols:
|
|
560
583
|
msg = "Number of headers cannot exceed the number of columns"
|
|
561
584
|
raise ValueError(msg)
|
|
562
|
-
|
|
585
|
+
if num_headers > MAX_HEADER_COUNT:
|
|
563
586
|
msg = f"Number of headers cannot exceed {MAX_HEADER_COUNT} columns"
|
|
564
587
|
raise ValueError(msg)
|
|
565
588
|
return self._model.num_header_cols(self._table_id, num_headers)
|
|
@@ -574,8 +597,9 @@ class Table(Cacheable):
|
|
|
574
597
|
"""int: The table's width in points."""
|
|
575
598
|
return self._model.table_width(self._table_id)
|
|
576
599
|
|
|
577
|
-
def row_height(self, row: int, height:
|
|
578
|
-
"""
|
|
600
|
+
def row_height(self, row: int, height: int | None = None) -> int:
|
|
601
|
+
"""
|
|
602
|
+
The height of a table row in points.
|
|
579
603
|
|
|
580
604
|
.. code-block:: python
|
|
581
605
|
|
|
@@ -593,11 +617,13 @@ class Table(Cacheable):
|
|
|
593
617
|
-------
|
|
594
618
|
int:
|
|
595
619
|
The height of the table row.
|
|
620
|
+
|
|
596
621
|
"""
|
|
597
622
|
return self._model.row_height(self._table_id, row, height)
|
|
598
623
|
|
|
599
|
-
def col_width(self, col: int, width:
|
|
600
|
-
"""
|
|
624
|
+
def col_width(self, col: int, width: int | None = None) -> int:
|
|
625
|
+
"""
|
|
626
|
+
The width of a table column in points.
|
|
601
627
|
|
|
602
628
|
Parameters
|
|
603
629
|
----------
|
|
@@ -610,16 +636,18 @@ class Table(Cacheable):
|
|
|
610
636
|
-------
|
|
611
637
|
int:
|
|
612
638
|
The width of the table column.
|
|
639
|
+
|
|
613
640
|
"""
|
|
614
641
|
return self._model.col_width(self._table_id, col, width)
|
|
615
642
|
|
|
616
643
|
@property
|
|
617
|
-
def coordinates(self) ->
|
|
644
|
+
def coordinates(self) -> tuple[float]:
|
|
618
645
|
"""Tuple[float]: The table's x, y offsets in points."""
|
|
619
646
|
return self._model.table_coordinates(self._table_id)
|
|
620
647
|
|
|
621
|
-
def rows(self, values_only: bool = False) ->
|
|
622
|
-
"""
|
|
648
|
+
def rows(self, values_only: bool = False) -> list[list[Cell]] | list[list[str]]:
|
|
649
|
+
"""
|
|
650
|
+
Return all rows of cells for the Table.
|
|
623
651
|
|
|
624
652
|
Parameters
|
|
625
653
|
----------
|
|
@@ -630,15 +658,16 @@ class Table(Cacheable):
|
|
|
630
658
|
-------
|
|
631
659
|
List[List[Cell]] | List[List[str]]:
|
|
632
660
|
List of rows; each row is a list of :class:`Cell` objects, or string values.
|
|
661
|
+
|
|
633
662
|
"""
|
|
634
663
|
if values_only:
|
|
635
664
|
return [[cell.value for cell in row] for row in self._data]
|
|
636
|
-
|
|
637
|
-
return self._data
|
|
665
|
+
return self._data
|
|
638
666
|
|
|
639
667
|
@property
|
|
640
|
-
def merge_ranges(self) ->
|
|
641
|
-
"""
|
|
668
|
+
def merge_ranges(self) -> list[str]:
|
|
669
|
+
"""
|
|
670
|
+
List[str]: The merge ranges of cells in A1 notation.
|
|
642
671
|
|
|
643
672
|
Example
|
|
644
673
|
-------
|
|
@@ -650,6 +679,7 @@ class Table(Cacheable):
|
|
|
650
679
|
<numbers_parser.cell.TextCell object at 0x1035f4a90>
|
|
651
680
|
>>> table.cell("A5")
|
|
652
681
|
<numbers_parser.cell.MergedCell object at 0x1035f5310>
|
|
682
|
+
|
|
653
683
|
"""
|
|
654
684
|
merge_cells = set()
|
|
655
685
|
for row, cells in enumerate(self._data):
|
|
@@ -659,8 +689,9 @@ class Table(Cacheable):
|
|
|
659
689
|
merge_cells.add(xl_range(row, col, row + size[0] - 1, col + size[1] - 1))
|
|
660
690
|
return sorted(merge_cells)
|
|
661
691
|
|
|
662
|
-
def cell(self, *args) ->
|
|
663
|
-
"""
|
|
692
|
+
def cell(self, *args) -> Cell | MergedCell: # noqa: D417
|
|
693
|
+
"""
|
|
694
|
+
Return a single cell in the table.
|
|
664
695
|
|
|
665
696
|
The ``cell()`` method supports two forms of notation to designate the position
|
|
666
697
|
of cells: **Row-column** notation and **A1** notation:
|
|
@@ -699,6 +730,7 @@ class Table(Cacheable):
|
|
|
699
730
|
<numbers_parser.cell.TextCell object at 0x105a80b90>
|
|
700
731
|
>>> table.cell("B2").value
|
|
701
732
|
1234.50
|
|
733
|
+
|
|
702
734
|
"""
|
|
703
735
|
if isinstance(args[0], str):
|
|
704
736
|
(row, col) = xl_cell_to_rowcol(args[0])
|
|
@@ -716,15 +748,16 @@ class Table(Cacheable):
|
|
|
716
748
|
|
|
717
749
|
return self._data[row][col]
|
|
718
750
|
|
|
719
|
-
def iter_rows(
|
|
751
|
+
def iter_rows(
|
|
720
752
|
self,
|
|
721
|
-
min_row:
|
|
722
|
-
max_row:
|
|
723
|
-
min_col:
|
|
724
|
-
max_col:
|
|
725
|
-
values_only:
|
|
726
|
-
) -> Iterator[
|
|
727
|
-
"""
|
|
753
|
+
min_row: int | None = None,
|
|
754
|
+
max_row: int | None = None,
|
|
755
|
+
min_col: int | None = None,
|
|
756
|
+
max_col: int | None = None,
|
|
757
|
+
values_only: bool | None = False,
|
|
758
|
+
) -> Iterator[tuple[Cell] | tuple[str]]:
|
|
759
|
+
"""
|
|
760
|
+
Produces cells from a table, by row.
|
|
728
761
|
|
|
729
762
|
Specify the iteration range using the indexes of the rows and columns.
|
|
730
763
|
|
|
@@ -758,6 +791,7 @@ class Table(Cacheable):
|
|
|
758
791
|
|
|
759
792
|
for row in table.iter_rows(min_row=2, max_row=7, values_only=True):
|
|
760
793
|
sum += row
|
|
794
|
+
|
|
761
795
|
"""
|
|
762
796
|
min_row = min_row or 0
|
|
763
797
|
max_row = max_row or self.num_rows - 1
|
|
@@ -784,15 +818,16 @@ class Table(Cacheable):
|
|
|
784
818
|
else:
|
|
785
819
|
yield tuple(rows[row][min_col : max_col + 1])
|
|
786
820
|
|
|
787
|
-
def iter_cols(
|
|
821
|
+
def iter_cols(
|
|
788
822
|
self,
|
|
789
|
-
min_col:
|
|
790
|
-
max_col:
|
|
791
|
-
min_row:
|
|
792
|
-
max_row:
|
|
793
|
-
values_only:
|
|
794
|
-
) -> Iterator[
|
|
795
|
-
"""
|
|
823
|
+
min_col: int | None = None,
|
|
824
|
+
max_col: int | None = None,
|
|
825
|
+
min_row: int | None = None,
|
|
826
|
+
max_row: int | None = None,
|
|
827
|
+
values_only: bool | None = False,
|
|
828
|
+
) -> Iterator[tuple[Cell] | tuple[str]]:
|
|
829
|
+
"""
|
|
830
|
+
Produces cells from a table, by column.
|
|
796
831
|
|
|
797
832
|
Specify the iteration range using the indexes of the rows and columns.
|
|
798
833
|
|
|
@@ -826,6 +861,7 @@ class Table(Cacheable):
|
|
|
826
861
|
|
|
827
862
|
for col in table.iter_cols(min_row=2, max_row=7):
|
|
828
863
|
sum += col.value
|
|
864
|
+
|
|
829
865
|
"""
|
|
830
866
|
min_row = min_row or 0
|
|
831
867
|
max_row = max_row or self.num_rows - 1
|
|
@@ -877,8 +913,9 @@ class Table(Cacheable):
|
|
|
877
913
|
|
|
878
914
|
return (row, col, *tuple(values))
|
|
879
915
|
|
|
880
|
-
def write(self, *args, style:
|
|
881
|
-
"""
|
|
916
|
+
def write(self, *args, style: Style | str | None = None) -> None: # noqa: D417
|
|
917
|
+
"""
|
|
918
|
+
Write a value to a cell and update the style/cell type.
|
|
882
919
|
|
|
883
920
|
The ``write()`` method supports two forms of notation to designate the position
|
|
884
921
|
of cells: **Row-column** notation and **A1** notation:
|
|
@@ -919,6 +956,7 @@ class Table(Cacheable):
|
|
|
919
956
|
If the style parameter is an invalid type.
|
|
920
957
|
ValueError:
|
|
921
958
|
If the cell type cannot be determined from the type of `param3`.
|
|
959
|
+
|
|
922
960
|
"""
|
|
923
961
|
# TODO: write needs to retain/init the border
|
|
924
962
|
(row, col, value) = self._validate_cell_coords(*args)
|
|
@@ -933,7 +971,7 @@ class Table(Cacheable):
|
|
|
933
971
|
if style is not None:
|
|
934
972
|
self.set_cell_style(row, col, style)
|
|
935
973
|
|
|
936
|
-
def set_cell_style(self, *args):
|
|
974
|
+
def set_cell_style(self, *args) -> None:
|
|
937
975
|
(row, col, style) = self._validate_cell_coords(*args)
|
|
938
976
|
if isinstance(style, Style):
|
|
939
977
|
self._data[row][col]._style = style
|
|
@@ -948,11 +986,12 @@ class Table(Cacheable):
|
|
|
948
986
|
|
|
949
987
|
def add_row(
|
|
950
988
|
self,
|
|
951
|
-
num_rows:
|
|
952
|
-
start_row:
|
|
953
|
-
default:
|
|
989
|
+
num_rows: int | None = 1,
|
|
990
|
+
start_row: int | None = None,
|
|
991
|
+
default: str | float | bool | datetime | timedelta | None = None,
|
|
954
992
|
) -> None:
|
|
955
|
-
"""
|
|
993
|
+
"""
|
|
994
|
+
Add or insert rows to the table.
|
|
956
995
|
|
|
957
996
|
Parameters
|
|
958
997
|
----------
|
|
@@ -978,6 +1017,7 @@ class Table(Cacheable):
|
|
|
978
1017
|
If the start_row is out of range for the table.
|
|
979
1018
|
ValueError:
|
|
980
1019
|
If the default value is unsupported by :py:meth:`numbers_parser.Table.write`.
|
|
1020
|
+
|
|
981
1021
|
"""
|
|
982
1022
|
if start_row is not None and (start_row < 0 or start_row >= self.num_rows):
|
|
983
1023
|
msg = "Row number not in range for table"
|
|
@@ -994,7 +1034,7 @@ class Table(Cacheable):
|
|
|
994
1034
|
[
|
|
995
1035
|
Cell._empty_cell(self._table_id, row, col, self._model)
|
|
996
1036
|
for col in range(self.num_cols)
|
|
997
|
-
]
|
|
1037
|
+
],
|
|
998
1038
|
)
|
|
999
1039
|
self._data[start_row:start_row] = rows
|
|
1000
1040
|
|
|
@@ -1010,11 +1050,12 @@ class Table(Cacheable):
|
|
|
1010
1050
|
|
|
1011
1051
|
def add_column(
|
|
1012
1052
|
self,
|
|
1013
|
-
num_cols:
|
|
1014
|
-
start_col:
|
|
1015
|
-
default:
|
|
1053
|
+
num_cols: int | None = 1,
|
|
1054
|
+
start_col: int | None = None,
|
|
1055
|
+
default: str | float | bool | datetime | timedelta | None = None,
|
|
1016
1056
|
) -> None:
|
|
1017
|
-
"""
|
|
1057
|
+
"""
|
|
1058
|
+
Add or insert columns to the table.
|
|
1018
1059
|
|
|
1019
1060
|
Parameters
|
|
1020
1061
|
----------
|
|
@@ -1040,6 +1081,7 @@ class Table(Cacheable):
|
|
|
1040
1081
|
If the start_col is out of range for the table.
|
|
1041
1082
|
ValueError:
|
|
1042
1083
|
If the default value is unsupported by :py:meth:`numbers_parser.Table.write`.
|
|
1084
|
+
|
|
1043
1085
|
"""
|
|
1044
1086
|
if start_col is not None and (start_col < 0 or start_col >= self.num_cols):
|
|
1045
1087
|
msg = "Column number not in range for table"
|
|
@@ -1066,10 +1108,11 @@ class Table(Cacheable):
|
|
|
1066
1108
|
|
|
1067
1109
|
def delete_row(
|
|
1068
1110
|
self,
|
|
1069
|
-
num_rows:
|
|
1070
|
-
start_row:
|
|
1111
|
+
num_rows: int | None = 1,
|
|
1112
|
+
start_row: int | None = None,
|
|
1071
1113
|
) -> None:
|
|
1072
|
-
"""
|
|
1114
|
+
"""
|
|
1115
|
+
Delete rows from the table.
|
|
1073
1116
|
|
|
1074
1117
|
Parameters
|
|
1075
1118
|
----------
|
|
@@ -1089,6 +1132,7 @@ class Table(Cacheable):
|
|
|
1089
1132
|
------
|
|
1090
1133
|
IndexError:
|
|
1091
1134
|
If the start_row is out of range for the table.
|
|
1135
|
+
|
|
1092
1136
|
"""
|
|
1093
1137
|
if start_row is not None and (start_row < 0 or start_row >= self.num_rows):
|
|
1094
1138
|
msg = "Row number not in range for table"
|
|
@@ -1110,10 +1154,11 @@ class Table(Cacheable):
|
|
|
1110
1154
|
|
|
1111
1155
|
def delete_column(
|
|
1112
1156
|
self,
|
|
1113
|
-
num_cols:
|
|
1114
|
-
start_col:
|
|
1157
|
+
num_cols: int | None = 1,
|
|
1158
|
+
start_col: int | None = None,
|
|
1115
1159
|
) -> None:
|
|
1116
|
-
"""
|
|
1160
|
+
"""
|
|
1161
|
+
Add or delete columns columns from the table.
|
|
1117
1162
|
|
|
1118
1163
|
Parameters
|
|
1119
1164
|
----------
|
|
@@ -1127,6 +1172,7 @@ class Table(Cacheable):
|
|
|
1127
1172
|
------
|
|
1128
1173
|
IndexError:
|
|
1129
1174
|
If the start_col is out of range for the table.
|
|
1175
|
+
|
|
1130
1176
|
"""
|
|
1131
1177
|
if start_col is not None and (start_col < 0 or start_col >= self.num_cols):
|
|
1132
1178
|
msg = "Column number not in range for table"
|
|
@@ -1143,8 +1189,9 @@ class Table(Cacheable):
|
|
|
1143
1189
|
self.num_cols -= num_cols
|
|
1144
1190
|
self._model.number_of_columns(self._table_id, self.num_cols)
|
|
1145
1191
|
|
|
1146
|
-
def merge_cells(self, cell_range:
|
|
1147
|
-
"""
|
|
1192
|
+
def merge_cells(self, cell_range: str | list[str]) -> None:
|
|
1193
|
+
"""
|
|
1194
|
+
Convert a cell range or list of cell ranges into merged cells.
|
|
1148
1195
|
|
|
1149
1196
|
Parameters
|
|
1150
1197
|
----------
|
|
@@ -1162,6 +1209,7 @@ class Table(Cacheable):
|
|
|
1162
1209
|
>>> table.merge_cells("B2:C2")
|
|
1163
1210
|
>>> table.cell("B2").is_merged
|
|
1164
1211
|
True
|
|
1212
|
+
|
|
1165
1213
|
"""
|
|
1166
1214
|
if isinstance(cell_range, list):
|
|
1167
1215
|
for x in cell_range:
|
|
@@ -1184,8 +1232,9 @@ class Table(Cacheable):
|
|
|
1184
1232
|
for col, cell in enumerate(cells):
|
|
1185
1233
|
cell._set_merge(merge_cells.get((row, col)))
|
|
1186
1234
|
|
|
1187
|
-
def set_cell_border(self, *args):
|
|
1188
|
-
"""
|
|
1235
|
+
def set_cell_border(self, *args) -> None:
|
|
1236
|
+
"""
|
|
1237
|
+
Set the borders for a cell.
|
|
1189
1238
|
|
|
1190
1239
|
Cell references can be row-column offsers or Excel/Numbers-style A1 notation. Borders
|
|
1191
1240
|
can be applied to multiple sides of a cell by passing a list of sides. The name(s)
|
|
@@ -1221,10 +1270,11 @@ class Table(Cacheable):
|
|
|
1221
1270
|
If an invalid number of arguments is passed or if the types of the arguments
|
|
1222
1271
|
are invalid.
|
|
1223
1272
|
|
|
1224
|
-
Warns
|
|
1273
|
+
Warns:
|
|
1225
1274
|
-----
|
|
1226
1275
|
RuntimeWarning:
|
|
1227
1276
|
If any of the sides to which the border is applied have been merged.
|
|
1277
|
+
|
|
1228
1278
|
"""
|
|
1229
1279
|
(row, col, *args) = self._validate_cell_coords(*args)
|
|
1230
1280
|
if len(args) == 2:
|
|
@@ -1250,20 +1300,17 @@ class Table(Cacheable):
|
|
|
1250
1300
|
return
|
|
1251
1301
|
|
|
1252
1302
|
cell = self._data[row][col]
|
|
1253
|
-
if
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1303
|
+
if (
|
|
1304
|
+
cell.is_merged
|
|
1305
|
+
and ((side == "right" and cell.size[1] > 1) or (side == "bottom" and cell.size[0] > 1))
|
|
1306
|
+
) or (
|
|
1307
|
+
isinstance(cell, MergedCell)
|
|
1308
|
+
and (
|
|
1309
|
+
(side == "top" and cell.row_start < row)
|
|
1310
|
+
or (side == "right" and cell.col_end > col)
|
|
1311
|
+
or (side == "bottom" and cell.row_end > row)
|
|
1312
|
+
or (side == "left" and cell.col_start < col)
|
|
1260
1313
|
)
|
|
1261
|
-
return
|
|
1262
|
-
elif isinstance(cell, MergedCell) and (
|
|
1263
|
-
(side == "top" and cell.row_start < row)
|
|
1264
|
-
or (side == "right" and cell.col_end > col)
|
|
1265
|
-
or (side == "bottom" and cell.row_end > row)
|
|
1266
|
-
or (side == "left" and cell.col_start < col)
|
|
1267
1314
|
):
|
|
1268
1315
|
warn(
|
|
1269
1316
|
f"{side} edge of [{row},{col}] is merged; border not set",
|
|
@@ -1287,7 +1334,8 @@ class Table(Cacheable):
|
|
|
1287
1334
|
self._model.add_stroke(self._table_id, row, col, side, border_value, length)
|
|
1288
1335
|
|
|
1289
1336
|
def set_cell_formatting(self, *args: str, **kwargs) -> None:
|
|
1290
|
-
r"""
|
|
1337
|
+
r"""
|
|
1338
|
+
Set the data format for a cell.
|
|
1291
1339
|
|
|
1292
1340
|
Cell references can be **row-column** offsers or Excel/Numbers-style **A1** notation.
|
|
1293
1341
|
|
|
@@ -1295,7 +1343,7 @@ class Table(Cacheable):
|
|
|
1295
1343
|
|
|
1296
1344
|
table.set_cell_formatting(
|
|
1297
1345
|
"C1",
|
|
1298
|
-
"
|
|
1346
|
+
"datetime",
|
|
1299
1347
|
date_time_format="EEEE, d MMMM yyyy"
|
|
1300
1348
|
)
|
|
1301
1349
|
table.set_cell_formatting(
|
|
@@ -1314,7 +1362,7 @@ class Table(Cacheable):
|
|
|
1314
1362
|
)
|
|
1315
1363
|
|
|
1316
1364
|
:Parameters:
|
|
1317
|
-
* **args** (*list*, *optional*)
|
|
1365
|
+
* **args** (*list*, *optional*) - Positional arguments for cell reference and data format type (see below)
|
|
1318
1366
|
* **kwargs** (*dict*, *optional*) - Key-value pairs defining a formatting options for each data format (see below).
|
|
1319
1367
|
|
|
1320
1368
|
:Args (row-column):
|
|
@@ -1343,9 +1391,9 @@ class Table(Cacheable):
|
|
|
1343
1391
|
depending upon the value of ``kwargs["type"]``.
|
|
1344
1392
|
|
|
1345
1393
|
:Common Args:
|
|
1346
|
-
* **name** (*str*)
|
|
1394
|
+
* **name** (*str*) - The name of the custom format. If no name is provided,
|
|
1347
1395
|
one is generated using the scheme ``Custom Format``, ``Custom Format 1``, ``Custom Format 2``, etc.
|
|
1348
|
-
* **type** (*str, optional, default: number*)
|
|
1396
|
+
* **type** (*str, optional, default: number*) - The type of format to
|
|
1349
1397
|
create:
|
|
1350
1398
|
|
|
1351
1399
|
* ``"base"``: A number base in the range 2-36.
|
|
@@ -1363,51 +1411,51 @@ class Table(Cacheable):
|
|
|
1363
1411
|
* ``"popup"``: A menu of options.
|
|
1364
1412
|
|
|
1365
1413
|
:``"base"``:
|
|
1366
|
-
* **base_use_minus_sign** (*int, optional, default: 10*)
|
|
1414
|
+
* **base_use_minus_sign** (*int, optional, default: 10*) - The integer
|
|
1367
1415
|
base to represent the number from 2-36.
|
|
1368
|
-
* **base_use_minus_sign** (*bool, optional, default: True*)
|
|
1416
|
+
* **base_use_minus_sign** (*bool, optional, default: True*) - If ``True``
|
|
1369
1417
|
use a standard minus sign, otherwise format as two's compliment (only
|
|
1370
1418
|
possible for binary, octal and hexadecimal.
|
|
1371
|
-
* **base_places** (*int, optional, default: 0*)
|
|
1419
|
+
* **base_places** (*int, optional, default: 0*) - The number of
|
|
1372
1420
|
decimal places, or ``None`` for automatic.
|
|
1373
1421
|
|
|
1374
1422
|
:``"custom"``:
|
|
1375
|
-
* **format** (*str | CustomFormating*)
|
|
1423
|
+
* **format** (*str | CustomFormating*) - The name of a custom
|
|
1376
1424
|
formatin the document or a :py:class:`~numbers_parser.CustomFormatting`
|
|
1377
1425
|
object.
|
|
1378
1426
|
|
|
1379
1427
|
:``"currency"``:
|
|
1380
|
-
* **currency** (*str, optional, default: "GBP"*)
|
|
1428
|
+
* **currency** (*str, optional, default: "GBP"*) - An ISO currency
|
|
1381
1429
|
code, e.g. ``"GBP"`` or ``"USD"``.
|
|
1382
|
-
* **decimal_places** (*int, optional, default: 2*)
|
|
1430
|
+
* **decimal_places** (*int, optional, default: 2*) - The number of
|
|
1383
1431
|
decimal places, or ``None`` for automatic.
|
|
1384
|
-
* **negative_style** (*:py:class:`~numbers_parser.NegativeNumberStyle`, optional, default: NegativeNumberStyle.MINUS*)
|
|
1432
|
+
* **negative_style** (*:py:class:`~numbers_parser.NegativeNumberStyle`, optional, default: NegativeNumberStyle.MINUS*) - How negative numbers are represented.
|
|
1385
1433
|
See `Negative number formats <#negative-formats>`_.
|
|
1386
|
-
* **show_thousands_separator** (*bool, optional, default: False*)
|
|
1434
|
+
* **show_thousands_separator** (*bool, optional, default: False*) - ``True``
|
|
1387
1435
|
if the number should include a thousands seperator, e.g. ``,``
|
|
1388
|
-
* **use_accounting_style** (*bool, optional, default: False*)
|
|
1436
|
+
* **use_accounting_style** (*bool, optional, default: False*) - ``True``
|
|
1389
1437
|
if the currency symbol should be formatted to the left of the cell and
|
|
1390
1438
|
separated from the number value by a tab.
|
|
1391
1439
|
|
|
1392
1440
|
:``"datetime"``:
|
|
1393
|
-
* **date_time_format** (*str, optional, default: "dd MMM YYY HH:MM"*)
|
|
1441
|
+
* **date_time_format** (*str, optional, default: "dd MMM YYY HH:MM"*) - A POSIX
|
|
1394
1442
|
strftime-like formatting string of `Numbers date/time
|
|
1395
1443
|
directives <#datetime-formats>`_.
|
|
1396
1444
|
|
|
1397
1445
|
:``"fraction"``:
|
|
1398
|
-
* **fraction_accuracy** (*:py:class:`~numbers_parser.FractionAccuracy`, optional, default: FractionAccuracy.THREE*
|
|
1446
|
+
* **fraction_accuracy** (*:py:class:`~numbers_parser.FractionAccuracy`, optional, default: FractionAccuracy.THREE* - The
|
|
1399
1447
|
precision of the faction.
|
|
1400
1448
|
|
|
1401
1449
|
:``"percentage"``:
|
|
1402
|
-
* **decimal_places** (*float, optional, default: None*)
|
|
1450
|
+
* **decimal_places** (*float, optional, default: None*) - number of
|
|
1403
1451
|
decimal places, or ``None`` for automatic.
|
|
1404
|
-
* **negative_style** (*:py:class:`~numbers_parser.NegativeNumberStyle`, optional, default: NegativeNumberStyle.MINUS*)
|
|
1452
|
+
* **negative_style** (*:py:class:`~numbers_parser.NegativeNumberStyle`, optional, default: NegativeNumberStyle.MINUS*) - How negative numbers are represented.
|
|
1405
1453
|
See `Negative number formats <#negative-formats>`_.
|
|
1406
|
-
* **show_thousands_separator** (*bool, optional, default: False*)
|
|
1454
|
+
* **show_thousands_separator** (*bool, optional, default: False*) - ``True``
|
|
1407
1455
|
if the number should include a thousands seperator, e.g. ``,``
|
|
1408
1456
|
|
|
1409
1457
|
:``"scientific"``:
|
|
1410
|
-
* **decimal_places** (*float, optional, default: None*)
|
|
1458
|
+
* **decimal_places** (*float, optional, default: None*) - number of
|
|
1411
1459
|
decimal places, or ``None`` for automatic.
|
|
1412
1460
|
|
|
1413
1461
|
:``"tickbox"``:
|
|
@@ -1439,13 +1487,13 @@ class Table(Cacheable):
|
|
|
1439
1487
|
* **minimum** (*float, optional, default: 1*) - increment value for the stepper
|
|
1440
1488
|
|
|
1441
1489
|
:`"popup"``:
|
|
1442
|
-
* **popup_values** (*List[str|int|float], optional, default: None*)
|
|
1490
|
+
* **popup_values** (*List[str|int|float], optional, default: None*) - values
|
|
1443
1491
|
for the popup menu
|
|
1444
1492
|
* **allow_none** (*bool, optional, default: True*) - If ``True``
|
|
1445
1493
|
include a blank value in the list
|
|
1446
1494
|
|
|
1447
1495
|
|
|
1448
|
-
"""
|
|
1496
|
+
"""
|
|
1449
1497
|
(row, col, *args) = self._validate_cell_coords(*args)
|
|
1450
1498
|
if len(args) == 1:
|
|
1451
1499
|
format_type = args[0]
|
|
@@ -1506,9 +1554,9 @@ class Table(Cacheable):
|
|
|
1506
1554
|
msg,
|
|
1507
1555
|
)
|
|
1508
1556
|
|
|
1509
|
-
|
|
1557
|
+
formatting = Formatting(type=format_type, **kwargs)
|
|
1510
1558
|
if format_type_name in FORMATTING_ACTION_CELLS:
|
|
1511
|
-
control_id = self._model.control_cell_archive(self._table_id, format_type,
|
|
1559
|
+
control_id = self._model.control_cell_archive(self._table_id, format_type, formatting)
|
|
1512
1560
|
else:
|
|
1513
1561
|
control_id = None
|
|
1514
1562
|
|
|
@@ -1527,20 +1575,20 @@ class Table(Cacheable):
|
|
|
1527
1575
|
) from None
|
|
1528
1576
|
else:
|
|
1529
1577
|
number_format_type = FormattingType.NUMBER
|
|
1530
|
-
format_id = self._model.format_archive(self._table_id, number_format_type,
|
|
1578
|
+
format_id = self._model.format_archive(self._table_id, number_format_type, formatting)
|
|
1531
1579
|
elif format_type_name == "popup":
|
|
1532
|
-
if cell.value == "" and not
|
|
1580
|
+
if cell.value == "" and not formatting.allow_none:
|
|
1533
1581
|
msg = "none value not allowed for popup"
|
|
1534
1582
|
raise IndexError(msg)
|
|
1535
|
-
|
|
1583
|
+
if cell.value != "" and cell.value not in formatting.popup_values:
|
|
1536
1584
|
msg = f"current cell value '{cell.value}' does not match any popup values"
|
|
1537
1585
|
raise IndexError(
|
|
1538
1586
|
msg,
|
|
1539
1587
|
)
|
|
1540
1588
|
|
|
1541
1589
|
popup_format_type = FormattingType.TEXT if isinstance(cell, TextCell) else True
|
|
1542
|
-
format_id = self._model.format_archive(self._table_id, popup_format_type,
|
|
1590
|
+
format_id = self._model.format_archive(self._table_id, popup_format_type, formatting)
|
|
1543
1591
|
else:
|
|
1544
|
-
format_id = self._model.format_archive(self._table_id, format_type,
|
|
1592
|
+
format_id = self._model.format_archive(self._table_id, format_type, formatting)
|
|
1545
1593
|
|
|
1546
1594
|
cell._set_formatting(format_id, format_type, control_id, is_currency=is_currency)
|