Создание окон в 1С 8.3: формы, вызов из кода и события

· 9 мин

Содержание

Окно в 1С 8.3 — это форма. Чтобы его сделать, есть два пути: нарисовать форму у объекта в Конфигураторе (правый клик по объекту → ветка Формы → добавить) либо открыть её из кода командой ОткрытьФорму. Первый способ задаёт внешний вид и обработчики событий, второй — показывает окно пользователю в нужный момент и передаёт в него параметры.

Разберём создание форм и обработчиков по шагам: как собрать окно в редакторе, вызвать его программно, передать и вернуть данные, отличить блокирующее окно от неблокирующего и подключить динамический список. Всё — на управляемых формах платформы 8.3, интерфейс «Такси».

Из чего состоит управляемая форма

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

У каждой формы три набора данных, они видны вкладками в правом верхнем углу редактора:

  • 🧩 Реквизиты — данные формы (ссылки, числа, строки, таблицы значений). Один из них помечается основным и связывает форму с объектом — справочником, документом, отчётом.
  • 🔘 Команды — действия: кнопки, пункты меню. За каждой командой стоит процедура-обработчик.
  • 🖼 Элементы — то, что видно на экране: поля, таблицы, группы, декорации. Элемент показывает реквизит или команду.

Код формы делится директивами компиляции. Они стоят перед процедурой и говорят платформе, где её выполнять:

&НаКлиенте
Процедура ПриИзмененииСуммы(Элемент)
    // выполняется у пользователя, видит элементы формы
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьПоУмолчанию()
    // выполняется на сервере, видит базу данных
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьКурс(Валюта, Дата)
    // быстрый серверный вызов без передачи всей формы
КонецФункции

&НаСервереБезКонтекста работает заметно быстрее обычного &НаСервере: платформа не гоняет на сервер и обратно все данные формы. Используйте его для расчётов, которым нужна только база, а не само окно.

Создание формы в Конфигураторе: по шагам

  1. Откройте дерево конфигурации (Конфигурация → Открыть конфигурацию), найдите нужный объект — например, справочник Контрагенты.
  2. Разверните его ветку, щёлкните правой кнопкой по подветке Формы → Добавить.
  3. В мастере выберите тип: форма элемента, форма списка, форма выбора, форма группы или произвольная форма. Для окна «с нуля» берите произвольную.
  4. На шаге мастера можно сразу перетащить реквизиты объекта в состав формы — платформа создаст под них поля.
  5. Нажмите Готово. Откроется редактор формы с тремя панелями: слева дерево элементов, справа реквизиты и команды, внизу — модуль формы.

Чтобы добавить на окно кнопку: в панели Команды нажмите ➕, назовите команду (Рассчитать), затем перетащите её в дерево элементов — появится кнопка. Двойной клик по команде создаёт пустой обработчик в модуле.

Чтобы добавить поле ввода: создайте реквизит в панели Реквизиты, перетащите его в дерево элементов. Тип элемента (поле ввода, флажок, переключатель) платформа подберёт по типу реквизита, но его можно сменить в свойствах.

Тип формы, выбранный в мастере, определяет, что окно умеет из коробки:

  • Форма элемента — редактирование одной записи справочника или документа. Основной реквизит — сам объект.
  • Форма списка — таблица записей с динамическим списком, отбором и командами создания.
  • Форма выбора — тот же список, но заточенный под возврат выбранного значения вызвавшему окну.
  • Произвольная форма — пустой холст без привязки к объекту: мастера, настройки, служебные диалоги.

Для одного объекта можно держать несколько форм каждого типа и переключать их — например, упрощённую и полную карточку.

Если форма не назначена основной у объекта, при открытии элемента откроется автогенерируемая форма, а не ваша. Назначьте свою форму основной в свойствах объекта, вкладка Формы → поле Основные формы.

Любое изменение формы вступит в силу только после обновления конфигурации базы данных (F7 или Обновить конфигурацию базы данных). Пока не обновили — пользователь видит старое окно.

