В практике автоматизации на платформе 1С:Предприятие часто возникает задача консолидации данных. Типичный пример — когда клиенту в течение определенного периода оказывались услуги или поставлялись товары по разным заказам, но бухгалтер хочет выставить один итоговый Счет на оплату. Разберем подробно, как реализовать этот механизм, основываясь на технических приемах и опыте разработчиков.
Прежде чем приступать к написанию кода, проанализируем ситуацию. Нам необходимо взять несколько исходных документов (например, Заказ покупателя, Поступление услуг или Реализация товаров и услуг), извлечь из них данные о товарах или услугах и перенести их в один целевой документ. При этом важно сохранить связь с документами-основаниями и правильно обработать данные шапки, такие как Контрагент, Организация и Договор.
Рассмотрим, как эта задача решается в стандартных продуктах 1С, так как это лучший источник идей для собственной разработки. Во многих конфигурациях (например, в БП 3.0 или УТ 11) уже есть кнопки типа «Добавить из документа» или рабочие места для пакетного оформления документов.
Если вы работаете в нетиповой конфигурации, нам придется реализовать этот алгоритм вручную.
Разберем по шагам, как программно собрать данные из нескольких документов. Предположим, у нас есть массив ссылок на документы-основания МассивОснований. Посмотрим на пример кода, который выполняет перенос данных:
// Очищаем текущую табличную часть перед заполнением
Объект.Товары.Очистить();
Для Каждого СсылкаНаДокумент Из МассивОснований Цикл
// Проверяем, что контрагент совпадает
Если СсылкаНаДокумент.Контрагент <> Объект.Контрагент Тогда
Продолжить; // Или выводим предупреждение пользователю
КонецЕсли;
// Обходим строки исходного документа
Для Каждого СтрокаИсточника Из СсылкаНаДокумент.Товары Цикл
НоваяСтрока = Объект.Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИсточника);
// Дополнительно можно заполнить содержание, чтобы было понятно, откуда строка
НоваяСтрока.Содержание = "По документу " + Строка(СсылкаНаДокумент);
КонецЦикла;
КонецЦикла;
Этот способ прост, но имеет недостаток: если в десяти документах была одна и та же услуга, в счете будет десять одинаковых строк. Для бизнеса это часто неудобно, поэтому проанализируем ситуацию со сверткой строк.
Чтобы счет выглядел аккуратно, одинаковые позиции лучше сгруппировать. Выясним, как это сделать максимально эффективно с помощью метода Свернуть. Для этого мы сначала выгрузим все данные во временную таблицу значений.
// Создаем временную таблицу для накопления данных
ТЗ = Объект.Товары.ВыгрузитьКолонки();
Для Каждого Док Из МассивОснований Цикл
Для Каждого Стр Из Док.Товары Цикл
НоваяСтр = ТЗ.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтр, Стр);
КонецЦикла;
КонецЦикла;
// Группируем данные по ключевым полям, суммируя количество и сумму
ТЗ.Свернуть("Номенклатура, Цена, СтавкаНДС, ЕдиницаИзмерения", "Количество, Сумма, СуммаНДС");
// Загружаем результат обратно в документ
Объект.Товары.Загрузить(ТЗ);
Важный нюанс: при свертке нельзя использовать поля, которые уникальны для каждой строки (например, номер строки или специфическое содержание), иначе группировка не сработает.
Рассмотрим более профессиональный подход — использование объекта Запрос. Это работает быстрее, если документов много, и позволяет сразу отсеять ненужные данные (например, помеченные на удаление или непроведенные документы).
Проанализируем пример запроса, который собирает данные из табличных частей Услуги документов ПоступлениеТоваровУслуг:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТЧ.Номенклатура КАК Номенклатура,
| СУММА(ТЧ.Количество) КАК Количество,
| ТЧ.Цена КАК Цена,
| СУММА(ТЧ.Сумма) КАК Сумма
|ИЗ
| Документ.ПоступлениеТоваровУслуг.Услуги КАК ТЧ
|ГДЕ
| ТЧ.Ссылка В(&МассивСсылок)
|СГРУППИРОВАТЬ ПО
| ТЧ.Номенклатура,
| ТЧ.Цена";
Запрос.УстановитьПараметр("МассивСсылок", МассивОснований);
РезультатЗапроса = Запрос.Выполнить();
Объект.Товары.Загрузить(РезультатЗапроса.Выгрузить());
Чтобы пользователь всегда мог понять, из каких кирпичиков собран общий счет, рекомендуется добавить в конфигурацию скрытую табличную часть под названием ДокументыОснования. Разберем, для чего это нужно:
Выясним причину возможных ошибок при слиянии документов. Перед записью итогового счета обязательно выполним следующие проверки:
Таким образом, создание общего счета — это не просто копирование строк, а полноценная процедура обработки данных, требующая внимания к деталям учета и архитектуре метаданных 1С.