mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-17 16:50:30 +03:00
feat(mxl-compile,mxl-decompile,mxl-validate): группы строк и колонок
Документные ключи rowGroups и columnGroups описывают сворачиваемые группы: диапазон, имя, признак свёрнутости и расположение заголовка. Форма плоская, как в формате: вложенность выражена вхождением одного диапазона в другой. Дерево было бы читаемее, но платформа хранит плоско, и для правки чужого макета дерево дороже — чтобы добавить группу внутрь существующей, пришлось бы искать родителя. Частичных пересечений платформа не порождает (корпус: 40 620 886 пар непересекающихся, 599 958 вложенных, ни одного частичного), поэтому компилятор их отвергает. Число уровней вложенности не задаётся: оно совпало с <vgLevels> у всех 1797 макетов корпуса. Порядок записи компилятор приводит к платформенному — родитель раньше вложенных, по возрастанию начала (совпало у 1798 макетов из 1798). Имя группы вывести нельзя, хотя 143 455 имён корпуса выглядят как автоматические R<номер строки>: 16 666 из них протухли после вставки строк, а 10 287 групп имени не имеют вовсе. Расположение заголовка взяло ключ titleLocation — то же свойство и то же имя, что в DSL форм. mxl-validate: проверка 14 — перевёрнутый диапазон, частичное пересечение, начало группы за пределами документа. Стенд Группировки собирается байт в байт обоими портами и добавлен в платформенные фикстуры. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
4005f36cce
commit
1e0b82d419
@@ -62,6 +62,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -J
|
||||
{ col, span, rowspan, style, param, detail, text, template, valueType, controlType, value, note }
|
||||
]}]}],
|
||||
namedAreas: [{ name, rows, cols }],
|
||||
rowGroups: [{ rows, name, collapsed, titleLocation }],
|
||||
columnGroups: [{ cols, name, collapsed, titleLocation }],
|
||||
columnSets: { name: { columns, columnWidths, columnStyles } }
|
||||
}
|
||||
```
|
||||
@@ -80,8 +82,9 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -J
|
||||
- `col` — 1-based позиция колонки
|
||||
- `rowspan` — объединение строк вниз (rowStyle учитывает занятые ячейки)
|
||||
- Содержимое ячейки задаётся одним из ключей: `param` — параметр заполнения, `text` — статический текст, `template` — текст со вставками `[Параметр]`
|
||||
- `rowGroups`/`columnGroups` — группы строк и колонок (сворачиваются кнопкой на полях): плоский список диапазонов, вложенность выражена вхождением одного в другой
|
||||
- `note` — всплывающая подсказка у ячейки: строка, объект языков или `{ text, style, autoSize, box }`
|
||||
- `valueType` делает ячейку полем ввода (`"Number(15,3,nonneg)"`, `"String(10)"`, `"CatalogRef.Валюты"`, составной через ` + `); текста в такой ячейке быть не может. `value` — значение в поле, `controlType: "checkbox"` — флажок вместо поля ввода
|
||||
- `valueType` делает ячейку полем ввода (`"Number(15,3,nonneg)"`, `"String(10)"`, `"CatalogRef.Валюты"`, составной через ` + `); текста в такой ячейке быть не может, значение задаётся ключом `value`
|
||||
|
||||
Двухуровневая шапка массивами:
|
||||
```json
|
||||
|
||||
@@ -87,6 +87,8 @@
|
||||
| `areas` | да | — | Массив областей — диапазонов подряд идущих строк (порядок = порядок в документе); имя необязательно |
|
||||
| `namedAreas` | нет | — | Именованные области, заданные координатами (см. ниже) |
|
||||
| `columnSets` | нет | — | Дополнительные колоночные раскладки (см. `styles.md`) |
|
||||
| `rowGroups` | нет | — | Группы строк (см. ниже) |
|
||||
| `columnGroups` | нет | — | Группы колонок (см. ниже) |
|
||||
|
||||
## Области (`areas[]`)
|
||||
|
||||
@@ -289,11 +291,37 @@
|
||||
| `text` | — | Текст подсказки: строка или объект «язык → текст» |
|
||||
| `style` | стиль подсказки | Имя стиля из `styles`; без него — оформление, которое даёт Конфигуратор |
|
||||
| `autoSize` | `true` | Подгонять ли размер окошка под текст |
|
||||
| `box` | канонический | Смещения окошка: `top`, `left` — положение, `bottom`, `right` — размер |
|
||||
| `box` | — | Смещения окошка: `top`, `left` — положение, `bottom`, `right` — размер. Без ключа окошко встаёт стандартно |
|
||||
|
||||
Координаты ячейки в примечании не задаются — платформа привязывает конец окошка к самой ячейке,
|
||||
и компилятор проставляет это сам. `autoSize` и `box` независимы: при автоподгоне размера
|
||||
положение окошка всё равно хранится.
|
||||
Координаты ячейки в примечании не задаются. `autoSize` и `box` независимы: при автоподгоне
|
||||
размера положение окошка всё равно хранится.
|
||||
|
||||
## Группы строк и колонок
|
||||
|
||||
Диапазон строк или колонок, который сворачивается кнопкой на полях. Задаются плоским списком;
|
||||
вложенность выражена вхождением одного диапазона в другой:
|
||||
|
||||
```json
|
||||
"rowGroups": [
|
||||
{ "rows": "2-4" },
|
||||
{ "rows": 3 },
|
||||
{ "rows": 5, "name": "Итоговая", "collapsed": true, "titleLocation": "begin" }
|
||||
],
|
||||
"columnGroups": [
|
||||
{ "cols": "2-3", "name": { "ru": "Показатели", "en": "Values" } },
|
||||
{ "cols": 3 }
|
||||
]
|
||||
```
|
||||
|
||||
| Поле | Обяз. | По умолч. | Описание |
|
||||
|------|:-----:|-----------|----------|
|
||||
| `rows` / `cols` | да | — | Диапазон 1-based: число или `"N-M"` |
|
||||
| `name` | нет | — | Имя группы: строка или объект «язык → текст» |
|
||||
| `collapsed` | нет | `false` | Свёрнута ли группа при открытии |
|
||||
| `titleLocation` | нет | `auto` | Расположение заголовка: `begin`, `end`, `auto` |
|
||||
|
||||
Диапазоны либо вложены, либо не пересекаются: частичное пересечение — ошибка. Порядок в списке
|
||||
не важен, число уровней вложенности считается само.
|
||||
|
||||
## `rowStyle` — оформление строки
|
||||
|
||||
@@ -311,7 +339,6 @@ XML не возвращается.
|
||||
|
||||
- объединения, не привязанные к ячейке (по всей высоте или ширине документа);
|
||||
- рисунки и картинки, в том числе штрихкоды;
|
||||
- группировки строк и колонок;
|
||||
- колонтитулы, параметры печати, область печати.
|
||||
|
||||
Пересборка макета из DSL — это полная перегенерация, а не точечная правка XML, поэтому
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# mxl-compile v1.43 — Compile 1C spreadsheet from JSON
|
||||
# mxl-compile v1.44 — Compile 1C spreadsheet from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -2037,11 +2037,124 @@ if ($def.namedAreas) {
|
||||
}
|
||||
}
|
||||
|
||||
# 7e-bis. Группировки строк и колонок. Платформа хранит их плоским списком диапазонов;
|
||||
# вложенность выражена вхождением одного диапазона в другой, а частичных пересечений не
|
||||
# бывает вовсе (корпус: 40 620 886 пар непересекающихся, 599 958 вложенных, 0 частичных).
|
||||
function Get-Groups {
|
||||
param([string]$key, [string]$axis)
|
||||
$out = @()
|
||||
$idx = 0
|
||||
foreach ($g in $def.$key) {
|
||||
$idx++
|
||||
$where = "$key[$idx]"
|
||||
$spec = "$($g.$axis)".Trim()
|
||||
if (-not $spec) {
|
||||
[Console]::Error.WriteLine("${key}: '$axis' is required: $where")
|
||||
exit 1
|
||||
}
|
||||
if ($spec -match '^(\d+)\s*-\s*(\d+)$') {
|
||||
$frm = [int]$Matches[1]; $to = [int]$Matches[2]
|
||||
} elseif ($spec -match '^\d+$') {
|
||||
$frm = [int]$spec; $to = $frm
|
||||
} else {
|
||||
[Console]::Error.WriteLine("${key}: invalid '$axis' value `"$spec`": $where")
|
||||
exit 1
|
||||
}
|
||||
if ($frm -lt 1) { $frm = 1 }
|
||||
if ($to -lt $frm) {
|
||||
[Console]::Error.WriteLine("${key}: '$axis' range is reversed `"$spec`": $where")
|
||||
exit 1
|
||||
}
|
||||
$header = ''
|
||||
if ($null -ne $g.titleLocation -and "$($g.titleLocation)" -ne '') {
|
||||
switch ("$($g.titleLocation)".Trim().ToLowerInvariant()) {
|
||||
'auto' { $header = '' }
|
||||
'begin' { $header = 'Begin' }
|
||||
'end' { $header = 'End' }
|
||||
default {
|
||||
[Console]::Error.WriteLine("${key}: unknown 'titleLocation' value `"$($g.titleLocation)`" ($where). Allowed: begin, end, auto")
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
}
|
||||
$out += @{
|
||||
B = $frm - 1; E = $to - 1
|
||||
Name = $g.name
|
||||
Collapsed = ($g.collapsed -eq $true -or "$($g.collapsed)" -eq 'true')
|
||||
Header = $header
|
||||
}
|
||||
}
|
||||
for ($i = 0; $i -lt $out.Count; $i++) {
|
||||
for ($j = $i + 1; $j -lt $out.Count; $j++) {
|
||||
$a = $out[$i]; $b = $out[$j]
|
||||
if ($a.E -lt $b.B -or $b.E -lt $a.B) { continue }
|
||||
if (($a.B -le $b.B -and $b.E -le $a.E) -or ($b.B -le $a.B -and $a.E -le $b.E)) { continue }
|
||||
[Console]::Error.WriteLine("${key}: ranges must nest or be disjoint, got a partial overlap ($($a.B + 1)-$($a.E + 1) and $($b.B + 1)-$($b.E + 1))")
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
# Порядок платформы — родитель раньше детей, по возрастанию начала.
|
||||
return @($out | Sort-Object @{ Expression = { $_.B } }, @{ Expression = { -$_.E } })
|
||||
}
|
||||
|
||||
function Get-GroupLevels {
|
||||
# Глубина вложенности. На корпусе она совпала с <vgLevels> у всех 1797 макетов.
|
||||
param($groups)
|
||||
$depth = 0
|
||||
for ($i = 0; $i -lt $groups.Count; $i++) {
|
||||
$g = $groups[$i]; $d = 1
|
||||
for ($j = 0; $j -lt $groups.Count; $j++) {
|
||||
if ($j -eq $i) { continue }
|
||||
$o = $groups[$j]
|
||||
if ($o.B -le $g.B -and $g.E -le $o.E -and -not ($o.B -eq $g.B -and $o.E -eq $g.E)) { $d++ }
|
||||
}
|
||||
if ($d -gt $depth) { $depth = $d }
|
||||
}
|
||||
return $depth
|
||||
}
|
||||
|
||||
function Emit-Groups {
|
||||
param([string]$tag, $groups)
|
||||
foreach ($g in $groups) {
|
||||
X "`t<$tag>"
|
||||
X "`t`t<b>$($g.B)</b>"
|
||||
if ($g.E -ne $g.B) { X "`t`t<e>$($g.E)</e>" }
|
||||
if ($null -ne $g.Name) {
|
||||
$pairs = @()
|
||||
if ($g.Name -is [System.Collections.IDictionary]) {
|
||||
foreach ($k in $g.Name.Keys) { $pairs += @{ Lang = "$k"; Text = "$($g.Name[$k])" } }
|
||||
} elseif ($g.Name -is [System.Management.Automation.PSCustomObject]) {
|
||||
foreach ($pr in $g.Name.PSObject.Properties) { $pairs += @{ Lang = $pr.Name; Text = "$($pr.Value)" } }
|
||||
} else {
|
||||
foreach ($l in $textLanguages) { $pairs += @{ Lang = $l; Text = "$($g.Name)" } }
|
||||
}
|
||||
X "`t`t<t>"
|
||||
foreach ($pr in $pairs) {
|
||||
X "`t`t`t<v8:item>"
|
||||
X "`t`t`t`t<v8:lang>$($pr.Lang)</v8:lang>"
|
||||
X "`t`t`t`t<v8:content>$(Esc-XmlText $pr.Text)</v8:content>"
|
||||
X "`t`t`t</v8:item>"
|
||||
}
|
||||
X "`t`t</t>"
|
||||
}
|
||||
# Развёрнутая группировка тега не пишет: на корпусе <o> только со значением false.
|
||||
if ($g.Collapsed) { X "`t`t<o>false</o>" }
|
||||
if ($g.Header) { X "`t`t<g>$($g.Header)</g>" }
|
||||
X "`t</$tag>"
|
||||
}
|
||||
}
|
||||
|
||||
$rowGroups = Get-Groups 'rowGroups' 'rows'
|
||||
$colGroups = Get-Groups 'columnGroups' 'cols'
|
||||
|
||||
# 7e. Scalar metadata
|
||||
X "`t<templateMode>true</templateMode>"
|
||||
X "`t<defaultFormatIndex>$defaultFormatIndex</defaultFormatIndex>"
|
||||
X "`t<height>$totalRowCount</height>"
|
||||
if ($rowGroups.Count -gt 0) { X "`t<vgLevels>$(Get-GroupLevels $rowGroups)</vgLevels>" }
|
||||
X "`t<vgRows>$totalRowCount</vgRows>"
|
||||
Emit-Groups 'vg' $rowGroups
|
||||
Emit-Groups 'hg' $colGroups
|
||||
|
||||
# 7f. Merges
|
||||
foreach ($m in $merges) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-compile v1.43 — Compile 1C spreadsheet from JSON
|
||||
# mxl-compile v1.44 — Compile 1C spreadsheet from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import hashlib
|
||||
@@ -1953,11 +1953,115 @@ def main():
|
||||
'EndCol': cols[1] - 1 if cols else -1,
|
||||
})
|
||||
|
||||
# 7e-bis. Группировки строк и колонок. Платформа хранит их плоским списком диапазонов;
|
||||
# вложенность выражена вхождением одного диапазона в другой, а частичных пересечений не
|
||||
# бывает вовсе (корпус: 40 620 886 пар непересекающихся, 599 958 вложенных, 0 частичных).
|
||||
def parse_groups(key, axis):
|
||||
out = []
|
||||
for i, g in enumerate(defn.get(key) or [], start=1):
|
||||
where = f'{key}[{i}]'
|
||||
if not isinstance(g, dict):
|
||||
print(f'{key}: element must be an object: {where}', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
spec = g.get(axis)
|
||||
if spec is None or str(spec).strip() == '':
|
||||
print(f"{key}: '{axis}' is required: {where}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
spec = str(spec).strip()
|
||||
m = re.match(r'^(\d+)\s*-\s*(\d+)$', spec)
|
||||
if m:
|
||||
frm, to = int(m.group(1)), int(m.group(2))
|
||||
elif re.match(r'^\d+$', spec):
|
||||
frm = to = int(spec)
|
||||
else:
|
||||
print(f"{key}: invalid '{axis}' value \"{spec}\": {where}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if frm < 1:
|
||||
frm = 1
|
||||
if to < frm:
|
||||
print(f"{key}: '{axis}' range is reversed \"{spec}\": {where}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
header = g.get('titleLocation')
|
||||
header = str(header).strip().lower() if header is not None else ''
|
||||
if header in ('', 'auto'):
|
||||
header = ''
|
||||
elif header == 'begin':
|
||||
header = 'Begin'
|
||||
elif header == 'end':
|
||||
header = 'End'
|
||||
else:
|
||||
print(f"{key}: unknown 'titleLocation' value \"{g.get('titleLocation')}\""
|
||||
f' ({where}). Allowed: begin, end, auto', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
out.append({
|
||||
'B': frm - 1, 'E': to - 1,
|
||||
'Name': g.get('name'),
|
||||
'Collapsed': g.get('collapsed') is True or str(g.get('collapsed')).lower() == 'true',
|
||||
'Header': header,
|
||||
})
|
||||
for i in range(len(out)):
|
||||
for j in range(i + 1, len(out)):
|
||||
a, b = out[i], out[j]
|
||||
if a['E'] < b['B'] or b['E'] < a['B']:
|
||||
continue
|
||||
if (a['B'] <= b['B'] and b['E'] <= a['E']) or (b['B'] <= a['B'] and a['E'] <= b['E']):
|
||||
continue
|
||||
print(f'{key}: ranges must nest or be disjoint, got a partial overlap'
|
||||
f' ({a["B"] + 1}-{a["E"] + 1} and {b["B"] + 1}-{b["E"] + 1})', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
# Порядок платформы — родитель раньше детей, по возрастанию начала.
|
||||
out.sort(key=lambda x: (x['B'], -x['E']))
|
||||
return out
|
||||
|
||||
row_groups = parse_groups('rowGroups', 'rows')
|
||||
col_groups = parse_groups('columnGroups', 'cols')
|
||||
|
||||
def group_levels(groups):
|
||||
"""Глубина вложенности. На корпусе она совпала с <vgLevels> у всех 1797 макетов."""
|
||||
depth = 0
|
||||
for i, g in enumerate(groups):
|
||||
d = 1
|
||||
for j, o in enumerate(groups):
|
||||
if j != i and o['B'] <= g['B'] and g['E'] <= o['E'] and (o['B'], o['E']) != (g['B'], g['E']):
|
||||
d += 1
|
||||
depth = max(depth, d)
|
||||
return depth
|
||||
|
||||
def emit_groups(lines, tag, groups):
|
||||
for g in groups:
|
||||
lines.append(f'\t<{tag}>')
|
||||
lines.append(f'\t\t<b>{g["B"]}</b>')
|
||||
if g['E'] != g['B']:
|
||||
lines.append(f'\t\t<e>{g["E"]}</e>')
|
||||
if g['Name'] is not None:
|
||||
value = g['Name']
|
||||
if isinstance(value, dict):
|
||||
pairs = [(str(k), str(v)) for k, v in value.items()]
|
||||
else:
|
||||
pairs = [(lang, str(value)) for lang in text_languages]
|
||||
lines.append('\t\t<t>')
|
||||
for lang, content in pairs:
|
||||
lines.append('\t\t\t<v8:item>')
|
||||
lines.append(f'\t\t\t\t<v8:lang>{lang}</v8:lang>')
|
||||
lines.append(f'\t\t\t\t<v8:content>{esc_xml_text(content)}</v8:content>')
|
||||
lines.append('\t\t\t</v8:item>')
|
||||
lines.append('\t\t</t>')
|
||||
# Развёрнутая группировка тега не пишет: на корпусе <o> только со значением false.
|
||||
if g['Collapsed']:
|
||||
lines.append('\t\t<o>false</o>')
|
||||
if g['Header']:
|
||||
lines.append(f'\t\t<g>{g["Header"]}</g>')
|
||||
lines.append(f'\t</{tag}>')
|
||||
|
||||
# 7e. Scalar metadata
|
||||
lines.append(f'\t<templateMode>true</templateMode>')
|
||||
lines.append(f'\t<defaultFormatIndex>{default_format_index}</defaultFormatIndex>')
|
||||
lines.append(f'\t<height>{total_row_count}</height>')
|
||||
if row_groups:
|
||||
lines.append(f'\t<vgLevels>{group_levels(row_groups)}</vgLevels>')
|
||||
lines.append(f'\t<vgRows>{total_row_count}</vgRows>')
|
||||
emit_groups(lines, 'vg', row_groups)
|
||||
emit_groups(lines, 'hg', col_groups)
|
||||
|
||||
# 7f. Merges
|
||||
for m in merges:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# mxl-decompile v1.23 — Decompile 1C spreadsheet to JSON
|
||||
# mxl-decompile v1.24 — Decompile 1C spreadsheet to JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -265,6 +265,41 @@ function Get-Format {
|
||||
return $rawFormats[$idx - 1]
|
||||
}
|
||||
|
||||
# --- 4b. Группировки строк и колонок ---
|
||||
# Платформа хранит их плоским списком диапазонов, родитель раньше детей. Число уровней
|
||||
# (<vgLevels>) не читаем: оно выводится из вложенности — совпало на всех 1797 макетах.
|
||||
function Read-Groups {
|
||||
param([string]$tag, [string]$axis)
|
||||
$out = @()
|
||||
foreach ($g in $root.SelectNodes("d:$tag", $ns)) {
|
||||
$bNode = $g.SelectSingleNode("d:b", $ns)
|
||||
$b = if ($bNode) { [int]$bNode.InnerText } else { 0 }
|
||||
$eNode = $g.SelectSingleNode("d:e", $ns)
|
||||
$e = if ($eNode) { [int]$eNode.InnerText } else { $b }
|
||||
$item = [ordered]@{}
|
||||
$item[$axis] = if ($e -eq $b) { $b + 1 } else { "$($b + 1)-$($e + 1)" }
|
||||
$tEl = $g.SelectSingleNode("d:t", $ns)
|
||||
if ($tEl) {
|
||||
$byLang = [ordered]@{}
|
||||
foreach ($it in $tEl.SelectNodes("v8:item", $ns)) {
|
||||
$l = $it.SelectSingleNode("v8:lang", $ns)
|
||||
$cnt = $it.SelectSingleNode("v8:content", $ns)
|
||||
$byLang[$(if ($l) { $l.InnerText } else { '' })] = $(if ($cnt) { $cnt.InnerText } else { '' })
|
||||
}
|
||||
if ($byLang.Count -gt 0) { $item["name"] = $byLang }
|
||||
}
|
||||
$oNode = $g.SelectSingleNode("d:o", $ns)
|
||||
if ($oNode -and $oNode.InnerText.Trim() -ceq 'false') { $item["collapsed"] = $true }
|
||||
$gNode = $g.SelectSingleNode("d:g", $ns)
|
||||
if ($gNode -and $gNode.InnerText) { $item["titleLocation"] = $gNode.InnerText.Trim().ToLowerInvariant() }
|
||||
$out += $item
|
||||
}
|
||||
return @($out)
|
||||
}
|
||||
|
||||
$rowGroups = Read-Groups 'vg' 'rows'
|
||||
$colGroups = Read-Groups 'hg' 'cols'
|
||||
|
||||
# --- 5. Extract columns and default width ---
|
||||
|
||||
# Колоночная раскладка («индивидуальная ширина колонок» для группы строк) — элемент <columns>.
|
||||
@@ -1435,6 +1470,13 @@ if ($extraSets.Count -gt 0) {
|
||||
$result["columnSets"] = $setsOut
|
||||
}
|
||||
|
||||
# Имя группировки — та же мультиязычная строка, что текст ячейки, и сворачивается так же.
|
||||
foreach ($g in ($rowGroups + $colGroups)) {
|
||||
if ($g.Contains("name")) { $g["name"] = Get-DslText $g["name"] }
|
||||
}
|
||||
if ($rowGroups.Count -gt 0) { $result["rowGroups"] = [array]$rowGroups }
|
||||
if ($colGroups.Count -gt 0) { $result["columnGroups"] = [array]$colGroups }
|
||||
|
||||
$result["areas"] = [array]$dslAreas
|
||||
|
||||
# Именованные области, не выразимые блоком, — координатами. Тип не пишем: он выводится
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-decompile v1.23 — Decompile 1C spreadsheet to JSON
|
||||
# mxl-decompile v1.24 — Decompile 1C spreadsheet to JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -431,6 +431,36 @@ def main():
|
||||
return None
|
||||
return raw_formats[idx - 1]
|
||||
|
||||
# --- 4b. Группировки строк и колонок ---
|
||||
# Платформа хранит их плоским списком диапазонов, родитель раньше детей. Число уровней
|
||||
# (<vgLevels>) не читаем: оно выводится из вложенности — совпало на всех 1797 макетах.
|
||||
def read_groups(tag, axis):
|
||||
out = []
|
||||
for g in findall(root, "d:" + tag):
|
||||
b = int_of(find(g, "d:b"))
|
||||
e_node = find(g, "d:e")
|
||||
e = int_of(e_node, b) if e_node is not None else b
|
||||
item = OrderedDict()
|
||||
item[axis] = (b + 1) if e == b else f'{b + 1}-{e + 1}'
|
||||
t_el = find(g, "d:t")
|
||||
if t_el is not None:
|
||||
by_lang = OrderedDict()
|
||||
for it in findall(t_el, "v8:item"):
|
||||
lang = text_of(find(it, "v8:lang")) or ''
|
||||
by_lang[lang] = text_of(find(it, "v8:content")) or ''
|
||||
if by_lang:
|
||||
item["name"] = by_lang
|
||||
if (text_of(find(g, "d:o")) or 'true').strip() == 'false':
|
||||
item["collapsed"] = True
|
||||
place = text_of(find(g, "d:g"))
|
||||
if place:
|
||||
item["titleLocation"] = place.strip().lower()
|
||||
out.append(item)
|
||||
return out
|
||||
|
||||
row_groups = read_groups("vg", "rows")
|
||||
col_groups = read_groups("hg", "cols")
|
||||
|
||||
# --- 5. Extract columns and default width ---
|
||||
|
||||
# Колоночная раскладка («индивидуальная ширина колонок» для группы строк) — элемент <columns>.
|
||||
@@ -1433,6 +1463,15 @@ def main():
|
||||
sets_out[cs["Id"]] = entry
|
||||
result["columnSets"] = sets_out
|
||||
|
||||
# Имя группировки — та же мультиязычная строка, что текст ячейки, и сворачивается так же.
|
||||
for _g in row_groups + col_groups:
|
||||
if "name" in _g:
|
||||
_g["name"] = get_dsl_text(_g["name"])
|
||||
if row_groups:
|
||||
result["rowGroups"] = row_groups
|
||||
if col_groups:
|
||||
result["columnGroups"] = col_groups
|
||||
|
||||
result["areas"] = dsl_areas
|
||||
|
||||
# Именованные области, не выразимые блоком, — координатами. Тип не пишем: он выводится
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# mxl-validate v1.5 — Validate 1C spreadsheet
|
||||
# mxl-validate v1.6 — Validate 1C spreadsheet
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Alias('Path')]
|
||||
@@ -507,6 +507,38 @@ if ($valueFormatIdx.Count -gt 0) {
|
||||
Report-OK "Value cells: $($valueFormatIdx.Count) value formats"
|
||||
}
|
||||
|
||||
# --- Check 14: группировки строк и колонок ---
|
||||
# Диапазоны группировок либо вложены, либо не пересекаются: на корпусе 40 620 886 пар
|
||||
# непересекающихся и 599 958 вложенных, частичных пересечений нет ни одного.
|
||||
|
||||
foreach ($tag in @('vg', 'hg')) {
|
||||
$ranges = @()
|
||||
foreach ($g in $root.SelectNodes("d:$tag", $nsMgr)) {
|
||||
$bNode = $g.SelectSingleNode("d:b", $nsMgr)
|
||||
if (-not $bNode) {
|
||||
Report-Error "Group <$tag>: <b> is missing"
|
||||
continue
|
||||
}
|
||||
$b = [int]$bNode.InnerText
|
||||
$eNode = $g.SelectSingleNode("d:e", $nsMgr)
|
||||
$e = if ($eNode) { [int]$eNode.InnerText } else { $b }
|
||||
if ($e -lt $b) { Report-Error "Group <$tag> $b..${e}: range is reversed" }
|
||||
if ($tag -ceq 'vg' -and $docHeight -gt 0 -and $b -ge $docHeight) {
|
||||
Report-Warn "Group <vg> starts at row $b, beyond document height ($docHeight)"
|
||||
}
|
||||
$ranges += ,@($b, $e)
|
||||
}
|
||||
for ($i = 0; $i -lt $ranges.Count; $i++) {
|
||||
for ($j = $i + 1; $j -lt $ranges.Count; $j++) {
|
||||
$a = $ranges[$i]; $c = $ranges[$j]
|
||||
if ($a[1] -lt $c[0] -or $c[1] -lt $a[0]) { continue }
|
||||
if (($a[0] -le $c[0] -and $c[1] -le $a[1]) -or ($c[0] -le $a[0] -and $a[1] -le $c[1])) { continue }
|
||||
Report-Error "Groups <$tag> $($a[0])..$($a[1]) and $($c[0])..$($c[1]) overlap partially"
|
||||
}
|
||||
}
|
||||
if ($ranges.Count -gt 0) { Report-OK "Groups <$tag>: $($ranges.Count)" }
|
||||
}
|
||||
|
||||
# --- Summary ---
|
||||
|
||||
$checks = $script:okCount + $errors + $warnings
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-validate v1.5 — Validate 1C spreadsheet document Template.xml
|
||||
# mxl-validate v1.6 — 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
|
||||
@@ -494,6 +494,35 @@ def main():
|
||||
if value_format_idx:
|
||||
r.ok(f'Value cells: {len(value_format_idx)} value formats')
|
||||
|
||||
# --- Check 14: группировки строк и колонок ---
|
||||
# Диапазоны группировок либо вложены, либо не пересекаются: на корпусе 40 620 886 пар
|
||||
# непересекающихся и 599 958 вложенных, частичных пересечений нет ни одного.
|
||||
for tag in ('vg', 'hg'):
|
||||
ranges = []
|
||||
for g in root.findall(f'{{{NS_D}}}{tag}'):
|
||||
b_node = g.find(f'{{{NS_D}}}b')
|
||||
if b_node is None or not b_node.text:
|
||||
r.error(f'Group <{tag}>: <b> is missing')
|
||||
continue
|
||||
b = int(b_node.text)
|
||||
e_node = g.find(f'{{{NS_D}}}e')
|
||||
e = int(e_node.text) if e_node is not None and e_node.text else b
|
||||
if e < b:
|
||||
r.error(f'Group <{tag}> {b}..{e}: range is reversed')
|
||||
if tag == 'vg' and doc_height > 0 and b >= doc_height:
|
||||
r.warn(f'Group <vg> starts at row {b}, beyond document height ({doc_height})')
|
||||
ranges.append((b, e))
|
||||
for i in range(len(ranges)):
|
||||
for j in range(i + 1, len(ranges)):
|
||||
a, c = ranges[i], ranges[j]
|
||||
if a[1] < c[0] or c[1] < a[0]:
|
||||
continue
|
||||
if (a[0] <= c[0] and c[1] <= a[1]) or (c[0] <= a[0] and a[1] <= c[1]):
|
||||
continue
|
||||
r.error(f'Groups <{tag}> {a[0]}..{a[1]} and {c[0]}..{c[1]} overlap partially')
|
||||
if ranges:
|
||||
r.ok(f'Groups <{tag}>: {len(ranges)}')
|
||||
|
||||
# --- Finalize ---
|
||||
checks = r.ok_count + r.errors + r.warnings
|
||||
if r.errors == 0 and r.warnings == 0 and not detailed:
|
||||
|
||||
@@ -601,6 +601,38 @@ current-config не объявляет, поэтому вынести объяв
|
||||
обратные, ячейки продолжают ссылаться на записи со старыми ширинами. Из итогового XML это
|
||||
значение не выводится — воспроизводить его не нужно.
|
||||
|
||||
## Группировки строк и колонок
|
||||
|
||||
```xml
|
||||
<vgLevels>2</vgLevels>
|
||||
<vgRows>8</vgRows>
|
||||
<vg>
|
||||
<b>1</b> <!-- начало диапазона, 0-based -->
|
||||
<e>2</e> <!-- конец; нет — группировка из одной строки -->
|
||||
<t><v8:item><v8:lang>ru</v8:lang><v8:content>Итоговая</v8:content></v8:item></t>
|
||||
<o>false</o> <!-- свёрнута; развёрнутая тег не пишет -->
|
||||
<g>Begin</g> <!-- расположение заголовка: Begin | End; нет — Авто -->
|
||||
</vg>
|
||||
<hg>…</hg> <!-- то же для колонок -->
|
||||
```
|
||||
|
||||
Строки группируются часто (1 797 макетов, 170 967 группировок), колонки — почти никогда
|
||||
(1 макет, 1 группировка). Порядок документных тегов: `height` → `vgLevels` → `vgRows` → `vg` →
|
||||
`hg`; `vgLevels` пишется только при наличии группировок.
|
||||
|
||||
| Наблюдение | Данные корпуса |
|
||||
|---|---|
|
||||
| диапазоны либо вложены, либо не пересекаются | 40 620 886 пар непересекающихся, 599 958 вложенных, **0 частичных** |
|
||||
| порядок записи — родитель раньше вложенных, по возрастанию начала | совпало у 1 798 макетов из 1 798 |
|
||||
| `<vgLevels>` = глубина вложенности | совпало у 1 797 из 1 797 |
|
||||
| `<o>` | только `false` (6 130) — развёрнутая группировка тег не пишет |
|
||||
| `<g>` | в корпусе только `Begin` (6); значение `End` даёт Конфигуратор при «Расположение заголовка: Конец» |
|
||||
|
||||
Имя (`<t>`) — мультиязычная строка, и в 143 455 случаях это автоимя `R<номер строки + 1>`.
|
||||
Вывести его нельзя: 16 666 имён «протухли» (`R91` у строки 103 — строки вставляли после
|
||||
создания группировки), а 10 287 группировок имени не имеют вовсе. Языковые наборы —
|
||||
`ru`+`en` (93 250) либо псевдоязык `#` (67 431), никогда вместе.
|
||||
|
||||
## Примечание к ячейке
|
||||
|
||||
```xml
|
||||
|
||||
+31
-1
@@ -87,6 +87,8 @@
|
||||
| `areas` | да | — | Массив областей — диапазонов подряд идущих строк (порядок = порядок в документе); имя необязательно |
|
||||
| `namedAreas` | нет | — | Именованные области, заданные координатами (см. ниже) |
|
||||
| `columnSets` | нет | — | Дополнительные колоночные раскладки (см. `mxl-dsl-styles.md`) |
|
||||
| `rowGroups` | нет | — | Группы строк (см. ниже) |
|
||||
| `columnGroups` | нет | — | Группы колонок (см. ниже) |
|
||||
|
||||
## Области (`areas[]`)
|
||||
|
||||
@@ -300,6 +302,35 @@
|
||||
и компилятор проставляет это сам. `autoSize` и `box` независимы: при автоподгоне размера
|
||||
положение окошка всё равно хранится.
|
||||
|
||||
## Группы строк и колонок
|
||||
|
||||
Диапазон строк или колонок, который сворачивается кнопкой на полях. Задаются плоским списком;
|
||||
вложенность выражена вхождением одного диапазона в другой:
|
||||
|
||||
```json
|
||||
"rowGroups": [
|
||||
{ "rows": "2-4" },
|
||||
{ "rows": 3 },
|
||||
{ "rows": 5, "name": "Итоговая", "collapsed": true, "titleLocation": "begin" }
|
||||
],
|
||||
"columnGroups": [
|
||||
{ "cols": "2-3", "name": { "ru": "Показатели", "en": "Values" } },
|
||||
{ "cols": 3 }
|
||||
]
|
||||
```
|
||||
|
||||
| Поле | Обяз. | По умолч. | Описание |
|
||||
|------|:-----:|-----------|----------|
|
||||
| `rows` / `cols` | да | — | Диапазон 1-based: число или `"N-M"` |
|
||||
| `name` | нет | — | Имя группы: строка или объект «язык → текст» |
|
||||
| `collapsed` | нет | `false` | Свёрнута ли группа при открытии |
|
||||
| `titleLocation` | нет | `auto` | Расположение заголовка: `begin`, `end`, `auto` |
|
||||
|
||||
Диапазоны либо вложены, либо не пересекаются — частичное пересечение платформа не хранит, и
|
||||
компилятор отвергает его с ненулевым кодом выхода. Число уровней вложенности считается само.
|
||||
Порядок в списке не важен: компилятор пишет группы так же, как платформа, — родитель
|
||||
раньше вложенных, по возрастанию начала.
|
||||
|
||||
## `rowStyle` — оформление строки
|
||||
|
||||
Стиль применяется ко ВСЕЙ ширине строки: позиции без явных ячеек получают тот же стиль. Так в табличных строках получаются сплошные рамки. Он же становится оформлением самой строки — именно так платформа хранит строку, оформленную целиком.
|
||||
@@ -316,7 +347,6 @@ XML не возвращается.
|
||||
|
||||
- объединения, не привязанные к ячейке (по всей высоте или ширине документа);
|
||||
- рисунки и картинки, в том числе штрихкоды;
|
||||
- группировки строк и колонок;
|
||||
- колонтитулы, параметры печати, область печати.
|
||||
|
||||
Пересборка макета из DSL — это полная перегенерация, а не точечная правка XML, поэтому
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Ошибка: группировки пересекаются частично",
|
||||
"input": {
|
||||
"columns": 2,
|
||||
"areas": [{ "rows": [["a"], ["b"], ["c"], ["d"]] }],
|
||||
"rowGroups": [{ "rows": "1-3" }, { "rows": "2-4" }]
|
||||
},
|
||||
"params": { "outputPath": "Template.xml" },
|
||||
"expectError": "rowGroups: ranges must nest or be disjoint, got a partial overlap (1-3 and 2-4)"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Ошибка: неизвестное расположение заголовка группировки",
|
||||
"input": {
|
||||
"columns": 2,
|
||||
"areas": [{ "rows": [["a"], ["b"]] }],
|
||||
"rowGroups": [{ "rows": 2, "titleLocation": "middle" }]
|
||||
},
|
||||
"params": { "outputPath": "Template.xml" },
|
||||
"expectError": "rowGroups: unknown 'titleLocation' value \"middle\" (rowGroups[1]). Allowed: begin, end, auto"
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
<?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>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>11</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>12</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>13</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>1</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>21</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>22</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>23</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>2</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>31</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>23</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>33</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>3</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>41</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>4</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>51</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>5</index>
|
||||
<indexTo>7</indexTo>
|
||||
<row>
|
||||
<empty>true</empty>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>1</defaultFormatIndex>
|
||||
<height>8</height>
|
||||
<vgLevels>2</vgLevels>
|
||||
<vgRows>8</vgRows>
|
||||
<vg>
|
||||
<b>1</b>
|
||||
<e>2</e>
|
||||
</vg>
|
||||
<vg>
|
||||
<b>2</b>
|
||||
</vg>
|
||||
<vg>
|
||||
<b>3</b>
|
||||
</vg>
|
||||
<vg>
|
||||
<b>4</b>
|
||||
</vg>
|
||||
<vg>
|
||||
<b>5</b>
|
||||
<t>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Произвеольное имя группы</v8:content>
|
||||
</v8:item>
|
||||
</t>
|
||||
</vg>
|
||||
<vg>
|
||||
<b>6</b>
|
||||
<t>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>ПИмяНачало</v8:content>
|
||||
</v8:item>
|
||||
</t>
|
||||
<g>Begin</g>
|
||||
</vg>
|
||||
<vg>
|
||||
<b>7</b>
|
||||
<t>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>ПИмяКонец</v8:content>
|
||||
</v8:item>
|
||||
</t>
|
||||
<g>End</g>
|
||||
</vg>
|
||||
<hg>
|
||||
<b>1</b>
|
||||
<e>2</e>
|
||||
</hg>
|
||||
<hg>
|
||||
<b>2</b>
|
||||
<t>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Горизонтальная</v8:content>
|
||||
</v8:item>
|
||||
</t>
|
||||
</hg>
|
||||
<format>
|
||||
<width>72</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"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,25 @@
|
||||
{
|
||||
"name": "Группировки строк и колонок",
|
||||
"input": {
|
||||
"columns": 3,
|
||||
"areas": [
|
||||
{ "rows": [
|
||||
["11", "12", "13"],
|
||||
["21", "22", "23"],
|
||||
["31", "32", "33"],
|
||||
["41"],
|
||||
["51"]
|
||||
]}
|
||||
],
|
||||
"rowGroups": [
|
||||
{ "rows": "2-4" },
|
||||
{ "rows": 3 },
|
||||
{ "rows": 5, "name": "Итоговая", "collapsed": true, "titleLocation": "begin" }
|
||||
],
|
||||
"columnGroups": [
|
||||
{ "cols": "2-3", "name": { "ru": "Показатели", "en": "Values" } },
|
||||
{ "cols": 3, "titleLocation": "end" }
|
||||
]
|
||||
},
|
||||
"params": { "outputPath": "Template.xml" }
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<?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>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>11</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>12</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>13</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>1</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>21</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>22</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>23</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>2</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>31</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>32</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>33</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>3</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>41</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>4</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>51</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>1</defaultFormatIndex>
|
||||
<height>5</height>
|
||||
<vgLevels>2</vgLevels>
|
||||
<vgRows>5</vgRows>
|
||||
<vg>
|
||||
<b>1</b>
|
||||
<e>3</e>
|
||||
</vg>
|
||||
<vg>
|
||||
<b>2</b>
|
||||
</vg>
|
||||
<vg>
|
||||
<b>4</b>
|
||||
<t>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Итоговая</v8:content>
|
||||
</v8:item>
|
||||
</t>
|
||||
<o>false</o>
|
||||
<g>Begin</g>
|
||||
</vg>
|
||||
<hg>
|
||||
<b>1</b>
|
||||
<e>2</e>
|
||||
<t>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Показатели</v8:content>
|
||||
</v8:item>
|
||||
<v8:item>
|
||||
<v8:lang>en</v8:lang>
|
||||
<v8:content>Values</v8:content>
|
||||
</v8:item>
|
||||
</t>
|
||||
</hg>
|
||||
<hg>
|
||||
<b>2</b>
|
||||
<g>End</g>
|
||||
</hg>
|
||||
<format>
|
||||
<width>10</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "Roundtrip — группировки строк и колонок",
|
||||
"preRun": [
|
||||
{
|
||||
"script": "mxl-compile/scripts/mxl-compile",
|
||||
"input": {
|
||||
"columns": 3,
|
||||
"areas": [
|
||||
{ "rows": [["11", "12", "13"], ["21", "22", "23"], ["31"], ["41"], ["51"]] }
|
||||
],
|
||||
"rowGroups": [
|
||||
{ "rows": "2-4" },
|
||||
{ "rows": 3 },
|
||||
{ "rows": 5, "name": "Итоговая", "collapsed": true, "titleLocation": "begin" }
|
||||
],
|
||||
"columnGroups": [
|
||||
{ "cols": "2-3", "name": { "#": "R2" } },
|
||||
{ "cols": 3, "titleLocation": "end" }
|
||||
]
|
||||
},
|
||||
"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,179 @@
|
||||
<?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>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>11</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>12</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>13</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>1</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>21</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>22</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>23</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>2</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>31</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>3</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>41</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>4</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>51</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>1</defaultFormatIndex>
|
||||
<height>5</height>
|
||||
<vgLevels>2</vgLevels>
|
||||
<vgRows>5</vgRows>
|
||||
<vg>
|
||||
<b>1</b>
|
||||
<e>3</e>
|
||||
</vg>
|
||||
<vg>
|
||||
<b>2</b>
|
||||
</vg>
|
||||
<vg>
|
||||
<b>4</b>
|
||||
<t>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Итоговая</v8:content>
|
||||
</v8:item>
|
||||
</t>
|
||||
<o>false</o>
|
||||
<g>Begin</g>
|
||||
</vg>
|
||||
<hg>
|
||||
<b>1</b>
|
||||
<e>2</e>
|
||||
<t>
|
||||
<v8:item>
|
||||
<v8:lang>#</v8:lang>
|
||||
<v8:content>R2</v8:content>
|
||||
</v8:item>
|
||||
</t>
|
||||
</hg>
|
||||
<hg>
|
||||
<b>2</b>
|
||||
<g>End</g>
|
||||
</hg>
|
||||
<format>
|
||||
<width>10</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1 @@
|
||||
{ "columns": 3, "defaultWidth": 10, "fonts": {}, "styles": {}, "rowGroups": [{ "rows": "2-4" }, { "rows": 3 }, { "rows": 5, "name": "Итоговая", "collapsed": true, "titleLocation": "begin" }], "columnGroups": [{ "cols": "2-3", "name": { "#": "R2" } }, { "cols": 3, "titleLocation": "end" }], "areas": [{ "rows": [["11", "12", "13"], ["21", "22", "23"], ["31"], ["41"], ["51"]] }] }
|
||||
Reference in New Issue
Block a user