Как в 1С вернуть значение из своей формы выбора с таблицей значений?

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

При разработке на платформе 1С часто возникает задача создать собственную, кастомную форму выбора вместо типовой. Это позволяет гибко настроить отображение данных, добавить фильтры или сложную логику. В качестве основы для такой формы часто используют Таблицу Значений (ТЗ) на управляемой форме. Однако после настройки внешнего вида и заполнения данными возникает ключевой вопрос: как правильно вернуть выбранные пользователем данные обратно в ту форму, откуда был инициирован выбор?

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

Шаг 1: Получение данных по идентификатору выбранной строки

Итак, пользователь сделал выбор в нашей форме двойным щелчком мыши или нажатием Enter. Срабатывает событие Выбор у элемента формы (таблицы). В обработчик этого события система передает параметр, который содержит идентификатор выбранной строки. Если в таблице включен множественный выбор, этот параметр будет содержать массив идентификаторов.

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

Рассмотрим пример обработчика события Выбор для таблицы на форме с именем СписокДокументовОснования. Предположим, что эта таблица отображает данные из реквизита формы (типа ТаблицаЗначений) с таким же именем.


&НаКлиенте
Процедура СписокДокументовОснованияВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    
    // В первую очередь отключаем стандартное поведение, 
    // чтобы система не пыталась закрыть форму и вернуть идентификатор.
    СтандартнаяОбработка = Ложь; 
    
    // Определим, какие строки были выбраны.
    // Если множественный выбор не используется, то можно получить выделенные строки так.
    // Но лучше использовать свойство элемента "ВыделенныеСтроки" - оно надежнее.
    МассивВыбранныхСтрок = Элементы.СписокДокументовОснования.ВыделенныеСтроки;

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

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

Шаг 2: Выбор формата возвращаемых данных

Прежде чем вернуть данные, нужно определиться с их форматом. Это зависит от того, что мы хотим получить в форме-владельце.

  1. Одно значение. Если всегда выбирается только одна строка и нужна только одна колонка (например, ссылка на справочник), то в итоге нужно вернуть не массив, а одно конкретное значение.
  2. Массив значений. Если пользователь может выбрать несколько строк, но нам нужна информация только из одной колонки (например, список выбранных номенклатурных позиций), то возвращаем массив простых значений.
  3. Структура. Если выбрана одна строка, но нужно вернуть данные из нескольких колонок (например, Номенклатура, Количество и Цена), удобно использовать структуру.
  4. Массив структур. Это самый универсальный и рекомендуемый вариант для множественного выбора. Для каждой выбранной строки формируется структура с нужными полями, и эти структуры помещаются в один общий массив. Это позволяет передать всю необходимую информацию о каждой строке.

Посмотрим на пример формирования массива структур. Доработаем наш предыдущий код:


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

    // Далее передаем РезультатВыбора...
    
КонецПроцедуры

Шаг 3: Возврат подготовленных данных в форму-владельца

Теперь, когда у нас есть переменная РезультатВыбора с нужными данными в правильном формате, ее необходимо передать обратно. Существует два основных механизма.

Метод 1: Закрыть(ВозвращаемоеЗначение)

Этот метод используется, если форма выбора была открыта модально (например, с помощью ОткрытьФормуМодально()). Выполнение кода в форме-владельце приостанавливается до тех пор, пока форма выбора не закроется. Значение, переданное в метод Закрыть(), становится результатом выполнения функции, открывшей форму.

В нашей форме выбора в конце обработчика добавляем:


    // ... код формирования РезультатВыбора
    
    // Если в результате только один элемент, можем вернуть его напрямую, а не в массиве
    Если РезультатВыбора.Количество() = 1 Тогда
        Закрыть(РезультатВыбора[0]);
    ИначеЕсли РезультатВыбора.Количество() > 1 Тогда
        Закрыть(РезультатВыбора);
    КонецЕсли;
    
КонецПроцедуры // Конец обработчика выбора

В форме-владельце вызов будет выглядеть так:


&НаКлиенте
Процедура ВыбратьДокументы()
    
    ВыбранныеДанные = ОткрытьФормуМодально("Обработка.МояФормаВыбора.Форма");
    
    Если ВыбранныеДанные <> Неопределено Тогда
        // Обрабатываем полученные данные (одно значение, массив или массив структур)
        Сообщить("Выбор сделан!");
    КонецЕсли;
    
КонецПроцедуры

Метод 2: ОповеститьОВыборе(ВозвращаемоеЗначение)

Это более современный и гибкий механизм, который работает как для модальных, так и для немодальных окон. Он не закрывает форму выбора автоматически. Вместо этого он генерирует событие в форме-владельце, которое можно обработать в процедуре ОбработкаОповещения.

В форме выбора в конце обработчика пишем:


    // ... код формирования РезультатВыбора
    
    Если РезультатВыбора.Количество() > 0 Тогда
        ОповеститьОВыборе(РезультатВыбора);
    КонецЕсли;
    
КонецПроцедуры

В форме-владельце нужно описать обработчик. Вызов формы при этом осуществляется через ОткрытьФорму() с указанием владельца.


&НаКлиенте
Процедура ВыбратьДокументы()
    ОткрытьФорму("Обработка.МояФормаВыбора.Форма",, ЭтаФорма);
КонецПроцедуры

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

    КонецЕсли;
    
КонецПроцедуры

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

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