feat(mxl-compile,mxl-decompile): значение ячейки-поля ввода и настройки элемента управления

Ключ ячейки value несёт значение, набранное в поле ввода, ключ control —
сериализованные настройки самого элемента управления. Оба живут у ячейки,
а не в палитре формата: у двух ячеек с одинаковым оформлением значения
разные.

Тип значения выражается литералом JSON и приведения к объявленному типу
НЕ делается. Так пишет платформа: ссылочный и составной тип она хранит
строкой, а при смене типа ячейки прежнее значение не переписывает — на
корпусе 560 ячеек объявлены числом, но несут строку. Приведение здесь
означало бы переписывать данные при пересборке. Дата литералом JSON не
выражается, поэтому едет строкой и читается как дата только у ячейки,
объявленной датой.

Настройки элемента управления возим дословно: 26 370 вхождений корпуса
дают всего 163 различных блоба, разбирать структуру незачем. Переводы
строк внутри блоба приводим к LF на чтении — XML-парсеры двух портов
нормализуют их по-разному, и без этого порты давали разный JSON на одном
файле.

Стенд СЗначениями снова собирается байт в байт обоими портами: фикстура
обновлена до версии со значениями, флажком и блобом настроек.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-15 13:32:40 +03:00
co-authored by Claude Opus 5
parent 66bb285636
commit 43d2f660da
14 changed files with 951 additions and 17 deletions
@@ -0,0 +1,14 @@
{
"name": "Ошибка: value без valueType",
"input": {
"columns": 1,
"areas": [
{
"name": "Ввод",
"rows": [{ "cells": [{ "col": 1, "value": "5" }] }]
}
]
},
"params": { "outputPath": "Template.xml" },
"expectError": "Cell 'value' requires 'valueType' (area \"Ввод\")"
}
@@ -112,10 +112,129 @@
</c>
</row>
</rowsItem>
<rowsItem>
<index>7</index>
<row>
<c>
<c>
<f>3</f>
<v xsi:type="xs:string">5</v>
</c>
</c>
<c>
<c>
<f>2</f>
<v xsi:type="xs:decimal">8</v>
</c>
</c>
</row>
</rowsItem>
<rowsItem>
<index>8</index>
<row>
<c>
<c>
<f>3</f>
<v xsi:type="xs:string">4 5</v>
</c>
</c>
<c>
<c>
<f>2</f>
<v xsi:type="xs:decimal">0</v>
</c>
</c>
<c>
<c>
<f>12</f>
<v xsi:type="xs:dateTime">0001-01-01T00:00:00</v>
</c>
</c>
</row>
</rowsItem>
<rowsItem>
<index>9</index>
<row>
<c>
<c>
<f>13</f>
<v xsi:type="xs:string">4 5</v>
</c>
</c>
<c>
<c>
<f>12</f>
<v xsi:type="xs:dateTime">0001-01-01T00:00:00</v>
</c>
</c>
<c>
<c>
<f>4</f>
<v xsi:type="xs:boolean">true</v>
</c>
</c>
</row>
</rowsItem>
<rowsItem>
<index>10</index>
<row>
<c>
<c>
<f>14</f>
<v xsi:type="xs:string">Составной</v>
</c>
</c>
<c>
<c>
<f>2</f>
<v xsi:type="xs:decimal">12.5</v>
</c>
</c>
<c>
<c>
<f>2</f>
<v xsi:type="xs:decimal">-3</v>
</c>
</c>
</row>
</rowsItem>
<rowsItem>
<index>11</index>
<row>
<c>
<c>
<f>15</f>
</c>
</c>
<c>
<c>
<f>12</f>
<v xsi:type="xs:dateTime">0001-01-01T00:00:00</v>
</c>
</c>
<c>
<c>
<f>3</f>
<control xsi:type="xs:base64Binary">77u/MiwxLDM4MWVkNjI0LTkyMTctNGU2My04NWRiLWM0YzNjYjg3ZGFhZSwNCnsN
Cns5LA0KeyJQYXR0ZXJuIiwNCnsiUyJ9DQp9LA0Kew0Kew0KezE2LDEsDQp7Myw0
LA0KezB9DQp9LA0KezMsNCwNCnswfQ0KfSwNCns3LDMsMCwxLDEwMH0sMCwNCnsz
LDQsDQp7MH0NCn0sDQp7Myw0LA0KezB9DQp9LA0KezMsNCwNCnswfQ0KfSwNCnsz
LDMsDQp7LTd9DQp9LA0KezMsMywNCnstMjF9DQp9LA0KezMsMSwNCnstMTh9LDAs
MCwwfSwNCnsxLDB9LDAsMCwxMDAsMCwwfSwzMCwwLDAsMSwwLDAsMSwxLDEsMCwx
LDAsMCwwLDAsMCw0LDAsDQp7IlUifSwNCnsiVSJ9LCIiLDAsMSwwLDAsMCwwLA0K
ezQsMCwNCnswfSwiIiwtMSwtMSwxLDAsIiJ9LA0KezQsMCwNCnswfSwiIiwtMSwt
MSwxLDAsIiJ9LDAsMCwwLA0KezAsMCwwfSwNCnsxLDB9LDAsMCwwLDAsMCwwLDAs
MTY3NzcyMTUsMn0NCn0sDQp7MSwNCns5YTc2NDNkMi0xOWU5LTQ1ZTItODg5My0y
ODBiYzkxOTVhOTcsDQp7NCwNCnsiVSJ9LA0KeyJVIn0sMCwiIiwwLDB9DQp9DQp9
LA0KezB9LDAsMSwwLA0KezEsMH0sMH0NCn0sMA==</control>
</c>
</c>
</row>
</rowsItem>
<templateMode>true</templateMode>
<defaultFormatIndex>12</defaultFormatIndex>
<height>7</height>
<vgRows>7</vgRows>
<defaultFormatIndex>16</defaultFormatIndex>
<height>12</height>
<vgRows>12</vgRows>
<format>
<containsValue>true</containsValue>
<valueType>
@@ -232,6 +351,57 @@
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:dateTime</v8:Type>
<v8:DateQualifiers>
<v8:DateFractions>DateTime</v8:DateFractions>
</v8:DateQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:CatalogRef.Бригады</v8:Type>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:boolean</v8:Type>
<v8:Type>xs:string</v8:Type>
<v8:Type>xs:dateTime</v8:Type>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>0</v8:Digits>
<v8:FractionDigits>0</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
<v8:StringQualifiers>
<v8:Length>0</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
<v8:DateQualifiers>
<v8:DateFractions>DateTime</v8:DateFractions>
</v8:DateQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>0</v8:Digits>
<v8:FractionDigits>0</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</valueType>
<controlType>35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26</controlType>
</format>
<format>
<width>72</width>
</format>
@@ -0,0 +1,225 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://v8.1c.ru/8.2/data/spreadsheet" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<languageSettings>
<currentLanguage>ru</currentLanguage>
<defaultLanguage>ru</defaultLanguage>
<languageInfo>
<id>ru</id>
<code>Русский</code>
<description>Русский</description>
</languageInfo>
</languageSettings>
<columns>
<size>3</size>
</columns>
<rowsItem>
<index>0</index>
<row>
<c>
<c>
<f>1</f>
<v xsi:type="xs:string">5</v>
</c>
</c>
<c>
<c>
<f>2</f>
<v xsi:type="xs:decimal">12.5</v>
</c>
</c>
<c>
<c>
<f>3</f>
<v xsi:type="xs:decimal">-3</v>
</c>
</c>
</row>
</rowsItem>
<rowsItem>
<index>1</index>
<row>
<c>
<c>
<f>4</f>
<v xsi:type="xs:boolean">true</v>
</c>
</c>
<c>
<c>
<f>4</f>
<v xsi:type="xs:boolean">false</v>
</c>
</c>
<c>
<c>
<f>5</f>
<v xsi:type="xs:dateTime">2026-08-09T13:45:00</v>
</c>
</c>
</row>
</rowsItem>
<rowsItem>
<index>2</index>
<row>
<c>
<c>
<f>6</f>
<v xsi:type="xs:string"></v>
</c>
</c>
<c>
<c>
<f>7</f>
<v xsi:type="xs:decimal">0</v>
</c>
</c>
<c>
<c>
<f>5</f>
<v xsi:type="xs:dateTime">0001-01-01T00:00:00</v>
</c>
</c>
</row>
</rowsItem>
<rowsItem>
<index>3</index>
<row>
<c>
<c>
<f>8</f>
<v xsi:type="xs:string">4 5</v>
</c>
</c>
<c>
<c>
<f>9</f>
<v xsi:type="xs:string">Составной</v>
</c>
</c>
<c>
<c>
<f>3</f>
<v xsi:type="xs:decimal">8</v>
<detailParameter>Расшифровка</detailParameter>
</c>
</c>
</row>
</rowsItem>
<templateMode>true</templateMode>
<defaultFormatIndex>10</defaultFormatIndex>
<height>4</height>
<vgRows>4</vgRows>
<namedItem xsi:type="NamedItemCells">
<name>Значения</name>
<area>
<type>Rows</type>
<beginRow>0</beginRow>
<endRow>3</endRow>
<beginColumn>-1</beginColumn>
<endColumn>-1</endColumn>
</area>
</namedItem>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:string</v8:Type>
<v8:StringQualifiers>
<v8:Length>10</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>15</v8:Digits>
<v8:FractionDigits>3</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>10</v8:Digits>
<v8:FractionDigits>2</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:boolean</v8:Type>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:dateTime</v8:Type>
<v8:DateQualifiers>
<v8:DateFractions>DateTime</v8:DateFractions>
</v8:DateQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:string</v8:Type>
<v8:StringQualifiers>
<v8:Length>0</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>0</v8:Digits>
<v8:FractionDigits>0</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:CatalogRef.Валюты</v8:Type>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:boolean</v8:Type>
<v8:Type>xs:string</v8:Type>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>0</v8:Digits>
<v8:FractionDigits>0</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
<v8:StringQualifiers>
<v8:Length>0</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<width>10</width>
</format>
</document>
@@ -0,0 +1,37 @@
{
"name": "Ячейки-поля ввода: сохранённое значение",
"input": {
"columns": 3,
"areas": [
{
"name": "Значения",
"rows": [
{ "cells": [
{ "col": 1, "valueType": "String(10)", "value": "5" },
{ "col": 2, "valueType": "Number(15,3)", "value": 12.5 },
{ "col": 3, "valueType": "Number(10,2)", "value": -3 }
]},
{ "cells": [
{ "col": 1, "valueType": "Boolean", "value": true },
{ "col": 2, "valueType": "Boolean", "value": false },
{ "col": 3, "valueType": "DateTime", "value": "2026-08-09T13:45:00" }
]},
{ "cells": [
{ "col": 1, "valueType": "String", "value": "" },
{ "col": 2, "valueType": "Number", "value": "" },
{ "col": 3, "valueType": "DateTime", "value": "" }
]},
{ "cells": [
{ "col": 1, "valueType": "CatalogRef.Валюты", "value": "4 5" },
{ "col": 2, "valueType": "Boolean + String + Number", "value": "Составной" },
{ "col": 3, "valueType": "Number(10,2)", "value": 8, "detail": "Расшифровка" }
]}
]
}
]
},
"params": {
"outputPath": "Template.xml"
},
"skipPlatformVerify": "ссылочный тип разрешается только в базе с матч-конфигурацией: временная база-заглушка таких объектов не содержит"
}
@@ -0,0 +1,41 @@
{
"name": "Roundtrip — сохранённые значения ячеек-полей ввода",
"preRun": [
{
"script": "mxl-compile/scripts/mxl-compile",
"input": {
"columns": 3,
"areas": [
{
"name": "Значения",
"rows": [
{ "cells": [
{ "col": 1, "valueType": "String(10)", "value": "5" },
{ "col": 2, "valueType": "Number(15,3)", "value": 12.5 },
{ "col": 3, "valueType": "Number(10,2)", "value": -3 }
]},
{ "cells": [
{ "col": 1, "valueType": "Boolean", "value": true },
{ "col": 2, "valueType": "DateTime", "value": "2026-08-09T13:45:00" },
{ "col": 3, "valueType": "DateTime", "value": "" }
]},
{ "cells": [
{ "col": 1, "valueType": "String", "value": "" },
{ "col": 2, "valueType": "Number", "value": "" },
{ "col": 3, "valueType": "Boolean + String + Number", "value": "Составной" }
]}
]
}
]
},
"args": { "-JsonPath": "{inputFile}", "-OutputPath": "Template.xml" },
"cwd": "{workDir}"
}
],
"params": { "templatePath": "Template.xml" },
"args_extra": ["-OutputPath", "{workDir}/back.json"],
"expect": {
"files": ["back.json"],
"stdoutContains": "[OK] Decompiled:"
}
}
@@ -0,0 +1,194 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://v8.1c.ru/8.2/data/spreadsheet" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<languageSettings>
<currentLanguage>ru</currentLanguage>
<defaultLanguage>ru</defaultLanguage>
<languageInfo>
<id>ru</id>
<code>Русский</code>
<description>Русский</description>
</languageInfo>
</languageSettings>
<columns>
<size>3</size>
</columns>
<rowsItem>
<index>0</index>
<row>
<c>
<c>
<f>1</f>
<v xsi:type="xs:string">5</v>
</c>
</c>
<c>
<c>
<f>2</f>
<v xsi:type="xs:decimal">12.5</v>
</c>
</c>
<c>
<c>
<f>3</f>
<v xsi:type="xs:decimal">-3</v>
</c>
</c>
</row>
</rowsItem>
<rowsItem>
<index>1</index>
<row>
<c>
<c>
<f>4</f>
<v xsi:type="xs:boolean">true</v>
</c>
</c>
<c>
<c>
<f>5</f>
<v xsi:type="xs:dateTime">2026-08-09T13:45:00</v>
</c>
</c>
<c>
<c>
<f>5</f>
<v xsi:type="xs:dateTime">0001-01-01T00:00:00</v>
</c>
</c>
</row>
</rowsItem>
<rowsItem>
<index>2</index>
<row>
<c>
<c>
<f>6</f>
<v xsi:type="xs:string"></v>
</c>
</c>
<c>
<c>
<f>7</f>
<v xsi:type="xs:decimal">0</v>
</c>
</c>
<c>
<c>
<f>8</f>
<v xsi:type="xs:string">Составной</v>
</c>
</c>
</row>
</rowsItem>
<templateMode>true</templateMode>
<defaultFormatIndex>9</defaultFormatIndex>
<height>3</height>
<vgRows>3</vgRows>
<namedItem xsi:type="NamedItemCells">
<name>Значения</name>
<area>
<type>Rows</type>
<beginRow>0</beginRow>
<endRow>2</endRow>
<beginColumn>-1</beginColumn>
<endColumn>-1</endColumn>
</area>
</namedItem>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:string</v8:Type>
<v8:StringQualifiers>
<v8:Length>10</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>15</v8:Digits>
<v8:FractionDigits>3</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>10</v8:Digits>
<v8:FractionDigits>2</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:boolean</v8:Type>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:dateTime</v8:Type>
<v8:DateQualifiers>
<v8:DateFractions>DateTime</v8:DateFractions>
</v8:DateQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:string</v8:Type>
<v8:StringQualifiers>
<v8:Length>0</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>0</v8:Digits>
<v8:FractionDigits>0</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:boolean</v8:Type>
<v8:Type>xs:string</v8:Type>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>0</v8:Digits>
<v8:FractionDigits>0</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
<v8:StringQualifiers>
<v8:Length>0</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
<format>
<width>10</width>
</format>
</document>
@@ -0,0 +1,16 @@
{
"columns": 3,
"defaultWidth": 10,
"fonts": {},
"styles": {},
"areas": [
{
"name": "Значения",
"rows": [
[{ "valueType": "String(10)", "value": "5" }, { "valueType": "Number(15,3)", "value": 12.5 }, { "valueType": "Number(10,2)", "value": -3 }],
[{ "valueType": "Boolean", "value": true }, { "valueType": "DateTime", "value": "2026-08-09T13:45:00" }, { "valueType": "DateTime", "value": "0001-01-01T00:00:00" }],
[{ "valueType": "String", "value": "" }, { "valueType": "Number", "value": 0 }, { "valueType": "Boolean + String + Number", "value": "Составной" }]
]
}
]
}