Spreadsheet editing: start with plain ods cells, then solve repeated and empty ones
Mantenedores costumam responder em até 1 dia
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 5/5
- Tempo estimado
- Mais de uma semana
- Facilidade para iniciantes
- 45/100
Direção de pesquisa
Start with odf_document.cpp, odf_parser.cpp, ooxml_spreadsheet_document.cpp, and the existing DocumentPath::Cell and html::edit flow. First run the existing spreadsheet translation/edit tests, then define the smaller ODS step: enable spreadsheet editability, handle cell value/type and formula behavior, and verify a soffice --convert-to round trip. Repeated and empty cells require a separate writable-node design and are not a small single-file change.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Editing is off for spreadsheets everywhere: odf::Document::is_editable returns true only for text/presentation/drawing (odf_document.cpp, // TODO fix spreadsheet editability), and xlsx returns false outright — and cannot save at all (ooxml_spreadsheet_document.cpp, UnsupportedOperation). So the practical target is ods, where save already rebuilds the package from content.xml.
The reason it is off is real, and it is the sparse sheet model. parse_sheet (odf_parser.cpp) only creates a sheet_cell Element for a cell that is non-empty; empty cells are recorded as a range in the sheet's position-keyed maps with null_element_id. And a cell with table:number-columns-repeated / number-rows-repeated gets one Element per column repeat, all pointing at the same pugi::xml_node, flagged is_repeated — which element_is_editable already refuses. Both are exactly the cases where writing through the current editor would be wrong: text_set_content splices the DOM of one text run, so writing a repeated cell writes all of its repeats, and an empty cell has no text run to splice at all.
First step: the cells that already work
A non-empty, non-repeated cell already has a paragraph → text subtree, element_is_editable already walks the parent chain and clears it, and DocumentPath already addresses a cell by position (DocumentPath::Cell, "cell" prefix) rather than by sibling index — so the path survives a sheet that is mostly holes. The missing piece is mostly the document-level gate.
- Let
is_editablebe true forDocumentType::spreadsheet, sotranslateemitscontenteditable+data-odr-pathfor those cells andhtml::editcan navigate back to them. office:valuehas to move with the text. A cell carriesoffice:value-typeplus a typed attribute; the<text:p>is only the display form. Typing42into a float cell and rewriting only the paragraph leaves the oldoffice:valuebehind, and LibreOffice reads the attribute — the cell silently reverts. So a cell edit is not a text edit: it needs to re-infer the type (or drop tostringand clear the typed attributes), which is the first thing that pushes pastmodifiedText.- Formula cells (
table:formula) have the same problem, worse: the text is a cached result. Simplest honest behaviour is to refuse, or to clear the formula and keep the literal. - A round-trip test through
soffice --convert-tois the check that the saved package is actually valid, not just that the bytes changed.
The broader solution: repeated and empty cells
Both are the same shape — the element tree does not have a place to write to — and both are fixed at write time, not at parse time. Neither should inflate the model: expanding repeats or materialising every empty cell up front is what #762 is already dying from.
- Repeated cells: split on write. Editing one cell of a
number-columns-repeated="10"run means rewriting that run as up to three nodes (before / the edited one / after) and fixing the repeat counts, then repointing the affected registry entries. Same on the row axis withnumber-rows-repeated, which is the harder one because a row split rewrites whole<table:table-row>nodes. - Empty cells: materialise on write (#236). An empty cell has a position and a style but no Element. The write path needs to be able to take a
DocumentPath::Cellposition, create the<table:table-cell>(splitting the surrounding repeat run to make room), give it a<text:p>, and register the new Element — i.e. the same splitting primitive as above, plus insertion. - That primitive — give me a writable, unshared xml node for position (c, r) — is the piece worth designing first; both cases and any later style edit go through it.
// TODO covered cells/// TODO mark as repeatedinodf_parser.cppsit next to it and are probably worth cleaning up in the same pass, since covered cells must never become writable targets.
What the diff protocol needs
html::edit accepts one thing: {"modifiedText": {path: string}}, and it hard-requires element.as_text(). An empty cell has no text element, so it can never appear in that map — the browser has nothing to attach data-odr-path to either, since translate_sheet writes empty cells as bare <td>. That means:
- the renderer must mark editable cells (not only text runs) with a path, and
- the diff needs a cell-shaped entry — value plus type — that
editcan apply to a position that has no Element yet.
Worth deciding whether that is a new key alongside modifiedText or a general "modifiedCells" that supersedes the text case for sheets.
Scope
Step one is small and shippable on its own (gate + value/type handling + a round-trip test). The splitting/materialising work is the real body and only makes sense for ods until xlsx can save at all. Related: #236 (empty cells, subsumed by this), #238 (cell overflow), #762 (why nothing here may expand the model).
- Linguagem predominante
- C++
- Estrelas
- 41
- Forks
- 10
- Merge médio
- 10h 30min
- PRs com merge (30d)
- 342
Preparar o ambiente
Este projeto não oferece contêiner de desenvolvimento, Dockerfile nem guia de contribuição, então a configuração fica por sua conta: comece pelo README e veja nosso guia da primeira contribuição para os passos gerais.
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de opendocument-app/OpenDocument.core
-
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 48/100
opendocument-app/OpenDocument.core#1281 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 57/100
opendocument-app/OpenDocument.core#1280 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 42/100
opendocument-app/OpenDocument.core#1279 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 35/100
opendocument-app/OpenDocument.core#1278 ·
Mantenedores costumam responder em até 1 dia
-
enhancement
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 35/100
opendocument-app/OpenDocument.core#1221 ·
Mantenedores costumam responder em até 1 dia
Todas as issues de opendocument-app/OpenDocument.core
Issues semelhantes
-
Issue-Bug Needs-Triage
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 62/100
microsoft/winget-cli#6645 ·
Mantenedores costumam responder em até 2 dias
-
cleanup help wanted
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 62/100
ESPresense/ESPresense#2602 ·
Mantenedores costumam responder em até 1 dia
-
devex good first issue
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 62/100
Mantenedores costumam responder em até 1 dia
-
artifact:simulation-scenario domain:physics good first issue help wanted role:validation testing
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 62/100
Mantenedores costumam responder em até 3 dias