Механизм работы форм в 1С: от реквизитов до событий и серверных вызовов

· 10 мин

Содержание

Форма в 1С — это не «картинка на экране», а пара из двух частей: данных формы (реквизиты, в которых лежат значения) и элементов (то, что видит пользователь). Элемент на экране не хранит значение сам — он показывает реквизит, с которым связан. Понять механизм формы — значит понять, как эти две части соединяются и где выполняется код: на компьютере пользователя или на сервере.

Ниже разберём устройство управляемой формы 1С 8.3 с интерфейсом «Такси»: из чего она собрана, как реквизиты привязаны к элементам и к данным объекта, в каком порядке срабатывают события и почему одна форма открывается мгновенно, а другая «думает» несколько секунд. Материал для разработчика и для администратора, который читает чужой код в конфигураторе.

Форма как связка данных и интерфейса

У любой управляемой формы есть внутренняя структура, которую видно в конфигураторе на вкладках редактора формы. Три ключевые вкладки:

  • 🗂 Реквизиты — данные формы. Здесь лежат значения: число, строка, ссылка, табличная часть, а также основной реквизит, связанный с объектом.
  • 🧩 Элементы — визуальная часть: поля ввода, таблицы, группы, кнопки, декорации. Элемент привязан к реквизиту через свойство ПутьКДанным.
  • ⚙️ Команды — действия, которые пользователь запускает кнопкой или пунктом меню.

Главное правило: элемент сам по себе ничего не хранит. Поле ввода «Сумма» показывает реквизит формы, и когда пользователь печатает в нём число, меняется именно реквизит. Если в коде нужно прочитать введённое значение, обращаются к реквизиту, а не к элементу.

Элементы и реквизиты называют одинаково по умолчанию, из-за этого их путают. В коде Элементы.Сумма — это объект интерфейса (цвет, доступность, видимость), а просто Сумма в контексте формы — это значение реквизита.

Управляемые и обычные формы: в чём разница

В 1С 8.3 существует два вида форм, и они работают принципиально по-разному.

ПризнакУправляемая формаОбычная форма
Где работаеттонкий клиент, веб-клиент, толстый клиенттолько толстый клиент
Вёрсткаавтоматическая, по группам и потокуручная, по пикселям
Кодделится на клиент и сервервесь код на клиенте
Разработка новыхда, это основной вариантнет, только поддержка старых баз

Управляемые формы появились в платформе 8.2 и стали основным механизмом интерфейса. В типовых конфигурациях (БП 3.0, ЗУП 3.1, УТ 11) все формы управляемые. Обычные формы остались для совместимости со старыми решениями и в режиме обычного приложения не делятся на клиент и сервер — поэтому старый код из обычной формы нельзя просто перенести в управляемую.

Если вы открываете конфигурацию и видите в свойствах формы разделение процедур на &НаКлиенте и &НаСервере — перед вами управляемая форма. Если такого разделения нет — обычная.

Реквизиты, элементы и команды: как собрана форма

Разберём три составные части подробнее — именно их настраивает разработчик.

Реквизиты формы — это переменные уровня формы. У каждой формы есть один основной реквизит (у формы документа это сам документ, у формы справочника — элемент). Основной реквизит связывает форму с данными объекта информационной базы. Остальные реквизиты — вспомогательные: флажки, отборы, временные значения, которые живут только пока форма открыта.

Элементы формы строятся деревом. Группы (ОбычнаяГруппа, страницы, командная панель) задают расположение, а вложенные поля показывают реквизиты. Платформа сама расставляет элементы по потоку — разработчик управляет группировкой, а не координатами. Каждое поле ссылается на реквизит через ПутьКДанным; разорвите эту связь — поле перестанет показывать и принимать данные.

Команды — это действия. Команда ссылается на процедуру-обработчик, а на форму выводится кнопкой или пунктом меню. Команды бывают стандартные (платформа добавляет «Записать», «Провести») и собственные, которые пишет разработчик.

Проверьте себя
Пользователь ввёл сумму в поле формы. Откуда код прочитает это значение?
Какой реквизит связывает форму документа с самим документом?
Где можно открыть обычную (неуправляемую) форму?

Как форма работает с данными объекта

Здесь кроется механизм, который чаще всего понимают неправильно. Данные формы — это копия данных объекта, а не сам объект.

Когда открывается форма документа, платформа читает документ из базы и раскладывает его реквизиты в реквизиты формы. Пользователь правит копию в форме. Только при записи платформа собирает данные формы обратно в объект и пишет его в базу.

