Как добавить колонку остатков номенклатуры в табличную часть документа 1С

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

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

Разберем подробно, какими способами можно вывести остаток товара в табличную часть документов конфигураций «Розница» и «Управление торговлей».

Способ 1. Добавление реквизита в метаданные конфигурации

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

  1. Откроем дерево метаданных конфигуратора и найдем требуемый документ (например, УстановкаЦенВМагазине).
  2. В табличной части Товары добавим новый реквизит Остаток с типом Число (длина 15, точность 3).
  3. Перейдем в форму документа и разместим добавленный реквизит в табличном поле.
  4. В модуле формы или в обработчиках заполнения табличной части пропишем заполнение остатков из регистра накопления (например, ТоварыНаСкладах или ТоварыВРознице).

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

Способ 2. Динамическое добавление колонки в обычных формах (1С:Розница 1.0)

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

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

Посмотрим на пример добавления колонки при открытии формы:


Процедура ПриОткрытии()
    
    // Проверяем, существует ли уже колонка
    Если ЭлементыФормы.Товары.Колонки.Найти("Остаток") = Неопределено Тогда
        НоваяКолонка = ЭлементыФормы.Товары.Колонки.Добавить("Остаток", "Остаток на складе");
        НоваяКолонка.УстановитьЭлементУправления(Тип("ПолеВвода"));
        НоваяКолонка.ЭлементУправления.ТолькоПросмотр = Истина;
        НоваяКолонка.Ширина = 10;
        НоваяКолонка.Положение = ПоложениеКолонки.После;
    КонецЕсли;
    
КонецПроцедуры

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

Используем обработчик ПриПолученииДанных, который обрабатывает видимые строки пакетом:


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

Способ 3. Программное добавление колонки в управляемых формах (УТ 11, Розница 2 / 3)

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

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


&НаСервере
Процедура ДобавитьКолонкуОстатковНаФорму(Форма)
    
    Если Форма.Элементы.Найти("ТоварыОстатки") = Неопределено Тогда
        
        // 1. Добавляем динамический реквизит формы
        Реквизиты = Новый Массив;
        Реквизиты.Добавить(Новый РеквизитФормы(
            "Остатки", 
            Новый ОписаниеТипов("Строка"), 
            "Объект.Товары", 
            "Доступно на складе", 
            Ложь
        ));
        Форма.ИзменитьРеквизиты(Реквизиты);
        
        // 2. Создаем элемент формы для отображения реквизита
        НовыйЭлементФормы = Форма.Элементы.Добавить("ТоварыОстатки", Тип("ПолеФормы"), Форма.Элементы.Товары);
        НовыйЭлементФормы.Вид = ВидПоляФормы.ПолеВвода;
        НовыйЭлементФормы.ТолькоПросмотр = Истина;
        НовыйЭлементФормы.ЦветТекста = WebЦвета.Серый;
        НовыйЭлементФормы.ГоризонтальноеПоложение = ГоризонтальноеПоложениеЭлемента.Право;
        НовыйЭлементФормы.ПутьКДанным = "Объект.Товары.Остатки";
        
    КонецЕсли;
    
    // 3. Рассчитываем и заполняем остатки
    ЗаполнитьОстаткиВТабличнойЧасти(Форма);
    
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьОстаткиВТабличнойЧасти(Форма)
    
    Склад = Форма.Объект.Склад;
    ТЧ = Форма.Объект.Товары;
    
    МассивНоменклатуры = Новый Массив;
    Для Каждого СтрокаТЧ Из ТЧ Цикл
        МассивНоменклатуры.Добавить(СтрокаТЧ.Номенклатура);
    КонецЦикла;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
        |	ЕСТЬNULL(ТоварыНаСкладахОстатки.ВНаличииОстаток, 0) - ЕСТЬNULL(ТоварыНаСкладахОстатки.КОтгрузкеОстаток, 0) КАК Остаток
        |ИЗ
        |	РегистрНакопления.ТоварыНаСкладах.Остатки(, Номенклатура В (&МассивНоменклатуры) И Склад = &Склад) КАК ТоварыНаСкладахОстатки";
        
    Запрос.УстановитьПараметр("Номенклатура", МассивНоменклатуры);
    Запрос.УстановитьПараметр("Склад", Склад);
    
    РезультатЗапроса = Запрос.Выполнить().Выгрузить();
    РезультатЗапроса.Индексы.Добавить("Номенклатура");
    
    Для Каждого Строка Из ТЧ Цикл
        НайденныйОстаток = РезультатЗапроса.Найти(Строка.Номенклатура, "Номенклатура");
        ОстатокЧисло = 0;
        Если НайденныйОстаток <> Неопределено Тогда
            ОстатокЧисло = НайденныйОстаток.Остаток;
        КонецЕсли;
        
        Если ОстатокЧисло = 0 Тогда
            Строка.Остатки = "0,000";
        ИначеЕсли ОстатокЧисло < Строка.Количество Тогда
            Строка.Остатки = "! мало: " + Строка(ОстатокЧисло);
        Иначе
            Строка.Остатки = Строка(ОстатокЧисло);
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Особенности работы с интерфейсом РМК и внешними обработками

Если задача стоит в выводе остатков на форму РМК (например, в документе ЧекККМ), обратим внимание на важные архитектурные нюансы:

  1. Подсистема дополнительных отчетов и обработок (БСП): команды с типом ВидОбработкиЗаполнениеОбъекта по умолчанию подключаются к основной форме документа (ФормаДокумента). Специализированная форма ФормаДокументаРМК не поддерживает стандартную панель дополнительных команд БСП без доработки формы.
  2. Использование расширений: для доработки формы РМК без снятия с поддержки рекомендуется использовать расширение конфигурации. В расширении можно добавить реквизит формы и перехватить событие ПриСозданииНаСервере или ПриИзменении номенклатуры с помощью аннотаций &После или &Вместо.
  3. Оптимизация запросов: не следует выполнять запрос к регистрам внутри цикла перебора строк. Запрос всегда должен выполняться один раз по всему массиву позиций документа.
← На главную