Как вывести штрихкод в динамический список номенклатуры в 1С:УТ 11, если колонка не отображается?

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

Представим типичную задачу разработчика 1С: клиенту или менеджеру склада потребовалось видеть штрихкоды товаров непосредственно в форме списка номенклатуры или форме выбора. Задача кажется тривиальной. Мы создаем расширение, заимствуем форму списка номенклатуры, добавляем в динамический список левое соединение с регистром сведений ШтрихкодыНоменклатуры, выносим новое поле на форму в виде колонки и запускаем базу в режиме «1С:Предприятие». Однако на форме добавленной колонки нет.

Мы проверяем запрос в консоли — всё работает отлично. Проверяем настройки формы в режиме пользователя (через «Изменить форму») — колонки нет даже в списке скрытых полей. Добавляем ради эксперимента другое поле, например, ставку НДС — она выводится без проблем. А штрихкод словно испаряется. Выясним, почему происходит эта «мистика» и как решить проблему правильно и красиво.

В чем причина исчезновения колонки?

В современных конфигурациях ERP-класса на платформе 1С:Предприятие 8.3 (включая «Управление торговлей 11.4» и выше, «Комплексную автоматизацию 2» и «ERP Управление предприятием 2») разработчики фирмы 1С активно используют механизмы динамического конструирования форм. Тексты запросов для ключевых динамических списков не являются статическими.

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


РаботаСНоменклатуройУТ.ПолучитьДополненныйЗапросДинамическогоСписка(СвойстваСписка.ТекстЗапроса);

Эта процедура полностью перезаписывает свойство ТекстЗапроса нашего динамического списка предопределенным шаблоном из общего модуля конфигурации. В итоге любые ручные изменения запроса динамического списка, выполненные разработчиком в редакторе формы (включая изменения через расширение конфигурации), просто полностью затираются в момент инициализации формы.

Ниже мы подробно разберем три практических способа решения этой проблемы: от классических вариантов до современных стандартов разработки (Best Practice), обеспечивающих максимальную производительность системы.


Способ 1. Программная модификация запроса на форме (после инициализации)

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

Разберем этот процесс по шагам:

  1. Создаем расширение конфигурации (или используем существующее).
  2. Добавляем в расширение форму списка номенклатуры (или форму выбора).
  3. В модуле формы расширения объявляем обработчик с аннотацией &После("ПриСозданииНаСервере").
  4. Вставляем следующий код, который модифицирует сформированный текст запроса:

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

Важное примечание: Обратите внимание на использование конструкции МИНИМУМ(Штрихкод) и группировки. Если у одной номенклатурной позиции в базе данных будет зарегистрировано два или более штрихкода, прямое левое соединение без группировки приведет к размножению строк в динамическом списке. Пользователь увидит одну и ту же позицию номенклатуры столько раз, сколько штрихкодов для нее заведено, что недопустимо.


Способ 2. Изменение общего модуля конфигурации (Глобальный подход)

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

Рассмотрим последовательность действий:

  1. Находим общий модуль, отвечающий за модификацию запроса номенклатуры. В УТ 11.4 это обычно РаботаСНоменклатуройУТ (в более новых версиях ERP/КА/УТ название может быть РаботаСНоменклатуройКлиентСервер или РаботаСНоменклатурой).
  2. Добавляем этот модуль в расширение.
  3. Находим метод ПолучитьДополненныйЗапросДинамическогоСписка.
  4. Используя аннотацию &Вместо или &ИзменениеИКонтроль, вносим изменения непосредственно в шаблон формируемого запроса.

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


Способ 3. Использование события «ПриПолученииДанныхНаСервере» (Наиболее производительный метод)

Начиная с версии платформы 8.3.10, разработчикам доступен крайне мощный механизм оптимизации — событие таблицы формы ПриПолученииДанныхНаСервере. Рассмотрим этот подход подробнее.

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

Метод ПриПолученииДанныхНаСервере позволяет запрашивать штрихкоды только для тех строк, которые физически отображаются на экране пользователя в данный момент (обычно это 30–40 строк).

Проанализируем реализацию данного подхода по шагам:

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

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

Преимущества использования Способа 3:

Мы проанализировали причины нетипичного поведения платформы при работе с расширениями динамических списков и разобрали три способа устранения этой проблемы. Рекомендуем использовать именно Способ 3 как наиболее технологичный, производительный и устойчивый к обновлениям программных продуктов семейства 1С:Предприятие 8.

← На главную