Как автоматически заполнять и отображать код и наименование справочника в регистре сведений

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

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

Архитектурный подход: избегаем избыточности данных

Прежде чем переходить к коду, проанализируем структуру базы данных. Если в регистре сведений создано измерение с типом СправочникСсылка, то система уже хранит ссылку на объект. Это означает, что через эту ссылку мы в любой момент можем получить и Код, и Наименование, и любой другой реквизит этого справочника. Создание дополнительных измерений «Код» и «Наименование» внутри регистра приводит к денормализации — избыточному дублированию данных. Если в справочнике изменится наименование, в регистре оно останется старым, что приведет к логическим ошибкам.

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

Реализация в обычных формах (1С 8.3)

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

Способ 1: Использование события ПриВыводеСтроки

Этот метод подходит для простых списков. Мы добавляем в таблицу формы колонку (без привязки к данным) и программно устанавливаем в ней текст. Разберем по шагам:

  1. Откроем форму списка регистра в Конфигураторе.
  2. Добавим в табличное поле новую колонку, назовем ее КодСтатьи. Поле Данные оставляем пустым.
  3. Создадим обработчик события ПриВыводеСтроки для табличного поля.

Проанализируем пример кода для этого обработчика:


Процедура РегистрСведенийСписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    // Проверяем, что ссылка на справочник (измерение "Статья") заполнена
    Если ДанныеСтроки.Статья <> Неопределено Тогда
        // Устанавливаем текст в ячейку "КодСтатьи" через обращение к ссылке
        ОформлениеСтроки.Ячейки.КодСтатьи.УстановитьТекст(ДанныеСтроки.Статья.Код);
    Иначе
        ОформлениеСтроки.Ячейки.КодСтатьи.УстановитьТекст("");
    КонецЕсли;
КонецПроцедуры

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

Способ 2: Оптимизация через ПриПолученииДанных

Для высоконагруженных систем рекомендуется использовать событие ПриПолученииДанных. Оно позволяет получить данные для всех видимых на экране строк одним запросом. Рассмотрим этот алгоритм:


Процедура РегистрСведенийСписокПриПолученииДанных(Элемент, ОформленияСтрок)
    // Создаем массив для хранения уникальных ссылок на справочник
    МассивСсылок = Новый Массив;
    Для Каждого Оформление Из ОформленияСтрок Цикл
        Если Оформление.ДанныеСтроки.Статья <> Неопределено Тогда
            МассивСсылок.Добавить(Оформление.ДанныеСтроки.Статья);
        КонецЕсли;
    КонецЦикла;

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

    // Заполняем ячейки данными из результата запроса
    Для Каждого Оформление Из ОформленияСтрок Цикл
        СтрокаДанных = ТаблицаДанных.Найти(Оформление.ДанныеСтроки.Статья, "Ссылка");
        Если СтрокаДанных <> Неопределено Тогда
            Оформление.Ячейки.КодСтатьи.УстановитьТекст(СтрокаДанных.Код);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Реализация в управляемых формах

В управляемом приложении (платформа 8.3) задача решается значительно проще благодаря механизму динамических списков. Нам не нужно писать код для отображения реквизитов ссылки.

Рассмотрим порядок действий в конфигураторе:

  1. Откроем форму списка регистра сведений.
  2. В окне Элементы найдем таблицу, отображающую список.
  3. В окне Реквизиты раскроем основную схему динамического списка (обычно это Список).
  4. Найдем наше измерение (например, Статья) и нажмем на значок «плюс» слева от него. Платформа раскроет все доступные реквизиты справочника.
  5. Перетащим поле Код из списка реквизитов в дерево элементов формы.

Система автоматически установит ПутьКДанным как Список.Статья.Код. Платформа сама оптимизирует SQL-запрос, добавляя LEFT JOIN, и выведет данные максимально эффективно.

Автоматическое заполнение полей на форме записи

Если нам нужно, чтобы при выборе справочника на форме записи регистра поле Код обновлялось интерактивно, мы воспользуемся обработчиками событий формы. Выясним причину, по которой прямое обращение может не работать: в модуле формы записи мы работаем с объектом Запись.

Разберем пример реализации для обычной формы записи:


// Обработчик изменения основного измерения
Процедура СтатьяПриИзменении(Элемент)
    ЗаполнитьРеквизитыСтатьи();
КонецПроцедуры

// Процедура для обновления виртуальных полей на форме
Процедура ЗаполнитьРеквизитыСтатьи()
    // ЭлементСтатьи - это текстовое поле или надпись на форме
    Если ЗначениеЗаполнено(Статья) Тогда
        ЭлементыФормы.НадписьКод.Значение = Статья.Код;
        ЭлементыФормы.НадписьНаименование.Значение = Статья.Наименование;
    Иначе
        ЭлементыФормы.НадписьКод.Значение = "";
        ЭлементыФормы.НадписьНаименование.Значение = "";
    КонецЕсли;
КонецПроцедуры

// Не забываем вызвать процедуру при открытии формы для существующих записей
Процедура ПриОткрытии()
    ЗаполнитьРеквизитыСтатьи();
КонецПроцедуры

Почему вылетает отладчик?

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

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

Итоги

Подводя итог, можно выделить следующие рекомендации по работе с полями справочников в регистрах:

← На главную