Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Spreadsheet editing: start with plain ods cells, then solve repeated and empty ones

Abierto
#766 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
45/100
Tipo de issue
Nueva funcionalidad
Claridad
Bastante claro
Estado de actividad
Tranquilo
Stack tecnológico
cpp, xml
Área
backend

Línea de trabajo

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.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

enhancement feature tracking

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_editable be true for DocumentType::spreadsheet, so translate emits contenteditable + data-odr-path for those cells and html::edit can navigate back to them.
  • office:value has to move with the text. A cell carries office:value-type plus a typed attribute; the <text:p> is only the display form. Typing 42 into a float cell and rewriting only the paragraph leaves the old office:value behind, 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 to string and clear the typed attributes), which is the first thing that pushes past modifiedText.
  • 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-to is 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 with number-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::Cell position, 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 repeated in odf_parser.cpp sit 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 edit can 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).

Lenguaje dominante
C++
Estrellas
41
Forks
10
Merge medio
12 h 4 min
PR fusionados (30 d)
297

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de opendocument-app/OpenDocument.core

Todos los issues de opendocument-app/OpenDocument.core

Issues similares

Más issues de C++

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.