feat(mxl-compile,mxl-decompile,mxl-validate): группы строк и колонок

Документные ключи rowGroups и columnGroups описывают сворачиваемые
группы: диапазон, имя, признак свёрнутости и расположение заголовка.

Форма плоская, как в формате: вложенность выражена вхождением одного
диапазона в другой. Дерево было бы читаемее, но платформа хранит плоско,
и для правки чужого макета дерево дороже — чтобы добавить группу внутрь
существующей, пришлось бы искать родителя. Частичных пересечений
платформа не порождает (корпус: 40 620 886 пар непересекающихся,
599 958 вложенных, ни одного частичного), поэтому компилятор их
отвергает.

Число уровней вложенности не задаётся: оно совпало с <vgLevels> у всех
1797 макетов корпуса. Порядок записи компилятор приводит к
платформенному — родитель раньше вложенных, по возрастанию начала
(совпало у 1798 макетов из 1798).

Имя группы вывести нельзя, хотя 143 455 имён корпуса выглядят как
автоматические R<номер строки>: 16 666 из них протухли после вставки
строк, а 10 287 групп имени не имеют вовсе. Расположение заголовка взяло
ключ titleLocation — то же свойство и то же имя, что в DSL форм.

mxl-validate: проверка 14 — перевёрнутый диапазон, частичное пересечение,
начало группы за пределами документа.

Стенд Группировки собирается байт в байт обоими портами и добавлен
в платформенные фикстуры.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-15 15:50:18 +03:00
co-authored by Claude Opus 5
parent 4005f36cce
commit 1e0b82d419
19 changed files with 1173 additions and 13 deletions
+32
View File
@@ -601,6 +601,38 @@ current-config не объявляет, поэтому вынести объяв
обратные, ячейки продолжают ссылаться на записи со старыми ширинами. Из итогового XML это
значение не выводится — воспроизводить его не нужно.
## Группировки строк и колонок
```xml
<vgLevels>2</vgLevels>
<vgRows>8</vgRows>
<vg>
<b>1</b> <!-- начало диапазона, 0-based -->
<e>2</e> <!-- конец; нет — группировка из одной строки -->
<t><v8:item><v8:lang>ru</v8:lang><v8:content>Итоговая</v8:content></v8:item></t>
<o>false</o> <!-- свёрнута; развёрнутая тег не пишет -->
<g>Begin</g> <!-- расположение заголовка: Begin | End; нет — Авто -->
</vg>
<hg></hg> <!-- то же для колонок -->
```
Строки группируются часто (1 797 макетов, 170 967 группировок), колонки — почти никогда
(1 макет, 1 группировка). Порядок документных тегов: `height``vgLevels``vgRows``vg`
`hg`; `vgLevels` пишется только при наличии группировок.
| Наблюдение | Данные корпуса |
|---|---|
| диапазоны либо вложены, либо не пересекаются | 40 620 886 пар непересекающихся, 599 958 вложенных, **0 частичных** |
| порядок записи — родитель раньше вложенных, по возрастанию начала | совпало у 1 798 макетов из 1 798 |
| `<vgLevels>` = глубина вложенности | совпало у 1 797 из 1 797 |
| `<o>` | только `false` (6 130) — развёрнутая группировка тег не пишет |
| `<g>` | в корпусе только `Begin` (6); значение `End` даёт Конфигуратор при «Расположение заголовка: Конец» |
Имя (`<t>`) — мультиязычная строка, и в 143 455 случаях это автоимя `R<номер строки + 1>`.
Вывести его нельзя: 16 666 имён «протухли» (`R91` у строки 103 — строки вставляли после
создания группировки), а 10 287 группировок имени не имеют вовсе. Языковые наборы —
`ru`+`en` (93 250) либо псевдоязык `#` (67 431), никогда вместе.
## Примечание к ячейке
```xml
+31 -1
View File
@@ -87,6 +87,8 @@
| `areas` | да | — | Массив областей — диапазонов подряд идущих строк (порядок = порядок в документе); имя необязательно |
| `namedAreas` | нет | — | Именованные области, заданные координатами (см. ниже) |
| `columnSets` | нет | — | Дополнительные колоночные раскладки (см. `mxl-dsl-styles.md`) |
| `rowGroups` | нет | — | Группы строк (см. ниже) |
| `columnGroups` | нет | — | Группы колонок (см. ниже) |
## Области (`areas[]`)
@@ -300,6 +302,35 @@
и компилятор проставляет это сам. `autoSize` и `box` независимы: при автоподгоне размера
положение окошка всё равно хранится.
## Группы строк и колонок
Диапазон строк или колонок, который сворачивается кнопкой на полях. Задаются плоским списком;
вложенность выражена вхождением одного диапазона в другой:
```json
"rowGroups": [
{ "rows": "2-4" },
{ "rows": 3 },
{ "rows": 5, "name": "Итоговая", "collapsed": true, "titleLocation": "begin" }
],
"columnGroups": [
{ "cols": "2-3", "name": { "ru": "Показатели", "en": "Values" } },
{ "cols": 3 }
]
```
| Поле | Обяз. | По умолч. | Описание |
|------|:-----:|-----------|----------|
| `rows` / `cols` | да | — | Диапазон 1-based: число или `"N-M"` |
| `name` | нет | — | Имя группы: строка или объект «язык → текст» |
| `collapsed` | нет | `false` | Свёрнута ли группа при открытии |
| `titleLocation` | нет | `auto` | Расположение заголовка: `begin`, `end`, `auto` |
Диапазоны либо вложены, либо не пересекаются — частичное пересечение платформа не хранит, и
компилятор отвергает его с ненулевым кодом выхода. Число уровней вложенности считается само.
Порядок в списке не важен: компилятор пишет группы так же, как платформа, — родитель
раньше вложенных, по возрастанию начала.
## `rowStyle` — оформление строки
Стиль применяется ко ВСЕЙ ширине строки: позиции без явных ячеек получают тот же стиль. Так в табличных строках получаются сплошные рамки. Он же становится оформлением самой строки — именно так платформа хранит строку, оформленную целиком.
@@ -316,7 +347,6 @@ XML не возвращается.
- объединения, не привязанные к ячейке (по всей высоте или ширине документа);
- рисунки и картинки, в том числе штрихкоды;
- группировки строк и колонок;
- колонтитулы, параметры печати, область печати.
Пересборка макета из DSL — это полная перегенерация, а не точечная правка XML, поэтому