При разработке отчетов в системе компоновки данных (СКД) одной из самых частых задач является вывод контактной информации (телефон, Email, адрес) контрагента. Основная трудность заключается в том, что в архитектуре 1С контактная информация хранится в виде табличных частей или записей регистра сведений. Если просто выбрать данные из этих таблиц, система сформирует несколько строк на одного контрагента — по одной на каждый вид контакта. Рассмотрим подробнее, как преобразовать эти данные и вывести их в одну красивую строку.
Разберем ситуацию: у контрагента есть «Телефон» и «Электронная почта». В базе данных это две разные записи в подчиненной таблице. Когда мы пишем запрос и просто выбираем данные из справочника Контрагенты и его табличной части КонтактнаяИнформация, СУБД выполняет соединение, результатом которого становится количество строк, равное количеству контактов. Чтобы этого избежать, нам нужно «развернуть» строки в колонки.
Это классический и самый надежный метод, который подходит для большинства конфигураций. Суть метода заключается в том, что мы присоединяем таблицу контактной информации столько раз, сколько различных видов контактов нам нужно получить. При этом в условии связи мы жестко ограничиваем выборку конкретным видом контактной информации.
Проанализируем пример запроса, который позволяет получить телефон и почту в отдельные колонки одной строки:
ВЫБРАТЬ
Контрагенты.Наименование КАК Наименование,
Контрагенты.ИНН КАК ИНН,
КонтрагентыПочта.АдресЭП КАК АдресЭП,
КонтрагентыТелефон.НомерТелефона КАК НомерТелефона
ИЗ
Справочник.Контрагенты КАК Контрагенты
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты.КонтактнаяИнформация КАК КонтрагентыТелефон
ПО Контрагенты.Ссылка = КонтрагентыТелефон.Ссылка
И (КонтрагентыТелефон.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонКонтрагента))
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты.КонтактнаяИнформация КАК КонтрагентыПочта
ПО Контрагенты.Ссылка = КонтрагентыПочта.Ссылка
И (КонтрагентыПочта.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.EmailКонтрагенты))
В данном примере мы используем ЛЕВОЕ СОЕДИНЕНИЕ. Это критически важно, так как если у контрагента не будет заполнена почта, но будет телефон, при использовании внутреннего соединения (INNER JOIN) такой контрагент вообще не попадет в отчет. Условие ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации...) позволяет нам обращаться к предопределенным элементам видов контактов напрямую в коде запроса.
Часто требуется вывести не только контакты самой компании, но и данные её основного контактного лица. Посмотрим на алгоритм реализации такой задачи. Нам необходимо сначала соединиться со справочником КонтактныеЛица, а затем от него по той же логике получить контактную информацию.
Выясним причину, почему это сложнее: контактное лицо — это самостоятельный объект со своим набором контактов. Запрос будет выглядеть следующим образом:
ВЫБРАТЬ
Контрагенты.Ссылка КАК Контрагент,
Контрагенты.КонтактноеЛицо КАК КонтактноеЛицо,
КИ_Контрагента.НомерТелефона КАК ТелефонКомпании,
КИ_КонтактногоЛица.НомерТелефона КАК ТелефонМенеджера
ИЗ
Справочник.Контрагенты КАК Контрагенты
// Получаем телефон самого контрагента
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты.КонтактнаяИнформация КАК КИ_Контрагента
ПО Контрагенты.Ссылка = КИ_Контрагента.Ссылка
И КИ_Контрагента.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонКонтрагента)
// Получаем телефон контактного лица
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КонтактныеЛица.КонтактнаяИнформация КАК КИ_КонтактногоЛица
ПО Контрагенты.КонтактноеЛицо = КИ_КонтактногоЛица.Ссылка
И КИ_КонтактногоЛица.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонКонтактногоЛица)
Если у одного контрагента может быть записано несколько телефонов (например, два рабочих номера), использование соединений в запросе может привести к дублированию строк, если мы не выберем только один «основной». В СКД есть мощный инструмент для решения этой проблемы без усложнения запроса — функция СоединитьСтроки.
Рассмотрим по шагам, как это настроить:
НомерТелефона.СоединитьСтроки(ТаблицаЗначений(НомерТелефона), ", ").Ссылка (или Контрагент).Этот метод позволит вывести все телефоны контрагента в одну ячейку через запятую, при этом основной отчет останется линейным и понятным. Для ознакомления со схожим примером группировки пригодится способ объединения значений строк в СКД.
В современных конфигурациях (УТ 11, ERP, БП 3.0), построенных на Библиотеке стандартных подсистем (БСП), контактная информация хранится в одноименном регистре сведений КонтактнаяИнформация. Работа с ним через запрос предпочтительнее с точки зрения производительности.
Обратите внимание на поле Объект в регистре — оно имеет составной тип. Поэтому при соединении важно соблюдать типизацию. Также в БСП часто используется поле Представление, которое уже содержит отформатированную строку контакта. Проанализируем пример связи с регистром:
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК КИ
ПО Контрагенты.Ссылка = КИ.Объект
И КИ.Вид = &ПараметрВидКИ
И КИ.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон)
Важный совет: Если вы работаете в типовой конфигурации, посмотрите на функции общего модуля УправлениеКонтактнойИнформацией. Там существуют готовые инструменты для парсинга адресов и телефонов из формата JSON/XML, в котором они хранятся в поле ЗначенияПолей. Для СКД это можно реализовать через Вычисляемые поля, вызывая функции модуля прямо в выражении поля.
При построении сложных отчетов с большим количеством контрагентов использование 5-10 левых соединений в одном запросе может замедлить работу базы. В таких случаях мы рекомендуем:
Ссылка и Объект.Следуя этим методам, вы сможете создавать профессиональные и быстродействующие отчеты, которые предоставляют данные в удобном для пользователя плоском виде.