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