Как вывести адрес в форму списка на управляемых формах 1С без дублирования строк

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

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

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

Почему возникает ошибка дублирования ключевых значений?

Динамический список в 1С спроектирован так, чтобы отображать уникальные строки, где в качестве уникального ключа по умолчанию выступает поле Ссылка. Когда мы выполняем левое соединение (LEFT JOIN) таблицы справочника с табличной частью КонтактнаяИнформация, СУБД сопоставляет каждому элементу справочника все связанные с ним строки контактной информации.

Если у одного объекта ККТ или контрагента в информационной базе заполнено несколько видов контактной информации (например, телефон, электронная почта, юридический адрес и фактический адрес), то СУБД вернет несколько строк для одной и той же ссылки. Платформа 1С не может сопоставить эти дублирующиеся строки с одной строкой визуального списка, из-за чего и генерирует ошибку дублирования ключей.

Попытка использовать в запросе ключевое слово РАЗЛИЧНЫЕ (DISTINCT) проблему не решает. Строки в результирующей выборке все равно будут уникальными в масштабе всей таблицы (так как адреса и телефоны различаются), но значение в поле Ссылка по-прежнему будет дублироваться. Кроме того, использование РАЗЛИЧНЫЕ или СГРУППИРОВАТЬ ПО в динамических списках крайне не рекомендуется фирмой «1С», так как это заставляет СУБД выполнять полное сканирование таблиц вместо быстрого постраничного вывода, что приводит к критическому падению производительности на больших базах данных.

Рассмотрим правильные архитектурные подходы к решению этой задачи.

Способ 1. Настройка левого соединения в запросе с жестким ограничением по Виду КИ

Чтобы левое соединение не плодило строки, мы должны гарантировать СУБД, что для каждого элемента справочника будет выбрана строго одна запись контактной информации. Для этого в условии связи таблиц (секция ПО) необходимо наложить жесткий фильтр по конкретному виду контактной информации.

Разберем пример запроса для динамического списка, в котором нам нужно вывести конкретный вид адреса (например, фактический адрес ККТ):


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

Обратите внимание на ключевые особенности этого запроса:

  1. Фильтрация происходит непосредственно в условии соединения ПО, а не в секции ГДЕ. Если перенести это условие в ГДЕ, то элементы справочника, у которых адрес вообще не заполнен, просто исчезнут из списка (левое соединение превратится во внутреннее).
  2. Мы связываем таблицу по конкретному предопределенному элементу Справочник.ВидыКонтактнойИнформации.ФактическийАдресККТ. Фильтровать по полю Тип (например, Перечисление.ТипыКонтактнойИнформации.Адрес) нельзя, так как у одного объекта может быть заведено несколько видов адресов, что опять приведет к дублированию строк.

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


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

Способ 2. Использование платформенного механизма характеристик (Рекомендуемый метод)

Наиболее красивым, гибким и производительным решением, полностью поддерживающим стандарты разработки фирмы «1С», является использование встроенного в платформу **механизма характеристик**. Этот способ уникален тем, что вам вообще не придется включать «Произвольный запрос» в динамическом списке и писать код соединения таблиц вручную. Платформа сама оптимизирует SQL-запрос при работе со списком.

Выполним настройку по шагам:

  1. Откроем конфигуратор, найдем наш справочник (например, ККТ) и перейдем на вкладку «Характеристики».
  2. Нажмем кнопку «Добавить» для создания нового описания характеристик и заполним параметры:
    • Вид характеристик: укажем справочник, хранящий виды контактной информации — Справочник.ВидыКонтактнойИнформации.
    • Отбор видов: здесь можно указать отбор (например, по полю Родитель), чтобы в списке предлагались только те виды контактной информации, которые логически относятся к нашему справочнику.
    • Таблица характеристик: укажем источник данных. Если КИ хранится в табличной части справочника, выбираем Справочник.ККТ.КонтактнаяИнформация. Если КИ хранится в регистре, выбираем РегистрСведений.КонтактнаяИнформация.
    • Ключ объекта: поле связи с объектом. Для табличной части это Ссылка, для регистра сведений — Объект.
    • Вид характеристики: поле Вид.
    • Значение: поле Представление (именно в нем хранится готовая строка адреса).
  3. Перейдем к форме списка нашего справочника. Убедимся, что у свойства «Список» заполнено свойство Основная таблица (в нем должен быть выбран наш справочник Справочник.ККТ).

Что мы получаем в результате? Теперь в режиме «1С:Предприятие» любой пользователь может зайти в форму списка, нажать кнопку «Еще — Изменить форму», развернуть стандартную группу полей Ссылка и увидеть там все доступные виды контактной информации как отдельные виртуальные поля! Пользователь может самостоятельно вынести «Фактический адрес» или «Телефон» на форму. При этом платформа гарантирует отсутствие дублей строк в списке и автоматически оптимизирует SQL-запросы к базе данных.

Способ 3. Использование оптимизированного кэша БСП для списков

В современных редакциях конфигураций (например, в УНФ 1.6/3.0, ERP, Комплексной автоматизации или Управлении торговлей) разработчики БСП предусмотрели специализированный механизм оптимизации списков. Динамическое левое соединение с тяжелыми таблицами КИ в реальном времени может замедлять работу интерфейса, если в списке выводятся тысячи элементов.

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

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

УправлениеКонтактнойИнформацией.ОбновитьКонтактнуюИнформациюДляСписков(Источник)

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

Резюме

Для быстрого и простого решения задачи в самописном справочнике отлично подойдет Способ 1 (произвольный запрос с левым соединением и жестким отбором по виду КИ в условии связи). Если же вы хотите предоставить пользователям гибкость в настройке видимости различных адресов и телефонов без привлечения программиста, обязательно используйте Способ 2 (механизм характеристик). Для высоконагруженных систем с большим объемом данных наиболее правильным выбором будет использование встроенных методов оптимизации списков БСП (Способ 3).

← На главную