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

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

При разработке интерфейсов на платформе 1С:Предприятие 8.3 часто возникает задача отобразить в форме списка не только основные реквизиты объекта, но и данные из его табличных частей. Типичный пример из УТ 11 или ERP — вывод контактной информации (номера телефона или адреса электронной почты) в списке контрагентов или контактных лиц. На первый взгляд задача кажется простой, но при использовании динамических списков разработчики часто сталкиваются с проблемой дублирования строк или невозможностью настроить корректную связь. В этой статье мы подробно разберем, как правильно решить эту задачу, избежав типичных ошибок.

Проблема использования прямого соединения в запросе

Рассмотрим стандартную ситуацию: мы хотим добавить колонку "Телефон" в динамический список. Если мы просто добавим в запрос динамического списка ЛЕВОЕ СОЕДИНЕНИЕ с табличной частью КонтактнаяИнформация, то получим крайне неприятный эффект. Если у одного контактного лица указано три телефона (рабочий, мобильный, домашний), то в списке это лицо продублируется трижды. Это происходит потому, что динамический список работает по принципам реляционных баз данных: одна запись в присоединенной таблице рождает одну строку в результате запроса.

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

Решение №1: Использование события ПриПолученииДанныхНаСервере

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

Рассмотрим пошагово реализацию этого метода:

  1. Подготовка формы. Добавим в динамический список новое поле. В редакторе запроса динамического списка (произвольный запрос) нужно добавить поле-пустышку. Например: ВЫБРАТЬ ..., NULL КАК ТелефонПредставление ИЗ .... После этого в элементах формы появится новая колонка.
  2. Создание обработчика. Создадим на сервере обработчик события динамического списка ПриПолученииДанныхНаСервере.

Посмотрим на пример кода, который эффективно решает задачу:


&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
    
    // Получаем массив ссылок на объекты, которые сейчас отображаются в списке
    МассивСсылок = Строки.ПолучитьКлючи();
    
    // Создаем запрос для получения контактной информации только по этим объектам
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |	КИ.Ссылка КАК Ссылка,
    |	КИ.Представление КАК Представление
    |ИЗ
    |	Справочник.КонтактныеЛицаПартнеров.КонтактнаяИнформация КАК КИ
    |ГДЕ
    |	КИ.Ссылка В(&МассивСсылок)
    |	И КИ.Вид.Наименование ПОДОБНО ""%Телефон%""";
    
    Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
    
    Выборка = Запрос.Выполнить().Выбрать();
    
    // Заполняем данные в строках списка
    Пока Выборка.Следующий() Цикл
        ТекущаяСтрока = Строки[Выборка.Ссылка];
        ТекущаяСтрока.Данные["ТелефонПредставление"] = Выборка.Представление;
    КонецЦикла;
    
КонецПроцедуры

Важный нюанс: Обратите внимание на использование Строки.ПолучитьКлючи(). Это критически важно для производительности. Запрос выполняется не для всей базы, а только для тех 20-40 записей, которые пользователь видит на экране в данный момент. Это делает работу списка молниеносной даже при миллионах записей в справочнике.

Решение №2: Несколько левых соединений в запросе

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

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


ВЫБРАТЬ
    КонтактныеЛица.Ссылка,
    КонтактныеЛица.Наименование,
    ТаблицаТелефоны.Представление КАК Телефон,
    ТаблицаПочта.Представление КАК ЭлектроннаяПочта
ИЗ
    Справочник.КонтактныеЛицаПартнеров КАК КонтактныеЛица
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КонтактныеЛицаПартнеров.КонтактнаяИнформация КАК ТаблицаТелефоны
        ПО КонтактныеЛица.Ссылка = ТаблицаТелефоны.Ссылка
        И ТаблицаТелефоны.Вид = &ВидТелефон
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КонтактныеЛицаПартнеров.КонтактнаяИнформация КАК ТаблицаПочта
        ПО КонтактныеЛица.Ссылка = ТаблицаПочта.Ссылка
        И ТаблицаПочта.Вид = &ВидПочта

В этом случае параметры &ВидТелефон и &ВидПочта нужно установить программно при создании формы, используя метод Список.Параметры.УстановитьЗначениеПараметра(). Этот метод гарантирует, что на каждую строку справочника придется максимум одна строка из табличной части (при условии, что у объекта только один телефон конкретного вида).

Оптимизация и особенности работы в типовых конфигурациях

Проанализируем ситуацию в современных конфигурациях на базе БСП (Бизнес-стандарт подсистем). В УТ 11, ERP и КА контактная информация часто хранится не только в табличных частях, но и в специальных регистрах сведений (например, КонтактнаяИнформация). Работа через регистр сведений в динамическом списке более предпочтительна с точки зрения скорости доступа к данным.

Также стоит помнить о поле Представление. В табличных частях контактной информации поле Представление содержит уже сформированную строку (например, "+7 (999) 000-00-00"). Всегда используйте именно его для вывода в списки, чтобы не нагружать сервер вычислениями по сборке номера из кода страны, города и добавочного номера.

Резюмируем:

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

← На главную