mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-19 09:40:22 +03:00
feat(mxl-compile,mxl-decompile): безымянные блоки и области координатами
Инкремент A кампании mxl-roundtrip. Блочная форма DSL не выражала больше половины корпуса: у 34% макетов ERP есть строки вне именованных областей, у 21% нет ни одной области типа Rows. Декомпилятор такие строки терял, а на макетах целиком из Rectangle отдавал areas: [] — компилятор отвечал "Required field 'areas' is missing". На пилоте из 40 макетов это 10 отказов из 26. Что сделано: - имя у блока стало необязательным. Блок без имени — просто кусок сетки; именованную область он не создаёт. Отдельный «плоский режим» не нужен: макет без выразимых блоков это один безымянный блок; - namedAreas — именованные области координатами, для всего, что блоком не ложится (не-Rows и пересекающиеся). Тип области НЕ указывается: он выводится из заданных осей, ровно как в ТабличныйДокумент.Область() — только строки дают полосу строк, только колонки полосу колонок, обе оси прямоугольник. Так нельзя написать противоречие вроде type: Rows с колоночными координатами; - диапазон записывается уже существующей грамматикой DSL (как ключи columnWidths): число или "N-M". Список через запятую запрещён — область непрерывна, платформа разрывную не хранит; - прощающим вводом принимается платформенный адрес "R1C1:R2C2" и правило «0 значит 1»; в документацию не вынесено; - декомпилятор перестал пропускать области не-Rows (там стоял безусловный continue) и режет сетку на блоки детерминированно: непересекающиеся Rows задают границы, дыры становятся безымянными блоками, остальное уходит в namedAreas. Отдельно: именованные элементы теперь эмитятся отсортированными по имени. Платформа хранит их именно так — на выборке 541 макета с несколькими элементами иного порядка нет ни разу. Сортировка ординальная и регистронезависимая; Sort-Object по умолчанию сортирует по текущей культуре и на кириллице дал бы другой порядок. Отсюда дрейф 13 снэпшотов — чистая перестановка, диффы симметричны, число элементов не изменилось. На пилоте отказы areas: [] закрыты полностью (10 → 0), цикл переживают 24 макета вместо 14. Оставшиеся 16 отказов — колоночные раскладки, это инкремент B. Правка на ps1, зазеркалена в py; вывод портов и в компиляции, и в декомпиляции совпадает байт в байт. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f6a478c85c
commit
720ea05325
@@ -64,6 +64,7 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -J
|
|||||||
- Тип заполнения определяется автоматически: `param` → Parameter, `text` → Text, `template` → Template
|
- Тип заполнения определяется автоматически: `param` → Parameter, `text` → Text, `template` → Template
|
||||||
- `rowspan` — объединение строк вниз (rowStyle учитывает занятые ячейки)
|
- `rowspan` — объединение строк вниз (rowStyle учитывает занятые ячейки)
|
||||||
- `empty` в строке — шорткат для N подряд пустых строк (`{ "empty": 3 }` = три `{}`)
|
- `empty` в строке — шорткат для N подряд пустых строк (`{ "empty": 3 }` = три `{}`)
|
||||||
|
- `name` у области необязателен: блок без имени — просто кусок сетки, именованную область он не создаёт
|
||||||
- Строку можно писать массивом ячеек — позиция из порядка, `col` не нужен: `"текст"`, `"{Имя}"` — параметр, `">"` — продолжить ячейку слева, `"|"` — сверху, `null` — пропуск колонки
|
- Строку можно писать массивом ячеек — позиция из порядка, `col` не нужен: `"текст"`, `"{Имя}"` — параметр, `">"` — продолжить ячейку слева, `"|"` — сверху, `null` — пропуск колонки
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|||||||
@@ -79,7 +79,8 @@
|
|||||||
| `columnWidths` | нет | `{}` | Ширины колонок. Ключи 1-based: `"1"`, `"3-14"`, `"5,7,9"`. Значения: число (абсолют) или `"Nx"` (множитель от defaultWidth, напр. `"2x"`, `"0.5x"`) |
|
| `columnWidths` | нет | `{}` | Ширины колонок. Ключи 1-based: `"1"`, `"3-14"`, `"5,7,9"`. Значения: число (абсолют) или `"Nx"` (множитель от defaultWidth, напр. `"2x"`, `"0.5x"`) |
|
||||||
| `fonts` | нет | — | Именованные шрифты (если не задано, создаётся Arial 10) |
|
| `fonts` | нет | — | Именованные шрифты (если не задано, создаётся Arial 10) |
|
||||||
| `styles` | нет | `{}` | Именованные стили |
|
| `styles` | нет | `{}` | Именованные стили |
|
||||||
| `areas` | да | — | Массив именованных областей (порядок = порядок в документе) |
|
| `areas` | да | — | Массив блоков строк (порядок = порядок в документе); имя у блока необязательно |
|
||||||
|
| `namedAreas` | нет | — | Именованные области, заданные координатами (см. ниже) |
|
||||||
|
|
||||||
## Шрифты (`fonts.<name>`)
|
## Шрифты (`fonts.<name>`)
|
||||||
|
|
||||||
@@ -110,9 +111,46 @@
|
|||||||
|
|
||||||
| Поле | Обяз. | Описание |
|
| Поле | Обяз. | Описание |
|
||||||
|------|:-----:|----------|
|
|------|:-----:|----------|
|
||||||
| `name` | да | Имя области для `Макет.ПолучитьОбласть("Имя")` |
|
| `name` | нет | Имя области для `Макет.ПолучитьОбласть("Имя")` |
|
||||||
| `rows` | да | Массив строк |
|
| `rows` | да | Массив строк |
|
||||||
|
|
||||||
|
Макет собирается из блоков строк, идущих подряд. Имя на блоке — сокращение: компилятор разворачивает его в именованную область типа «строки» на диапазон блока. **Блок без имени** — просто кусок сетки: так описываются строки, не принадлежащие ни одной именованной области.
|
||||||
|
|
||||||
|
## Именованные области координатами (`namedAreas[]`)
|
||||||
|
|
||||||
|
Для областей, которые блоком не выражаются: не привязанных к диапазону строк (полоса колонок, прямоугольник, ячейка) и пересекающихся с другими.
|
||||||
|
|
||||||
|
| Поле | Обяз. | Описание |
|
||||||
|
|------|:-----:|----------|
|
||||||
|
| `name` | да | Имя области |
|
||||||
|
| `rows` | \* | Строки: число или диапазон `"N-M"`, 1-based |
|
||||||
|
| `cols` | \* | Колонки: число или диапазон `"N-M"`, 1-based |
|
||||||
|
|
||||||
|
\* Обязательна хотя бы одна из осей.
|
||||||
|
|
||||||
|
**Тип области не указывается** — он следует из того, какие оси заданы, как в `ТабличныйДокумент.Область()`: только строки → полоса строк, только колонки → полоса колонок, обе оси → прямоугольник, одиночные значения по обеим осям → одна ячейка.
|
||||||
|
|
||||||
|
```json
|
||||||
|
"namedAreas": [
|
||||||
|
{ "name": "ОбластьПечатиПоВысоте", "rows": "1-48" },
|
||||||
|
{ "name": "ОбластьПечатиПоШирине", "cols": "1-35" },
|
||||||
|
{ "name": "HZY", "rows": 9, "cols": "16-17" }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Диапазон — та же грамматика, что у `columnWidths`, но **только** число или `"N-M"`: список через запятую запрещён, область непрерывна.
|
||||||
|
|
||||||
|
Ошибки (stderr, код возврата 1):
|
||||||
|
|
||||||
|
| Условие | Сообщение |
|
||||||
|
|---------|-----------|
|
||||||
|
| нет `name` | `namedAreas: 'name' is required: …` |
|
||||||
|
| не задана ни одна ось | `namedAreas: at least one of 'rows'/'cols' is required: …` |
|
||||||
|
| список через запятую | `namedAreas: 'cols' must be a single number or range, got list "…": …` |
|
||||||
|
| диапазон задом наперёд | `namedAreas: 'rows' range is reversed "…": …` |
|
||||||
|
|
||||||
|
Порядок именованных элементов в выходном XML — по имени: так их хранит платформа, компилятор сортирует сам.
|
||||||
|
|
||||||
## Строки (`rows[]`)
|
## Строки (`rows[]`)
|
||||||
|
|
||||||
| Поле | По умолч. | Описание |
|
| Поле | По умолч. | Описание |
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# mxl-compile v1.17 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи)
|
# mxl-compile v1.18 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
@@ -978,15 +978,118 @@ foreach ($area in $def.areas) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$areaEndRow = $globalRow - 1
|
$areaEndRow = $globalRow - 1
|
||||||
$namedItems += @{
|
# Блок без имени — просто кусок сетки: строки, не принадлежащие ни одной именованной
|
||||||
Name = $areaName
|
# области (в корпусе таких дыр 34%, а макетов вовсе без Rows-областей — 21%).
|
||||||
BeginRow = $areaStartRow
|
# Имя на блоке — сахар: разворачиваем его в обычную именованную область типа Rows.
|
||||||
EndRow = $areaEndRow
|
if (-not [string]::IsNullOrEmpty($areaName)) {
|
||||||
|
$namedItems += @{
|
||||||
|
Name = $areaName
|
||||||
|
BeginRow = $areaStartRow
|
||||||
|
EndRow = $areaEndRow
|
||||||
|
BeginCol = -1
|
||||||
|
EndCol = -1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$totalRowCount = $globalRow
|
$totalRowCount = $globalRow
|
||||||
|
|
||||||
|
# 7d-bis. Именованные области, заданные координатами (namedAreas).
|
||||||
|
# Нужны для всего, что блоком не выражается: области не-Rows и пересекающиеся Rows.
|
||||||
|
# Ось, которую не указали, означает «вся» — так же устроен ТабличныйДокумент.Область().
|
||||||
|
|
||||||
|
# Диапазон — та же грамматика, что у columnWidths: число или "N-M". Список через запятую
|
||||||
|
# для области бессмыслен: область непрерывна, платформа разрывную не хранит.
|
||||||
|
function ConvertTo-AreaRange {
|
||||||
|
param($spec, [string]$axis, [string]$where)
|
||||||
|
if ($null -eq $spec) { return $null }
|
||||||
|
$s = ([string]$spec).Trim()
|
||||||
|
if ($s -eq '') { return $null }
|
||||||
|
if ($s.Contains(',')) {
|
||||||
|
[Console]::Error.WriteLine("namedAreas: '$axis' must be a single number or range, got list `"$s`": $where")
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if ($s -match '^(\d+)\s*-\s*(\d+)$') {
|
||||||
|
$from = [int]$Matches[1]; $to = [int]$Matches[2]
|
||||||
|
} elseif ($s -match '^(\d+)$') {
|
||||||
|
$from = [int]$Matches[1]; $to = $from
|
||||||
|
} else {
|
||||||
|
[Console]::Error.WriteLine("namedAreas: invalid '$axis' value `"$s`": $where")
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
# Платформа трактует 0 как 1 (см. описание Область()) — принимаем так же.
|
||||||
|
if ($from -lt 1) { $from = 1 }
|
||||||
|
if ($to -lt $from) {
|
||||||
|
[Console]::Error.WriteLine("namedAreas: '$axis' range is reversed `"$s`": $where")
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
return @{ From = $from; To = $to }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Прощающий ввод: платформенный адрес "R1C1:R2C2" — модель, пишущая код на встроенном
|
||||||
|
# языке, естественно потянется за ним. В документацию не выносим.
|
||||||
|
function ConvertFrom-R1C1 {
|
||||||
|
param([string]$s)
|
||||||
|
$m = [regex]::Match($s.Trim(), '^R(\d+)(?:C(\d+))?(?::R(\d+)(?:C(\d+))?)?$', 'IgnoreCase')
|
||||||
|
if (-not $m.Success) {
|
||||||
|
$m2 = [regex]::Match($s.Trim(), '^C(\d+)(?::C(\d+))?$', 'IgnoreCase')
|
||||||
|
if (-not $m2.Success) { return $null }
|
||||||
|
$c1 = [int]$m2.Groups[1].Value
|
||||||
|
$c2 = if ($m2.Groups[2].Success) { [int]$m2.Groups[2].Value } else { $c1 }
|
||||||
|
return @{ Rows = $null; Cols = @{ From = $c1; To = $c2 } }
|
||||||
|
}
|
||||||
|
$r1 = [int]$m.Groups[1].Value
|
||||||
|
$r2 = if ($m.Groups[3].Success) { [int]$m.Groups[3].Value } else { $r1 }
|
||||||
|
$cols = $null
|
||||||
|
if ($m.Groups[2].Success) {
|
||||||
|
$c1 = [int]$m.Groups[2].Value
|
||||||
|
$c2 = if ($m.Groups[4].Success) { [int]$m.Groups[4].Value } else { $c1 }
|
||||||
|
$cols = @{ From = $c1; To = $c2 }
|
||||||
|
}
|
||||||
|
return @{ Rows = @{ From = $r1; To = $r2 }; Cols = $cols }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($def.namedAreas) {
|
||||||
|
$naIdx = 0
|
||||||
|
foreach ($na in $def.namedAreas) {
|
||||||
|
$naIdx++
|
||||||
|
$naName = "$($na.name)"
|
||||||
|
$where = "namedAreas[$naIdx]" + $(if ($naName) { " `"$naName`"" } else { '' })
|
||||||
|
if ([string]::IsNullOrEmpty($naName)) {
|
||||||
|
[Console]::Error.WriteLine("namedAreas: 'name' is required: $where")
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
$rows = ConvertTo-AreaRange $na.rows 'rows' $where
|
||||||
|
$cols = ConvertTo-AreaRange $na.cols 'cols' $where
|
||||||
|
if (-not $rows -and -not $cols) {
|
||||||
|
$addr = $null
|
||||||
|
foreach ($k in 'area', 'at', 'address') {
|
||||||
|
if ($na.PSObject.Properties[$k] -and "$($na.$k)" -ne '') { $addr = "$($na.$k)"; break }
|
||||||
|
}
|
||||||
|
if ($addr) {
|
||||||
|
$parsed = ConvertFrom-R1C1 $addr
|
||||||
|
if ($null -eq $parsed) {
|
||||||
|
[Console]::Error.WriteLine("namedAreas: invalid address `"$addr`": $where")
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
$rows = $parsed.Rows; $cols = $parsed.Cols
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (-not $rows -and -not $cols) {
|
||||||
|
[Console]::Error.WriteLine("namedAreas: at least one of 'rows'/'cols' is required: $where")
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
# DSL 1-based, XML 0-based; отсутствующая ось помечается -1.
|
||||||
|
$namedItems += @{
|
||||||
|
Name = $naName
|
||||||
|
BeginRow = if ($rows) { $rows.From - 1 } else { -1 }
|
||||||
|
EndRow = if ($rows) { $rows.To - 1 } else { -1 }
|
||||||
|
BeginCol = if ($cols) { $cols.From - 1 } else { -1 }
|
||||||
|
EndCol = if ($cols) { $cols.To - 1 } else { -1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# 7e. Scalar metadata
|
# 7e. Scalar metadata
|
||||||
X "`t<templateMode>true</templateMode>"
|
X "`t<templateMode>true</templateMode>"
|
||||||
X "`t<defaultFormatIndex>$defaultFormatIndex</defaultFormatIndex>"
|
X "`t<defaultFormatIndex>$defaultFormatIndex</defaultFormatIndex>"
|
||||||
@@ -1004,15 +1107,26 @@ foreach ($m in $merges) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# 7g. Named items
|
# 7g. Named items
|
||||||
foreach ($ni in $namedItems) {
|
# Платформа хранит именованные элементы ОТСОРТИРОВАННЫМИ по имени: на выборке 541 макета
|
||||||
|
# с несколькими элементами иного порядка нет ни разу. Сортировка регистронезависимая и
|
||||||
|
# ординальная — Sort-Object брать нельзя, он сортирует по текущей культуре и на кириллице
|
||||||
|
# даст другой порядок. NB: имён с «ё» в выборке не встретилось, этот случай не проверен.
|
||||||
|
$sortedNamedItems = @($namedItems | Sort-Object -Property @{ Expression = { $_.Name.ToLowerInvariant() } } `
|
||||||
|
-CaseSensitive)
|
||||||
|
foreach ($ni in $sortedNamedItems) {
|
||||||
|
# Тип области выводится из указанных осей, как в ТабличныйДокумент.Область():
|
||||||
|
# нет колонок → полоса строк, нет строк → полоса колонок, обе → прямоугольник.
|
||||||
|
$hasRows = $ni.BeginRow -ge 0
|
||||||
|
$hasCols = $ni.BeginCol -ge 0
|
||||||
|
$type = if ($hasRows -and $hasCols) { 'Rectangle' } elseif ($hasCols) { 'Columns' } else { 'Rows' }
|
||||||
X "`t<namedItem xsi:type=`"NamedItemCells`">"
|
X "`t<namedItem xsi:type=`"NamedItemCells`">"
|
||||||
X "`t`t<name>$($ni.Name)</name>"
|
X "`t`t<name>$($ni.Name)</name>"
|
||||||
X "`t`t<area>"
|
X "`t`t<area>"
|
||||||
X "`t`t`t<type>Rows</type>"
|
X "`t`t`t<type>$type</type>"
|
||||||
X "`t`t`t<beginRow>$($ni.BeginRow)</beginRow>"
|
X "`t`t`t<beginRow>$($ni.BeginRow)</beginRow>"
|
||||||
X "`t`t`t<endRow>$($ni.EndRow)</endRow>"
|
X "`t`t`t<endRow>$($ni.EndRow)</endRow>"
|
||||||
X "`t`t`t<beginColumn>-1</beginColumn>"
|
X "`t`t`t<beginColumn>$($ni.BeginCol)</beginColumn>"
|
||||||
X "`t`t`t<endColumn>-1</endColumn>"
|
X "`t`t`t<endColumn>$($ni.EndCol)</endColumn>"
|
||||||
X "`t`t</area>"
|
X "`t`t</area>"
|
||||||
X "`t</namedItem>"
|
X "`t</namedItem>"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# mxl-compile v1.17 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи)
|
# mxl-compile v1.18 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
@@ -976,14 +976,105 @@ def main():
|
|||||||
global_row += 1
|
global_row += 1
|
||||||
|
|
||||||
area_end_row = global_row - 1
|
area_end_row = global_row - 1
|
||||||
named_items.append({
|
# Блок без имени — просто кусок сетки: строки, не принадлежащие ни одной именованной
|
||||||
'Name': area_name,
|
# области (в корпусе таких дыр 34%, а макетов вовсе без Rows-областей — 21%).
|
||||||
'BeginRow': area_start_row,
|
# Имя на блоке — сахар: разворачиваем его в обычную именованную область типа Rows.
|
||||||
'EndRow': area_end_row,
|
if area_name:
|
||||||
})
|
named_items.append({
|
||||||
|
'Name': area_name,
|
||||||
|
'BeginRow': area_start_row,
|
||||||
|
'EndRow': area_end_row,
|
||||||
|
'BeginCol': -1,
|
||||||
|
'EndCol': -1,
|
||||||
|
})
|
||||||
|
|
||||||
total_row_count = global_row
|
total_row_count = global_row
|
||||||
|
|
||||||
|
# 7d-bis. Именованные области, заданные координатами (namedAreas).
|
||||||
|
# Нужны для всего, что блоком не выражается: области не-Rows и пересекающиеся Rows.
|
||||||
|
# Ось, которую не указали, означает «вся» — так же устроен ТабличныйДокумент.Область().
|
||||||
|
|
||||||
|
def to_area_range(spec, axis, where):
|
||||||
|
"""Диапазон — та же грамматика, что у columnWidths: число или "N-M". Список через
|
||||||
|
запятую для области бессмыслен: область непрерывна, платформа разрывную не хранит."""
|
||||||
|
if spec is None:
|
||||||
|
return None
|
||||||
|
s = str(spec).strip()
|
||||||
|
if s == '':
|
||||||
|
return None
|
||||||
|
if ',' in s:
|
||||||
|
print(f'namedAreas: \'{axis}\' must be a single number or range, got list "{s}": {where}',
|
||||||
|
file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
m = re.match(r'^(\d+)\s*-\s*(\d+)$', s)
|
||||||
|
if m:
|
||||||
|
frm, to = int(m.group(1)), int(m.group(2))
|
||||||
|
elif re.match(r'^\d+$', s):
|
||||||
|
frm = to = int(s)
|
||||||
|
else:
|
||||||
|
print(f'namedAreas: invalid \'{axis}\' value "{s}": {where}', file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
# Платформа трактует 0 как 1 (см. описание Область()) — принимаем так же.
|
||||||
|
if frm < 1:
|
||||||
|
frm = 1
|
||||||
|
if to < frm:
|
||||||
|
print(f'namedAreas: \'{axis}\' range is reversed "{s}": {where}', file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
return (frm, to)
|
||||||
|
|
||||||
|
def from_r1c1(s):
|
||||||
|
"""Прощающий ввод: платформенный адрес "R1C1:R2C2" — модель, пишущая код на встроенном
|
||||||
|
языке, естественно потянется за ним. В документацию не выносим."""
|
||||||
|
s = s.strip()
|
||||||
|
m = re.match(r'^R(\d+)(?:C(\d+))?(?::R(\d+)(?:C(\d+))?)?$', s, re.IGNORECASE)
|
||||||
|
if not m:
|
||||||
|
m2 = re.match(r'^C(\d+)(?::C(\d+))?$', s, re.IGNORECASE)
|
||||||
|
if not m2:
|
||||||
|
return None
|
||||||
|
c1 = int(m2.group(1))
|
||||||
|
c2 = int(m2.group(2)) if m2.group(2) else c1
|
||||||
|
return (None, (c1, c2))
|
||||||
|
r1 = int(m.group(1))
|
||||||
|
r2 = int(m.group(3)) if m.group(3) else r1
|
||||||
|
cols = None
|
||||||
|
if m.group(2):
|
||||||
|
c1 = int(m.group(2))
|
||||||
|
c2 = int(m.group(4)) if m.group(4) else c1
|
||||||
|
cols = (c1, c2)
|
||||||
|
return ((r1, r2), cols)
|
||||||
|
|
||||||
|
for na_idx, na in enumerate(defn.get('namedAreas') or [], start=1):
|
||||||
|
na_name = str(na.get('name') or '')
|
||||||
|
where = f'namedAreas[{na_idx}]' + (f' "{na_name}"' if na_name else '')
|
||||||
|
if not na_name:
|
||||||
|
print(f'namedAreas: \'name\' is required: {where}', file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
rows = to_area_range(na.get('rows'), 'rows', where)
|
||||||
|
cols = to_area_range(na.get('cols'), 'cols', where)
|
||||||
|
if not rows and not cols:
|
||||||
|
addr = None
|
||||||
|
for k in ('area', 'at', 'address'):
|
||||||
|
if na.get(k):
|
||||||
|
addr = str(na.get(k))
|
||||||
|
break
|
||||||
|
if addr:
|
||||||
|
parsed = from_r1c1(addr)
|
||||||
|
if parsed is None:
|
||||||
|
print(f'namedAreas: invalid address "{addr}": {where}', file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
rows, cols = parsed
|
||||||
|
if not rows and not cols:
|
||||||
|
print(f'namedAreas: at least one of \'rows\'/\'cols\' is required: {where}', file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
# DSL 1-based, XML 0-based; отсутствующая ось помечается -1.
|
||||||
|
named_items.append({
|
||||||
|
'Name': na_name,
|
||||||
|
'BeginRow': rows[0] - 1 if rows else -1,
|
||||||
|
'EndRow': rows[1] - 1 if rows else -1,
|
||||||
|
'BeginCol': cols[0] - 1 if cols else -1,
|
||||||
|
'EndCol': cols[1] - 1 if cols else -1,
|
||||||
|
})
|
||||||
|
|
||||||
# 7e. Scalar metadata
|
# 7e. Scalar metadata
|
||||||
lines.append(f'\t<templateMode>true</templateMode>')
|
lines.append(f'\t<templateMode>true</templateMode>')
|
||||||
lines.append(f'\t<defaultFormatIndex>{default_format_index}</defaultFormatIndex>')
|
lines.append(f'\t<defaultFormatIndex>{default_format_index}</defaultFormatIndex>')
|
||||||
@@ -1001,15 +1092,24 @@ def main():
|
|||||||
lines.append('\t</merge>')
|
lines.append('\t</merge>')
|
||||||
|
|
||||||
# 7g. Named items
|
# 7g. Named items
|
||||||
for ni in named_items:
|
# Платформа хранит именованные элементы ОТСОРТИРОВАННЫМИ по имени: на выборке 541 макета
|
||||||
|
# с несколькими элементами иного порядка нет ни разу. Сортировка регистронезависимая и
|
||||||
|
# ординальная (в ps1 поэтому нельзя Sort-Object — он сортирует по текущей культуре).
|
||||||
|
# NB: имён с «ё» в выборке не встретилось, этот случай не проверен.
|
||||||
|
for ni in sorted(named_items, key=lambda x: str(x['Name']).lower()):
|
||||||
|
# Тип области выводится из указанных осей, как в ТабличныйДокумент.Область():
|
||||||
|
# нет колонок → полоса строк, нет строк → полоса колонок, обе → прямоугольник.
|
||||||
|
has_rows = int(ni['BeginRow']) >= 0
|
||||||
|
has_cols = int(ni.get('BeginCol', -1)) >= 0
|
||||||
|
area_type = 'Rectangle' if (has_rows and has_cols) else ('Columns' if has_cols else 'Rows')
|
||||||
lines.append('\t<namedItem xsi:type="NamedItemCells">')
|
lines.append('\t<namedItem xsi:type="NamedItemCells">')
|
||||||
lines.append(f'\t\t<name>{ni["Name"]}</name>')
|
lines.append(f'\t\t<name>{ni["Name"]}</name>')
|
||||||
lines.append('\t\t<area>')
|
lines.append('\t\t<area>')
|
||||||
lines.append('\t\t\t<type>Rows</type>')
|
lines.append(f'\t\t\t<type>{area_type}</type>')
|
||||||
lines.append(f'\t\t\t<beginRow>{ni["BeginRow"]}</beginRow>')
|
lines.append(f'\t\t\t<beginRow>{ni["BeginRow"]}</beginRow>')
|
||||||
lines.append(f'\t\t\t<endRow>{ni["EndRow"]}</endRow>')
|
lines.append(f'\t\t\t<endRow>{ni["EndRow"]}</endRow>')
|
||||||
lines.append('\t\t\t<beginColumn>-1</beginColumn>')
|
lines.append(f'\t\t\t<beginColumn>{ni.get("BeginCol", -1)}</beginColumn>')
|
||||||
lines.append('\t\t\t<endColumn>-1</endColumn>')
|
lines.append(f'\t\t\t<endColumn>{ni.get("EndCol", -1)}</endColumn>')
|
||||||
lines.append('\t\t</area>')
|
lines.append('\t\t</area>')
|
||||||
lines.append('\t</namedItem>')
|
lines.append('\t</namedItem>')
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# mxl-decompile v1.3 — Decompile 1C spreadsheet to JSON
|
# mxl-decompile v1.4 — Decompile 1C spreadsheet to JSON
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
@@ -161,19 +161,29 @@ foreach ($mNode in $root.SelectNodes("d:merge", $ns)) {
|
|||||||
|
|
||||||
# --- 7. Extract named items ---
|
# --- 7. Extract named items ---
|
||||||
|
|
||||||
|
# Захватываем области ВСЕХ типов. Раньше здесь стоял `if ($areaType -ne "Rows") { continue }`,
|
||||||
|
# из-за чего терялись Rectangle и Columns — а они есть у 61% макетов корпуса.
|
||||||
$namedAreas = @()
|
$namedAreas = @()
|
||||||
foreach ($niNode in $root.SelectNodes("d:namedItem", $ns)) {
|
foreach ($niNode in $root.SelectNodes("d:namedItem", $ns)) {
|
||||||
$xsiType = $niNode.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance")
|
$xsiType = $niNode.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance")
|
||||||
if ($xsiType -ne "NamedItemCells") { continue }
|
if ($xsiType -ne "NamedItemCells") { continue }
|
||||||
|
|
||||||
$areaNode = $niNode.SelectSingleNode("d:area", $ns)
|
$areaNode = $niNode.SelectSingleNode("d:area", $ns)
|
||||||
$areaType = $areaNode.SelectSingleNode("d:type", $ns).InnerText
|
if (-not $areaNode) { continue }
|
||||||
if ($areaType -ne "Rows") { continue }
|
$getCoord = {
|
||||||
|
param([string]$tag)
|
||||||
|
$n = $areaNode.SelectSingleNode("d:$tag", $ns)
|
||||||
|
if ($n) { return [int]$n.InnerText }
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
$namedAreas += @{
|
$namedAreas += @{
|
||||||
Name = $niNode.SelectSingleNode("d:name", $ns).InnerText
|
Name = $niNode.SelectSingleNode("d:name", $ns).InnerText
|
||||||
BeginRow = [int]$areaNode.SelectSingleNode("d:beginRow", $ns).InnerText
|
Type = $areaNode.SelectSingleNode("d:type", $ns).InnerText
|
||||||
EndRow = [int]$areaNode.SelectSingleNode("d:endRow", $ns).InnerText
|
BeginRow = & $getCoord 'beginRow'
|
||||||
|
EndRow = & $getCoord 'endRow'
|
||||||
|
BeginCol = & $getCoord 'beginColumn'
|
||||||
|
EndCol = & $getCoord 'endColumn'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,9 +444,50 @@ function Get-StyleName {
|
|||||||
|
|
||||||
# --- 12. Build areas ---
|
# --- 12. Build areas ---
|
||||||
|
|
||||||
|
# Сетка нарезается на блоки: непересекающиеся области типа Rows задают границы, строки вне
|
||||||
|
# них становятся БЕЗЫМЯННЫМИ блоками. Раньше строки вне областей просто терялись — в корпусе
|
||||||
|
# такие дыры у 34% макетов, а макетов вовсе без Rows-областей 21%.
|
||||||
|
# Всё, что блоком не выражается (области не-Rows и пересекающиеся Rows), уходит в namedAreas
|
||||||
|
# координатами. Правило детерминированное — иначе раундтрип поехал бы.
|
||||||
|
|
||||||
|
$maxRowIdx = -1
|
||||||
|
foreach ($k in $rowData.Keys) { if ([int]$k -gt $maxRowIdx) { $maxRowIdx = [int]$k } }
|
||||||
|
|
||||||
|
$blockAreas = @()
|
||||||
|
$overlayAreas = @()
|
||||||
|
$claimed = @{} # строка → занята блоком
|
||||||
|
foreach ($a in @($namedAreas | Sort-Object @{ Expression = { $_.BeginRow } }, @{ Expression = { $_.EndRow } })) {
|
||||||
|
$fitsBlock = ($a.Type -eq 'Rows' -and $a.BeginRow -ge 0 -and $a.EndRow -ge $a.BeginRow)
|
||||||
|
if ($fitsBlock) {
|
||||||
|
for ($r = $a.BeginRow; $r -le $a.EndRow; $r++) {
|
||||||
|
if ($claimed.ContainsKey($r)) { $fitsBlock = $false; break }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($fitsBlock) {
|
||||||
|
for ($r = $a.BeginRow; $r -le $a.EndRow; $r++) { $claimed[$r] = $true }
|
||||||
|
$blockAreas += $a
|
||||||
|
} else {
|
||||||
|
$overlayAreas += $a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Блоки в порядке строк + безымянные заполнители дыр.
|
||||||
|
$blocks = @()
|
||||||
|
$cursor = 0
|
||||||
|
foreach ($a in @($blockAreas | Sort-Object @{ Expression = { $_.BeginRow } })) {
|
||||||
|
if ($a.BeginRow -gt $cursor) {
|
||||||
|
$blocks += @{ Name = $null; BeginRow = $cursor; EndRow = $a.BeginRow - 1 }
|
||||||
|
}
|
||||||
|
$blocks += @{ Name = $a.Name; BeginRow = $a.BeginRow; EndRow = $a.EndRow }
|
||||||
|
$cursor = $a.EndRow + 1
|
||||||
|
}
|
||||||
|
if ($cursor -le $maxRowIdx) {
|
||||||
|
$blocks += @{ Name = $null; BeginRow = $cursor; EndRow = $maxRowIdx }
|
||||||
|
}
|
||||||
|
|
||||||
$dslAreas = @()
|
$dslAreas = @()
|
||||||
|
|
||||||
foreach ($area in $namedAreas) {
|
foreach ($area in $blocks) {
|
||||||
$areaRows = @()
|
$areaRows = @()
|
||||||
|
|
||||||
for ($globalRow = $area.BeginRow; $globalRow -le $area.EndRow; $globalRow++) {
|
for ($globalRow = $area.BeginRow; $globalRow -le $area.EndRow; $globalRow++) {
|
||||||
@@ -557,10 +608,11 @@ foreach ($area in $namedAreas) {
|
|||||||
else { $compressedRows += [ordered]@{ empty = $emptyRun } }
|
else { $compressedRows += [ordered]@{ empty = $emptyRun } }
|
||||||
}
|
}
|
||||||
|
|
||||||
$dslAreas += [ordered]@{
|
$dslBlock = [ordered]@{}
|
||||||
name = $area.Name
|
# Безымянный блок — просто кусок сетки, ключ name у него не пишем.
|
||||||
rows = [array]$compressedRows
|
if (-not [string]::IsNullOrEmpty($area.Name)) { $dslBlock["name"] = $area.Name }
|
||||||
}
|
$dslBlock["rows"] = [array]$compressedRows
|
||||||
|
$dslAreas += $dslBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 13. Compress columnWidths ---
|
# --- 13. Compress columnWidths ---
|
||||||
@@ -632,6 +684,23 @@ $result["fonts"] = $fontsOut
|
|||||||
$result["styles"] = $styleDefs
|
$result["styles"] = $styleDefs
|
||||||
$result["areas"] = [array]$dslAreas
|
$result["areas"] = [array]$dslAreas
|
||||||
|
|
||||||
|
# Именованные области, не выразимые блоком, — координатами. Тип не пишем: он выводится
|
||||||
|
# из указанных осей (как в ТабличныйДокумент.Область()). DSL 1-based, XML 0-based.
|
||||||
|
if ($overlayAreas.Count -gt 0) {
|
||||||
|
$naOut = @()
|
||||||
|
foreach ($a in $overlayAreas) {
|
||||||
|
$entry = [ordered]@{ name = $a.Name }
|
||||||
|
if ($a.BeginRow -ge 0) {
|
||||||
|
$entry["rows"] = if ($a.EndRow -gt $a.BeginRow) { "$($a.BeginRow + 1)-$($a.EndRow + 1)" } else { $a.BeginRow + 1 }
|
||||||
|
}
|
||||||
|
if ($a.BeginCol -ge 0) {
|
||||||
|
$entry["cols"] = if ($a.EndCol -gt $a.BeginCol) { "$($a.BeginCol + 1)-$($a.EndCol + 1)" } else { $a.BeginCol + 1 }
|
||||||
|
}
|
||||||
|
$naOut += $entry
|
||||||
|
}
|
||||||
|
$result["namedAreas"] = [array]$naOut
|
||||||
|
}
|
||||||
|
|
||||||
# --- 16. Convert to JSON ---
|
# --- 16. Convert to JSON ---
|
||||||
|
|
||||||
# Custom JSON serializer — компактный, 2-пробельный indent, массивы примитивов inline.
|
# Custom JSON serializer — компактный, 2-пробельный indent, массивы примитивов inline.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# mxl-decompile v1.3 — Decompile 1C spreadsheet to JSON
|
# mxl-decompile v1.4 — Decompile 1C spreadsheet to JSON
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -337,6 +337,8 @@ def main():
|
|||||||
|
|
||||||
# --- 7. Extract named items ---
|
# --- 7. Extract named items ---
|
||||||
|
|
||||||
|
# Захватываем области ВСЕХ типов. Раньше здесь стоял `if area_type != "Rows": continue`,
|
||||||
|
# из-за чего терялись Rectangle и Columns — а они есть у 61% макетов корпуса.
|
||||||
named_areas = []
|
named_areas = []
|
||||||
for ni_node in findall(root, "d:namedItem"):
|
for ni_node in findall(root, "d:namedItem"):
|
||||||
xsi_type = ni_node.get(f"{{{XSI_NS}}}type", "")
|
xsi_type = ni_node.get(f"{{{XSI_NS}}}type", "")
|
||||||
@@ -344,15 +346,20 @@ def main():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
area_node = find(ni_node, "d:area")
|
area_node = find(ni_node, "d:area")
|
||||||
area_type_node = find(area_node, "d:type")
|
if area_node is None:
|
||||||
area_type = text_of(area_type_node) or ""
|
|
||||||
if area_type != "Rows":
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
def coord(tag, node=area_node):
|
||||||
|
n = find(node, "d:" + tag)
|
||||||
|
return int_of(n) if n is not None else -1
|
||||||
|
|
||||||
named_areas.append({
|
named_areas.append({
|
||||||
"Name": text_of(find(ni_node, "d:name")) or "",
|
"Name": text_of(find(ni_node, "d:name")) or "",
|
||||||
"BeginRow": int_of(find(area_node, "d:beginRow")),
|
"Type": text_of(find(area_node, "d:type")) or "",
|
||||||
"EndRow": int_of(find(area_node, "d:endRow")),
|
"BeginRow": coord("beginRow"),
|
||||||
|
"EndRow": coord("endRow"),
|
||||||
|
"BeginCol": coord("beginColumn"),
|
||||||
|
"EndCol": coord("endColumn"),
|
||||||
})
|
})
|
||||||
|
|
||||||
# --- 8. Extract rows ---
|
# --- 8. Extract rows ---
|
||||||
@@ -630,9 +637,44 @@ def main():
|
|||||||
|
|
||||||
# --- 12. Build areas ---
|
# --- 12. Build areas ---
|
||||||
|
|
||||||
|
# Сетка нарезается на блоки: непересекающиеся области типа Rows задают границы, строки вне
|
||||||
|
# них становятся БЕЗЫМЯННЫМИ блоками. Раньше строки вне областей просто терялись — в корпусе
|
||||||
|
# такие дыры у 34% макетов, а макетов вовсе без Rows-областей 21%.
|
||||||
|
# Всё, что блоком не выражается (области не-Rows и пересекающиеся Rows), уходит в namedAreas
|
||||||
|
# координатами. Правило детерминированное — иначе раундтрип поехал бы.
|
||||||
|
|
||||||
|
max_row_idx = max(row_data.keys()) if row_data else -1
|
||||||
|
|
||||||
|
block_areas = []
|
||||||
|
overlay_areas = []
|
||||||
|
claimed = set()
|
||||||
|
for a in sorted(named_areas, key=lambda x: (x["BeginRow"], x["EndRow"])):
|
||||||
|
fits = a["Type"] == "Rows" and a["BeginRow"] >= 0 and a["EndRow"] >= a["BeginRow"]
|
||||||
|
if fits:
|
||||||
|
for r in range(a["BeginRow"], a["EndRow"] + 1):
|
||||||
|
if r in claimed:
|
||||||
|
fits = False
|
||||||
|
break
|
||||||
|
if fits:
|
||||||
|
claimed.update(range(a["BeginRow"], a["EndRow"] + 1))
|
||||||
|
block_areas.append(a)
|
||||||
|
else:
|
||||||
|
overlay_areas.append(a)
|
||||||
|
|
||||||
|
# Блоки в порядке строк + безымянные заполнители дыр.
|
||||||
|
blocks = []
|
||||||
|
cursor = 0
|
||||||
|
for a in sorted(block_areas, key=lambda x: x["BeginRow"]):
|
||||||
|
if a["BeginRow"] > cursor:
|
||||||
|
blocks.append({"Name": None, "BeginRow": cursor, "EndRow": a["BeginRow"] - 1})
|
||||||
|
blocks.append({"Name": a["Name"], "BeginRow": a["BeginRow"], "EndRow": a["EndRow"]})
|
||||||
|
cursor = a["EndRow"] + 1
|
||||||
|
if cursor <= max_row_idx:
|
||||||
|
blocks.append({"Name": None, "BeginRow": cursor, "EndRow": max_row_idx})
|
||||||
|
|
||||||
dsl_areas = []
|
dsl_areas = []
|
||||||
|
|
||||||
for area in named_areas:
|
for area in blocks:
|
||||||
area_rows = []
|
area_rows = []
|
||||||
|
|
||||||
for global_row in range(area["BeginRow"], area["EndRow"] + 1):
|
for global_row in range(area["BeginRow"], area["EndRow"] + 1):
|
||||||
@@ -746,10 +788,12 @@ def main():
|
|||||||
else:
|
else:
|
||||||
compressed_rows.append(OrderedDict([("empty", empty_run)]))
|
compressed_rows.append(OrderedDict([("empty", empty_run)]))
|
||||||
|
|
||||||
dsl_areas.append(OrderedDict([
|
dsl_block = OrderedDict()
|
||||||
("name", area["Name"]),
|
# Безымянный блок — просто кусок сетки, ключ name у него не пишем.
|
||||||
("rows", compressed_rows),
|
if area["Name"]:
|
||||||
]))
|
dsl_block["name"] = area["Name"]
|
||||||
|
dsl_block["rows"] = compressed_rows
|
||||||
|
dsl_areas.append(dsl_block)
|
||||||
|
|
||||||
# --- 13. Compress columnWidths ---
|
# --- 13. Compress columnWidths ---
|
||||||
|
|
||||||
@@ -833,6 +877,21 @@ def main():
|
|||||||
result["styles"] = style_defs
|
result["styles"] = style_defs
|
||||||
result["areas"] = dsl_areas
|
result["areas"] = dsl_areas
|
||||||
|
|
||||||
|
# Именованные области, не выразимые блоком, — координатами. Тип не пишем: он выводится
|
||||||
|
# из указанных осей (как в ТабличныйДокумент.Область()). DSL 1-based, XML 0-based.
|
||||||
|
if overlay_areas:
|
||||||
|
na_out = []
|
||||||
|
for a in overlay_areas:
|
||||||
|
entry = OrderedDict([("name", a["Name"])])
|
||||||
|
if a["BeginRow"] >= 0:
|
||||||
|
entry["rows"] = (f'{a["BeginRow"] + 1}-{a["EndRow"] + 1}'
|
||||||
|
if a["EndRow"] > a["BeginRow"] else a["BeginRow"] + 1)
|
||||||
|
if a["BeginCol"] >= 0:
|
||||||
|
entry["cols"] = (f'{a["BeginCol"] + 1}-{a["EndCol"] + 1}'
|
||||||
|
if a["EndCol"] > a["BeginCol"] else a["BeginCol"] + 1)
|
||||||
|
na_out.append(entry)
|
||||||
|
result["namedAreas"] = na_out
|
||||||
|
|
||||||
# --- 16. Convert to JSON ---
|
# --- 16. Convert to JSON ---
|
||||||
|
|
||||||
json_str = convert_to_compact_json(result)
|
json_str = convert_to_compact_json(result)
|
||||||
|
|||||||
+40
-2
@@ -79,7 +79,8 @@
|
|||||||
| `columnWidths` | нет | `{}` | Ширины колонок. Ключи 1-based: `"1"`, `"3-14"`, `"5,7,9"`. Значения: число (абсолют) или `"Nx"` (множитель от defaultWidth, напр. `"2x"`, `"0.5x"`) |
|
| `columnWidths` | нет | `{}` | Ширины колонок. Ключи 1-based: `"1"`, `"3-14"`, `"5,7,9"`. Значения: число (абсолют) или `"Nx"` (множитель от defaultWidth, напр. `"2x"`, `"0.5x"`) |
|
||||||
| `fonts` | нет | — | Именованные шрифты (если не задано, создаётся Arial 10) |
|
| `fonts` | нет | — | Именованные шрифты (если не задано, создаётся Arial 10) |
|
||||||
| `styles` | нет | `{}` | Именованные стили |
|
| `styles` | нет | `{}` | Именованные стили |
|
||||||
| `areas` | да | — | Массив именованных областей (порядок = порядок в документе) |
|
| `areas` | да | — | Массив блоков строк (порядок = порядок в документе); имя у блока необязательно |
|
||||||
|
| `namedAreas` | нет | — | Именованные области, заданные координатами (см. ниже) |
|
||||||
|
|
||||||
## Шрифты (`fonts.<name>`)
|
## Шрифты (`fonts.<name>`)
|
||||||
|
|
||||||
@@ -110,9 +111,46 @@
|
|||||||
|
|
||||||
| Поле | Обяз. | Описание |
|
| Поле | Обяз. | Описание |
|
||||||
|------|:-----:|----------|
|
|------|:-----:|----------|
|
||||||
| `name` | да | Имя области для `Макет.ПолучитьОбласть("Имя")` |
|
| `name` | нет | Имя области для `Макет.ПолучитьОбласть("Имя")` |
|
||||||
| `rows` | да | Массив строк |
|
| `rows` | да | Массив строк |
|
||||||
|
|
||||||
|
Макет собирается из блоков строк, идущих подряд. Имя на блоке — сокращение: компилятор разворачивает его в именованную область типа «строки» на диапазон блока. **Блок без имени** — просто кусок сетки: так описываются строки, не принадлежащие ни одной именованной области.
|
||||||
|
|
||||||
|
## Именованные области координатами (`namedAreas[]`)
|
||||||
|
|
||||||
|
Для областей, которые блоком не выражаются: не привязанных к диапазону строк (полоса колонок, прямоугольник, ячейка) и пересекающихся с другими.
|
||||||
|
|
||||||
|
| Поле | Обяз. | Описание |
|
||||||
|
|------|:-----:|----------|
|
||||||
|
| `name` | да | Имя области |
|
||||||
|
| `rows` | \* | Строки: число или диапазон `"N-M"`, 1-based |
|
||||||
|
| `cols` | \* | Колонки: число или диапазон `"N-M"`, 1-based |
|
||||||
|
|
||||||
|
\* Обязательна хотя бы одна из осей.
|
||||||
|
|
||||||
|
**Тип области не указывается** — он следует из того, какие оси заданы, как в `ТабличныйДокумент.Область()`: только строки → полоса строк, только колонки → полоса колонок, обе оси → прямоугольник, одиночные значения по обеим осям → одна ячейка.
|
||||||
|
|
||||||
|
```json
|
||||||
|
"namedAreas": [
|
||||||
|
{ "name": "ОбластьПечатиПоВысоте", "rows": "1-48" },
|
||||||
|
{ "name": "ОбластьПечатиПоШирине", "cols": "1-35" },
|
||||||
|
{ "name": "HZY", "rows": 9, "cols": "16-17" }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Диапазон — та же грамматика, что у `columnWidths`, но **только** число или `"N-M"`: список через запятую запрещён, область непрерывна.
|
||||||
|
|
||||||
|
Ошибки (stderr, код возврата 1):
|
||||||
|
|
||||||
|
| Условие | Сообщение |
|
||||||
|
|---------|-----------|
|
||||||
|
| нет `name` | `namedAreas: 'name' is required: …` |
|
||||||
|
| не задана ни одна ось | `namedAreas: at least one of 'rows'/'cols' is required: …` |
|
||||||
|
| список через запятую | `namedAreas: 'cols' must be a single number or range, got list "…": …` |
|
||||||
|
| диапазон задом наперёд | `namedAreas: 'rows' range is reversed "…": …` |
|
||||||
|
|
||||||
|
Порядок именованных элементов в выходном XML — по имени: так их хранит платформа, компилятор сортирует сам.
|
||||||
|
|
||||||
## Строки (`rows[]`)
|
## Строки (`rows[]`)
|
||||||
|
|
||||||
| Поле | По умолч. | Описание |
|
| Поле | По умолч. | Описание |
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "Ошибка: список через запятую в координатах области",
|
||||||
|
"input": {
|
||||||
|
"columns": 5,
|
||||||
|
"areas": [{ "rows": [["А", "Б", "В", "Г", "Д"]] }],
|
||||||
|
"namedAreas": [{ "name": "Разрывная", "cols": "1,3,5" }]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"outputPath": "Template.xml"
|
||||||
|
},
|
||||||
|
"expectError": "namedAreas: 'cols' must be a single number or range, got list \"1,3,5\": namedAreas[1] \"Разрывная\""
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "Ошибка: у именованной области не задано ни одной оси",
|
||||||
|
"input": {
|
||||||
|
"columns": 3,
|
||||||
|
"areas": [{ "rows": [["А", "Б", "В"]] }],
|
||||||
|
"namedAreas": [{ "name": "Пустая" }]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"outputPath": "Template.xml"
|
||||||
|
},
|
||||||
|
"expectError": "namedAreas: at least one of 'rows'/'cols' is required: namedAreas[1] \"Пустая\""
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "Именованные области координатами: тип выводится из осей",
|
||||||
|
"input": {
|
||||||
|
"columns": 4,
|
||||||
|
"areas": [
|
||||||
|
{ "rows": [["А", "Б", "В", "Г"], ["{П1}", "{П2}", "{П3}", "{П4}"]] }
|
||||||
|
],
|
||||||
|
"namedAreas": [
|
||||||
|
{ "name": "ПолосаСтрок", "rows": "1-2" },
|
||||||
|
{ "name": "ПолосаКолонок", "cols": "2-4" },
|
||||||
|
{ "name": "Прямоугольник", "rows": 2, "cols": "2-3" },
|
||||||
|
{ "name": "Ячейка", "rows": 1, "cols": 1 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"outputPath": "Template.xml"
|
||||||
|
},
|
||||||
|
"validatePath": "Template.xml",
|
||||||
|
"expect": {
|
||||||
|
"files": ["Template.xml"],
|
||||||
|
"fileContains": {
|
||||||
|
"file": "Template.xml",
|
||||||
|
"text": ["<type>Rows</type>", "<type>Columns</type>", "<type>Rectangle</type>"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -76,16 +76,6 @@
|
|||||||
<c>0</c>
|
<c>0</c>
|
||||||
<w>2</w>
|
<w>2</w>
|
||||||
</merge>
|
</merge>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
|
||||||
<name>Заголовок</name>
|
|
||||||
<area>
|
|
||||||
<type>Rows</type>
|
|
||||||
<beginRow>0</beginRow>
|
|
||||||
<endRow>2</endRow>
|
|
||||||
<beginColumn>-1</beginColumn>
|
|
||||||
<endColumn>-1</endColumn>
|
|
||||||
</area>
|
|
||||||
</namedItem>
|
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Данные</name>
|
<name>Данные</name>
|
||||||
<area>
|
<area>
|
||||||
@@ -96,6 +86,16 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Заголовок</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>0</beginRow>
|
||||||
|
<endRow>2</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
<line width="1" gap="false">
|
<line width="1" gap="false">
|
||||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||||
</line>
|
</line>
|
||||||
|
|||||||
@@ -102,16 +102,6 @@
|
|||||||
<defaultFormatIndex>1</defaultFormatIndex>
|
<defaultFormatIndex>1</defaultFormatIndex>
|
||||||
<height>2</height>
|
<height>2</height>
|
||||||
<vgRows>2</vgRows>
|
<vgRows>2</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>
|
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Строка</name>
|
<name>Строка</name>
|
||||||
<area>
|
<area>
|
||||||
@@ -122,6 +112,16 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>ШапкаТаблицы</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>0</beginRow>
|
||||||
|
<endRow>0</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
<line width="1" gap="false">
|
<line width="1" gap="false">
|
||||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||||
</line>
|
</line>
|
||||||
|
|||||||
@@ -136,16 +136,6 @@
|
|||||||
<h>1</h>
|
<h>1</h>
|
||||||
<w>0</w>
|
<w>0</w>
|
||||||
</merge>
|
</merge>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
|
||||||
<name>Шапка</name>
|
|
||||||
<area>
|
|
||||||
<type>Rows</type>
|
|
||||||
<beginRow>0</beginRow>
|
|
||||||
<endRow>1</endRow>
|
|
||||||
<beginColumn>-1</beginColumn>
|
|
||||||
<endColumn>-1</endColumn>
|
|
||||||
</area>
|
|
||||||
</namedItem>
|
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Строка</name>
|
<name>Строка</name>
|
||||||
<area>
|
<area>
|
||||||
@@ -156,6 +146,16 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
|
<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">
|
<line width="1" gap="false">
|
||||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||||
</line>
|
</line>
|
||||||
|
|||||||
@@ -156,11 +156,11 @@
|
|||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>ШапкаТаблицы</name>
|
<name>Итого</name>
|
||||||
<area>
|
<area>
|
||||||
<type>Rows</type>
|
<type>Rows</type>
|
||||||
<beginRow>1</beginRow>
|
<beginRow>3</beginRow>
|
||||||
<endRow>1</endRow>
|
<endRow>3</endRow>
|
||||||
<beginColumn>-1</beginColumn>
|
<beginColumn>-1</beginColumn>
|
||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
@@ -176,11 +176,11 @@
|
|||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Итого</name>
|
<name>ШапкаТаблицы</name>
|
||||||
<area>
|
<area>
|
||||||
<type>Rows</type>
|
<type>Rows</type>
|
||||||
<beginRow>3</beginRow>
|
<beginRow>1</beginRow>
|
||||||
<endRow>3</endRow>
|
<endRow>1</endRow>
|
||||||
<beginColumn>-1</beginColumn>
|
<beginColumn>-1</beginColumn>
|
||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
<?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>
|
||||||
|
<i>0</i>
|
||||||
|
<c>
|
||||||
|
<f>2</f>
|
||||||
|
<tl>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>А</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</tl>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
<c>
|
||||||
|
<i>1</i>
|
||||||
|
<c>
|
||||||
|
<f>2</f>
|
||||||
|
<tl>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>Б</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</tl>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
<c>
|
||||||
|
<i>2</i>
|
||||||
|
<c>
|
||||||
|
<f>2</f>
|
||||||
|
<tl>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>В</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</tl>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
<c>
|
||||||
|
<i>3</i>
|
||||||
|
<c>
|
||||||
|
<f>2</f>
|
||||||
|
<tl>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>Г</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</tl>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
</row>
|
||||||
|
</rowsItem>
|
||||||
|
<rowsItem>
|
||||||
|
<index>1</index>
|
||||||
|
<row>
|
||||||
|
<c>
|
||||||
|
<i>0</i>
|
||||||
|
<c>
|
||||||
|
<f>3</f>
|
||||||
|
<parameter>П1</parameter>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
<c>
|
||||||
|
<i>1</i>
|
||||||
|
<c>
|
||||||
|
<f>3</f>
|
||||||
|
<parameter>П2</parameter>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
<c>
|
||||||
|
<i>2</i>
|
||||||
|
<c>
|
||||||
|
<f>3</f>
|
||||||
|
<parameter>П3</parameter>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
<c>
|
||||||
|
<i>3</i>
|
||||||
|
<c>
|
||||||
|
<f>3</f>
|
||||||
|
<parameter>П4</parameter>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
</row>
|
||||||
|
</rowsItem>
|
||||||
|
<templateMode>true</templateMode>
|
||||||
|
<defaultFormatIndex>1</defaultFormatIndex>
|
||||||
|
<height>2</height>
|
||||||
|
<vgRows>2</vgRows>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>ПолосаКолонок</name>
|
||||||
|
<area>
|
||||||
|
<type>Columns</type>
|
||||||
|
<beginRow>-1</beginRow>
|
||||||
|
<endRow>-1</endRow>
|
||||||
|
<beginColumn>1</beginColumn>
|
||||||
|
<endColumn>3</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>ПолосаСтрок</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>0</beginRow>
|
||||||
|
<endRow>1</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Прямоугольник</name>
|
||||||
|
<area>
|
||||||
|
<type>Rectangle</type>
|
||||||
|
<beginRow>1</beginRow>
|
||||||
|
<endRow>1</endRow>
|
||||||
|
<beginColumn>1</beginColumn>
|
||||||
|
<endColumn>2</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Ячейка</name>
|
||||||
|
<area>
|
||||||
|
<type>Rectangle</type>
|
||||||
|
<beginRow>0</beginRow>
|
||||||
|
<endRow>0</endRow>
|
||||||
|
<beginColumn>0</beginColumn>
|
||||||
|
<endColumn>0</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
|
<font faceName="Arial" height="10" bold="false" italic="false" underline="false" strikeout="false" kind="Absolute" scale="100"/>
|
||||||
|
<format>
|
||||||
|
<width>10</width>
|
||||||
|
</format>
|
||||||
|
<format>
|
||||||
|
<font>0</font>
|
||||||
|
<fillType>Text</fillType>
|
||||||
|
</format>
|
||||||
|
<format>
|
||||||
|
<font>0</font>
|
||||||
|
<fillType>Parameter</fillType>
|
||||||
|
</format>
|
||||||
|
</document>
|
||||||
@@ -151,16 +151,6 @@
|
|||||||
<defaultFormatIndex>1</defaultFormatIndex>
|
<defaultFormatIndex>1</defaultFormatIndex>
|
||||||
<height>2</height>
|
<height>2</height>
|
||||||
<vgRows>2</vgRows>
|
<vgRows>2</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>
|
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Строка</name>
|
<name>Строка</name>
|
||||||
<area>
|
<area>
|
||||||
@@ -171,6 +161,16 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>ШапкаТаблицы</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>0</beginRow>
|
||||||
|
<endRow>0</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
<line width="1" gap="false">
|
<line width="1" gap="false">
|
||||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||||
</line>
|
</line>
|
||||||
|
|||||||
@@ -110,16 +110,6 @@
|
|||||||
<c>1</c>
|
<c>1</c>
|
||||||
<w>1</w>
|
<w>1</w>
|
||||||
</merge>
|
</merge>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
|
||||||
<name>Шапка</name>
|
|
||||||
<area>
|
|
||||||
<type>Rows</type>
|
|
||||||
<beginRow>0</beginRow>
|
|
||||||
<endRow>1</endRow>
|
|
||||||
<beginColumn>-1</beginColumn>
|
|
||||||
<endColumn>-1</endColumn>
|
|
||||||
</area>
|
|
||||||
</namedItem>
|
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Тело</name>
|
<name>Тело</name>
|
||||||
<area>
|
<area>
|
||||||
@@ -130,6 +120,16 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
|
<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">
|
<line width="1" gap="false">
|
||||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||||
</line>
|
</line>
|
||||||
|
|||||||
@@ -501,26 +501,6 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
|
||||||
<name>ШапкаТаблицы</name>
|
|
||||||
<area>
|
|
||||||
<type>Rows</type>
|
|
||||||
<beginRow>4</beginRow>
|
|
||||||
<endRow>4</endRow>
|
|
||||||
<beginColumn>-1</beginColumn>
|
|
||||||
<endColumn>-1</endColumn>
|
|
||||||
</area>
|
|
||||||
</namedItem>
|
|
||||||
<namedItem xsi:type="NamedItemCells">
|
|
||||||
<name>Строка</name>
|
|
||||||
<area>
|
|
||||||
<type>Rows</type>
|
|
||||||
<beginRow>5</beginRow>
|
|
||||||
<endRow>5</endRow>
|
|
||||||
<beginColumn>-1</beginColumn>
|
|
||||||
<endColumn>-1</endColumn>
|
|
||||||
</area>
|
|
||||||
</namedItem>
|
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Итого</name>
|
<name>Итого</name>
|
||||||
<area>
|
<area>
|
||||||
@@ -541,6 +521,26 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Строка</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>5</beginRow>
|
||||||
|
<endRow>5</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>ШапкаТаблицы</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>4</beginRow>
|
||||||
|
<endRow>4</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
<line width="1" gap="false">
|
<line width="1" gap="false">
|
||||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||||
</line>
|
</line>
|
||||||
|
|||||||
@@ -234,6 +234,16 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Итого</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>4</beginRow>
|
||||||
|
<endRow>4</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Подпись</name>
|
<name>Подпись</name>
|
||||||
<area>
|
<area>
|
||||||
@@ -245,11 +255,11 @@
|
|||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>ШапкаТаблицы</name>
|
<name>Примечание</name>
|
||||||
<area>
|
<area>
|
||||||
<type>Rows</type>
|
<type>Rows</type>
|
||||||
<beginRow>2</beginRow>
|
<beginRow>5</beginRow>
|
||||||
<endRow>2</endRow>
|
<endRow>5</endRow>
|
||||||
<beginColumn>-1</beginColumn>
|
<beginColumn>-1</beginColumn>
|
||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
@@ -265,21 +275,11 @@
|
|||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Итого</name>
|
<name>ШапкаТаблицы</name>
|
||||||
<area>
|
<area>
|
||||||
<type>Rows</type>
|
<type>Rows</type>
|
||||||
<beginRow>4</beginRow>
|
<beginRow>2</beginRow>
|
||||||
<endRow>4</endRow>
|
<endRow>2</endRow>
|
||||||
<beginColumn>-1</beginColumn>
|
|
||||||
<endColumn>-1</endColumn>
|
|
||||||
</area>
|
|
||||||
</namedItem>
|
|
||||||
<namedItem xsi:type="NamedItemCells">
|
|
||||||
<name>Примечание</name>
|
|
||||||
<area>
|
|
||||||
<type>Rows</type>
|
|
||||||
<beginRow>5</beginRow>
|
|
||||||
<endRow>5</endRow>
|
|
||||||
<beginColumn>-1</beginColumn>
|
<beginColumn>-1</beginColumn>
|
||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
|
|||||||
@@ -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>3</size>
|
||||||
|
</columns>
|
||||||
|
<rowsItem>
|
||||||
|
<index>0</index>
|
||||||
|
<row>
|
||||||
|
<c>
|
||||||
|
<i>0</i>
|
||||||
|
<c>
|
||||||
|
<f>2</f>
|
||||||
|
<tl>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>А</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</tl>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
<c>
|
||||||
|
<i>1</i>
|
||||||
|
<c>
|
||||||
|
<f>2</f>
|
||||||
|
<tl>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>Б</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</tl>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
<c>
|
||||||
|
<i>2</i>
|
||||||
|
<c>
|
||||||
|
<f>2</f>
|
||||||
|
<tl>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>В</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</tl>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
</row>
|
||||||
|
</rowsItem>
|
||||||
|
<rowsItem>
|
||||||
|
<index>1</index>
|
||||||
|
<row>
|
||||||
|
<c>
|
||||||
|
<i>0</i>
|
||||||
|
<c>
|
||||||
|
<f>2</f>
|
||||||
|
<tl>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>строки вне областей</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</tl>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
</row>
|
||||||
|
</rowsItem>
|
||||||
|
<rowsItem>
|
||||||
|
<index>2</index>
|
||||||
|
<row>
|
||||||
|
<c>
|
||||||
|
<i>0</i>
|
||||||
|
<c>
|
||||||
|
<f>3</f>
|
||||||
|
<parameter>П1</parameter>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
<c>
|
||||||
|
<i>1</i>
|
||||||
|
<c>
|
||||||
|
<f>3</f>
|
||||||
|
<parameter>П2</parameter>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
<c>
|
||||||
|
<i>2</i>
|
||||||
|
<c>
|
||||||
|
<f>3</f>
|
||||||
|
<parameter>П3</parameter>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
</row>
|
||||||
|
</rowsItem>
|
||||||
|
<templateMode>true</templateMode>
|
||||||
|
<defaultFormatIndex>1</defaultFormatIndex>
|
||||||
|
<height>3</height>
|
||||||
|
<vgRows>3</vgRows>
|
||||||
|
<merge>
|
||||||
|
<r>1</r>
|
||||||
|
<c>0</c>
|
||||||
|
<w>2</w>
|
||||||
|
</merge>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Строка</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>2</beginRow>
|
||||||
|
<endRow>2</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Шапка</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>0</beginRow>
|
||||||
|
<endRow>0</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
|
<font faceName="Arial" height="10" bold="false" italic="false" underline="false" strikeout="false" kind="Absolute" scale="100"/>
|
||||||
|
<format>
|
||||||
|
<width>10</width>
|
||||||
|
</format>
|
||||||
|
<format>
|
||||||
|
<font>0</font>
|
||||||
|
<fillType>Text</fillType>
|
||||||
|
</format>
|
||||||
|
<format>
|
||||||
|
<font>0</font>
|
||||||
|
<fillType>Parameter</fillType>
|
||||||
|
</format>
|
||||||
|
</document>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "Блок без имени не порождает именованную область",
|
||||||
|
"input": {
|
||||||
|
"columns": 3,
|
||||||
|
"areas": [
|
||||||
|
{ "name": "Шапка", "rows": [["А", "Б", "В"]] },
|
||||||
|
{ "rows": [["строки вне областей", ">", ">"]] },
|
||||||
|
{ "name": "Строка", "rows": [["{П1}", "{П2}", "{П3}"]] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"outputPath": "Template.xml"
|
||||||
|
},
|
||||||
|
"validatePath": "Template.xml",
|
||||||
|
"expect": {
|
||||||
|
"files": ["Template.xml"],
|
||||||
|
"stdoutContains": "Areas: 2",
|
||||||
|
"fileContains": {
|
||||||
|
"file": "Template.xml",
|
||||||
|
"text": ["<name>Шапка</name>", "<name>Строка</name>", "строки вне областей"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -101,16 +101,6 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
|
||||||
<name>Строка</name>
|
|
||||||
<area>
|
|
||||||
<type>Rows</type>
|
|
||||||
<beginRow>1</beginRow>
|
|
||||||
<endRow>1</endRow>
|
|
||||||
<beginColumn>-1</beginColumn>
|
|
||||||
<endColumn>-1</endColumn>
|
|
||||||
</area>
|
|
||||||
</namedItem>
|
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Итого</name>
|
<name>Итого</name>
|
||||||
<area>
|
<area>
|
||||||
@@ -121,6 +111,16 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Строка</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>1</beginRow>
|
||||||
|
<endRow>1</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
<line width="1" gap="false">
|
<line width="1" gap="false">
|
||||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||||
</line>
|
</line>
|
||||||
|
|||||||
@@ -143,6 +143,16 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Итого</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>3</beginRow>
|
||||||
|
<endRow>3</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Поставщик</name>
|
<name>Поставщик</name>
|
||||||
<area>
|
<area>
|
||||||
@@ -163,16 +173,6 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
|
||||||
<name>Итого</name>
|
|
||||||
<area>
|
|
||||||
<type>Rows</type>
|
|
||||||
<beginRow>3</beginRow>
|
|
||||||
<endRow>3</endRow>
|
|
||||||
<beginColumn>-1</beginColumn>
|
|
||||||
<endColumn>-1</endColumn>
|
|
||||||
</area>
|
|
||||||
</namedItem>
|
|
||||||
<line width="1" gap="false">
|
<line width="1" gap="false">
|
||||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||||
</line>
|
</line>
|
||||||
|
|||||||
@@ -117,6 +117,16 @@
|
|||||||
<c>1</c>
|
<c>1</c>
|
||||||
<w>1</w>
|
<w>1</w>
|
||||||
</merge>
|
</merge>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Строка</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>2</beginRow>
|
||||||
|
<endRow>2</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Шапка</name>
|
<name>Шапка</name>
|
||||||
<area>
|
<area>
|
||||||
@@ -137,16 +147,6 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
|
||||||
<name>Строка</name>
|
|
||||||
<area>
|
|
||||||
<type>Rows</type>
|
|
||||||
<beginRow>2</beginRow>
|
|
||||||
<endRow>2</endRow>
|
|
||||||
<beginColumn>-1</beginColumn>
|
|
||||||
<endColumn>-1</endColumn>
|
|
||||||
</area>
|
|
||||||
</namedItem>
|
|
||||||
<font faceName="Arial" height="10" bold="false" italic="false" underline="false" strikeout="false" kind="Absolute" scale="100"/>
|
<font faceName="Arial" height="10" bold="false" italic="false" underline="false" strikeout="false" kind="Absolute" scale="100"/>
|
||||||
<format>
|
<format>
|
||||||
<width>10</width>
|
<width>10</width>
|
||||||
|
|||||||
@@ -163,16 +163,6 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
|
||||||
<name>ШапкаТаблицы</name>
|
|
||||||
<area>
|
|
||||||
<type>Rows</type>
|
|
||||||
<beginRow>1</beginRow>
|
|
||||||
<endRow>2</endRow>
|
|
||||||
<beginColumn>-1</beginColumn>
|
|
||||||
<endColumn>-1</endColumn>
|
|
||||||
</area>
|
|
||||||
</namedItem>
|
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Строка</name>
|
<name>Строка</name>
|
||||||
<area>
|
<area>
|
||||||
@@ -183,6 +173,16 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>ШапкаТаблицы</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>1</beginRow>
|
||||||
|
<endRow>2</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
<line width="1" gap="false">
|
<line width="1" gap="false">
|
||||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||||
</line>
|
</line>
|
||||||
|
|||||||
@@ -138,16 +138,6 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
<namedItem xsi:type="NamedItemCells">
|
|
||||||
<name>Строка</name>
|
|
||||||
<area>
|
|
||||||
<type>Rows</type>
|
|
||||||
<beginRow>1</beginRow>
|
|
||||||
<endRow>1</endRow>
|
|
||||||
<beginColumn>-1</beginColumn>
|
|
||||||
<endColumn>-1</endColumn>
|
|
||||||
</area>
|
|
||||||
</namedItem>
|
|
||||||
<namedItem xsi:type="NamedItemCells">
|
<namedItem xsi:type="NamedItemCells">
|
||||||
<name>Итого</name>
|
<name>Итого</name>
|
||||||
<area>
|
<area>
|
||||||
@@ -158,6 +148,16 @@
|
|||||||
<endColumn>-1</endColumn>
|
<endColumn>-1</endColumn>
|
||||||
</area>
|
</area>
|
||||||
</namedItem>
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Строка</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>1</beginRow>
|
||||||
|
<endRow>1</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
<line width="1" gap="false">
|
<line width="1" gap="false">
|
||||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||||
</line>
|
</line>
|
||||||
|
|||||||
Reference in New Issue
Block a user