Поэтому в коде формы прямого объекта нет — есть данные формы. Чтобы получить настоящий объект (например, вызвать его метод), применяют преобразование:

&НаСервере
Процедура ПересчитатьНаСервере()
    Документ = РеквизитФормыВЗначение("Объект"); // данные формы -> объект
    Документ.Пересчитать();                       // метод объекта
    ЗначениеВРеквизитФормы(Документ, "Объект");   // объект -> данные формы
КонецПроцедуры
  • РеквизитФормыВЗначение собирает объект из данных формы.
  • ЗначениеВРеквизитФормы раскладывает изменённый объект обратно.

Эти преобразования недёшевы: платформа копирует все данные, включая табличные части. В цикле их не вызывают — иначе форма «повиснет». Для простого чтения отдельного значения достаточно обратиться к реквизиту напрямую, преобразование не нужно.

Табличные части формы работают так же: в форме лежит таблица значений, связанная с табличной частью объекта. Строки добавляют и правят в данных формы, а в базу они попадают только при записи документа.

У такой копии есть практическое следствие. Пока пользователь не нажал «Записать», все его правки существуют только в открытой форме. Если сеанс оборвётся или форма закроется без записи — изменения пропадут, в базе останется прежняя версия. Поэтому проведение, расчёт итогов и любые действия, которые должны сохраниться, выполняют либо при записи, либо явной командой, которая пишет объект в базу.

Ещё одно следствие — две открытые формы одного документа работают с разными копиями. Один пользователь записал изменения, второй у себя их не видит, пока не перечитает. Платформа предупредит о конфликте при попытке записать устаревшую версию — это не ошибка формы, а защита от потери чужих правок.

Клиент и сервер: где выполняется код формы

Управляемая форма исполняется в двух местах сразу. Часть кода работает на компьютере пользователя (клиент), часть — на сервере. Разделение задаётся директивами компиляции над процедурой.

  • &НаКлиенте — выполняется у пользователя. Отсюда управляют интерфейсом, показывают вопросы, открывают другие формы. Прямого доступа к базе данных здесь нет.
  • &НаСервере — выполняется на сервере, имеет доступ к базе и к данным формы. При вызове платформа передаёт данные формы на сервер и возвращает обратно.
  • &НаСервереБезКонтекста — тоже на сервере, но данные формы не передаются. Такой вызов легче: меньше трафика между клиентом и сервером.
  • &НаКлиентеНаСервереБезКонтекста — общая процедура, доступная и там, и там, без контекста формы.

Каждый переход с клиента на сервер — это сетевой вызов. Чем их меньше, тем быстрее форма. Запрос к базе, чтение справочника, проведение документа — всё это может идти только на сервере. Реакция на действие пользователя (нажал кнопку, изменил поле) начинается на клиенте, а за данными уходит на сервер.

Стоимость вызова зависит не только от его количества, но и от объёма передаваемых данных. Вызов &НаСервере тянет с клиента на сервер и обратно всю копию формы вместе с табличными частями. Если в форме крупная таблица, такой round-trip ощутимо дороже, чем вызов &НаСервереБезКонтекста, который передаёт только параметры процедуры. Поэтому при одинаковой задаче без контекста работает быстрее.

Логика распределения простая. На клиенте остаётся то, что управляет интерфейсом и реагирует на пользователя: показать вопрос, открыть другую форму, сменить видимость поля. На сервер уходит всё, что касается базы и бизнес-логики. А промежуточный слой — общие модули — позволяет вынести повторяющийся серверный код из формы, чтобы он не дублировался в десятках обработок.

Правило простое: что можно сделать без базы — делайте на клиенте; что требует базу — на сервере, и собирайте такие операции в один вызов, а не в несколько.

События формы: что срабатывает и в каком порядке

Форма живёт по событиям. Платформа вызывает обработчики в предсказуемом порядке — зная его, вы понимаете, куда поставить свой код.

Основные события при открытии формы документа идут так:

  1. ПриЧтенииНаСервере — объект прочитан из базы (для существующего документа).
  2. ПриСозданииНаСервере — форма создаётся на сервере; здесь настраивают видимость, отборы, начальные значения. Выполняется один раз.
  3. ПриОткрытии — форма открывается на клиенте; здесь клиентская донастройка.

При записи порядок другой:

  1. ПередЗаписью (клиент) — можно отменить запись, спросить подтверждение.
  2. ПередЗаписьюНаСервере — последняя проверка перед записью.
  3. ПриЗаписиНаСервере — объект уже пишется в транзакции.
  4. ПослеЗаписи (клиент) — обновить интерфейс после успешной записи.

