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

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

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

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

Проблема "Квадратных колес": Архитектурный анализ

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

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

Рассмотрим правильный путь и альтернативные методы реализации.

Решение 1: Использование подчиненного справочника (Архитектурно верный путь)

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

В документе ЗаказКлиента в табличной части добавим реквизит Характеристика с типом СправочникСсылка.ХарактеристикиНоменклатуры. Теперь при выборе характеристики 1С автоматически откроет форму выбора с фильтром по текущему товару. Это стандартный механизм, который не требует написания сложного кода.

Проанализируем преимущества:

Решение 2: Динамический список по табличной части

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

Создадим новую форму в справочнике Товары и назовем ее ФормаВыбораХарактеристик. Основным реквизитом формы сделаем ДинамическийСписок. Главный секрет здесь кроется в запросе динамического списка. Вместо выбора из основной таблицы справочника, мы напишем запрос к его табличной части:


ВЫБРАТЬ
    ТоварыХарактеристики.Ссылка КАК Товар,
    ТоварыХарактеристики.Цвет КАК Цвет,
    ТоварыХарактеристики.Размер КАК Размер
ИЗ
    Справочник.Товары.Характеристики КАК ТоварыХарактеристики

Теперь в форме выбора пользователь будет видеть не просто товары, а каждую строку "Товар + Цвет + Размер" как отдельную позицию. При выборе строки нам нужно передать данные обратно в документ. Для этого в событии Выбор или ПередЗакрытием формы выбора сформируем структуру:


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

Решение 3: Программный подбор через список выбора (QuickChoice)

Если цветов и размеров у конкретного товара немного (например, до 10-15 вариантов), можно реализовать выбор через выпадающий список прямо в строке документа. Разберем ситуацию: пользователь выбрал товар, и программа тут же предлагает ему выбрать цвет из списка.

В модуле формы документа ЗаказКлиента используем событие ПриИзменении для реквизита Номенклатура:


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

Затем опишем процедуру обработки результата, которая заполнит реквизиты строки:


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

Важные технические нюансы

Разберем, на что стоит обратить внимание при написании запросов к табличным частям. При работе с методом ПолучитьХарактеристикиНаСервере, всегда используйте запрос, а не обращение к объекту через точку, чтобы не нагружать память сервера лишними данными:


&НаСервереБезКонтекста
Функция ПолучитьХарактеристикиНаСервере(ТоварСсылка)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	ТоварыХарактеристики.Цвет КАК Цвет,
        |	ТоварыХарактеристики.Размер КАК Размер
        |ИЗ
        |	Справочник.Товары.Характеристики КАК ТоварыХарактеристики
        |ГДЕ
        |	ТоварыХарактеристики.Ссылка = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", ТоварСсылка);
    Возврат Запрос.Выполнить().Выгрузить();
КонецФункции

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

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

← На главную