mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-18 01:00:24 +03:00
feat(mxl-compile,mxl-decompile,mxl-validate): ячейки-поля ввода
Тип значения ячейки и элемент управления переживают цикл компиляции и декомпиляции. Макет стенда с полями ввода собирается из своего же JSON байт в байт. DSL: два ключа ячейки — valueType (грамматика типа семьи: примитивы с квалификаторами, ссылочные типы, категории целиком, составной через " + ") и control (input/checkbox, синонимы, GUID для неизвестных элементов, none для формата вовсе без тега). containsValue отдельным ключом не выражается: он выводится из наличия типа. Текст и шаблон в такой ячейке запрещены, параметр и расшифровка допустимы. Умолчания голых типов взяты платформенные (строка без длины безлимитна, число без параметров без ограничения разрядности), поэтому эмиттер типа свой, а не копия meta-compile; resolve_type_str скопирован из эталона семьи и объявлен в реестре дрейфа. Канон типа в ключе дедупликации палитры развёрнут: иначе разные написания одного типа дали бы две одинаковые записи формата и сдвинули бы все ссылки ячеек. mxl-validate: проверка согласованности таких форматов — тип без признака значения, ячейка с текстом и значением одновременно, посторонний тег внутри типа, формат значения у строки или колонки, неизвестный GUID элемента управления. Попутно сведены два расхождения портов mxl-validate: py молчал там, где ps1 писал строку об отсутствии шрифтов, и шапка подробного вывода печаталась в разной форме. Версии сведены: mxl-compile 1.41 в обоих портах (было 1.40/1.39). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
83bb5b6fd3
commit
7f743b18a9
@@ -59,7 +59,7 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -J
|
||||
styles: { name: { font, horizontalAlignment, verticalAlignment, textPlacement,
|
||||
backColor, textColor, border, borderColor, format, hidden } },
|
||||
areas: [{ name, columnSet, rows: [{ height, hidden, rowStyle, cells: [
|
||||
{ col, span, rowspan, style, param, detail, text, template }
|
||||
{ col, span, rowspan, style, param, detail, text, template, valueType, control }
|
||||
]}]}],
|
||||
namedAreas: [{ name, rows, cols }],
|
||||
columnSets: { name: { columns, columnWidths, columnStyles } }
|
||||
@@ -80,6 +80,7 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -J
|
||||
- `col` — 1-based позиция колонки
|
||||
- `rowspan` — объединение строк вниз (rowStyle учитывает занятые ячейки)
|
||||
- Содержимое ячейки задаётся одним из ключей: `param` — параметр заполнения, `text` — статический текст, `template` — текст со вставками `[Параметр]`
|
||||
- `valueType` делает ячейку полем ввода (`"Number(15,3,nonneg)"`, `"String(10)"`, `"CatalogRef.Валюты"`, составной через ` + `); текста в такой ячейке быть не может, а `control: "checkbox"` меняет поле ввода на флажок
|
||||
|
||||
Двухуровневая шапка массивами:
|
||||
```json
|
||||
|
||||
@@ -182,6 +182,8 @@
|
||||
| `detail` | нет | — | Параметр расшифровки (только с `param`) |
|
||||
| `text` | нет | — | Статический текст. Строка или объект `{ ru, en }` — см. ниже |
|
||||
| `template` | нет | — | Шаблонный текст с `[Параметр]`. Строка или объект, как `text` |
|
||||
| `valueType` | нет | — | Тип значения: ячейка становится полем ввода (см. ниже) |
|
||||
| `control` | нет | `input` | Элемент управления поля ввода: `input` или `checkbox`. Только вместе с `valueType` |
|
||||
|
||||
### Содержимое ячейки
|
||||
|
||||
@@ -212,6 +214,44 @@
|
||||
|
||||
Пустая строка — это текст: ячейка с `"text": ""` даёт пустую надпись, а не ячейку без текста.
|
||||
|
||||
## Ячейка-поле ввода
|
||||
|
||||
Ячейка может не показывать текст, а принимать значение от пользователя — так делают макеты для
|
||||
ввода данных. Достаточно задать тип значения:
|
||||
|
||||
```json
|
||||
{ "col": 1, "valueType": "Number(15,3,nonneg)" }
|
||||
{ "col": 2, "valueType": "String(10)" }
|
||||
{ "col": 3, "valueType": "Boolean", "control": "checkbox" }
|
||||
{ "col": 4, "valueType": "CatalogRef.Валюты" }
|
||||
{ "col": 5, "valueType": "Boolean + String + Date + CatalogRef.Валюты" }
|
||||
{ "col": 6, "valueType": "AnyRef" }
|
||||
```
|
||||
|
||||
Грамматика типа:
|
||||
|
||||
| Запись | Значение |
|
||||
|---|---|
|
||||
| `Boolean` | булево |
|
||||
| `String`, `String(10)`, `String(10,fixed)` | строка; без длины — неограниченная, `fixed` — фиксированной длины |
|
||||
| `Number`, `Number(15,3)`, `Number(15,3,nonneg)` | число; без параметров — без ограничения разрядности, `nonneg` — неотрицательное |
|
||||
| `Date`, `DateTime`, `Time` | дата, дата со временем, время |
|
||||
| `CatalogRef.Валюты`, `DocumentRef.Реализация`, `EnumRef.Статусы`, `DefinedType.Сумма` | ссылочный тип |
|
||||
| `CatalogRef`, `DocumentRef`, `AnyRef` | категория целиком: любая ссылка этого вида |
|
||||
| `A + B` | составной тип; повтор одного примитива недопустим |
|
||||
|
||||
Русские имена принимаются наравне с английскими: `Число(15,3)`, `Строка(10)`,
|
||||
`СправочникСсылка.Валюты`.
|
||||
|
||||
`text` и `template` в такой ячейке недопустимы — платформа не показывает текст там, где вводится
|
||||
значение. `param` и `detail` допустимы: они описывают заполнение и расшифровку, а не содержимое.
|
||||
|
||||
Пустой тип `"valueType": ""` — «ячейка содержит значение», но тип не ограничен.
|
||||
|
||||
`control` нужен редко: умолчание платформы — поле ввода, и оно применяется ко всем типам, включая
|
||||
`Boolean`. Флажок задаётся явно. Значение `"none"` (тега элемента управления нет вовсе) — форма
|
||||
раундтрипа, для ручного авторинга не нужна.
|
||||
|
||||
## `rowStyle` — оформление строки
|
||||
|
||||
Стиль применяется ко ВСЕЙ ширине строки: позиции без явных ячеек получают тот же стиль. Так в табличных строках получаются сплошные рамки. Он же становится оформлением самой строки — именно так платформа хранит строку, оформленную целиком.
|
||||
@@ -226,7 +266,8 @@ DSL описывает не все конструкции табличного
|
||||
round-trip** (`/mxl-decompile` → `/mxl-compile`): в JSON оно не попадает, в сгенерированный
|
||||
XML не возвращается.
|
||||
|
||||
- ячейки-поля ввода (`containsValue` / `valueType` / `controlType`);
|
||||
- начальное значение ячейки-поля ввода и сериализованные настройки её элемента управления
|
||||
(тип значения при этом переживает цикл);
|
||||
- объединения, не привязанные к ячейке (по всей высоте или ширине документа);
|
||||
- рисунки и картинки, в том числе штрихкоды, и примечания к ячейкам;
|
||||
- группировки строк и колонок;
|
||||
|
||||
@@ -74,4 +74,4 @@
|
||||
- `fillType` — выводится из того, каким ключом задано содержимое ячейки
|
||||
(`text` / `param` / `template`);
|
||||
- `containsValue`, `valueType`, `controlType` — свойства конкретной ячейки, а не общего
|
||||
оформления; сейчас не поддерживаются.
|
||||
оформления: задаются ключами ячейки `valueType` и `control`.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# mxl-compile v1.40 — Compile 1C spreadsheet from JSON
|
||||
# mxl-compile v1.41 — Compile 1C spreadsheet from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -621,6 +621,270 @@ function Resolve-Style {
|
||||
return $props
|
||||
}
|
||||
|
||||
# --- 5.9. Ячейка-поле ввода: тип значения и элемент управления ---
|
||||
# containsValue/valueType/controlType платформа держит в записи палитры формата, но принадлежат
|
||||
# они конкретной ЯЧЕЙКЕ: на корпусе ERP 370 197 ссылок на такие записи — все из <f>, ни одной
|
||||
# из строки, колонки или defaultFormatIndex. Поэтому в DSL это ключи ячейки, а не стиля.
|
||||
|
||||
# Прощающий ввод типа — общая семья Resolve-TypeStr (эталон meta-compile). Словарь синонимов
|
||||
# у каждого навыка свой: здесь только то, что бывает значением ячейки макета.
|
||||
$script:typeSynonyms = @{}
|
||||
$script:typeSynonyms["число"] = "Number"
|
||||
$script:typeSynonyms["строка"] = "String"
|
||||
$script:typeSynonyms["булево"] = "Boolean"
|
||||
$script:typeSynonyms["дата"] = "Date"
|
||||
$script:typeSynonyms["датавремя"] = "DateTime"
|
||||
$script:typeSynonyms["время"] = "Time"
|
||||
$script:typeSynonyms["number"] = "Number"
|
||||
$script:typeSynonyms["string"] = "String"
|
||||
$script:typeSynonyms["boolean"] = "Boolean"
|
||||
$script:typeSynonyms["bool"] = "Boolean"
|
||||
$script:typeSynonyms["date"] = "Date"
|
||||
$script:typeSynonyms["datetime"] = "DateTime"
|
||||
$script:typeSynonyms["time"] = "Time"
|
||||
$script:typeSynonyms["справочникссылка"] = "CatalogRef"
|
||||
$script:typeSynonyms["документссылка"] = "DocumentRef"
|
||||
$script:typeSynonyms["перечислениессылка"] = "EnumRef"
|
||||
$script:typeSynonyms["плансчетовссылка"] = "ChartOfAccountsRef"
|
||||
$script:typeSynonyms["планвидовхарактеристикссылка"] = "ChartOfCharacteristicTypesRef"
|
||||
$script:typeSynonyms["планвидоврасчётассылка"] = "ChartOfCalculationTypesRef"
|
||||
$script:typeSynonyms["планвидоврасчетассылка"] = "ChartOfCalculationTypesRef"
|
||||
$script:typeSynonyms["планобменассылка"] = "ExchangePlanRef"
|
||||
$script:typeSynonyms["бизнеспроцессссылка"] = "BusinessProcessRef"
|
||||
$script:typeSynonyms["задачассылка"] = "TaskRef"
|
||||
$script:typeSynonyms["любаяссылка"] = "AnyRef"
|
||||
$script:typeSynonyms["catalogref"] = "CatalogRef"
|
||||
$script:typeSynonyms["documentref"] = "DocumentRef"
|
||||
$script:typeSynonyms["enumref"] = "EnumRef"
|
||||
$script:typeSynonyms["anyref"] = "AnyRef"
|
||||
$script:typeSynonyms["определяемыйтип"] = "DefinedType"
|
||||
$script:typeSynonyms["definedtype"] = "DefinedType"
|
||||
|
||||
# Голые метатипы-категории («любой объект категории») — множество, а не тип: <v8:TypeSet>.
|
||||
$script:valueTypeSets = @('CatalogRef', 'DocumentRef', 'EnumRef', 'ChartOfAccountsRef',
|
||||
'ChartOfCharacteristicTypesRef', 'ChartOfCalculationTypesRef', 'ExchangePlanRef',
|
||||
'BusinessProcessRef', 'TaskRef', 'AnyRef', 'AnyIBRef')
|
||||
# Категории ссылочных типов с именем объекта — <v8:Type>.
|
||||
$script:valueRefKinds = @('CatalogRef', 'DocumentRef', 'EnumRef', 'ChartOfAccountsRef',
|
||||
'ChartOfCharacteristicTypesRef', 'ChartOfCalculationTypesRef', 'ExchangePlanRef',
|
||||
'BusinessProcessRef', 'BusinessProcessRoutePointRef', 'TaskRef')
|
||||
|
||||
# Элемент управления. В выгрузке — GUID, имён у платформы в XML нет вовсе, поэтому канон DSL
|
||||
# придуман: input и checkbox. Умолчание платформы — поле ввода для ВСЕХ типов, включая Булево
|
||||
# (корпус: 63 629 форматов против 7 у флажка), поэтому input не пишем в XML как «по умолчанию»,
|
||||
# а эмитим всегда — так делает платформа.
|
||||
$script:valueControlGuids = @{
|
||||
'input' = '381ed624-9217-4e63-85db-c4c3cb87daae'
|
||||
'checkbox' = '35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26'
|
||||
}
|
||||
$script:valueControlSynonyms = @{
|
||||
# Ключи нормализованы: без пробелов, в нижнем регистре («Поле ввода» → «полеввода»).
|
||||
'полеввода' = 'input'; 'inputfield' = 'input'
|
||||
'полефлажка' = 'checkbox'; 'флажок' = 'checkbox'; 'checkboxfield' = 'checkbox'
|
||||
}
|
||||
|
||||
function Resolve-TypeStr {
|
||||
param([string]$typeStr)
|
||||
if (-not $typeStr) { return $typeStr }
|
||||
|
||||
# Прощающий ввод: ведущий префикс приходит копипастой из выгрузки. Без срезания он ломает
|
||||
# поиск в словаре — русское имя типа остаётся непереведённым, и платформа отвечает
|
||||
# «Неизвестное имя типа». cfg: снимаем всегда — он однозначно означает текущую конфигурацию.
|
||||
# Сгенерированный dNpM: (в корпусе на этом URI встречаются d4p1, d5p1, d6p1 — имя префикса
|
||||
# платформа выдаёт по порядку объявления) снимаем ТОЛЬКО у ссылочных типов, с точкой:
|
||||
# сам по себе префикс многозначен — в формах d5p1:Chart, d5p1:TextDocument,
|
||||
# d5p1:GeographicalSchema адресуют чужие пространства имён, и там он часть значения.
|
||||
if ($typeStr.StartsWith('cfg:')) {
|
||||
$typeStr = $typeStr.Substring(4)
|
||||
} elseif ($typeStr.Contains('.') -and $typeStr -match '^d\d+p\d+:') {
|
||||
$typeStr = $typeStr.Substring($typeStr.IndexOf(':') + 1)
|
||||
}
|
||||
|
||||
# Параметризованные типы: Number(15,2), Строка(100)
|
||||
if ($typeStr -match '^([^(]+)\((.+)\)$') {
|
||||
$baseName = $Matches[1].Trim()
|
||||
$params = $Matches[2]
|
||||
$resolved = $script:typeSynonyms[$baseName.ToLower()]
|
||||
if ($resolved) { return "$resolved($params)" }
|
||||
return $typeStr
|
||||
}
|
||||
|
||||
# Ссылочные типы: СправочникСсылка.Организации → CatalogRef.Организации
|
||||
if ($typeStr.Contains('.')) {
|
||||
$dotIdx = $typeStr.IndexOf('.')
|
||||
$prefix = $typeStr.Substring(0, $dotIdx)
|
||||
$suffix = $typeStr.Substring($dotIdx) # includes the dot
|
||||
$resolved = $script:typeSynonyms[$prefix.ToLower()]
|
||||
if ($resolved) { return "$resolved$suffix" }
|
||||
return $typeStr
|
||||
}
|
||||
|
||||
# Простое имя
|
||||
$resolved = $script:typeSynonyms[$typeStr.ToLower()]
|
||||
if ($resolved) { return $resolved }
|
||||
return $typeStr
|
||||
}
|
||||
|
||||
# Канон типа: развёрнутая запись со всеми умолчаниями. Она же ложится в ключ дедупликации
|
||||
# палитры, поэтому «Число(15,3)» и «Number(15,3)» обязаны дать ОДНУ запись формата — иначе
|
||||
# палитра распухнет на дубли и все ссылки <f> уедут.
|
||||
# Умолчания здесь ПЛАТФОРМЕННЫЕ, а не как у реквизита метаданных: голая строка — безлимитная
|
||||
# (Length 0), голое число — 0,0 (проверено на макетах, собранных Конфигуратором).
|
||||
function Get-CanonValueType {
|
||||
param([string]$typeStr, [string]$where)
|
||||
$parts = @()
|
||||
$seen = @{}
|
||||
foreach ($raw in ($typeStr -split '[+|]')) {
|
||||
$p = Resolve-TypeStr $raw.Trim()
|
||||
if (-not $p) { continue }
|
||||
$canon = $null
|
||||
$kind = $null
|
||||
if ($p -ceq 'Boolean') {
|
||||
$canon = 'Boolean'; $kind = 'Boolean'
|
||||
} elseif ($p -match '^String(\((\d+)(\s*,\s*(fixed|variable))?\))?$') {
|
||||
$len = if ($Matches[2]) { $Matches[2] } else { '0' }
|
||||
$al = if ($Matches[4] -and $Matches[4].ToLowerInvariant() -eq 'fixed') { 'fixed' } else { 'variable' }
|
||||
$canon = "String($len,$al)"; $kind = 'String'
|
||||
} elseif ($p -match '^Number(\((\d+)(\s*,\s*(\d+))?(\s*,\s*(nonneg|any))?\))?$') {
|
||||
$digits = if ($Matches[2]) { $Matches[2] } else { '0' }
|
||||
$fraction = if ($Matches[4]) { $Matches[4] } else { '0' }
|
||||
$sign = if ($Matches[6] -and $Matches[6].ToLowerInvariant() -eq 'nonneg') { 'nonneg' } else { 'any' }
|
||||
$canon = "Number($digits,$fraction,$sign)"; $kind = 'Number'
|
||||
} elseif ($p -ceq 'Date' -or $p -ceq 'DateTime' -or $p -ceq 'Time') {
|
||||
$canon = $p; $kind = 'Date'
|
||||
} elseif ($p -match '^(DefinedType|Characteristic)\.(.+)$') {
|
||||
$canon = $p; $kind = "set:$p"
|
||||
} elseif ($p.Contains('.')) {
|
||||
$kindName = $p.Substring(0, $p.IndexOf('.'))
|
||||
if ($script:valueRefKinds -ccontains $kindName) {
|
||||
$canon = $p; $kind = "ref:$p"
|
||||
} else {
|
||||
[Console]::Error.WriteLine("Unknown value type `"$($raw.Trim())`" ($where). Reference kinds: $($script:valueRefKinds -join ', ')")
|
||||
exit 1
|
||||
}
|
||||
} elseif ($p.Contains(':')) {
|
||||
# Чужое пространство имён — пишем как есть: калечить его мы не вправе.
|
||||
$canon = $p; $kind = "raw:$p"
|
||||
} elseif ($script:valueTypeSets -ccontains $p) {
|
||||
$canon = $p; $kind = "set:$p"
|
||||
} else {
|
||||
[Console]::Error.WriteLine("Unknown value type `"$($raw.Trim())`" ($where). Expected: Boolean, String(N), Number(D,F), Date, <Kind>Ref.<Name> or a bare metatype")
|
||||
exit 1
|
||||
}
|
||||
# Повтор одного вида в составном типе платформа выразить не может: блок квалификаторов
|
||||
# внутри <valueType> один на вид.
|
||||
if ($seen.ContainsKey($kind)) {
|
||||
[Console]::Error.WriteLine("Duplicate type `"$canon`" in composite value type ($where)")
|
||||
exit 1
|
||||
}
|
||||
$seen[$kind] = $true
|
||||
$parts += $canon
|
||||
}
|
||||
if ($parts.Count -eq 0) {
|
||||
[Console]::Error.WriteLine("Empty value type ($where)")
|
||||
exit 1
|
||||
}
|
||||
return ($parts -join ' + ')
|
||||
}
|
||||
|
||||
# Содержимое <valueType> по КАНОНУ — умолчаний здесь нет, они уже развёрнуты. Порядок снят
|
||||
# с платформы: сначала ВСЕ <v8:Type>/<v8:TypeSet> в порядке источника, затем блоки
|
||||
# квалификаторов Number → String → Date. Ссылочные типы несут ЛОКАЛЬНОЕ объявление xmlns
|
||||
# на каждом узле — в макете префикс current-config всегда d4p1.
|
||||
function Emit-ValueTypeContent {
|
||||
param([string]$indent, [string]$canonType)
|
||||
$cfgNs = 'http://v8.1c.ru/8.1/data/enterprise/current-config'
|
||||
$typeLines = @()
|
||||
$quals = @{}
|
||||
foreach ($p in ($canonType -split ' \+ ')) {
|
||||
if ($p -ceq 'Boolean') {
|
||||
$typeLines += "$indent<v8:Type>xs:boolean</v8:Type>"
|
||||
} elseif ($p -match '^String\((\d+),(fixed|variable)\)$') {
|
||||
$len = $Matches[1]
|
||||
$al = if ($Matches[2] -ceq 'fixed') { 'Fixed' } else { 'Variable' }
|
||||
$typeLines += "$indent<v8:Type>xs:string</v8:Type>"
|
||||
$quals['String'] = @(
|
||||
"$indent<v8:StringQualifiers>",
|
||||
"$indent`t<v8:Length>$len</v8:Length>",
|
||||
"$indent`t<v8:AllowedLength>$al</v8:AllowedLength>",
|
||||
"$indent</v8:StringQualifiers>")
|
||||
} elseif ($p -match '^Number\((\d+),(\d+),(nonneg|any)\)$') {
|
||||
$digits = $Matches[1]
|
||||
$fraction = $Matches[2]
|
||||
$sign = if ($Matches[3] -ceq 'nonneg') { 'Nonnegative' } else { 'Any' }
|
||||
$typeLines += "$indent<v8:Type>xs:decimal</v8:Type>"
|
||||
$quals['Number'] = @(
|
||||
"$indent<v8:NumberQualifiers>",
|
||||
"$indent`t<v8:Digits>$digits</v8:Digits>",
|
||||
"$indent`t<v8:FractionDigits>$fraction</v8:FractionDigits>",
|
||||
"$indent`t<v8:AllowedSign>$sign</v8:AllowedSign>",
|
||||
"$indent</v8:NumberQualifiers>")
|
||||
} elseif ($p -ceq 'Date' -or $p -ceq 'DateTime' -or $p -ceq 'Time') {
|
||||
$typeLines += "$indent<v8:Type>xs:dateTime</v8:Type>"
|
||||
$quals['Date'] = @(
|
||||
"$indent<v8:DateQualifiers>",
|
||||
"$indent`t<v8:DateFractions>$p</v8:DateFractions>",
|
||||
"$indent</v8:DateQualifiers>")
|
||||
} elseif ($p -match '^(DefinedType|Characteristic)\.') {
|
||||
$typeLines += "$indent<v8:TypeSet xmlns:d4p1=`"$cfgNs`">d4p1:$p</v8:TypeSet>"
|
||||
} elseif ($p.Contains('.')) {
|
||||
$typeLines += "$indent<v8:Type xmlns:d4p1=`"$cfgNs`">d4p1:$p</v8:Type>"
|
||||
} elseif ($p.Contains(':')) {
|
||||
$typeLines += "$indent<v8:Type>$p</v8:Type>"
|
||||
} else {
|
||||
$typeLines += "$indent<v8:TypeSet xmlns:d4p1=`"$cfgNs`">d4p1:$p</v8:TypeSet>"
|
||||
}
|
||||
}
|
||||
foreach ($l in $typeLines) { X $l }
|
||||
foreach ($q in @('Number', 'String', 'Date')) {
|
||||
if ($quals.ContainsKey($q)) { foreach ($l in $quals[$q]) { X $l } }
|
||||
}
|
||||
}
|
||||
|
||||
# Свойства значения ячейки — пустой набор, если ячейка обычная. Считаются ОДНОЙ функцией:
|
||||
# пре-проход регистрации палитры и генерация обязаны получить один и тот же набор, иначе
|
||||
# состав палитры разойдётся и все ссылки <f> сдвинутся.
|
||||
function Get-CellValueProps {
|
||||
param($cell, [string]$where)
|
||||
$props = @{}
|
||||
$vt = $cell.valueType
|
||||
$ctl = $cell.control
|
||||
if ($null -eq $vt) {
|
||||
if ($null -ne $ctl -and "$ctl" -ne '') {
|
||||
[Console]::Error.WriteLine("Cell 'control' requires 'valueType' ($where)")
|
||||
exit 1
|
||||
}
|
||||
return $props
|
||||
}
|
||||
# Ячейка, содержащая значение, текста не несёт: платформа этого не допускает, и в корпусе
|
||||
# нет ни одной такой ячейки из 370 197.
|
||||
if ($null -ne $cell.text -or $null -ne $cell.template) {
|
||||
[Console]::Error.WriteLine("Cell with 'valueType' cannot have 'text' or 'template' ($where)")
|
||||
exit 1
|
||||
}
|
||||
$props['containsValue'] = 'true'
|
||||
# Пустая строка — третье состояние: <containsValue> есть, тип не задан (<valueType/>).
|
||||
$props['valueType'] = if ("$vt" -eq '') { '' } else { Get-CanonValueType "$vt" $where }
|
||||
|
||||
$name = 'input'
|
||||
if ($null -ne $ctl -and "$ctl" -ne '') {
|
||||
$norm = ("$ctl" -replace '\s', '').ToLowerInvariant()
|
||||
if ($script:valueControlSynonyms.ContainsKey($norm)) { $norm = $script:valueControlSynonyms[$norm] }
|
||||
$name = $norm
|
||||
}
|
||||
if ($name -ceq 'none') { return $props } # формат вовсе без <controlType>
|
||||
if ($script:valueControlGuids.ContainsKey($name)) {
|
||||
$props['controlType'] = $script:valueControlGuids[$name]
|
||||
} elseif ($name -match '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') {
|
||||
# Неизвестный элемент управления сохраняем как есть — терять его нельзя.
|
||||
$props['controlType'] = $name
|
||||
} else {
|
||||
[Console]::Error.WriteLine("Unknown 'control' value `"$ctl`" ($where). Allowed: input, checkbox, none or a GUID")
|
||||
exit 1
|
||||
}
|
||||
return $props
|
||||
}
|
||||
|
||||
# --- 6. Format palette builder ---
|
||||
|
||||
$formatRegistry = [ordered]@{} # key -> hashtable with properties
|
||||
@@ -843,8 +1107,13 @@ function Get-FillType {
|
||||
|
||||
# Helper: register a cell format and return its index
|
||||
function Register-CellFormat {
|
||||
param($styleName, [string]$fillType)
|
||||
param($styleName, [string]$fillType, [hashtable]$valueProps)
|
||||
$resolved = Resolve-Style -styleName $styleName -fillType $fillType
|
||||
# Свойства значения кладём ПОВЕРХ стиля — до проверки на пустоту: у ячейки-поля ввода
|
||||
# оформления может не быть вовсе, и без слияния она получила бы <f>0</f>, потеряв значение.
|
||||
if ($valueProps) {
|
||||
foreach ($k in $valueProps.Keys) { $resolved[$k] = $valueProps[$k] }
|
||||
}
|
||||
# У ячейки без собственного оформления формата НЕТ вовсе: <f>0</f>, где ноль — не индекс
|
||||
# записи, а «формата нет». В корпусе так у 170 710 ячеек против 50 635, ссылающихся на
|
||||
# формат по умолчанию; <f>0</f> встречается в 71% макетов.
|
||||
@@ -870,7 +1139,8 @@ function Set-CellProp {
|
||||
# это ru, en, ru1, Русский.
|
||||
function Test-CellObject {
|
||||
param($el)
|
||||
$cellKeys = @('col', 'span', 'rowspan', 'style', 'param', 'detail', 'text', 'template')
|
||||
$cellKeys = @('col', 'span', 'rowspan', 'style', 'param', 'detail', 'text', 'template',
|
||||
'valueType', 'control')
|
||||
foreach ($p in $el.PSObject.Properties) {
|
||||
if ($cellKeys -contains $p.Name) { return $true }
|
||||
}
|
||||
@@ -1051,7 +1321,8 @@ foreach ($area in $def.areas) {
|
||||
foreach ($cell in $row.cells) {
|
||||
$cellStyle = if ($cell.style) { $cell.style } elseif ($cellsStyle) { $cellsStyle } else { "default" }
|
||||
$ft = Get-FillType $cell
|
||||
Register-CellFormat -styleName $cellStyle -fillType $ft | Out-Null
|
||||
$vp = Get-CellValueProps $cell "area `"$($area.name)`""
|
||||
Register-CellFormat -styleName $cellStyle -fillType $ft -valueProps $vp | Out-Null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1332,7 +1603,8 @@ foreach ($area in $def.areas) {
|
||||
$rowspan = if ($cell.rowspan) { [int]$cell.rowspan } else { 1 }
|
||||
$cellStyle = if ($cell.style) { $cell.style } elseif ($cellsStyle) { $cellsStyle } else { "default" }
|
||||
$ft = Get-FillType $cell
|
||||
$fmtIdx = Register-CellFormat -styleName $cellStyle -fillType $ft
|
||||
$vp = Get-CellValueProps $cell "area `"$areaName`", row $($localRow + 1)"
|
||||
$fmtIdx = Register-CellFormat -styleName $cellStyle -fillType $ft -valueProps $vp
|
||||
|
||||
$cellInfo = @{
|
||||
Col = $colStart - 1 # 0-based
|
||||
@@ -1659,6 +1931,15 @@ foreach ($key in $formatRegistry.Keys) {
|
||||
X "`t`t`t`t<v8:content>$(Esc-XmlText $val)</v8:content>"
|
||||
X "`t`t`t</v8:item>"
|
||||
X "`t`t</$tag>"
|
||||
} elseif ($tag -ceq 'valueType') {
|
||||
# Пустой тип — самостоятельное состояние: «содержит значение», тип не задан.
|
||||
if ("$val" -eq '') {
|
||||
X "`t`t<valueType/>"
|
||||
} else {
|
||||
X "`t`t<valueType>"
|
||||
Emit-ValueTypeContent "`t`t`t" "$val"
|
||||
X "`t`t</valueType>"
|
||||
}
|
||||
} elseif ($script:formatTagKind[$tag] -ceq 'color' -and (Get-ColorNamespace "$val")) {
|
||||
# web/win-палитры в корне документа не объявлены — платформа дописывает объявление
|
||||
# прямо на узел и пишет значение с этим префиксом.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-compile v1.39 — Compile 1C spreadsheet from JSON
|
||||
# mxl-compile v1.41 — Compile 1C spreadsheet from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import hashlib
|
||||
@@ -439,6 +439,251 @@ def get_format_key(props):
|
||||
return '|'.join(parts)
|
||||
|
||||
|
||||
# --- Ячейка-поле ввода: тип значения и элемент управления ---
|
||||
# containsValue/valueType/controlType платформа держит в записи палитры формата, но принадлежат
|
||||
# они конкретной ЯЧЕЙКЕ: на корпусе ERP 370 197 ссылок на такие записи — все из <f>, ни одной
|
||||
# из строки, колонки или defaultFormatIndex. Поэтому в DSL это ключи ячейки, а не стиля.
|
||||
|
||||
# Прощающий ввод типа — общая семья resolve_type_str (эталон meta-compile). Словарь синонимов
|
||||
# у каждого навыка свой: здесь только то, что бывает значением ячейки макета.
|
||||
TYPE_SYNONYMS = {
|
||||
'число': 'Number', 'строка': 'String', 'булево': 'Boolean',
|
||||
'дата': 'Date', 'датавремя': 'DateTime', 'время': 'Time',
|
||||
'number': 'Number', 'string': 'String', 'boolean': 'Boolean', 'bool': 'Boolean',
|
||||
'date': 'Date', 'datetime': 'DateTime', 'time': 'Time',
|
||||
'справочникссылка': 'CatalogRef',
|
||||
'документссылка': 'DocumentRef',
|
||||
'перечислениессылка': 'EnumRef',
|
||||
'плансчетовссылка': 'ChartOfAccountsRef',
|
||||
'планвидовхарактеристикссылка': 'ChartOfCharacteristicTypesRef',
|
||||
'планвидоврасчётассылка': 'ChartOfCalculationTypesRef',
|
||||
'планвидоврасчетассылка': 'ChartOfCalculationTypesRef',
|
||||
'планобменассылка': 'ExchangePlanRef',
|
||||
'бизнеспроцессссылка': 'BusinessProcessRef',
|
||||
'задачассылка': 'TaskRef',
|
||||
'любаяссылка': 'AnyRef',
|
||||
'catalogref': 'CatalogRef', 'documentref': 'DocumentRef', 'enumref': 'EnumRef',
|
||||
'anyref': 'AnyRef',
|
||||
'определяемыйтип': 'DefinedType', 'definedtype': 'DefinedType',
|
||||
}
|
||||
|
||||
# Голые метатипы-категории («любой объект категории») — множество, а не тип: <v8:TypeSet>.
|
||||
VALUE_TYPE_SETS = ('CatalogRef', 'DocumentRef', 'EnumRef', 'ChartOfAccountsRef',
|
||||
'ChartOfCharacteristicTypesRef', 'ChartOfCalculationTypesRef', 'ExchangePlanRef',
|
||||
'BusinessProcessRef', 'TaskRef', 'AnyRef', 'AnyIBRef')
|
||||
# Категории ссылочных типов с именем объекта — <v8:Type>.
|
||||
VALUE_REF_KINDS = ('CatalogRef', 'DocumentRef', 'EnumRef', 'ChartOfAccountsRef',
|
||||
'ChartOfCharacteristicTypesRef', 'ChartOfCalculationTypesRef', 'ExchangePlanRef',
|
||||
'BusinessProcessRef', 'BusinessProcessRoutePointRef', 'TaskRef')
|
||||
|
||||
# Элемент управления. В выгрузке — GUID, имён у платформы в XML нет вовсе, поэтому канон DSL
|
||||
# придуман: input и checkbox. Умолчание платформы — поле ввода для ВСЕХ типов, включая Булево
|
||||
# (корпус: 63 629 форматов против 7 у флажка), поэтому input не пишем в XML как «по умолчанию»,
|
||||
# а эмитим всегда — так делает платформа.
|
||||
VALUE_CONTROL_GUIDS = {
|
||||
'input': '381ed624-9217-4e63-85db-c4c3cb87daae',
|
||||
'checkbox': '35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26',
|
||||
}
|
||||
VALUE_CONTROL_SYNONYMS = {
|
||||
# Ключи нормализованы: без пробелов, в нижнем регистре («Поле ввода» → «полеввода»).
|
||||
'полеввода': 'input', 'inputfield': 'input',
|
||||
'полефлажка': 'checkbox', 'флажок': 'checkbox', 'checkboxfield': 'checkbox',
|
||||
}
|
||||
|
||||
CFG_NS = 'http://v8.1c.ru/8.1/data/enterprise/current-config'
|
||||
|
||||
|
||||
def resolve_type_str(type_str):
|
||||
if not type_str:
|
||||
return type_str
|
||||
|
||||
# Прощающий ввод: ведущий префикс приходит копипастой из выгрузки. Без срезания он ломает
|
||||
# поиск в словаре — русское имя типа остаётся непереведённым, и платформа отвечает
|
||||
# «Неизвестное имя типа». cfg: снимаем всегда — он однозначно означает текущую конфигурацию.
|
||||
# Сгенерированный dNpM: (в корпусе на этом URI встречаются d4p1, d5p1, d6p1 — имя префикса
|
||||
# платформа выдаёт по порядку объявления) снимаем ТОЛЬКО у ссылочных типов, с точкой:
|
||||
# сам по себе префикс многозначен — в формах d5p1:Chart, d5p1:TextDocument,
|
||||
# d5p1:GeographicalSchema адресуют чужие пространства имён, и там он часть значения.
|
||||
if type_str.startswith('cfg:'):
|
||||
type_str = type_str[4:]
|
||||
elif '.' in type_str and re.match(r'^d\d+p\d+:', type_str):
|
||||
type_str = type_str[type_str.index(':') + 1:]
|
||||
|
||||
# Параметризованные типы: Number(15,2), Строка(100)
|
||||
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
|
||||
if m:
|
||||
base_name = m.group(1).strip()
|
||||
params = m.group(2)
|
||||
resolved = TYPE_SYNONYMS.get(base_name.lower())
|
||||
if resolved:
|
||||
return f'{resolved}({params})'
|
||||
return type_str
|
||||
|
||||
# Ссылочные типы: СправочникСсылка.Организации → CatalogRef.Организации
|
||||
if '.' in type_str:
|
||||
dot_idx = type_str.index('.')
|
||||
prefix = type_str[:dot_idx]
|
||||
suffix = type_str[dot_idx:] # includes the dot
|
||||
resolved = TYPE_SYNONYMS.get(prefix.lower())
|
||||
if resolved:
|
||||
return f'{resolved}{suffix}'
|
||||
return type_str
|
||||
|
||||
# Простое имя
|
||||
resolved = TYPE_SYNONYMS.get(type_str.lower())
|
||||
if resolved:
|
||||
return resolved
|
||||
return type_str
|
||||
|
||||
|
||||
def canon_value_type(type_str, where):
|
||||
"""Канон типа: развёрнутая запись со всеми умолчаниями. Она же ложится в ключ дедупликации
|
||||
палитры, поэтому «Число(15,3)» и «Number(15,3)» обязаны дать ОДНУ запись формата — иначе
|
||||
палитра распухнет на дубли и все ссылки <f> уедут.
|
||||
Умолчания здесь ПЛАТФОРМЕННЫЕ, а не как у реквизита метаданных: голая строка — безлимитная
|
||||
(Length 0), голое число — 0,0 (проверено на макетах, собранных Конфигуратором)."""
|
||||
parts = []
|
||||
seen = set()
|
||||
for raw in re.split(r'[+|]', type_str):
|
||||
p = resolve_type_str(raw.strip())
|
||||
if not p:
|
||||
continue
|
||||
m_str = re.match(r'^String(\((\d+)(\s*,\s*(fixed|variable))?\))?$', p)
|
||||
m_num = re.match(r'^Number(\((\d+)(\s*,\s*(\d+))?(\s*,\s*(nonneg|any))?\))?$', p)
|
||||
if p == 'Boolean':
|
||||
canon, kind = 'Boolean', 'Boolean'
|
||||
elif m_str:
|
||||
length = m_str.group(2) if m_str.group(2) else '0'
|
||||
al = 'fixed' if (m_str.group(4) and m_str.group(4).lower() == 'fixed') else 'variable'
|
||||
canon, kind = f'String({length},{al})', 'String'
|
||||
elif m_num:
|
||||
digits = m_num.group(2) if m_num.group(2) else '0'
|
||||
fraction = m_num.group(4) if m_num.group(4) else '0'
|
||||
sign = 'nonneg' if (m_num.group(6) and m_num.group(6).lower() == 'nonneg') else 'any'
|
||||
canon, kind = f'Number({digits},{fraction},{sign})', 'Number'
|
||||
elif p in ('Date', 'DateTime', 'Time'):
|
||||
canon, kind = p, 'Date'
|
||||
elif re.match(r'^(DefinedType|Characteristic)\.(.+)$', p):
|
||||
canon, kind = p, f'set:{p}'
|
||||
elif '.' in p:
|
||||
kind_name = p[:p.index('.')]
|
||||
if kind_name in VALUE_REF_KINDS:
|
||||
canon, kind = p, f'ref:{p}'
|
||||
else:
|
||||
print(f'Unknown value type "{raw.strip()}" ({where}).'
|
||||
f' Reference kinds: {", ".join(VALUE_REF_KINDS)}', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
elif ':' in p:
|
||||
# Чужое пространство имён — пишем как есть: калечить его мы не вправе.
|
||||
canon, kind = p, f'raw:{p}'
|
||||
elif p in VALUE_TYPE_SETS:
|
||||
canon, kind = p, f'set:{p}'
|
||||
else:
|
||||
print(f'Unknown value type "{raw.strip()}" ({where}). Expected: Boolean, String(N),'
|
||||
f' Number(D,F), Date, <Kind>Ref.<Name> or a bare metatype', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
# Повтор одного вида в составном типе платформа выразить не может: блок квалификаторов
|
||||
# внутри <valueType> один на вид.
|
||||
if kind in seen:
|
||||
print(f'Duplicate type "{canon}" in composite value type ({where})', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
seen.add(kind)
|
||||
parts.append(canon)
|
||||
if not parts:
|
||||
print(f'Empty value type ({where})', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
return ' + '.join(parts)
|
||||
|
||||
|
||||
def emit_value_type_content(lines, indent, canon_type):
|
||||
"""Содержимое <valueType> по КАНОНУ — умолчаний здесь нет, они уже развёрнуты. Порядок снят
|
||||
с платформы: сначала ВСЕ <v8:Type>/<v8:TypeSet> в порядке источника, затем блоки
|
||||
квалификаторов Number → String → Date. Ссылочные типы несут ЛОКАЛЬНОЕ объявление xmlns
|
||||
на каждом узле — в макете префикс current-config всегда d4p1."""
|
||||
type_lines = []
|
||||
quals = {}
|
||||
for p in canon_type.split(' + '):
|
||||
m_str = re.match(r'^String\((\d+),(fixed|variable)\)$', p)
|
||||
m_num = re.match(r'^Number\((\d+),(\d+),(nonneg|any)\)$', p)
|
||||
if p == 'Boolean':
|
||||
type_lines.append(f'{indent}<v8:Type>xs:boolean</v8:Type>')
|
||||
elif m_str:
|
||||
al = 'Fixed' if m_str.group(2) == 'fixed' else 'Variable'
|
||||
type_lines.append(f'{indent}<v8:Type>xs:string</v8:Type>')
|
||||
quals['String'] = [
|
||||
f'{indent}<v8:StringQualifiers>',
|
||||
f'{indent}\t<v8:Length>{m_str.group(1)}</v8:Length>',
|
||||
f'{indent}\t<v8:AllowedLength>{al}</v8:AllowedLength>',
|
||||
f'{indent}</v8:StringQualifiers>']
|
||||
elif m_num:
|
||||
sign = 'Nonnegative' if m_num.group(3) == 'nonneg' else 'Any'
|
||||
type_lines.append(f'{indent}<v8:Type>xs:decimal</v8:Type>')
|
||||
quals['Number'] = [
|
||||
f'{indent}<v8:NumberQualifiers>',
|
||||
f'{indent}\t<v8:Digits>{m_num.group(1)}</v8:Digits>',
|
||||
f'{indent}\t<v8:FractionDigits>{m_num.group(2)}</v8:FractionDigits>',
|
||||
f'{indent}\t<v8:AllowedSign>{sign}</v8:AllowedSign>',
|
||||
f'{indent}</v8:NumberQualifiers>']
|
||||
elif p in ('Date', 'DateTime', 'Time'):
|
||||
type_lines.append(f'{indent}<v8:Type>xs:dateTime</v8:Type>')
|
||||
quals['Date'] = [
|
||||
f'{indent}<v8:DateQualifiers>',
|
||||
f'{indent}\t<v8:DateFractions>{p}</v8:DateFractions>',
|
||||
f'{indent}</v8:DateQualifiers>']
|
||||
elif re.match(r'^(DefinedType|Characteristic)\.', p):
|
||||
type_lines.append(f'{indent}<v8:TypeSet xmlns:d4p1="{CFG_NS}">d4p1:{p}</v8:TypeSet>')
|
||||
elif '.' in p:
|
||||
type_lines.append(f'{indent}<v8:Type xmlns:d4p1="{CFG_NS}">d4p1:{p}</v8:Type>')
|
||||
elif ':' in p:
|
||||
type_lines.append(f'{indent}<v8:Type>{p}</v8:Type>')
|
||||
else:
|
||||
type_lines.append(f'{indent}<v8:TypeSet xmlns:d4p1="{CFG_NS}">d4p1:{p}</v8:TypeSet>')
|
||||
lines.extend(type_lines)
|
||||
for q in ('Number', 'String', 'Date'):
|
||||
if q in quals:
|
||||
lines.extend(quals[q])
|
||||
|
||||
|
||||
def cell_value_props(cell, where):
|
||||
"""Свойства значения ячейки — пустой набор, если ячейка обычная. Считаются ОДНОЙ функцией:
|
||||
пре-проход регистрации палитры и генерация обязаны получить один и тот же набор, иначе
|
||||
состав палитры разойдётся и все ссылки <f> сдвинутся."""
|
||||
props = {}
|
||||
vt = cell.get('valueType')
|
||||
ctl = cell.get('control')
|
||||
if vt is None:
|
||||
if ctl is not None and str(ctl) != '':
|
||||
print(f"Cell 'control' requires 'valueType' ({where})", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
return props
|
||||
# Ячейка, содержащая значение, текста не несёт: платформа этого не допускает, и в корпусе
|
||||
# нет ни одной такой ячейки из 370 197.
|
||||
if cell.get('text') is not None or cell.get('template') is not None:
|
||||
print(f"Cell with 'valueType' cannot have 'text' or 'template' ({where})", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
props['containsValue'] = 'true'
|
||||
# Пустая строка — третье состояние: <containsValue> есть, тип не задан (<valueType/>).
|
||||
props['valueType'] = '' if str(vt) == '' else canon_value_type(str(vt), where)
|
||||
|
||||
name = 'input'
|
||||
if ctl is not None and str(ctl) != '':
|
||||
norm = re.sub(r'\s', '', str(ctl)).lower()
|
||||
norm = VALUE_CONTROL_SYNONYMS.get(norm, norm)
|
||||
name = norm
|
||||
if name == 'none':
|
||||
return props # формат вовсе без <controlType>
|
||||
if name in VALUE_CONTROL_GUIDS:
|
||||
props['controlType'] = VALUE_CONTROL_GUIDS[name]
|
||||
elif re.match(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$', name):
|
||||
# Неизвестный элемент управления сохраняем как есть — терять его нельзя.
|
||||
props['controlType'] = name
|
||||
else:
|
||||
print(f'Unknown \'control\' value "{ctl}" ({where}).'
|
||||
f' Allowed: input, checkbox, none or a GUID', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
return props
|
||||
|
||||
|
||||
def main():
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
sys.stderr.reconfigure(encoding="utf-8")
|
||||
@@ -885,8 +1130,12 @@ def main():
|
||||
return ''
|
||||
|
||||
# Helper: register a cell format and return its index
|
||||
def register_cell_format(style_name, fill_type):
|
||||
def register_cell_format(style_name, fill_type, value_props=None):
|
||||
resolved = resolve_style(style_name, fill_type)
|
||||
# Свойства значения кладём ПОВЕРХ стиля — до проверки на пустоту: у ячейки-поля ввода
|
||||
# оформления может не быть вовсе, и без слияния она получила бы <f>0</f>, потеряв значение.
|
||||
if value_props:
|
||||
resolved.update(value_props)
|
||||
# У ячейки без собственного оформления формата НЕТ вовсе: <f>0</f>, где ноль — не
|
||||
# индекс записи, а «формата нет». В корпусе так у 170 710 ячеек против 50 635,
|
||||
# ссылающихся на формат по умолчанию; <f>0</f> встречается в 71% макетов.
|
||||
@@ -904,7 +1153,8 @@ def main():
|
||||
"""Объект описывает СВОЙСТВА ячейки или является её ЗНАЧЕНИЕМ: в первом случае среди
|
||||
ключей есть ключ схемы ячейки, во втором ключи — идентификаторы языков. Пересечений
|
||||
нет: в корпусе это ru, en, ru1, Русский."""
|
||||
cell_keys = ('col', 'span', 'rowspan', 'style', 'param', 'detail', 'text', 'template')
|
||||
cell_keys = ('col', 'span', 'rowspan', 'style', 'param', 'detail', 'text', 'template',
|
||||
'valueType', 'control')
|
||||
return any(k in el for k in cell_keys)
|
||||
|
||||
def expand_shorthand_row(row, area_name, row_idx, open_by_col, max_cols):
|
||||
@@ -1069,7 +1319,8 @@ def main():
|
||||
for cell in row['cells']:
|
||||
cell_style = cell.get('style') or cells_style or 'default'
|
||||
ft = get_fill_type(cell)
|
||||
register_cell_format(cell_style, ft)
|
||||
vp = cell_value_props(cell, f'area "{area.get("name") or ""}"')
|
||||
register_cell_format(cell_style, ft, vp)
|
||||
|
||||
# Формат по умолчанию — последняя запись палитры (см. выше).
|
||||
default_format_index = register_format({'width': default_width})
|
||||
@@ -1309,7 +1560,8 @@ def main():
|
||||
rowspan = int(cell.get('rowspan', 1))
|
||||
cell_style = cell.get('style') or cells_style or 'default'
|
||||
ft = get_fill_type(cell)
|
||||
fmt_idx = register_cell_format(cell_style, ft)
|
||||
vp = cell_value_props(cell, f'area "{area_name}", row {local_row + 1}')
|
||||
fmt_idx = register_cell_format(cell_style, ft, vp)
|
||||
|
||||
cell_info = {
|
||||
'Col': col_start - 1, # 0-based
|
||||
@@ -1603,6 +1855,14 @@ def main():
|
||||
lines.append(f'\t\t\t\t<v8:content>{esc_xml_text(val)}</v8:content>')
|
||||
lines.append('\t\t\t</v8:item>')
|
||||
lines.append(f'\t\t</{tag}>')
|
||||
elif tag == 'valueType':
|
||||
# Пустой тип — самостоятельное состояние: «содержит значение», тип не задан.
|
||||
if str(val) == '':
|
||||
lines.append('\t\t<valueType/>')
|
||||
else:
|
||||
lines.append('\t\t<valueType>')
|
||||
emit_value_type_content(lines, '\t\t\t', str(val))
|
||||
lines.append('\t\t</valueType>')
|
||||
elif kinds.get(tag) == 'color' and color_namespace(str(val)):
|
||||
# web/win-палитры в корне документа не объявлены — платформа дописывает
|
||||
# объявление прямо на узел и пишет значение с этим префиксом.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# mxl-decompile v1.20 — Decompile 1C spreadsheet to JSON
|
||||
# mxl-decompile v1.21 — Decompile 1C spreadsheet to JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -78,6 +78,78 @@ function ConvertTo-DslColor {
|
||||
return $val
|
||||
}
|
||||
|
||||
$CFG_NS = 'http://v8.1c.ru/8.1/data/enterprise/current-config'
|
||||
|
||||
# Элемент управления ячейки: в выгрузке это GUID, имён у платформы в XML нет.
|
||||
$valueControlNames = @{
|
||||
'381ed624-9217-4e63-85db-c4c3cb87daae' = 'input'
|
||||
'35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26' = 'checkbox'
|
||||
}
|
||||
|
||||
# Обратная функция к эмиттеру типа компилятора: <valueType> → строка DSL в КРАТЧАЙШЕЙ форме
|
||||
# (Boolean, String, String(10,fixed), Number(15,3,nonneg), DateTime, CatalogRef.X, AnyRef),
|
||||
# из которой компилятор восстановит тот же XML. Пустой тег → пустая строка: «содержит
|
||||
# значение» без указания типа — самостоятельное состояние.
|
||||
# Префикс ссылочного типа разрешаем по URI, а не по имени: локальное объявление платформа
|
||||
# называет сгенерированным dNpM. Чужое пространство имён оставляем как есть.
|
||||
function Get-ValueQualifier {
|
||||
param($quals, [string]$kind, [string]$name, [string]$default = '')
|
||||
if (-not $quals.ContainsKey($kind)) { return $default }
|
||||
$sub = $quals[$kind].SelectSingleNode("v8:$name", $ns)
|
||||
if ($sub -and $sub.InnerText) { return $sub.InnerText.Trim() }
|
||||
return $default
|
||||
}
|
||||
|
||||
function ConvertFrom-ValueTypeNode {
|
||||
param($node)
|
||||
$types = @()
|
||||
$quals = @{}
|
||||
foreach ($child in $node.ChildNodes) {
|
||||
if ($child.NodeType -ne [System.Xml.XmlNodeType]::Element) { continue }
|
||||
$tag = $child.get_LocalName()
|
||||
if ($tag -ceq 'Type' -or $tag -ceq 'TypeSet') {
|
||||
$types += ,@($child, $child.InnerText.Trim())
|
||||
} elseif ($tag -like '*Qualifiers') {
|
||||
$quals[$tag.Substring(0, $tag.Length - 'Qualifiers'.Length)] = $child
|
||||
}
|
||||
}
|
||||
|
||||
$parts = @()
|
||||
foreach ($t in $types) {
|
||||
$child = $t[0]
|
||||
$val = $t[1]
|
||||
if ($val -like '*:*') {
|
||||
$prefix = $val.Substring(0, $val.IndexOf(':'))
|
||||
$name = $val.Substring($val.IndexOf(':') + 1)
|
||||
# get_*(): XML-адаптер PowerShell перекрывает .NET-члены одноимёнными атрибутами узла.
|
||||
$uri = $child.GetNamespaceOfPrefix($prefix)
|
||||
if ($uri -ceq $CFG_NS) { $val = $name }
|
||||
elseif ($uri -ceq 'http://www.w3.org/2001/XMLSchema') { $val = "xs:$name" }
|
||||
}
|
||||
if ($val -ceq 'xs:boolean') {
|
||||
$parts += 'Boolean'
|
||||
} elseif ($val -ceq 'xs:string') {
|
||||
$length = Get-ValueQualifier $quals 'String' 'Length' '0'
|
||||
$fixed = (Get-ValueQualifier $quals 'String' 'AllowedLength' 'Variable') -ceq 'Fixed'
|
||||
if ($fixed) { $parts += "String($length,fixed)" }
|
||||
elseif ($length -ne '0') { $parts += "String($length)" }
|
||||
else { $parts += 'String' }
|
||||
} elseif ($val -ceq 'xs:decimal') {
|
||||
$digits = Get-ValueQualifier $quals 'Number' 'Digits' '0'
|
||||
$fraction = Get-ValueQualifier $quals 'Number' 'FractionDigits' '0'
|
||||
$nonneg = (Get-ValueQualifier $quals 'Number' 'AllowedSign' 'Any') -ceq 'Nonnegative'
|
||||
if ($nonneg) { $parts += "Number($digits,$fraction,nonneg)" }
|
||||
elseif ($digits -ne '0' -or $fraction -ne '0') { $parts += "Number($digits,$fraction)" }
|
||||
else { $parts += 'Number' }
|
||||
} elseif ($val -ceq 'xs:dateTime') {
|
||||
$parts += (Get-ValueQualifier $quals 'Date' 'DateFractions' 'DateTime')
|
||||
} else {
|
||||
$parts += $val
|
||||
}
|
||||
}
|
||||
return ($parts -join ' + ')
|
||||
}
|
||||
|
||||
# --- 2. Extract font palette ---
|
||||
|
||||
# Размер шрифта бывает дробным (8.3, 11.3 — в корпусе ERP это треть макетов). [int] его
|
||||
@@ -144,6 +216,13 @@ foreach ($fmtNode in $root.SelectNodes("d:format", $ns)) {
|
||||
if ($item -and $item.InnerText) { $fmt.Props[$tag] = $item.InnerText }
|
||||
continue
|
||||
}
|
||||
# Тип значения ячейки — единственный тег со СВОЕЙ структурой: разбираем его до обеих
|
||||
# отсечек ниже. Пустой <valueType/> тоже значим — это «содержит значение» без
|
||||
# указания типа.
|
||||
if ($tag -ceq 'valueType') {
|
||||
$fmt.Props[$tag] = ConvertFrom-ValueTypeNode $child
|
||||
continue
|
||||
}
|
||||
# Вложенный элемент скаляром не является: InnerText склеил бы всё поддерево вместе
|
||||
# с переводами строк. py-порт брал .text и получал пустоту — отсюда расхождение портов.
|
||||
if ($child.SelectNodes('*').Count -gt 0) { continue }
|
||||
@@ -952,7 +1031,11 @@ foreach ($area in $blocks) {
|
||||
$gapCells = @()
|
||||
|
||||
foreach ($cell in $rd.Cells) {
|
||||
$hasContent = $cell.Param -or $cell.HasText
|
||||
# Ячейка-поле ввода — содержательная, даже когда ни текста, ни параметра в ней нет:
|
||||
# значение задаёт её формат. Без этого такая строка уходила бы в пустые.
|
||||
$cf = Get-Format $cell.FormatIdx
|
||||
$hasValue = ($cf -and $cf.Props['containsValue'] -ceq 'true')
|
||||
$hasContent = $cell.Param -or $cell.HasText -or $hasValue
|
||||
$hasMerge = $mergeMap.ContainsKey("$globalRow,$($cell.Col)")
|
||||
|
||||
if ($hasContent -or $hasMerge) {
|
||||
@@ -1034,6 +1117,24 @@ foreach ($area in $blocks) {
|
||||
}
|
||||
}
|
||||
|
||||
# Значение (ячейка-поле ввода). Свойство живёт в формате, но принадлежит ячейке:
|
||||
# на корпусе на такие записи ссылаются только <f>.
|
||||
if ($cellFmt -and $cellFmt.Props['containsValue'] -ceq 'true') {
|
||||
$dslCell["valueType"] = if ($cellFmt.Props.Contains('valueType')) { $cellFmt.Props['valueType'] } else { "" }
|
||||
if (-not $cellFmt.Props.Contains('controlType')) {
|
||||
# Формат без <controlType> вовсе — так пишут машинно-сгенерированные макеты
|
||||
# регламентированной отчётности; компилятор такое повторит только по
|
||||
# явному указанию.
|
||||
$dslCell["control"] = "none"
|
||||
} else {
|
||||
$ctl = "$($cellFmt.Props['controlType'])"
|
||||
$name = if ($valueControlNames.ContainsKey($ctl.ToLowerInvariant())) { $valueControlNames[$ctl.ToLowerInvariant()] } else { $ctl }
|
||||
# input — умолчание компилятора, писать его значит шуметь на 63 629
|
||||
# форматах корпуса.
|
||||
if ($name -cne 'input') { $dslCell["control"] = $name }
|
||||
}
|
||||
}
|
||||
|
||||
# Content
|
||||
$fillType = if ($cellFmt) { $cellFmt.FillType } else { "" }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-decompile v1.20 — Decompile 1C spreadsheet to JSON
|
||||
# mxl-decompile v1.21 — Decompile 1C spreadsheet to JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -117,6 +117,76 @@ def color_to_dsl(node, val):
|
||||
return val
|
||||
|
||||
|
||||
CFG_NS = 'http://v8.1c.ru/8.1/data/enterprise/current-config'
|
||||
|
||||
# Элемент управления ячейки: в выгрузке это GUID, имён у платформы в XML нет.
|
||||
VALUE_CONTROL_NAMES = {
|
||||
'381ed624-9217-4e63-85db-c4c3cb87daae': 'input',
|
||||
'35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26': 'checkbox',
|
||||
}
|
||||
|
||||
|
||||
def value_type_to_dsl(node):
|
||||
"""Обратная функция к эмиттеру типа компилятора: <valueType> → строка DSL в КРАТЧАЙШЕЙ
|
||||
форме (Boolean, String, String(10,fixed), Number(15,3,nonneg), DateTime, CatalogRef.X,
|
||||
AnyRef), из которой компилятор восстановит тот же XML. Пустой тег → пустая строка:
|
||||
«содержит значение» без указания типа — самостоятельное состояние.
|
||||
Префикс ссылочного типа разрешаем по URI, а не по имени: локальное объявление платформа
|
||||
называет сгенерированным dNpM. Чужое пространство имён оставляем как есть."""
|
||||
types = []
|
||||
quals = {}
|
||||
for child in node:
|
||||
tag = etree.QName(child).localname
|
||||
if tag in ('Type', 'TypeSet'):
|
||||
types.append((tag, child, (child.text or '').strip()))
|
||||
elif tag.endswith('Qualifiers'):
|
||||
quals[tag[:-len('Qualifiers')]] = child
|
||||
|
||||
def qual(kind, name, default=''):
|
||||
el = quals.get(kind)
|
||||
if el is None:
|
||||
return default
|
||||
sub = find(el, 'v8:' + name)
|
||||
val = text_of(sub)
|
||||
return val.strip() if val else default
|
||||
|
||||
parts = []
|
||||
for tag, child, val in types:
|
||||
if ':' in val:
|
||||
prefix, name = val.split(':', 1)
|
||||
uri = child.nsmap.get(prefix)
|
||||
if uri == CFG_NS:
|
||||
val = name
|
||||
elif uri == 'http://www.w3.org/2001/XMLSchema':
|
||||
val = 'xs:' + name
|
||||
if val == 'xs:boolean':
|
||||
parts.append('Boolean')
|
||||
elif val == 'xs:string':
|
||||
length = qual('String', 'Length', '0')
|
||||
fixed = qual('String', 'AllowedLength', 'Variable') == 'Fixed'
|
||||
if fixed:
|
||||
parts.append(f'String({length},fixed)')
|
||||
elif length != '0':
|
||||
parts.append(f'String({length})')
|
||||
else:
|
||||
parts.append('String')
|
||||
elif val == 'xs:decimal':
|
||||
digits = qual('Number', 'Digits', '0')
|
||||
fraction = qual('Number', 'FractionDigits', '0')
|
||||
nonneg = qual('Number', 'AllowedSign', 'Any') == 'Nonnegative'
|
||||
if nonneg:
|
||||
parts.append(f'Number({digits},{fraction},nonneg)')
|
||||
elif digits != '0' or fraction != '0':
|
||||
parts.append(f'Number({digits},{fraction})')
|
||||
else:
|
||||
parts.append('Number')
|
||||
elif val == 'xs:dateTime':
|
||||
parts.append(qual('Date', 'DateFractions', 'DateTime'))
|
||||
else:
|
||||
parts.append(val)
|
||||
return ' + '.join(parts)
|
||||
|
||||
|
||||
def int_of(node, default=0):
|
||||
if node is not None and node.text:
|
||||
return int(node.text)
|
||||
@@ -311,6 +381,12 @@ def main():
|
||||
if val:
|
||||
fmt["Props"][tag] = val
|
||||
continue
|
||||
# Тип значения ячейки — единственный тег со СВОЕЙ структурой: разбираем его до
|
||||
# обеих отсечек ниже. Пустой <valueType/> тоже значим — это «содержит значение»
|
||||
# без указания типа.
|
||||
if tag == "valueType":
|
||||
fmt["Props"][tag] = value_type_to_dsl(child)
|
||||
continue
|
||||
# Вложенный элемент скаляром не является: .text дал бы пустоту, а ps1-порт брал
|
||||
# InnerText и получал склейку поддерева — отсюда расхождение портов.
|
||||
if len(child):
|
||||
@@ -952,7 +1028,11 @@ def main():
|
||||
gap_cells = []
|
||||
|
||||
for cell in rd["Cells"]:
|
||||
has_content = cell["Param"] or cell["HasText"]
|
||||
# Ячейка-поле ввода — содержательная, даже когда ни текста, ни параметра в ней
|
||||
# нет: значение задаёт её формат. Без этого такая строка уходила бы в пустые.
|
||||
cf = get_format(cell["FormatIdx"])
|
||||
has_value = bool(cf and cf["Props"].get("containsValue") == "true")
|
||||
has_content = cell["Param"] or cell["HasText"] or has_value
|
||||
has_merge = f"{global_row},{cell['Col']}" in merge_map
|
||||
|
||||
if has_content or has_merge:
|
||||
@@ -1030,6 +1110,23 @@ def main():
|
||||
if sn != "default" or cells_name:
|
||||
dsl_cell["style"] = sn
|
||||
|
||||
# Значение (ячейка-поле ввода). Свойство живёт в формате, но принадлежит
|
||||
# ячейке: на корпусе на такие записи ссылаются только <f>.
|
||||
if cell_fmt and cell_fmt["Props"].get("containsValue") == "true":
|
||||
dsl_cell["valueType"] = cell_fmt["Props"].get("valueType", "")
|
||||
ctl = cell_fmt["Props"].get("controlType")
|
||||
if ctl is None:
|
||||
# Формат без <controlType> вовсе — так пишут машинно-сгенерированные
|
||||
# макеты регламентированной отчётности; компилятор такое повторит
|
||||
# только по явному указанию.
|
||||
dsl_cell["control"] = "none"
|
||||
else:
|
||||
name = VALUE_CONTROL_NAMES.get(ctl.lower(), ctl)
|
||||
# input — умолчание компилятора, писать его значит шуметь на 63 629
|
||||
# форматах корпуса.
|
||||
if name != "input":
|
||||
dsl_cell["control"] = name
|
||||
|
||||
# Content
|
||||
fill_type = cell_fmt["FillType"] if cell_fmt else ""
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ allowed-tools:
|
||||
|
||||
# /mxl-validate — валидация макета табличного документа (MXL)
|
||||
|
||||
Проверяет Template.xml на структурные ошибки: индексы, ссылки на палитры, диапазоны именованных областей и объединений.
|
||||
Проверяет Template.xml на структурные ошибки: индексы, ссылки на палитры, диапазоны именованных областей и объединений, согласованность ячеек-полей ввода.
|
||||
|
||||
## Параметры
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# mxl-validate v1.2 — Validate 1C spreadsheet
|
||||
# mxl-validate v1.3 — Validate 1C spreadsheet
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Alias('Path')]
|
||||
@@ -91,7 +91,9 @@ function Report-Warn {
|
||||
|
||||
$templateName = [System.IO.Path]::GetFileName([System.IO.Path]::GetDirectoryName([System.IO.Path]::GetDirectoryName($TemplatePath)))
|
||||
if ($Detailed) {
|
||||
Write-Host "=== Validation: $templateName ==="
|
||||
# Форма имени та же, что в итоговой строке и у py-порта: раньше шапка -Detailed
|
||||
# печаталась без префикса «Template.», и вывод портов расходился одной строкой.
|
||||
Write-Host "=== Validation: Template.$templateName ==="
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
@@ -400,6 +402,80 @@ foreach ($drawing in $root.SelectNodes("d:drawing", $nsMgr)) {
|
||||
}
|
||||
}
|
||||
|
||||
# --- Check 13: value cells (input fields) ---
|
||||
# Свойства containsValue/valueType/controlType принадлежат ЯЧЕЙКЕ: на корпусе ERP
|
||||
# (370 197 ссылок) на такие записи палитры ссылаются только <f>, ни строка, ни колонка,
|
||||
# ни defaultFormatIndex. Ячейка со значением текста не несёт — ни одна из 370 197.
|
||||
|
||||
$valueFormatIdx = @{}
|
||||
$controlGuids = @('381ed624-9217-4e63-85db-c4c3cb87daae', '35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26')
|
||||
for ($i = 0; $i -lt $formatNodes.Count; $i++) {
|
||||
$fmt = $formatNodes[$i]
|
||||
$contains = $fmt.SelectSingleNode("d:containsValue", $nsMgr)
|
||||
$vt = $fmt.SelectSingleNode("d:valueType", $nsMgr)
|
||||
if (-not $contains -and -not $vt) { continue }
|
||||
$num = $i + 1
|
||||
$valueFormatIdx[$num] = $true
|
||||
if (-not $contains -or $contains.InnerText.Trim() -cne 'true') {
|
||||
Report-Error "Format ${num}: <valueType> without <containsValue>true</containsValue>"
|
||||
} elseif (-not $vt) {
|
||||
Report-Error "Format ${num}: <containsValue> without <valueType>"
|
||||
}
|
||||
if ($vt) {
|
||||
foreach ($child in $vt.ChildNodes) {
|
||||
if ($child.NodeType -ne [System.Xml.XmlNodeType]::Element) { continue }
|
||||
$tag = $child.get_LocalName()
|
||||
if ($tag -cne 'Type' -and $tag -cne 'TypeSet' -and $tag -notlike '*Qualifiers') {
|
||||
Report-Error "Format ${num}: unexpected <$tag> inside <valueType>"
|
||||
}
|
||||
}
|
||||
}
|
||||
$ctl = $fmt.SelectSingleNode("d:controlType", $nsMgr)
|
||||
if ($ctl -and ($controlGuids -notcontains $ctl.InnerText.Trim().ToLowerInvariant())) {
|
||||
Report-Warn "Format ${num}: unknown controlType $($ctl.InnerText.Trim())"
|
||||
}
|
||||
}
|
||||
|
||||
if ($valueFormatIdx.Count -gt 0) {
|
||||
foreach ($ri in $root.SelectNodes("d:rowsItem", $nsMgr)) {
|
||||
if ($stopped) { break }
|
||||
$row = $ri.SelectSingleNode("d:row", $nsMgr)
|
||||
if (-not $row) { continue }
|
||||
$idxNode = $ri.SelectSingleNode("d:index", $nsMgr)
|
||||
$rn = if ($idxNode) { $idxNode.InnerText } else { '?' }
|
||||
$rowFmt = $row.SelectSingleNode("d:formatIndex", $nsMgr)
|
||||
if ($rowFmt -and $valueFormatIdx.ContainsKey([int]$rowFmt.InnerText)) {
|
||||
Report-Warn "Row ${rn}: formatIndex points to a value format (cell-only property)"
|
||||
}
|
||||
foreach ($cGroup in $row.SelectNodes("d:c", $nsMgr)) {
|
||||
$cell = $cGroup.SelectSingleNode("d:c", $nsMgr)
|
||||
if (-not $cell) { continue }
|
||||
$fNode = $cell.SelectSingleNode("d:f", $nsMgr)
|
||||
if (-not $fNode -or -not $valueFormatIdx.ContainsKey([int]$fNode.InnerText)) { continue }
|
||||
if ($cell.SelectSingleNode("d:tl", $nsMgr)) {
|
||||
Report-Error "Row ${rn}: cell contains a value and text at the same time"
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($cols in $root.SelectNodes("d:columns", $nsMgr)) {
|
||||
foreach ($ci in $cols.SelectNodes("d:columnsItem", $nsMgr)) {
|
||||
$col = $ci.SelectSingleNode("d:column", $nsMgr)
|
||||
if (-not $col) { continue }
|
||||
$fmtNode = $col.SelectSingleNode("d:formatIndex", $nsMgr)
|
||||
if ($fmtNode -and $valueFormatIdx.ContainsKey([int]$fmtNode.InnerText)) {
|
||||
$colIdxNode = $ci.SelectSingleNode("d:index", $nsMgr)
|
||||
$colIdxText = if ($colIdxNode) { $colIdxNode.InnerText } else { '?' }
|
||||
Report-Warn "Column ${colIdxText}: formatIndex points to a value format (cell-only property)"
|
||||
}
|
||||
}
|
||||
}
|
||||
$dfi = $root.SelectSingleNode("d:defaultFormatIndex", $nsMgr)
|
||||
if ($dfi -and $valueFormatIdx.ContainsKey([int]$dfi.InnerText)) {
|
||||
Report-Warn "defaultFormatIndex points to a value format (cell-only property)"
|
||||
}
|
||||
Report-OK "Value cells: $($valueFormatIdx.Count) value formats"
|
||||
}
|
||||
|
||||
# --- Summary ---
|
||||
|
||||
$checks = $script:okCount + $errors + $warnings
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-validate v1.2 — Validate 1C spreadsheet document Template.xml
|
||||
# mxl-validate v1.3 — Validate 1C spreadsheet document Template.xml
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
"""Validates spreadsheet Template.xml: height, palette refs, column/row indices, areas, merges."""
|
||||
import sys, os, argparse
|
||||
@@ -223,7 +223,11 @@ def main():
|
||||
r.error(f'Font index {max_font_ref} exceeds palette size ({font_count})')
|
||||
elif max_font_ref > 0:
|
||||
r.error(f'Font index {max_font_ref} referenced but no fonts defined')
|
||||
# No font references — no check needed
|
||||
else:
|
||||
# Макет без единого шрифта — норма (ячейки-поля ввода, макеты без оформления).
|
||||
# Строку печатаем как ps1-порт: раньше py молчал, и на таком макете число проверок
|
||||
# у портов расходилось.
|
||||
r.ok('No font references')
|
||||
|
||||
# --- Check 11: line/border indices in formats ---
|
||||
if line_count > 0:
|
||||
@@ -233,7 +237,8 @@ def main():
|
||||
r.error(f'Line index {max_line_ref} exceeds palette size ({line_count})')
|
||||
elif max_line_ref > 0:
|
||||
r.error(f'Line index {max_line_ref} referenced but no lines defined')
|
||||
# No line/border references — no check needed
|
||||
else:
|
||||
r.ok('No line/border references')
|
||||
|
||||
# --- Check 3, 4, 5, 6: row/cell checks ---
|
||||
max_cell_format_ref = 0
|
||||
@@ -393,6 +398,67 @@ def main():
|
||||
draw_id = draw_id_node.text if draw_id_node is not None else '?'
|
||||
r.error(f'Drawing id={draw_id}: pictureIndex={pic_idx} > picture count ({picture_count})')
|
||||
|
||||
# --- Check 13: value cells (input fields) ---
|
||||
# Свойства containsValue/valueType/controlType принадлежат ЯЧЕЙКЕ: на корпусе ERP
|
||||
# (370 197 ссылок) на такие записи палитры ссылаются только <f>, ни строка, ни колонка,
|
||||
# ни defaultFormatIndex. Ячейка со значением текста не несёт — ни одна из 370 197.
|
||||
value_format_idx = set()
|
||||
control_guids = ('381ed624-9217-4e63-85db-c4c3cb87daae', '35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26')
|
||||
for i, fmt in enumerate(format_nodes, start=1):
|
||||
contains = fmt.find(f'{{{NS_D}}}containsValue')
|
||||
vt = fmt.find(f'{{{NS_D}}}valueType')
|
||||
if contains is None and vt is None:
|
||||
continue
|
||||
value_format_idx.add(i)
|
||||
if contains is None or (contains.text or '').strip() != 'true':
|
||||
r.error(f'Format {i}: <valueType> without <containsValue>true</containsValue>')
|
||||
elif vt is None:
|
||||
r.error(f'Format {i}: <containsValue> without <valueType>')
|
||||
if vt is not None:
|
||||
for child in vt:
|
||||
tag = child.tag.split('}')[-1]
|
||||
if tag not in ('Type', 'TypeSet') and not tag.endswith('Qualifiers'):
|
||||
r.error(f'Format {i}: unexpected <{tag}> inside <valueType>')
|
||||
ctl = fmt.find(f'{{{NS_D}}}controlType')
|
||||
if ctl is not None and (ctl.text or '').strip().lower() not in control_guids:
|
||||
r.warn(f'Format {i}: unknown controlType {(ctl.text or "").strip()}')
|
||||
|
||||
if value_format_idx:
|
||||
for ri in root.findall(f'{{{NS_D}}}rowsItem'):
|
||||
if r.stopped:
|
||||
break
|
||||
row = ri.find(f'{{{NS_D}}}row')
|
||||
if row is None:
|
||||
continue
|
||||
idx_node = ri.find(f'{{{NS_D}}}index')
|
||||
rn = idx_node.text if idx_node is not None else '?'
|
||||
row_fmt = row.find(f'{{{NS_D}}}formatIndex')
|
||||
if row_fmt is not None and row_fmt.text and int(row_fmt.text) in value_format_idx:
|
||||
r.warn(f'Row {rn}: formatIndex points to a value format (cell-only property)')
|
||||
for c_group in row.findall(f'{{{NS_D}}}c'):
|
||||
cell = c_group.find(f'{{{NS_D}}}c')
|
||||
if cell is None:
|
||||
continue
|
||||
f_node = cell.find(f'{{{NS_D}}}f')
|
||||
if f_node is None or not f_node.text or int(f_node.text) not in value_format_idx:
|
||||
continue
|
||||
if cell.find(f'{{{NS_D}}}tl') is not None:
|
||||
r.error(f'Row {rn}: cell contains a value and text at the same time')
|
||||
for cols in root.findall(f'{{{NS_D}}}columns'):
|
||||
for ci in cols.findall(f'{{{NS_D}}}columnsItem'):
|
||||
col = ci.find(f'{{{NS_D}}}column')
|
||||
if col is None:
|
||||
continue
|
||||
fmt_node = col.find(f'{{{NS_D}}}formatIndex')
|
||||
if fmt_node is not None and fmt_node.text and int(fmt_node.text) in value_format_idx:
|
||||
col_idx_node = ci.find(f'{{{NS_D}}}index')
|
||||
col_idx_text = col_idx_node.text if col_idx_node is not None else '?'
|
||||
r.warn(f'Column {col_idx_text}: formatIndex points to a value format (cell-only property)')
|
||||
dfi = root.find(f'{{{NS_D}}}defaultFormatIndex')
|
||||
if dfi is not None and dfi.text and int(dfi.text) in value_format_idx:
|
||||
r.warn('defaultFormatIndex points to a value format (cell-only property)')
|
||||
r.ok(f'Value cells: {len(value_format_idx)} value formats')
|
||||
|
||||
# --- Finalize ---
|
||||
checks = r.ok_count + r.errors + r.warnings
|
||||
if r.errors == 0 and r.warnings == 0 and not detailed:
|
||||
|
||||
@@ -513,6 +513,84 @@ pictureSizeMode · picHorizontalAlignment · picVerticalAlignment · textPositio
|
||||
каждой ячейки (`backColor`: 13 899 ячеек повторяют против 96). Исключение — `hidden`: оно
|
||||
остаётся только у строки (24 026 против 62 856).
|
||||
|
||||
### Ячейка-поле ввода: `containsValue` / `valueType` / `controlType`
|
||||
|
||||
Ячейка может содержать не текст, а редактируемое значение. Три тега формата описывают это
|
||||
целиком:
|
||||
|
||||
```xml
|
||||
<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>Nonnegative</v8:AllowedSign>
|
||||
</v8:NumberQualifiers>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
```
|
||||
|
||||
Свойство принадлежит ЯЧЕЙКЕ, хотя и живёт в общей палитре: из 370 197 ссылок на такие записи
|
||||
(корпус ERP, 5 809 макетов из 10 924) все до одной идут из `<f>` — ни строка, ни колонка, ни
|
||||
`<defaultFormatIndex>` на них не ссылаются ни разу.
|
||||
|
||||
| Наблюдение | Данные корпуса |
|
||||
|---|---|
|
||||
| `containsValue` всегда `true` | 63 726 форматов, других значений нет |
|
||||
| `valueType` присутствует всегда | 0 форматов без него; 12 — с ПУСТЫМ `<valueType/>` (тип не ограничен) |
|
||||
| текста у такой ячейки не бывает | 0 из 370 197 несут `<tl>` |
|
||||
| `<parameter>` и `<detailParameter>` — бывают | 3 219 и 2 278 |
|
||||
| `fillType` у формата со значением недостоверен | 94 062 записи несут `Text` при полном отсутствии текста — след прежнего состояния, как `width` |
|
||||
|
||||
**Элемент управления** задаётся GUID; имён в XML нет вовсе. В Конфигураторе это «ЭлементУправления»
|
||||
со значениями «Поле ввода» и «Поле флажка»:
|
||||
|
||||
| GUID | Элемент | Вхождений |
|
||||
|---|---|---:|
|
||||
| `381ed624-9217-4e63-85db-c4c3cb87daae` | Поле ввода | 63 629 |
|
||||
| `35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26` | Поле флажка | 7 |
|
||||
|
||||
Умолчание — поле ввода, и оно же стоит у Булево: из 664 булевых форматов флажок выбран в семи.
|
||||
У 90 форматов (22 макета регламентированной отчётности, явно машинно-сгенерированных) тега
|
||||
`<controlType>` нет вовсе.
|
||||
|
||||
**Структура `<valueType>`** — то же описание типов, что в метаданных: сначала все `<v8:Type>` и
|
||||
`<v8:TypeSet>` в порядке источника, затем блоки квалификаторов в порядке Number → String → Date.
|
||||
Голая категория без имени объекта (`CatalogRef`, `AnyRef`) — это `<v8:TypeSet>`, а не `<v8:Type>`.
|
||||
|
||||
Ссылочные типы несут **локальное объявление пространства имён на каждом узле**:
|
||||
|
||||
```xml
|
||||
<v8:Type xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:CatalogRef.Валюты</v8:Type>
|
||||
```
|
||||
|
||||
Префикс всегда `d4p1` (15 вхождений на корпусе, отклонений нет) — независимо от того, есть ли
|
||||
в макете цвета web-палитры, которым платформа даёт `d3p1`. Корень `<document>` пространство
|
||||
current-config не объявляет, поэтому вынести объявление наверх нельзя.
|
||||
|
||||
**Продолжение конструкции — на уровне САМОЙ ячейки**, а не палитры:
|
||||
|
||||
```xml
|
||||
<c>
|
||||
<f>34</f>
|
||||
<v xsi:type="xs:decimal">0</v>
|
||||
<control xsi:type="xs:base64Binary">77u/MiwxLDM4MWVkNjI0…</control>
|
||||
</c>
|
||||
```
|
||||
|
||||
| Тег ячейки | Смысл | Вхождений | Макетов |
|
||||
|---|---|---:|---:|
|
||||
| `<v>` | сохранённое значение ячейки; `xsi:type` соответствует объявленному типу (decimal 153 566, string 61 203, dateTime 3 333, boolean 1 012) | 219 114 | 4 578 |
|
||||
| `<control>` | сериализованные настройки элемента управления (base64; внутри — тот же GUID и структура вида маски/списка выбора) | 26 370 | 1 246 |
|
||||
|
||||
Оба тега встречаются ИСКЛЮЧИТЕЛЬНО в ячейках, чей формат несёт `containsValue` — ни одного
|
||||
вхождения в обычной ячейке. То есть это вторая половина той же конструкции, а не отдельное
|
||||
свойство. Обрати внимание на совпадение имён: `<control>` у ячейки и `<controlType>` в формате —
|
||||
разные вещи.
|
||||
|
||||
**Ловушка: `width` в формате ЯЧЕЙКИ не описывает ячейку.** Ссылка ячейки на запись палитры не
|
||||
обновляется при изменении ширины колонки, поэтому там остаётся ширина от прежнего состояния
|
||||
документа. Проверено на контролируемом стенде: в макете, где ширины колонок поменяли на
|
||||
|
||||
@@ -74,4 +74,4 @@
|
||||
- `fillType` — выводится из того, каким ключом задано содержимое ячейки
|
||||
(`text` / `param` / `template`);
|
||||
- `containsValue`, `valueType`, `controlType` — свойства конкретной ячейки, а не общего
|
||||
оформления; сейчас не поддерживаются.
|
||||
оформления: задаются ключами ячейки `valueType` и `control`.
|
||||
|
||||
+42
-1
@@ -182,6 +182,8 @@
|
||||
| `detail` | нет | — | Параметр расшифровки (только с `param`) |
|
||||
| `text` | нет | — | Статический текст. Строка или объект `{ ru, en }` — см. ниже |
|
||||
| `template` | нет | — | Шаблонный текст с `[Параметр]`. Строка или объект, как `text` |
|
||||
| `valueType` | нет | — | Тип значения: ячейка становится полем ввода (см. ниже) |
|
||||
| `control` | нет | `input` | Элемент управления поля ввода: `input` или `checkbox`. Только вместе с `valueType` |
|
||||
|
||||
### Содержимое ячейки
|
||||
|
||||
@@ -212,6 +214,44 @@
|
||||
|
||||
Пустая строка — это текст: ячейка с `"text": ""` даёт пустую надпись, а не ячейку без текста.
|
||||
|
||||
## Ячейка-поле ввода
|
||||
|
||||
Ячейка может не показывать текст, а принимать значение от пользователя — так делают макеты для
|
||||
ввода данных. Достаточно задать тип значения:
|
||||
|
||||
```json
|
||||
{ "col": 1, "valueType": "Number(15,3,nonneg)" }
|
||||
{ "col": 2, "valueType": "String(10)" }
|
||||
{ "col": 3, "valueType": "Boolean", "control": "checkbox" }
|
||||
{ "col": 4, "valueType": "CatalogRef.Валюты" }
|
||||
{ "col": 5, "valueType": "Boolean + String + Date + CatalogRef.Валюты" }
|
||||
{ "col": 6, "valueType": "AnyRef" }
|
||||
```
|
||||
|
||||
Грамматика типа:
|
||||
|
||||
| Запись | Значение |
|
||||
|---|---|
|
||||
| `Boolean` | булево |
|
||||
| `String`, `String(10)`, `String(10,fixed)` | строка; без длины — неограниченная, `fixed` — фиксированной длины |
|
||||
| `Number`, `Number(15,3)`, `Number(15,3,nonneg)` | число; без параметров — без ограничения разрядности, `nonneg` — неотрицательное |
|
||||
| `Date`, `DateTime`, `Time` | дата, дата со временем, время |
|
||||
| `CatalogRef.Валюты`, `DocumentRef.Реализация`, `EnumRef.Статусы`, `DefinedType.Сумма` | ссылочный тип |
|
||||
| `CatalogRef`, `DocumentRef`, `AnyRef` | категория целиком: любая ссылка этого вида |
|
||||
| `A + B` | составной тип; повтор одного примитива недопустим |
|
||||
|
||||
Русские имена принимаются наравне с английскими: `Число(15,3)`, `Строка(10)`,
|
||||
`СправочникСсылка.Валюты`.
|
||||
|
||||
`text` и `template` в такой ячейке недопустимы — платформа не показывает текст там, где вводится
|
||||
значение. `param` и `detail` допустимы: они описывают заполнение и расшифровку, а не содержимое.
|
||||
|
||||
Пустой тип `"valueType": ""` — «ячейка содержит значение», но тип не ограничен.
|
||||
|
||||
`control` нужен редко: умолчание платформы — поле ввода, и оно применяется ко всем типам, включая
|
||||
`Boolean`. Флажок задаётся явно. Значение `"none"` (тега элемента управления нет вовсе) — форма
|
||||
раундтрипа, для ручного авторинга не нужна.
|
||||
|
||||
## `rowStyle` — оформление строки
|
||||
|
||||
Стиль применяется ко ВСЕЙ ширине строки: позиции без явных ячеек получают тот же стиль. Так в табличных строках получаются сплошные рамки. Он же становится оформлением самой строки — именно так платформа хранит строку, оформленную целиком.
|
||||
@@ -226,7 +266,8 @@ DSL описывает не все конструкции табличного
|
||||
round-trip** (`/mxl-decompile` → `/mxl-compile`): в JSON оно не попадает, в сгенерированный
|
||||
XML не возвращается.
|
||||
|
||||
- ячейки-поля ввода (`containsValue` / `valueType` / `controlType`);
|
||||
- начальное значение ячейки-поля ввода и сериализованные настройки её элемента управления
|
||||
(тип значения при этом переживает цикл);
|
||||
- объединения, не привязанные к ячейке (по всей высоте или ширине документа);
|
||||
- рисунки и картинки, в том числе штрихкоды, и примечания к ячейкам;
|
||||
- группировки строк и колонок;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Ошибка: неизвестный элемент управления",
|
||||
"input": {
|
||||
"columns": 1,
|
||||
"areas": [
|
||||
{
|
||||
"name": "Ввод",
|
||||
"rows": [{ "cells": [{ "col": 1, "valueType": "Boolean", "control": "кнопка" }] }]
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": { "outputPath": "Template.xml" },
|
||||
"expectError": "Unknown 'control' value \"кнопка\" (area \"Ввод\"). Allowed: input, checkbox, none or a GUID"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Ошибка: неизвестный тип значения (голое имя не становится множеством типов)",
|
||||
"input": {
|
||||
"columns": 1,
|
||||
"areas": [
|
||||
{
|
||||
"name": "Ввод",
|
||||
"rows": [{ "cells": [{ "col": 1, "valueType": "Boolen" }] }]
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": { "outputPath": "Template.xml" },
|
||||
"expectError": "Unknown value type \"Boolen\" (area \"Ввод\")"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Ошибка: control без valueType",
|
||||
"input": {
|
||||
"columns": 1,
|
||||
"areas": [
|
||||
{
|
||||
"name": "Ввод",
|
||||
"rows": [{ "cells": [{ "col": 1, "control": "checkbox" }] }]
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": { "outputPath": "Template.xml" },
|
||||
"expectError": "Cell 'control' requires 'valueType' (area \"Ввод\")"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Ошибка: составной тип с двумя строками (блок квалификаторов один)",
|
||||
"input": {
|
||||
"columns": 1,
|
||||
"areas": [
|
||||
{
|
||||
"name": "Ввод",
|
||||
"rows": [{ "cells": [{ "col": 1, "valueType": "String(10) + String(20)" }] }]
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": { "outputPath": "Template.xml" },
|
||||
"expectError": "Duplicate type \"String(20,variable)\" in composite value type (area \"Ввод\")"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Ошибка: ячейка со значением несёт текст",
|
||||
"input": {
|
||||
"columns": 1,
|
||||
"areas": [
|
||||
{
|
||||
"name": "Ввод",
|
||||
"rows": [{ "cells": [{ "col": 1, "valueType": "Boolean", "text": "Да" }] }]
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": { "outputPath": "Template.xml" },
|
||||
"expectError": "Cell with 'valueType' cannot have 'text' or 'template' (area \"Ввод\")"
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
<?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>
|
||||
<languageInfo>
|
||||
<id>en</id>
|
||||
<code>Английский</code>
|
||||
<description>Английский</description>
|
||||
</languageInfo>
|
||||
</languageSettings>
|
||||
<columns>
|
||||
<size>3</size>
|
||||
</columns>
|
||||
<rowsItem>
|
||||
<index>0</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>1</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>2</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>3</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>1</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>4</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>5</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>2</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>3</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>6</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>7</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>3</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>8</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>4</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>9</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>5</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>10</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>6</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>11</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>12</defaultFormatIndex>
|
||||
<height>7</height>
|
||||
<vgRows>7</vgRows>
|
||||
<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>Nonnegative</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>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: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:boolean</v8:Type>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:Type>xs:boolean</v8:Type>
|
||||
</valueType>
|
||||
<controlType>35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26</controlType>
|
||||
</format>
|
||||
<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:string</v8:Type>
|
||||
<v8:StringQualifiers>
|
||||
<v8:Length>10</v8:Length>
|
||||
<v8:AllowedLength>Fixed</v8:AllowedLength>
|
||||
</v8:StringQualifiers>
|
||||
</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 xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:CatalogRef.ГорячиеКлавиши</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:TypeSet xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:DocumentRef</v8:TypeSet>
|
||||
<v8:TypeSet xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:CatalogRef</v8:TypeSet>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:TypeSet xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:AnyRef</v8:TypeSet>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<width>72</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "Раундтрип макета ПЛАТФОРМЫ байт в байт: СЗначениями (ячейки-поля ввода)",
|
||||
"setup": "fixture:platform-roundtrip",
|
||||
"preRun": [
|
||||
{
|
||||
"script": "mxl-decompile/scripts/mxl-decompile",
|
||||
"args": {
|
||||
"-TemplatePath": "СЗначениями.xml",
|
||||
"-OutputPath": "back.json"
|
||||
},
|
||||
"cwd": "{workDir}"
|
||||
}
|
||||
],
|
||||
"params": {
|
||||
"outputPath": "out.xml"
|
||||
},
|
||||
"noSnapshot": "эталон — файл платформы, сверяется expect.filesEqual",
|
||||
"expect": {
|
||||
"filesEqual": {
|
||||
"actual": "out.xml",
|
||||
"expected": "СЗначениями.xml"
|
||||
}
|
||||
},
|
||||
"inputFrom": "back.json"
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
<?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>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>2</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>3</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>1</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>4</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>5</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>2</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>6</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>7</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>8</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>3</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>9</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>10</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>11</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>12</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:decimal</v8:Type>
|
||||
<v8:NumberQualifiers>
|
||||
<v8:Digits>15</v8:Digits>
|
||||
<v8:FractionDigits>3</v8:FractionDigits>
|
||||
<v8:AllowedSign>Nonnegative</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>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: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:boolean</v8:Type>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:Type>xs:boolean</v8:Type>
|
||||
</valueType>
|
||||
<controlType>35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26</controlType>
|
||||
</format>
|
||||
<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:string</v8:Type>
|
||||
<v8:StringQualifiers>
|
||||
<v8:Length>10</v8:Length>
|
||||
<v8:AllowedLength>Fixed</v8:AllowedLength>
|
||||
</v8:StringQualifiers>
|
||||
</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:dateTime</v8:Type>
|
||||
<v8:DateQualifiers>
|
||||
<v8:DateFractions>Date</v8:DateFractions>
|
||||
</v8:DateQualifiers>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:Type>xs:dateTime</v8:Type>
|
||||
<v8:DateQualifiers>
|
||||
<v8:DateFractions>Time</v8:DateFractions>
|
||||
</v8:DateQualifiers>
|
||||
</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>
|
||||
<width>10</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,97 @@
|
||||
<?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>6</size>
|
||||
</columns>
|
||||
<rowsItem>
|
||||
<index>0</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>1</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>1</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>1</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>2</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>2</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>3</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>4</defaultFormatIndex>
|
||||
<height>1</height>
|
||||
<vgRows>1</vgRows>
|
||||
<namedItem xsi:type="NamedItemCells">
|
||||
<name>Дедупликация</name>
|
||||
<area>
|
||||
<type>Rows</type>
|
||||
<beginRow>0</beginRow>
|
||||
<endRow>0</endRow>
|
||||
<beginColumn>-1</beginColumn>
|
||||
<endColumn>-1</endColumn>
|
||||
</area>
|
||||
</namedItem>
|
||||
<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: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:boolean</v8:Type>
|
||||
</valueType>
|
||||
<controlType>35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<width>10</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,131 @@
|
||||
<?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>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>2</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>3</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>1</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>4</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>5</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>6</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>7</defaultFormatIndex>
|
||||
<height>2</height>
|
||||
<vgRows>2</vgRows>
|
||||
<namedItem xsi:type="NamedItemCells">
|
||||
<name>Ввод</name>
|
||||
<area>
|
||||
<type>Rows</type>
|
||||
<beginRow>0</beginRow>
|
||||
<endRow>1</endRow>
|
||||
<beginColumn>-1</beginColumn>
|
||||
<endColumn>-1</endColumn>
|
||||
</area>
|
||||
</namedItem>
|
||||
<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 xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:DocumentRef.Реализация</v8:Type>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:TypeSet xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:DefinedType.СуммаДокумента</v8:TypeSet>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:TypeSet xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:DocumentRef</v8:TypeSet>
|
||||
<v8:TypeSet xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:CatalogRef</v8:TypeSet>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:TypeSet xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:AnyRef</v8:TypeSet>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:Type>xs:boolean</v8:Type>
|
||||
<v8:Type xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:CatalogRef.ГорячиеКлавиши</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>
|
||||
<width>10</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,140 @@
|
||||
<?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>4</size>
|
||||
</columns>
|
||||
<rowsItem>
|
||||
<index>0</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>1</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>2</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>3</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>4</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>1</index>
|
||||
<row>
|
||||
<formatIndex>5</formatIndex>
|
||||
<c>
|
||||
<c>
|
||||
<f>5</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>6</f>
|
||||
<parameter>Сумма</parameter>
|
||||
<detailParameter>Расшифровка</detailParameter>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>5</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>5</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>7</defaultFormatIndex>
|
||||
<height>2</height>
|
||||
<vgRows>2</vgRows>
|
||||
<namedItem xsi:type="NamedItemCells">
|
||||
<name>Состояния</name>
|
||||
<area>
|
||||
<type>Rows</type>
|
||||
<beginRow>0</beginRow>
|
||||
<endRow>1</endRow>
|
||||
<beginColumn>-1</beginColumn>
|
||||
<endColumn>-1</endColumn>
|
||||
</area>
|
||||
</namedItem>
|
||||
<line width="1" gap="false">
|
||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||
</line>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<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>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:Type>xs:boolean</v8:Type>
|
||||
</valueType>
|
||||
<controlType>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<border>0</border>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:Type>xs:string</v8:Type>
|
||||
<v8:StringQualifiers>
|
||||
<v8:Length>50</v8:Length>
|
||||
<v8:AllowedLength>Variable</v8:AllowedLength>
|
||||
</v8:StringQualifiers>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<border>0</border>
|
||||
</format>
|
||||
<format>
|
||||
<border>0</border>
|
||||
<fillType>Parameter</fillType>
|
||||
<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>
|
||||
<width>10</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "Ячейки-поля ввода: примитивные типы значения",
|
||||
"input": {
|
||||
"columns": 3,
|
||||
"areas": [
|
||||
{
|
||||
"name": "Ввод",
|
||||
"rows": [
|
||||
{ "cells": [
|
||||
{ "col": 1, "valueType": "Number(15,3,nonneg)" },
|
||||
{ "col": 2, "valueType": "Number" },
|
||||
{ "col": 3, "valueType": "String" }
|
||||
]},
|
||||
{ "cells": [
|
||||
{ "col": 1, "valueType": "Boolean" },
|
||||
{ "col": 2, "valueType": "Boolean", "control": "checkbox" }
|
||||
]},
|
||||
{ "cells": [
|
||||
{ "col": 1, "valueType": "String(10)" },
|
||||
{ "col": 2, "valueType": "String(10,fixed)" },
|
||||
{ "col": 3, "valueType": "DateTime" }
|
||||
]},
|
||||
{ "cells": [
|
||||
{ "col": 1, "valueType": "Date" },
|
||||
{ "col": 2, "valueType": "Time" },
|
||||
{ "col": 3, "valueType": "Boolean + String + DateTime + Number" }
|
||||
]}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"outputPath": "Template.xml"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "Ячейки-поля ввода: разные написания одного типа дают ОДИН формат",
|
||||
"input": {
|
||||
"columns": 6,
|
||||
"areas": [
|
||||
{
|
||||
"name": "Дедупликация",
|
||||
"rows": [
|
||||
[
|
||||
{ "valueType": "Число(15,3)" },
|
||||
{ "valueType": "Number(15,3)" },
|
||||
{ "valueType": "Number(15,3,any)" },
|
||||
{ "valueType": "Строка(10)" },
|
||||
{ "valueType": "String(10,variable)" },
|
||||
{ "valueType": "Булево", "control": "Поле Флажка" }
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"outputPath": "Template.xml"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "Ячейки-поля ввода: ссылочные типы и категории целиком",
|
||||
"input": {
|
||||
"columns": 3,
|
||||
"areas": [
|
||||
{
|
||||
"name": "Ввод",
|
||||
"rows": [
|
||||
{ "cells": [
|
||||
{ "col": 1, "valueType": "CatalogRef.Валюты" },
|
||||
{ "col": 2, "valueType": "DocumentRef.Реализация" },
|
||||
{ "col": 3, "valueType": "DefinedType.СуммаДокумента" }
|
||||
]},
|
||||
{ "cells": [
|
||||
{ "col": 1, "valueType": "DocumentRef + CatalogRef" },
|
||||
{ "col": 2, "valueType": "AnyRef" },
|
||||
{ "col": 3, "valueType": "Boolean + CatalogRef.ГорячиеКлавиши + String + DateTime + Number" }
|
||||
]}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"outputPath": "Template.xml"
|
||||
},
|
||||
"skipPlatformVerify": "ссылочные типы разрешаются только в базе с матч-конфигурацией: временная база-заглушка таких объектов не содержит"
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "Ячейки-поля ввода: три состояния типа и элемент управления",
|
||||
"input": {
|
||||
"columns": 4,
|
||||
"styles": { "bordered": { "border": "Solid" } },
|
||||
"areas": [
|
||||
{
|
||||
"name": "Состояния",
|
||||
"rows": [
|
||||
{ "cells": [
|
||||
{ "col": 1, "valueType": "" },
|
||||
{ "col": 2, "valueType": "Number(15,3)", "control": "none" },
|
||||
{ "col": 3, "valueType": "Boolean", "control": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" },
|
||||
{ "col": 4, "valueType": "String(50)", "style": "bordered" }
|
||||
]},
|
||||
{ "rowStyle": "bordered", "cells": [
|
||||
{ "col": 2, "valueType": "Number(10,2)", "param": "Сумма", "detail": "Расшифровка" }
|
||||
]}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"outputPath": "Template.xml"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "Roundtrip — ячейки-поля ввода (тип значения и элемент управления)",
|
||||
"preRun": [
|
||||
{
|
||||
"script": "mxl-compile/scripts/mxl-compile",
|
||||
"input": {
|
||||
"columns": 3,
|
||||
"areas": [
|
||||
{
|
||||
"name": "Ввод",
|
||||
"rows": [
|
||||
{ "cells": [
|
||||
{ "col": 1, "valueType": "Number(15,3,nonneg)" },
|
||||
{ "col": 2, "valueType": "String(10,fixed)" },
|
||||
{ "col": 3, "valueType": "Boolean", "control": "checkbox" }
|
||||
]},
|
||||
{ "cells": [
|
||||
{ "col": 1, "valueType": "" },
|
||||
{ "col": 2, "valueType": "Number(10,2)", "control": "none" },
|
||||
{ "col": 3, "valueType": "Boolean + CatalogRef.Валюты + String + DateTime" }
|
||||
]},
|
||||
{ "cells": [
|
||||
{ "col": 1, "valueType": "AnyRef" },
|
||||
{ "col": 2, "valueType": "Number(10,2)", "param": "Сумма", "detail": "Расшифровка" }
|
||||
]}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"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,172 @@
|
||||
<?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>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>2</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>3</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>1</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>4</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>5</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>6</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>2</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>7</f>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>8</f>
|
||||
<parameter>Сумма</parameter>
|
||||
<detailParameter>Расшифровка</detailParameter>
|
||||
</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:decimal</v8:Type>
|
||||
<v8:NumberQualifiers>
|
||||
<v8:Digits>15</v8:Digits>
|
||||
<v8:FractionDigits>3</v8:FractionDigits>
|
||||
<v8:AllowedSign>Nonnegative</v8:AllowedSign>
|
||||
</v8:NumberQualifiers>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:Type>xs:string</v8:Type>
|
||||
<v8:StringQualifiers>
|
||||
<v8:Length>10</v8:Length>
|
||||
<v8:AllowedLength>Fixed</v8:AllowedLength>
|
||||
</v8:StringQualifiers>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:Type>xs:boolean</v8:Type>
|
||||
</valueType>
|
||||
<controlType>35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<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>
|
||||
</format>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:Type>xs:boolean</v8:Type>
|
||||
<v8:Type xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:CatalogRef.Валюты</v8:Type>
|
||||
<v8:Type>xs:string</v8:Type>
|
||||
<v8:Type>xs:dateTime</v8:Type>
|
||||
<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:TypeSet xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:AnyRef</v8:TypeSet>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<fillType>Parameter</fillType>
|
||||
<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>
|
||||
<width>10</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"columns": 3,
|
||||
"defaultWidth": 10,
|
||||
"fonts": {},
|
||||
"styles": {},
|
||||
"areas": [
|
||||
{
|
||||
"name": "Ввод",
|
||||
"rows": [[{ "valueType": "Number(15,3,nonneg)" }, { "valueType": "String(10,fixed)" }, { "valueType": "Boolean", "control": "checkbox" }], [{ "valueType": "" }, { "valueType": "Number(10,2)", "control": "none" }, { "valueType": "Boolean + CatalogRef.Валюты + String + DateTime" }], [{ "valueType": "AnyRef" }, { "valueType": "Number(10,2)", "param": "Сумма", "detail": "Расшифровка" }]]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "Ошибка: ячейка одновременно содержит значение и текст",
|
||||
"setup": "fixture:value-cell-with-text",
|
||||
"params": { "templatePath": "Template.xml" },
|
||||
"expectError": true,
|
||||
"expect": { "stdoutContains": "cell contains a value and text at the same time" }
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?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>1</size>
|
||||
</columns>
|
||||
<rowsItem>
|
||||
<index>0</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>1</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Текст в ячейке со значением</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>2</defaultFormatIndex>
|
||||
<height>1</height>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:Type>xs:boolean</v8:Type>
|
||||
</valueType>
|
||||
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<width>72</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?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>1</size>
|
||||
</columns>
|
||||
<rowsItem>
|
||||
<index>0</index>
|
||||
<row>
|
||||
<formatIndex>1</formatIndex>
|
||||
<c>
|
||||
<c>
|
||||
<f>1</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>2</defaultFormatIndex>
|
||||
<height>1</height>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:Type>xs:boolean</v8:Type>
|
||||
</valueType>
|
||||
<controlType>11111111-2222-3333-4444-555555555555</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<width>72</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?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>1</size>
|
||||
</columns>
|
||||
<rowsItem>
|
||||
<index>0</index>
|
||||
<row>
|
||||
<formatIndex>1</formatIndex>
|
||||
<c>
|
||||
<c>
|
||||
<f>1</f>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>2</defaultFormatIndex>
|
||||
<height>1</height>
|
||||
<format>
|
||||
<containsValue>true</containsValue>
|
||||
<valueType>
|
||||
<v8:Type>xs:boolean</v8:Type>
|
||||
</valueType>
|
||||
<controlType>11111111-2222-3333-4444-555555555555</controlType>
|
||||
</format>
|
||||
<format>
|
||||
<width>72</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "Предупреждения: формат со значением у строки и неизвестный элемент управления",
|
||||
"setup": "fixture:value-format-misplaced",
|
||||
"params": { "templatePath": "Template.xml" },
|
||||
"args_extra": ["-Detailed"],
|
||||
"expect": { "stdoutContains": "unknown controlType" }
|
||||
}
|
||||
@@ -170,7 +170,7 @@ const FAMILIES = [
|
||||
// TYPE_SYNONYMS / $script:typeSynonyms на свой локальный словарь.
|
||||
variants: [
|
||||
{ id: 'base', authority: 'meta-compile',
|
||||
consumers: ['form-compile', 'form-edit', 'meta-edit', 'skd-compile', 'skd-edit'] },
|
||||
consumers: ['form-compile', 'form-edit', 'meta-edit', 'mxl-compile', 'skd-compile', 'skd-edit'] },
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user