Как открыть окно из кода и передать в него параметры

Программно окно открывает метод ОткрытьФорму. Минимально ему нужно имя формы; остальное — по необходимости:

&НаКлиенте
Процедура ОткрытьПодбор(Команда)

    Параметры = Новый Структура;
    Параметры.Вставить("Организация", Организация);
    Параметры.Вставить("ТолькоАктуальные", Истина);

    Оповещение = Новый ОписаниеОповещения("ПослеВыбораТовара", ЭтотОбъект);

    ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора",
        Параметры, ЭтотОбъект, , , , Оповещение);

КонецПроцедуры

Разберём аргументы по порядку:

  • Имя формы — строка вида Справочник.Номенклатура.ФормаВыбора или ОбщаяФорма.Настройки.
  • Параметры — структура с данными, которые получит открываемое окно.
  • Владелец (ЭтотОбъект) — форма, которая открывает. Нужна, чтобы вернуть результат и чтобы платформа не плодила дубли окон.
  • Дальше идут уникальность, окно, навигационная ссылка.
  • Оповещение о закрытии — объект ОписаниеОповещения, он укажет, какую процедуру вызвать после закрытия окна.

Открытое окно читает параметры в обработчике ПриСозданииНаСервере — это самый первый обработчик, он срабатывает ещё до показа формы:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    Если Параметры.Свойство("Организация") Тогда
        Список.Отбор.Элементы... // применяем отбор
    КонецЕсли;

КонецПроцедуры

Свойство Параметры.Ключ доступно только в ПриСозданииНаСервере. Если значение нужно позже — сразу перепишите его в реквизит формы, иначе к ПриОткрытии оно уже недоступно.

Чтобы вернуть значение в вызвавшее окно, форма при закрытии передаёт результат в метод Закрыть:

&НаКлиенте
Процедура ВыбратьИЗакрыть(Команда)
    Закрыть(ТекущийТовар);
КонецПроцедуры

А владелец ловит этот результат в процедуре, указанной в ОписаниеОповещения:

&НаКлиенте
Процедура ПослеВыбораТовара(РезультатЗакрытия, ДопПараметры) Экспорт
    Если РезультатЗакрытия <> Неопределено Тогда
        Товар = РезультатЗакрытия;
    КонецЕсли;
КонецПроцедуры

Для форм выбора есть ещё механизм ОповеститьОВыборе(Значение) — он срабатывает на стандартном событии выбора и тоже возвращает значение владельцу. Разница в том, что ОповеститьОВыборе закрывает окно сам.

Блокирующие и неблокирующие окна вместо модальности

Раньше окно открывали модально — метод ОткрытьФормуМодально останавливал выполнение кода, пока пользователь не закроет окно. В платформе 8.3 от модальности отказались: она не работает в веб-клиенте и на мобильных. В свойствах конфигурации режим модальности ставят в Не использовать, а старые методы заменяют на асинхронные.

Теперь окно не «замораживает» код. Поэтому результат ловят не следующей строкой, а в отдельном обработчике-оповещении. Так работают и системные диалоги: вместо Вопрос(...) вызывают ПоказатьВопрос(...), вместо Предупреждение(...) — ПоказатьПредупреждение(...).

