Как добавить колонку "Номенклатура" в список заказов на производство в 1С:УПП?

Программист 1С v8.3 (Обычные формы) Управленческий учет Промышленность, строительство и АПК
← На главную

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

Постановка задачи и начальные настройки в Конфигураторе

Представим ситуацию: нам необходимо добавить в форму списка документа ЗаказНаПроизводство три колонки: Номенклатура, Спецификация и Количество. Поскольку эти данные хранятся в табличной части "Продукция", нам потребуется внести изменения в свойства формы списка.

Для начала откроем конфигуратор и выполним следующие действия:

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

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

Решение 1: Использование события ПриВыводеСтроки (быстрый, но затратный метод)

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

Рассмотрим пример кода, который позволяет вывести данные первой строки табличной части в список:


Процедура СписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    
    // Проверяем, есть ли в документе хотя бы одна строка в табличной части Продукция
    Если ДанныеСтроки.Ссылка.Продукция.Количество() > 0 Тогда
        
        // Получаем первую строку табличной части
        ПерваяСтрока = ДанныеСтроки.Ссылка.Продукция[0];
        
        // Заполняем ячейки оформления значениями
        ОформлениеСтроки.Ячейки.Номенклатура.Значение = ПерваяСтрока.Номенклатура;
        ОформлениеСтроки.Ячейки.Спецификация.Значение = ПерваяСтрока.Спецификация;
        ОформлениеСтроки.Ячейки.Количество.Значение   = ПерваяСтрока.Количество;
        
    КонецЕсли;

КонецПроцедуры

Почему это решение может быть опасным? Проанализируем ситуацию: когда вы прокручиваете список, 1С выполняет этот код для каждой видимой строки. Обращение через точку к табличной части ДанныеСтроки.Ссылка.Продукция заставляет систему делать отдельный запрос к базе данных для каждого документа. Если в списке отображается 20 строк, система сделает 20 дополнительных запросов. Это приводит к заметным задержкам ("тормозам") при работе пользователя.

Решение 2: Оптимизация через событие ПриПолученииДанных (профессиональный подход)

Чтобы избежать проблемы "N+1 запросов", мы можем использовать событие ПриПолученииДанных. В отличие от предыдущего метода, это событие получает данные сразу для всего массива строк, которые система планирует отобразить на экране. Это позволяет нам выполнить всего один запрос к базе данных вместо десятков.

Разберем алгоритм работы в этом событии по шагам:

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

Посмотрим на пример реализации такого кода:


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

Этот метод работает на порядок быстрее, так как обращение к серверу базы данных происходит пакетно.

Решение 3: Архитектурное изменение (использование реквизита в шапке)

Если ваша база данных содержит сотни тысяч заказов и список все равно работает медленно, стоит рассмотреть наиболее радикальный и надежный способ. Мы можем добавить в сам документ ЗаказНаПроизводство новые реквизиты (не в табличную часть, а в "шапку"): ОсновнаяНоменклатура, ОсновнаяСпецификация и ОбщееКоличество.

Логика работы будет следующей:

Преимущества этого метода:

  1. Мгновенная скорость: Системе не нужно выполнять ни запросы, ни сложный программный код при отрисовке списка.
  2. Возможность поиска и сортировки: По стандартным колонкам списка можно легко выполнять поиск или сортировку, в то время как по "вычисляемым" колонкам из первого и второго решений сортировка работать не будет.

// В модуле документа ЗаказНаПроизводство
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    Если Продукция.Количество() > 0 Тогда
        // Заполняем реквизиты шапки для отображения в списке
        РеквизитНоменклатураДляСписка = Продукция[0].Номенклатура;
        РеквизитКоличествоДляСписка = Продукция.Итог("Количество");
    Иначе
        РеквизитНоменклатураДляСписка = Справочники.Номенклатура.ПустаяСсылка();
        РеквизитКоличествоДляСписка = 0;
    КонецЕсли;
КонецПроцедуры

Важные замечания по реализации

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

Также проанализируем ситуацию с многострочными заказами. Если в одном заказе на производство указано 10 позиций номенклатуры, вывод в список только первой позиции может дезинформировать сотрудников склада или производства. В таких случаях рекомендуем использовать метод "Реквизит в шапке" и записывать туда либо самую крупную позицию, либо текстовую строку вида "Номенклатура 1, Номенклатура 2... и еще 8 позиций".

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

← На главную