При закрытии срабатывают ПередЗакрытием (можно удержать форму открытой) и ПриЗакрытии.

Отдельно работают события элементов: ПриИзменении поля, ПриАктивизацииСтроки таблицы, Выбор, Открытие. Они клиентские — пользователь что-то сделал, код реагирует. Если реакции нужны данные из базы, обработчик вызывает серверную процедуру.

Распространённая ошибка — тяжёлые вычисления в ПриСозданииНаСервере. Это событие выполняется до показа формы, и всё, что в нём медленное, задерживает открытие. Вынесите то, что не нужно сразу, в отдельную команду или в фоновое задание.

Как ускорить медленную форму

Если форма открывается долго или «подтормаживает» при вводе, причина почти всегда в лишних серверных вызовах или в тяжёлой загрузке данных. Что проверить:

  • 🔁 Вызовы сервера в цикле. Серверную процедуру вызвали внутри обхода строк таблицы — каждый проход уходит на сервер и обратно. Соберите данные за один вызов и верните массивом.
  • 📦 Лишний контекст. Если серверной процедуре не нужны данные формы, поставьте &НаСервереБезКонтекста. Платформа не будет гонять копию формы туда-сюда.
  • 🧮 Вычисления в событии открытия. Всё, что можно посчитать позже или по запросу пользователя, убирают из ПриСозданииНаСервере.
  • 🎨 Оформление кодом вместо условного оформления. Подсветку строк, доступность полей по условию лучше задавать условным оформлением формы, а не пробегать по строкам кодом при каждом изменении.
  • 🗃 Чтение больших таблиц целиком. Не загружайте в форму тысячи строк, если пользователь видит десяток. Применяйте динамический список с отбором — он читает данные порциями.

Динамический список — отдельный механизм: это не копия данных в форме, а «окно» в базу, которое платформа подгружает по мере прокрутки. Для списков документов и справочников он на порядок экономнее, чем загрузка таблицы значений вручную.

Проверка перед правкой формы
Выполнено: 0 / 5

Частые ошибки при работе с формами

Эти ошибки встречаются в чужом коде чаще всего — проверьте их, прежде чем искать что-то сложное.

  • Обращение к базе на клиенте. Запрос, чтение справочника или проведение в &НаКлиенте вызовут ошибку компиляции. Такой код переносят на сервер.
  • Правка объекта, а не данных формы. Вызвали метод объекта, но забыли вернуть результат через ЗначениеВРеквизитФормы — изменения не попадут ни на экран, ни в базу.
  • Путаница элемента и реквизита. Присвоили значение Элементы.Поле, ожидая изменить данные. Нужно менять реквизит, на который поле ссылается; через элемент управляют только видом (цвет, доступность, видимость).
  • Тяжёлый ПриСозданииНаСервере. Форма открывается с задержкой, потому что в событии создания идёт долгий запрос или перебор.

Ни одно из этого не чинится «перезапуском 1С» — это ошибки логики кода, и правят их в конфигураторе.

Частые вопросы

Чем реквизит формы отличается от реквизита объекта?
Реквизит объекта хранится в базе и принадлежит документу или справочнику. Реквизит формы живёт только пока форма открыта и в базу сам по себе не пишется. Основной реквизит формы связывает одно с другим: при записи его данные уходят в объект.
Почему нельзя обратиться к базе данных прямо на клиенте?
Клиент — это компьютер пользователя, у него нет прямого соединения с базой из соображений безопасности и архитектуры. Любое чтение и запись идут через сервер. Поэтому код, работающий с базой, помечают &НаСервере.
Когда ставить `&НаСервереБезКонтекста` вместо `&НаСервере`?
Когда процедуре на сервере не нужны данные формы — например, она просто читает справочник по переданному параметру и возвращает значение. Без контекста платформа не передаёт копию формы, вызов получается легче и быстрее.
Можно ли перенести код из обычной формы в управляемую без переделки?
Нет. В обычной форме весь код клиентский и имеет прямой доступ к данным, а в управляемой он делится на клиент и сервер. При переносе процедуры размечают директивами и перестраивают логику обращения к данным.
Как получить настоящий объект документа в коде формы?
Через РеквизитФормыВЗначение("Объект") на сервере — платформа соберёт объект из данных формы. После изменения вернуть обратно через ЗначениеВРеквизитФормы. Для чтения одного значения преобразование не требуется — достаточно обратиться к реквизиту формы.