&НаКлиенте
Процедура Удалить(Команда)
    Оповещение = Новый ОписаниеОповещения("ПослеВопроса", ЭтотОбъект);
    ПоказатьВопрос(Оповещение, "Удалить строку?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры

&НаКлиенте
Процедура ПослеВопроса(Ответ, ДопПараметры) Экспорт
    Если Ответ = КодВозвратаДиалога.Да Тогда
        // удаляем
    КонецЕсли;
КонецПроцедуры

Блокировать окно всё же можно — но не весь интерфейс, а только окно-владелец. За это отвечает последний аргумент ОткрытьФорму — режим открытия:

Режим открытияЧто делаетКогда применять
НезависимыйОбычное окно, работает параллельноКарточки, списки, отчёты
БлокироватьОкноВладельцаВладелец заблокирован, остальное доступноДиалоги подбора, ввода параметров
БлокироватьВесьИнтерфейсЗаблокированы все окна приложенияКритичные подтверждения, мастера

Выбор режима — вопрос сценария. Ниже короткий ориентир:

Какое окно открыть?

События формы и реакция на действия пользователя

Обработчики — это процедуры, которые платформа вызывает сама в ответ на событие. Делятся на события формы (всей) и события элементов.

Ключевые события формы, по порядку их жизни:

  1. ПриСозданииНаСервере — форма готовится на сервере. Здесь читают параметры, заполняют значения по умолчанию, настраивают видимость.
  2. ПриОткрытии — окно вот-вот покажется пользователю (клиент). Годится для проверок, требующих взаимодействия.
  3. ПередЗаписью / ПриЗаписиНаСервере / ПослеЗаписи — цикл сохранения объекта.
  4. ПередЗакрытием — можно отменить закрытие (Отказ = Истина), например, если есть несохранённые данные.
  5. ПриЗакрытии — окно уже закрывается, отменить нельзя.

События элементов вешают на конкретные поля и таблицы. Самые частые:

  • ПриИзменении — пользователь изменил значение поля. Типичное место для пересчёта.
  • НачалоВыбора — нажали кнопку выбора в поле (можно подменить стандартный выбор своим окном).
  • ПриАктивизацииСтроки — курсор встал на другую строку таблицы.
  • Обработка у поля с автоподбором.

Назначают обработчик в свойствах элемента (значок 🔍 рядом со строкой события) либо в коде. Пример реакции на ввод:

&НаКлиенте
Процедура КоличествоПриИзменении(Элемент)
    Сумма = Количество * Цена;
КонецПроцедуры

Отдельно стоит связь между окнами без владельца. Когда одно окно должно сообщить другим, что данные изменились, используют пару Оповестить → ОбработкаОповещения:

// в окне, которое что-то изменило
Оповестить("ЗаказОплачен", Заказ);

// в другом открытом окне
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    Если ИмяСобытия = "ЗаказОплачен" Тогда
        ОбновитьСписок();
    КонецЕсли;
КонецПроцедуры

Оповестить рассылает сигнал всем открытым окнам сразу. Это удобнее, чем держать ссылки друг на друга: список сам обновится, когда карточка запишет изменение.

Динамический список и таблицы на форме

Чтобы окно показывало строки из базы, на форму кладут динамический список — специальный реквизит типа ДинамическийСписок. У формы списка он уже есть и помечен основным. На произвольную форму его добавляют вручную: создайте реквизит типа ДинамическийСписок, в его свойствах укажите Основная таблица (например, Справочник.Контрагенты), затем перетащите реквизит в элементы — появится таблица с колонками.

Динамический список умеет работать не только по одной таблице, но и по произвольному запросу:

  1. В свойствах реквизита включите Произвольный запрос.
  2. Откройте Настройка списка → Запрос и впишите текст запроса.
  3. Колонки, доступные для вывода, список возьмёт из полей запроса.

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

Если же нужна таблица не из базы, а «на лету» (расчётная, временная) — используйте реквизит типа ТаблицаЗначений. Колонки добавляют в конструкторе реквизита, заполняют кодом на сервере:

&НаСервере
Процедура ЗаполнитьТаблицу()
    РезультатЗапроса = Запрос.Выполнить().Выгрузить();
    ТаблицаНаФорме.Загрузить(РезультатЗапроса);
КонецПроцедуры

Таблица значений — серверный объект. Напрямую создать или заполнить её в клиентской процедуре нельзя: делайте это в &НаСервере, а на форму выводите готовую.

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

Эти сбои ловят почти все, кто начинает делать окна. Причины у них не в коде формы, а в непонимании клиент-серверной модели.

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