Как программно создать управляемую форму в 1С: от добавления реквизитов до обработки событий

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Программное создание элементов формы в 1С — это мощный инструмент, который позволяет разработчику создавать динамические интерфейсы, подстраивающиеся под конкретные данные или права пользователя. Однако этот процесс требует четкого понимания разделения между данными формы (реквизитами) и элементами интерфейса. В этой статье мы подробно разберем, как создать форму "с нуля" кодом, настроить интерактивное поведение кнопок и реализовать сложную логику выбора в таблице значений.

Шаг 1. Создание программных реквизитов формы

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

Разберем, как это реализовать в процедуре ПриСозданииНаСервере. Мы используем метод ИзменитьРеквизиты, который принимает массив новых реквизитов. Важно помнить, что создание реквизитов — операция ресурсоемкая, поэтому лучше собрать все изменения в один массив и вызвать метод единожды.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // 1. Подготовка массива для новых реквизитов
    ДобавляемыеРеквизиты = Новый Массив;
    
    // 2. Описание одиночного реквизита (строка)
    ТипСтрока = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(150));
    РеквизитТекст = Новый РеквизитФормы("БазовоеЗначение", ТипСтрока);
    ДобавляемыеРеквизиты.Добавить(РеквизитТекст);
    
    // 3. Описание таблицы значений
    ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы("ТаблицаЗнач", Новый ОписаниеТипов("ТаблицаЗначений")));
    
    // 4. Описание колонок таблицы (указываем путь к владельцу — ТаблицаЗнач)
    ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы("Значение", ТипСтрока, "ТаблицаЗнач"));
    ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы("Выбрано", Новый ОписаниеТипов("Булево"), "ТаблицаЗнач"));
    
    // Применяем изменения на форме
    ЭтаФорма.ИзменитьРеквизиты(ДобавляемыеРеквизиты);
    
КонецПроцедуры

Шаг 2. Размещение элементов управления на форме

Теперь, когда "фундамент" из данных готов, мы можем возводить "стены" — визуальные элементы. Проанализируем, как связать созданные реквизиты с элементами формы. Для этого используется свойство ПутьКДанным.

Продолжим работу в той же серверной процедуре. Мы добавим поле ввода, настроим его внешний вид (цвет фона и подсказку) и создадим таблицу с колонками.


// Создание поля ввода для "БазовоеЗначение"
ПолеТекст = Элементы.Добавить("БазовоеЗначение", Тип("ПолеФормы"));
ПолеТекст.Вид = ВидПоляФормы.ПолеВвода;
ПолеТекст.ПутьКДанным = "БазовоеЗначение";
ПолеТекст.ЦветФона = Новый Цвет(148, 248, 255); // Светло-голубой
ПолеТекст.ПодсказкаВвода = "Укажите базовый текст";
    
// Создание таблицы
ТаблицаФормы = Элементы.Добавить("ТаблицаВизуальная", Тип("ТаблицаФормы"));
ТаблицаФормы.ПутьКДанным = "ТаблицаЗнач";
    
// Добавление колонок в таблицу
КолонкаЗначение = Элементы.Добавить("КолонкаЗначение", Тип("ПолеФормы"), ТаблицаФормы);
КолонкаЗначение.Вид = ВидПоляФормы.ПолеВвода;
КолонкаЗначение.ПутьКДанным = "ТаблицаЗнач.Значение";
КолонкаЗначение.ТолькоПросмотр = Истина; // Запрещаем редактирование по условию задачи
    
КолонкаВыбрано = Элементы.Добавить("КолонкаВыбрано", Тип("ПолеФормы"), ТаблицаФормы);
КолонкаВыбрано.Вид = ВидПоляФормы.ПолеФлажка;
КолонкаВыбрано.ПутьКДанным = "ТаблицаЗнач.Выбрано";

Шаг 3. Динамическое управление доступностью кнопки

Одной из интересных задач является изменение доступности кнопки "в реальном времени", пока пользователь еще печатает текст. Для этого нам не подойдет обычное событие ПриИзменении, так как оно срабатывает только после потери фокуса полем ввода.

Рассмотрим использование события ИзменениеТекстаРедактирования. Мы назначим обработчик программно с помощью метода УстановитьДействие.


// В ПриСозданииНаСервере:
// Создаем команду и кнопку
Команда = Команды.Добавить("Заполнить");
Команда.Действие = "ОбработкаКомандыЗаполнить";
    
Кнопка = Элементы.Добавить("КнопкаЗаполнить", Тип("КнопкаФормы"));
Кнопка.ИмяКоманды = "Заполнить";
Кнопка.Доступность = Ложь; // По умолчанию недоступна
    
// Привязываем событие живого изменения текста
ПолеТекст.УстановитьДействие("ИзменениеТекстаРедактирования", "ПолеТекстИзменениеТекста");

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


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

Шаг 4. Работа с асинхронными вызовами (Ввод числа)

Современная платформа 1С требует отказа от модальных окон. Поэтому для ввода количества строк мы будем использовать метод ПоказатьВводЗначения. Это позволит нашей обработке работать в веб-клиенте и мобильных приложениях.

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


