Почему на обычных формах 1С вечно разъезжаются привязки и как мы перестали править их руками: редактор, линтер, превью в браузере и скилл для ИИ
Разработка - Инструментарий разработчика
Файлы
ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.
Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний
Оформите подписку на компанию для решения рабочих задач
Оформить подписку и скачать решение со скидкойВы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
У нас в компании до сих пор живёт большой контур на обычных формах. И каждый раз, когда нужно добавить пару полей или кнопку, начинается одно и то же. Привязки ломаются, а исправлять их муторно. Особенно в сложных формах, которые дорабатывались годами разными людьми — десятки невидимых разделителей (направляющих) и перекрёстных привязок.
Когда я начал подключать к разработке ИИ-агентов, это стало отдельным квестом — управляемую форму читает и правит легко, обычная форма только вручную.
Пришлось выяснить, как Конфигуратор хранит обычные формы и их привязки, и написать свой инструмент. В итоге я перестал настраивать привязки руками — скрипты добавляют или двигают элементы, а все привязки и разделители считаются автоматически. А ещё бонусом он может в автоматическом режиме проверить, есть ли наложение элементов во всей конфигурации — так я нашёл много элементов, которые вообще никто никогда не видит: вставили, забыли, так оно и лежит слоями прямо как в археологии :)
Как устроены привязки изнутри (и почему они вечно ломаются)
Когда я разобрал сериализацию формы в frame.dll, стало понятно, почему в Конфигураторе так легко сломать вёрстку.
У каждого элемента на форме есть блок геометрии {8, Left, Top, Right, Bottom, НомерСтраницы, ...} и 6 границ: 0 — Верх, 1 — Низ, 2 — Лево, 3 — Право, 4 — Центр по горизонтали, 5 — Центр по вертикали.
Каждая привязка хранится в файле дважды — как двунаправленный граф:
- Исходящая пружина у самого элемента: запись вида
{2, TargetID, TargetEdge, OffsetPx}. Она говорит: «Моя граница должна отстоять от границыTargetEdgeобъектаTargetIDровно наOffsetPxпикселей».- Если
TargetIDравен0— граница привязана к краю самой формы (панели). - Если
TargetIDравен ID самого элемента (например, правый край привязан к своему же левому краю со смещениемWidth) — это жёсткая распорка, элемент держит фиксированную ширину. - Если
TargetID— это ID соседнего поля ввода, они сцеплены в цепочку.
- Если
- Входящая обратная ссылка у родителя или соседа: у самой панели (
InnerPanel) и у каждого контрола есть 6 встречных списков: «Ко мне за такую-то границу прицеплены вот эти элементы». - Разделители (Guides): отдельно в панели лежит массив пунктирных линий-направляющих с их координатами в пикселях и отступами от противоположного края.
Как только вы двигаете элемент на форме в Конфигураторе или меняете координаты в файле, смещения OffsetPx, координаты разделителей и встречные списки должны сойтись до пикселя. Если обратная ссылка потерялась или смещение разошлось с координатами (Left, Top, Right, Bottom) — элементы при открытии или растягивании окна начинают наезжать друг на друга или блокировать.
Протестировано на платформе 1С:Предприятие 8.3 (релиз 8.3.27.2074, совместимо со всеми релизами 8.2 и 8.3).
Что делает мой инструмент
Я собрал автономный набор скриптов на Python (без сторонних библиотек и без запуска 1cv8.exe) + описание скилла SKILL.md для подключения к ИИ-агентам:
- Безопасная распаковка, сборка и лечение
Ext/Form.bin(form_bin.py)- Распаковывает
Ext/Form.binв два файла (form.layoutиModule.bsl) и собирает обратно строго вPLAIN-режиме с проверкойUTF-8 BOM. - Если вам достался битый
Form.bin(кто-то сжал его через Deflate или сбил кодировку), командаverify --fixчинит его на месте.
- Распаковывает
- Парсер скобочного дерева (
ordinary_form_ast.py)- Разбирает
form.layoutв понятный JSON: все контролы (понимает более 20 классов: поля ввода, кнопки, надписи, табличные поля, панели со вкладками, рамки, командные панели), их координаты, страницы, события и колонки таблиц. - Гарантирует 100% обратимость: разбор и обратная сериализация не меняют ни одного байта.
- Разбирает
- Редактор форм с авторасчётом привязок (
ordinary_form_editor.py) Вам и ИИ-агенту больше не нужно трогать привязки руками:set-rect(подвинуть или изменить размер): меняет координаты элемента, сам пересчитывает смещения всех его исходящих пружин, находит все соседние контролы, привязанные к его границам, и синхронно обновляет их пружины и индивидуальные разделители (Guides). Соседние поля никуда не уезжают.add-control(добавить элемент): добавляетКнопка,Надпись,ПолеВвода,ПолеВыбора,Флажок,РамкаГруппы(на форму или на нужную страницу панели). Сам выделяет свободныйControlID, сдвигает счётчикNextControlIDв шапке формы, создаёт распорки ширины/высоты со встречными ссылками, выставляетTabOrderи прописывает обработчик события BSL.add-column/bind-column(добавить или привязать колонку вТабличноеПоле): решает известную проблему списков (СправочникСписок/ДокументСписок), когда добавленная колонка отображается пустой. Причина в том, что в колонке списка (CLSID 48a6ebc3-...) тип данных хранится сразу в двух местах: в открытомcore[35](Pattern) и внутри поляcore[39], где зашит#base64-блокCompressedMemoryStream(18-байтный заголовок + сжатыйDeflate wbits=-15поток встроенного редактора ячейки). Скрипт сам формирует и пакует этот#base64по переданным--data-uuidи--type-uuid.build-from-dsl(собрать форму с нуля по JSON): по короткому JSON-описанию генерирует готовую обычную форму со всеми направляющими, страницами и привязками.
- Статический линтер формы до запуска 1С (
form_linter.py) Проверяет форму без открытия Конфигуратора:- сверяет прямые и обратные ссылки привязок (
MISSING_REVERSE_SPRING_REF,SPRING_OFFSET_DESYNC); - симулирует растягивание окна формы на
+200x150пикселей по графу пружин и показывает, какие элементы схлопнутся (CONTROL_COLLAPSE_ON_RESIZE); - находит наложения элементов друг на друга на одной вкладке (
CONTROL_OVERLAP); - проверяет счётчик
NextControlID, дубли ID/имён и сверяет все привязанные события кнопок и полей с реальными процедурами вModule.bsl.
- сверяет прямые и обратные ссылки привязок (
- Визуальное превью 1:1 в браузере (
form_preview.py)- Генерирует один HTML-файл с отрисовкой обычной формы в классическом стиле 1С 8.2/8.3.
- В браузере можно включить отображение всех линий-разделителей (
Guides), порядок обхода (TabOrder), кликнуть мышкой в любой элемент и справа увидеть его ID, координаты, привязки, колонки, события и замечания линтера.
Пример работы из консоли
powershell
# 1. Распаковываем Ext/Form.bin
python scripts/form_bin.py unpack "Catalogs/Номенклатура/Forms/ФормаСписка/Ext/Form.bin" --out-dir "./staging"
# 2. Двигаем или меняем размер существующего элемента (привязки пересчитаются сами)
python scripts/ordinary_form_editor.py set-rect "./staging/form.layout" -o "./staging/form.layout" `
--control "ПолеВводаКомментарий" --left 100 --top 12 --width 260 --height 19
# 3. Добавляем кнопку с обработчиком
python scripts/ordinary_form_editor.py add-control "./staging/form.layout" -o "./staging/form.layout" `
--type Кнопка --name кнПроверить --caption "Проверить" `
--left 446 --top 8 --width 80 --height 19 --handler кнПроверитьНажатие
# 4. Добавляем колонку в СправочникСписок с привязкой к реквизиту
python scripts/ordinary_form_editor.py add-column "./staging/form.layout" -o "./staging/form.layout" `
--table "СправочникСписок" --name "КодТНВЭД" --caption "Код ТН ВЭД" --width 120 `
--data-uuid "<UUID-реквизита>" --type-uuid "<UUID-типа>"
# 5. Или собираем новую форму целиком из JSON
python scripts/ordinary_form_editor.py build-from-dsl "examples/sample_form_dsl.json" -o "./staging/form.layout"
# 6. Проверяем линтером, строим HTML-превью и пакуем обратно в Ext/Form.bin
python scripts/form_linter.py "./staging/form.layout" --module "./staging/Module.bsl"
python scripts/form_preview.py "./staging/form.layout" -o "./staging/form.preview.html"
python scripts/form_bin.py pack "./staging" "Catalogs/Номенклатура/Forms/ФормаСписка/Ext/Form.bin" --cleanup
Вступайте в нашу телеграмм-группу Инфостарт