docs(mxl): актуализировать спецификацию XML табличного документа

За кампанию XML-уровень изучен заметно глубже, чем был описан. Внесено то,
что проверено на корпусе ERP (10 924 макета) и на контролируемом стенде:

- <i> платформа пишет только при разрыве последовательности;
- <indexTo> схлопывает только ПУСТЫЕ строки — прежняя формулировка «строки
  с одинаковым содержимым» неверна: одинаковых непустых схлопнутых нет ни одной
  при 98 153 несхлопнутых;
- <f>0</f> — у ячейки формата нет вовсе, это не индекс записи;
- канонический порядок тегов внутри <format> (height раньше width);
- единица ширины — 1/8 символа;
- свёртка четырёх одинаковых сторон рамки в <border>;
- цвет — значение с префиксом пространства имён, web/win объявляются прямо
  на узле; в Form.xml те же цвета выглядят как web:/win:;
- формат строки несёт не только высоту, а формат колонки не только ширину;
  оформление строки материализуется и в ячейки, кроме hidden;
- columnsItem с formatIndex 0 и с индексом за пределами size;
- полный список стилей линии вместо Solid/None.

Отдельно описана ловушка: width в формате ЯЧЕЙКИ — устаревшая ссылка, она не
описывает итоговое состояние документа и воспроизведению не подлежит.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-11 19:08:52 +03:00
co-authored by Claude Opus 5
parent ba25aa4a00
commit 250ec9ef0d
+97 -14
View File
@@ -80,7 +80,16 @@
</columns>
```
Перечисляются только колонки с нестандартной шириной. Формат колонки определяет ширину через свойство `<width>` в палитре форматов.
Перечисляются колонки, у которых есть собственный формат. Обычно это ширина (`<width>` в
палитре форматов), но формат колонки несёт и оформление: шрифт (3 006 форматов на корпусе),
выравнивания, рамки, `hidden`.
Два случая, которые легко упустить:
- `<formatIndex>0</formatIndex>` — колонка перечислена, а формата у неё **нет** (ноль здесь не
индекс записи). Встречается у 4% макетов;
- индекс колонки бывает **больше или равен `<size>`** — платформа описывает колонки за
пределами объявленной ширины сетки (25% макетов).
### Дополнительные наборы колонок
@@ -123,8 +132,12 @@
</rowsItem>
```
- Строки с одинаковым содержимым объединяются через `<indexTo>`
- `<indexTo>` объединяет подряд идущие **пустые** строки. Одинаковые НЕпустые строки платформа
не схлопывает никогда: на корпусе ERP (10 924 макета) схлопнутых непустых нет ни одной,
несхлопнутых одинаковых непустых — 98 153; несхлопнутых одинаковых пустых — тоже ни одной
- `<columnsID>` привязывает строку к дополнительному набору колонок. Без него — используется основной набор
- `<formatIndex>` строки несёт не только высоту: в корпусе там `hidden` (17 423 вхождения),
`font` (9 216), `backColor`, выравнивания, `protection`, рамки
### Ячейка
@@ -152,6 +165,14 @@
- Если `<i>` не указан — колонка = предыдущая + 1
- Первая ячейка без `<i>` идёт в колонку 0
Платформа пишет `<i>` **только при разрыве последовательности**: у подряд идущей ячейки его нет.
На корпусе ERP из 1 212 023 записанных номеров ни один не избыточен (счётчик начинается с −1,
поэтому у ячейки в колонке 0 номера тоже нет).
`<f>0</f>` означает, что формата у ячейки **нет вовсе** — это не индекс записи. Так записана
ячейка без собственного оформления: 170 710 таких ячеек против 50 635, ссылающихся на формат
по умолчанию; `<f>0</f>` встречается в 71% макетов.
### Типы заполнения ячеек
Тип заполнения определяется свойством `fillType` в формате ячейки:
@@ -327,12 +348,13 @@
</line>
```
| xsi:type | Значения |
|-----------------------------------------|-------------|
| `v8ui:SpreadsheetDocumentCellLineType` | Solid, None |
| `v8ui:SpreadsheetDocumentDrawingLineType` | Solid, None |
| xsi:type | Значения |
|-------------------------------------------|----------|
| `v8ui:SpreadsheetDocumentCellLineType` | `Solid`, `None`, `Dotted`, `ThinDashed`, `LargeDashed`, `ThickDashed`, `Double` |
| `v8ui:SpreadsheetDocumentDrawingLineType` | те же |
Атрибут `width` — толщина линии (1 = тонкая, 2 = толстая).
Атрибут `width` — толщина линии; в корпусе встречаются 0, 1, 2, 3. Атрибут `gap` на корпусе
всегда `false`, но пишется всегда.
## Шрифты
@@ -376,15 +398,76 @@
Все свойства опциональны. Формат может содержать только `<width>` (для колонки) или только `<height>` (для строки).
### Порядок тегов
Внутри `<format>` теги идут в строгой последовательности — от неё зависит побайтовое совпадение
с выгрузкой. Порядок снят с корпуса ERP: 766 960 форматов, ни один его не нарушает.
```
print · drawingBorder · drawingHaveLeftBorder · drawingHaveTopBorder ·
drawingHaveRightBorder · drawingHaveBottomBorder · font · leftBorder · topBorder ·
rightBorder · bottomBorder · border · height · borderColor · width ·
autoWidthCalculation · widthWeightFactor · horizontalAlignment · verticalAlignment ·
textColor · backColor · patternColor · pattern · textPlacement · fillType · protection ·
hidden · textOrientation · detailsUse · bySelectedColumns · markNegatives ·
containsValue · valueType · format · controlType · hyperLink · autoMarkIncomplete ·
indent · autoIndent · editFormat · columnSizeChange · mask · picIndex ·
pictureSizeMode · picHorizontalAlignment · picVerticalAlignment · textPosition
```
Обрати внимание: `height` идёт РАНЬШЕ `width`, а `format` — после `valueType`.
### Ширина и высота
Единица — **1/8 символа**: `72` = стандартные 9 символов, `240` = 30, `80` = 10.
### Рамка
Четыре стороны и свёрнутый `<border>` взаимоисключающи. Если все четыре стороны одинаковы,
платформа пишет один `<border>`; иначе — по сторонам. На корпусе: 70 265 свёрнутых форматов
против 36 783 записанных по сторонам, и среди вторых нет ни одного с четырьмя совпадающими
значениями; смешения `border` с посторонними тегами нет ни разу.
### Цвет
Значение цвета (`backColor`, `textColor`, `borderColor`, `patternColor`) — строка с **префиксом
пространства имён**, а не свободный текст:
| Запись в XML | Смысл |
|---|---|
| `#RRGGBB` | RGB-hex |
| `style:ИмяСтиля` | элемент стиля; префикс `style` объявлен в корне документа |
| `d3p1:Имя` + `xmlns:d3p1=".../ui/colors/web"` на самом узле | цвет web-палитры |
| `d3p1:Имя` + `xmlns:d3p1=".../ui/colors/windows"` на самом узле | системный цвет Windows |
Корень `<document>` объявляет только `style`, поэтому для web- и windows-палитр платформа
дописывает объявление прямо на узел. Префикс всегда `d3p1` (1264 вхождения на корпусе без
отклонений). В Form.xml те же цвета выглядят как `web:Имя` и `win:Имя` — там эти префиксы
объявлены в корне.
### Связь формата с контекстом
| Контекст | Ссылка | Значимые свойства формата |
|------------------|--------------------|--------------------------|
| Колонка | `<formatIndex>` | `width` |
| Строка | `<formatIndex>` | `height` |
| Ячейка | `<f>` | Все остальные |
| Рисунок | `<formatIndex>` | `drawingBorder` |
| По умолчанию | `<defaultFormatIndex>` | `width` |
Один формат обслуживает всех: колонка, строка и ячейка ссылаются в одну палитру, и набор
свойств у них общий (`hidden` встречается у ячеек 30 175 раз, у строк 17 423, у колонок 57;
`protection` — 84 442 / 1 492 / 1 017).
| Контекст | Ссылка | Свойства, специфичные для контекста |
|------------------|------------------------|-------------------------------------|
| Колонка | `<formatIndex>` | `width` |
| Строка | `<formatIndex>` | `height`, `hidden` |
| Ячейка | `<f>` | `fillType`, `containsValue` |
| Рисунок | `<formatIndex>` | `drawingBorder`, `drawing*` |
| По умолчанию | `<defaultFormatIndex>` | `width` |
Оформление, применённое к строке целиком, платформа записывает И в формат строки, И в формат
каждой ячейки (`backColor`: 13 899 ячеек повторяют против 96). Исключение — `hidden`: оно
остаётся только у строки (24 026 против 62 856).
**Ловушка: `width` в формате ЯЧЕЙКИ не описывает ячейку.** Ссылка ячейки на запись палитры не
обновляется при изменении ширины колонки, поэтому там остаётся ширина от прежнего состояния
документа. Проверено на контролируемом стенде: в макете, где ширины колонок поменяли на
обратные, ячейки продолжают ссылаться на записи со старыми ширинами. Из итогового XML это
значение не выводится — воспроизводить его не нужно.
## Ресурсы картинок