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

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

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

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

Почему не стоит дублировать данные в табличных частях

Первое побуждение новичка — при записи абонента программно найти нужный тип телефона, получить его объект и добавить строку в его табличную часть. Мы должны проанализировать, к чему это приведет:

  1. Нарушение целостности: Если вы измените тип телефона у абонента, вам придется писать сложный код для удаления старой записи из справочника типов. Вероятность появления «мусорных» данных крайне высока.
  2. Конфликты блокировок: При записи одного абонента система будет блокировать объект типа телефона. Если несколько пользователей одновременно редактируют абонентов с типом «Мобильный», возникнет очередь, и программа начнет выдавать ошибки.
  3. Избыточность: База данных неоправданно растет, так как одна и та же информация хранится в двух местах.

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

Способ 1. Использование Динамического списка (рекомендуемый)

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

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

  1. Откроем форму элемента справочника ТипыТелефонов.
  2. В окне Реквизиты добавим новый реквизит (например, СписокАбонентов) с типом ДинамическийСписок.
  3. В свойствах этого реквизита установим флаг Произвольный запрос и нажмем Открыть.

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


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

После написания запроса перетащим реквизит СписокАбонентов на форму. Теперь нам нужно передать параметр &СсылкаНаТип в этот список. Это делается в модуле формы в процедуре ПриЧтенииНаСервере или ПриСозданииНаСервере:


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

Способ 2. Использование критериев отбора

Если нам нужно видеть связанные данные без написания кода, мы можем использовать стандартный механизм платформы — Критерии отбора. Это «лоу-код» решение задачи.

Рассмотрим алгоритм настройки:

  1. В дереве метаданных найдем ветку Общие -> Критерии отбора и создадим новый объект, например, СвязанныеАбоненты.
  2. В поле Тип выберем СправочникСсылка.ТипыТелефонов.
  3. На вкладке Состав отметим реквизит ТипТелефона из табличной части справочника Абоненты.

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

Работа с результатами запроса в программном коде

Иногда задача требует не просто показать данные, а обработать их программно (например, для проверки перед записью). Выясним, как правильно работать с объектом Запрос в модуле объекта.

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ АбонентыДанные.Ссылка) КАК КолВо
    |ИЗ
    |	Справочник.Абоненты.Данные КАК АбонентыДанные
    |ГДЕ
    |	АбонентыДанные.ТипТелефона = &Тип";

Запрос.УстановитьПараметр("Тип", ЭтотОбъект.Ссылка);

РезультатЗапроса = Запрос.Выполнить();

Если Не РезультатЗапроса.Пустой() Тогда
    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        Сообщить("Данный тип используют абонентов: " + ВыборкаДетальныеЗаписи.КолВо);
    КонецЦикла;
КонецЕсли;

Важные моменты при написании запросов:

Подведение итогов

Мы проанализировали ситуацию и выяснили, что для отображения связей между справочниками Абоненты и ТипыТелефонов лучше всего подходят Динамические списки или Критерии отбора. Они избавляют от необходимости дублировать данные в табличных частях и обеспечивают высокую скорость работы базы данных.

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

← На главную