Как реализовать интерактивный выбор строки табличной части документа в диалоге?

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

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

Способ 1. Использование списка значений и метода «ПоказатьВыборЭлемента»

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

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


&НаКлиенте
Процедура ВыбратьСтрокуЧерезСписок(Команда)
    
    СписокВыбора = Новый СписокЗначений;
    
    // Обходим табличную часть документа
    Для каждого СтрокаТЧ Из Объект.Товары Цикл
        // Формируем понятное пользователю представление строки
        Представление = "Стр. №" + СтрокаТЧ.НомерСтроки + ": " + СтрокаТЧ.Номенклатура + " (" + СтрокаТЧ.Количество + ")";
        // Добавляем в список: значением будет номер строки, текстом — наше представление
        СписокВыбора.Добавить(СтрокаТЧ.НомерСтроки, Представление);
    КонецЦикла;
    
    // Создаем описание оповещения для обработки результата выбора
    Обработчик = Новый ОписаниеОповещения("ПослеВыбораИзСписка", ЭтотОбъект);
    
    // Показываем диалог выбора пользователю
    СписокВыбора.ПоказатьВыборЭлемента(Обработчик, "Выберите позицию для обработки");
    
КонецПроцедуры

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


&НаКлиенте
Процедура ПослеВыбораИзСписка(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
    
    Если ВыбранныйЭлемент <> Неопределено Тогда
        // Получаем номер строки из значения выбранного элемента
        НомерСтроки = ВыбранныйЭлемент.Значение;
        
        // Индекс в массиве строк ТЧ на 1 меньше, чем номер строки
        ИндексСтроки = НомерСтроки - 1;
        ВыбраннаяСтрока = Объект.Товары[ИндексСтроки];
        
        // Выполняем действия с выбранной строкой
        Сообщить("Вы выбрали: " + ВыбраннаяСтрока.Номенклатура);
    КонецЕсли;
    
КонецПроцедуры

Важный нюанс: в управляемых формах для корректной работы ОписаниеОповещения рекомендуется использовать ЭтаФорма или ЭтотОбъект (в контексте модуля формы они указывают на саму форму). Если система «ругается» на неопределенную переменную ЭтотОбъект, используйте ЭтаФорма — это стандартное обращение к объекту формы в платформе 8.3.

Способ 2. Создание специализированной формы выбора

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

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

Шаг 2. Настройка реквизитов. На этой форме создайте реквизит с типом ДинамическийСписок. В свойствах списка установите флаг Произвольный запрос. Это критически важный момент. Посмотрим, какой запрос нам понадобится:


ВЫБРАТЬ
    ТЧ.НомерСтроки КАК НомерСтроки,
    ТЧ.Номенклатура КАК Номенклатура,
    ТЧ.Количество КАК Количество,
    ТЧ.Цена КАК Цена
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК ТЧ
ГДЕ
    ТЧ.Ссылка = &СсылкаНаДокумент

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

Шаг 3. Передача параметров. Чтобы форма открылась с данными именно нашего документа, нам нужно передать ссылку. В основной форме документа пишем следующий код:


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

Шаг 4. Установка параметров в открываемой форме. В модуле созданной нами формы выбора необходимо перехватить переданную ссылку и установить ее в параметры запроса динамического списка:


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

Шаг 5. Возврат результата. Чтобы при двойном клике или нажатии кнопки «Выбрать» данные возвращались в основную форму, проанализируем событие выбора в списке:


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

Сравнение методов и практические советы

Выясним, какой из методов лучше использовать в различных ситуациях. Метод со списком значений хорош своей мобильностью: он работает «на лету», не требует изменений в структуре конфигурации и отлично справляется с визуализацией простых данных. Однако у него есть существенный минус — он не видит изменений в табличной части, которые пользователь внес, но еще не нажал кнопку «Записать» (так как мы программно обходим коллекцию Объект.ТабличнаяЧасть, этот минус нивелируется, если мы берем данные прямо из объекта формы).

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

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

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

← На главную