diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1
index 422722bd..27773fe3 100644
--- a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1
+++ b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1
@@ -1,4 +1,4 @@
-# mxl-compile v1.19 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи)
+# mxl-compile v1.20 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -789,6 +789,14 @@ foreach ($area in $def.areas) {
$activeRowspans = @() # @{ColStart=1-based; ColEnd=1-based; EndLocalRow=int}
$localRow = 0
# Ссылка области на колоночную раскладку — её получают все строки области.
+ # Раскладка адресуется ИМЕНЕМ из columnSets — инлайновой формы в этом DSL нет ни у чего
+ # (стиль и шрифт тоже только по имени). Иначе сообщение включало бы сериализованный
+ # объект, а он у портов выглядит по-разному.
+ if ($area.PSObject.Properties['columnSet'] -and
+ ($area.columnSet -is [System.Management.Automation.PSCustomObject] -or $area.columnSet -is [System.Collections.IDictionary])) {
+ [Console]::Error.WriteLine("'columnSet' must be a name declared in columnSets, got an object: area `"$($area.name)`"")
+ exit 1
+ }
$areaColumnSet = if ($area.PSObject.Properties['columnSet']) { "$($area.columnSet)" } else { '' }
$areaLayout = $columnLayouts[0]
if ($areaColumnSet) {
diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.py b/.claude/skills/mxl-compile/scripts/mxl-compile.py
index 51905dff..e69477a2 100644
--- a/.claude/skills/mxl-compile/scripts/mxl-compile.py
+++ b/.claude/skills/mxl-compile/scripts/mxl-compile.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# mxl-compile v1.19 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи)
+# mxl-compile v1.20 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import json
@@ -814,6 +814,13 @@ def main():
active_rowspans = []
local_row = 0
# Ссылка области на колоночную раскладку — её получают все строки области.
+ # Раскладка адресуется ИМЕНЕМ из columnSets — инлайновой формы в этом DSL нет ни у чего
+ # (стиль и шрифт тоже только по имени). Иначе сообщение включало бы сериализованный
+ # объект, а он у портов выглядит по-разному.
+ if isinstance(area.get('columnSet'), (dict, list)):
+ print(f'\'columnSet\' must be a name declared in columnSets, got an object:'
+ f' area "{area.get("name", "")}"', file=sys.stderr)
+ sys.exit(1)
area_column_set = str(area.get('columnSet') or '')
area_layout = column_layouts[0]
if area_column_set:
diff --git a/tests/skills/cases/mxl-compile/column-sets.json b/tests/skills/cases/mxl-compile/column-sets.json
new file mode 100644
index 00000000..0bcd22f5
--- /dev/null
+++ b/tests/skills/cases/mxl-compile/column-sets.json
@@ -0,0 +1,25 @@
+{
+ "name": "Колоночные раскладки: своя ширина колонок у группы строк",
+ "input": {
+ "columns": 3,
+ "columnWidths": { "1-3": 20 },
+ "columnSets": {
+ "узкая": { "columns": 3, "columnWidths": { "1-3": 8 } }
+ },
+ "areas": [
+ { "name": "Шапка", "rows": [["Наименование", "Количество", "Сумма"]] },
+ { "name": "ТабличнаяЧасть", "columnSet": "узкая", "rows": [["{Товар}", "{Кол}", "{Сумма}"]] }
+ ]
+ },
+ "params": {
+ "outputPath": "Template.xml"
+ },
+ "validatePath": "Template.xml",
+ "expect": {
+ "files": ["Template.xml"],
+ "fileContains": {
+ "file": "Template.xml",
+ "text": ["узкая", "узкая"]
+ }
+ }
+}
diff --git a/tests/skills/cases/mxl-compile/error-columnset-inline.json b/tests/skills/cases/mxl-compile/error-columnset-inline.json
new file mode 100644
index 00000000..fdbdc3eb
--- /dev/null
+++ b/tests/skills/cases/mxl-compile/error-columnset-inline.json
@@ -0,0 +1,13 @@
+{
+ "name": "Ошибка: columnSet задан объектом вместо имени",
+ "input": {
+ "columns": 3,
+ "areas": [
+ { "name": "Шапка", "columnSet": { "columns": 5 }, "rows": [["А", "Б", "В"]] }
+ ]
+ },
+ "params": {
+ "outputPath": "Template.xml"
+ },
+ "expectError": "'columnSet' must be a name declared in columnSets, got an object: area \"Шапка\""
+}
diff --git a/tests/skills/cases/mxl-compile/snapshots/column-sets/Template.xml b/tests/skills/cases/mxl-compile/snapshots/column-sets/Template.xml
new file mode 100644
index 00000000..8cd9d95f
--- /dev/null
+++ b/tests/skills/cases/mxl-compile/snapshots/column-sets/Template.xml
@@ -0,0 +1,165 @@
+
+
+
+ ru
+ ru
+
+ ru
+ Русский
+ Русский
+
+
+
+ 3
+
+ 0
+
+ 2
+
+
+
+ 1
+
+ 2
+
+
+
+ 2
+
+ 2
+
+
+
+
+ узкая
+ 3
+
+ 0
+
+ 3
+
+
+
+ 1
+
+ 3
+
+
+
+ 2
+
+ 3
+
+
+
+
+ 0
+
+
+ 0
+
+ 4
+
+
+ ru
+ Наименование
+
+
+
+
+
+ 1
+
+ 4
+
+
+ ru
+ Количество
+
+
+
+
+
+ 2
+
+ 4
+
+
+ ru
+ Сумма
+
+
+
+
+
+
+
+ 1
+
+ узкая
+
+ 0
+
+ 5
+ Товар
+
+
+
+ 1
+
+ 5
+ Кол
+
+
+
+ 2
+
+ 5
+ Сумма
+
+
+
+
+ true
+ 1
+ 2
+ 2
+
+ ТабличнаяЧасть
+
+ Rows
+ 1
+ 1
+ -1
+ -1
+
+
+
+ Шапка
+
+ Rows
+ 0
+ 0
+ -1
+ -1
+
+
+
+
+ 10
+
+
+ 20
+
+
+ 8
+
+
+ 0
+ Text
+
+
+ 0
+ Parameter
+
+
\ No newline at end of file