Как вывести код номенклатуры контрагента в табличную часть документа в 1С:Управление торговлей 10.3?

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

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

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

Анализ типичных ошибок при динамическом выводе данных

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

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

Решение 1. Пакетное получение данных через событие ПриПолученииДанных (Рекомендуемый способ)

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

Разберем по шагам алгоритм реализации:

  1. Добавим в табличное поле Товары новую колонку с именем КодПост.
  2. В свойствах табличного поля назначим обработчик события ПриПолученииДанных.
  3. Соберем список ссылок на номенклатуру из всех переданных строк.
  4. Выполним один запрос к регистру сведений НоменклатураКонтрагентов с отбором по списку номенклатуры и контрагенту из шапки документа.
  5. Заполним ячейки оформления строк полученными значениями.

Посмотрим на пример реализации кода модуля формы документа:


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

Учет характеристик номенклатуры

Рассмотрим подробнее ситуацию, когда в базе ведется учет по характеристикам номенклатуры. В типовом регистре НоменклатураКонтрагентов измерение ХарактеристикаНоменклатуры также участвует в ключе уникальности. Если у поставщика артикулы или коды зависят от характеристик, запрос и сопоставление необходимо строить по двум полям (номенклатура и характеристика), чтобы избежать неточных данных.

Решение 2. Добавление реквизита в табличную часть документа

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

  1. Добавим реквизит КодНоменклатурыКонтрагента (тип Строка) напрямую в табличную часть Товары документа ЗаказПоставщику.
  2. В обработчике события ТоварыНоменклатураПриИзменении настроим автоматическое заполнение этого реквизита из регистра сведений.
  3. При смене реквизита Контрагент в шапке документа выполним пересчет и перезаполнение кодов для всех строк табличной части.

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

← На главную