Как реализовать сложение дублирующихся строк в табличной части 1С?

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

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

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

Общая постановка задачи и варианты решения

Решить задачу объединения одинаковых позиций можно двумя основными путями:

  1. Интерактивно в процессе ввода — объединять строки непосредственно в момент сканирования, выбора из формы подбора или изменении номенклатуры в табличной части.
  2. Отложенно при сохранении — позволить пользователю вводить любые строки, но перед записью документа автоматически сгруппировать их.

Вариант 1. Поиск и объединение строк при подборе и сканировании штрихкодов

При работе со сканером штрихкодов или при подборе товаров алгоритм работает наиболее прозрачно, так как данные добавляются программно целиком.

Проанализируем порядок действий при сканировании или добавлении из подбора:

  1. Определяем номенклатуру и её аналитические разрезы (характеристику, упаковку и т.д.).
  2. Выполняем поиск совпадений в табличной части с помощью метода НайтиСтроки().
  3. Если строка найдена — увеличиваем количество. Если не найдена — вызываем метод Добавить().

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


Отбор = Новый Структура;
Отбор.Вставить("Номенклатура", НайденнаяНоменклатура);
Отбор.Вставить("Характеристика", НайденнаяХарактеристика);

НайденныеСтроки = Объект.Товары.НайтиСтроки(Отбор);

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

Вариант 2. Интерактивное объединение строк при ручном вводе номенклатуры

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

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

  1. Получаем текущую редактируемую строку табличной части.
  2. Формируем структуру отбора по выбранным реквизитам.
  3. Ищем совпадающие строки методом НайтиСтроки().
  4. Переносим количество из текущей строки в ранее существовавшую и удаляем текущую дублирующую строку.
  5. Смещаем фокус ввода (текущую строку формы) на объединенную позицию.

Посмотрим на пример клиентской процедуры:


&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Или Не ЗначениеЗаполнено(ТекущаяСтрока.Номенклатура) Тогда
        Возврат;
    КонецЕсли;
    
    Отбор = Новый Структура;
    Отбор.Вставить("Номенклатура", ТекущаяСтрока.Номенклатура);
    Отбор.Вставить("Характеристика", ТекущаяСтрока.Характеристика);
    
    НайденныеСтроки = Объект.Товары.НайтиСтроки(Отбор);
    
    Для Каждого Стр Из НайденныеСтроки Цикл
        // Исключаем из обработки текущую редактируемую строку
        Если Стр.ПолучитьИдентификатор() <> ТекущаяСтрока.ПолучитьИдентификатор() Тогда
            // Прибавляем количество и удаляем дубль
            Стр.Количество = Стр.Количество + ?(ТекущаяСтрока.Количество = 0, 1, ТекущаяСтрока.Количество);
            Объект.Товары.Удалить(ТекущаяСтрока);
            
            // Переводим фокус на найденную строку
            Элементы.Товары.ТекущаяСтрока = Стр.ПолучитьИдентификатор();
            Прервать;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Вариант 3. Группировка и сворачивание строк перед записью документа

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

Обратите внимание: объект ДанныеФормыКоллекция (типом которого является Объект.Товары на управляемой форме) не имеет прямого метода Свернуть(). Для его использования необходимо преобразовать данные формы в объект ТаблицаЗначений на сервере.

Проанализируем реализацию данного подхода в обработчике события ПередЗаписьюНаСервере:


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    // Преобразуем данные формы в полноценную таблицу значений
    ТЗТовары = РеквизитФормыВЗначение("Объект.Товары");
    
    // Указываем колонки группировки и суммируемые колонки
    ГруппируемыеКолонки = "Номенклатура, Характеристика, Упаковка, Цена, СтавкаНДС";
    СуммируемыеКолонки = "Количество, Сумма, СуммаНДС";
    
    ТЗТовары.Свернуть(ГруппируемыеКолонки, СуммируемыеКолонки);
    
    // Загружаем свернутую таблицу обратно в реквизит формы
    ЗначениеВРеквизитФормы(ТЗТовары, "Объект.Товары");
КонецПроцедуры

Особенности работы с данными формы и аналитикой

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

В структуру отбора для поиска совпадений или в список группируемых колонок необходимо включать:

Выбор конкретного решения зависит от требований бизнес-процесса: для работы со сканером идеален Вариант 1, для строгого контроля дублей вручную — Вариант 2, а для гарантированной чистоты данных в базе без изменения механики ввода — Вариант 3.

← На главную