masaccio / numbers-parser

Python module for parsing Apple Numbers .numbers files
MIT License
201 stars 14 forks source link

Add support for pop-up menus #74

Closed wrc-marek closed 7 months ago

wrc-marek commented 7 months ago

Is there a way to add a pop-up menu?

Screenshot 2024-02-22 at 22 41 31

I have tried to open a Numbers file with a pop-up menu, and after saving the pop-up is removed:

Screenshot 2024-02-22 at 22 42 24
masaccio commented 7 months ago

This has been published in v4.9.0. There's an example in this test. Error handling is a bit ropey at the moment. For example there's no check that values written match the available popup values. You can mix types in the menu, but currently only float and str are supported. Numbers detects percentages and currencies, but I think that will be fragile in python.

wrc-marek commented 7 months ago

It's working thanks. The only problem that I see is that it's also removing pop-up menu when the value is None. Original file:

Screenshot 2024-02-25 at 19 38 46

After saving:

Screenshot 2024-02-25 at 19 39 35
masaccio commented 7 months ago

As in you have a popup with an empty first value, load the document in numbers-parser, re-save and the resulting popup is removed?

wrc-marek commented 7 months ago

Correct, I have a document with many popups. Some popups have a non-empty default value and some have default value None. After loading this document into number-parser and re-saving, it keeps popups where the first value isn't empty but for those where the default value is None it removes popup definition and the cell ends up with empty value. I'm using 4.9.1 version, tested also on 4.9.0 with no difference.

masaccio commented 7 months ago

v4.9.2 adds support for empty cells with popup menus.

wrc-marek commented 7 months ago

Works perfectly, thanks!

wrc-marek commented 7 months ago

I have one more problem with pop-ups when reading existing Numbers file. Here is how to reproduce the error:

1) Create a new Numbers file and save it to template.numbers file 2) Execute

from numbers_parser import Document

doc = Document("./template.numbers")
table = doc.sheets[0].tables[0]
table.write(0, 1, "Dog")
table.set_cell_formatting(0, 1, "popup", popup_values=["Cat", "Dog", "Rabbit"], allow_none=True)

Error:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "test.py", line 22, in <module>
    table.set_cell_formatting(0, 1, "popup", popup_values=["Cat", "Dog", "Rabbit"], allow_none=True)
  File "venv/lib/python3.11/site-packages/numbers_parser/document.py", line 1384, in set_cell_formatting
    self._set_cell_data_format(row, col, format_type, **kwargs)
  File "venv/lib/python3.11/site-packages/numbers_parser/document.py", line 1426, in _set_cell_data_format
    control_id = self._model.control_cell_archive(self._table_id, format_type, format)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "venv/lib/python3.11/site-packages/numbers_parser/model.py", line 418, in control_cell_archive
    popup_id = self.cell_popup_model(self._control_specs.id(table_id), format)
                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "venv/lib/python3.11/site-packages/numbers_parser/model.py", line 161, in id
    return self._datalists[table_id]["id"]
           ~~~~~~~~~~~~~~~^^^^^^^^^^
KeyError: 904538

Tested on numbers-parser==4.10.0

wrc-marek commented 7 months ago

I tested also without template.numbers file and I'm also getting error. This doesn't work:

doc = Document()
table = doc.sheets[0].tables[0]

table.write(1, 0, "Dog")
table.set_cell_formatting(1, 0, "popup", popup_values=["Cat", "Dog", "Rabbit"], allow_none=True)

This works:

doc = Document()
table = doc.sheets[0].tables[0]

table.write(0, 0, False)
table.set_cell_formatting(0, 0, "tickbox")

table.write(1, 0, "Dog")
table.set_cell_formatting(1, 0, "popup", popup_values=["Cat", "Dog", "Rabbit"], allow_none=True)
wrc-marek commented 7 months ago

Also, what is the best way to add pop-up with None value? I tried:

table.set_cell_formatting(0, 1, "popup", popup_values=["Test"], allow_none=True)

And I'm getting TypeError: cannot use popup formatting for cells of type EmptyCell I tried also:

table.write(0, 1, "")
table.set_cell_formatting(0, 1, "popup", popup_values=["Test"], allow_none=True)

And I'm getting IndexError: current cell value '' does not match any popup values

masaccio commented 7 months ago

Thanks for spotting that using a different control before the popup hid the bug -- the popup code was not calling an init method.

I've added checks for empty cells and popups. Empty values are only allowed if allow_none is True:

    table.write(0, 0, "")
    # Valid
    table.set_cell_formatting(0, 0, "popup", popup_values=["Cat", "Dog", "Rabbit"], allow_none=True)
    # raises IndexError
    table.set_cell_formatting(0, 0, "popup", popup_values=["Cat", "Dog", "Rabbit"])

All published in v4.10.1.

wrc-marek commented 7 months ago

Works perfect, thanks!