При работе с документами (например, «Реализация товаров и услуг») часто возникает необходимость избежать дублирования строк с одинаковым товаром. В идеальном сценарии, если позиция уже присутствует в табличной части, система должна прибавить количество к существующей строке, а не создавать новую.
Разберем основные подходы к решению этой задачи на управляемых формах платформы «1С:Предприятие 8.3» в зависимости от того, как происходит ввод данных: вручную, из формы подбора или с помощью сканера штрихкодов.
Решить задачу объединения одинаковых позиций можно двумя основными путями:
При работе со сканером штрихкодов или при подборе товаров алгоритм работает наиболее прозрачно, так как данные добавляются программно целиком.
Проанализируем порядок действий при сканировании или добавлении из подбора:
НайтиСтроки().Добавить().Рассмотрим пример кода для обработки сканирования или программного добавления:
Отбор = Новый Структура;
Отбор.Вставить("Номенклатура", НайденнаяНоменклатура);
Отбор.Вставить("Характеристика", НайденнаяХарактеристика);
НайденныеСтроки = Объект.Товары.НайтиСтроки(Отбор);
Если НайденныеСтроки.Количество() > 0 Тогда
// Строка уже есть — прибавляем количество
СтрокаТЧ = НайденныеСтроки[0];
СтрокаТЧ.Количество = СтрокаТЧ.Количество + СканируемоеКоличество;
Иначе
// Строки нет — создаем новую
СтрокаТЧ = Объект.Товары.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаТЧ, ДанныеНовогоТовара);
СтрокаТЧ.Количество = СканируемоеКоличество;
КонецЕсли;
Если пользователь добавляет новую строку кнопкой «Добавить» и затем выбирает номенклатуру из справочника, новая строка уже добавлена в коллекцию. В этом случае логику обработки необходимо размещать в событии ПриИзменении элемента формы, соответствующего колонке «Номенклатура».
Разберем по шагам алгоритм действия при ручном выборе:
НайтиСтроки().Посмотрим на пример клиентской процедуры:
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
Если ТекущаяСтрока = Неопределено Или Не ЗначениеЗаполнено(ТекущаяСтрока.Номенклатура) Тогда
Возврат;
КонецЕсли;
Отбор = Новый Структура;
Отбор.Вставить("Номенклатура", ТекущаяСтрока.Номенклатура);
Отбор.Вставить("Характеристика", ТекущаяСтрока.Характеристика);
НайденныеСтроки = Объект.Товары.НайтиСтроки(Отбор);
Для Каждого Стр Из НайденныеСтроки Цикл
// Исключаем из обработки текущую редактируемую строку
Если Стр.ПолучитьИдентификатор() <> ТекущаяСтрока.ПолучитьИдентификатор() Тогда
// Прибавляем количество и удаляем дубль
Стр.Количество = Стр.Количество + ?(ТекущаяСтрока.Количество = 0, 1, ТекущаяСтрока.Количество);
Объект.Товары.Удалить(ТекущаяСтрока);
// Переводим фокус на найденную строку
Элементы.Товары.ТекущаяСтрока = Стр.ПолучитьИдентификатор();
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Если интерактивное суммирование вызывает неудобства у пользователей при вводе сложных позиций, самым простым и надежным решением является группировка строк перед сохранением документа.
Обратите внимание: объект ДанныеФормыКоллекция (типом которого является Объект.Товары на управляемой форме) не имеет прямого метода Свернуть(). Для его использования необходимо преобразовать данные формы в объект ТаблицаЗначений на сервере.
Проанализируем реализацию данного подхода в обработчике события ПередЗаписьюНаСервере:
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
// Преобразуем данные формы в полноценную таблицу значений
ТЗТовары = РеквизитФормыВЗначение("Объект.Товары");
// Указываем колонки группировки и суммируемые колонки
ГруппируемыеКолонки = "Номенклатура, Характеристика, Упаковка, Цена, СтавкаНДС";
СуммируемыеКолонки = "Количество, Сумма, СуммаНДС";
ТЗТовары.Свернуть(ГруппируемыеКолонки, СуммируемыеКолонки);
// Загружаем свернутую таблицу обратно в реквизит формы
ЗначениеВРеквизитФормы(ТЗТовары, "Объект.Товары");
КонецПроцедуры
При реализации суммирования строк критически важно учитывать составной ключ уникальности. Складывать строки только по одному реквизиту Номенклатура нельзя, если в конфигурации используется дополнительная аналитика учета.
В структуру отбора для поиска совпадений или в список группируемых колонок необходимо включать:
Выбор конкретного решения зависит от требований бизнес-процесса: для работы со сканером идеален Вариант 1, для строгого контроля дублей вручную — Вариант 2, а для гарантированной чистоты данных в базе без изменения механики ввода — Вариант 3.