&НаКлиенте
Процедура ОбработкаКомандыЗаполнить(Команда)
    Оповещение = Новый ОписаниеОповещения("ПослеВводаКоличества", ЭтотОбъект);
    ПоказатьВводЗначения(Оповещение, 0, "Сколько строк добавить?");
КонецПроцедуры

&НаКлиенте
Процедура ПослеВводаКоличества(Результат, ДополнительныеПараметры) Экспорт
    Если Результат = Неопределено Тогда 
        Возврат; // Пользователь нажал отмену
    КонецЕсли;
    
    Количество = Число(Результат);
    Для Счетчик = 1 По Количество Цикл
        НоваяСтрока = ТаблицаЗнач.Добавить();
        НоваяСтрока.Значение = БазовоеЗначение + " " + (ТаблицаЗнач.Количество());
    КонецЦикла;
КонецПроцедуры

Шаг 5. Реализация "Единственного выбора" в таблице

Часто требуется, чтобы в таблице флаг "Выбрано" стоял только в одной строке. Если пользователь ставит флаг во второй строке, система должна спросить подтверждение и снять флаг с первой.

Для реализации этого алгоритма выясним, как программно перехватить изменение флажка. Нам нужно добавить событие ПриИзменении для колонки "Выбрано" при создании формы:

КолонкаВыбрано.УстановитьДействие("ПриИзменении", "КолонкаВыбраноПриИзменении");

Разберем клиентскую логику обработки этого события. Мы будем искать другие строки с установленным флагом и выводить предупреждение через ПоказатьВопрос.


&НаКлиенте
Процедура КолонкаВыбраноПриИзменении(Элемент)
    ТекущиеДанные = Элементы.ТаблицаВизуальная.ТекущиеДанные;
    
    // Если пользователь снял флаг - ничего не делаем
    Если Не ТекущиеДанные.Выбрано Тогда
        ОбновитьИнфоНадпись();
        Возврат;
    КонецЕсли;
    
    // Ищем, есть ли уже выбранная строка (кроме текущей)
    НайденнаяСтрока = Неопределено;
    Для Каждого СтрокаТЗ Из ТаблицаЗнач Цикл
        Если СтрокаТЗ.Выбрано И СтрокаТЗ <> ТекущиеДанные Тогда
            НайденнаяСтрока = СтрокаТЗ;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Если НайденнаяСтрока <> Неопределено Тогда
        // Сохраняем индекс найденной строки, чтобы сбросить её позже
        ДопПараметры = Новый Структура("СтараяСтрока, ТекущаяСтрока", НайденнаяСтрока, ТекущиеДанные);
        Оповещение = Новый ОписаниеОповещения("ПослеОтветаНаВопрос", ЭтотОбъект, ДопПараметры);
        
        ТекстВопроса = "В одной из строк уже установлен флаг. Оно будет очищено. Продолжить?";
        ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
    Иначе
        ОбновитьИнфоНадпись();
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПослеОтветаНаВопрос(Результат, ДопПараметры) Экспорт
    Если Результат = КодВозвратаДиалога.Да Тогда
        ДопПараметры.СтараяСтрока.Выбрано = Ложь;
    Иначе
        ДопПараметры.ТекущаяСтрока.Выбрано = Ложь;
    КонецЕсли;
    ОбновитьИнфоНадпись();
КонецПроцедуры

Шаг 6. Динамическая надпись (Декорация)

В завершение добавим под таблицу информационную надпись, которая будет показывать номер выбранной строки. Создадим элемент типа ДекорацияФормы с видом Надпись.


// В ПриСозданииНаСервере:
ИнфоНадпись = Элементы.Добавить("ИнфоНадпись", Тип("ДекорацияФормы"), ЭтаФорма);
ИнфоНадпись.Вид = ВидДекорацииФормы.Надпись;
ИнфоНадпись.Заголовок = "";
ИнфоНадпись.Видимость = Ложь;

Напишем вспомогательную процедуру, которая будет обновлять текст этой надписи. Мы будем вызывать её каждый раз, когда меняется флаг в таблице или добавляются новые строки.


&НаКлиенте
Процедура ОбновитьИнфоНадпись()
    НомерСтроки = 0;
    Для Каждого Стр Из ТаблицаЗнач Цикл
        Если Стр.Выбрано Тогда
            НомерСтроки = ТаблицаЗнач.Индекс(Стр) + 1;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Если НомерСтроки > 0 Тогда
        Элементы.ИнфоНадпись.Заголовок = "Основной текст в строке №" + НомерСтроки;
        Элементы.ИнфоNadpis.Видимость = Истина;
    Иначе
        Элементы.ИнфоНадпись.Видимость = Ложь;
    КонецЕсли;
КонецПроцедуры

Подведем итог: мы проанализировали полный цикл жизни программной формы. Основной секрет успеха здесь заключается в строгом соблюдении последовательности: сначала создаем реквизиты через ИзменитьРеквизиты, затем добавляем элементы управления через Элементы.Добавить и только в конце связываем их с событиями через УстановитьДействие. Такой подход делает ваш код чистым, расширяемым и надежным.

← На главную