Как разбить строку табличной части на несколько строк в 1С?

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

В практике разработки на платформе 1С:Предприятие 8 часто возникает задача трансформации данных в табличных частях документов. Одной из таких задач является «разбиение» или «развертка» строки: когда одна позиция с большим количеством (например, 5 единиц) должна превратиться в пять отдельных строк с количеством 1. Это может потребоваться для указания индивидуальных серий, штрихкодов, ячеек хранения или для подготовки данных к маркировке «Честный Знак».

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

Использование стандартного функционала в типовых решениях

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

Как правило, кнопка «Разбить строку» находится в командной панели табличной части (иногда она скрыта в подменю «Еще»). В документах «Отбор (размещение) товаров» или «Приходный ордер на товары» этот функционал работает автоматически при включенном адресном хранении или учете по сериям. Если вам нужно разделить строку вручную, поищите иконку с изображением двух стрелок, направленных в разные стороны.

Программная реализация: логика обхода коллекции

Рассмотрим ситуацию, когда нам необходимо программно обойти табличную часть и разделить строки. Основная ошибка, которую совершают многие программисты (и что мы видим в сообщениях форума), — это попытка изменять коллекцию прямо в процессе её обхода циклом Для Каждого.

Проанализируем проблему: когда вы используете цикл Для Каждого СтрокаТЧ Из Объект.Товары и внутри добавляете новую строку методом Добавить(), индекс коллекции смещается, и цикл может либо уйти в бесконечность, либо пропустить необработанные строки. Чтобы этого избежать, мы рекомендуем два подхода:

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

Рассмотрим пример правильного обхода с конца:


// Определяем количество строк до начала обработки
ВсегоСтрок = Объект.Товары.Количество();

// Обходим таблицу с последней строки к первой
Для Индекс = -(ВсегоСтрок - 1) По 0 Цикл
    ТекущийИндекс = -Индекс;
    СтрокаТЧ = Объект.Товары[ТекущийИндекс];
    
    Если СтрокаТЧ.Количество > 1 Тогда
        ИсходноеКоличество = СтрокаТЧ.Количество;
        
        // Устанавливаем количество в текущей строке равным 1
        СтрокаТЧ.Количество = 1;
        
        // Добавляем недостающие строки (Количество - 1)
        Для Счетчик = 1 По (ИсходноеКоличество - 1) Цикл
            НоваяСтрока = Объект.Товары.Добавить();
            ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЧ);
            НоваяСтрока.Количество = 1;
        КонецЦикла;
    КонецЕсли;
КонецЦикла;

Метод ЗаполнитьЗначенияСвойств для копирования данных

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

Обратите внимание, что после копирования свойств в новой строке нужно обязательно скорректировать реквизит Количество (и, возможно, Сумма), иначе данные будут задвоены.

Реализация при заполнении «на основании»

Часто задача разбиения строк возникает в момент создания одного документа на основании другого. В этом случае логику удобнее встроить в процедуру ОбработкаЗаполнения в модуле объекта. Выясним, как это выглядит на практике:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаказПокупателя") Тогда
        Для Каждого ТекСтрока Из ДанныеЗаполнения.Товары Цикл
            // Если в заказе 5 штук, создаем 5 строк в текущем документе
            Для Счетчик = 1 По ТекСтрока.Количество Цикл
                НоваяСтрока = Товары.Добавить();
                ЗаполнитьЗначенияСвойств(НоваяСтрока, ТекСтрока);
                НоваяСтрока.Количество = 1;
                // Не забываем про пересчет сумм, если это необходимо
            КонецЦикла;
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Нюансы работы с суммами и округлением

Проанализируем ситуацию с дробным количеством и денежными суммами. Если вы разбиваете строку, где количество было равно 3, а общая сумма составляла 100 рублей, то при простом делении у вас получится три строки по 33.33 рубля. В сумме это даст 99.99 рублей.

Важные рекомендации:

Работа с адресным складом (Ячейки)

Как упоминалось в сообщении 7 обсуждаемой темы, разбиение часто требуется для распределения товара по ячейкам. Если запрос к остаткам показывает, что товар лежит в трех разных ячейках, нам нужно создать три строки, даже если в исходном распоряжении была одна. В этом случае мы сначала получаем таблицу остатков по ячейкам, а затем в цикле заполняем табличную часть документа, уменьшая «требуемое» количество на то, что фактически нашли в каждой конкретной ячейке.

Таким образом, задача разбиения строки — это не просто создание дублей, а инструмент для детализации учета. Правильное использование индексов при обходе и методов копирования свойств позволит вам избежать ошибок «Метод объекта не обнаружен» и некорректного заполнения данных.

← На главную