masaccio / numbers-parser

Python module for parsing Apple Numbers .numbers files
MIT License
208 stars 15 forks source link

Modifying an already existing file previously opened with APP and writing same string to different cells. #79

Closed darioclock closed 8 months ago

darioclock commented 8 months ago

Describe the bug I create a new file from scratch using the Numbers App and close the App. I open the same file again using numbers-parser (Document('./test.numbers')) and write the same string such as "TEST" to multiple rows (it must be a string). Now I open the file with Numbers App again and try to modify one of the rows that I previously wrote with numbers-parser. All the rows that were written with the same string will now turn blank! They loose their value as if they were "linked" in the numbers document. Also, if the file is then saved in the Numbers App it won't be able to be opened again using Document('./test.numbers').

To Reproduce 1) Create a new blank spreadsheet using Numbers App and save it as 'test.numbers' 2) Run Python code below 3) Open ./test.numbers with Numbers App 4) Modify any cell that contains "TEST"

name = "./test.numbers"  
doc = Document(name)
sheet = doc.sheets["Sheet 1"]
table = sheet.tables["Table 1"]
for i,d in enumerate(range(10)):
    table.write(i,1,"TEST")
doc.save(name)

Expected behavior When I re-open the numbers file with the Numbers App I should be able to only modify the cell that I intend to modify with my input, but in reality all the cells that have the same string value will turn blank.

Attachments can't attach a numbers file but would work with any file that has been created or even opened with the Numbers App.

Additional information 4.10.3

In addition, once the document is corrupted by point 4) and is saved from the Numbers App, the next time it is attempted to open it with the numbers-parser function Document(name), the function will fail. Can send traceback in another comment if needed.

masaccio commented 8 months ago

I am struggling to reproduce this. I used this code:

def test_issue_79(configurable_save_file):
    doc = Document("tests/data/test-issue-79.numbers")
    doc.add_style(name="Changed Cells", bold=True)
    table = doc.default_table
    for row in range(2, 12):
        table.write(row, 0, table.cell(1, 0).value, style="Changed Cells")
        table.write(row, 1, table.cell(1, 1).value, style="Changed Cells")
    doc.save(configurable_save_file)
    doc = Document(configurable_save_file)
    table = doc.default_table
    assert all([table.cell(row, 0).value == table.cell(1, 0).value for row in range(2, 12)])
    assert all([table.cell(row, 1).value == table.cell(1, 1).value for row in range(2, 12)])

Where tests/data/test-issue-79.numbers was created by Numbers and has a table like this:

Test 1 Test 2
FOO BAR
 

I used styles so it's clear which cells are changed. For each column, the original value is retained.

Strings in Numbers are only stored once but if the existing data cells are untouched then their references to this strings should be retained.

Are you able to attach an example doc?

darioclock commented 8 months ago

I do replicate it on my side using your exact code! Your code is generating a corruptible file for me.

1) Open, using the Numbers app, the file saved with "configurable_save_file". 2) Input anything on any on any other FOO or BAR cell (press enter to input the info) 3) If you modified a FOO cell, all above and below FOO cells values disappear (if you don't see them disappear they will disappear once you double click them. 4) If you modified BAR, all above and below BAR cells values disappear.

I wanted to attach a numbers before but .numbers were not allowed if I remember correctly. However, your method of generating the corruptible file does reproduce my issue.

I can maybe try to record the screen show better/

masaccio commented 8 months ago

I will take another look. I was running off the main branch rather than the release.

masaccio commented 8 months ago

But you can zip broken files and attach too

darioclock commented 8 months ago

You are right, sorry.

In this archive I bundled a video recording and the corrupted file in question.

Archive.zip

FTY I'm running: Python 3.9.6 numbers-parser 4.10.3, main branch, SHA 99c86a9

masaccio commented 8 months ago

That helped - I missed the step of reloading in Numbers and trying to edit. The reference counting of strings should now be correct in v4.10.4.

darioclock commented 8 months ago

4.10.4 fixes the issue for me! Thanks a bunch!