Создание окон в 1С 8.3: формы, вызов из кода и события
Содержание
Окно в 1С 8.3 — это форма. Чтобы его сделать, есть два пути: нарисовать форму у объекта в Конфигураторе (правый клик по объекту → ветка Формы → добавить) либо открыть её из кода командой ОткрытьФорму. Первый способ задаёт внешний вид и обработчики событий, второй — показывает окно пользователю в нужный момент и передаёт в него параметры.
Разберём создание форм и обработчиков по шагам: как собрать окно в редакторе, вызвать его программно, передать и вернуть данные, отличить блокирующее окно от неблокирующего и подключить динамический список. Всё — на управляемых формах платформы 8.3, интерфейс «Такси».
Из чего состоит управляемая форма
Управляемая форма живёт сразу на двух сторонах: часть кода выполняется на клиенте (у пользователя), часть — на сервере. Разработчик не рисует окно пикселями — он описывает его состав, а платформа сама раскладывает элементы под размер экрана и устройство. Поэтому одна форма одинаково открывается в тонком клиенте и в браузере.
У каждой формы три набора данных, они видны вкладками в правом верхнем углу редактора:
- 🧩 Реквизиты — данные формы (ссылки, числа, строки, таблицы значений). Один из них помечается основным и связывает форму с объектом — справочником, документом, отчётом.
- 🔘 Команды — действия: кнопки, пункты меню. За каждой командой стоит процедура-обработчик.
- 🖼 Элементы — то, что видно на экране: поля, таблицы, группы, декорации. Элемент показывает реквизит или команду.
Код формы делится директивами компиляции. Они стоят перед процедурой и говорят платформе, где её выполнять:
&НаКлиенте
Процедура ПриИзмененииСуммы(Элемент)
// выполняется у пользователя, видит элементы формы
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьПоУмолчанию()
// выполняется на сервере, видит базу данных
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьКурс(Валюта, Дата)
// быстрый серверный вызов без передачи всей формы
КонецФункции
&НаСервереБезКонтекста работает заметно быстрее обычного &НаСервере: платформа не гоняет на сервер и обратно все данные формы. Используйте его для расчётов, которым нужна только база, а не само окно.
Создание формы в Конфигураторе: по шагам
- Откройте дерево конфигурации (
Конфигурация → Открыть конфигурацию), найдите нужный объект — например, справочникКонтрагенты. - Разверните его ветку, щёлкните правой кнопкой по подветке Формы → Добавить.
- В мастере выберите тип: форма элемента, форма списка, форма выбора, форма группы или произвольная форма. Для окна «с нуля» берите произвольную.
- На шаге мастера можно сразу перетащить реквизиты объекта в состав формы — платформа создаст под них поля.
- Нажмите Готово. Откроется редактор формы с тремя панелями: слева дерево элементов, справа реквизиты и команды, внизу — модуль формы.
Чтобы добавить на окно кнопку: в панели Команды нажмите ➕, назовите команду (Рассчитать), затем перетащите её в дерево элементов — появится кнопка. Двойной клик по команде создаёт пустой обработчик в модуле.
Чтобы добавить поле ввода: создайте реквизит в панели Реквизиты, перетащите его в дерево элементов. Тип элемента (поле ввода, флажок, переключатель) платформа подберёт по типу реквизита, но его можно сменить в свойствах.
Тип формы, выбранный в мастере, определяет, что окно умеет из коробки:
- Форма элемента — редактирование одной записи справочника или документа. Основной реквизит — сам объект.
- Форма списка — таблица записей с динамическим списком, отбором и командами создания.
- Форма выбора — тот же список, но заточенный под возврат выбранного значения вызвавшему окну.
- Произвольная форма — пустой холст без привязки к объекту: мастера, настройки, служебные диалоги.
Для одного объекта можно держать несколько форм каждого типа и переключать их — например, упрощённую и полную карточку.
Если форма не назначена основной у объекта, при открытии элемента откроется автогенерируемая форма, а не ваша. Назначьте свою форму основной в свойствах объекта, вкладка Формы → поле Основные формы.
Любое изменение формы вступит в силу только после обновления конфигурации базы данных (F7 или Обновить конфигурацию базы данных). Пока не обновили — пользователь видит старое окно.
Как открыть окно из кода и передать в него параметры
Программно окно открывает метод ОткрытьФорму. Минимально ему нужно имя формы; остальное — по необходимости:
&НаКлиенте
Процедура ОткрытьПодбор(Команда)
Параметры = Новый Структура;
Параметры.Вставить("Организация", Организация);
Параметры.Вставить("ТолькоАктуальные", Истина);
Оповещение = Новый ОписаниеОповещения("ПослеВыбораТовара", ЭтотОбъект);
ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора",
Параметры, ЭтотОбъект, , , , Оповещение);
КонецПроцедуры
Разберём аргументы по порядку:
- Имя формы — строка вида
Справочник.Номенклатура.ФормаВыбораилиОбщаяФорма.Настройки. - Параметры — структура с данными, которые получит открываемое окно.
- Владелец (
ЭтотОбъект) — форма, которая открывает. Нужна, чтобы вернуть результат и чтобы платформа не плодила дубли окон. - Дальше идут уникальность, окно, навигационная ссылка.
- Оповещение о закрытии — объект
ОписаниеОповещения, он укажет, какую процедуру вызвать после закрытия окна.
Открытое окно читает параметры в обработчике ПриСозданииНаСервере — это самый первый обработчик, он срабатывает ещё до показа формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("Организация") Тогда
Список.Отбор.Элементы... // применяем отбор
КонецЕсли;
КонецПроцедуры
Свойство Параметры.Ключ доступно только в ПриСозданииНаСервере. Если значение нужно позже — сразу перепишите его в реквизит формы, иначе к ПриОткрытии оно уже недоступно.
Чтобы вернуть значение в вызвавшее окно, форма при закрытии передаёт результат в метод Закрыть:
&НаКлиенте
Процедура ВыбратьИЗакрыть(Команда)
Закрыть(ТекущийТовар);
КонецПроцедуры
А владелец ловит этот результат в процедуре, указанной в ОписаниеОповещения:
&НаКлиенте
Процедура ПослеВыбораТовара(РезультатЗакрытия, ДопПараметры) Экспорт
Если РезультатЗакрытия <> Неопределено Тогда
Товар = РезультатЗакрытия;
КонецЕсли;
КонецПроцедуры
Для форм выбора есть ещё механизм ОповеститьОВыборе(Значение) — он срабатывает на стандартном событии выбора и тоже возвращает значение владельцу. Разница в том, что ОповеститьОВыборе закрывает окно сам.
Блокирующие и неблокирующие окна вместо модальности
Раньше окно открывали модально — метод ОткрытьФормуМодально останавливал выполнение кода, пока пользователь не закроет окно. В платформе 8.3 от модальности отказались: она не работает
в веб-клиенте и на мобильных. В свойствах конфигурации режим модальности ставят в Не использовать, а старые методы заменяют на асинхронные.
Теперь окно не «замораживает» код. Поэтому результат ловят не следующей строкой, а в отдельном обработчике-оповещении. Так работают и системные диалоги: вместо Вопрос(...) вызывают ПоказатьВопрос(...), вместо Предупреждение(...) — ПоказатьПредупреждение(...).
&НаКлиенте
Процедура Удалить(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВопроса", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Удалить строку?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВопроса(Ответ, ДопПараметры) Экспорт
Если Ответ = КодВозвратаДиалога.Да Тогда
// удаляем
КонецЕсли;
КонецПроцедуры
Блокировать окно всё же можно — но не весь интерфейс, а только окно-владелец. За это отвечает последний аргумент ОткрытьФорму — режим открытия:
| Режим открытия | Что делает | Когда применять |
|---|---|---|
Независимый | Обычное окно, работает параллельно | Карточки, списки, отчёты |
БлокироватьОкноВладельца | Владелец заблокирован, остальное доступно | Диалоги подбора, ввода параметров |
БлокироватьВесьИнтерфейс | Заблокированы все окна приложения | Критичные подтверждения, мастера |
Выбор режима — вопрос сценария. Ниже короткий ориентир:
БлокироватьОкноВладельца и ловите результат в оповещении о закрытии.Независимый — окно открывается рядом, исходное остаётся активным.БлокироватьВесьИнтерфейс. Применяйте редко — он останавливает всю работу в приложении.ПоказатьВопрос или ПоказатьПредупреждение с оповещением.События формы и реакция на действия пользователя
Обработчики — это процедуры, которые платформа вызывает сама в ответ на событие. Делятся на события формы (всей) и события элементов.
Ключевые события формы, по порядку их жизни:
ПриСозданииНаСервере— форма готовится на сервере. Здесь читают параметры, заполняют значения по умолчанию, настраивают видимость.ПриОткрытии— окно вот-вот покажется пользователю (клиент). Годится для проверок, требующих взаимодействия.ПередЗаписью/ПриЗаписиНаСервере/ПослеЗаписи— цикл сохранения объекта.ПередЗакрытием— можно отменить закрытие (Отказ = Истина), например, если есть несохранённые данные.ПриЗакрытии— окно уже закрывается, отменить нельзя.
События элементов вешают на конкретные поля и таблицы. Самые частые:
ПриИзменении— пользователь изменил значение поля. Типичное место для пересчёта.НачалоВыбора— нажали кнопку выбора в поле (можно подменить стандартный выбор своим окном).ПриАктивизацииСтроки— курсор встал на другую строку таблицы.Обработкау поля с автоподбором.
Назначают обработчик в свойствах элемента (значок 🔍 рядом со строкой события) либо в коде. Пример реакции на ввод:
&НаКлиенте
Процедура КоличествоПриИзменении(Элемент)
Сумма = Количество * Цена;
КонецПроцедуры
Отдельно стоит связь между окнами без владельца. Когда одно окно должно сообщить другим, что данные изменились, используют пару Оповестить → ОбработкаОповещения:
// в окне, которое что-то изменило
Оповестить("ЗаказОплачен", Заказ);
// в другом открытом окне
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ЗаказОплачен" Тогда
ОбновитьСписок();
КонецЕсли;
КонецПроцедуры
Оповестить рассылает сигнал всем открытым окнам сразу. Это удобнее, чем держать ссылки друг на друга: список сам обновится, когда карточка запишет изменение.
Динамический список и таблицы на форме
Чтобы окно показывало строки из базы, на форму кладут динамический список — специальный реквизит типа ДинамическийСписок. У формы списка он уже есть и помечен основным. На произвольную форму его добавляют вручную: создайте реквизит типа ДинамическийСписок, в его свойствах укажите Основная таблица (например, Справочник.Контрагенты), затем перетащите реквизит в элементы — появится таблица с колонками.
Динамический список умеет работать не только по одной таблице, но и по произвольному запросу:
- В свойствах реквизита включите Произвольный запрос.
- Откройте Настройка списка → Запрос и впишите текст запроса.
- Колонки, доступные для вывода, список возьмёт из полей запроса.
Отбор, сортировку и группировку задают через свойство Отбор (программно) или в пользовательских настройках списка. Важно: динамический список подгружает данные порциями по мере прокрутки, поэтому он тянет даже миллионы строк без тормозов.
Если же нужна таблица не из базы, а «на лету» (расчётная, временная) — используйте реквизит типа ТаблицаЗначений. Колонки добавляют в конструкторе реквизита, заполняют кодом на сервере:
&НаСервере
Процедура ЗаполнитьТаблицу()
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
ТаблицаНаФорме.Загрузить(РезультатЗапроса);
КонецПроцедуры
Таблица значений — серверный объект. Напрямую создать или заполнить её в клиентской процедуре нельзя: делайте это в &НаСервере, а на форму выводите готовую.
Частые ошибки при работе с формами
Эти сбои ловят почти все, кто начинает делать окна. Причины у них не в коде формы, а в непонимании клиент-серверной модели.
- ❌ Вызов серверного метода из клиентской процедуры напрямую. Клиент не видит базу. Оберните обращение в
&НаСервере-процедуру и вызовите её. - ❌ Обращение к элементам формы на сервере. Наоборот:
&НаСерверене видитЭлементы.Поле. Меняйте видимость и доступность либо на клиенте, либо через связанные реквизиты. - ❌ Старые модальные методы в веб-клиенте.
Вопрос,Предупреждение,ОткрытьФормуМодальнов браузере вызовут ошибку при отключённой модальности. Заменяйте наПоказать...с оповещением. - ❌ Потеря
Параметрыпосле создания. Читайте их только вПриСозданииНаСервереи сразу сохраняйте в реквизиты. - ❌ Форма не стала основной. Нарисовали окно, а открывается автоформа — назначьте свою форму основной в свойствах объекта.
Чем форма отличается от окна в 1С 8.3?
Как открыть форму в отдельном окне, а не во вкладке?
ОткрытьФорму. Полностью навязать отдельное окно из кода штатно нельзя.Почему нельзя просто написать `ОткрытьФормуМодально` и получить результат следующей строкой?
Как передать несколько значений в открываемое окно?
ОткрытьФорму. В открытом окне прочитайте через Параметры.Свойство("Имя", Значение) в ПриСозданииНаСервере.Нужно ли обновлять конфигурацию базы после правки формы?
F7). До этого пользователи видят прежнюю версию окна.