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