Как автоматически заполнить табличную часть всеми характеристиками номенклатуры?

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

В процессе работы с документами в 1С часто возникает ситуация, когда пользователю необходимо ввести в документ (например, в «Заказ покупателя» или «Поступление товаров») сразу весь размерный ряд или все цветовые вариации одной модели товара. Вводить каждую характеристику вручную — задача трудоемкая и чреватая ошибками. Разберем, как реализовать механизм автоматического заполнения табличной части всеми характеристиками выбранной номенклатуры с помощью встроенного языка 1С.

Постановка задачи и анализ структуры данных

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

Существует два основных подхода к хранению характеристик:

  1. Индивидуальные характеристики: они привязаны непосредственно к конкретной позиции номенклатуры. В этом случае в справочнике ХарактеристикиНоменклатуры владельцем является элемент справочника Номенклатура.
  2. Общие характеристики: они создаются для целой категории товаров (Вида номенклатуры). Например, для вида «Обувь» задается общая сетка размеров. В этом случае владельцем характеристики выступает элемент справочника ВидыНоменклатуры.

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

Шаг 1: Подготовка команды и получение текущих данных

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


&НаКлиенте
Процедура ЗаполнитьВсемиХарактеристиками(Команда)
    
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    
    Если ТекущаяСтрока = Неопределено Тогда
        Предупреждение("Пожалуйста, выберите строку с товаром!");
        Возврат;
    КонецЕсли;
    
    // Вызываем серверную процедуру для работы с базой данных
    ДобавитьХарактеристикиНаСервере(ТекущаяСтрока.Номенклатура, Объект.Ссылка);
    
КонецПроцедуры

Шаг 2: Написание запроса для получения характеристик

Теперь проанализируем ситуацию на стороне сервера. Нам необходимо написать запрос, который выберет все доступные характеристики. Чтобы решение было универсальным, мы должны проверить, используются ли индивидуальные характеристики или общие для вида номенклатуры.


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

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

Шаг 3: Цикл по характеристикам и заполнение табличной части

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


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

Оптимизация: Учет остатков на складах

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

Проанализируем пример запроса с учетом остатков:


Запрос.Текст = 
    "ВЫБРАТЬ
    |	ТоварыНаСкладахОстатки.Характеристика КАК Характеристика,
    |	ТоварыНаСкладахОстатки.В наличииОстаток КАК Количество
    |ИЗ
    |	РегистрНакопления.ТоварыНаСкладах.Остатки(, Номенклатура = &Номенклатура) КАК ТоварыНаСкладахОстатки";

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

Важные рекомендации по реализации

  1. Проверка использования характеристик: Перед запуском цикла всегда проверяйте свойство ИспользоватьХарактеристики у Номенклатуры или её Вида. Если характеристики не используются, кнопка должна быть недоступна или выводить предупреждение.
  2. Метод ЗаполнитьЗначенияСвойств: Если вы копируете данные из одной строки в другие, используйте ЗаполнитьЗначенияСвойств(НоваяСтрока, ИсходнаяСтрока). Это позволит автоматически перенести цену, ставку НДС и другие важные поля.
  3. Транзакции и скорость: Если характеристик очень много (например, сотни), выполнение Добавить() в цикле на форме может работать медленно. В таких случаях лучше сначала подготовить таблицу значений на сервере, а затем разом загрузить ее в табличную часть методом Объект.Товары.Загрузить(ТаблицаСРезультатами), но будьте осторожны, так как этот метод полностью перезаписывает ТЧ.
  4. Пользовательский интерфейс: Хорошей практикой считается выделение добавленных строк цветом или автоматическая установка фокуса на колонку «Количество» в первой добавленной строке, чтобы пользователь мог сразу приступить к вводу данных.

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

← На главную